[JIT] Fix cancel jit task and visit machinecode

Fixed bind jit task with thread id, may cancel failed when mutli jsthread bind one pthread
Add lock in sweep machinecode space and iterate machinecode obj
Disallow alloc string when across gc point

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IALVNG
Change-Id: Ic857714ce92b5a9d504d85d869db537abe4f8bed
Signed-off-by: xiaoweidong <xiaoweidong@huawei.com>
This commit is contained in:
xiaoweidong 2024-08-22 15:12:15 +08:00
parent 5be332038b
commit 847f22baa8
18 changed files with 139 additions and 25 deletions

View File

@ -105,7 +105,8 @@ panda_file::File::EntityId AOTCompilationEnv::GetIdFromCache(JSTaggedValue const
return ConstantPool::GetIdFromCache(constpool, index);
}
JSTaggedValue AOTCompilationEnv::GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const
JSTaggedValue AOTCompilationEnv::GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx,
[[maybe_unused]] bool allowAlloc) const
{
return ptManager_->GetStringFromConstantPool(methodOffset, cpIdx);
}

View File

@ -56,7 +56,8 @@ public:
// GlobalConstants
const GlobalEnvConstants *GlobalConstants() const override;
JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const override;
JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx,
bool allowAlloc = true) const override;
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_COMPILER_AOT_COMPILATION_ENV_H

View File

@ -81,7 +81,8 @@ public:
virtual JSTaggedValue GetObjectLiteralFromCache(JSTaggedValue constpool, uint32_t index, CString entry) const = 0;
virtual JSTaggedValue GetMethodFromCache(JSTaggedValue constpool, uint32_t index) const = 0;
virtual panda_file::File::EntityId GetIdFromCache(JSTaggedValue constpool, uint32_t index) const = 0;
virtual JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const = 0;
virtual JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx,
bool allowAlloc = true) const = 0;
// GlobalEnv
virtual JSHandle<GlobalEnv> GetGlobalEnv() const = 0;

View File

@ -170,13 +170,13 @@ const GlobalEnvConstants *JitCompilationEnv::GlobalConstants() const
}
JSTaggedValue JitCompilationEnv::GetStringFromConstantPool([[maybe_unused]] const uint32_t methodOffset,
const uint16_t cpIdx) const
const uint16_t cpIdx, bool allowAlloc) const
{
JSTaggedValue constpool = GetConstantPoolByMethodOffset(methodOffset);
if (constpool.IsUndefined()) {
return JSTaggedValue::Undefined();
}
return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx);
return ConstantPool::GetStringFromCacheForJit(GetJSThread(), constpool, cpIdx, allowAlloc);
}
JSFunction *JitCompilationEnv::GetJsFunctionByMethodOffset(uint32_t methodOffset) const

View File

@ -58,7 +58,8 @@ public:
// GlobalConstants
const GlobalEnvConstants *GlobalConstants() const override;
JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx) const override;
JSTaggedValue GetStringFromConstantPool(const uint32_t methodOffset, const uint16_t cpIdx,
bool allowAlloc = true) const override;
JSThread *GetHostThread() const override
{

View File

@ -98,7 +98,11 @@ GateRef TSHCROptPass::ConvertStringEqualToConst(GateRef left, GateRef right)
auto leftMethodOffset = acc_.TryGetMethodOffset(left);
auto rightMethodOffset = acc_.TryGetMethodOffset(right);
JSTaggedValue leftStr = GetStringFromConstantPool(leftMethodOffset, leftId);
JSTaggedValue rightStr = GetStringFromConstantPool(rightMethodOffset, rightId);
// jit: disallow alloc jsstring, across gc point
JSTaggedValue rightStr = GetStringFromConstantPool(rightMethodOffset, rightId, false);
if (leftStr == JSTaggedValue::Undefined() || rightStr == JSTaggedValue::Undefined()) {
return Circuit::NullGate();
}
if (leftStr == rightStr) {
return builder_.Boolean(true);
}

View File

@ -63,9 +63,9 @@ private:
return methodName_;
}
JSTaggedValue GetStringFromConstantPool(uint32_t methodOffset, uint32_t cpIdx) const
JSTaggedValue GetStringFromConstantPool(uint32_t methodOffset, uint32_t cpIdx, bool allowAlloc = true) const
{
return compilationEnv_->GetStringFromConstantPool(methodOffset, cpIdx);
return compilationEnv_->GetStringFromConstantPool(methodOffset, cpIdx, allowAlloc);
}
GateRef VisitTypedBinaryOp(GateRef gate);

