Support Lazy Import

Issue: https://e.gitee.com/open_harmony/dashboard?issue=IAARFN

Signed-off-by: yaochaonan <yaochaonan@huawei.com>
Change-Id: I8ccd39ba22d71827eb93699d560165beb9d12ba9
This commit is contained in:
yaochaonan 2024-07-10 00:41:17 +08:00
parent d3c47b0080
commit 28325725ac
46 changed files with 858 additions and 32 deletions

View File

@ -5619,5 +5619,25 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM
{
(void)bytecodeArray;
}
BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8)
{
(void)bytecodeArray;
}
BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16)
{
(void)bytecodeArray;
}
BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8)
{
(void)bytecodeArray;
}
BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16)
{
(void)bytecodeArray;
}
#undef LOG_INST
} // namespace panda::ecmascript::kungfu

View File

@ -392,7 +392,11 @@ namespace panda::ecmascript::kungfu {
T(HandleCallRuntimeLdSendableVarImm8Imm8) \
T(HandleCallRuntimeLdSendableVarImm16Imm16) \
T(HandleCallRuntimeIstruePrefImm8) \
T(HandleCallRuntimeIsfalsePrefImm8)
T(HandleCallRuntimeIsfalsePrefImm8) \
T(HandleCallRuntimeLdLazyModuleVarPrefImm8) \
T(HandleCallRuntimeWideLdLazyModuleVarPrefImm16) \
T(HandleCallRuntimeLdLazySendableModuleVarPrefImm8) \
T(HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16)
#define ASM_INTERPRETER_BC_HELPER_STUB_LIST(V) \
V(SingleStepDebugging) \

View File

@ -478,6 +478,10 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16:
case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8:
case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16:
case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8:
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16:
case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8:
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16:
flags |= BytecodeFlags::READ_FUNC;
break;
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
@ -1236,6 +1240,26 @@ void BytecodeInfo::InitBytecodeInfo(BytecodeCircuitBuilder *builder,
info.inputs.emplace_back(Immediate(index));
break;
}
case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: {
int32_t index = READ_INST_8_1();
info.inputs.emplace_back(Immediate(index));
break;
}
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: {
int32_t index = READ_INST_16_1();
info.inputs.emplace_back(Immediate(index));
break;
}
case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: {
int32_t index = READ_INST_8_1();
info.inputs.emplace_back(Immediate(index));
break;
}
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: {
int32_t index = READ_INST_16_1();
info.inputs.emplace_back(Immediate(index));
break;
}
case EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16: {
uint16_t stringId = READ_INST_16_2();
info.inputs.emplace_back(ConstDataId(ConstDataIDType::StringIDType, stringId));

View File

@ -291,7 +291,7 @@ public:
static constexpr uint32_t LAST_THROW_OPCODE =
static_cast<uint32_t>(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16);
static constexpr uint32_t LAST_CALLRUNTIME_OPCODE =
static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8);
static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16);
static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX ==
static_cast<uint32_t>(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE));

View File

@ -340,6 +340,10 @@ namespace panda::ecmascript::kungfu {
V(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16) \
V(CALLRUNTIME_ISTRUE_PREF_IMM8) \
V(CALLRUNTIME_ISFALSE_PREF_IMM8) \
V(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8) \
V(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16) \
V(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8) \
V(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16) \
inline std::string GetEcmaOpcodeStr(EcmaOpcode opcode)
{

View File

@ -5881,6 +5881,85 @@ DECLARE_ASM_HANDLER(HandleCallRuntimeLdSendableVarImm16Imm16)
DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16);
}
DECLARE_ASM_HANDLER(HandleCallRuntimeLdLazyModuleVarPrefImm8)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined());
GateRef index = ReadInst8_1(pc);
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazyExternalModuleVarByIndex), { Int8ToTaggedInt(index), currentFunc });
auto env = GetEnvironment();
Label notException(env);
CHECK_EXCEPTION_WITH_JUMP(*moduleRef, &notException);
Bind(&notException);
{
varAcc = *moduleRef;
DISPATCH_WITH_ACC(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8);
}
}
DECLARE_ASM_HANDLER(HandleCallRuntimeWideLdLazyModuleVarPrefImm16)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined());
GateRef index = ReadInst16_1(pc);
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazyExternalModuleVarByIndex), { Int16ToTaggedInt(index), currentFunc });
auto env = GetEnvironment();
Label notException(env);
CHECK_EXCEPTION_WITH_JUMP(*moduleRef, &notException);
Bind(&notException);
{
varAcc = *moduleRef;
DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16);
}
}
DECLARE_ASM_HANDLER(HandleCallRuntimeLdLazySendableModuleVarPrefImm8)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined());
GateRef index = ReadInst8_1(pc);
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazySendableExternalModuleVarByIndex),
{ Int8ToTaggedInt(index), currentFunc });
auto env = GetEnvironment();
Label notException(env);
CHECK_EXCEPTION_WITH_JUMP(*moduleRef, &notException);
Bind(&notException);
{
varAcc = *moduleRef;
DISPATCH_WITH_ACC(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8);
}
}
DECLARE_ASM_HANDLER(HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined());
GateRef index = ReadInst16_1(pc);
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazySendableExternalModuleVarByIndex),
{ Int16ToTaggedInt(index), currentFunc });
auto env = GetEnvironment();
Label notException(env);
CHECK_EXCEPTION_WITH_JUMP(*moduleRef, &notException);
Bind(&notException);
{
varAcc = *moduleRef;
DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16);
}
}
ASM_INTERPRETER_BC_TYPE_PROFILER_STUB_LIST(DECLARE_ASM_HANDLER_PROFILE)
ASM_INTERPRETER_BC_LAYOUT_PROFILER_STUB_LIST(DECLARE_ASM_HANDLER_PROFILE)

View File

