Avoid Sendable's DropFrame

Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IALL34

Signed-off-by: hanweiqi <hanweiqi3@huawei.com>
This commit is contained in:
hanweiqi 2024-08-21 18:52:28 +08:00
parent f87fd7f329
commit 401c33fd0a
5 changed files with 98 additions and 30 deletions

View File

@ -1300,6 +1300,11 @@ bool DebuggerApi::CheckPromiseQueueSize(const EcmaVM *ecmaVm)
return queueSizeEntry == queueSizeCurrent;
}
bool DebuggerApi::CheckIsSendableMethod(const EcmaVM *ecmaVm)
{
auto *debuggerMgr = ecmaVm->GetJsDebuggerManager();
return debuggerMgr->CheckIsSendableMethod();
}
bool DebuggerApi::IsMainThread()
{
return JSThread::IsMainThread();

View File

@ -197,6 +197,7 @@ public:
Global<MapRef> internalObjects);
static bool CheckPromiseQueueSize(const EcmaVM *ecmaVm);
static bool CheckIsSendableMethod(const EcmaVM *ecmaVm);
static bool IsMainThread();
static void DropLastFrame(const EcmaVM *ecmaVm);
};

View File

@ -72,48 +72,62 @@ std::pair<uint16_t, uint16_t> DropframeManager::ReadStlexvarParams(const uint8_t
void DropframeManager::MethodEntry(JSThread *thread, JSHandle<Method> method, JSHandle<JSTaggedValue> envHandle)
{
std::set<std::pair<uint16_t, uint16_t>> modifiedLexVarPos;
NewLexModifyRecordLevel();
const JSPandaFile* methodJsPandaFile = method->GetJSPandaFile();
panda_file::File::EntityId methodId = method->GetMethodId();
PushMethodInfo(std::make_tuple(const_cast<JSPandaFile *>(methodJsPandaFile), methodId));
if (!envHandle->IsLexicalEnv()) {
if (method->IsSendableMethod()) {
PushMethodType(MethodType::SENDABLE_METHOD);
return;
}
NewLexModifyRecordLevel();
PushPromiseQueueSizeRecord(thread);
if (!envHandle->IsLexicalEnv()) {
PushMethodType(MethodType::OTHER_METHOD);
return;
}
PushMethodType(MethodType::NORMAL_METHOD);
uint32_t codeSize = method->GetCodeSize();
uint16_t newEnvCount = 0;
auto bcIns = BytecodeInstruction(method->GetBytecodeArray());
auto bcInsLast = bcIns.JumpTo(codeSize);
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
BytecodeInstruction::Opcode op = bcIns.GetOpcode();
if (IsNewlexenvOpcode(op)) {
newEnvCount++;
} else if (IsStlexvarOpcode(op)) {
std::pair<uint16_t, uint16_t> lexVarPos = ReadStlexvarParams(bcIns.GetAddress(), op);
uint16_t level;
uint16_t slot;
std::tie(level, slot) = lexVarPos;
JSTaggedValue env = envHandle.GetTaggedValue();
for (uint16_t i = 0; ; i++) {
if ((level < newEnvCount || i >= level - newEnvCount) &&
slot < LexicalEnv::Cast(env.GetTaggedObject())->GetLength() - LexicalEnv::RESERVED_ENV_LENGTH &&
!modifiedLexVarPos.count({i, slot})) {
JSTaggedValue value = LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot);
EmplaceLexModifyRecord(thread, env, slot, value);
modifiedLexVarPos.insert({i, slot});
}
if (i >= level) {
break;
}
JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
if (!taggedParentEnv.IsLexicalEnv()) {
break;
}
env = taggedParentEnv;
}
}
AddLexPropertiesToRecord(thread, bcIns, newEnvCount, modifiedLexVarPos, envHandle);
bcIns = bcIns.GetNext();
}
PushPromiseQueueSizeRecord(thread);
}
void DropframeManager::AddLexPropertiesToRecord(JSThread *thread, BytecodeInstruction &bcIns, uint16_t &newEnvCount,
std::set<std::pair<uint16_t, uint16_t>> &modifiedLexVarPos, JSHandle<JSTaggedValue> envHandle)
{
BytecodeInstruction::Opcode op = bcIns.GetOpcode();
if (IsNewlexenvOpcode(op)) {
newEnvCount++;
return;
}
if (IsStlexvarOpcode(op)) {
std::pair<uint16_t, uint16_t> lexVarPos = ReadStlexvarParams(bcIns.GetAddress(), op);
uint16_t level;
uint16_t slot;
std::tie(level, slot) = lexVarPos;
JSTaggedValue env = envHandle.GetTaggedValue();
for (uint16_t i = 0; ; i++) {
if ((level < newEnvCount || i >= level - newEnvCount) &&
slot < LexicalEnv::Cast(env.GetTaggedObject())->GetLength() - LexicalEnv::RESERVED_ENV_LENGTH &&
!modifiedLexVarPos.count({i, slot})) {
JSTaggedValue value = LexicalEnv::Cast(env.GetTaggedObject())->GetProperties(slot);
EmplaceLexModifyRecord(thread, env, slot, value);
modifiedLexVarPos.insert({i, slot});
}
if (i >= level) {
break;
}
JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetTaggedObject())->GetParentEnv();
if (!taggedParentEnv.IsLexicalEnv()) {
break;
}
env = taggedParentEnv;
}
}
}
void DropframeManager::MethodExit(JSThread *thread, [[maybe_unused]] JSHandle<Method> method)
@ -124,6 +138,11 @@ void DropframeManager::MethodExit(JSThread *thread, [[maybe_unused]] JSHandle<Me
return;
}
PopMethodInfo();
if (CheckIsSendableMethod()) {
PopMethodType();
return;
}
PopMethodType();
MergeLexModifyRecordOfTopFrame(thread);
PopPromiseQueueSizeRecord();
}
@ -142,6 +161,7 @@ void DropframeManager::DropLastFrame(JSThread *thread)
LexicalEnv::Cast(env.GetTaggedObject())->SetProperties(thread, slot, valueHandle.GetTaggedValue());
}
PopMethodInfo();
PopMethodType();
RemoveLexModifyRecordOfTopFrame(thread);
PopPromiseQueueSizeRecord();
@ -226,6 +246,11 @@ void DropframeManager::MergeLexModifyRecordOfTopFrame(JSThread *thread)
std::vector<std::tuple<JSHandle<JSTaggedValue>, uint16_t, JSHandle<JSTaggedValue>>> lexModifyRecord;
lexModifyRecord = modifiedLexVar_.top();
modifiedLexVar_.pop();
if (!modifiedLexVar_.empty() && modifiedLexVar_.top().empty()) {
modifiedLexVar_.pop();
modifiedLexVar_.push(lexModifyRecord);
return;
}
for (const auto &item : lexModifyRecord) {
JSHandle<JSTaggedValue> envHandle;
uint16_t slot;
@ -295,4 +320,22 @@ void DropframeManager::PopMethodInfo()
methodInfo_.pop();
}
}
void DropframeManager::PushMethodType(MethodType methodType)
{
methodType_.push(methodType);
}
bool DropframeManager::CheckIsSendableMethod()
{
ASSERT(!methodType_.empty());
return methodType_.top() == MethodType::SENDABLE_METHOD;
}
void DropframeManager::PopMethodType()
{
if (!methodType_.empty()) {
methodType_.pop();
}
}
}

