Fix aot flags mismatch when new method by aot methodLiteral in interp

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9711X?from=project-issue
Signed-off-by: zhangyukun8 <zhangyukun8@huawei.com>
Change-Id: I8431de2f73dd4f7f59f48577214b7d981da0a9e7
This commit is contained in:
zhangyukun8 2024-03-08 18:34:02 +08:00
parent d1160fcf35
commit 629899bb1f
12 changed files with 78 additions and 22 deletions

View File

@ -405,6 +405,38 @@ JSTaggedValue BuiltinsArkTools::IsAOTDeoptimized(EcmaRuntimeCallInfo *info)
return JSTaggedValue(false);
}
JSTaggedValue BuiltinsArkTools::CheckDeoptStatus(EcmaRuntimeCallInfo *info)
{
ASSERT(info);
JSThread *thread = info->GetThread();
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<JSTaggedValue> obj = GetCallArg(info, 0);
JSHandle<JSFunction> func(thread, obj.GetTaggedValue());
Method *method = func->GetCallTarget();
bool isAotCompiled = method->IsAotWithCallField();
uint16_t threshold = method->GetDeoptThreshold();
if (threshold > 0) {
return JSTaggedValue(isAotCompiled);
}
// check status before deopt
JSHandle<JSTaggedValue> hasDeopt = GetCallArg(info, 1);
if (hasDeopt->IsFalse()) {
return JSTaggedValue(!isAotCompiled);
}
if (!hasDeopt->IsTrue()) {
return JSTaggedValue(false);
}
// check status after deopt
if (isAotCompiled ||
method->IsFastCall() ||
method->GetDeoptType() != kungfu::DeoptType::NOTCHECK ||
method->GetCodeEntryOrLiteral() == 0) {
return JSTaggedValue(false);
}
return JSTaggedValue(true);
}
JSTaggedValue BuiltinsArkTools::PrintTypedOpProfilerAndReset(EcmaRuntimeCallInfo *info)
{
ASSERT(info);

View File

@ -48,6 +48,7 @@
V("isAOTDeoptimized", IsAOTDeoptimized, 1, INVALID) \
V("printTypedOpProfilerAndReset", PrintTypedOpProfilerAndReset, 1, INVALID) \
V("isOnHeap", IsOnHeap, 1, INVALID) \
V("checkDeoptStatus", CheckDeoptStatus, 2, INVALID) \
V("checkCircularImport", CheckCircularImport, 2, INVALID)
#define BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \
@ -187,6 +188,9 @@ public:
// ArkTools.isAOTCompiledAssert(func)
static JSTaggedValue IsAOTDeoptimized(EcmaRuntimeCallInfo *info);
// ArkTools.CheckDeoptStatus(func, deopt?)
static JSTaggedValue CheckDeoptStatus(EcmaRuntimeCallInfo *info);
// ArkTools.isOnHeap(object)
static JSTaggedValue IsOnHeap(EcmaRuntimeCallInfo *info);

View File

@ -281,7 +281,7 @@ void AOTFileManager::SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JS
mainMethod->SetNativeBit(false);
Method *method = mainFunc->GetCallTarget();
method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
method->SetCodeEntryAndMarkAOT(static_cast<uintptr_t>(mainEntry));
method->SetCodeEntryAndMarkAOTWhenBinding(static_cast<uintptr_t>(mainEntry));
method->SetIsFastCall(isFastCall);
#ifndef NDEBUG
PrintAOTEntry(jsPandaFile, method, mainEntry);
@ -307,7 +307,7 @@ void AOTFileManager::SetAOTFuncEntry(const JSPandaFile *jsPandaFile, Method *met
return;
}
method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
method->SetCodeEntryAndMarkAOT(codeEntry);
method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry);
method->SetIsFastCall(entry.isFastCall_);
if (canFastCall != nullptr) {
*canFastCall = entry.isFastCall_;

View File

@ -534,7 +534,7 @@ void Deoptimizier::UpdateAndDumpDeoptInfo(kungfu::DeoptType type)
method->SetDeoptType(type);
method->SetDeoptThreshold(--deoptThreshold);
} else {
method->ClearAOTFlags();
method->ClearAOTStatusWhenDeopt();
if (method->GetMachineCode() != JSTaggedValue::Undefined()) {
method->SetMachineCode(thread_, JSTaggedValue::Undefined());
}

View File

@ -1337,7 +1337,7 @@ JSHandle<JSTaggedValue> JSDeserializer::ReadMethod()
if (!ReadNativePointer(&codeEntry)) {
return JSHandle<JSTaggedValue>();
}
method->SetCodeEntryAndMarkAOT(codeEntry);
method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry);
uint8_t deoptThreshold = thread_->GetEcmaVM()->GetJSOptions().GetDeoptThreshold();
method->SetDeoptThreshold(deoptThreshold);