@ -784,6 +784,14 @@ void SlowPathLowering::Lower(GateRef gate)
case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16:
LowerLdSendableVar(gate);
break;
case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8:
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16:
LowerLdLazyExternalModuleVar(gate);
break;
case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8:
case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16:
LowerLdLazySendableExternalModuleVar(gate);
break;
case EcmaOpcode::LDA_STR_ID16:
LowerLdStr(gate);
break;
@ -3864,4 +3872,23 @@ void SlowPathLowering::LowerGetUnsharedConstPool(GateRef gate)
acc_.DeleteGate(gate);
}
void SlowPathLowering::LowerLdLazyExternalModuleVar(GateRef gate)
{
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
GateRef result = LowerCallRuntime(gate,
RTSTUB_ID(LdLazyExternalModuleVarByIndex), {index, jsFunc}, true);
ReplaceHirWithValue(gate, result);
}
void SlowPathLowering::LowerLdLazySendableExternalModuleVar(GateRef gate)
{
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0));
GateRef result = LowerCallRuntime(gate,
RTSTUB_ID(LdLazySendableExternalModuleVarByIndex), {index, jsFunc}, true);
ReplaceHirWithValue(gate, result);
}
} // namespace panda::ecmascript

View File

@ -335,6 +335,8 @@ private:
void LowerLdStr(GateRef gate);
void LowerGetSharedConstPool(GateRef gate);
void LowerGetUnsharedConstPool(GateRef gate);
void LowerLdLazyExternalModuleVar(GateRef gate);
void LowerLdLazySendableExternalModuleVar(GateRef gate);
CompilationEnv *compilationEnv_;
const MethodLiteral *methodLiteral_ {nullptr};

View File

@ -418,6 +418,8 @@ EcmaVM::~EcmaVM()
}
#endif
thread_->GetCurrentEcmaContext()->GetModuleManager()->NativeObjDestory();
if (!isBundlePack_) {
std::shared_ptr<JSPandaFile> jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_);
if (jsPandaFile != nullptr) {

View File

@ -1039,7 +1039,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
constexpr size_t numOps = 0x100;
constexpr size_t numThrowOps = 10;
constexpr size_t numWideOps = 20;
constexpr size_t numCallRuntimeOps = 21;
constexpr size_t numCallRuntimeOps = 25;
constexpr size_t numDeprecatedOps = 47;
static std::array<const void *, numOps> instDispatchTable {
@ -7803,6 +7803,46 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
SET_ACC(SendableEnv::Cast(env.GetTaggedObject())->GetProperties(slot));
DISPATCH(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16);
}
HANDLE_OPCODE(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8) {
int32_t index = READ_INST_8_1();
JSTaggedValue funcObj = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, funcObj);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8);
}
HANDLE_OPCODE(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16) {
int32_t index = READ_INST_16_1();
JSTaggedValue funcObj = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, funcObj);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16);
}
HANDLE_OPCODE(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8) {
int32_t index = READ_INST_8_1();
JSTaggedValue funcObj = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, funcObj);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8);
}
HANDLE_OPCODE(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16) {
int32_t index = READ_INST_16_1();
JSTaggedValue funcObj = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, funcObj);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16);
}
#include "templates/debugger_instruction_handler.inl"
}
#endif

View File

@ -7796,6 +7796,62 @@ void InterpreterAssembly::ExceptionHandler(
DISPATCH_OFFSET(0);
}
void InterpreterAssembly::HandleCallRuntimeLdLazyModuleVarPrefImm8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
int32_t index = READ_INST_8_1();
JSTaggedValue thisFunc = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, thisFunc);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8);
}
void InterpreterAssembly::HandleCallRuntimeWideLdLazyModuleVarPrefImm16(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
int32_t index = READ_INST_16_1();
JSTaggedValue thisFunc = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, thisFunc);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16);
}
void InterpreterAssembly::HandleCallRuntimeLdLazySendableModuleVarPrefImm8(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
int32_t index = READ_INST_8_1();
JSTaggedValue thisFunc = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, thisFunc);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8);
}
void InterpreterAssembly::HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
int32_t index = READ_INST_16_1();
JSTaggedValue thisFunc = GetFunction(sp);
LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index;
JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, thisFunc);
INTERPRETER_RETURN_IF_ABRUPT(moduleVar);
SET_ACC(moduleVar);
DISPATCH(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16);
}
#define DECLARE_UNUSED_ASM_HANDLE(name) \
void InterpreterAssembly::name( \
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, \

View File

@ -1057,6 +1057,21 @@ JSTaggedValue SlowRuntimeStub::LdSendableExternalModuleVar(JSThread *thread, int
return RuntimeStubs::RuntimeLdSendableExternalModuleVar(thread, index, thisFunc);
}
JSTaggedValue SlowRuntimeStub::LdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc)
{
RUNTIME_TRACE(thread, LdLazyExternalModuleVarByIndex);
[[maybe_unused]] EcmaHandleScope scope(thread);
return RuntimeStubs::RuntimeLdLazyExternalModuleVar(thread, index, thisFunc);
}
JSTaggedValue SlowRuntimeStub::LdLazySendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc)
{
RUNTIME_TRACE(thread, LdLazySendableExternalModuleVarByIndex);
[[maybe_unused]] EcmaHandleScope scope(thread);
return RuntimeStubs::RuntimeLdLazySendableExternalModuleVar(thread, index, thisFunc);
}
JSTaggedValue SlowRuntimeStub::LdSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key,
JSTaggedValue thisFunc)
{

View File

@ -120,6 +120,8 @@ public:
static JSTaggedValue LdLocalModuleVar(JSThread *thread, int32_t index);
static JSTaggedValue LdExternalModuleVar(JSThread *thread, int32_t index);
static JSTaggedValue LdSendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc);
static JSTaggedValue LdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc);
static JSTaggedValue LdLazySendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc);
static JSTaggedValue CreateRegExpWithLiteral(JSThread *thread, JSTaggedValue pattern, uint8_t flags);
static JSTaggedValue GetIteratorNext(JSThread *thread, JSTaggedValue obj, JSTaggedValue method);

View File

