fixed for Set/GetPropertyByValue & test262 case verify

Signed-off-by: getingke <getingke@huawei.com>
Change-Id: I06214f39ebff93754edb3d275be4d4d76c1dba0c
This commit is contained in:
getingke 2021-10-16 18:06:22 +08:00
parent 121c45d6ab
commit b35952f22a
22 changed files with 756 additions and 49 deletions

View File

@ -735,13 +735,13 @@ void GetPropertyByIndexStub::GenerateCircuit()
StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter);
Return(CallRuntime(callAccessorGetter, thread,
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
{thread, *holder, value}));
{thread, value, *holder}));
}
Bind(&notInternal);
{
StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter);
Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
{thread, receiver, value}));
{thread, value, receiver}));
}
}
Bind(&notAccessor);
@ -891,7 +891,7 @@ void GetPropertyByNameStub::GenerateCircuit()
Label isDicMode(env);
Label notDicMode(env);
// if branch condition : LIKELY(!hclass->IsDictionaryMode())
Branch(IsDictionaryElement(hClass), &isDicMode, &notDicMode);
Branch(IsDictionaryModeByHClass(hClass), &isDicMode, &notDicMode);
Bind(&notDicMode);
{
// LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject())
@ -918,6 +918,7 @@ void GetPropertyByNameStub::GenerateCircuit()
Label notAccessor(env);
Branch(IsAccessor(attr), &isAccessor, &notAccessor);
Bind(&isAccessor);
{
Label isInternal(env);
Label notInternal(env);
@ -927,13 +928,13 @@ void GetPropertyByNameStub::GenerateCircuit()
StubDescriptor *callAccessorGetter = GET_STUBDESCRIPTOR(AccessorGetter);
Return(CallRuntime(callAccessorGetter, thread,
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
{thread, *holder, value}));
{thread, value, *holder}));
}
Bind(&notInternal);
{
StubDescriptor *callGetter = GET_STUBDESCRIPTOR(CallGetter);
Return(CallRuntime(callGetter, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
{thread, receiver, value}));
{thread, value, receiver}));
}
}
Bind(&notAccessor);
@ -976,13 +977,13 @@ void GetPropertyByNameStub::GenerateCircuit()
StubDescriptor *callAccessorGetter1 = GET_STUBDESCRIPTOR(AccessorGetter);
Return(CallRuntime(callAccessorGetter1, thread,
GetWord64Constant(FAST_STUB_ID(AccessorGetter)),
{thread, *holder, value}));
{thread, value, *holder}));
}
Bind(&notInternal1);
{
StubDescriptor *callGetter1 = GET_STUBDESCRIPTOR(CallGetter);
Return(CallRuntime(callGetter1, thread, GetWord64Constant(FAST_STUB_ID(CallGetter)),
{thread, receiver, value}));
{thread, value, receiver,}));
}
}
Bind(&notAccessor1);
@ -1314,4 +1315,159 @@ void FunctionCallInternalStub::GenerateCircuit()
Return(CallRuntime(execute, thread, GetWord64Constant(FAST_STUB_ID(Execute)),
{thread, func, thisArg, argc, argv}));
}
void GetPropertyByValueStub::GenerateCircuit()
{
auto env = GetEnvironment();
AddrShift thread = PtrArgument(0);
AddrShift receiver = PtrArgument(1);
DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */
Label isNumberOrStringSymbol(env);
Label notNumber(env);
Label isStringOrSymbol(env);
Label notStringOrSymbol(env);
Label exit(env);
Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, &notNumber);
Bind(&notNumber);
{
Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, &notStringOrSymbol);
Bind(&notStringOrSymbol);
{
Return(GetHoleConstant());
}
}
Bind(&isNumberOrStringSymbol);
{
AddrShift index = TryToElementsIndex(*key);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, &notValidIndex);
Bind(&validIndex);
{
auto getPropertyByIndex = GET_STUBDESCRIPTOR(GetPropertyByIndex);
Return(CallStub(getPropertyByIndex, GetWord64Constant(FAST_STUB_ID(GetPropertyByIndex)),
{thread, receiver, index}));
}
Bind(&notValidIndex);
{
Label notNumber(env);
Label getByName(env);
Branch(TaggedIsNumber(*key), &exit, &notNumber);
Bind(&notNumber);
{
Label isString(env);
Label notString(env);
Label isInternalString(env);
Label notIntenalString(env);
Branch(TaggedIsString(*key), &isString, &notString);
Bind(&isString);
{
Branch(IsInternalString(*key), &isInternalString, &notIntenalString);
Bind(&isInternalString);
Jump(&getByName);
Bind(&notIntenalString);
{
StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString);
key = CallRuntime(newInternalString, thread,
GetWord64Constant(FAST_STUB_ID(NewInternalString)),
{thread, *key});
Jump(&getByName);
}
}
Bind(&notString);
{
Jump(&getByName);
}
}
Bind(&getByName);
{
auto getPropertyByName = GET_STUBDESCRIPTOR(GetPropertyByName);
Return(CallStub(getPropertyByName, GetWord64Constant(FAST_STUB_ID(GetPropertyByName)),
{thread, receiver, *key}));
}
}
}
Bind(&exit);
Return(GetHoleConstant());
}
void SetPropertyByValueStub::GenerateCircuit()
{
auto env = GetEnvironment();
AddrShift thread = PtrArgument(0);
AddrShift receiver = PtrArgument(1);
DEFVARIABLE(key, TAGGED_TYPE, PtrArgument(2)); /* 2 : 3rd parameter is key */
AddrShift value = Int64Argument(3); /* 3 : 4th parameter is value */
Label isNumberOrStringSymbol(env);
Label notNumber(env);
Label isStringOrSymbol(env);
Label notStringOrSymbol(env);
Label exit(env);
Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, &notNumber);
Bind(&notNumber);
{
Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, &notStringOrSymbol);
Bind(&notStringOrSymbol);
{
Return(GetHoleConstant());
}
}
Bind(&isNumberOrStringSymbol);
{
AddrShift index = TryToElementsIndex(*key);
Label validIndex(env);
Label notValidIndex(env);
Branch(Int32GreaterThanOrEqual(index, GetInteger32Constant(0)), &validIndex, &notValidIndex);
Bind(&validIndex);
{
auto setPropertyByIndex = GET_STUBDESCRIPTOR(SetPropertyByIndex);
Return(CallStub(setPropertyByIndex, GetWord64Constant(FAST_STUB_ID(SetPropertyByIndex)),
{thread, receiver, index, value}));
}
Bind(&notValidIndex);
{
Label notNumber(env);
Label getByName(env);
Branch(TaggedIsNumber(*key), &exit, &notNumber);
Bind(&notNumber);
{
Label isString(env);
Label notString(env);
Label isInternalString(env);
Label notIntenalString(env);
Branch(TaggedIsString(*key), &isString, &notString);
Bind(&isString);
{
Branch(IsInternalString(*key), &isInternalString, &notIntenalString);
Bind(&isInternalString);
Jump(&getByName);
Bind(&notIntenalString);
{
StubDescriptor *newInternalString = GET_STUBDESCRIPTOR(NewInternalString);
key = CallRuntime(newInternalString, thread,
GetWord64Constant(FAST_STUB_ID(NewInternalString)),
{thread, *key});
Jump(&getByName);
}
}
Bind(&notString);
{
Jump(&getByName);
}
}
Bind(&getByName);
{
auto setPropertyByName = GET_STUBDESCRIPTOR(SetPropertyByName);
Return(CallStub(setPropertyByName, GetWord64Constant(FAST_STUB_ID(SetPropertyByName)),
{thread, receiver, *key, value}));
}
}
}
Bind(&exit);
Return(GetHoleConstant());
}
} // namespace kungfu

