Add MIR for LdLexVar and StLexVar

Issues: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I7M1VF

Signed-off-by: sunzhe23 <sunzhe23@huawei.com>
This commit is contained in:
sunzhe23 2023-07-17 20:37:44 +08:00
parent 90ddc0b915
commit bd9b7009a5
15 changed files with 170 additions and 31 deletions

View File

@ -983,6 +983,18 @@ GateRef CircuitBuilder::LogicOr(GateRef x, GateRef y)
return ret;
}
GateRef CircuitBuilder::LoadFromTaggedArray(GateRef array, size_t index)
{
auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
return LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
}
GateRef CircuitBuilder::StoreToTaggedArray(GateRef array, size_t index, GateRef value)
{
auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
return StoreConstOffset(VariableType::JS_ANY(), array, dataOffset, value);
}
int CircuitBuilder::NextVariableId()
{
return env_->NextVariableId();

View File

@ -615,6 +615,19 @@ GateRef CircuitBuilder::Float64CheckRightIsZero(GateRef right)
return ret;
}
GateRef CircuitBuilder::LexVarIsHoleCheck(GateRef value)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->LexVarIsHoleCheck(),
MachineType::I1, {currentControl, currentDepend, value, frameState}, GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::ValueCheckNegOverflow(GateRef value)
{
auto currentLabel = env_->GetCurrentLabel();

View File

@ -277,6 +277,7 @@ public:
GateRef NegativeIndexCheck(GateRef index);
GateRef LargeIndexCheck(GateRef index, GateRef length);
GateRef OverflowCheck(GateRef value);
GateRef LexVarIsHoleCheck(GateRef value);
GateRef Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound);
GateRef Int32DivWithCheck(GateRef left, GateRef right);
MachineType GetMachineTypeOfValueType(ValueType type);
@ -646,6 +647,8 @@ public:
GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index);
GateRef IsBase(GateRef ctor);
inline GateRef GetMethodId(GateRef func);
inline GateRef LoadFromTaggedArray(GateRef array, size_t index);
inline GateRef StoreToTaggedArray(GateRef array, size_t index, GateRef value);
private:
#define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \

View File