@ -34,3 +34,7 @@
&&HANDLE_CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16,
&&HANDLE_CALLRUNTIME_ISTRUE_PREF_IMM8,
&&HANDLE_CALLRUNTIME_ISFALSE_PREF_IMM8,
&&HANDLE_CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8,
&&HANDLE_CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16,
&&HANDLE_CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8,
&&HANDLE_CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16,

View File

@ -207,6 +207,8 @@ void JSPandaFile::InitializeMergedPF()
info->isSharedModule = fieldAccessor.GetValue<bool>().value();
} else if (std::strcmp(HAS_TOP_LEVEL_AWAIT, fieldName) == 0) {
info->hasTopLevelAwait = fieldAccessor.GetValue<bool>().value();
} else if (std::strcmp(LAZY_IMPORT, fieldName) == 0) {
info->lazyImportIdx = fieldAccessor.GetValue<uint32_t>().value();
} else if (std::strcmp(TYPE_FLAG, fieldName) == 0) {
info->hasTSTypes = fieldAccessor.GetValue<uint8_t>().value() != 0;
} else if (std::strcmp(TYPE_SUMMARY_OFFSET, fieldName) == 0) {

View File

@ -42,6 +42,7 @@ public:
bool hasTopLevelAwait {false};
CUnorderedMap<uint32_t, uint64_t> constpoolMap;
bool hasTSTypes {false};
uint32_t lazyImportIdx {0};
uint32_t typeSummaryOffset {0};
uint32_t classId {CLASSID_OFFSET_NOT_FOUND};
CString npmPackageName;
@ -77,6 +78,7 @@ public:
static constexpr char MODULE_RECORD_IDX[] = "moduleRecordIdx";
static constexpr char IS_SHARED_MODULE[] = "isSharedModule";
static constexpr char HAS_TOP_LEVEL_AWAIT[] = "hasTopLevelAwait";
static constexpr char LAZY_IMPORT[] = "moduleRequestPhaseIdx";
static constexpr char PACKAGE_NAME[] = "pkgName@";
static constexpr char MERGE_ABC_NAME[] = "modules.abc";
static constexpr char NPM_PATH_SEGMENT[] = "node_modules";

View File

@ -164,6 +164,80 @@ JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTagge
UNREACHABLE();
}
JSTaggedValue ModuleManager::GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc)
{
JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
return GetLazyModuleValueOutterInternal(index, currentModule);
}
JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule)
{
JSThread *thread = vm_->GetJSThread();
if (currentModule.IsUndefined()) {
LOG_FULL(FATAL) << "GetLazyModuleValueOutter currentModule failed";
UNREACHABLE();
}
JSHandle<SourceTextModule> currentModuleHdl(thread, currentModule);
JSTaggedValue moduleEnvironment = currentModuleHdl->GetEnvironment();
if (moduleEnvironment.IsUndefined()) {
return thread->GlobalConstants()->GetUndefined();
}
ASSERT(moduleEnvironment.IsTaggedArray());
JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index);
if (resolvedBinding.IsResolvedIndexBinding()) {
JSHandle<ResolvedIndexBinding> binding(thread, resolvedBinding);
JSTaggedValue resolvedModule = binding->GetModule();
JSHandle<SourceTextModule> module(thread, resolvedModule);
ASSERT(resolvedModule.IsSourceTextModule());
SourceTextModule::Evaluate(thread, module, nullptr);
if (thread->HasPendingException()) {
return JSTaggedValue::Undefined();
}
// Support for only modifying var value of HotReload.
// Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
EcmaContext *context = thread->GetCurrentEcmaContext();
if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) {
const JSHandle<JSTaggedValue> resolvedModuleOfHotReload =
context->FindPatchModule(ConvertToString(module->GetEcmaModuleRecordName()));
if (!resolvedModuleOfHotReload->IsHole()) {
resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
JSHandle<SourceTextModule> moduleOfHotReload(thread, resolvedModule);
return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex());
}
}
return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
}
if (resolvedBinding.IsResolvedBinding()) {
JSHandle<ResolvedBinding> binding(thread, resolvedBinding);
JSTaggedValue resolvedModule = binding->GetModule();
JSHandle<SourceTextModule> module(thread, resolvedModule);
ModuleStatus status = module->GetStatus();
ModuleTypes moduleType = module->GetTypes();
if (SourceTextModule::IsNativeModule(moduleType)) {
SourceTextModule::InstantiateNativeModule(thread, currentModuleHdl, module, moduleType);
module->SetStatus(ModuleStatus::EVALUATED);
return ModuleManagerHelper::GetNativeModuleValue(thread, resolvedModule, binding->GetBindingName());
}
if (moduleType == ModuleTypes::CJS_MODULE) {
if (status != ModuleStatus::EVALUATED) {
SourceTextModule::ModuleExecution(thread, module, nullptr, 0);
module->SetStatus(ModuleStatus::EVALUATED);
}
SourceTextModule::InstantiateCJS(thread, currentModuleHdl, module);
JSHandle<JSTaggedValue> cjsModuleName(thread, SourceTextModule::GetModuleName(module.GetTaggedValue()));
return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue();
}
}
if (resolvedBinding.IsResolvedRecordIndexBinding()) {
return ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(thread, currentModuleHdl, resolvedBinding);
}
if (resolvedBinding.IsResolvedRecordBinding()) {
return ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(thread, currentModuleHdl, resolvedBinding);
}
LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding";
UNREACHABLE();
}
void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value)
{
JSThread *thread = vm_->GetJSThread();
@ -465,7 +539,8 @@ JSHandle<JSTaggedValue> ModuleManager::ResolveModule(JSThread *thread, const JSP
JSHandle<JSTaggedValue> moduleRecord = thread->GlobalConstants()->GetHandledUndefined();
JSRecordInfo recordInfo = const_cast<JSPandaFile *>(jsPandaFile)->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME);
if (jsPandaFile->IsModule(&recordInfo)) {
moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, moduleFileName, moduleFileName);
moduleRecord = ModuleDataExtractor::ParseModule(
thread, jsPandaFile, moduleFileName, moduleFileName, &recordInfo);
} else {
ASSERT(jsPandaFile->IsCjs(&recordInfo));
moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile);
@ -508,7 +583,7 @@ JSHandle<JSTaggedValue> ModuleManager::ResolveModuleWithMerge(
}
if (jsPandaFile->IsModule(recordInfo)) {
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread);
moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordNameStr, moduleFileName);
moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordNameStr, moduleFileName, recordInfo);
} else if (jsPandaFile->IsJson(recordInfo)) {
moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName, recordNameStr);
} else {
@ -852,7 +927,8 @@ void ModuleManager::RemoveModuleFromCache(JSTaggedValue recordName)
int entry = dict->FindEntry(recordName);
LOG_ECMA_IF(entry == -1, FATAL) << "Can not get module: " << ConvertToString(recordName) <<
", when try to remove the module";
JSTaggedValue result = dict->GetValue(entry);
SourceTextModule::Cast(result)->DestoryLazyImportArray();
resolvedModules_ = NameDictionary::Remove(thread, dict, entry).GetTaggedValue();
}
} // namespace panda::ecmascript

