mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
efdee45a09
Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAMPAW Description:1:短路求值整改,修改BoolAnd/BoolOr为LogicAnd/LogicOr;2:为降低性能影响,部分确定无问题的场景,依然使用BoolAnd类接口,并修改其名称为BitAnd Signed-off-by: zhangyinlu <zhangyinlu@huawei.com> Change-Id: Ia7dc6f73322dc7588213c6a4c1a14f87104bf378
265 lines
6.3 KiB
C++
265 lines
6.3 KiB
C++
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
|
|
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
|
|
|
|
#include "ecmascript/compiler/lcr_circuit_builder.h"
|
|
#include "ecmascript/compiler/mcr_circuit_builder.h"
|
|
#include "ecmascript/compiler/hcr_circuit_builder.h"
|
|
#include "ecmascript/compiler/circuit_builder.h"
|
|
#include "ecmascript/mem/region.h"
|
|
#include "ecmascript/method.h"
|
|
|
|
namespace panda::ecmascript::kungfu {
|
|
// constant
|
|
GateRef CircuitBuilder::True()
|
|
{
|
|
return Boolean(true);
|
|
}
|
|
|
|
GateRef CircuitBuilder::False()
|
|
{
|
|
return Boolean(false);
|
|
}
|
|
|
|
GateRef CircuitBuilder::Undefined()
|
|
{
|
|
return UndefineConstant();
|
|
}
|
|
|
|
GateRef CircuitBuilder::Hole()
|
|
{
|
|
return HoleConstant();
|
|
}
|
|
|
|
GateRef CircuitBuilder::DoubleIsINF(GateRef x)
|
|
{
|
|
GateRef infinity = Double(base::POSITIVE_INFINITY);
|
|
GateRef negativeInfinity = Double(-base::POSITIVE_INFINITY);
|
|
GateRef diff1 = DoubleEqual(x, infinity);
|
|
GateRef diff2 = DoubleEqual(x, negativeInfinity);
|
|
return BitOr(diff1, diff2);
|
|
}
|
|
|
|
GateRef CircuitBuilder::DoubleIsNanOrInf(GateRef x)
|
|
{
|
|
return BitOr(DoubleIsNAN(x), DoubleIsINF(x));
|
|
}
|
|
|
|
// Js World
|
|
// cast operation
|
|
|
|
GateRef CircuitBuilder::GetGlobalConstantOffset(ConstantIndex index)
|
|
{
|
|
return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index)));
|
|
}
|
|
|
|
GateRef CircuitBuilder::GetExpectedNumOfArgs(GateRef method)
|
|
{
|
|
GateRef callFieldOffset = IntPtr(Method::CALL_FIELD_OFFSET);
|
|
GateRef callfield = Load(VariableType::INT64(), method, callFieldOffset);
|
|
return Int64And(
|
|
Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
|
|
Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
|
|
}
|
|
|
|
int CircuitBuilder::NextVariableId()
|
|
{
|
|
return env_->NextVariableId();
|
|
}
|
|
|
|
void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit)
|
|
{
|
|
BRANCH_CIR2(Equal(result, ExceptionConstant()), fail, success);
|
|
Bind(fail);
|
|
{
|
|
Jump(exit);
|
|
}
|
|
}
|
|
|
|
void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal)
|
|
{
|
|
BRANCH_CIR2(Equal(result, exceptionVal), fail, success);
|
|
Bind(fail);
|
|
{
|
|
Jump(exit);
|
|
}
|
|
}
|
|
|
|
void CircuitBuilder::SubCfgEntry(Label *entry)
|
|
{
|
|
ASSERT(env_ != nullptr);
|
|
env_->SubCfgEntry(entry);
|
|
}
|
|
|
|
void CircuitBuilder::SubCfgExit()
|
|
{
|
|
ASSERT(env_ != nullptr);
|
|
env_->SubCfgExit();
|
|
}
|
|
|
|
GateRef CircuitBuilder::Return(GateRef value)
|
|
{
|
|
auto control = GetCurrentLabel()->GetControl();
|
|
auto depend = GetCurrentLabel()->GetDepend();
|
|
return Return(control, depend, value);
|
|
}
|
|
|
|
GateRef CircuitBuilder::Return()
|
|
{
|
|
auto control = GetCurrentLabel()->GetControl();
|
|
auto depend = GetCurrentLabel()->GetDepend();
|
|
return ReturnVoid(control, depend);
|
|
}
|
|
|
|
void CircuitBuilder::Bind(Label *label)
|
|
{
|
|
label->Bind();
|
|
env_->SetCurrentLabel(label);
|
|
}
|
|
|
|
void CircuitBuilder::Bind(Label *label, bool justSlowPath)
|
|
{
|
|
if (!justSlowPath) {
|
|
label->Bind();
|
|
env_->SetCurrentLabel(label);
|
|
}
|
|
}
|
|
|
|
GateRef CircuitBuilder::GetState() const
|
|
{
|
|
return GetCurrentLabel()->GetControl();
|
|
}
|
|
|
|
GateRef CircuitBuilder::GetDepend() const
|
|
{
|
|
return GetCurrentLabel()->GetDepend();
|
|
}
|
|
|
|
StateDepend CircuitBuilder::GetStateDepend() const
|
|
{
|
|
return StateDepend(GetState(), GetDepend());
|
|
}
|
|
|
|
void CircuitBuilder::SetDepend(GateRef depend)
|
|
{
|
|
GetCurrentLabel()->SetDepend(depend);
|
|
}
|
|
|
|
void CircuitBuilder::SetState(GateRef state)
|
|
{
|
|
GetCurrentLabel()->SetControl(state);
|
|
}
|
|
|
|
Label *CircuitBuilder::GetCurrentLabel() const
|
|
{
|
|
return GetCurrentEnvironment()->GetCurrentLabel();
|
|
}
|
|
|
|
LogicAndBuilder::LogicAndBuilder(Environment *env)
|
|
: env_(env), builder_(env_->GetBuilder())
|
|
{
|
|
subentry_ = new Label(env_);
|
|
builder_->SubCfgEntry(subentry_);
|
|
result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->False());
|
|
exit_ = new Label(env_);
|
|
}
|
|
|
|
LogicAndBuilder::~LogicAndBuilder()
|
|
{
|
|
ASSERT(exit_ != nullptr);
|
|
delete exit_;
|
|
exit_ = nullptr;
|
|
ASSERT(result_ != nullptr);
|
|
delete result_;
|
|
result_ = nullptr;
|
|
ASSERT(subentry_ != nullptr);
|
|
delete subentry_;
|
|
subentry_ = nullptr;
|
|
for (auto &label : labels_) {
|
|
ASSERT(label != nullptr);
|
|
delete label;
|
|
label = nullptr;
|
|
}
|
|
}
|
|
|
|
LogicAndBuilder &LogicAndBuilder::And(GateRef check)
|
|
{
|
|
auto checkTrue = new Label(env_);
|
|
labels_.push_back(checkTrue);
|
|
builder_->Branch(check, checkTrue, exit_);
|
|
builder_->Bind(checkTrue);
|
|
return *this;
|
|
}
|
|
|
|
GateRef LogicAndBuilder::Done()
|
|
{
|
|
*result_ = builder_->True();
|
|
builder_->Jump(exit_);
|
|
builder_->Bind(exit_);
|
|
auto ret = **result_;
|
|
builder_->SubCfgExit();
|
|
return ret;
|
|
}
|
|
|
|
LogicOrBuilder::LogicOrBuilder(Environment *env)
|
|
: env_(env), builder_(env_->GetBuilder())
|
|
{
|
|
subentry_ = new Label(env_);
|
|
builder_->SubCfgEntry(subentry_);
|
|
result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->True());
|
|
exit_ = new Label(env_);
|
|
}
|
|
|
|
LogicOrBuilder::~LogicOrBuilder()
|
|
{
|
|
ASSERT(exit_ != nullptr);
|
|
delete exit_;
|
|
exit_ = nullptr;
|
|
ASSERT(result_ != nullptr);
|
|
delete result_;
|
|
result_ = nullptr;
|
|
ASSERT(subentry_ != nullptr);
|
|
delete subentry_;
|
|
subentry_ = nullptr;
|
|
for (auto &label : labels_) {
|
|
ASSERT(label != nullptr);
|
|
delete label;
|
|
label = nullptr;
|
|
}
|
|
}
|
|
|
|
LogicOrBuilder &LogicOrBuilder::Or(GateRef check)
|
|
{
|
|
auto checkFalse = new Label(env_);
|
|
labels_.push_back(checkFalse);
|
|
builder_->Branch(check, exit_, checkFalse);
|
|
builder_->Bind(checkFalse);
|
|
return *this;
|
|
}
|
|
|
|
GateRef LogicOrBuilder::Done()
|
|
{
|
|
*result_ = builder_->False();
|
|
builder_->Jump(exit_);
|
|
builder_->Bind(exit_);
|
|
auto ret = **result_;
|
|
builder_->SubCfgExit();
|
|
return ret;
|
|
}
|
|
} // namespace panda::ecmascript::kungfu
|
|
|
|
#endif
|