!3020 Adapt to Hot Patch and Add Testcases

Merge pull request !3020 from lijiamin/master
This commit is contained in:
openharmony_ci 2022-11-29 01:52:45 +00:00 committed by Gitee
commit 0875afa157
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 215 additions and 42 deletions

View File

@ -101,7 +101,12 @@ bool QuickFixLoader::LoadPatchInternal(JSThread *thread, const JSPandaFile *base
}
if (!ReplaceMethod(thread, baseFile, patchFile, baseConstpoolValues.value())) {
LOG_ECMA(ERROR) << "replace method failed";
LOG_ECMA(ERROR) << "Replace method failed";
return false;
}
if (isHotPatch_ && !ExecutePatchMain(thread, patchPrograms, patchFile)) {
LOG_ECMA(ERROR) << "Execute patch main failed";
return false;
}
@ -138,6 +143,13 @@ CVector<JSHandle<Program>> QuickFixLoader::ParseAllConstpoolWithMerge(JSThread *
uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex(recordName);
ASSERT(mainMethodIndex != 0);
const char *mainMethodName =
MethodLiteral::GetMethodName(jsPandaFile, panda_file::File::EntityId(mainMethodIndex));
if (!isHotPatch_ && std::strcmp(mainMethodName, JSPandaFile::PATCH_FUNCTION_NAME_0) == 0) {
isHotPatch_ = true;
}
if (!isNewVersion) {
PandaFileTranslator::ParseFuncAndLiteralConstPool(vm, jsPandaFile, recordName, constpool);
} else {
@ -404,49 +416,48 @@ bool QuickFixLoader::UnloadPatch(JSThread *thread, const CString &patchFileName)
return false;
}
for (const auto &iter : baseConstpoolValues.value().get()) {
uint32_t index = iter.first;
ConstantPool *baseConstpool = ConstantPool::Cast((iter.second).GetTaggedObject());
for (const auto &item : reservedBaseNormalMethodInfo_) {
NormalMethodIndex normalMethodIndex = item.first;
if (index == normalMethodIndex.constpoolNum) {
uint32_t constpoolIndex = normalMethodIndex.constpoolIndex;
MethodLiteral *base = item.second;
JSTaggedValue value = baseConstpool->GetObjectFromCache(constpoolIndex);
ASSERT(value.IsMethod());
Method *method = Method::Cast(value.GetTaggedObject());
JSTaggedValue baseConstpoolValue = FindConstpoolVal(thread, baseFile, base->GetMethodId());
ReplaceMethodInner(thread, method, base, baseConstpoolValue);
LOG_ECMA(INFO) << "Replace normal method: " << method->GetMethodName();
}
}
for (auto &item : reservedBaseClassMethodInfo_) {
ClassMethodIndex classMethodIndex = item.first;
if (index == classMethodIndex.constpoolNum) {
uint32_t constpoolIndex = classMethodIndex.constpoolIndex;
MethodLiteral *base = item.second;
TaggedArray *classLiteral = TaggedArray::Cast(baseConstpool->GetObjectFromCache(constpoolIndex));
JSTaggedValue value = classLiteral->Get(thread, classMethodIndex.literalIndex);
ASSERT(value.IsJSFunctionBase());
JSFunctionBase *func = JSFunctionBase::Cast(value.GetTaggedObject());
Method *method = Method::Cast(func->GetMethod().GetTaggedObject());
for (const auto &item : reservedBaseNormalMethodInfo_) {
NormalMethodIndex normalMethodIndex = item.first;
ConstantPool *baseConstpool = ConstantPool::Cast(
(baseConstpoolValues.value().get()[normalMethodIndex.constpoolNum]).GetTaggedObject());
JSTaggedValue baseConstpoolValue = FindConstpoolVal(thread, baseFile, base->GetMethodId());
ReplaceMethodInner(thread, method, base, baseConstpoolValue);
LOG_ECMA(INFO) << "Replace class method: " << method->GetMethodName();
}
}
uint32_t constpoolIndex = normalMethodIndex.constpoolIndex;
MethodLiteral *base = item.second;
JSTaggedValue value = baseConstpool->GetObjectFromCache(constpoolIndex);
ASSERT(value.IsMethod());
Method *method = Method::Cast(value.GetTaggedObject());
JSTaggedValue baseConstpoolValue = FindConstpoolVal(thread, baseFile, base->GetMethodId());
ReplaceMethodInner(thread, method, base, baseConstpoolValue);
LOG_ECMA(INFO) << "Replace normal method: " << method->GetMethodName();
}
for (auto &item : reservedBaseClassMethodInfo_) {
ClassMethodIndex classMethodIndex = item.first;
ConstantPool *baseConstpool = ConstantPool::Cast(
(baseConstpoolValues.value().get()[classMethodIndex.constpoolNum]).GetTaggedObject());
uint32_t constpoolIndex = classMethodIndex.constpoolIndex;
MethodLiteral *base = item.second;
TaggedArray *classLiteral = TaggedArray::Cast(baseConstpool->GetObjectFromCache(constpoolIndex));
JSTaggedValue value = classLiteral->Get(thread, classMethodIndex.literalIndex);
ASSERT(value.IsJSFunctionBase());
JSFunctionBase *func = JSFunctionBase::Cast(value.GetTaggedObject());
Method *method = Method::Cast(func->GetMethod().GetTaggedObject());
JSTaggedValue baseConstpoolValue = FindConstpoolVal(thread, baseFile, base->GetMethodId());
ReplaceMethodInner(thread, method, base, baseConstpoolValue);
LOG_ECMA(INFO) << "Replace class method: " << method->GetMethodName();
}
vm->GetJsDebuggerManager()->GetHotReloadManager()->NotifyPatchUnloaded(patchFile);
ClearReservedInfo();
ClearPatchInfo(thread, patchFileName);
isHotPatch_ = false;
LOG_ECMA(INFO) << "UnloadPatch success!";
return true;
}

View File

@ -84,6 +84,7 @@ private:
static bool CheckStarExportEntryMismatch(StarExportEntry *patch, StarExportEntry *base);
CString baseFileName_;
bool isHotPatch_ {false}; // true: HotPatch; false: HotReload.
struct NormalMethodIndex {
uint32_t constpoolNum {UINT32_MAX};

View File

@ -105,7 +105,7 @@ int Main(const int argc, const char **argv)
#endif
uint32_t len = fileNames.size();
if (len < 4) { // 4: four abc file
std::cout << "Must include base.abc, patch.abc, test1.abc, test2.abc absolute path" << std::endl;
std::cout << "Must include base.abc, patch.abc, test.abc, retest.abc absolute path" << std::endl;
return -1;
}
std::string baseFileName = fileNames[0];

View File

@ -13,7 +13,7 @@
import("//arkcompiler/ets_runtime/test/test_helper.gni")
test_list = [
hot_reload_test_list = [
"check_import",
"class_inheritance",
"class_mem_func",
@ -28,7 +28,7 @@ test_list = [
]
if (!is_debug) {
test_list += [
hot_reload_test_list += [
"multi_classconstpool",
"multi_closureconstpool",
"multi_constructorconstpool",
@ -37,6 +37,8 @@ if (!is_debug) {
]
}
hot_patch_test_list = [ "add_callfunction" ]
host_quickfix_test_action("multi_patch") {
extra_patches = [
"patch1",
@ -45,17 +47,28 @@ host_quickfix_test_action("multi_patch") {
entry_point = "--entry-point=base"
}
foreach(testcase, test_list) {
foreach(testcase, hot_reload_test_list) {
host_quickfix_test_action("${testcase}") {
entry_point = "--entry-point=base"
}
}
foreach(testcase, hot_patch_test_list) {
host_quickfix_test_action("${testcase}") {
entry_point = "--entry-point=base"
is_hotpatch = true
}
}
group("ark_quickfix_test") {
testonly = true
deps = []
foreach(testcase, test_list) {
foreach(testcase, hot_reload_test_list) {
deps += [ ":${testcase}QuickfixAction" ]
}
foreach(testcase, hot_patch_test_list) {
deps += [ ":${testcase}QuickfixAction" ]
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) 2022 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.
*/
function A() {
print("base A()");
B();
}
function B() {
print("base B()");
}
globalThis.A = A;
globalThis.B = B;

View File

@ -0,0 +1,2 @@
base.js;base;module;base.js
module.js;module;module;module.js

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2022 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.
*/
function A() {
print("patch A()");
B();
C();
}
function B() {
print("patch B()");
}
function C() {
print("patch C()");
}
globalThis.C = C;

View File

@ -0,0 +1,26 @@
# Copyright (c) 2022 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.
QuickFix Execute start
QuickFix start load patch
QuickFix load patch success
patch A()
patch B()
patch C()
QuickFix start check exception
QuickFix have no exception
QuickFix start unload patch
QuickFix unload patch success
base A()
base B()
QuickFix Execute end

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2022 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.
*/
export var nop = undefined

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2022 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.
*/
export var nop = undefined

View File

@ -0,0 +1,2 @@
base_modify.js;base;module;base.js
module_modify.js;module;module;module.js

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2022 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.
*/
A()

View File

@ -663,6 +663,10 @@ template("host_quickfix_test_action") {
_script_args_ = invoker.entry_point + " "
}
if (defined(invoker.is_hotpatch) && invoker.is_hotpatch) {
_test_map_path_ = "$target_out_dir/${_target_name_}/base.map"
}
foreach(filename, _test_file_name_) {
merge_file_raw = "//arkcompiler/ets_runtime/test/quickfix/"
if (filename == "test" || filename == "retest") {
@ -703,10 +707,23 @@ template("host_quickfix_test_action") {
"--merge-abc",
]
if (defined(invoker.is_hotpatch) && filename == "patch") {
extra_args += [ "--generate-patch" ]
}
if (defined(invoker.is_hotpatch) && filename == "base") {
dump_symbol_table = rebase_path(_test_map_path_)
}
if (defined(invoker.is_hotpatch) && filename == "patch") {
input_symbol_table = rebase_path(_test_map_path_)
}
in_puts = [
_test_expect_path_,
merge_file,
]
out_puts = [ abc_path ]
}