View File

@ -37,6 +37,7 @@ public:
JSTaggedValue GetModuleValueOutter(int32_t index);
JSTaggedValue GetModuleValueOutter(int32_t index, JSTaggedValue jsFunc);
JSTaggedValue GetModuleValueOutter(int32_t index, JSHandle<JSTaggedValue> currentModule);
JSTaggedValue GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc);
void StoreModuleValue(int32_t index, JSTaggedValue value);
void StoreModuleValue(int32_t index, JSTaggedValue value, JSTaggedValue jsFunc);
JSTaggedValue GetModuleNamespace(int32_t index);
@ -115,6 +116,19 @@ public:
return ordinal;
}
void NativeObjDestory()
{
NameDictionary* dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
int size = dict->Size();
for (int hashIndex = 0; hashIndex < size; hashIndex++) {
JSTaggedValue key(dict->GetKey(hashIndex));
if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) {
JSTaggedValue val(dict->GetValue(hashIndex));
SourceTextModule::Cast(val)->DestoryLazyImportArray();
}
}
}
private:
NO_COPY_SEMANTIC(ModuleManager);
NO_MOVE_SEMANTIC(ModuleManager);
@ -123,6 +137,8 @@ private:
void StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,
int32_t index, JSTaggedValue value);
JSTaggedValue GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule);
// deprecated begin
JSTaggedValue GetModuleValueOutterInternal(JSTaggedValue key, JSTaggedValue currentModule);
void StoreModuleValueInternal(JSHandle<SourceTextModule> &currentModule,

View File

@ -488,13 +488,12 @@ bool SourceTextModule::LoadNativeModule(JSThread *thread, const JSHandle<SourceT
}
void SourceTextModule::InstantiateNativeModule(JSThread *thread, JSHandle<SourceTextModule> &currentModule,
JSHandle<SourceTextModule> &requiredModule, const JSHandle<JSTaggedValue> &moduleRequest,
ModuleTypes moduleType)
JSHandle<SourceTextModule> &requiredModule, ModuleTypes moduleType)
{
if (requiredModule->GetStatus() != ModuleStatus::EVALUATED) {
if (!SourceTextModule::LoadNativeModule(thread, requiredModule, moduleType)) {
LOG_FULL(WARN) << "LoadNativeModule " <<
ModulePathHelper::Utf8ConvertToString(moduleRequest.GetTaggedValue()) << " failed";
ModulePathHelper::Utf8ConvertToString(requiredModule->GetEcmaModuleRecordName()) << " failed";
return;
}
}
@ -1114,21 +1113,26 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
size_t requestedModulesLen = requestedModules->GetLength();
JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
JSHandle<SourceTextModule> requiredModule;
bool *lazyFlag = module->GetLazyImportStatusArray();
for (size_t idx = 0; idx < requestedModulesLen; idx++) {
if (lazyFlag[idx]) {
continue;
}
required.Update(requestedModules->Get(idx));
JSMutableHandle<SourceTextModule> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
if (moduleRecordName.IsUndefined()) {
requiredModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, required));
requiredModule = JSHandle<SourceTextModule>::Cast(
SourceTextModule::HostResolveImportedModule(thread, module, required));
} else {
ASSERT(moduleRecordName.IsString());
requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
requiredModule = JSHandle<SourceTextModule>::Cast(
SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
}
ModuleTypes moduleType = requiredModule->GetTypes();
if (SourceTextModule::IsNativeModule(moduleType)) {
InstantiateNativeModule(thread, module, requiredModule, required, moduleType);
InstantiateNativeModule(thread, module, requiredModule, moduleType);
requiredModule->SetStatus(ModuleStatus::EVALUATED);
continue;
}
@ -1156,7 +1160,7 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
int dfsAncIdx = std::min(module->GetDFSAncestorIndex(), requiredModule->GetDFSAncestorIndex());
module->SetDFSAncestorIndex(dfsAncIdx);
} else {
requiredModule.Update(requiredModule->GetCycleRoot());
requiredModule = JSHandle<SourceTextModule>(thread, requiredModule->GetCycleRoot());
requiredModuleStatus = requiredModule->GetStatus();
ASSERT(requiredModuleStatus == ModuleStatus::EVALUATING_ASYNC ||
requiredModuleStatus == ModuleStatus::EVALUATED);
@ -1355,7 +1359,7 @@ int SourceTextModule::ModuleEvaluation(JSThread *thread, const JSHandle<ModuleRe
}
ModuleTypes moduleType = requiredModule->GetTypes();
if (SourceTextModule::IsNativeModule(moduleType)) {
InstantiateNativeModule(thread, module, requiredModule, required, moduleType);
InstantiateNativeModule(thread, module, requiredModule, moduleType);
requiredModule->SetStatus(ModuleStatus::EVALUATED);
continue;
}

View File

@ -232,6 +232,22 @@ public:
SharedTypes::SENDABLE_FUNCTION_MODULE;
}
inline void SetLazyImportArray(bool *lazyImportArray)
{
DestoryLazyImportArray();
SetLazyImportStatus(ToUintPtr(lazyImportArray));
}
inline void DestoryLazyImportArray()
{
delete[] GetLazyImportStatusArray();
}
inline bool *GetLazyImportStatusArray()
{
return reinterpret_cast<bool *>(GetLazyImportStatus());
}
static constexpr size_t SOURCE_TEXT_MODULE_OFFSET = ModuleRecord::SIZE;
ACCESSORS(Environment, SOURCE_TEXT_MODULE_OFFSET, NAMESPACE_OFFSET);
ACCESSORS(Namespace, NAMESPACE_OFFSET, ECMA_MODULE_FILENAME);
@ -251,7 +267,9 @@ public:
ACCESSORS_PRIMITIVE_FIELD(DFSAncestorIndex, int32_t, DFS_ANCESTOR_INDEX_OFFSET, DFS_INDEX_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(DFSIndex, int32_t, DFS_INDEX_OFFSET, ASYNC_EVALUATION_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(AsyncEvaluatingOrdinal, uint32_t, ASYNC_EVALUATION_OFFSET, PENDING_DEPENDENCIES_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(PendingAsyncDependencies, int32_t, PENDING_DEPENDENCIES_OFFSET, BIT_FIELD_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(PendingAsyncDependencies,
int32_t, PENDING_DEPENDENCIES_OFFSET, LAYZ_IMPORT_STATUS_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(LazyImportStatus, uintptr_t, LAYZ_IMPORT_STATUS_OFFSET, BIT_FIELD_OFFSET);
ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
DEFINE_ALIGN_SIZE(LAST_OFFSET);
@ -289,7 +307,6 @@ public:
const JSHandle<SourceTextModule> &requiredModule);
static void InstantiateNativeModule(JSThread *thread, JSHandle<SourceTextModule> &currentModule,
JSHandle<SourceTextModule> &requiredModule,
const JSHandle<JSTaggedValue> &moduleRequest,
ModuleTypes moduleType);
JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow);

View File

@ -127,7 +127,8 @@ JSHandle<TaggedArray> JSSharedModule::CloneEnvForSModule(JSThread *thread, const
}
JSHandle<JSTaggedValue> SharedModuleHelper::ParseSharedModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &descriptor, const CString &moduleFilename)
const CString &descriptor, const CString &moduleFilename,
JSRecordInfo *recordInfo)
{
int moduleIdx = jsPandaFile->GetModuleRecordIdx(descriptor);
ASSERT(jsPandaFile->IsNewVersion() && (moduleIdx != -1)); // new pandafile version use new literal offset mechanism
@ -136,7 +137,7 @@ JSHandle<JSTaggedValue> SharedModuleHelper::ParseSharedModule(JSThread *thread,
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<SourceTextModule> moduleRecord = factory->NewSSourceTextModule();
moduleRecord->SetSharedType(SharedTypes::SHARED_MODULE);
ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord);
ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord, recordInfo);
bool hasTLA = jsPandaFile->GetHasTopLevelAwait(descriptor);
moduleRecord->SetHasTLA(hasTLA);

View File

@ -75,7 +75,8 @@ public:
class SharedModuleHelper {
public:
static JSHandle<JSTaggedValue> ParseSharedModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &descriptor, const CString &moduleFilename);
const CString &descriptor, const CString &moduleFilename,
JSRecordInfo *recordInfo);
};
} // namespace panda::ecmascript

