From cfa142fd598be2895d82737f9e71c2b3ed8e9f3e Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 16 Sep 2024 18:42:15 +0800 Subject: [PATCH] Fix wrong kind of method when different thread define sendable class 1. Only set kind when set inherit relationship 2. Support create sendable array with double-type length Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IARLPQ Signed-off-by: wengchangcheng Change-Id: I18b971cb5327ac8555e288c0129497f7c8d72dfd --- ecmascript/builtins/builtins_shared_array.cpp | 6 +- .../tests/builtins_shared_array_test.cpp | 79 +++++++++++++++++-- .../jspandafile/class_info_extractor.cpp | 11 ++- 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/ecmascript/builtins/builtins_shared_array.cpp b/ecmascript/builtins/builtins_shared_array.cpp index a23a7a457b..278c3417ed 100644 --- a/ecmascript/builtins/builtins_shared_array.cpp +++ b/ecmascript/builtins/builtins_shared_array.cpp @@ -323,7 +323,7 @@ JSTaggedValue BuiltinsSharedArray::Create(EcmaRuntimeCallInfo *argv) } JSHandle thisHandle = GetThis(argv); JSHandle arrayLengthValue = GetCallArg(argv, 0); - if (!arrayLengthValue->IsInt()) { + if (!arrayLengthValue->IsNumber()) { auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } @@ -2446,7 +2446,7 @@ JSTaggedValue BuiltinsSharedArray::ShrinkTo(EcmaRuntimeCallInfo *argv) JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); JSHandle newLengthValue = GetCallArg(argv, 0); - if (!newLengthValue->IsInt()) { + if (!newLengthValue->IsNumber()) { auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } @@ -2485,7 +2485,7 @@ JSTaggedValue BuiltinsSharedArray::ExtendTo(EcmaRuntimeCallInfo *argv) JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); [[maybe_unused]] ConcurrentApiScope scope(thread, thisHandle); JSHandle newLengthValue = GetCallArg(argv, 0); - if (!newLengthValue->IsInt()) { + if (!newLengthValue->IsNumber()) { auto error = ContainerError::ParamError(thread, "Parameter error.Invalid array length."); THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } diff --git a/ecmascript/builtins/tests/builtins_shared_array_test.cpp b/ecmascript/builtins/tests/builtins_shared_array_test.cpp index f19f0feca9..3c6470f20f 100644 --- a/ecmascript/builtins/tests/builtins_shared_array_test.cpp +++ b/ecmascript/builtins/tests/builtins_shared_array_test.cpp @@ -1215,8 +1215,9 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, At_TWO) ASSERT_EQ(result, JSTaggedValue::Undefined()); } -HWTEST_F_L0(BuiltinsSharedArrayTest, Create) +HWTEST_F_L0(BuiltinsSharedArrayTest, Create1) { + static int32_t len = 3; JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))->GetTaggedObject()); EXPECT_TRUE(arr != nullptr); JSHandle obj(thread, arr); @@ -1228,14 +1229,38 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, Create) auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, array.GetTaggedValue(), 8); ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined()); - ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(3))); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(len)); ecmaRuntimeCallInfo1->SetCallArg(1, obj.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); JSTaggedValue result = Array::Create(ecmaRuntimeCallInfo1); TestHelper::TearDownFrame(thread, prev); - JSTaggedValue value(static_cast(result.GetRawData())); - ASSERT_TRUE(value.IsECMAObject()); + ASSERT_TRUE(result.IsECMAObject()); + EXPECT_EQ(JSSharedArray::Cast(result.GetTaggedObject())->GetArrayLength(), len); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, Create2) +{ + static double len = 100; + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))->GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); + EXPECT_EQ(JSSharedArray::GetProperty(thread, JSHandle(obj), lengthKeyHandle, SCheckMode::SKIP) \ + .GetValue()->GetInt(), 0); + + JSHandle array(thread->GetEcmaVM()->GetGlobalEnv()->GetSharedArrayFunction()); + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, array.GetTaggedValue(), 8); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(len)); + ecmaRuntimeCallInfo1->SetCallArg(1, obj.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::Create(ecmaRuntimeCallInfo1); + TestHelper::TearDownFrame(thread, prev); + ASSERT_TRUE(result.IsECMAObject()); + EXPECT_EQ(JSSharedArray::Cast(result.GetTaggedObject())->GetArrayLength(), len); } // Array.isArray(arg) @@ -1314,7 +1339,7 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, Unscopables) ASSERT_TRUE(value.IsECMAObject()); } -HWTEST_F_L0(BuiltinsSharedArrayTest, ShrinkTo) +HWTEST_F_L0(BuiltinsSharedArrayTest, ShrinkTo1) { JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(10))->GetTaggedObject()); EXPECT_TRUE(arr != nullptr); @@ -1336,7 +1361,29 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, ShrinkTo) TestHelper::TearDownFrame(thread, prev); } -HWTEST_F_L0(BuiltinsSharedArrayTest, ExtendTo) +HWTEST_F_L0(BuiltinsSharedArrayTest, ShrinkTo2) +{ + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(10))->GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + + std::vector descVals{1, 2, 3, 4, 5}; + auto keys = SharedArrayDefineOwnPropertyTest(thread, obj, descVals); + + JSHandle array(thread->GetEcmaVM()->GetGlobalEnv()->GetSharedArrayFunction()); + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, array.GetTaggedValue(), 6); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(3))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::ShrinkTo(ecmaRuntimeCallInfo1); + EXPECT_EQ(result, JSTaggedValue::Undefined()); + EXPECT_EQ(arr->GetArrayLength(), 3U); + TestHelper::TearDownFrame(thread, prev); +} + +HWTEST_F_L0(BuiltinsSharedArrayTest, ExtendTo1) { JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))->GetTaggedObject()); EXPECT_TRUE(arr != nullptr); @@ -1356,6 +1403,26 @@ HWTEST_F_L0(BuiltinsSharedArrayTest, ExtendTo) TestHelper::TearDownFrame(thread, prev); } +HWTEST_F_L0(BuiltinsSharedArrayTest, ExtendTo2) +{ + JSSharedArray *arr = JSSharedArray::Cast(JSSharedArray::ArrayCreate(thread, JSTaggedNumber(0))->GetTaggedObject()); + EXPECT_TRUE(arr != nullptr); + JSHandle obj(thread, arr); + + JSHandle array(thread->GetEcmaVM()->GetGlobalEnv()->GetSharedArrayFunction()); + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, array.GetTaggedValue(), 8); + ecmaRuntimeCallInfo1->SetFunction(array.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetThis(obj.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue(static_cast(3))); + ecmaRuntimeCallInfo1->SetCallArg(1, obj.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1); + JSTaggedValue result = Array::ExtendTo(ecmaRuntimeCallInfo1); + ASSERT_EQ(result, JSTaggedValue::Undefined()); + EXPECT_EQ(arr->GetArrayLength(), 3U); + TestHelper::TearDownFrame(thread, prev); +} + bool TestSharedArraySetProperty(EcmaRuntimeCallInfo *argv) { JSThread *thread = argv->GetThread(); diff --git a/ecmascript/jspandafile/class_info_extractor.cpp b/ecmascript/jspandafile/class_info_extractor.cpp index a89d87afdb..fca1c15a18 100644 --- a/ecmascript/jspandafile/class_info_extractor.cpp +++ b/ecmascript/jspandafile/class_info_extractor.cpp @@ -752,7 +752,16 @@ JSHandle SendableClassDefiner::DefineSendableClassFromExtractor(JSTh JSHandle constructorHClass = ClassInfoExtractor::CreateSendableHClass(thread, staticKeys, staticProperties, false, staticFields); JSHandle method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())); - method->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR); + /* + * Method::SetFunctionKind can't be called here, because method will set kind when set inheritance relationship, + * so there is a multi-threading problem with multi-threads define sendable DERIVED class at the same time. + * Scenario: + * A thread: define DERIVED class X [X's kind = DEFAULT --> BASE CLASS --> DERIVED CLASS], new X() + * B thread: define DERIVED class X [X's kind = DEFAULT --> BASE CLASS --> DERIVED CLASS], new X() + * Issue: + * When A thread new DERIVED class X, X's kind maybe set to BASE CLASS at B thread, + * and A thread will throw error when call super(). + */ if (!constructorHClass->IsDictionaryMode() && staticFields > 0) { auto layout = JSHandle(thread, constructorHClass->GetLayout()); AddFieldTypeToHClass(thread, staticFieldArray, length, layout, constructorHClass, ~0U); -- Gitee