View File

@ -125,11 +125,33 @@ const JSTaggedValue Method::GetRecordName() const
void Method::SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall)
{
ASSERT(codeEntry != 0);
SetCodeEntryAndMarkAOT(codeEntry);
SetCodeEntryAndMarkAOTWhenBinding(codeEntry);
SetIsFastCall(isFastCall);
MethodLiteral *methodLiteral = GetMethodLiteral();
methodLiteral->SetAotCodeBit(true);
methodLiteral->SetIsFastCall(isFastCall);
}
void Method::SetCodeEntryAndMarkAOTWhenBinding(uintptr_t codeEntry)
{
SetAotCodeBit(true);
SetNativeBit(false);
SetCodeEntryOrLiteral(codeEntry);
}
void Method::ClearAOTStatusWhenDeopt()
{
ClearAOTFlagsWhenInit();
SetDeoptType(kungfu::DeoptType::NOTCHECK);
const JSPandaFile *jsPandaFile = GetJSPandaFile();
MethodLiteral *methodLiteral = jsPandaFile->FindMethodLiteral(GetMethodId().GetOffset());
SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(methodLiteral));
}
void Method::ClearAOTFlagsWhenInit()
{
SetAotCodeBit(false);
SetIsFastCall(false);
}
} // namespace panda::ecmascript

View File

@ -386,20 +386,11 @@ public:
}
// add for AOT
void SetCodeEntryAndMarkAOT(uintptr_t codeEntry)
{
SetAotCodeBit(true);
SetNativeBit(false);
SetCodeEntryOrLiteral(codeEntry);
}
void SetCodeEntryAndMarkAOTWhenBinding(uintptr_t codeEntry);
void ClearAOTFlags()
{
SetAotCodeBit(false);
SetIsFastCall(false);
SetDeoptType(kungfu::DeoptType::NOTCHECK);
SetCodeEntryOrLiteral(reinterpret_cast<uintptr_t>(nullptr));
}
void ClearAOTStatusWhenDeopt();
void ClearAOTFlagsWhenInit();
void SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall);

View File

@ -1840,6 +1840,8 @@ JSHandle<Method> ObjectFactory::NewMethod(const JSPandaFile *jsPandaFile, Method
if (needSetAotFlag) {
thread_->GetEcmaVM()->GetAOTFileManager()->
SetAOTFuncEntry(jsPandaFile, *method, entryIndex, canFastCall);
} else {
method->ClearAOTFlagsWhenInit();
}
return method;
}

View File

@ -3025,7 +3025,7 @@ void RuntimeStubs::SaveFrameToContext(JSThread *thread, JSHandle<GeneratorContex
JSTaggedValue function = frameHandler.GetFunction();
Method *method = JSFunction::Cast(function.GetTaggedObject())->GetCallTarget();
if (method->IsAotWithCallField()) {
method->ClearAOTFlags();
method->ClearAOTStatusWhenDeopt();
}
context->SetMethod(thread, function);
context->SetThis(thread, frameHandler.GetThis());

View File

@ -1957,7 +1957,7 @@ HWTEST_F_L0(JSSerializerTest, SerializeAOTMethod)
method->SetConstantPool(thread, constPool.GetTaggedValue());
uintptr_t codeEntry = 0x1234;
method->SetCodeEntryAndMarkAOT(codeEntry);
method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry);
JSSerializer *serializer = new JSSerializer(thread);
bool success = serializer->SerializeJSTaggedValue(JSHandle<JSTaggedValue>::Cast(method));

View File

@ -15,4 +15,5 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_assert_test_action("deopt") {
deps = []
is_only_typed_path = true
}

View File

@ -19,9 +19,13 @@ function tryHello(v: number): void {
let ret: number = a + v;
assert_equal(ret, "1a");
}
assert_equal(ArkTools.checkDeoptStatus(tryHello, false), true);
tryHello(<number><Object>'a');
assert_equal(ArkTools.checkDeoptStatus(tryHello, true), true);
for (let i = 0; i < 25; i++) {
tryHello(<number><Object>'a');
}
assert_equal(ArkTools.checkDeoptStatus(tryHello, true), true);
function tryIf(v: number, b: number): void {
let a : number = 1;