View File

@ -79,6 +79,44 @@ JSTaggedValue SharedModuleManager::GetSendableModuleValueImpl(
UNREACHABLE();
}
JSTaggedValue SharedModuleManager::GetLazySendableModuleValue(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
{
JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule();
return GetLazySendableModuleValueImpl(thread, index, currentModule);
}
JSTaggedValue SharedModuleManager::GetLazySendableModuleValueImpl(
JSThread *thread, int32_t index, JSTaggedValue currentModule) const
{
if (currentModule.IsUndefined()) {
LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed";
UNREACHABLE();
}
JSHandle<SourceTextModule> module(thread, currentModule.GetTaggedObject());
JSTaggedValue moduleEnvironment = module->GetEnvironment();
if (moduleEnvironment.IsUndefined()) {
return thread->GlobalConstants()->GetUndefined();
}
ASSERT(moduleEnvironment.IsTaggedArray());
JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index);
if (resolvedBinding.IsResolvedRecordIndexBinding()) {
return ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(thread, module, resolvedBinding);
} else if (resolvedBinding.IsResolvedIndexBinding()) {
ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject());
JSHandle<SourceTextModule> resolvedModule(thread, binding->GetModule().GetTaggedObject());
SourceTextModule::Evaluate(thread, resolvedModule, nullptr);
if (thread->HasPendingException()) {
return JSTaggedValue::Undefined();
}
return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetIndex());
} else if (resolvedBinding.IsResolvedRecordBinding()) {
return ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(thread, module, resolvedBinding);
}
LOG_ECMA(FATAL) << "Unexpect binding";
UNREACHABLE();
}
JSHandle<JSTaggedValue> SharedModuleManager::ResolveImportedModule(JSThread *thread, const CString &fileName,
bool executeFromJob)
{
@ -122,7 +160,7 @@ JSHandle<JSTaggedValue> SharedModuleManager::ResolveSharedImportedModule(JSThrea
ASSERT(jsPandaFile->IsModule(recordInfo));
JSHandle<JSTaggedValue> moduleRecord = SharedModuleHelper::ParseSharedModule(thread,
jsPandaFile, fileName, fileName);
jsPandaFile, fileName, fileName, recordInfo);
moduleManager->AddResolveImportedModule(requireModule, moduleRecord);
moduleManager->AddToInstantiatingSModuleList(fileName);
return moduleRecord;
@ -173,7 +211,7 @@ JSHandle<JSTaggedValue> SharedModuleManager::ResolveSharedImportedModuleWithMerg
ASSERT(jsPandaFile->IsModule(recordInfo));
JSHandle<JSTaggedValue> moduleRecord = SharedModuleHelper::ParseSharedModule(thread, jsPandaFile, recordName,
fileName);
fileName, recordInfo);
JSHandle<SourceTextModule>::Cast(moduleRecord)->SetEcmaModuleRecordName(thread, requireModule);
moduleManager->AddResolveImportedModule(requireModule, moduleRecord);
moduleManager->AddToInstantiatingSModuleList(recordName);

