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#include "ecmascript/compiler/escape_analysis.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ciVirtualObject::VirtualObject(size_t numIn, Chunk* chunk)
214514f5e3Sopenharmony_ci    : fields_(chunk), users_(chunk)
224514f5e3Sopenharmony_ci{
234514f5e3Sopenharmony_ci    for (size_t i = 0; i < numIn; i++) {
244514f5e3Sopenharmony_ci        FieldLocation tmp;
254514f5e3Sopenharmony_ci        fields_.emplace_back(tmp);
264514f5e3Sopenharmony_ci    }
274514f5e3Sopenharmony_ci}
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_civoid VirtualObject::SetEscaped()
304514f5e3Sopenharmony_ci{
314514f5e3Sopenharmony_ci    escaped_ = true;
324514f5e3Sopenharmony_ci}
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_cibool VirtualObject::IsEscaped() const
354514f5e3Sopenharmony_ci{
364514f5e3Sopenharmony_ci    return escaped_;
374514f5e3Sopenharmony_ci}
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_ciFieldLocation VirtualObject::GetField(size_t offset)
404514f5e3Sopenharmony_ci{
414514f5e3Sopenharmony_ci    constexpr size_t fieldSize = 8;
424514f5e3Sopenharmony_ci    ASSERT(offset % fieldSize == 0);
434514f5e3Sopenharmony_ci    if (offset / fieldSize >= fields_.size()) {
444514f5e3Sopenharmony_ci        return FieldLocation::Invalid();
454514f5e3Sopenharmony_ci    }
464514f5e3Sopenharmony_ci    return fields_.at(offset/fieldSize);
474514f5e3Sopenharmony_ci}
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_cisize_t FieldLocation::maxid = 0;
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ciChunkVector<GateRef>& VirtualObject::GetUsers()
524514f5e3Sopenharmony_ci{
534514f5e3Sopenharmony_ci    return users_;
544514f5e3Sopenharmony_ci}
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_civoid VirtualObject::ClearUsers()
574514f5e3Sopenharmony_ci{
584514f5e3Sopenharmony_ci    users_.clear();
594514f5e3Sopenharmony_ci}
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_civoid VirtualObject::AddUser(GateRef gate)
624514f5e3Sopenharmony_ci{
634514f5e3Sopenharmony_ci    users_.push_back(gate);
644514f5e3Sopenharmony_ci}
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ciGateInfo::GateInfo(Circuit* circuit, GateRef curGate, EscapeAnalysis* escapeAnalysis, Chunk* chunk)
674514f5e3Sopenharmony_ci    : circuit_(circuit), acc_(circuit), curGate_(curGate), escapeAnalysis_(escapeAnalysis), state_(chunk)
684514f5e3Sopenharmony_ci{
694514f5e3Sopenharmony_ci    if (acc_.GetOpCode(curGate) == OpCode::DEPEND_SELECTOR) {
704514f5e3Sopenharmony_ci        state_ = MergeState(curGate);
714514f5e3Sopenharmony_ci    } else {
724514f5e3Sopenharmony_ci        ASSERT(acc_.GetDependCount(curGate) <= 1);
734514f5e3Sopenharmony_ci        if (acc_.GetDependCount(curGate) == 1) {
744514f5e3Sopenharmony_ci            state_ = escapeAnalysis_->GetOrCreateState(acc_.GetDep(curGate));
754514f5e3Sopenharmony_ci        }
764514f5e3Sopenharmony_ci    }
774514f5e3Sopenharmony_ci}
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ciGateInfo::~GateInfo()
804514f5e3Sopenharmony_ci{
814514f5e3Sopenharmony_ci    State& preState = escapeAnalysis_->GetOrCreateState(curGate_);
824514f5e3Sopenharmony_ci    if (state_.IsMapEqual(preState) ||
834514f5e3Sopenharmony_ci        object_ != escapeAnalysis_->TryGetVirtualObject(curGate_)) {
844514f5e3Sopenharmony_ci        escapeAnalysis_->SetReplaceGate(curGate_);
854514f5e3Sopenharmony_ci    }
864514f5e3Sopenharmony_ci    escapeAnalysis_->SetState(curGate_, state_);
874514f5e3Sopenharmony_ci
884514f5e3Sopenharmony_ci    escapeAnalysis_->SetVirtualObject(curGate_, object_);
894514f5e3Sopenharmony_ci    escapeAnalysis_->SetReplacement(curGate_, replacement_);
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ciGateRef GateInfo::GetCurrentGate() const
934514f5e3Sopenharmony_ci{
944514f5e3Sopenharmony_ci    return curGate_;
954514f5e3Sopenharmony_ci}
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ciState GateInfo::MergeState(GateRef gate)
984514f5e3Sopenharmony_ci{
994514f5e3Sopenharmony_ci    size_t numIn = acc_.GetDependCount(gate);
1004514f5e3Sopenharmony_ci    State& preState = escapeAnalysis_->GetOrCreateState(acc_.GetDep(gate, 0));
1014514f5e3Sopenharmony_ci    State result = preState;
1024514f5e3Sopenharmony_ci    for (auto fieldValue : preState) {
1034514f5e3Sopenharmony_ci        FieldLocation field = fieldValue.first;
1044514f5e3Sopenharmony_ci        GateRef value = fieldValue.second;
1054514f5e3Sopenharmony_ci        ASSERT(field != FieldLocation::Invalid());
1064514f5e3Sopenharmony_ci        if (value != Circuit::NullGate()) {
1074514f5e3Sopenharmony_ci            std::vector<GateRef> input;
1084514f5e3Sopenharmony_ci            input.push_back(acc_.GetState(gate));
1094514f5e3Sopenharmony_ci            input.push_back(value);
1104514f5e3Sopenharmony_ci            size_t numAliveState = 1;
1114514f5e3Sopenharmony_ci            bool differentFlag = false;
1124514f5e3Sopenharmony_ci            for (size_t i = 1; i < numIn; i++) {
1134514f5e3Sopenharmony_ci                State& inputState = escapeAnalysis_->GetOrCreateState(acc_.GetDep(gate, i));
1144514f5e3Sopenharmony_ci                GateRef inputValue = inputState.GetFieldValue(field);
1154514f5e3Sopenharmony_ci                if (inputValue != Circuit::NullGate()) {
1164514f5e3Sopenharmony_ci                    numAliveState++;
1174514f5e3Sopenharmony_ci                }
1184514f5e3Sopenharmony_ci                if (inputValue != value) {
1194514f5e3Sopenharmony_ci                    differentFlag = true;
1204514f5e3Sopenharmony_ci                }
1214514f5e3Sopenharmony_ci                input.push_back(inputValue);
1224514f5e3Sopenharmony_ci            }
1234514f5e3Sopenharmony_ci
1244514f5e3Sopenharmony_ci            if (numAliveState == 1 && acc_.GetOpCode(acc_.GetState(gate)) == OpCode::LOOP_BEGIN) {
1254514f5e3Sopenharmony_ci                result.SetFieldValue(field, value);
1264514f5e3Sopenharmony_ci            } else if (numAliveState < numIn) {
1274514f5e3Sopenharmony_ci                result.SetFieldValue(field, Circuit::NullGate());
1284514f5e3Sopenharmony_ci            } else {
1294514f5e3Sopenharmony_ci                if (!differentFlag) {
1304514f5e3Sopenharmony_ci                    result.SetFieldValue(field, value);
1314514f5e3Sopenharmony_ci                } else {
1324514f5e3Sopenharmony_ci                    State& oldState = escapeAnalysis_->GetOrCreateState(gate);
1334514f5e3Sopenharmony_ci                    GateRef oldValue = oldState.GetFieldValue(field);
1344514f5e3Sopenharmony_ci                    if (oldValue != Circuit::NullGate() &&
1354514f5e3Sopenharmony_ci                        acc_.GetOpCode(oldValue) == OpCode::DEPEND_SELECTOR &&
1364514f5e3Sopenharmony_ci                        acc_.GetState(oldValue) == acc_.GetState(gate)) {
1374514f5e3Sopenharmony_ci                        for (size_t i = 0; i < numIn; i++) {
1384514f5e3Sopenharmony_ci                            ASSERT(input[i + 1] != Circuit::NullGate());
1394514f5e3Sopenharmony_ci                            if (acc_.GetValueIn(oldValue, i) != input[i + 1]) {
1404514f5e3Sopenharmony_ci                                acc_.ReplaceValueIn(oldValue, input[i + 1], i);
1414514f5e3Sopenharmony_ci                                escapeAnalysis_->RevisitGate(oldValue);
1424514f5e3Sopenharmony_ci                            }
1434514f5e3Sopenharmony_ci                        }
1444514f5e3Sopenharmony_ci                        result.SetFieldValue(field, oldValue);
1454514f5e3Sopenharmony_ci                    } else {
1464514f5e3Sopenharmony_ci                        MachineType machineType = acc_.GetMachineType(value);
1474514f5e3Sopenharmony_ci                        auto gateType = acc_.GetGateType(value);
1484514f5e3Sopenharmony_ci                        const GateMetaData* meta = circuit_->ValueSelector(numIn);
1494514f5e3Sopenharmony_ci                        GateRef valueSelector = circuit_->NewGate(meta, machineType, input.size(),
1504514f5e3Sopenharmony_ci                                                                  input.data(), gateType);
1514514f5e3Sopenharmony_ci                        result.SetFieldValue(field, valueSelector);
1524514f5e3Sopenharmony_ci                        escapeAnalysis_->RevisitGate(valueSelector);
1534514f5e3Sopenharmony_ci                    }
1544514f5e3Sopenharmony_ci                }
1554514f5e3Sopenharmony_ci            }
1564514f5e3Sopenharmony_ci        }
1574514f5e3Sopenharmony_ci    }
1584514f5e3Sopenharmony_ci    return result;
1594514f5e3Sopenharmony_ci}
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ciGateRef GateInfo::GetFieldValue(FieldLocation field) const
1624514f5e3Sopenharmony_ci{
1634514f5e3Sopenharmony_ci    return state_.GetFieldValue(field);
1644514f5e3Sopenharmony_ci}
1654514f5e3Sopenharmony_ci
1664514f5e3Sopenharmony_civoid GateInfo::SetFieldValue(FieldLocation field, GateRef value)
1674514f5e3Sopenharmony_ci{
1684514f5e3Sopenharmony_ci    state_.SetFieldValue(field, value);
1694514f5e3Sopenharmony_ci}
1704514f5e3Sopenharmony_ci
1714514f5e3Sopenharmony_civoid GateInfo::SetEliminated()
1724514f5e3Sopenharmony_ci{
1734514f5e3Sopenharmony_ci    replacement_ = circuit_->DeadGate();
1744514f5e3Sopenharmony_ci    object_ = nullptr;
1754514f5e3Sopenharmony_ci}
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_civoid GateInfo::SetReplacement(GateRef replacement)
1784514f5e3Sopenharmony_ci{
1794514f5e3Sopenharmony_ci    replacement_ = replacement;
1804514f5e3Sopenharmony_ci    object_ = escapeAnalysis_->TryGetVirtualObject(replacement);
1814514f5e3Sopenharmony_ci}
1824514f5e3Sopenharmony_ci
1834514f5e3Sopenharmony_civoid GateInfo::SetVirtualObject(VirtualObject* object)
1844514f5e3Sopenharmony_ci{
1854514f5e3Sopenharmony_ci    object_ = object;
1864514f5e3Sopenharmony_ci}
1874514f5e3Sopenharmony_ci
1884514f5e3Sopenharmony_civoid State::SetFieldValue(FieldLocation field, GateRef gate)
1894514f5e3Sopenharmony_ci{
1904514f5e3Sopenharmony_ci    map_[field] = gate;
1914514f5e3Sopenharmony_ci}
1924514f5e3Sopenharmony_ci
1934514f5e3Sopenharmony_ciGateRef State::GetFieldValue(FieldLocation field) const
1944514f5e3Sopenharmony_ci{
1954514f5e3Sopenharmony_ci    auto result = map_.find(field);
1964514f5e3Sopenharmony_ci    if (result == map_.end()) {
1974514f5e3Sopenharmony_ci        return Circuit::NullGate();
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci    return result->second;
2004514f5e3Sopenharmony_ci}
2014514f5e3Sopenharmony_ci
2024514f5e3Sopenharmony_cibool State::IsMapEqual(const State &state) const
2034514f5e3Sopenharmony_ci{
2044514f5e3Sopenharmony_ci    return map_.size() == state.map_.size() &&
2054514f5e3Sopenharmony_ci           std::equal(map_.begin(), map_.end(), state.map_.begin());
2064514f5e3Sopenharmony_ci}
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_civoid EscapeAnalysis::SetReplacement(GateRef gate, GateRef replacement)
2094514f5e3Sopenharmony_ci{
2104514f5e3Sopenharmony_ci    replacements_[gate] = replacement;
2114514f5e3Sopenharmony_ci}
2124514f5e3Sopenharmony_ci
2134514f5e3Sopenharmony_ciGateRef EscapeAnalysis::TryGetReplacement(GateRef gate) const
2144514f5e3Sopenharmony_ci{
2154514f5e3Sopenharmony_ci    if (!replacements_.count(gate)) {
2164514f5e3Sopenharmony_ci        return Circuit::NullGate();
2174514f5e3Sopenharmony_ci    }
2184514f5e3Sopenharmony_ci    return replacements_.at(gate);
2194514f5e3Sopenharmony_ci}
2204514f5e3Sopenharmony_ci
2214514f5e3Sopenharmony_ciGateRef EscapeAnalysis::GetCurrentGate(GateRef gate) const
2224514f5e3Sopenharmony_ci{
2234514f5e3Sopenharmony_ci    GateRef replacement = TryGetReplacement(gate);
2244514f5e3Sopenharmony_ci    if (replacement == Circuit::NullGate()) {
2254514f5e3Sopenharmony_ci        return gate;
2264514f5e3Sopenharmony_ci    }
2274514f5e3Sopenharmony_ci    return replacement;
2284514f5e3Sopenharmony_ci}
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_ciVirtualObject* EscapeAnalysis::TryGetVirtualObject(GateRef gate) const
2314514f5e3Sopenharmony_ci{
2324514f5e3Sopenharmony_ci    if (gateToVirtualObject_.count(gate)) {
2334514f5e3Sopenharmony_ci        VirtualObject* vObj = gateToVirtualObject_.at(gate);
2344514f5e3Sopenharmony_ci        return vObj;
2354514f5e3Sopenharmony_ci    }
2364514f5e3Sopenharmony_ci    return nullptr;
2374514f5e3Sopenharmony_ci}
2384514f5e3Sopenharmony_ci
2394514f5e3Sopenharmony_ciVirtualObject* EscapeAnalysis::TryGetVirtualObjectAndAddUser(GateRef gate, GateRef currentGate)
2404514f5e3Sopenharmony_ci{
2414514f5e3Sopenharmony_ci    if (gateToVirtualObject_.count(gate)) {
2424514f5e3Sopenharmony_ci        VirtualObject* vObj = gateToVirtualObject_[gate];
2434514f5e3Sopenharmony_ci        if (vObj != nullptr) {
2444514f5e3Sopenharmony_ci            vObj->AddUser(currentGate);
2454514f5e3Sopenharmony_ci        }
2464514f5e3Sopenharmony_ci        return vObj;
2474514f5e3Sopenharmony_ci    }
2484514f5e3Sopenharmony_ci    return nullptr;
2494514f5e3Sopenharmony_ci}
2504514f5e3Sopenharmony_ci
2514514f5e3Sopenharmony_ci
2524514f5e3Sopenharmony_civoid EscapeAnalysis::SetVirtualObject(GateRef gate, VirtualObject* object)
2534514f5e3Sopenharmony_ci{
2544514f5e3Sopenharmony_ci    gateToVirtualObject_[gate] = object;
2554514f5e3Sopenharmony_ci}
2564514f5e3Sopenharmony_ci
2574514f5e3Sopenharmony_civoid EscapeAnalysis::RevisitUser(VirtualObject* vObj)
2584514f5e3Sopenharmony_ci{
2594514f5e3Sopenharmony_ci    auto& users = vObj->GetUsers();
2604514f5e3Sopenharmony_ci    for (auto user : users) {
2614514f5e3Sopenharmony_ci        if (isTraced_) {
2624514f5e3Sopenharmony_ci            LOG_COMPILER(INFO) << "[escape analysis] revisit user : " <<acc_.GetId(user);
2634514f5e3Sopenharmony_ci        }
2644514f5e3Sopenharmony_ci        visitor_->ReVisitGate(user);
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci    vObj->ClearUsers();
2674514f5e3Sopenharmony_ci}
2684514f5e3Sopenharmony_ci
2694514f5e3Sopenharmony_civoid EscapeAnalysis::SetEscaped(GateRef gate)
2704514f5e3Sopenharmony_ci{
2714514f5e3Sopenharmony_ci    if (isTraced_) {
2724514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "[escape analysis] set escaped: " << acc_.GetId(gate);
2734514f5e3Sopenharmony_ci    }
2744514f5e3Sopenharmony_ci    VirtualObject* vObj = TryGetVirtualObject(gate);
2754514f5e3Sopenharmony_ci    if (vObj != nullptr && !vObj->IsEscaped()) {
2764514f5e3Sopenharmony_ci        vObj->SetEscaped();
2774514f5e3Sopenharmony_ci        RevisitUser(vObj);
2784514f5e3Sopenharmony_ci    }
2794514f5e3Sopenharmony_ci}
2804514f5e3Sopenharmony_ci
2814514f5e3Sopenharmony_ciVirtualObject* EscapeAnalysis::GetOrCreateVirtualObject(size_t numIn, GateInfo* info)
2824514f5e3Sopenharmony_ci{
2834514f5e3Sopenharmony_ci    GateRef gate = info->GetCurrentGate();
2844514f5e3Sopenharmony_ci    VirtualObject* vobj = TryGetVirtualObject(gate);
2854514f5e3Sopenharmony_ci    if (vobj == nullptr) {
2864514f5e3Sopenharmony_ci        vobj = chunk_->New<VirtualObject>(numIn, chunk_);
2874514f5e3Sopenharmony_ci    }
2884514f5e3Sopenharmony_ci    vobj->AddUser(gate);
2894514f5e3Sopenharmony_ci    info->SetVirtualObject(vobj);
2904514f5e3Sopenharmony_ci    return vobj;
2914514f5e3Sopenharmony_ci}
2924514f5e3Sopenharmony_ci
2934514f5e3Sopenharmony_ci
2944514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitCreateObjectWithBuffer(GateRef gate, GateInfo* info)
2954514f5e3Sopenharmony_ci{
2964514f5e3Sopenharmony_ci    constexpr size_t startIn = 4; // 4 : start of props
2974514f5e3Sopenharmony_ci    constexpr size_t fieldSize = 8; // 8 : bytes per field
2984514f5e3Sopenharmony_ci    constexpr size_t stride = 2; // 2: offset and value
2994514f5e3Sopenharmony_ci    auto numIn = acc_.GetNumValueIn(gate);
3004514f5e3Sopenharmony_ci    size_t size = acc_.GetConstantValue(acc_.GetValueIn(gate, 0)) / fieldSize;
3014514f5e3Sopenharmony_ci    VirtualObject* vObj = GetOrCreateVirtualObject(size, info);
3024514f5e3Sopenharmony_ci
3034514f5e3Sopenharmony_ci    for (size_t i = startIn; i < numIn; i += stride) {
3044514f5e3Sopenharmony_ci        GateRef value = acc_.GetValueIn(gate, i);
3054514f5e3Sopenharmony_ci        GateRef offset = acc_.GetValueIn(gate, i + 1);
3064514f5e3Sopenharmony_ci        if (vObj != nullptr && !vObj->IsEscaped() &&
3074514f5e3Sopenharmony_ci            vObj->GetField(acc_.GetConstantValue(offset)) != FieldLocation::Invalid()) {
3084514f5e3Sopenharmony_ci            info->SetFieldValue(vObj->GetField(acc_.GetConstantValue(offset)), value);
3094514f5e3Sopenharmony_ci        } else {
3104514f5e3Sopenharmony_ci            SetEscaped(value);
3114514f5e3Sopenharmony_ci            SetEscaped(gate);
3124514f5e3Sopenharmony_ci        }
3134514f5e3Sopenharmony_ci    }
3144514f5e3Sopenharmony_ci    info->SetVirtualObject(vObj);
3154514f5e3Sopenharmony_ci    return replaceGate_;
3164514f5e3Sopenharmony_ci}
3174514f5e3Sopenharmony_ci
3184514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitLoadProperty(GateRef gate, GateInfo* info)
3194514f5e3Sopenharmony_ci{
3204514f5e3Sopenharmony_ci    GateRef object = acc_.GetValueIn(gate, 0);
3214514f5e3Sopenharmony_ci    GateRef offset = acc_.GetValueIn(gate, 1);
3224514f5e3Sopenharmony_ci    VirtualObject* vObj = TryGetVirtualObjectAndAddUser(object, gate);
3234514f5e3Sopenharmony_ci
3244514f5e3Sopenharmony_ci    PropertyLookupResult plr(acc_.GetConstantValue(offset));
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_ci    if (vObj != nullptr && !vObj->IsEscaped() && vObj->GetField(plr.GetOffset()) != FieldLocation::Invalid()) {
3274514f5e3Sopenharmony_ci        GateRef value = info->GetFieldValue(vObj->GetField(plr.GetOffset()));
3284514f5e3Sopenharmony_ci        if (value != Circuit::NullGate()) {
3294514f5e3Sopenharmony_ci            if (isTraced_) {
3304514f5e3Sopenharmony_ci                LOG_COMPILER(INFO) << "[escape analysis] replace" << acc_.GetId(gate) << " with " << acc_.GetId(value);
3314514f5e3Sopenharmony_ci            }
3324514f5e3Sopenharmony_ci            info->SetReplacement(value);
3334514f5e3Sopenharmony_ci        } else {
3344514f5e3Sopenharmony_ci            SetEscaped(object);
3354514f5e3Sopenharmony_ci        }
3364514f5e3Sopenharmony_ci    } else {
3374514f5e3Sopenharmony_ci        SetEscaped(object);
3384514f5e3Sopenharmony_ci    }
3394514f5e3Sopenharmony_ci    return replaceGate_;
3404514f5e3Sopenharmony_ci}
3414514f5e3Sopenharmony_ci
3424514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitLoadConstOffset(GateRef gate, GateInfo* info)
3434514f5e3Sopenharmony_ci{
3444514f5e3Sopenharmony_ci    GateRef object = acc_.GetValueIn(gate, 0);
3454514f5e3Sopenharmony_ci    size_t offset = acc_.GetOffset(gate);
3464514f5e3Sopenharmony_ci    VirtualObject* vObj = TryGetVirtualObjectAndAddUser(object, gate);
3474514f5e3Sopenharmony_ci
3484514f5e3Sopenharmony_ci    if (vObj != nullptr && !vObj->IsEscaped() && vObj->GetField(offset) != FieldLocation::Invalid()) {
3494514f5e3Sopenharmony_ci        GateRef value = info->GetFieldValue(vObj->GetField(offset));
3504514f5e3Sopenharmony_ci        if (value != Circuit::NullGate()) {
3514514f5e3Sopenharmony_ci            if (isTraced_) {
3524514f5e3Sopenharmony_ci                LOG_COMPILER(INFO) << "[escape analysis] replace " <<
3534514f5e3Sopenharmony_ci                                      acc_.GetId(gate) << " with " << acc_.GetId(value);
3544514f5e3Sopenharmony_ci            }
3554514f5e3Sopenharmony_ci            info->SetReplacement(value);
3564514f5e3Sopenharmony_ci        } else {
3574514f5e3Sopenharmony_ci            SetEscaped(object);
3584514f5e3Sopenharmony_ci        }
3594514f5e3Sopenharmony_ci    } else {
3604514f5e3Sopenharmony_ci        SetEscaped(object);
3614514f5e3Sopenharmony_ci    }
3624514f5e3Sopenharmony_ci    return replaceGate_;
3634514f5e3Sopenharmony_ci}
3644514f5e3Sopenharmony_ci
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitStoreProperty(GateRef gate, GateInfo* info)
3674514f5e3Sopenharmony_ci{
3684514f5e3Sopenharmony_ci    GateRef object = acc_.GetValueIn(gate, 0);
3694514f5e3Sopenharmony_ci    GateRef offset = acc_.GetValueIn(gate, 1);
3704514f5e3Sopenharmony_ci    GateRef value = acc_.GetValueIn(gate, 2);
3714514f5e3Sopenharmony_ci    VirtualObject* vObj = TryGetVirtualObjectAndAddUser(object, gate);
3724514f5e3Sopenharmony_ci    PropertyLookupResult plr(acc_.GetConstantValue(offset));
3734514f5e3Sopenharmony_ci
3744514f5e3Sopenharmony_ci    if (vObj != nullptr && !vObj->IsEscaped() && vObj->GetField(plr.GetOffset()) != FieldLocation::Invalid()) {
3754514f5e3Sopenharmony_ci        info->SetFieldValue(vObj->GetField(plr.GetOffset()), value);
3764514f5e3Sopenharmony_ci        info->SetEliminated();
3774514f5e3Sopenharmony_ci    } else {
3784514f5e3Sopenharmony_ci        SetEscaped(value);
3794514f5e3Sopenharmony_ci        SetEscaped(object);
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci    return replaceGate_;
3824514f5e3Sopenharmony_ci}
3834514f5e3Sopenharmony_ci
3844514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitObjectTypeCheck(GateRef gate, GateInfo* info)
3854514f5e3Sopenharmony_ci{
3864514f5e3Sopenharmony_ci    info->SetVirtualObject(TryGetVirtualObject(acc_.GetValueIn(gate)));
3874514f5e3Sopenharmony_ci    return Circuit::NullGate();
3884514f5e3Sopenharmony_ci}
3894514f5e3Sopenharmony_ci
3904514f5e3Sopenharmony_ciState& EscapeAnalysis::GetOrCreateState(GateRef gate)
3914514f5e3Sopenharmony_ci{
3924514f5e3Sopenharmony_ci    auto it = gateToState_.find(gate);
3934514f5e3Sopenharmony_ci    if (it == gateToState_.end()) {
3944514f5e3Sopenharmony_ci        State tmp(chunk_);
3954514f5e3Sopenharmony_ci        auto result = gateToState_.insert(std::make_pair(gate, std::move(tmp)));
3964514f5e3Sopenharmony_ci        return result.first->second;
3974514f5e3Sopenharmony_ci    }
3984514f5e3Sopenharmony_ci    return it->second;
3994514f5e3Sopenharmony_ci}
4004514f5e3Sopenharmony_ci
4014514f5e3Sopenharmony_civoid EscapeAnalysis::SetState(GateRef gate, State state)
4024514f5e3Sopenharmony_ci{
4034514f5e3Sopenharmony_ci    auto it = gateToState_.find(gate);
4044514f5e3Sopenharmony_ci    if (it == gateToState_.end()) {
4054514f5e3Sopenharmony_ci        gateToState_.insert(std::make_pair(gate, std::move(state)));
4064514f5e3Sopenharmony_ci    } else {
4074514f5e3Sopenharmony_ci        it->second = state;
4084514f5e3Sopenharmony_ci    }
4094514f5e3Sopenharmony_ci}
4104514f5e3Sopenharmony_ci
4114514f5e3Sopenharmony_civoid EscapeAnalysis::RevisitGate(GateRef gate)
4124514f5e3Sopenharmony_ci{
4134514f5e3Sopenharmony_ci    visitor_->ReVisitGate(gate);
4144514f5e3Sopenharmony_ci}
4154514f5e3Sopenharmony_ci
4164514f5e3Sopenharmony_civoid EscapeAnalysis::SetReplaceGate(GateRef gate)
4174514f5e3Sopenharmony_ci{
4184514f5e3Sopenharmony_ci    replaceGate_ = gate;
4194514f5e3Sopenharmony_ci}
4204514f5e3Sopenharmony_ci
4214514f5e3Sopenharmony_ciGateRef EscapeAnalysis::VisitGate(GateRef gate)
4224514f5e3Sopenharmony_ci{
4234514f5e3Sopenharmony_ci    GateInfo info(circuit_, gate, this, chunk_);
4244514f5e3Sopenharmony_ci    auto opcode = acc_.GetOpCode(gate);
4254514f5e3Sopenharmony_ci    replaceGate_ = Circuit::NullGate();
4264514f5e3Sopenharmony_ci    switch (opcode) {
4274514f5e3Sopenharmony_ci        case OpCode::STORE_PROPERTY:
4284514f5e3Sopenharmony_ci        case OpCode::STORE_PROPERTY_NO_BARRIER:
4294514f5e3Sopenharmony_ci            return VisitStoreProperty(gate, &info);
4304514f5e3Sopenharmony_ci        case OpCode::LOAD_PROPERTY:
4314514f5e3Sopenharmony_ci            return VisitLoadProperty(gate, &info);
4324514f5e3Sopenharmony_ci        case OpCode::LOAD_CONST_OFFSET:
4334514f5e3Sopenharmony_ci            return VisitLoadConstOffset(gate, &info);
4344514f5e3Sopenharmony_ci        case OpCode::TYPED_CREATE_OBJ_WITH_BUFFER:
4354514f5e3Sopenharmony_ci            return VisitCreateObjectWithBuffer(gate, &info);
4364514f5e3Sopenharmony_ci        case OpCode::OBJECT_TYPE_CHECK:
4374514f5e3Sopenharmony_ci        case OpCode::CHECK_AND_CONVERT:
4384514f5e3Sopenharmony_ci            return VisitObjectTypeCheck(gate, &info);
4394514f5e3Sopenharmony_ci        case OpCode::FRAME_VALUES:
4404514f5e3Sopenharmony_ci        case OpCode::STATE_SPLIT:
4414514f5e3Sopenharmony_ci        case OpCode::FRAME_STATE:
4424514f5e3Sopenharmony_ci            break;
4434514f5e3Sopenharmony_ci        default : {
4444514f5e3Sopenharmony_ci            size_t numIns = acc_.GetNumValueIn(gate);
4454514f5e3Sopenharmony_ci            for (size_t i = 0; i < numIns; i++) {
4464514f5e3Sopenharmony_ci                GateRef in = GetCurrentGate(acc_.GetValueIn(gate, i));
4474514f5e3Sopenharmony_ci                SetEscaped(in);
4484514f5e3Sopenharmony_ci            }
4494514f5e3Sopenharmony_ci        }
4504514f5e3Sopenharmony_ci    }
4514514f5e3Sopenharmony_ci    return Circuit::NullGate();
4524514f5e3Sopenharmony_ci}
4534514f5e3Sopenharmony_ci
4544514f5e3Sopenharmony_ci}