View File

@ -471,7 +471,7 @@ void Jit::Compile(EcmaVM *vm, JSHandle<JSFunction> &jsFunction, CompilerTier tie
void Jit::RequestInstallCode(std::shared_ptr<JitTask> jitTask)
{
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[jitTask->GetTaskThreadId()];
ThreadTaskInfo &info = threadTaskInfo_[jitTask->GetHostThread()];
if (info.skipInstallTask_) {
return;
}
@ -531,15 +531,15 @@ uint32_t Jit::GetRunningTaskCnt(EcmaVM *vm)
}
});
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()->GetThreadId()];
ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()];
auto &taskQueue = info.installJitTasks_;
return taskQueue.size() + cnt;
}
void Jit::InstallTasks(uint32_t threadId)
void Jit::InstallTasks(JSThread *jsThread)
{
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[threadId];
ThreadTaskInfo &info = threadTaskInfo_[jsThread];
auto &taskQueue = info.installJitTasks_;
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, ConvertToStdString("Jit::InstallTasks count:" + ToCString(taskQueue.size())));
@ -608,7 +608,7 @@ void Jit::ClearTaskWithVm(EcmaVM *vm)
{
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()->GetThreadId()];
ThreadTaskInfo &info = threadTaskInfo_[vm->GetJSThread()];
info.skipInstallTask_ = true;
auto &taskQueue = info.installJitTasks_;
taskQueue.clear();
@ -622,14 +622,14 @@ void Jit::ClearTaskWithVm(EcmaVM *vm)
void Jit::IncJitTaskCnt(JSThread *thread)
{
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[thread->GetThreadId()];
ThreadTaskInfo &info = threadTaskInfo_[thread];
info.jitTaskCnt_.fetch_add(1);
}
void Jit::DecJitTaskCnt(JSThread *thread)
{
LockHolder holder(threadTaskInfoLock_);
ThreadTaskInfo &info = threadTaskInfo_[thread->GetThreadId()];
ThreadTaskInfo &info = threadTaskInfo_[thread];
uint32_t old = info.jitTaskCnt_.fetch_sub(1);
if (old == 1) {
info.jitTaskCntCv_.Signal();

View File

@ -81,7 +81,7 @@ public:
int JitVerifyAndCopy(void *codeSigner, void *jit_memory, void *tmpBuffer, int size);
void RequestInstallCode(std::shared_ptr<JitTask> jitTask);
void InstallTasks(uint32_t threadId);
void InstallTasks(JSThread *jsThread);
void ClearTask(const std::function<bool(Task *task)> &checkClear);
void ClearTask(EcmaContext *ecmaContext);
void ClearTaskWithVm(EcmaVM *vm);
@ -240,7 +240,7 @@ private:
std::string bundleName_;
bool isEnableAppPGO_ { true };
std::unordered_map<uint32_t, ThreadTaskInfo> threadTaskInfo_;
std::unordered_map<JSThread*, ThreadTaskInfo> threadTaskInfo_;
RecursiveMutex threadTaskInfoLock_;
bool isEnableJitFort_ { true };
bool isDisableCodeSign_ { true };

View File

@ -795,7 +795,7 @@ bool JSThread::CheckSafepoint()
vmThreadControl_->SuspendVM();
}
if (HasInstallMachineCode()) {
vm_->GetJit()->InstallTasks(GetThreadId());
vm_->GetJit()->InstallTasks(this);
SetInstallMachineCode(false);
}

View File

@ -72,10 +72,14 @@ JSHandle<TaggedArray> ConstantPool::GetFieldLiteral(JSThread *thread, JSHandle<C
return literalArray;
}
JSTaggedValue ConstantPool::GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index)
JSTaggedValue ConstantPool::GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index,
bool allowAlloc)
{
const ConstantPool *taggedPool = ConstantPool::Cast(constpool.GetTaggedObject());
auto val = taggedPool->Get(index);
if (!allowAlloc && val.IsHole()) {
return JSTaggedValue::Undefined();
}
if (val.IsHole()) {
JSPandaFile *jsPandaFile = taggedPool->GetJSPandaFile();
panda_file::File::EntityId id = taggedPool->GetEntityId(index);

View File

@ -668,7 +668,8 @@ public:
return GetLiteralFromCache<type>(thread, constpool, index, entry);
}
static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index);
static JSTaggedValue PUBLIC_API GetStringFromCacheForJit(JSThread *thread, JSTaggedValue constpool, uint32_t index,
bool allowAlloc = true);
static JSTaggedValue PUBLIC_API GetStringFromCache(JSThread *thread, JSTaggedValue constpool, uint32_t index);