View File

@ -50,6 +50,10 @@ public:
JSTaggedValue GetSendableModuleValueImpl(JSThread *thread, int32_t index, JSTaggedValue currentModule) const;
JSTaggedValue GetLazySendableModuleValue(JSThread *thread, int32_t index, JSTaggedValue jsFunc);
JSTaggedValue GetLazySendableModuleValueImpl(JSThread *thread, int32_t index, JSTaggedValue currentModule) const;
void Iterate(const RootVisitor &v);
JSHandle<JSTaggedValue> ResolveImportedModule(JSThread *thread, const CString &referencingModule,

View File

@ -31,11 +31,11 @@ using BuiltinsJson = builtins::BuiltinsJson;
using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
JSHandle<JSTaggedValue> ModuleDataExtractor::ParseModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &descriptor, const CString &moduleFilename)
const CString &descriptor, const CString &moduleFilename,
JSRecordInfo *recordInfo)
{
int moduleIdx = jsPandaFile->GetModuleRecordIdx(descriptor);
ASSERT(moduleIdx != -1);
panda_file::File::EntityId moduleId;
if (jsPandaFile->IsNewVersion()) { // new pandafile version use new literal offset mechanism
moduleId = panda_file::File::EntityId(static_cast<uint32_t>(moduleIdx));
@ -46,9 +46,9 @@ JSHandle<JSTaggedValue> ModuleDataExtractor::ParseModule(JSThread *thread, const
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<SourceTextModule> moduleRecord = factory->NewSourceTextModule();
ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord);
ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord, recordInfo);
bool hasTLA = jsPandaFile->GetHasTopLevelAwait(descriptor);
bool hasTLA = recordInfo->hasTopLevelAwait;
moduleRecord->SetHasTLA(hasTLA);
JSHandle<EcmaString> ecmaModuleFilename = factory->NewFromUtf8(moduleFilename);
@ -63,7 +63,8 @@ JSHandle<JSTaggedValue> ModuleDataExtractor::ParseModule(JSThread *thread, const
void ModuleDataExtractor::ExtractModuleDatas(JSThread *thread, const JSPandaFile *jsPandaFile,
panda_file::File::EntityId moduleId,
JSHandle<SourceTextModule> &moduleRecord)
JSHandle<SourceTextModule> &moduleRecord,
[[maybe_unused]]JSRecordInfo *recordInfo)
{
[[maybe_unused]] EcmaHandleScope scope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
@ -86,6 +87,17 @@ void ModuleDataExtractor::ExtractModuleDatas(JSThread *thread, const JSPandaFile
moduleRecord->SetRequestedModules(thread, requestModuleArray);
}
if (recordInfo->lazyImportIdx != 0) {
bool *lazyImportFlags = ModuleLazyImportFlagAccessor(jsPandaFile,
panda_file::File::EntityId(static_cast<uint32_t>(recordInfo->lazyImportIdx)));
moduleRecord->SetLazyImportArray(lazyImportFlags); // set module Lazy Import flag
} else {
bool *lazyImportArray = new bool[len]();
for (size_t idx = 0; idx < len; idx++) {
lazyImportArray[idx] = 0;
}
moduleRecord->SetLazyImportArray(lazyImportArray); // set module Lazy Import 0
}
// note the order can't change
mda.EnumerateImportEntry(thread, requestModuleArray, moduleRecord);
mda.EnumerateLocalExportEntry(thread, moduleRecord);
@ -174,4 +186,19 @@ JSTaggedValue ModuleDataExtractor::JsonParse(JSThread *thread, const JSPandaFile
info->SetCallArg(value);
return BuiltinsJson::Parse(info);
}
bool* ModuleDataExtractor::ModuleLazyImportFlagAccessor(const JSPandaFile *pandaFile,
panda_file::File::EntityId module_lazy_import_flag_id)
{
auto &pf = *pandaFile->GetPandaFile();
auto sp = pf.GetSpanFromId(module_lazy_import_flag_id);
uint32_t numLazyImportFlags = panda_file::helpers::Read<panda_file::ID_SIZE>(&sp);
bool *lazyImportArray = new bool[numLazyImportFlags]();
for (size_t idx = 0; idx < numLazyImportFlags; idx++) {
uint32_t value = static_cast<uint32_t>(panda_file::helpers::Read<sizeof(uint8_t)>(&sp));
lazyImportArray[idx] = value > 0 ? 1 : 0;
}
return lazyImportArray;
}
} // namespace panda::ecmascript

View File

@ -34,15 +34,19 @@ public:
static void ExtractModuleDatas(JSThread *thread, const JSPandaFile *jsPandaFile,
panda_file::File::EntityId moduleId,
JSHandle<SourceTextModule> &moduleRecord);
JSHandle<SourceTextModule> &moduleRecord,
[[maybe_unused]]JSRecordInfo *recordInfo);
static JSHandle<JSTaggedValue> ParseModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &descriptor, const CString &moduleFilename);
const CString &descriptor, const CString &moduleFilename,
JSRecordInfo *recordInfo);
static JSHandle<JSTaggedValue> ParseCjsModule(JSThread *thread, const JSPandaFile *jsPandaFile);
static JSHandle<JSTaggedValue> ParseJsonModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &moduleFilename, const CString &recordName);
static JSHandle<JSTaggedValue> ParseNativeModule(JSThread *thread, const CString &moduleRequestName,
const CString &baseFileName, ModuleTypes moduleType);
static JSTaggedValue JsonParse(JSThread *thread, const JSPandaFile *jsPandaFile, CString entryPoint);
static bool *ModuleLazyImportFlagAccessor(const JSPandaFile *pandaFile,
panda_file::File::EntityId module_lazy_import_flag_id);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_MODULE_MODULE_DATA_EXTRACTOR_H