View File

@ -83,7 +83,10 @@ public:
class GetElementStub : public Stub {
public:
// 3 : 3 means argument counts
explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit) {}
explicit GetElementStub(Circuit *circuit) : Stub("GetElement", 3, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~GetElementStub() = default;
NO_MOVE_SEMANTIC(GetElementStub);
NO_COPY_SEMANTIC(GetElementStub);
@ -113,7 +116,10 @@ public:
class GetPropertyByIndexStub : public Stub {
public:
// 3 : 3 means argument counts
explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit) {}
explicit GetPropertyByIndexStub(Circuit *circuit) : Stub("GetPropertyByIndex", 3, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~GetPropertyByIndexStub() = default;
NO_MOVE_SEMANTIC(GetPropertyByIndexStub);
NO_COPY_SEMANTIC(GetPropertyByIndexStub);
@ -123,7 +129,10 @@ public:
class SetPropertyByIndexStub : public Stub {
public:
// 4 : 4 means argument counts
explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit) {}
explicit SetPropertyByIndexStub(Circuit *circuit) : Stub("SetPropertyByIndex", 4, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~SetPropertyByIndexStub() = default;
NO_MOVE_SEMANTIC(SetPropertyByIndexStub);
NO_COPY_SEMANTIC(SetPropertyByIndexStub);
@ -133,7 +142,10 @@ public:
class GetPropertyByNameStub : public Stub {
public:
// 3 : 3 means argument counts
explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit) {}
explicit GetPropertyByNameStub(Circuit *circuit) : Stub("GetPropertyByName", 3, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~GetPropertyByNameStub() = default;
NO_MOVE_SEMANTIC(GetPropertyByNameStub);
NO_COPY_SEMANTIC(GetPropertyByNameStub);
@ -172,5 +184,31 @@ public:
NO_COPY_SEMANTIC(FunctionCallInternalStub);
void GenerateCircuit() override;
};
class GetPropertyByValueStub : public Stub {
public:
// 3 : 3 means argument counts
explicit GetPropertyByValueStub(Circuit *circuit) : Stub("FastGetPropertyByValue", 3, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~GetPropertyByValueStub() = default;
NO_MOVE_SEMANTIC(GetPropertyByValueStub);
NO_COPY_SEMANTIC(GetPropertyByValueStub);
void GenerateCircuit() override;
};
class SetPropertyByValueStub : public Stub {
public:
// 4 : 4 means argument counts
explicit SetPropertyByValueStub(Circuit *circuit) : Stub("FastSetPropertyByValue", 4, circuit)
{
circuit->SetFrameType(panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME);
}
~SetPropertyByValueStub() = default;
NO_MOVE_SEMANTIC(SetPropertyByValueStub);
NO_COPY_SEMANTIC(SetPropertyByValueStub);
void GenerateCircuit() override;
};
} // namespace kungfu
#endif // ECMASCRIPT_COMPILER_FASTPATH_STUB_H

View File

@ -29,7 +29,8 @@ namespace kungfu {
V(FindElementWithCache, 4) \
V(Execute, 5) \
V(StringGetHashCode, 1) \
V(FloatMod, 2)
V(FloatMod, 2) \
V(NewInternalString, 2)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define FAST_RUNTIME_STUB_LIST(V) \
@ -60,7 +61,9 @@ namespace kungfu {
V(FindOwnElement2, 6) \
V(GetPropertyByIndex, 3) \
V(FunctionCallInternal, 5) \
V(SetPropertyByIndex, 4)
V(SetPropertyByIndex, 4) \
V(GetPropertyByValue, 3) \
V(SetPropertyByValue, 4)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define TEST_FUNC_LIST(V) \

View File

@ -185,12 +185,20 @@ Properties OpCode::GetProperties() const
return {INT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT};
case ZEXT_INT1_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT};
case ZEXT_INT8_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT};
case ZEXT_INT16_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT16), NO_ROOT};
case ZEXT_INT1_TO_INT64:
return {INT64, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT};
case SEXT_INT32_TO_INT64:
return {INT64, NO_STATE, NO_DEPEND, VALUE(INT32), NO_ROOT};
case SEXT_INT1_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT};
case SEXT_INT8_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT};
case SEXT_INT16_TO_INT32:
return {INT32, NO_STATE, NO_DEPEND, VALUE(INT8), NO_ROOT};
case SEXT_INT1_TO_INT64:
return {INT64, NO_STATE, NO_DEPEND, VALUE(INT1), NO_ROOT};
case TRUNC_INT64_TO_INT32:
@ -400,9 +408,13 @@ std::string OpCode::Str() const
{FLOAT64_CONSTANT, "FLOAT64_CONSTANT"},
{ZEXT_INT32_TO_INT64, "ZEXT_INT32_TO_INT64"},
{ZEXT_INT1_TO_INT32, "ZEXT_INT1_TO_INT32"},
{ZEXT_INT8_TO_INT32, "ZEXT_INT8_TO_INT32"},
{ZEXT_INT16_TO_INT32, "ZEXT_INT16_TO_INT32"},
{ZEXT_INT1_TO_INT64, "ZEXT_INT1_TO_INT64"},
{SEXT_INT32_TO_INT64, "SEXT_INT32_TO_INT64"},
{SEXT_INT1_TO_INT32, "SEXT_INT1_TO_INT32"},
{SEXT_INT8_TO_INT32, "SEXT_INT8_TO_INT32"},
{SEXT_INT16_TO_INT32, "SEXT_INT16_TO_INT32"},
{SEXT_INT1_TO_INT64, "SEXT_INT1_TO_INT64"},
{TRUNC_INT64_TO_INT32, "TRUNC_INT64_TO_INT32"},
{TRUNC_INT64_TO_INT1, "TRUNC_INT64_TO_INT1"},
@ -1305,4 +1317,9 @@ bool OpCode::IsLoopHead() const
{
return (this->op == OpCode::LOOP_BEGIN);
}
bool OpCode::IsNop() const
{
return (this->op == OpCode::NOP);
}
} // namespace kungfu