View File

@ -22,6 +22,12 @@
#include "libpandafile/bytecode_instruction.h"
namespace panda::ecmascript::tooling {
enum class MethodType : uint8_t {
OTHER_METHOD = 0,
NORMAL_METHOD,
SENDABLE_METHOD
};
class DropframeManager {
public:
DropframeManager() = default;
@ -33,6 +39,7 @@ public:
void MethodExit(JSThread *thread, JSHandle<Method> method);
void DropLastFrame(JSThread *thread);
uint32_t GetPromiseQueueSizeRecordOfTopFrame();
bool CheckIsSendableMethod();
private:
bool IsNewlexenvOpcode(BytecodeInstruction::Opcode op);
bool IsStlexvarOpcode(BytecodeInstruction::Opcode op);
@ -52,8 +59,15 @@ private:
bool CheckExitMethodInfo(std::tuple<JSPandaFile*, panda_file::File::EntityId> methodInfo);
void PopMethodInfo();
void PushMethodType(MethodType methodType);
void PopMethodType();
void AddLexPropertiesToRecord(JSThread *thread, BytecodeInstruction &bcIns, uint16_t &newEnvCount,
std::set<std::pair<uint16_t, uint16_t>> &modifiedLexVarPos, JSHandle<JSTaggedValue> envHandle);
std::stack<std::vector<std::tuple<JSHandle<JSTaggedValue>, uint16_t, JSHandle<JSTaggedValue>>>> modifiedLexVar_;
std::stack<uint32_t> promiseQueueSizeRecord_;
std::stack<MethodType> methodType_;
std::stack<std::tuple<JSPandaFile*, panda_file::File::EntityId>> methodInfo_;
};
}

View File

@ -206,6 +206,11 @@ public:
return dropframeManager_.GetPromiseQueueSizeRecordOfTopFrame();
}
bool CheckIsSendableMethod()
{
return dropframeManager_.CheckIsSendableMethod();
}
void EnableObjectHashDisplay()
{
isObjHashDisplayEnabled_ = true;