View File

@ -204,4 +204,67 @@ JSTaggedValue ModuleManagerHelper::GetModuleValueFromRecordBinding(JSThread *thr
}
return GetModuleValue(thread, resolvedModule, binding->GetBindingName());
}
JSTaggedValue ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding)
{
JSHandle<ResolvedRecordIndexBinding> binding(thread, resolvedBinding);
JSHandle<JSTaggedValue> moduleRecord(thread, binding->GetModuleRecord());
ASSERT(moduleRecord->IsString());
// moduleRecord is string, find at current vm
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<SourceTextModule> resolvedModule;
if (moduleManager->IsLocalModuleLoaded(moduleRecord.GetTaggedValue())) {
if (moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) {
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
} else {
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
SourceTextModule::Evaluate(thread, resolvedModule, nullptr);
if (thread->HasPendingException()) {
return JSTaggedValue::Undefined();
}
}
} else {
auto isMergedAbc = !module->GetEcmaModuleRecordName().IsUndefined();
CString record = ConvertToString(moduleRecord.GetTaggedValue());
CString fileName = ConvertToString(binding->GetAbcFileName());
if (!JSPandaFileExecutor::LazyExecuteModule(thread, record, fileName, isMergedAbc)) {
LOG_ECMA(FATAL) << "LazyExecuteModule failed";
}
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
}
return GetModuleValue(thread, resolvedModule, binding->GetIndex());
}
JSTaggedValue ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(
JSThread *thread, JSHandle<SourceTextModule> module, JSTaggedValue resolvedBinding)
{
JSHandle<ResolvedRecordBinding> binding(thread, resolvedBinding);
JSHandle<JSTaggedValue> moduleRecord(thread, binding->GetModuleRecord());
ASSERT(moduleRecord->IsString());
// moduleRecord is string, find at current vm
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<SourceTextModule> resolvedModule;
if (moduleManager->IsLocalModuleLoaded(moduleRecord.GetTaggedValue())) {
if (moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) {
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
} else {
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
SourceTextModule::Evaluate(thread, resolvedModule, nullptr);
if (thread->HasPendingException()) {
return JSTaggedValue::Undefined();
}
}
} else {
auto isMergedAbc = !module->GetEcmaModuleRecordName().IsUndefined();
CString record = ConvertToString(moduleRecord.GetTaggedValue());
CString fileName = ConvertToString(module->GetEcmaModuleFilename());
if (!JSPandaFileExecutor::LazyExecuteModule(thread, record, fileName, isMergedAbc)) {
LOG_ECMA(FATAL) << "LazyExecuteModule failed";
}
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
}
return GetModuleValue(thread, resolvedModule, binding->GetBindingName());
}
} // namespace panda::ecmascript

View File

@ -45,6 +45,14 @@ public:
static JSTaggedValue PUBLIC_API GetModuleValueFromRecordBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding);
static JSTaggedValue GetLazyModuleValueFromIndexBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding);
static JSTaggedValue GetLazyModuleValueFromRecordBinding(JSThread *thread,
JSHandle<SourceTextModule> module,
JSTaggedValue resolvedBinding);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_MODULE_JS_SHARED_MODULE_H

View File

@ -4718,6 +4718,8 @@ JSHandle<SourceTextModule> ObjectFactory::NewSourceTextModule()
obj->SetTypes(ModuleTypes::UNKNOWN);
obj->SetIsNewBcVersion(false);
obj->SetRegisterCounts(UINT16_MAX);
bool *tmp = new bool[0];
obj->SetLazyImportStatus(ToUintPtr(tmp));
obj->SetSharedType(SharedTypes::UNSENDABLE_MODULE);
obj->SetSendableEnv(thread_, undefinedValue);
return obj;

View File

@ -689,6 +689,8 @@ JSHandle<SourceTextModule> ObjectFactory::NewSSourceTextModule()
obj->SetTypes(ModuleTypes::UNKNOWN);
obj->SetIsNewBcVersion(false);
obj->SetRegisterCounts(UINT16_MAX);
bool *tmp = new bool[0];
obj->SetLazyImportStatus(ToUintPtr(tmp));
obj->SetSharedType(SharedTypes::UNSENDABLE_MODULE);
obj->SetSendableEnv(thread_, undefinedValue);
return obj;

View File