View File

@ -147,9 +147,13 @@ public:
FLOAT64_CONSTANT,
ZEXT_INT32_TO_INT64,
ZEXT_INT1_TO_INT32,
ZEXT_INT8_TO_INT32,
ZEXT_INT16_TO_INT32,
ZEXT_INT1_TO_INT64,
SEXT_INT32_TO_INT64,
SEXT_INT1_TO_INT32,
SEXT_INT8_TO_INT32,
SEXT_INT16_TO_INT32,
SEXT_INT1_TO_INT64,
TRUNC_INT64_TO_INT32,
TRUNC_INT64_TO_INT1,
@ -253,6 +257,7 @@ public:
[[nodiscard]] bool IsCFGMerge() const;
[[nodiscard]] bool IsControlCase() const;
[[nodiscard]] bool IsLoopHead() const;
[[nodiscard]] bool IsNop() const;
~OpCode() = default;
private:

View File

@ -92,6 +92,8 @@ void LLVMIRBuilder::AssignHandleMap()
{OpCode::INT64_CONSTANT, &LLVMIRBuilder::HandleInt64Constant},
{OpCode::FLOAT64_CONSTANT, &LLVMIRBuilder::HandleFloat64Constant},
{OpCode::ZEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleZExtInt},
{OpCode::ZEXT_INT8_TO_INT32, &LLVMIRBuilder::HandleZExtInt},
{OpCode::ZEXT_INT16_TO_INT32, &LLVMIRBuilder::HandleZExtInt},
{OpCode::ZEXT_INT32_TO_INT64, &LLVMIRBuilder::HandleZExtInt},
{OpCode::ZEXT_INT1_TO_INT64, &LLVMIRBuilder::HandleZExtInt},
{OpCode::SEXT_INT1_TO_INT32, &LLVMIRBuilder::HandleSExtInt},
@ -134,6 +136,8 @@ void LLVMIRBuilder::AssignHandleMap()
{OpCode::FLOAT64_EQ, &LLVMIRBuilder::HandleFloatOrDoubleCmp},
{OpCode::INT32_NE, &LLVMIRBuilder::HandleIntOrUintCmp},
{OpCode::INT64_NE, &LLVMIRBuilder::HandleIntOrUintCmp},
{OpCode::INT8_LOAD, &LLVMIRBuilder::HandleLoad},
{OpCode::INT16_LOAD, &LLVMIRBuilder::HandleLoad},
{OpCode::INT32_LOAD, &LLVMIRBuilder::HandleLoad},
{OpCode::INT64_LOAD, &LLVMIRBuilder::HandleLoad},
{OpCode::INT32_STORE, &LLVMIRBuilder::HandleStore},
@ -186,7 +190,6 @@ void LLVMIRBuilder::Build()
AddrShift gate = (*schedule_)[bbIdx][instIdx - 1];
std::vector<AddrShift> ins = circuit_->GetInVector(gate);
std::vector<AddrShift> outs = circuit_->GetOutVector(gate);
std::cout << "instIdx :" << instIdx << std::endl;
circuit_->Print(gate);
auto found = opCodeHandleMap_.find(circuit_->GetOpCode(gate));
if (found != opCodeHandleMap_.end()) {
@ -362,6 +365,9 @@ LLVMTypeRef LLVMIRBuilder::GetMachineRepType(MachineRep rep) const
case MachineRep::K_WORD8:
dstType = LLVMInt8TypeInContext(context_);
break;
case MachineRep::K_WORD16:
dstType = LLVMInt16TypeInContext(context_);
break;
case MachineRep::K_WORD32:
dstType = LLVMInt32TypeInContext(context_);
break;
@ -626,6 +632,8 @@ void LLVMIRBuilder::HandleZExtInt(AddrShift gate)
{
std::vector<AddrShift> ins = circuit_->GetInVector(gate);
switch (circuit_->GetOpCode(gate)) {
case OpCode::ZEXT_INT8_TO_INT32: // no break, fall through
case OpCode::ZEXT_INT16_TO_INT32:
case OpCode::ZEXT_INT1_TO_INT32: {
VisitZExtInt(gate, ins[0], MachineRep::K_WORD32);
break;
@ -1041,6 +1049,16 @@ void LLVMIRBuilder::HandleLoad(AddrShift gate)
std::vector<AddrShift> ins = circuit_->GetInVector(gate);
std::vector<AddrShift> outs = circuit_->GetOutVector(gate);
switch (circuit_->GetOpCode(gate)) {
case OpCode::INT8_LOAD: {
AddrShift base = ins[1];
VisitLoad(gate, MachineRep::K_WORD8, base);
break;
}
case OpCode::INT16_LOAD: {
AddrShift base = ins[1];
VisitLoad(gate, MachineRep::K_WORD16, base);
break;
}
case OpCode::INT32_LOAD: {
AddrShift base = ins[1];
VisitLoad(gate, MachineRep::K_WORD32, base);

View File

@ -104,7 +104,7 @@ void LLVMAssembler::BuildAndRunPasses() const
LOG_ECMA(INFO) << "BuildAndRunPasses - ";
LLVMPassManagerRef pass = LLVMCreatePassManager();
LLVMAddConstantPropagationPass(pass);
LLVMAddInstructionCombiningPass(pass);
//LLVMAddInstructionCombiningPass(pass);
llvm::unwrap(pass)->add(llvm::createRewriteStatepointsForGCLegacyPass());
char *info = LLVMPrintModuleToString(module_);
LOG_ECMA(INFO) << "Current Module: " << info;

View File

@ -34,10 +34,11 @@ AddrShift Stub::Variable::AddPhiOperand(AddrShift val)
Label label = env_->GetLabelFromSelector(val);
size_t idx = 0;
for (auto pred : label.GetPredecessors()) {
auto preVal = pred.ReadVariable(this);
ASSERT(!env_->GetCircuit()->GetOpCode(preVal).IsNop());
idx++;
val = AddOperandToSelector(val, idx, pred.ReadVariable(this));
val = AddOperandToSelector(val, idx, preVal);
}
return TryRemoveTrivialPhi(val);
}
@ -66,6 +67,7 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal)
// the phi is unreachable or in the start block
same = env_->GetCircuit()->LoadGatePtr(env_->GetCircuitBuilder().UndefineConstant());
}
auto same_addr_shift = env_->GetCircuit()->SaveGatePtr(same);
// remove the trivial phi
// get all users of phi except self
@ -92,10 +94,15 @@ AddrShift Stub::Variable::TryRemoveTrivialPhi(AddrShift phiVal)
for (auto out : outs) {
if (IsSelector(out->GetGate())) {
auto out_addr_shift = env_->GetCircuit()->SaveGatePtr(out->GetGate());
TryRemoveTrivialPhi(out_addr_shift);
auto result = TryRemoveTrivialPhi(out_addr_shift);
if (same_addr_shift == out_addr_shift)
{
same_addr_shift = result;
}
}
}
return env_->GetCircuit()->SaveGatePtr(same);
return same_addr_shift;
}
void Stub::Variable::RerouteOuts(const std::vector<Out *> &outs, Gate *newGate)
@ -123,7 +130,10 @@ void LabelImpl::WriteVariable(Variable *var, AddrShift value)
AddrShift LabelImpl::ReadVariable(Variable *var)
{
if (valueMap_.find(var) != valueMap_.end()) {
return valueMap_.at(var);
auto result = valueMap_.at(var);
if (!env_->GetCircuit()->GetOpCode(result).IsNop()) {
return result;
}
}
return ReadVariableRecursive(var);
}
@ -423,7 +433,7 @@ AddrShift Stub::FindElementFromNumberDictionary(AddrShift thread, AddrShift elem
Bind(&notMatch);
Jump(&loopEnd);
Bind(&loopEnd);
entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1)));
entry = GetNextPositionForHash(*entry, *count, capacity);
count = Int32Add(*count, GetInteger32Constant(1));
LoopEnd(&loopHead);
Bind(&exit);
@ -594,7 +604,7 @@ AddrShift Stub::FindEntryFromNameDictionary(AddrShift thread, AddrShift elements
}
Bind(&loopEnd);
{
entry = Word32And(Int32Add(*entry, *count), Int32Sub(capacity, GetInteger32Constant(1)));
entry = GetNextPositionForHash(*entry, *count, capacity);
count = Int32Add(*count, GetInteger32Constant(1));
LoopEnd(&loopHead);
}
@ -626,7 +636,7 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a
Int32Mul(Int32Sub(
GetInteger32Constant(panda::ecmascript::JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS), attrOffset),
GetInteger32Constant(panda::ecmascript::JSTaggedValue::TaggedTypeSize())));
result = Int64BuildTagged(Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset)));
result = Load(UINT64_TYPE, obj, ZExtInt32ToInt64(propOffset));
Jump(&exit);
}
Bind(&notInlinedProp);
@ -646,10 +656,9 @@ AddrShift Stub::JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift a
void Stub::ThrowTypeAndReturn(AddrShift thread, int messageId, AddrShift val)
{
AddrShift taggedId = GetInteger32Constant(messageId);
StubDescriptor *throwTypeError = GET_STUBDESCRIPTOR(ThrowTypeError);
CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)),
{thread, taggedId});
AddrShift msgIntId = GetInteger32Constant(messageId);
CallRuntime(throwTypeError, thread, GetWord64Constant(FAST_STUB_ID(ThrowTypeError)), {thread, msgIntId});
Return(val);
}
@ -793,4 +802,248 @@ void Stub::UpdateAndStoreRepresention(AddrShift hclass, AddrShift value)
AddrShift newRep = UpdateRepresention(GetElementRepresentation(hclass), value);
SetElementRepresentation(hclass, newRep);
}
AddrShift Stub::TaggedIsString(AddrShift obj)
{
auto env = GetEnvironment();
Label entry(env);
[[maybe_unused]] SubCircuitScope subCircuit(env, &entry);
Label exit(env);
DEFVARIABLE(result, BOOL_TYPE, FalseConstant());
Label isHeapObject(env);
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
Bind(&isHeapObject);
{
result = Word32Equal(GetObjectType(LoadHClass(obj)),
GetInteger32Constant(static_cast<int32_t>(panda::ecmascript::JSType::STRING)));
Jump(&exit);
}
Bind(&exit);
return *result;
}
AddrShift Stub::TaggedIsStringOrSymbol(AddrShift obj)
{
auto env = GetEnvironment();
Label entry(env);
[[maybe_unused]] SubCircuitScope subCircuit(env, &entry);
Label exit(env);
DEFVARIABLE(result, BOOL_TYPE, FalseConstant());
Label isHeapObject(env);
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
Bind(&isHeapObject);
{
AddrShift objType = GetObjectType(LoadHClass(obj));
result = Word32Equal(objType,
GetInteger32Constant(static_cast<int32_t>(panda::ecmascript::JSType::STRING)));
Label isString(env);
Label notString(env);
Branch(*result, &exit, &notString);
Bind(&notString);
{
result = Word32Equal(objType,
GetInteger32Constant(static_cast<int32_t>(panda::ecmascript::JSType::SYMBOL)));
Jump(&exit);
}
}
Bind(&exit);
return *result;
}
AddrShift Stub::IsUtf16String(AddrShift string)
{
// compressedStringsEnabled fixed to true constant
AddrShift len = Load(MachineType::UINT32_TYPE, string,
GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset()));
return Word32Equal(
Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)),
GetInteger32Constant(panda::ecmascript::EcmaString::STRING_UNCOMPRESSED));
}
AddrShift Stub::IsUtf8String(AddrShift string)
{
// compressedStringsEnabled fixed to true constant
AddrShift len = Load(MachineType::UINT32_TYPE, string,
GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset()));
return Word32Equal(
Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED_BIT)),
GetInteger32Constant(panda::ecmascript::EcmaString::STRING_COMPRESSED));
}
AddrShift Stub::IsInternalString(AddrShift string)
{
// compressedStringsEnabled fixed to true constant
AddrShift len = Load(MachineType::UINT32_TYPE, string,
GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset()));
return Word32NotEqual(
Word32And(len, GetInteger32Constant(panda::ecmascript::EcmaString::STRING_INTERN_BIT)),
GetInteger32Constant(0));
}
AddrShift Stub::IsDigit(AddrShift ch)
{
return TruncInt32ToInt1(
Word32And(SExtInt1ToInt32(Int32LessThanOrEqual(ch, GetInteger32Constant('9'))),
SExtInt1ToInt32(Int32GreaterThanOrEqual(ch, GetInteger32Constant('0')))));
}
AddrShift Stub::StringToElementIndex(AddrShift string)
{
auto env = GetEnvironment();
Label entry(env);
[[maybe_unused]] SubCircuitScope subCircuit(env, &entry);
Label exit(env);
DEFVARIABLE(result, INT32_TYPE, GetInteger32Constant(-1));
Label greatThanZero(env);
Label inRange(env);
AddrShift len = Load(MachineType::UINT32_TYPE, string,
GetPtrConstant(panda::ecmascript::EcmaString::GetLengthOffset()));
len = Word32LSR(len, GetInteger32Constant(2));
Branch(Word32Equal(len, GetInteger32Constant(0)), &exit, &greatThanZero);
Bind(&greatThanZero);
Branch(Int32GreaterThan(len, GetInteger32Constant(panda::ecmascript::MAX_INDEX_LEN)), &exit, &inRange);
Bind(&inRange);
{
AddrShift dataUtf16 = PtrAdd(string, GetPtrConstant(panda::ecmascript::EcmaString::GetDataOffset()));
DEFVARIABLE(c, UINT32_TYPE, GetInteger32Constant(0));
Label isUtf16(env);
Label isUtf8(env);
Label getChar1(env);
AddrShift isUtf16String = IsUtf16String(string);
Branch(isUtf16String, &isUtf16, &isUtf8);
Bind(&isUtf16);
{
c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16));
Jump(&getChar1);
}
Bind(&isUtf8);
{
c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16));
Jump(&getChar1);
}
Bind(&getChar1);
{
Label isDigitZero(env);
Label notDigitZero(env);
Branch(Word32Equal(*c, GetInteger32Constant('0')), &isDigitZero, &notDigitZero);
Bind(&isDigitZero);
{
Label lengthIsOne(env);
Branch(Word32Equal(len, GetInteger32Constant(1)), &lengthIsOne, &exit);
Bind(&lengthIsOne);
{
result = GetInteger32Constant(0);
Jump(&exit);
}
}
Bind(&notDigitZero);
{
Label isDigit(env);
DEFVARIABLE(i, UINT32_TYPE, GetInteger32Constant(1));
DEFVARIABLE(n, UINT32_TYPE, Int32Sub(*c, GetInteger32Constant('0')));
Branch(IsDigit(*c), &isDigit, &exit);
Label loopHead(env);
Label loopEnd(env);
Label afterLoop(env);
Bind(&isDigit);
Branch(Int32LessThan(*i, len), &loopHead, &exit);
LoopBegin(&loopHead);
{
Label isUtf16(env);
Label notUtf16(env);
Label getChar2(env);
Branch(isUtf16String, &isUtf16, &notUtf16);
Bind(&isUtf16);
{
c = ZExtInt16ToInt32(Load(INT16_TYPE, dataUtf16, PtrMul(*i, GetPtrConstant(2))));
Jump(&getChar2);
}
Bind(&notUtf16);
{
c = ZExtInt8ToInt32(Load(INT8_TYPE, dataUtf16, *i));
Jump(&getChar2);
}
Bind(&getChar2);
{
Label isDigit2(env);
Label notDigit2(env);
Branch(IsDigit(*c), &isDigit2, &notDigit2);
Bind(&isDigit2);
{
n = Int32Add(Int32Mul(*n, GetInteger32Constant(10)),
Int32Sub(*c, GetInteger32Constant('0')));
i = Int32Add(*i, GetInteger32Constant(1));
Branch(Int32LessThan(*i, len), &loopEnd, &afterLoop);
}
Bind(&notDigit2);
Jump(&exit);
}
}
Bind(&loopEnd);
LoopEnd(&loopHead);
Bind(&afterLoop);
{
Label lessThanMaxIndex(env);
Branch(Word32LessThan(*n, GetInteger32Constant(panda::ecmascript::JSObject::MAX_ELEMENT_INDEX)),
&lessThanMaxIndex, &exit);
Bind(&lessThanMaxIndex);
{
result = *n;
Jump(&exit);
}
}
}
}
}
Bind(&exit);
return *result;
}
AddrShift Stub::TryToElementsIndex(AddrShift key)
{
auto env = GetEnvironment();
Label entry(env);
[[maybe_unused]] SubCircuitScope subCircuit(env, &entry);
Label exit(env);
Label isKeyInt(env);
Label notKeyInt(env);
DEFVARIABLE(resultKey, INT32_TYPE, GetInteger32Constant(0));
Branch(TaggedIsInt(key), &isKeyInt, &notKeyInt);
Bind(&isKeyInt);
{
resultKey = TaggedCastToInt32(key);
Jump(&exit);
}
Bind(&notKeyInt);
{
Label isString(env);
Label notString(env);
Branch(TaggedIsString(key), &isString, &notString);
Bind(&isString);
{
resultKey = StringToElementIndex(key);
Jump(&exit);
}
Bind(&notString);
{
Label isDouble(env);
Branch(TaggedIsDouble(key), &isDouble, &exit);
Bind(&isDouble);
{
AddrShift number = TaggedCastToDouble(key);
AddrShift integer = ChangeInt64ToInt32(CastDoubleToInt64(number));
Label isEqual(env);
Branch(DoubleEqual(number, CastInt64ToFloat64(SExtInt32ToInt64(integer))), &isEqual, &exit);
Bind(&isEqual);
{
resultKey = integer;
Jump(&exit);
}
}
}
}
Bind(&exit);
return *resultKey;
}
} // namespace kungfu

