• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/ecma_vm.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_handle.h"
19 #include "ecmascript/js_runtime_options.h"
20 #include "ecmascript/log.h"
21 #include "ecmascript/mem/concurrent_marker.h"
22 #include "ecmascript/mem/space.h"
23 #include "ecmascript/mem/verification.h"
24 #include "ecmascript/object_factory.h"
25 #include "ecmascript/tagged_array-inl.h"
26 #include "ecmascript/tests/test_helper.h"
27 
28 #include <csetjmp>
29 #include <csignal>
30 using namespace panda::ecmascript;
31 
32 namespace panda::test {
33 class ReadOnlySpaceTest : public testing::Test {
34 public:
SetUpTestCase()35     static void SetUpTestCase()
36     {
37         GTEST_LOG_(INFO) << "SetUpTestCase";
38     }
39 
TearDownTestCase()40     static void TearDownTestCase()
41     {
42         GTEST_LOG_(INFO) << "TearDownCase";
43     }
44 
SetUp()45     void SetUp() override
46     {
47         InitializeLogger();
48         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
49         factory = thread->GetEcmaVM()->GetFactory();
50         const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())->SetMarkType(MarkType::MARK_FULL);
51     }
52 
InitializeLogger()53     void InitializeLogger()
54     {
55         panda::ecmascript::JSRuntimeOptions runtimeOptions;
56         runtimeOptions.SetLogLevel("error");
57         ecmascript::Log::Initialize(runtimeOptions);
58     }
59 
TearDown()60     void TearDown() override
61     {
62         TestHelper::DestroyEcmaVMWithScope(instance, scope);
63     }
64 
65     JSThread *thread {nullptr};
66     ObjectFactory *factory {nullptr};
67     EcmaVM *instance {nullptr};
68     ecmascript::EcmaHandleScope *scope {nullptr};
69 };
70 
71 static sigjmp_buf g_env;
72 static bool g_segmentfault_flag = false;
73 class ReadOnlyTestManager {
74 public:
75     // static constexpr int RO_SEGMENTFAULT = 1;
ProcessReadOnlySegmentFault(int sig)76     static void ProcessReadOnlySegmentFault(int sig)
77     {
78         g_segmentfault_flag = true;
79         siglongjmp(g_env, sig);
80     }
81 
RegisterSignal()82     static int RegisterSignal()
83     {
84         struct sigaction act;
85         act.sa_handler = ProcessReadOnlySegmentFault;
86         sigemptyset(&act.sa_mask);
87         sigaddset(&act.sa_mask, SIGQUIT);
88         act.sa_flags = SA_RESETHAND;
89         return sigaction(SIGSEGV, &act, nullptr);
90     }
91 };
92 
HWTEST_F_L0(ReadOnlySpaceTest,ReadOnlyTest)93 HWTEST_F_L0(ReadOnlySpaceTest, ReadOnlyTest)
94 {
95     auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
96     heap->GetReadOnlySpace()->SetReadOnly();
97     if (ReadOnlyTestManager::RegisterSignal() == -1) {
98         perror("sigaction error");
99         exit(1);
100     }
101     auto ret = sigsetjmp(g_env, 1);
102     if (ret != SIGSEGV) {
103         heap->AllocateReadOnlyOrHugeObject(
104             JSHClass::Cast(thread->GlobalConstants()->GetBigIntClass().GetTaggedObject()));
105     } else {
106         // catch signal SIGSEGV caused by modify read only memory
107         EXPECT_TRUE(g_segmentfault_flag);
108     }
109 }
110 
HWTEST_F_L0(ReadOnlySpaceTest,AllocateTest)111 HWTEST_F_L0(ReadOnlySpaceTest, AllocateTest)
112 {
113     auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
114     auto *object = heap->AllocateReadOnlyOrHugeObject(
115         JSHClass::Cast(thread->GlobalConstants()->GetBigIntClass().GetTaggedObject()));
116     auto *region = Region::ObjectAddressToRange(object);
117     EXPECT_TRUE(region->InReadOnlySpace());
118 }
119 
HWTEST_F_L0(ReadOnlySpaceTest,CompactHeapBeforeForkTest)120 HWTEST_F_L0(ReadOnlySpaceTest, CompactHeapBeforeForkTest)
121 {
122     auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
123     std::string rawStr = "test string";
124     JSHandle<EcmaString> string = factory->NewFromStdString(rawStr);
125     JSHandle<JSObject> obj = factory->NewEmptyJSObject();
126     auto *regionBefore = Region::ObjectAddressToRange(string.GetObject<TaggedObject>());
127     auto *objRegionBefore = Region::ObjectAddressToRange(obj.GetObject<TaggedObject>());
128     EXPECT_FALSE(regionBefore->InReadOnlySpace());
129     EXPECT_FALSE(objRegionBefore->InReadOnlySpace());
130     heap->CompactHeapBeforeFork();
131     auto *regionAfter = Region::ObjectAddressToRange(string.GetObject<TaggedObject>());
132     auto *objRegionAfter = Region::ObjectAddressToRange(obj.GetObject<TaggedObject>());
133     EXPECT_TRUE(regionAfter->InReadOnlySpace());
134     EXPECT_FALSE(objRegionAfter->InReadOnlySpace());
135 }
136 
HWTEST_F_L0(ReadOnlySpaceTest,GCTest)137 HWTEST_F_L0(ReadOnlySpaceTest, GCTest)
138 {
139     auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
140     auto *object = heap->AllocateReadOnlyOrHugeObject(
141         JSHClass::Cast(thread->GlobalConstants()->GetBigIntClass().GetTaggedObject()));
142     heap->CollectGarbage(TriggerGCType::YOUNG_GC);
143     heap->CollectGarbage(TriggerGCType::OLD_GC);
144     heap->CollectGarbage(TriggerGCType::FULL_GC);
145     auto *region = Region::ObjectAddressToRange(object);
146     EXPECT_TRUE(region->InReadOnlySpace());
147 }
148 
HWTEST_F_L0(ReadOnlySpaceTest,ForkTest)149 HWTEST_F_L0(ReadOnlySpaceTest, ForkTest)
150 {
151     auto vm = thread->GetEcmaVM();
152     auto *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
153     std::string rawStr = "fork string";
154     JSHandle<EcmaString> string = factory->NewFromStdString(rawStr);
155     JSNApi::PreFork(vm);
156     if (fork() != 0) {
157         // test gc in parent process
158         heap->CollectGarbage(TriggerGCType::OLD_GC);
159     } else {
160         panda::RuntimeOption postOption;
161         JSNApi::PostFork(vm, postOption);
162         // test gc in child process
163         heap->CollectGarbage(TriggerGCType::OLD_GC);
164         auto *region = Region::ObjectAddressToRange(string.GetObject<TaggedObject>());
165         EXPECT_TRUE(region->InReadOnlySpace());
166     }
167 }
168 }  // namespace panda::test
169