@ -1347,6 +1347,17 @@ JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t
return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(index, jsFunc);
}
JSTaggedValue RuntimeStubs::RuntimeLdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
{
return thread->GetCurrentEcmaContext()->GetModuleManager()->GetLazyModuleValueOutter(index, jsFunc);
}
JSTaggedValue RuntimeStubs::RuntimeLdLazySendableExternalModuleVar(
JSThread *thread, int32_t index, JSTaggedValue jsFunc)
{
return SharedModuleManager::GetInstance()->GetLazySendableModuleValue(thread, index, jsFunc);
}
JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner)
{
if (inner) {

View File

@ -1936,6 +1936,22 @@ DEF_RUNTIME_STUBS(LdSendableExternalModuleVarByIndex)
return RuntimeLdSendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData();
}
DEF_RUNTIME_STUBS(LdLazyExternalModuleVarByIndex)
{
RUNTIME_STUBS_HEADER(LdLazyExternalModuleVarByIndex);
JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter
JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter
return RuntimeLdLazyExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData();
}
DEF_RUNTIME_STUBS(LdLazySendableExternalModuleVarByIndex)
{
RUNTIME_STUBS_HEADER(LdLazySendableExternalModuleVarByIndex);
JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter
JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter
return RuntimeLdLazySendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData();
}
DEF_RUNTIME_STUBS(LdLocalModuleVarByIndexOnJSFunc)
{
RUNTIME_STUBS_HEADER(LdLocalModuleVarByIndexOnJSFunc);

View File

@ -347,6 +347,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
V(LdLocalModuleVarByIndex) \
V(LdExternalModuleVarByIndex) \
V(LdSendableExternalModuleVarByIndex) \
V(LdLazyExternalModuleVarByIndex) \
V(LdLazySendableExternalModuleVarByIndex) \
V(LdLocalModuleVarByIndexOnJSFunc) \
V(LdExternalModuleVarByIndexOnJSFunc) \
V(LdModuleVar) \
@ -753,6 +755,10 @@ private:
JSTaggedValue jsFunc);
static inline JSTaggedValue RuntimeLdExternalModuleVar(JSThread *thread, int32_t index,
JSTaggedValue jsFunc);
static inline JSTaggedValue RuntimeLdLazySendableExternalModuleVar(JSThread *thread, int32_t index,
JSTaggedValue jsFunc);
static inline JSTaggedValue RuntimeLdLazyExternalModuleVar(JSThread *thread, int32_t index,
JSTaggedValue jsFunc);
static inline JSTaggedValue RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner);
static inline JSTaggedValue RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner,
JSTaggedValue jsFunc);

View File

@ -1370,7 +1370,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
break;
}
case JSType::SOURCE_TEXT_MODULE_RECORD: {
CHECK_DUMP_FIELDS(ModuleRecord::SIZE, SourceTextModule::SIZE, 17U);
CHECK_DUMP_FIELDS(ModuleRecord::SIZE, SourceTextModule::SIZE, 18U);
JSHandle<SourceTextModule> moduleSourceRecord = factory->NewSourceTextModule();
DUMP_FOR_HANDLE(moduleSourceRecord);
break;

View File

@ -105,6 +105,7 @@ group("ark_js_moduletest") {
"merge",
"module",
"moduleImportJson",
"moduleLazyImport",
"moduleUseCjs",
"multiargs",
"multiprotoic",

View File

@ -0,0 +1,34 @@
/*
* 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.
*/
/*
* @tc.name:moduleCircularCheck
* @tc.desc:check module circular import
* @tc.type: FUNC
* @tc.require: issueI5RC2C
*/
import ss from './D_Cjs'
import lazy {b} from './B'
print("this is A");
print(JSON.stringify(ss));
export class A {
static myMethod() {
print('static');
}
myMethod() {
print('instance', b);
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
/*
* @tc.name:moduleCircularCheck
* @tc.desc:check module circular import
* @tc.type: FUNC
* @tc.require: issueI5RC2C
*/
import {fun} from './C_Cjs'
import foo from './D_Cjs'
export let b = "3";
print("this is B", JSON.stringify(foo));
fun();

View File

@ -0,0 +1,22 @@
# 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("../../test_helper.gni")
host_moduletest_action("moduleLazyImport") {
deps = []
entry_point = "--entry-point=moduleLazyImport"
is_module = true
is_merge = true
is_merge_abc = true
}

View File

@ -0,0 +1,26 @@
/*
* 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.
*/
/*
* @tc.name:cjsImportJson
* @tc.desc:test import Json
* @tc.type: FUNC
* @tc.require: issueI5NO8G
*/
module.exports.fun = function foo5 () {
print("foo5");
};
print("this is C_Cjs")

View File

@ -0,0 +1,25 @@
/*
* 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.
*/
/*
* @tc.name:moduleCircularCheck
* @tc.desc:check module circular import
* @tc.type: FUNC
* @tc.require: issueI5RC2C
*/
print("this is D_Cjs");
module.exports = {
foo: "module use cjsModule"
}

View File

@ -0,0 +1,25 @@
/*
* 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.
*/
/*
* @tc.name:moduleCircularCheck
* @tc.desc:check module circular import
* @tc.type: FUNC
* @tc.require: issueI5RC2C
*/
export function aaa() {
print("E func");
}
print("this is E");

View File

@ -0,0 +1,25 @@
/*
* 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.
*/
/*
* @tc.name:moduleCircularCheck
* @tc.desc:check module circular import
* @tc.type: FUNC
* @tc.require: issueI5RC2C
*/
export function func1() {
print("F func");
}
print("this is F");

View File

@ -0,0 +1,25 @@
# 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.
this is E
this is entry
this is F
F func
this is D_Cjs
this is A
{"foo":"module use cjsModule"}
this is C_Cjs
this is B {"foo":"module use cjsModule"}
foo5
instance 3
E func

View File

@ -0,0 +1,30 @@
/*
* 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.
*/
/*
* @tc.name:importJson
* @tc.desc:test import Json
* @tc.type: FUNC
* @tc.require: issueI5NO8G
*/
import lazy {A} from "./A"
import { aaa } from "./E";
import lazy {func1} from './F';
print("this is entry");
func1();
let myClass = new A();
myClass.myMethod();
aaa();

View File

@ -0,0 +1,7 @@
A.js;A;esm;A.js;xxAxx
B.js;B;esm;B.js;xxBxx
C_Cjs.js;C_Cjs;commonjs;C_Cjs.js;xxC_Cjsxx
D_Cjs.js;D_Cjs;commonjs;D_Cjs.js;xxD_Cjsxx
E.js;E;esm;E.js;xxExx
F.js;F;esm;F.js;xxFxx
moduleLazyImport.js;moduleLazyImport;esm;moduleLazyImport.js;xxmoduleLazyImportxx

View File

@ -23,7 +23,7 @@
// @ts-nocheck
declare function print(str: any): string;
import {Test1, foo2} from "./func"
import lazy {Test1, foo2} from "./func"
import {strA, strB} from "./string"
class SendableClassA {