View File

@ -699,7 +699,16 @@ public:
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::FLOAT64_DIV), x, y);
}
AddrShift Int32Div(AddrShift x, AddrShift y);
AddrShift Int32Div(AddrShift x, AddrShift y)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_SDIV), x, y);
}
AddrShift Word32Div(AddrShift x, AddrShift y)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_UDIV), x, y);
}
AddrShift Int64Div(AddrShift x, AddrShift y);
AddrShift Int32Mod(AddrShift x, AddrShift y)
@ -761,11 +770,6 @@ public:
return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_AND), x, y);
}
AddrShift WordLogicNot(AddrShift x)
{
return env_.GetCircuitBuilder().NewLogicGate(OpCode(OpCode::INT32_REV), x);
}
AddrShift Word32LSL(AddrShift x, AddrShift y)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::INT32_LSL), x, y);
@ -828,15 +832,27 @@ public:
SExtInt1ToInt32(
Word64Equal(Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)),
GetWord64Constant(0))),
Word32Or(SExtInt1ToInt32(Word64NotEqual(
Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_MASK)),
WordLogicOr(SExtInt1ToInt32(Word64NotEqual(
Word64And(x, GetWord64Constant(panda::ecmascript::JSTaggedValue::TAG_SPECIAL_VALUE)),
GetWord64Constant(0))), SExtInt1ToInt32(TaggedIsHole(x)))));
}
AddrShift TaggedIsHeapObject(AddrShift x)
{
return TruncInt32ToInt1(
Word32And(SExtInt1ToInt32(TaggedIsObject(x)), Word32Not(SExtInt1ToInt32(TaggedIsSpecial(x)))));
WordLogicAnd(SExtInt1ToInt32(TaggedIsObject(x)),
SExtInt1ToInt32(Word32Equal(SExtInt1ToInt32(TaggedIsSpecial(x)), GetInteger32Constant(0)))));
}
AddrShift TaggedIsString(AddrShift obj);
AddrShift TaggedIsStringOrSymbol(AddrShift obj);
AddrShift GetNextPositionForHash(AddrShift last, AddrShift count, AddrShift size)
{
auto nextOffset = Word32LSR(Int32Mul(count, Int32Add(count, GetInteger32Constant(1))),
GetInteger32Constant(2));
return Word32And(Int32Add(last, nextOffset), Int32Sub(size, GetInteger32Constant(1)));
}
AddrShift DoubleIsNAN(AddrShift x)
@ -1062,6 +1078,17 @@ public:
GetInteger32Constant(0));
}
AddrShift IsDictionaryModeByHClass(AddrShift hClass)
{
AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET);
AddrShift bitfield = Load(INT64_TYPE, hClass, bitfieldOffset);
return Word64NotEqual(
Word64And(
Word64LSR(bitfield, GetWord64Constant(panda::ecmascript::JSHClass::IsDictionaryBit::START_BIT)),
GetWord64Constant((1LLU << panda::ecmascript::JSHClass::IsDictionaryBit::SIZE) - 1)),
GetWord64Constant(0));
}
AddrShift IsDictionaryElement(AddrShift hclass)
{
AddrShift bitfieldOffset = GetPtrConstant(panda::ecmascript::JSHClass::BIT_FIELD_OFFSET);
@ -1309,6 +1336,18 @@ public:
AddrShift JSObjectGetProperty(AddrShift obj, AddrShift hClass, AddrShift propAttr);
AddrShift IsUtf16String(AddrShift string);
AddrShift IsUtf8String(AddrShift string);
AddrShift IsInternalString(AddrShift string);
AddrShift IsDigit(AddrShift ch);
AddrShift StringToElementIndex(AddrShift string);
AddrShift TryToElementsIndex(AddrShift key);
AddrShift TaggedCastToInt64(AddrShift x)
{
return Word64And(x, GetWord64Constant(~panda::ecmascript::JSTaggedValue::TAG_MASK));
@ -1365,6 +1404,16 @@ public:
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT1_TO_INT32), x);
}
AddrShift ZExtInt8ToInt32(AddrShift x)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT8_TO_INT32), x);
}
AddrShift ZExtInt16ToInt32(AddrShift x)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::ZEXT_INT16_TO_INT32), x);
}
AddrShift TruncInt64ToInt32(AddrShift x)
{
return env_.GetCircuitBuilder().NewArithMeticGate(OpCode(OpCode::TRUNC_INT64_TO_INT32), x);

View File

@ -161,7 +161,8 @@ void StubAotCompiler::BuildStubModuleAndSave(const char *triple, panda::ecmascri
SET_STUB_TO_MODULE(module, GetPropertyByIndex) \
SET_STUB_TO_MODULE(module, SetPropertyByIndex) \
SET_STUB_TO_MODULE(module, FunctionCallInternal) \
SET_STUB_TO_MODULE(module, GetPropertyByName)
SET_STUB_TO_MODULE(module, GetPropertyByName) \
SET_STUB_TO_MODULE(module, GetPropertyByValue)
int main(const int argc, const char **argv)
{

View File

@ -39,6 +39,7 @@ public:
}
void BuildStubModuleAndSave(const char *triple, panda::ecmascript::StubModule *module,
const std::string &filename);
void SetAllStubToModule();
void SetStub(int index, Stub *optimizer)
{
stubs_[index] = optimizer;

View File

@ -28,4 +28,4 @@ options:
- x86_64-unknown-linux-gnu
- arm-unknown-linux-gnu
- aarch64-unknown-linux-gnu
description: stub aot compiler target triple
description: stub aot compiler target triple

View File

@ -245,6 +245,36 @@ CALL_STUB_INIT_DESCRIPTOR(SetPropertyByIndex)
descriptor->SetParameters(params.data());
}
CALL_STUB_INIT_DESCRIPTOR(GetPropertyByValue)
{
// 3 : 3 input parameters
static StubDescriptor getPropertyByValue("GetPropertyByValue", 0, 3, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE);
*descriptor = getPropertyByValue;
// 3 : 3 input parameters
std::array<MachineType, 3> params = {
MachineType::UINT64_TYPE,
MachineType::UINT64_TYPE,
MachineType::UINT64_TYPE,
};
descriptor->SetParameters(params.data());
}
CALL_STUB_INIT_DESCRIPTOR(SetPropertyByValue)
{
// // 4 : 4 input parameters
// static StubDescriptor setPropertyByValue("SetPropertyByValue", 0, 4, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE);
// *descriptor = setPropertyByValue;
// // 4 : 4 input parameters
// std::array<MachineType, 4> params = {
// MachineType::UINT64_TYPE,
// MachineType::UINT64_TYPE,
// MachineType::UINT64_TYPE,
// MachineType::UINT64_TYPE,
// };
// descriptor->SetParameters(params.data());
}
CALL_STUB_INIT_DESCRIPTOR(AddElementInternal)
{
// 5 : 5 input parameters
@ -404,6 +434,20 @@ CALL_STUB_INIT_DESCRIPTOR(StringGetHashCode)
descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB);
}
CALL_STUB_INIT_DESCRIPTOR(NewInternalString)
{
// 2 : 2 input parameters
static StubDescriptor stringGetHashCode("NewInternalString", 0, 2, ArgumentsOrder::DEFAULT_ORDER, UINT64_TYPE);
*descriptor = stringGetHashCode;
// 2 : 2 input parameters
std::array<MachineType, 2> params = {
MachineType::UINT64_TYPE,
MachineType::UINT64_TYPE,
};
descriptor->SetParameters(params.data());
descriptor->SetStubKind(StubDescriptor::CallStubKind::RUNTIME_STUB);
}
CALL_STUB_INIT_DESCRIPTOR(FastLoadElement)
{
// 2 : 2 input parameters

View File

@ -1185,6 +1185,91 @@ HWTEST_F_L0(StubTest, GetPropertyByNameStub)
EXPECT_EQ(resVal.GetNumber(), y);
}
HWTEST_F_L0(StubTest, FastGetPropertyByValueStub)
{
auto module = stubModule.GetModule();
LLVMValueRef getPropertyByIndexfunction = LLVMGetNamedFunction(module, "GetPropertyByIndex");
Circuit netOfGates2;
GetPropertyByIndexStub getPropertyByIndexStub(&netOfGates2);
getPropertyByIndexStub.GenerateCircuit();
netOfGates2.PrintAllGates();
auto cfg2 = Scheduler::Run(&netOfGates2);
LLVMIRBuilder llvmBuilder2(&cfg2, &netOfGates2, &stubModule, getPropertyByIndexfunction);
llvmBuilder2.Build();
LLVMValueRef getPropertyByNamefunction = LLVMGetNamedFunction(module, "GetPropertyByName");
Circuit netOfGates1;
GetPropertyByNameStub getPropertyByNameStub(&netOfGates1);
getPropertyByNameStub.GenerateCircuit();
bool result = Verifier::Run(&netOfGates1);
ASSERT_TRUE(result);
auto cfg1 = Scheduler::Run(&netOfGates1);
LLVMIRBuilder llvmBuilder1(&cfg1, &netOfGates1, &stubModule, getPropertyByNamefunction);
llvmBuilder1.Build();
LLVMValueRef function = LLVMGetNamedFunction(module, "GetPropertyByValue");
Circuit netOfGates;
GetPropertyByValueStub optimizer(&netOfGates);
optimizer.GenerateCircuit();
netOfGates.PrintAllGates();
result = Verifier::Run(&netOfGates);
ASSERT_TRUE(result);
auto cfg = Scheduler::Run(&netOfGates);
for (size_t bbIdx = 0; bbIdx < cfg.size(); bbIdx++) {
std::cout << (netOfGates.GetOpCode(cfg[bbIdx].front()).IsCFGMerge() ? "MERGE_" : "BB_") << bbIdx << ":"
<< std::endl;
for (size_t instIdx = cfg[bbIdx].size(); instIdx > 0; instIdx--) {
netOfGates.Print(cfg[bbIdx][instIdx - 1]);
}
}
LLVMIRBuilder llvmBuilder(&cfg, &netOfGates, &stubModule, function);
llvmBuilder.Build();
LLVMAssembler assembler(module, "x86_64-unknown-linux-gnu");
assembler.Run();
auto engine = assembler.GetEngine();
auto *getPropertyByValuePtr = reinterpret_cast<JSTaggedValue (*)(JSThread *, uint64_t, uint64_t)>(
reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(engine, function)));
auto *getPropertyByNamePtr = reinterpret_cast<JSTaggedValue (*)(JSThread *, uint64_t, uint64_t)>(
reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(engine, getPropertyByNamefunction)));
auto *getpropertyByIndexPtr = reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, uint32_t)>(
reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(engine, getPropertyByIndexfunction)));
auto *factory = JSThread::Cast(thread)->GetEcmaVM()->GetFactory();
JSHandle<JSObject> obj = factory->NewEmptyJSObject();
int x = 213;
int y = 10;
FastRuntimeStub::SetOwnElement(thread, obj.GetTaggedValue(), 1, JSTaggedValue(x));
FastRuntimeStub::SetOwnElement(thread, obj.GetTaggedValue(), 10250, JSTaggedValue(y));
JSHandle<JSTaggedValue> strA(factory->NewFromCanBeCompressString("a"));
JSHandle<JSTaggedValue> strBig(factory->NewFromCanBeCompressString("biggest"));
JSHandle<JSTaggedValue> strDigit(factory->NewFromCanBeCompressString("10250"));
FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strA.GetTaggedValue(), JSTaggedValue(x));
FastRuntimeStub::SetPropertyByName(thread, obj.GetTaggedValue(), strBig.GetTaggedValue(), JSTaggedValue(y));
assembler.Disassemble();
JSTaggedValue resVal1 = getPropertyByNamePtr(thread, obj.GetTaggedValue().GetRawData(),
strA.GetTaggedValue().GetRawData());
EXPECT_EQ(resVal1.GetNumber(), x);
JSTaggedValue resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(),
strA.GetTaggedValue().GetRawData());
EXPECT_EQ(resVal.GetNumber(), x);
resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), strBig.GetTaggedValue().GetRawData());
EXPECT_EQ(resVal.GetNumber(), y);
resVal = getpropertyByIndexPtr(thread, obj.GetTaggedValue(), 1);
EXPECT_EQ(resVal.GetNumber(), x);
resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), JSTaggedValue(10250).GetRawData());
EXPECT_EQ(resVal.GetNumber(), y);
resVal = getPropertyByValuePtr(thread, obj.GetTaggedValue().GetRawData(), strDigit.GetTaggedValue().GetRawData());
EXPECT_EQ(resVal.GetNumber(), y);
JSHandle<JSTaggedValue> strHello(factory->NewFromCanBeCompressString("hello world"));
double key = 4.29497e+09;
resVal = getPropertyByValuePtr(thread, strHello.GetTaggedValue().GetRawData(), JSTaggedValue(key).GetRawData());
EXPECT_EQ(resVal.GetRawData(), 0);
}
HWTEST_F_L0(StubTest, FastTypeOfTest)
{
auto module = stubModule.GetModule();

View File

@ -45,6 +45,13 @@ public:
static EcmaString *FastSubString(const JSHandle<EcmaString> &src, uint32_t start, uint32_t utf16Len,
const EcmaVM *vm);
static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1;
static constexpr uint32_t STRING_INTERN_BIT = 0x2;
enum CompressedStatus {
STRING_COMPRESSED,
STRING_UNCOMPRESSED,
};
template<bool verify = true>
uint16_t At(int32_t index) const;
@ -285,12 +292,6 @@ private:
static void CopyUtf16AsUtf8(const uint16_t *utf16From, uint8_t *utf8To, uint32_t utf16Len);
static bool compressedStringsEnabled;
static constexpr uint32_t STRING_COMPRESSED_BIT = 0x1;
static constexpr uint32_t STRING_INTERN_BIT = 0x2;
enum CompressedStatus {
STRING_COMPRESSED,
STRING_UNCOMPRESSED,
};
static bool IsASCIICharacter(uint16_t data)
{

View File

@ -168,6 +168,9 @@ bool EcmaVM::Initialize()
globalEnv->SetTemplateMap(thread_, JSTaggedValue(TemplateMap::Create(thread_)));
globalEnv->SetRegisterSymbols(GetJSThread(), JSTaggedValue(SymbolTable::Create(GetJSThread())));
std::string moduleFile = options_.GetStubModuleFile();
thread_->LoadFastStubModule(moduleFile.c_str());
SetupRegExpResultCache();
microJobQueue_ = factory_->NewMicroJobQueue().GetTaggedValue();

View File

@ -622,7 +622,10 @@ bool FastRuntimeStub::FastSetPropertyByIndex(JSThread *thread, JSTaggedValue rec
JSTaggedValue value)
{
INTERPRETER_TRACE(thread, FastSetPropertyByIndex);
JSTaggedValue result = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value);
auto *setPropertyByIndex = \
reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue)> \
(reinterpret_cast<uintptr_t>(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex))));
JSTaggedValue result = setPropertyByIndex(thread, receiver, index, value);
if (!result.IsHole()) {
return result != JSTaggedValue::Exception();
}
@ -654,7 +657,9 @@ JSTaggedValue FastRuntimeStub::FastGetPropertyByName(JSThread *thread, JSTaggedV
// Maybe moved by GC
receiver = receiverHandler.GetTaggedValue();
}
JSTaggedValue result = FastRuntimeStub::GetPropertyByName(thread, receiver, key);
auto *getPropertyByNamePtr = reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, JSTaggedValue)>(
thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName)));
JSTaggedValue result = getPropertyByNamePtr(thread, receiver, key);
if (result.IsHole()) {
return JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(thread, receiver),
JSHandle<JSTaggedValue>(thread, key))
@ -681,7 +686,10 @@ template<bool UseHole> // UseHole is only for Array::Sort() which requires Hole
JSTaggedValue FastRuntimeStub::FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index)
{
INTERPRETER_TRACE(thread, FastGetPropertyByIndex);
JSTaggedValue result = GetPropertyByIndex(thread, receiver, index);
auto getPropertyByIndex = reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, uint32_t)>(
thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex)));
JSTaggedValue result = getPropertyByIndex(thread, receiver, index);
if (result.IsHole() && !UseHole) {
return JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(thread, receiver), index)
.GetValue()

