mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Description: Number Speculative Pass
Issues: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6NSQS Signed-off-by: K0u1hw <wangchunyang15@huawei.com> Change-Id: I7b372a0cd2d28fda49fb85466cac731cae31f95a
This commit is contained in:
parent
26bdac03bf
commit
50973eef7d
@ -99,6 +99,9 @@ ohos_source_set("libark_jsoptimizer_set") {
|
||||
"llvm_codegen.cpp",
|
||||
"llvm_ir_builder.cpp",
|
||||
"new_object_stub_builder.cpp",
|
||||
"number_speculative_lowering.cpp",
|
||||
"number_speculative_retype.cpp",
|
||||
"number_speculative_runner.cpp",
|
||||
"operations_stub_builder.cpp",
|
||||
"pass_manager.cpp",
|
||||
"rt_call_signature.cpp",
|
||||
|
@ -116,6 +116,12 @@ GateRef CircuitBuilder::GetDoubleOfTDouble(GateRef x)
|
||||
return CastInt64ToFloat64(val);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetBooleanOfTBoolean(GateRef x)
|
||||
{
|
||||
GateRef tagged = ChangeTaggedPointerToInt64(x);
|
||||
return TruncInt64ToInt1(tagged);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetDoubleOfTNumber(GateRef x)
|
||||
{
|
||||
Label subentry(env_);
|
||||
|
@ -49,7 +49,6 @@ GateRef CircuitBuilder::Selector(OpCode opcode, MachineType machineType, GateRef
|
||||
return circuit_->NewGate(meta, machineType, inList.size(), inList.data(), type.GetGateType());
|
||||
}
|
||||
|
||||
|
||||
GateRef CircuitBuilder::Selector(OpCode opcode, GateRef control,
|
||||
const std::vector<GateRef> &values, int valueCounts, VariableType type)
|
||||
{
|
||||
@ -203,6 +202,126 @@ GateRef CircuitBuilder::IndexCheck(GateType type, GateRef gate, GateRef index)
|
||||
return ret;
|
||||
}
|
||||
|
||||
MachineType CircuitBuilder::GetMachineTypeOfValueType(ValueType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ValueType::BOOL:
|
||||
return MachineType::I1;
|
||||
case ValueType::INT32:
|
||||
return MachineType::I32;
|
||||
case ValueType::FLOAT64:
|
||||
return MachineType::F64;
|
||||
case ValueType::TAGGED_BOOLEAN:
|
||||
case ValueType::TAGGED_INT:
|
||||
case ValueType::TAGGED_DOUBLE:
|
||||
case ValueType::TAGGED_NUMBER:
|
||||
return MachineType::I64;
|
||||
default:
|
||||
return MachineType::NOVALUE;
|
||||
}
|
||||
}
|
||||
|
||||
GateType CircuitBuilder::GetGateTypeOfValueType(ValueType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ValueType::BOOL:
|
||||
case ValueType::INT32:
|
||||
case ValueType::FLOAT64:
|
||||
return GateType::NJSValue();
|
||||
case ValueType::TAGGED_BOOLEAN:
|
||||
return GateType::BooleanType();
|
||||
case ValueType::TAGGED_INT:
|
||||
return GateType::IntType();
|
||||
case ValueType::TAGGED_DOUBLE:
|
||||
return GateType::DoubleType();
|
||||
case ValueType::TAGGED_NUMBER:
|
||||
return GateType::NumberType();
|
||||
default:
|
||||
return GateType::Empty();
|
||||
}
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckAndConvert(GateRef gate, ValueType src, ValueType dst)
|
||||
{
|
||||
MachineType machineType = GetMachineTypeOfValueType(dst);
|
||||
GateType gateType = GetGateTypeOfValueType(dst);
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
ASSERT(acc_.HasFrameState(currentDepend));
|
||||
auto frameState = acc_.GetFrameState(currentDepend);
|
||||
uint64_t value = ValuePairTypeAccessor::ToValue(src, dst);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->CheckAndConvert(value),
|
||||
machineType, {currentControl, currentDepend, gate, frameState}, gateType);
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Convert(GateRef gate, ValueType src, ValueType dst)
|
||||
{
|
||||
MachineType machineType = GetMachineTypeOfValueType(dst);
|
||||
GateType gateType = GetGateTypeOfValueType(dst);
|
||||
uint64_t value = ValuePairTypeAccessor::ToValue(src, dst);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->Convert(value), machineType, {gate}, gateType);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertInt32ToFloat64(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::INT32, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertFloat64ToInt32(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::FLOAT64, ValueType::INT32);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertBoolToTaggedBoolean(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::BOOL, ValueType::TAGGED_BOOLEAN);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::INT32, ValueType::TAGGED_INT);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ConvertFloat64ToTaggedDouble(GateRef gate)
|
||||
{
|
||||
return Convert(gate, ValueType::FLOAT64, ValueType::TAGGED_DOUBLE);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedIntAndConvertToInt32(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::INT32);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToInt32(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::INT32);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedNumberAndConvertToInt32(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::INT32);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedIntAndConvertToFloat64(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_INT, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedDoubleAndConvertToFloat64(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_DOUBLE, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CheckTaggedNumberAndConvertToFloat64(GateRef gate)
|
||||
{
|
||||
return CheckAndConvert(gate, ValueType::TAGGED_NUMBER, ValueType::FLOAT64);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TryPrimitiveTypeCheck(GateType type, GateRef gate)
|
||||
{
|
||||
if (acc_.GetOpCode(gate) == OpCode::CONSTANT) {
|
||||
|
@ -106,6 +106,7 @@ class Variable;
|
||||
V(TruncInt32ToInt1, Trunc, MachineType::I1) \
|
||||
V(TruncInt32ToInt16, Trunc, MachineType::I16) \
|
||||
V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64) \
|
||||
V(TruncFloatToInt32, TruncFloatToInt32, MachineType::I32) \
|
||||
V(ExtFloat32ToDouble, Fext, MachineType::F64) \
|
||||
V(TruncDoubleToFloat32, Ftrunc, MachineType::F32) \
|
||||
V(ChangeTaggedPointerToInt64, TaggedToInt64, MachineType::I64) \
|
||||
@ -242,6 +243,21 @@ public:
|
||||
GateRef TypedCallOperator(GateRef hirGate, MachineType type, const std::initializer_list<GateRef>& args);
|
||||
inline GateRef TypedCallBuiltin(GateRef hirGate, GateRef x, BuiltinsStubCSigns::ID id);
|
||||
GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
|
||||
MachineType GetMachineTypeOfValueType(ValueType type);
|
||||
GateType GetGateTypeOfValueType(ValueType type);
|
||||
GateRef Convert(GateRef gate, ValueType src, ValueType dst);
|
||||
GateRef ConvertBoolToTaggedBoolean(GateRef gate);
|
||||
GateRef ConvertInt32ToTaggedInt(GateRef gate);
|
||||
GateRef ConvertFloat64ToTaggedDouble(GateRef gate);
|
||||
GateRef ConvertFloat64ToInt32(GateRef gate);
|
||||
GateRef ConvertInt32ToFloat64(GateRef gate);
|
||||
GateRef CheckAndConvert(GateRef gate, ValueType src, ValueType dst);
|
||||
GateRef CheckTaggedIntAndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedDoubleAndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedNumberAndConvertToInt32(GateRef gate);
|
||||
GateRef CheckTaggedIntAndConvertToFloat64(GateRef gate);
|
||||
GateRef CheckTaggedDoubleAndConvertToFloat64(GateRef gate);
|
||||
GateRef CheckTaggedNumberAndConvertToFloat64(GateRef gate);
|
||||
GateRef TypedUnaryOperator(MachineType type, TypedUnOp unaryOp, GateType typeVal,
|
||||
const std::vector<GateRef>& inList, GateType gateType);
|
||||
GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState);
|
||||
@ -347,6 +363,7 @@ public:
|
||||
inline GateRef GetInt32OfTInt(GateRef x);
|
||||
inline GateRef TaggedCastToIntPtr(GateRef x);
|
||||
inline GateRef GetDoubleOfTDouble(GateRef x);
|
||||
inline GateRef GetBooleanOfTBoolean(GateRef x);
|
||||
inline GateRef GetDoubleOfTNumber(GateRef x);
|
||||
inline GateRef Int32ToTaggedPtr(GateRef x);
|
||||
inline GateRef Int64ToTaggedPtr(GateRef x);
|
||||
|
@ -362,14 +362,11 @@ void EarlyElimination::Run()
|
||||
VisitDependEntry(entry);
|
||||
VisitGraph();
|
||||
|
||||
for (auto gate : stateSplits_) {
|
||||
ReplaceGate(gate, circuit_->DeadGate());
|
||||
}
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
<< "===================="
|
||||
<< " After check eliminating "
|
||||
<< " After early eliminating "
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
@ -703,10 +700,8 @@ GateRef EarlyElimination::TryEliminateStateSplitAndFrameState(GateRef gate)
|
||||
auto curFrameState = acc_.GetFrameState(gate);
|
||||
if (frameState != Circuit::NullGate()) {
|
||||
acc_.UpdateAllUses(curFrameState, frameState);
|
||||
acc_.DeleteGate(curFrameState);
|
||||
return circuit_->DeadGate();
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
stateSplits_.insert(gate);
|
||||
dependInfo = dependInfo->UpdateFrameState(curFrameState);
|
||||
return UpdateDependInfo(gate, dependInfo);
|
||||
}
|
||||
|
@ -341,7 +341,7 @@ class EarlyElimination : public GraphVisitor {
|
||||
public:
|
||||
EarlyElimination(Circuit *circuit, bool enableLog, const std::string& name, Chunk* chunk)
|
||||
: GraphVisitor(circuit, chunk), enableLog_(enableLog),
|
||||
methodName_(name), dependInfos_(chunk), stateSplits_(chunk) {}
|
||||
methodName_(name), dependInfos_(chunk) {}
|
||||
|
||||
~EarlyElimination() = default;
|
||||
|
||||
@ -391,7 +391,6 @@ private:
|
||||
bool enableLog_ {false};
|
||||
std::string methodName_;
|
||||
ChunkVector<DependChainInfo*> dependInfos_;
|
||||
ChunkSet<GateRef> stateSplits_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_EARLY_ELIMINATION_H
|
@ -17,6 +17,7 @@
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/graph_editor.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
using UseIterator = GateAccessor::UseIterator;
|
||||
@ -135,6 +136,24 @@ GateType GateAccessor::GetParamGateType(GateRef gate) const
|
||||
return accessor.GetGateType();
|
||||
}
|
||||
|
||||
ValueType GateAccessor::GetSrcType(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
|
||||
GetOpCode(gate) == OpCode::CHECK_AND_CONVERT);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetSrcType();
|
||||
}
|
||||
|
||||
ValueType GateAccessor::GetDstType(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
|
||||
GetOpCode(gate) == OpCode::CHECK_AND_CONVERT);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetDstType();
|
||||
}
|
||||
|
||||
GateType GateAccessor::GetLeftType(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::TYPED_UNARY_OP ||
|
||||
@ -383,6 +402,11 @@ bool GateAccessor::IsConstantValue(GateRef gate, uint64_t value) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GateAccessor::IsConstantUndefined(GateRef gate) const
|
||||
{
|
||||
return IsConstantValue(gate, JSTaggedValue::VALUE_UNDEFINED);
|
||||
}
|
||||
|
||||
bool GateAccessor::IsTypedOperator(GateRef gate) const
|
||||
{
|
||||
return GetMetaData(gate)->IsTypedOperator();
|
||||
@ -457,8 +481,12 @@ void GateAccessor::SetGateType(GateRef gate, GateType gt)
|
||||
UseIterator GateAccessor::ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state)
|
||||
{
|
||||
ASSERT(GetOpCode(*useIt) == OpCode::IF_SUCCESS);
|
||||
auto firstUse = Uses(*useIt).begin();
|
||||
ReplaceIn(*firstUse, firstUse.GetIndex(), state);
|
||||
auto uses = Uses(*useIt);
|
||||
for (auto it = uses.begin(); it != uses.end();) {
|
||||
if (IsStateIn(it)) {
|
||||
it = ReplaceIn(it, state);
|
||||
}
|
||||
}
|
||||
auto next = DeleteGate(useIt);
|
||||
return next;
|
||||
}
|
||||
@ -501,6 +529,8 @@ void GateAccessor::ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success,
|
||||
} else if (op == OpCode::IF_EXCEPTION) {
|
||||
ifException = *it;
|
||||
it = ReplaceHirIfException(it, exception);
|
||||
} else if (op == OpCode::STATE_SPLIT) {
|
||||
it = ReplaceIn(it, success.State());
|
||||
} else {
|
||||
ExceptionReturn(exception.State(), exception.Depend());
|
||||
it = ReplaceIn(it, success.State());
|
||||
@ -632,6 +662,9 @@ size_t GateAccessor::GetInValueCount(GateRef gate) const
|
||||
|
||||
void GateAccessor::UpdateAllUses(GateRef oldIn, GateRef newIn)
|
||||
{
|
||||
if (oldIn == newIn) {
|
||||
return;
|
||||
}
|
||||
auto uses = Uses(oldIn);
|
||||
for (auto useIt = uses.begin(); useIt != uses.end();) {
|
||||
useIt = ReplaceIn(useIt, newIn);
|
||||
@ -690,6 +723,35 @@ GateRef GateAccessor::GetConstantGate(MachineType bitValue, BitField bitfield, G
|
||||
return circuit_->GetConstantGate(bitValue, bitfield, type);
|
||||
}
|
||||
|
||||
bool GateAccessor::IsConstantNumber(GateRef gate) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
if (GetGateType(gate).IsNJSValueType() ||
|
||||
(GetOpCode(gate) != OpCode::CONSTANT)) {
|
||||
return false;
|
||||
}
|
||||
JSTaggedValue value(GetConstantValue(gate));
|
||||
return value.IsNumber();
|
||||
}
|
||||
|
||||
double GateAccessor::GetFloat64FromConstant(GateRef gate) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(GetOpCode(gate) == OpCode::CONSTANT);
|
||||
ASSERT(!GetGateType(gate).IsNJSValueType());
|
||||
JSTaggedValue value(GetConstantValue(gate));
|
||||
return value.GetDouble();
|
||||
}
|
||||
|
||||
int GateAccessor::GetInt32FromConstant(GateRef gate) const
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
ASSERT(GetOpCode(gate) == OpCode::CONSTANT);
|
||||
ASSERT(!GetGateType(gate).IsNJSValueType());
|
||||
JSTaggedValue value(GetConstantValue(gate));
|
||||
return value.GetInt();
|
||||
}
|
||||
|
||||
bool GateAccessor::IsStateIn(const UseIterator &useIt) const
|
||||
{
|
||||
size_t stateStartIndex = 0;
|
||||
@ -773,10 +835,13 @@ void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, Gate
|
||||
auto uses = Uses(gate);
|
||||
for (auto useIt = uses.begin(); useIt != uses.end();) {
|
||||
if (IsStateIn(useIt)) {
|
||||
ASSERT(state != Circuit::NullGate());
|
||||
useIt = ReplaceIn(useIt, state);
|
||||
} else if (IsDependIn(useIt)) {
|
||||
ASSERT(depend != Circuit::NullGate());
|
||||
useIt = ReplaceIn(useIt, depend);
|
||||
} else if (IsValueIn(useIt)) {
|
||||
ASSERT(value != Circuit::NullGate());
|
||||
useIt = ReplaceIn(useIt, value);
|
||||
} else {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_GATE_ACCESSOR_H
|
||||
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
@ -395,6 +396,8 @@ public:
|
||||
UseIterator ReplaceIn(const UseIterator &useIt, GateRef replaceGate);
|
||||
// Add for lowering
|
||||
GateType GetGateType(GateRef gate) const;
|
||||
ValueType GetSrcType(GateRef gate) const;
|
||||
ValueType GetDstType(GateRef gate) const;
|
||||
void SetGateType(GateRef gate, GateType gt);
|
||||
void DeleteIn(GateRef gate, size_t idx);
|
||||
UseIterator DeleteGate(const UseIterator &useIt);
|
||||
@ -414,6 +417,8 @@ public:
|
||||
MachineType GetMachineType(GateRef gate) const;
|
||||
void SetMachineType(GateRef gate, MachineType type);
|
||||
GateRef GetConstantGate(MachineType bitValue, BitField bitfield, GateType type) const;
|
||||
double GetFloat64FromConstant(GateRef gate) const;
|
||||
int GetInt32FromConstant(GateRef gate) const;
|
||||
bool IsInGateNull(GateRef gate, size_t idx) const;
|
||||
bool IsSelector(GateRef g) const;
|
||||
bool IsControlCase(GateRef gate) const;
|
||||
@ -423,6 +428,8 @@ public:
|
||||
bool IsConstant(GateRef gate) const;
|
||||
bool IsDependSelector(GateRef gate) const;
|
||||
bool IsConstantValue(GateRef gate, uint64_t value) const;
|
||||
bool IsConstantUndefined(GateRef gate) const;
|
||||
bool IsConstantNumber(GateRef gate) const;
|
||||
bool IsTypedOperator(GateRef gate) const;
|
||||
bool IsNotWrite(GateRef gate) const;
|
||||
bool IsDead(GateRef gate) const;
|
||||
@ -560,6 +567,7 @@ private:
|
||||
friend class ArgumentAccessor;
|
||||
friend class BytecodeCircuitBuilder;
|
||||
friend class TSInlineLowering;
|
||||
friend class GraphVisitor;
|
||||
};
|
||||
|
||||
class ConstGateAccessor {
|
||||
|
@ -162,6 +162,7 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(Ftrunc, FTRUNC, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(Rev, REV, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(TruncFloatToInt64, TRUNC_FLOAT_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(TruncFloatToInt32, TRUNC_FLOAT_TO_INT32, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(TaggedToInt64, TAGGED_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(Int64ToTagged, INT64_TO_TAGGED, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(SignedIntToFloat, SIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
@ -246,7 +247,9 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(Int32OverflowCheck, INT32_OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1)
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
|
||||
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
|
||||
@ -589,6 +592,37 @@ private:
|
||||
GateType type_;
|
||||
};
|
||||
|
||||
class ValuePairTypeAccessor {
|
||||
public:
|
||||
// type bits shift
|
||||
static constexpr int OPRAND_TYPE_BITS = 8;
|
||||
explicit ValuePairTypeAccessor(uint64_t value) : bitField_(value) {}
|
||||
|
||||
ValueType GetSrcType() const
|
||||
{
|
||||
return static_cast<ValueType>(LeftBits::Get(bitField_));
|
||||
}
|
||||
|
||||
ValueType GetDstType() const
|
||||
{
|
||||
return static_cast<ValueType>(RightBits::Get(bitField_));
|
||||
}
|
||||
|
||||
static uint16_t ToValue(ValueType srcType, ValueType dstType)
|
||||
{
|
||||
uint8_t srcVlaue = static_cast<uint8_t>(srcType);
|
||||
uint8_t dstVlaue = static_cast<uint8_t>(dstType);
|
||||
return LeftBits::Encode(srcVlaue) | RightBits::Encode(dstVlaue);
|
||||
}
|
||||
|
||||
private:
|
||||
using LeftBits = panda::BitField<uint8_t, 0, OPRAND_TYPE_BITS>;
|
||||
using RightBits = LeftBits::NextField<uint8_t, OPRAND_TYPE_BITS>;
|
||||
|
||||
uint64_t bitField_;
|
||||
};
|
||||
|
||||
|
||||
class GatePairTypeAccessor {
|
||||
public:
|
||||
// type bits shift
|
||||
|
@ -76,6 +76,14 @@ void GraphVisitor::VisitGraph()
|
||||
}
|
||||
}
|
||||
|
||||
void GraphVisitor::ReVisitGate(GateRef gate)
|
||||
{
|
||||
if (acc_.GetMark(gate) == MarkCode::FINISHED) {
|
||||
PushEffectGate(gate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reverse post-order
|
||||
void GraphVisitor::VisitTopGate(Edge& current)
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
virtual ~GraphVisitor() = default;
|
||||
|
||||
void VisitGraph();
|
||||
void ReVisitGate(GateRef gate);
|
||||
|
||||
virtual GateRef VisitGate(GateRef gate) = 0;
|
||||
protected:
|
||||
|
@ -184,6 +184,7 @@ void LLVMIRBuilder::InitializeHandlers()
|
||||
{OpCode::FMOD, &LLVMIRBuilder::HandleMod},
|
||||
{OpCode::DEOPT, &LLVMIRBuilder::HandleDeopt},
|
||||
{OpCode::TRUNC_FLOAT_TO_INT64, &LLVMIRBuilder::HandleTruncFloatToInt},
|
||||
{OpCode::TRUNC_FLOAT_TO_INT32, &LLVMIRBuilder::HandleTruncFloatToInt},
|
||||
};
|
||||
illegalOpHandlers_ = {
|
||||
OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY,
|
||||
|
86
ecmascript/compiler/number_gate_info.h
Normal file
86
ecmascript/compiler/number_gate_info.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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_NUMBER_GATE_INFO_H
|
||||
#define ECMASCRIPT_NUMBER_GATE_INFO_H
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
enum class TypeInfo {
|
||||
NONE,
|
||||
INT1,
|
||||
INT32,
|
||||
FLOAT64,
|
||||
TAGGED,
|
||||
};
|
||||
|
||||
class UseInfo {
|
||||
public:
|
||||
UseInfo(uint8_t tag) : tag_(tag) {}
|
||||
static constexpr uint8_t UNUSED = 0;
|
||||
static constexpr uint8_t BOOL = 1 << 0;
|
||||
static constexpr uint8_t INT32 = 1 << 1;
|
||||
static constexpr uint8_t FLOAT64 = 1 << 2;
|
||||
static constexpr uint8_t NATIVE = BOOL | INT32 | FLOAT64;
|
||||
static constexpr uint8_t TAGGED = 1 << 3;
|
||||
bool AddUse(const UseInfo &UseInfo)
|
||||
{
|
||||
uint8_t oldTag = tag_;
|
||||
tag_ |= UseInfo.tag_;
|
||||
return oldTag != tag_;
|
||||
}
|
||||
bool UsedAsBool() const
|
||||
{
|
||||
return ((tag_ & BOOL) == BOOL);
|
||||
}
|
||||
bool UsedAsFloat64() const
|
||||
{
|
||||
return ((tag_ & FLOAT64) == FLOAT64);
|
||||
}
|
||||
bool UsedAsNative() const
|
||||
{
|
||||
return ((tag_ & NATIVE) != 0);
|
||||
}
|
||||
bool UsedAsTagged() const
|
||||
{
|
||||
return ((tag_ & TAGGED) != 0);
|
||||
}
|
||||
static UseInfo UnUsed()
|
||||
{
|
||||
return UseInfo(UNUSED);
|
||||
}
|
||||
static UseInfo BoolUse()
|
||||
{
|
||||
return UseInfo(BOOL);
|
||||
}
|
||||
static UseInfo Int32Use()
|
||||
{
|
||||
return UseInfo(INT32);
|
||||
}
|
||||
static UseInfo Float64Use()
|
||||
{
|
||||
return UseInfo(FLOAT64);
|
||||
}
|
||||
static UseInfo TaggedUse()
|
||||
{
|
||||
return UseInfo(TAGGED);
|
||||
}
|
||||
private:
|
||||
uint8_t tag_ {0};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_GATE_INFO_H
|
293
ecmascript/compiler/number_speculative_lowering.cpp
Normal file
293
ecmascript/compiler/number_speculative_lowering.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/compiler/type_lowering.h"
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
#include "ecmascript/compiler/new_object_stub_builder.h"
|
||||
#include "ecmascript/compiler/number_speculative_lowering.h"
|
||||
#include "ecmascript/deoptimizer/deoptimizer.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
#include "ecmascript/js_locale.h"
|
||||
#include "ecmascript/js_native_pointer.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
|
||||
void NumberSpeculativeLowering::Run()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
acc_.GetAllGates(gateList);
|
||||
for (auto gate : gateList) {
|
||||
VisitGate(gate);
|
||||
}
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitGate(GateRef gate)
|
||||
{
|
||||
OpCode op = acc_.GetOpCode(gate);
|
||||
switch (op) {
|
||||
case OpCode::TYPED_BINARY_OP: {
|
||||
ASSERT(acc_.GetLeftType(gate).IsNumberType() && acc_.GetRightType(gate).IsNumberType());
|
||||
VisitNumberBinaryOp(gate);
|
||||
break;
|
||||
}
|
||||
case OpCode::VALUE_SELECTOR: {
|
||||
VisitPhi(gate);
|
||||
break;
|
||||
}
|
||||
case OpCode::CONSTANT: {
|
||||
VisitConstant(gate);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitNumberBinaryOp(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
TypedBinOp Op = acc_.GetTypedBinaryOp(gate);
|
||||
switch (Op) {
|
||||
case TypedBinOp::TYPED_ADD: {
|
||||
VisitNumberCalculate<TypedBinOp::TYPED_ADD>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_SUB: {
|
||||
VisitNumberCalculate<TypedBinOp::TYPED_SUB>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_MUL: {
|
||||
VisitNumberCalculate<TypedBinOp::TYPED_MUL>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_LESS: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_LESS>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_LESSEQ: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_LESSEQ>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_GREATER: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_GREATER>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_GREATEREQ: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_GREATEREQ>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_EQ: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_EQ>(gate);
|
||||
break;
|
||||
}
|
||||
case TypedBinOp::TYPED_NOTEQ: {
|
||||
VisitNumberCompare<TypedBinOp::TYPED_NOTEQ>(gate);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
void NumberSpeculativeLowering::VisitNumberCalculate(GateRef gate)
|
||||
{
|
||||
GateRef left = acc_.GetValueIn(gate, 0);
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (gateType.IsIntType()) {
|
||||
result = CalculateInts<Op>(left, right); // int op int
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
} else {
|
||||
result = CalculateDoubles<Op>(left, right); // float op float
|
||||
acc_.SetMachineType(gate, MachineType::F64);
|
||||
}
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
void NumberSpeculativeLowering::VisitNumberCompare(GateRef gate)
|
||||
{
|
||||
GateRef left = acc_.GetValueIn(gate, 0);
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateType leftType = acc_.GetLeftType(gate);
|
||||
GateType rightType = acc_.GetRightType(gate);
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (leftType.IsIntType() && rightType.IsIntType()) {
|
||||
result = CompareInts<Op>(left, right); // int op int
|
||||
} else {
|
||||
result = CompareDoubles<Op>(left, right); // float op float
|
||||
}
|
||||
acc_.SetMachineType(gate, MachineType::I1);
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitConstant(GateRef gate)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT32: {
|
||||
int value = acc_.GetInt32FromConstant(gate);
|
||||
acc_.UpdateAllUses(gate, builder_.Int32(value));
|
||||
break;
|
||||
}
|
||||
case TypeInfo::FLOAT64: {
|
||||
double value = acc_.GetFloat64FromConstant(gate);
|
||||
acc_.UpdateAllUses(gate, builder_.Double(value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitPhi(GateRef gate)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT1: {
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::I1);
|
||||
break;
|
||||
}
|
||||
case TypeInfo::INT32: {
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
break;
|
||||
}
|
||||
case TypeInfo::FLOAT64: {
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.SetMachineType(gate, MachineType::F64);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef NumberSpeculativeLowering::CalculateInts(GateRef left, GateRef right)
|
||||
{
|
||||
GateRef res = Circuit::NullGate();
|
||||
left = builder_.SExtInt32ToInt64(left);
|
||||
right = builder_.SExtInt32ToInt64(right);
|
||||
switch (Op) {
|
||||
case TypedBinOp::TYPED_ADD:
|
||||
res = builder_.Int64Add(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_SUB:
|
||||
res = builder_.Int64Sub(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_MUL:
|
||||
res = builder_.Int64Mul(left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// DeoptCheckForOverFlow
|
||||
GateRef max = builder_.Int64(INT32_MAX);
|
||||
GateRef min = builder_.Int64(INT32_MIN);
|
||||
GateRef notOverflow = builder_.Int64LessThanOrEqual(res, max);
|
||||
GateRef notUnderflow = builder_.Int64GreaterThanOrEqual(res, min);
|
||||
GateRef condition = builder_.BoolAnd(notOverflow, notUnderflow);
|
||||
builder_.DeoptCheck(condition, acc_.GetFrameState(builder_.GetDepend()), DeoptType::NOTINT);
|
||||
GateRef result = builder_.TruncInt64ToInt32(res);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef NumberSpeculativeLowering::CalculateDoubles(GateRef left, GateRef right)
|
||||
{
|
||||
GateRef res = Circuit::NullGate();
|
||||
switch (Op) {
|
||||
case TypedBinOp::TYPED_ADD:
|
||||
res = builder_.DoubleAdd(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_SUB:
|
||||
res = builder_.DoubleSub(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_MUL:
|
||||
res = builder_.DoubleMul(left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef NumberSpeculativeLowering::CompareInts(GateRef left, GateRef right)
|
||||
{
|
||||
GateRef condition = Circuit::NullGate();
|
||||
switch (Op) {
|
||||
case TypedBinOp::TYPED_LESS:
|
||||
condition = builder_.Int32LessThan(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_LESSEQ:
|
||||
condition = builder_.Int32LessThanOrEqual(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_GREATER:
|
||||
condition = builder_.Int32GreaterThan(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_GREATEREQ:
|
||||
condition = builder_.Int32GreaterThanOrEqual(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_EQ:
|
||||
condition = builder_.Int32Equal(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_NOTEQ:
|
||||
condition = builder_.Int32NotEqual(left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef NumberSpeculativeLowering::CompareDoubles(GateRef left, GateRef right)
|
||||
{
|
||||
GateRef condition = Circuit::NullGate();
|
||||
switch (Op) {
|
||||
case TypedBinOp::TYPED_LESS:
|
||||
condition = builder_.DoubleLessThan(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_LESSEQ:
|
||||
condition = builder_.DoubleLessThanOrEqual(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_GREATER:
|
||||
condition = builder_.DoubleGreaterThan(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_GREATEREQ:
|
||||
condition = builder_.DoubleGreaterThanOrEqual(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_EQ:
|
||||
condition = builder_.DoubleEqual(left, right);
|
||||
break;
|
||||
case TypedBinOp::TYPED_NOTEQ:
|
||||
condition = builder_.DoubleNotEqual(left, right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return condition;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
60
ecmascript/compiler/number_speculative_lowering.h
Normal file
60
ecmascript/compiler/number_speculative_lowering.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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_NUMBER_SPECULATIVE_LOWERING_H
|
||||
#define ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_LOWERING_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeLowering {
|
||||
public:
|
||||
NumberSpeculativeLowering(Circuit *circuit, ChunkVector<TypeInfo>& typeInfos)
|
||||
: circuit_(circuit), acc_(circuit), builder_(circuit), typeInfos_(typeInfos) {}
|
||||
void Run();
|
||||
|
||||
private:
|
||||
void VisitGate(GateRef gate);
|
||||
void VisitNumberBinaryOp(GateRef gate);
|
||||
void VisitConstant(GateRef gate);
|
||||
void VisitPhi(GateRef gate);
|
||||
|
||||
template<TypedBinOp Op>
|
||||
void VisitNumberCalculate(GateRef gate);
|
||||
template<TypedBinOp Op>
|
||||
void VisitNumberCompare(GateRef gate);
|
||||
|
||||
template<TypedBinOp Op>
|
||||
GateRef CalculateInts(GateRef left, GateRef right);
|
||||
template<TypedBinOp Op>
|
||||
GateRef CalculateDoubles(GateRef left, GateRef right);
|
||||
template<TypedBinOp Op>
|
||||
GateRef CompareInts(GateRef left, GateRef right);
|
||||
template<TypedBinOp Op>
|
||||
GateRef CompareDoubles(GateRef left, GateRef right);
|
||||
|
||||
Circuit* circuit_;
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
// ChunkVector<UseInfo>& useInfos_;
|
||||
ChunkVector<TypeInfo>& typeInfos_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_LOWERING_H
|
323
ecmascript/compiler/number_speculative_retype.cpp
Normal file
323
ecmascript/compiler/number_speculative_retype.cpp
Normal file
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/number_speculative_retype.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType pgoType)
|
||||
{
|
||||
TypeInfo& type = typeInfos_[acc_.GetId(gate)];
|
||||
TypeInfo old = type;
|
||||
if (pgoType.IsIntType()) {
|
||||
type = TypeInfo::INT32;
|
||||
} else if (pgoType.IsDoubleType()) {
|
||||
type = TypeInfo::FLOAT64;
|
||||
} else if (pgoType.IsBooleanType()) {
|
||||
type = TypeInfo::INT1;
|
||||
} else {
|
||||
type = TypeInfo::TAGGED;
|
||||
}
|
||||
return old == type ? Circuit::NullGate() : gate;
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
{
|
||||
OpCode op = acc_.GetOpCode(gate);
|
||||
switch (op) {
|
||||
case OpCode::TYPED_BINARY_OP:
|
||||
ASSERT(acc_.GetLeftType(gate).IsNumberType() && acc_.GetRightType(gate).IsNumberType());
|
||||
return VisitNumberBinaryOp(gate);
|
||||
case OpCode::TYPED_UNARY_OP:
|
||||
case OpCode::INDEX_CHECK:
|
||||
case OpCode::LOAD_ELEMENT:
|
||||
case OpCode::STORE_ELEMENT:
|
||||
return VisitNumberRelated(gate);
|
||||
case OpCode::VALUE_SELECTOR:
|
||||
return VisitPhi(gate);
|
||||
case OpCode::CONSTANT:
|
||||
return VisitConstant(gate);
|
||||
default:
|
||||
return VisitOthers(gate);
|
||||
}
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
if (acc_.IsConstantNumber(gate)) {
|
||||
return SetOutputType(gate, gateType);
|
||||
} else {
|
||||
return SetOutputType(gate, GateType::AnyType());
|
||||
}
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
|
||||
{
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
if (IsRetype()) {
|
||||
TypeInfo tempType = TypeInfo::NONE;
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
TypeInfo inputInfo = typeInfos_[acc_.GetId(input)];
|
||||
if (tempType == TypeInfo::NONE) {
|
||||
tempType = inputInfo;
|
||||
} else if ((tempType != inputInfo) && (inputInfo != TypeInfo::NONE)) {
|
||||
tempType = TypeInfo::TAGGED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TypeInfo& typeInfo = typeInfos_[acc_.GetId(gate)];
|
||||
if (typeInfo != tempType) {
|
||||
typeInfo = tempType;
|
||||
return gate;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsConvert()) {
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
if (output == TypeInfo::TAGGED) {
|
||||
return VisitOthers(gate);
|
||||
}
|
||||
}
|
||||
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
|
||||
{
|
||||
TypedBinOp op = acc_.GetTypedBinaryOp(gate);
|
||||
switch (op) {
|
||||
case TypedBinOp::TYPED_ADD:
|
||||
case TypedBinOp::TYPED_SUB:
|
||||
case TypedBinOp::TYPED_MUL: {
|
||||
return VisitNumberCalculate(gate);
|
||||
}
|
||||
case TypedBinOp::TYPED_LESS:
|
||||
case TypedBinOp::TYPED_LESSEQ:
|
||||
case TypedBinOp::TYPED_GREATER:
|
||||
case TypedBinOp::TYPED_GREATEREQ:
|
||||
case TypedBinOp::TYPED_EQ:
|
||||
case TypedBinOp::TYPED_NOTEQ: {
|
||||
return VisitNumberCompare(gate);
|
||||
}
|
||||
default:
|
||||
return VisitNumberRelated(gate);
|
||||
}
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
|
||||
{
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
if (IsRetype()) {
|
||||
GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
|
||||
return SetOutputType(gate, resType);
|
||||
} else if (IsConvert()) {
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
if (gateType.IsIntType()) {
|
||||
ConvertForIntOperator(gate);
|
||||
} else {
|
||||
ConvertForDoubleOperator(gate);
|
||||
}
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::BooleanType());
|
||||
}
|
||||
if (IsConvert()) {
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateType leftType = acc_.GetLeftType(gate);
|
||||
GateType rightType = acc_.GetRightType(gate);
|
||||
if (leftType.IsIntType() && rightType.IsIntType()) {
|
||||
ConvertForIntOperator(gate);
|
||||
} else {
|
||||
ConvertForDoubleOperator(gate);
|
||||
}
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate)
|
||||
{
|
||||
GateRef left = acc_.GetValueIn(gate, 0);
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateType leftType = acc_.GetLeftType(gate);
|
||||
GateType rightType = acc_.GetRightType(gate);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
|
||||
}
|
||||
|
||||
void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate)
|
||||
{
|
||||
GateRef left = acc_.GetValueIn(gate, 0);
|
||||
GateRef right = acc_.GetValueIn(gate, 1);
|
||||
GateType leftType = acc_.GetLeftType(gate);
|
||||
GateType rightType = acc_.GetRightType(gate);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::NumberType());
|
||||
}
|
||||
if (IsConvert()) {
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
GateType inputType = acc_.GetGateType(input);
|
||||
if (inputType.IsNumberType() || inputType.IsBooleanType()) {
|
||||
acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType), i);
|
||||
}
|
||||
}
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitOthers(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::AnyType());
|
||||
}
|
||||
if (IsConvert()) {
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
|
||||
}
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT32:
|
||||
return gate;
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToInt32(gate);
|
||||
case TypeInfo::TAGGED: {
|
||||
ASSERT(gateType.IsNumberType());
|
||||
if (gateType.IsIntType()) {
|
||||
return builder_.CheckTaggedIntAndConvertToInt32(gate);
|
||||
} else if (gateType.IsDoubleType()) {
|
||||
return builder_.CheckTaggedDoubleAndConvertToInt32(gate);
|
||||
} else {
|
||||
return builder_.CheckTaggedNumberAndConvertToInt32(gate);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToFloat64(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return gate;
|
||||
case TypeInfo::TAGGED: {
|
||||
ASSERT(gateType.IsNumberType());
|
||||
if (gateType.IsIntType()) {
|
||||
return builder_.CheckTaggedIntAndConvertToFloat64(gate);
|
||||
} else if (gateType.IsDoubleType()) {
|
||||
return builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
|
||||
} else {
|
||||
return builder_.CheckTaggedNumberAndConvertToFloat64(gate);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType gateType)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT1:
|
||||
return builder_.ConvertBoolToTaggedBoolean(gate);
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToTaggedInt(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToTaggedDouble(gate);
|
||||
case TypeInfo::TAGGED: {
|
||||
ASSERT(gateType.IsNumberType() || gateType.IsBooleanType());
|
||||
builder_.TryPrimitiveTypeCheck(gateType, gate);
|
||||
return gate;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
|
||||
{
|
||||
TypeInfo output = typeInfos_[acc_.GetId(gate)];
|
||||
switch (output) {
|
||||
case TypeInfo::INT1:
|
||||
return builder_.ConvertBoolToTaggedBoolean(gate);
|
||||
case TypeInfo::INT32:
|
||||
return builder_.ConvertInt32ToTaggedInt(gate);
|
||||
case TypeInfo::FLOAT64:
|
||||
return builder_.ConvertFloat64ToTaggedDouble(gate);
|
||||
case TypeInfo::TAGGED: {
|
||||
return gate;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
}
|
||||
|
||||
void NumberSpeculativeRetype::Run()
|
||||
{
|
||||
// visit gate in RPO, propagate use infos and
|
||||
// reset the machine type of number operator gate and related phi,
|
||||
// if some tagged phi is used as native value, change it to native phi.
|
||||
state_ = State::Retype;
|
||||
VisitGraph();
|
||||
state_ = State::Convert;
|
||||
VisitGraph();
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript::kungfu
|
73
ecmascript/compiler/number_speculative_retype.h
Normal file
73
ecmascript/compiler/number_speculative_retype.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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_NUMBER_SPECULATIVE_RETYPE_H
|
||||
#define ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_RETYPE_H
|
||||
|
||||
#include "ecmascript/compiler/circuit_builder.h"
|
||||
#include "ecmascript/compiler/gate_accessor.h"
|
||||
#include "ecmascript/compiler/gate_meta_data.h"
|
||||
#include "ecmascript/compiler/graph_visitor.h"
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/type.h"
|
||||
#include "ecmascript/mem/chunk_containers.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRetype : public GraphVisitor {
|
||||
public:
|
||||
NumberSpeculativeRetype(Circuit *circuit, Chunk* chunk, ChunkVector<TypeInfo>& typeInfos)
|
||||
: GraphVisitor(circuit, chunk), acc_(circuit), builder_(circuit), typeInfos_(typeInfos) {}
|
||||
void Run();
|
||||
GateRef VisitGate(GateRef gate);
|
||||
|
||||
private:
|
||||
enum class State {
|
||||
Retype,
|
||||
Convert,
|
||||
};
|
||||
|
||||
bool IsRetype() const
|
||||
{
|
||||
return state_ == State::Retype;
|
||||
}
|
||||
|
||||
bool IsConvert() const
|
||||
{
|
||||
return state_ == State::Convert;
|
||||
}
|
||||
|
||||
GateRef SetOutputType(GateRef gate, GateType type);
|
||||
GateRef VisitPhi(GateRef gate);
|
||||
GateRef VisitConstant(GateRef gate);
|
||||
GateRef VisitNumberBinaryOp(GateRef gate);
|
||||
GateRef VisitNumberCalculate(GateRef gate);
|
||||
GateRef VisitNumberCompare(GateRef gate);
|
||||
void ConvertForIntOperator(GateRef gate);
|
||||
void ConvertForDoubleOperator(GateRef gate);
|
||||
GateRef VisitNumberRelated(GateRef gate);
|
||||
GateRef VisitOthers(GateRef gate);
|
||||
|
||||
GateRef CheckAndConvertToInt32(GateRef gate, GateType gateType);
|
||||
GateRef CheckAndConvertToFloat64(GateRef gate, GateType gateType);
|
||||
GateRef CheckAndConvertToTagged(GateRef gate, GateType gateType);
|
||||
GateRef ConvertToTagged(GateRef gate);
|
||||
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
ChunkVector<TypeInfo>& typeInfos_;
|
||||
State state_ {0};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_RETYPE_H
|
53
ecmascript/compiler/number_speculative_runner.cpp
Normal file
53
ecmascript/compiler/number_speculative_runner.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/number_speculative_runner.h"
|
||||
#include "ecmascript/compiler/number_gate_info.h"
|
||||
#include "ecmascript/compiler/number_speculative_lowering.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void NumberSpeculativeRunner::Run()
|
||||
{
|
||||
auto maxId = circuit_->GetMaxGateId();
|
||||
typeInfos_.resize(maxId + 1, TypeInfo::TAGGED);
|
||||
NumberSpeculativeRetype retype(circuit_, chunk_, typeInfos_);
|
||||
retype.Run();
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
<< "===================="
|
||||
<< " After number speculative retype "
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
circuit_->PrintAllGatesWithBytecode();
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
||||
}
|
||||
NumberSpeculativeLowering lowering(circuit_, typeInfos_);
|
||||
lowering.Run();
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
<< "===================="
|
||||
<< " After number speculative runner "
|
||||
<< "[" << GetMethodName() << "]"
|
||||
<< "===================="
|
||||
<< "\033[0m";
|
||||
circuit_->PrintAllGatesWithBytecode();
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
|
||||
}
|
||||
}
|
||||
} // panda::ecmascript::kungfu
|
50
ecmascript/compiler/number_speculative_runner.h
Normal file
50
ecmascript/compiler/number_speculative_runner.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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_NUMBER_SPECULATIVE_RUNNER_H
|
||||
#define ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_RUNNER_H
|
||||
|
||||
#include "ecmascript/compiler/number_speculative_lowering.h"
|
||||
#include "ecmascript/compiler/number_speculative_retype.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class NumberSpeculativeRunner {
|
||||
public:
|
||||
NumberSpeculativeRunner(Circuit *circuit, bool enableLog, const std::string& name, Chunk* chunk)
|
||||
: circuit_(circuit), acc_(circuit), enableLog_(enableLog),
|
||||
methodName_(name), chunk_(chunk), typeInfos_(chunk) {}
|
||||
|
||||
~NumberSpeculativeRunner() = default;
|
||||
void Run();
|
||||
private:
|
||||
bool IsLogEnabled() const
|
||||
{
|
||||
return enableLog_;
|
||||
}
|
||||
|
||||
const std::string& GetMethodName() const
|
||||
{
|
||||
return methodName_;
|
||||
}
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
bool enableLog_ {false};
|
||||
std::string methodName_;
|
||||
Chunk *chunk_ {nullptr};
|
||||
ChunkVector<TypeInfo> typeInfos_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_NUMBER_SPECULATIVE_RUNNER_H
|
@ -22,6 +22,7 @@
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/compiler/compiler_log.h"
|
||||
#include "ecmascript/compiler/llvm_codegen.h"
|
||||
#include "ecmascript/compiler/number_speculative_runner.h"
|
||||
#include "ecmascript/compiler/scheduler.h"
|
||||
#include "ecmascript/compiler/slowpath_lowering.h"
|
||||
#include "ecmascript/compiler/ts_inline_lowering.h"
|
||||
@ -274,6 +275,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class NumberSpeculativePass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
{
|
||||
TimeScope timescope("NumberSpeculativePass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
Chunk chunk(data->GetNativeAreaAllocator());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog();
|
||||
NumberSpeculativeRunner(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk).Run();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class EarlyEliminationPass {
|
||||
public:
|
||||
bool Run(PassData* data)
|
||||
|
@ -116,6 +116,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
if (EnableTypeLowering()) {
|
||||
pipeline.RunPass<TSTypeLoweringPass>();
|
||||
pipeline.RunPass<EarlyEliminationPass>();
|
||||
pipeline.RunPass<NumberSpeculativePass>();
|
||||
pipeline.RunPass<TypeLoweringPass>();
|
||||
}
|
||||
pipeline.RunPass<SlowPathLoweringPass>();
|
||||
|
@ -41,6 +41,7 @@ void SlowPathLowering::CallRuntimeLowering()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
circuit_->GetAllGates(gateList);
|
||||
|
||||
for (const auto &gate : gateList) {
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op == OpCode::JS_BYTECODE) {
|
||||
@ -59,6 +60,8 @@ void SlowPathLowering::CallRuntimeLowering()
|
||||
LowerTypedAotCall(gate);
|
||||
} else if (op == OpCode::UPDATE_HOTNESS) {
|
||||
LowerUpdateHotness(gate);
|
||||
} else if (op == OpCode::STATE_SPLIT) {
|
||||
DeleteStateSplit(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +76,12 @@ void SlowPathLowering::CallRuntimeLowering()
|
||||
}
|
||||
}
|
||||
|
||||
void SlowPathLowering::DeleteStateSplit(GateRef gate)
|
||||
{
|
||||
auto depend = acc_.GetDep(gate);
|
||||
acc_.ReplaceGate(gate, Circuit::NullGate(), depend, Circuit::NullGate());
|
||||
}
|
||||
|
||||
void SlowPathLowering::LowerToJSCall(GateRef hirGate, const std::vector<GateRef> &args)
|
||||
{
|
||||
GateRef stateInGate = builder_.GetState();
|
||||
|
@ -298,6 +298,7 @@ private:
|
||||
void LowerTypedAotCall(GateRef gate);
|
||||
void LowerUpdateHotness(GateRef gate);
|
||||
void LowerNotifyConcurrentResult(GateRef gate);
|
||||
void DeleteStateSplit(GateRef gate);
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const MethodLiteral *methodLiteral_ {nullptr};
|
||||
|
@ -32,8 +32,6 @@ void TSTypeLowering::RunTSTypeLowering()
|
||||
}
|
||||
}
|
||||
|
||||
VerifyGuard();
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
LOG_COMPILER(INFO) << "";
|
||||
LOG_COMPILER(INFO) << "\033[34m"
|
||||
@ -512,8 +510,6 @@ void TSTypeLowering::SpeculateNumbers(GateRef gate)
|
||||
GateType leftType = acc_.GetGateType(left);
|
||||
GateType rightType = acc_.GetGateType(right);
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
builder_.TryPrimitiveTypeCheck(leftType, left);
|
||||
builder_.TryPrimitiveTypeCheck(rightType, right);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType);
|
||||
@ -536,7 +532,6 @@ void TSTypeLowering::SpeculateNumber(GateRef gate)
|
||||
GateType valueType = acc_.GetGateType(value);
|
||||
GateType gateType = acc_.GetGateType(gate);
|
||||
|
||||
builder_.TryPrimitiveTypeCheck(valueType, value);
|
||||
if (valueType.IsIntType() && NeedInt32OverflowCheck(Op)) {
|
||||
builder_.Int32OverflowCheck<Op>(value);
|
||||
}
|
||||
@ -563,7 +558,6 @@ void TSTypeLowering::LowerPrimitiveTypeToNumber(GateRef gate)
|
||||
{
|
||||
GateRef src = acc_.GetValueIn(gate, 0);
|
||||
GateType srcType = acc_.GetGateType(src);
|
||||
builder_.TryPrimitiveTypeCheck(srcType, src);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
GateRef result = builder_.PrimitiveToNumber(src, VariableType(MachineType::I64, srcType));
|
||||
@ -789,7 +783,6 @@ void TSTypeLowering::LowerTypedStObjByIndex(GateRef gate)
|
||||
}
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
builder_.IndexCheck(receiverType, receiver, index);
|
||||
builder_.TryPrimitiveTypeCheck(valueType, value);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
if (tsManager_->IsFloat32ArrayType(receiverType)) {
|
||||
@ -826,10 +819,8 @@ void TSTypeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
|
||||
|
||||
AddProfiling(gate);
|
||||
|
||||
builder_.TryPrimitiveTypeCheck(GateType::IntType(), propKey);
|
||||
builder_.StableArrayCheck(receiver);
|
||||
builder_.IndexCheck(receiverType, receiver, propKey);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
GateRef result = builder_.LoadElement<TypedLoadOp::ARRAY_LOAD_ELEMENT>(receiver, propKey);
|
||||
|
||||
@ -848,8 +839,6 @@ void TSTypeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag)
|
||||
|
||||
AddProfiling(gate);
|
||||
|
||||
builder_.TryPrimitiveTypeCheck(valueType, value);
|
||||
|
||||
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
|
||||
|
||||
GateRef result;
|
||||
|
@ -202,6 +202,11 @@ public:
|
||||
return (m == 0) && (l == static_cast<uint32_t>(TSPrimitiveType::BIG_INT));
|
||||
}
|
||||
|
||||
bool IsNJSValueType() const
|
||||
{
|
||||
return type_ == NJS_VALUE;
|
||||
}
|
||||
|
||||
bool IsDigitablePrimitiveType() const
|
||||
{
|
||||
return IsNumberType() || IsNullType() || IsUndefinedType() || IsBooleanType() || IsBigIntType();
|
||||
@ -269,6 +274,16 @@ private:
|
||||
uint32_t type_ {0};
|
||||
};
|
||||
|
||||
enum class ValueType : uint8_t {
|
||||
BOOL,
|
||||
INT32,
|
||||
FLOAT64,
|
||||
TAGGED_BOOLEAN,
|
||||
TAGGED_INT,
|
||||
TAGGED_DOUBLE,
|
||||
TAGGED_NUMBER,
|
||||
};
|
||||
|
||||
class Type {
|
||||
public:
|
||||
explicit Type(GateType payload);
|
||||
|
@ -118,6 +118,12 @@ void TypeLowering::LowerType(GateRef gate)
|
||||
case OpCode::GET_SUPER_CONSTRUCTOR:
|
||||
LowerGetSuperConstructor(gate);
|
||||
break;
|
||||
case OpCode::CONVERT:
|
||||
LowerConvert(gate);
|
||||
break;
|
||||
case OpCode::CHECK_AND_CONVERT:
|
||||
LowerCheckAndConvert(gate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -640,7 +646,29 @@ void TypeLowering::LowerArrayLoadElement(GateRef gate)
|
||||
GateRef element =
|
||||
builder_.Load(VariableType::JS_POINTER(), receiver, builder_.IntPtr(JSObject::ELEMENTS_OFFSET));
|
||||
GateRef index = acc_.GetValueIn(gate, 1);
|
||||
index = builder_.GetInt32OfTInt(index);
|
||||
GateType indexType = acc_.GetGateType(gate);
|
||||
|
||||
Label midMerge(&builder_);
|
||||
if (indexType.IsIntType()) {
|
||||
index = builder_.GetInt32OfTInt(index);
|
||||
} else if (indexType.IsDoubleType()) {
|
||||
index = builder_.TruncFloatToInt32(builder_.GetDoubleOfTDouble(index));
|
||||
} else {
|
||||
// is number and need typecheck in runtime.
|
||||
DEFVAlUE(idx, (&builder_), VariableType::INT32(), builder_.Int32(0));
|
||||
Label isInt(&builder_);
|
||||
Label isDouble(&builder_);
|
||||
builder_.Branch(builder_.TaggedIsInt(index), &isInt, &isDouble);
|
||||
builder_.Bind(&isInt);
|
||||
idx = builder_.GetInt32OfTInt(index);
|
||||
builder_.Jump(&midMerge);
|
||||
builder_.Bind(&isDouble);
|
||||
idx = builder_.TruncFloatToInt32(builder_.GetDoubleOfTDouble(index));
|
||||
builder_.Jump(&midMerge);
|
||||
builder_.Bind(&midMerge);
|
||||
index = *idx;
|
||||
}
|
||||
|
||||
GateRef res = builder_.GetValueFromTaggedArray(element, index);
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), res);
|
||||
Label isHole(&builder_);
|
||||
@ -3149,4 +3177,179 @@ void TypeLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue,
|
||||
StateDepend exception(ifTrue, eDepend);
|
||||
acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerConvert(GateRef gate)
|
||||
{
|
||||
GateRef value = acc_.GetValueIn(gate);
|
||||
ValueType srcType = acc_.GetSrcType(gate);
|
||||
ValueType dstType = acc_.GetDstType(gate);
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (srcType == ValueType::BOOL) {
|
||||
ASSERT(dstType == ValueType::TAGGED_BOOLEAN);
|
||||
result = ConvertBoolToTaggedBoolean(value);
|
||||
} else if (srcType == ValueType::INT32) {
|
||||
ASSERT(dstType == ValueType::TAGGED_INT || dstType == ValueType::FLOAT64);
|
||||
if (dstType == ValueType::TAGGED_INT) {
|
||||
result = ConvertInt32ToTaggedInt(value);
|
||||
} else {
|
||||
result = ConvertInt32ToFloat64(value);
|
||||
}
|
||||
} else if (srcType == ValueType::FLOAT64) {
|
||||
ASSERT(dstType == ValueType::TAGGED_DOUBLE || dstType == ValueType::INT32);
|
||||
if (dstType == ValueType::TAGGED_DOUBLE) {
|
||||
result = ConvertFloat64ToTaggedDouble(value);
|
||||
} else {
|
||||
result = ConvertFloat64ToInt32(value);
|
||||
}
|
||||
}
|
||||
acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), result);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit)
|
||||
{
|
||||
DEFVAlUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0));
|
||||
Label isInt(&builder_);
|
||||
Label isDouble(&builder_);
|
||||
builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
|
||||
builder_.Bind(&isInt);
|
||||
result = ConvertTaggedIntToInt32(gate);
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(&isDouble);
|
||||
result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate));
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(exit);
|
||||
return *result;
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)
|
||||
{
|
||||
DEFVAlUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
|
||||
Label isInt(&builder_);
|
||||
Label isDouble(&builder_);
|
||||
builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
|
||||
builder_.Bind(&isInt);
|
||||
result = ConvertInt32ToFloat64(ConvertTaggedIntToInt32(gate));
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(&isDouble);
|
||||
result = ConvertTaggedDoubleToFloat64(gate);
|
||||
builder_.Jump(exit);
|
||||
builder_.Bind(exit);
|
||||
return *result;
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCheckAndConvert(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
ValueType srcType = acc_.GetSrcType(gate);
|
||||
switch (srcType) {
|
||||
case ValueType::TAGGED_INT:
|
||||
LowerCheckTaggedIntAndConvert(gate);
|
||||
break;
|
||||
case ValueType::TAGGED_DOUBLE:
|
||||
LowerCheckTaggedDoubleAndConvert(gate);
|
||||
break;
|
||||
case ValueType::TAGGED_NUMBER:
|
||||
LowerCheckTaggedNumberAndConvert(gate);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCheckTaggedIntAndConvert(GateRef gate)
|
||||
{
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
GateRef typeCheck = builder_.TaggedIsInt(value);
|
||||
builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT);
|
||||
GateRef result = Circuit::NullGate();
|
||||
ValueType dst = acc_.GetDstType(gate);
|
||||
ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
|
||||
if (dst == ValueType::INT32) {
|
||||
result = ConvertTaggedIntToInt32(value);
|
||||
} else {
|
||||
result = ConvertTaggedIntToFloat64(value);
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate)
|
||||
{
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
GateRef typeCheck = builder_.TaggedIsDouble(value);
|
||||
builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE);
|
||||
GateRef result = Circuit::NullGate();
|
||||
ValueType dst = acc_.GetDstType(gate);
|
||||
ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
|
||||
if (dst == ValueType::INT32) {
|
||||
result = ConvertTaggedDoubleToInt32(value);
|
||||
} else {
|
||||
result = ConvertTaggedDoubleToFloat64(value);
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCheckTaggedNumberAndConvert(GateRef gate)
|
||||
{
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
GateRef value = acc_.GetValueIn(gate, 0);
|
||||
GateRef typeCheck = builder_.TaggedIsNumber(value);
|
||||
builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER);
|
||||
GateRef result = Circuit::NullGate();
|
||||
ValueType dst = acc_.GetDstType(gate);
|
||||
ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
|
||||
Label exit(&builder_);
|
||||
if (dst == ValueType::INT32) {
|
||||
result = ConvertTaggedNumberToInt32(value, &exit);
|
||||
} else {
|
||||
result = ConvertTaggedNumberToFloat64(value, &exit);
|
||||
}
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertBoolToTaggedBoolean(GateRef gate)
|
||||
{
|
||||
return builder_.BooleanToTaggedBooleanPtr(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertInt32ToFloat64(GateRef gate)
|
||||
{
|
||||
return builder_.ChangeInt32ToFloat64(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertInt32ToTaggedInt(GateRef gate)
|
||||
{
|
||||
return builder_.Int32ToTaggedPtr(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertFloat64ToInt32(GateRef gate)
|
||||
{
|
||||
return builder_.ChangeFloat64ToInt32(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertFloat64ToTaggedDouble(GateRef gate)
|
||||
{
|
||||
return builder_.DoubleToTaggedDoublePtr(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedIntToInt32(GateRef gate)
|
||||
{
|
||||
return builder_.GetInt32OfTInt(gate);
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedIntToFloat64(GateRef gate)
|
||||
{
|
||||
return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate));
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedDoubleToInt32(GateRef gate)
|
||||
{
|
||||
return builder_.ChangeFloat64ToInt32(builder_.GetDoubleOfTDouble(gate));
|
||||
}
|
||||
|
||||
GateRef TypeLowering::ConvertTaggedDoubleToFloat64(GateRef gate)
|
||||
{
|
||||
return builder_.GetDoubleOfTDouble(gate);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -253,6 +253,24 @@ private:
|
||||
GateRef GetObjectFromConstPool(GateRef jsFunc, GateRef index);
|
||||
GateRef ConvertNumberToBool(GateRef gate, GateType valueType);
|
||||
GateRef ConvertBooleanToBool(GateRef gate);
|
||||
|
||||
void LowerConvert(GateRef gate);
|
||||
void LowerCheckAndConvert(GateRef gate);
|
||||
void LowerCheckTaggedIntAndConvert(GateRef gate);
|
||||
void LowerCheckTaggedDoubleAndConvert(GateRef gate);
|
||||
void LowerCheckTaggedNumberAndConvert(GateRef gate);
|
||||
GateRef ConvertBoolToTaggedBoolean(GateRef gate);
|
||||
GateRef ConvertInt32ToFloat64(GateRef gate);
|
||||
GateRef ConvertInt32ToTaggedInt(GateRef gate);
|
||||
GateRef ConvertFloat64ToInt32(GateRef gate);
|
||||
GateRef ConvertFloat64ToTaggedDouble(GateRef gate);
|
||||
GateRef ConvertTaggedIntToInt32(GateRef gate);
|
||||
GateRef ConvertTaggedIntToFloat64(GateRef gate);
|
||||
GateRef ConvertTaggedDoubleToInt32(GateRef gate);
|
||||
GateRef ConvertTaggedDoubleToFloat64(GateRef gate);
|
||||
GateRef ConvertTaggedNumberToInt32(GateRef gate, Label *exit);
|
||||
GateRef ConvertTaggedNumberToFloat64(GateRef gate, Label *exit);
|
||||
|
||||
GateRef GetFrameState(GateRef gate) const
|
||||
{
|
||||
return acc_.GetFrameState(gate);
|
||||
|
Loading…
Reference in New Issue
Block a user