@ -242,26 +242,34 @@ DependInfoNode* EarlyElimination::UpdateWrite(GateRef gate, DependInfoNode* depe
bool EarlyElimination::MayAccessOneMemory(GateRef lhs, GateRef rhs)
{
if (acc_.GetOpCode(rhs) == OpCode::STORE_ELEMENT) {
return acc_.GetOpCode(lhs) == OpCode::LOAD_ELEMENT;
}
auto rop = acc_.GetOpCode(rhs);
auto lop = acc_.GetOpCode(lhs);
ASSERT(acc_.GetOpCode(rhs) == OpCode::STORE_PROPERTY ||
acc_.GetOpCode(rhs) == OpCode::STORE_PROPERTY_NO_BARRIER ||
acc_.GetOpCode(rhs) == OpCode::STORE_CONST_OFFSET);
if (lop == OpCode::LOAD_PROPERTY) {
auto loff = acc_.GetValueIn(lhs, 1);
auto roff = acc_.GetValueIn(rhs, 1);
ASSERT(acc_.GetOpCode(loff) == OpCode::CONSTANT);
ASSERT(acc_.GetOpCode(roff) == OpCode::CONSTANT);
return loff == roff;
} else if (lop == OpCode::LOAD_CONST_OFFSET) {
auto loff = acc_.GetOffset(lhs);
auto roff = acc_.GetOffset(rhs);
return loff == roff;
} else {
return false;
switch (rop) {
case OpCode::STORE_ELEMENT:
return lop == OpCode::LOAD_ELEMENT;
case OpCode::STORE_PROPERTY:
case OpCode::STORE_PROPERTY_NO_BARRIER: {
if (lop == OpCode::LOAD_PROPERTY) {
auto loff = acc_.GetValueIn(lhs, 1);
auto roff = acc_.GetValueIn(rhs, 1);
ASSERT(acc_.GetOpCode(loff) == OpCode::CONSTANT);
ASSERT(acc_.GetOpCode(roff) == OpCode::CONSTANT);
return loff == roff;
}
break;
}
case OpCode::STORE_CONST_OFFSET: {
if (lop == OpCode::LOAD_CONST_OFFSET) {
auto loff = acc_.GetOffset(lhs);
auto roff = acc_.GetOffset(rhs);
return loff == roff;
}
break;
}
default:
break;
}
return false;
}
bool EarlyElimination::CompareOrder(GateRef lhs, GateRef rhs)

View File

@ -100,6 +100,7 @@ enum class TypedJumpOp : uint8_t {
V(LargeIndex, LARGEINDEX) \
V(InlineFail, INLINEFAIL) \
V(NotJSFastCallTarget, NOTJSFASTCALLTGT) \
V(LexVarIsHole, LEXVARISHOLE) \
V(ModZero, MODZERO)
enum class DeoptType : uint8_t {
@ -198,7 +199,8 @@ std::string MachineTypeToStr(MachineType machineType);
V(LargeIndexCheck, LARGE_INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(OverflowCheck, OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(Int32UnsignedUpperBoundCheck, INT32_UNSIGNED_UPPER_BOUND_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2)
V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1)
#define UNARY_GATE_META_DATA_CACHE_LIST(V) \
V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1) \

View File

@ -52,6 +52,15 @@ GateRef LaterElimination::VisitGate(GateRef gate)
case OpCode::ARRAY_GUARDIAN_CHECK:
case OpCode::HCLASS_STABLE_ARRAY_CHECK:
case OpCode::HEAP_OBJECT_CHECK:
case OpCode::INT32_UNSIGNED_UPPER_BOUND_CHECK:
case OpCode::OVERFLOW_CHECK:
case OpCode::LARGE_INDEX_CHECK:
case OpCode::NEGATIVE_INDEX_CHECK:
case OpCode::VALUE_CHECK_NEG_OVERFLOW:
case OpCode::FLOAT64_CHECK_RIGHT_IS_ZERO:
case OpCode::INT32_CHECK_RIGHT_IS_ZERO:
case OpCode::INT32_DIV_WITH_CHECK:
case OpCode::LEX_VAR_IS_HOLE_CHECK:
return TryEliminateGate(gate);
case OpCode::DEPEND_SELECTOR:
return TryEliminateDependSelector(gate);

View File

@ -86,6 +86,9 @@ void LCRLowering::Run()
case OpCode::INT32_DIV_WITH_CHECK:
LowerInt32DivWithCheck(gate);
break;
case OpCode::LEX_VAR_IS_HOLE_CHECK:
LowerLexVarIsHoleCheck(gate);
break;
default:
break;
}
@ -568,6 +571,16 @@ void LCRLowering::LowerFloat64CheckRightIsZero(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void LCRLowering::LowerLexVarIsHoleCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = acc_.GetFrameState(gate);
GateRef value = acc_.GetValueIn(gate, 0);
GateRef valueIsNotHole = builder_.TaggedIsNotHole(value);
builder_.DeoptCheck(valueIsNotHole, frameState, DeoptType::LEXVARISHOLE);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void LCRLowering::LowerValueCheckNegOverflow(GateRef gate)
{
Environment env(gate, circuit_, &builder_);

View File

@ -69,6 +69,7 @@ private:
void LowerOverflowCheck(GateRef gate);
void LowerInt32UnsignedUpperBoundCheck(GateRef gate);
void LowerInt32DivWithCheck(GateRef gate);
void LowerLexVarIsHoleCheck(GateRef gate);
GateRef ConvertBoolToTaggedBoolean(GateRef gate);
GateRef ConvertInt32ToFloat64(GateRef gate);

View File

@ -14,6 +14,7 @@
*/
#include "ecmascript/compiler/ntype_hcr_lowering.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
namespace panda::ecmascript::kungfu {
@ -60,11 +61,79 @@ void NTypeHCRLowering::Lower(GateRef gate)
case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8:
LowerTypedStOwnByName(gate);
break;
case EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16:
LowerThrowUndefinedIfHoleWithName(gate);
break;
case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
LowerLdLexVar(gate);
break;
case EcmaOpcode::STLEXVAR_IMM4_IMM4:
case EcmaOpcode::STLEXVAR_IMM8_IMM8:
case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
LowerStLexVar(gate);
break;
default:
break;
}
}
void NTypeHCRLowering::LowerThrowUndefinedIfHoleWithName(GateRef gate)
{
GateRef value = acc_.GetValueIn(gate, 1); // 1: the second parameter
builder_.LexVarIsHoleCheck(value);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
}
void NTypeHCRLowering::LowerLdLexVar(GateRef gate)
{
AddProfiling(gate);
GateRef level = acc_.GetValueIn(gate, 0); // 0: first parameter
GateRef index = acc_.GetValueIn(gate, 1); // 1: the second parameter
GateRef currentEnv = acc_.GetValueIn(gate, 2); // 2: the third parameter
uint32_t levelValue = static_cast<uint32_t>(acc_.GetConstantValue(level));
uint32_t indexValue = static_cast<uint32_t>(acc_.GetConstantValue(index));
indexValue += LexicalEnv::RESERVED_ENV_LENGTH;
GateRef result = Circuit::NullGate();
if (levelValue == 0) {
result = builder_.LoadFromTaggedArray(currentEnv, indexValue);
} else if (levelValue == 1) { // 1: level 1
auto parentEnv = builder_.LoadFromTaggedArray(currentEnv, LexicalEnv::PARENT_ENV_INDEX);
result = builder_.LoadFromTaggedArray(parentEnv, indexValue);
} else {
// level > 1, go slowpath
return;
}
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void NTypeHCRLowering::LowerStLexVar(GateRef gate)
{
AddProfiling(gate);
GateRef level = acc_.GetValueIn(gate, 0); // 0: first parameter
GateRef index = acc_.GetValueIn(gate, 1); // 1: the second parameter
GateRef currentEnv = acc_.GetValueIn(gate, 2); // 2: the third parameter
GateRef value = acc_.GetValueIn(gate, 3); // 3: the fourth parameter
uint32_t levelValue = static_cast<uint32_t>(acc_.GetConstantValue(level));
uint32_t indexValue = static_cast<uint32_t>(acc_.GetConstantValue(index));
indexValue += LexicalEnv::RESERVED_ENV_LENGTH;
GateRef result = Circuit::NullGate();
if (levelValue == 0) {
result = builder_.StoreToTaggedArray(currentEnv, indexValue, value);
} else if (levelValue == 1) { // 1: level 1
auto parentEnv = builder_.LoadFromTaggedArray(currentEnv, LexicalEnv::PARENT_ENV_INDEX);
result = builder_.StoreToTaggedArray(parentEnv, indexValue, value);
} else {
// level > 1, go slowpath
return;
}
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void NTypeHCRLowering::LowerTypedCreateEmptyArray(GateRef gate)
{
// in the future, the type of the elements in the array will be obtained through pgo,

View File

@ -45,6 +45,9 @@ private:
void LowerTypedCreateEmptyArray(GateRef gate);
void LowerTypedStownByIndex(GateRef gate);
void LowerTypedStOwnByName(GateRef gate);
void LowerLdLexVar(GateRef gate);
void LowerStLexVar(GateRef gate);
void LowerThrowUndefinedIfHoleWithName(GateRef gate);
bool IsLogEnabled() const
{

View File

@ -46,6 +46,8 @@ private:
void LowerCreateArray(GateRef gate, GateRef glue);
void LowerCreateEmptyArray(GateRef gate);
void LowerCreateArrayWithOwn(GateRef gate, GateRef glue);
void LowerStLexVar(GateRef gate);
void LowerLdLexVar(GateRef gate);
GateRef NewTaggedArray(size_t length);
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,

View File

@ -126,6 +126,9 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
case OpCode::FRAME_ARGS:
case OpCode::SAVE_REGISTER:
case OpCode::RESTORE_REGISTER:
case OpCode::LOAD_CONST_OFFSET:
case OpCode::STORE_CONST_OFFSET:
case OpCode::LEX_VAR_IS_HOLE_CHECK:
return VisitOthers(gate);
default:
return Circuit::NullGate();

View File

@ -442,7 +442,7 @@ void TypeMCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType
GateRef TypeMCRLowering::LoadFromConstPool(GateRef jsFunc, size_t index)
{
GateRef constPool = builder_.GetConstPool(jsFunc);
return LoadFromTaggedArray(constPool, index);
return builder_.LoadFromTaggedArray(constPool, index);
}
GateRef TypeMCRLowering::GetObjectFromConstPool(GateRef jsFunc, GateRef index)
@ -1072,12 +1072,6 @@ void TypeMCRLowering::LowerGetSuperConstructor(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
}
GateRef TypeMCRLowering::LoadFromTaggedArray(GateRef array, size_t index)
{
auto dataOffset = TaggedArray::DATA_OFFSET + index * JSTaggedValue::TaggedTypeSize();
return builder_.LoadConstOffset(VariableType::JS_ANY(), array, dataOffset);
}
GateRef TypeMCRLowering::LoadFromVTable(GateRef receiver, size_t index)
{
GateRef hclass = builder_.LoadConstOffset(
@ -1085,8 +1079,8 @@ GateRef TypeMCRLowering::LoadFromVTable(GateRef receiver, size_t index)
GateRef vtable = builder_.LoadConstOffset(VariableType::JS_ANY(),
hclass, JSHClass::VTABLE_OFFSET);
GateRef itemOwner = LoadFromTaggedArray(vtable, VTable::TupleItem::OWNER + index);
GateRef itemOffset = LoadFromTaggedArray(vtable, VTable::TupleItem::OFFSET + index);
GateRef itemOwner = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OWNER + index);
GateRef itemOffset = builder_.LoadFromTaggedArray(vtable, VTable::TupleItem::OFFSET + index);
return builder_.Load(VariableType::JS_ANY(), itemOwner, builder_.TaggedGetInt(itemOffset));
}
@ -1113,7 +1107,7 @@ GateRef TypeMCRLowering::GetLengthFromSupers(GateRef supers)
GateRef TypeMCRLowering::GetValueFromSupers(GateRef supers, size_t index)
{
GateRef val = LoadFromTaggedArray(supers, index);
GateRef val = builder_.LoadFromTaggedArray(supers, index);
return builder_.LoadObjectFromWeakRef(val);
}

View File

@ -12,3 +12,4 @@
# limitations under the License.
2
1

View File

@ -14,10 +14,16 @@
*/
declare function print(str:any):string;
{
function f() { return x + 1; }
let gValue = 0;
function g() {
gValue++;
}
const x = 1;
print(f());
}
g();
print(gValue);