View File

@ -16,6 +16,7 @@
#ifndef ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_H
#define ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_H
#include <memory>
#include "ecmascript/js_tagged_value.h"
namespace panda::ecmascript {
@ -24,6 +25,7 @@ class PropertyAttributes;
class FastRuntimeStub {
public:
using Address = uintptr_t;
/* -------------- Common API Begin, Don't change those interface!!! ----------------- */
static inline JSTaggedValue FastAdd(JSTaggedValue left, JSTaggedValue right);
static inline JSTaggedValue FastSub(JSTaggedValue left, JSTaggedValue right);

View File

@ -2439,7 +2439,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool
JSTaggedValue receiver = GET_VREG_VALUE(v0);
// fast path
if (LIKELY(receiver.IsHeapObject())) {
JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, receiver, idx);
auto getPropertyByIndex = reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, uint32_t)>(
thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByIndex)));
JSTaggedValue res = getPropertyByIndex(thread, receiver, idx);
if (!res.IsHole()) {
INTERPRETER_RETURN_IF_ABRUPT(res);
SET_ACC(res);
@ -2464,7 +2466,10 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool
SAVE_ACC();
JSTaggedValue value = GET_ACC();
// fast path
JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex(thread, receiver, index, value);
auto *setPropertyByIndex = \
reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, uint32_t, JSTaggedValue)> \
(reinterpret_cast<uintptr_t>(thread->GetFastStubEntry(FAST_STUB_ID(SetPropertyByIndex))));
JSTaggedValue res = setPropertyByIndex(thread, receiver, index, value);
if (!res.IsHole()) {
INTERPRETER_RETURN_IF_ABRUPT(res);
RESTORE_ACC();
@ -2887,7 +2892,9 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool
if (LIKELY(receiver.IsHeapObject())) {
// fast path
JSTaggedValue res = FastRuntimeStub::GetPropertyByName(thread, receiver, propKey);
auto *getPropertyByNamePtr = reinterpret_cast<JSTaggedValue (*)(JSThread *, JSTaggedValue, JSTaggedValue)>(
thread->GetFastStubEntry(FAST_STUB_ID(GetPropertyByName)));
JSTaggedValue res = getPropertyByNamePtr(thread, receiver, propKey);
if (!res.IsHole()) {
ASSERT(!res.IsAccessor());
INTERPRETER_RETURN_IF_ABRUPT(res);

View File

@ -170,6 +170,14 @@ public:
return fastStubEntires_[id];
}
void SetFastStubEntry(uint32_t id, Address entry)
{
ASSERT(id < kungfu::FAST_STUB_MAXCOUNT);
fastStubEntires_[id] = entry;
}
void InitializeFastRuntimeStubs();
void LoadFastStubModule(const char *moduleFile);
static uint32_t GetRuntimeFunctionsOffset()

View File

@ -149,4 +149,11 @@ double RuntimeTrampolines::FloatMod(double left, double right)
{
return std::fmod(left, right);
}
uint64_t RuntimeTrampolines::NewInternalString(uint64_t argThread, uint64_t argKey)
{
auto thread = reinterpret_cast<JSThread *>(argThread);
JSHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue(reinterpret_cast<TaggedObject *>(argKey)));
return JSTaggedValue(thread->GetEcmaVM()->GetFactory()->InternString(keyHandle)).GetRawData();
}
} // namespace panda::ecmascript

View File

@ -50,6 +50,7 @@ public:
static uint32_t StringGetHashCode(uint64_t ecmaString);
static uint64_t Execute(uint64_t argThread, uint64_t argFunc, uint64_t thisArg, uint32_t argc, uint64_t argArgv);
static double FloatMod(double left, double right);
static uint64_t NewInternalString(uint64_t argThread, uint64_t argKey);
};
class CallRuntimeTrampolinesScope {