View File

@ -654,7 +654,6 @@ uintptr_t MachineCodeSpace::JitFortAllocate(MachineCodeDesc *desc)
// Record info on JitFort mem allocated to live MachineCode objects
void MachineCodeSpace::FreeRegion(Region *current, bool isMain)
{
LockHolder holder(freeRegionMutex_);
LOG_JIT(DEBUG) << "MachineCodeSpace FreeRegion: " << current << " isMain " << isMain;
uintptr_t freeStart = current->GetBegin();
current->IterateAllMarkedBits([this, &current, &freeStart, isMain](void *mem) {
@ -679,6 +678,23 @@ void MachineCodeSpace::FreeRegion(Region *current, bool isMain)
}
}
void MachineCodeSpace::AsyncSweep(bool isMain)
{
LockHolder holder(asyncSweepMutex_);
Region *current = GetSweepingRegionSafe();
while (current != nullptr) {
FreeRegion(current, isMain);
// Main thread sweeping region is added;
if (!isMain) {
AddSweptRegionSafe(current);
} else {
current->MergeOldToNewRSetForCS();
current->MergeLocalToShareRSetForCS();
}
current = GetSweepingRegionSafe();
}
}
uintptr_t MachineCodeSpace::Allocate(size_t size, bool allowGC)
{
return SparseSpace::Allocate(size, allowGC);
@ -742,7 +758,7 @@ size_t MachineCodeSpace::CheckMachineCodeObject(uintptr_t curPtr, uintptr_t &mac
uintptr_t MachineCodeSpace::GetMachineCodeObject(uintptr_t pc)
{
uintptr_t machineCode = 0;
LockHolder holder(freeRegionMutex_);
LockHolder holder(asyncSweepMutex_);
allocator_->FillBumpPointer();
EnumerateRegions([&](Region *region) {

View File

@ -70,7 +70,7 @@ public:
// For sweeping
void PrepareSweeping();
void Sweep();
void AsyncSweep(bool isMain);
virtual void AsyncSweep(bool isMain);
bool TryFillSweptRegion();
// Ensure All region finished sweeping
@ -273,6 +273,7 @@ public:
NO_MOVE_SEMANTIC(MachineCodeSpace); // Note: Expand() left for define
uintptr_t GetMachineCodeObject(uintptr_t pc);
size_t CheckMachineCodeObject(uintptr_t curPtr, uintptr_t &machineCode, uintptr_t pc);
void AsyncSweep(bool isMain) override;
void FreeRegion(Region *current, bool isMain = true) override;
uintptr_t Allocate(size_t size, bool allowGC = true);
uintptr_t Allocate(size_t size, MachineCodeDesc *desc, bool allowGC = true);
@ -306,7 +307,7 @@ public:
private:
JitFort *jitFort_ {nullptr};
Mutex freeRegionMutex_;
Mutex asyncSweepMutex_;
friend class Heap;
friend class ConcurrentSweeper;
};

View File

@ -30,6 +30,7 @@ group("ark_jit_ts_test") {
"ts_inline",
"proxy_fast_call",
"fuzz_exception",
"throw_error",
]
deps = [ "pgo_roottype_test:pgo_roottype_test" ]

View File

@ -0,0 +1,18 @@
# Copyright (c) 2024 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_jit_test_action("throw_error") {
deps = []
}

View File

@ -0,0 +1,14 @@
# Copyright (c) 2024 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.
60

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 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.
*/
let catchcnt = 0;
function ThrowFunc() {
try {
throw new Error("error");
} catch (e) {
catchcnt++;
}
}
function CallThrowFunc() {
ThrowFunc();
let arr = [];
for(var i = 0; i < 10; i++){
arr.push('CallThrowFunc')
}
for(var i = 0; i < 10; i++){
arr.push('push............')
}
ThrowFunc();
}
function Test() {
CallThrowFunc();
}
for (let i = 0; i < 10; i++) {
Test();
}
ArkTools.jitCompileAsync(Test);
var ret = ArkTools.waitJitCompileFinish(Test);
for (let i = 0; i < 20; i++) {
Test();
ArkTools.gc(0);
}
print(catchcnt);