diff --git a/ecmascript/builtins/builtins_ark_tools.cpp b/ecmascript/builtins/builtins_ark_tools.cpp index c01b1e0dcd8f26dc762d571282847f6485cace41..a87bcd7d6176471a938ee475cf2b87dc705c776c 100644 --- a/ecmascript/builtins/builtins_ark_tools.cpp +++ b/ecmascript/builtins/builtins_ark_tools.cpp @@ -691,7 +691,7 @@ JSTaggedValue BuiltinsArkTools::GetAPIVersion(EcmaRuntimeCallInfo *info) RETURN_IF_DISALLOW_ARKTOOLS(thread); [[maybe_unused]] EcmaHandleScope handleScope(thread); - return JSTaggedValue(thread->GetEcmaVM()->GetVMAPIVersion()); + return JSTaggedValue(thread->GetAPIVersion()); } JSTaggedValue BuiltinsArkTools::SetAPIVersion(EcmaRuntimeCallInfo *info) @@ -703,7 +703,7 @@ JSTaggedValue BuiltinsArkTools::SetAPIVersion(EcmaRuntimeCallInfo *info) JSHandle value = GetCallArg(info, 0); if (value->IsInt()) { - thread->GetEcmaVM()->SetVMAPIVersion(value->GetInt()); + thread->SetAPIVersion(value->GetInt()); } return JSTaggedValue::Undefined(); } diff --git a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp index aa143b9696446e34f96949d7e198fea23b8b24db..d97a5d18fdfceb284b40bbda1568c52b051437bc 100644 --- a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp @@ -820,6 +820,8 @@ void BuiltinsStringStubBuilder::Replace(GateRef glue, GateRef thisValue, GateRef Label searchIsHeapObj(env); Label replaceIsHeapObj(env); + DEFVARIABLE(pos, VariableType::INT32(), Int32(-1)); + BRANCH(TaggedIsHeapObject(thisValue), &thisIsHeapObj, slowPath); Bind(&thisIsHeapObj); BRANCH(Int64Equal(IntPtr(2), numArgs), &tagsDefined, slowPath); // 2: number of parameters. search & replace Tag @@ -863,8 +865,22 @@ void BuiltinsStringStubBuilder::Replace(GateRef glue, GateRef thisValue, GateRef searchFlat.FlattenString(glue, searchTag, &searchFlattenFastPath); Bind(&searchFlattenFastPath); StringInfoGateRef searchStringInfoGate(&searchFlat); - GateRef pos = StringIndexOf(glue, thisStringInfoGate, searchStringInfoGate, Int32(-1)); - BRANCH(Int32Equal(pos, Int32(-1)), &noReplace, &nextProcess); + Label newVersion(env); + Label oldVersion(env); + Label apiVersionNext(env); + GateRef isNewVersion = + APIVersionGreaterThanOrEqual(glue, Int32(static_cast(APIVersion::APIVersion21))); + BRANCH(isNewVersion, &newVersion, &oldVersion); + { + Bind(&newVersion); + pos = StringIndexOf(glue, thisStringInfoGate, searchStringInfoGate, Int32(0)); + Jump(&apiVersionNext); + Bind(&oldVersion); + pos = StringIndexOf(glue, thisStringInfoGate, searchStringInfoGate, Int32(-1)); + Jump(&apiVersionNext); + } + Bind(&apiVersionNext); + BRANCH(Int32Equal(*pos, Int32(-1)), &noReplace, &nextProcess); Bind(&noReplace); { res->WriteVariable(thisValue); @@ -879,13 +895,13 @@ void BuiltinsStringStubBuilder::Replace(GateRef glue, GateRef thisValue, GateRef { Label replHandleIsString(env); - GateRef replHandle = GetSubstitution(glue, searchTag, thisValue, pos, replaceTag); + GateRef replHandle = GetSubstitution(glue, searchTag, thisValue, *pos, replaceTag); BRANCH(IsString(glue, replHandle), &replHandleIsString, slowPath); Bind(&replHandleIsString); { - GateRef tailPos = Int32Add(pos, searchStringInfoGate.GetLength()); + GateRef tailPos = Int32Add(*pos, searchStringInfoGate.GetLength()); GateRef prefixString = FastSubString(glue, thisValue, Int32(0), - pos, thisStringInfoGate); + *pos, thisStringInfoGate); GateRef thisLen = thisStringInfoGate.GetLength(); GateRef suffixString = FastSubString(glue, thisValue, tailPos, Int32Sub(thisLen, tailPos), thisStringInfoGate); diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 90bf40f9f4e4fb56e07263499f889d9c49a12984..4840c420d2b0bb03310ba353f985f91bb162e96c 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -4656,5 +4656,12 @@ inline GateRef StubBuilder::GetSetIteratorDetector(GateRef env) { return env_->GetBuilder()->GetSetIteratorDetector(env); } + +inline GateRef StubBuilder::APIVersionGreaterThanOrEqual(GateRef glue, GateRef targetVersion) +{ + GateRef apiVersionOffset = IntPtr(JSThread::GlueData::GetApiVersionOffset(env_->Is32Bit())); + GateRef apiVersion = LoadPrimitive(VariableType::INT32(), glue, apiVersionOffset); + return Int32GreaterThanOrEqual(apiVersion, targetVersion); +} } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_STUB_INL_H diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index a909b492ca9d3d7ddb2f7f7a2846928b78b7300f..78e51afafb84ba4a2f0a2ec3b58ad1d8e36f47d0 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -1283,6 +1283,7 @@ public: GateRef OrdinaryToPrimitive(GateRef glue, GateRef value, PreferredPrimitiveType type, GateRef hir = Circuit::NullGate()); GateRef CallFunction(GateRef glue, GateRef func); + GateRef APIVersionGreaterThanOrEqual(GateRef glue, GateRef targetVersion); enum CopyKind { SameArray, diff --git a/ecmascript/containers/tests/containers_treeset_test.cpp b/ecmascript/containers/tests/containers_treeset_test.cpp index f5c9e2fb9c5180d905f07b56e25c82f4d8bcac3c..62f1c6393f5f691bd25a5e12474a99b3595f4924 100644 --- a/ecmascript/containers/tests/containers_treeset_test.cpp +++ b/ecmascript/containers/tests/containers_treeset_test.cpp @@ -1086,7 +1086,7 @@ HWTEST_F_L0(ContainersTreeSetTest, CustomCompareFunctionApi20Test) { constexpr int NODE_NUMBERS = 8; // 20 : Isolating version to fix comparator missing - thread->GetEcmaVM()->SetVMAPIVersion(20); + thread->SetAPIVersion(20); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle func = factory->NewJSFunction(env, reinterpret_cast(TestClass::TestCompareFunction)); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index c555dcd81a9958876a1c884b898471e742191e92..c19a051adebe4a0473d32d570d2b7e33db1c8ecb 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -1107,16 +1107,6 @@ public: void PUBLIC_API PrintAOTSnapShotStats(); - void SetVMAPIVersion(uint32_t APIVersion) - { - apiVersion_ = APIVersion; - } - - uint32_t GetVMAPIVersion() - { - return apiVersion_; - } - JSTaggedValue GetRegisterSymbols() const { return registerSymbols_; @@ -1414,9 +1404,6 @@ private: int32_t unsharedConstpoolsArrayLen_ = UNSHARED_CONSTANTPOOL_COUNT; static constexpr int32_t SHARED_CONSTPOOL_KEY_NOT_FOUND = INT32_MAX; // INT32_MAX :invalid value. - //apiVersion states - uint32_t apiVersion_ = 8; - // VM memory management. std::unique_ptr nativeAreaAllocator_; std::unique_ptr heapRegionAllocator_; diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 48dfa108a82a508303b108c2f5aecc2ee3e96592..125034107968a8c018eb93e2b0804c68c0311bbb 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -112,6 +112,19 @@ enum ThreadType : uint8_t { DAEMON_THREAD, }; +enum class APIVersion: uint32_t { + APIVersion12 = 12, + APIVersion13, + APIVersion14, + APIVersion15, + APIVersion16, + APIVersion17, + APIVersion18, + APIVersion19, + APIVersion20, + APIVersion21, +}; + using BaseThread = common::BaseThread; using BaseThreadType = common::BaseThreadType; @@ -1162,6 +1175,7 @@ public: ElementsHClassEntries, base::AlignedPointer, base::AlignedUint32, + base::AlignedUint32, base::AlignedBool> { enum class Index : size_t { BcStubEntriesIndex = 0, @@ -1220,6 +1234,7 @@ public: moduleLoggerIndex, stageOfHotReloadIndex, isMultiContextTriggeredIndex, + apiVersionIndex, NumOfMembers }; static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); @@ -1518,6 +1533,10 @@ public: return GetOffset(Index::isMultiContextTriggeredIndex)>( isArch32); } + static size_t GetApiVersionOffset(bool isArch32) + { + return GetOffset(Index::apiVersionIndex)>(isArch32); + } alignas(EAS) BCStubEntries bcStubEntries_ {}; alignas(EAS) uint32_t isEnableCMCGC_ {0}; @@ -1575,6 +1594,7 @@ public: alignas(EAS) ModuleLogger *moduleLogger_ {nullptr}; alignas(EAS) StageOfHotReload stageOfHotReload_ {StageOfHotReload::INITIALIZE_STAGE_OF_HOTRELOAD}; alignas(EAS) bool isMultiContextTriggered_ {false}; + alignas(EAS) uint32_t apiVersion_ {8}; }; STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64); @@ -1617,6 +1637,16 @@ public: glueData_.isMultiContextTriggered_ = isMultiContextTriggered; } + uint32_t GetAPIVersion() const + { + return glueData_.apiVersion_; + } + + void SetAPIVersion(uint32_t apiVersion) + { + glueData_.apiVersion_ = apiVersion; + } + JSHandle GetDependentInfo() const; void SetDependentInfo(JSTaggedValue info); diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index 8ecb46fa4ce16e01681750fbfe2dfecd9aeb1ac9..12295a9813577c4ab85e8bef50b3cf6715d79d04 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -5942,7 +5942,7 @@ uint32_t JSNApi::GetCurrentThreadId() void JSNApi::SetVMAPIVersion(EcmaVM *vm, const int32_t apiVersion) { - vm->SetVMAPIVersion(static_cast(apiVersion) % API_VERSION_MASK); + vm->GetJSThread()->SetAPIVersion(static_cast(apiVersion) % API_VERSION_MASK); } void JSNApi::UpdateStackInfo(EcmaVM *vm, void *currentStackInfo, uint32_t opKind) diff --git a/ecmascript/tagged_tree.cpp b/ecmascript/tagged_tree.cpp index a6b7b41c8095f42292ad46fdf2c97c53bbe54e6f..ddb3c1950ab981d066c178a0deca45566167ea4c 100644 --- a/ecmascript/tagged_tree.cpp +++ b/ecmascript/tagged_tree.cpp @@ -474,7 +474,7 @@ JSHandle TaggedTree::GrowCapacity(const JSThread *thread, JSHa int length = ELEMENTS_START_INDEX + newCapacity * (Derived::ENTRY_SIZE); JSHandle newTree = AdjustTaggedTree(thread, tree, length); // 20 : version isolation at api20 - if (thread->GetEcmaVM()->GetVMAPIVersion() >= 20) { + if (thread->GetAPIVersion() >= 20) { JSTaggedValue fn = tree->GetCompare(thread); if (!fn.IsUndefined() && !fn.IsNull()) { newTree->SetCompare(thread, fn); diff --git a/test/moduletest/stringreplace/stringreplace.js b/test/moduletest/stringreplace/stringreplace.js index 8881e90d5c0988485edb438aad49126861b4ec23..d646366ee687c001dc8004f9ce432b7c8efcfad1 100644 --- a/test/moduletest/stringreplace/stringreplace.js +++ b/test/moduletest/stringreplace/stringreplace.js @@ -111,4 +111,8 @@ let v5 = String.fromCharCode(0).replaceAll(/(?.)/ug); assert_equal("undefinedss".replace(undefined,v5),"undefinedss"); assert_equal("undefinedss".replaceAll(undefined,v5),"undefinedss"); +let str = "dddd" +res = str.replace("", "abc"); +assert_equal(res, "abcdddd"); + test_end(); \ No newline at end of file