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/tests/test_helper.h" 17 18#include "ecmascript/ecma_vm.h" 19#include "ecmascript/global_env.h" 20#include "ecmascript/js_handle.h" 21#include "ecmascript/mem/clock_scope.h" 22#include "ecmascript/mem/concurrent_marker.h" 23#include "ecmascript/mem/verification.h" 24 25using namespace panda::ecmascript; 26 27namespace panda::test { 28class ConcurrentMarkingTest : public BaseTestWithScope<false> { 29public: 30 void SetUp() override 31 { 32 JSRuntimeOptions options; 33 instance = JSNApi::CreateEcmaVM(options); 34 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; 35 thread = instance->GetJSThread(); 36 thread->ManagedCodeBegin(); 37 scope = new EcmaHandleScope(thread); 38 instance->SetEnableForceGC(false); 39 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 40 heap->GetConcurrentMarker()->EnableConcurrentMarking(EnableConcurrentMarkType::ENABLE); 41 } 42 43 JSHandle<TaggedArray> CreateTaggedArray(uint32_t length, JSTaggedValue initVal, MemSpaceType spaceType) 44 { 45 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 46 return factory->NewTaggedArray(length, initVal, spaceType); 47 } 48}; 49 50HWTEST_F_L0(ConcurrentMarkingTest, PerformanceWithConcurrentMarking) 51{ 52 uint32_t length = 1_KB; 53 JSHandle<TaggedArray> rootArray = 54 CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 55 for (uint32_t i = 0; i < length; i++) { 56 auto array = CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 57 rootArray->Set(thread, i, array); 58 } 59 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 60 heap->TriggerConcurrentMarking(); // concurrent mark 61 for (uint32_t i = 0; i < length; i++) { 62 auto array = CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 63 rootArray->Set(thread, i, array); 64 } 65 heap->CollectGarbage(TriggerGCType::OLD_GC); 66} 67 68HWTEST_F_L0(ConcurrentMarkingTest, PerformanceWithoutConcurrentMarking) 69{ 70 uint32_t length = 1_KB; 71 JSHandle<TaggedArray> rootArray = 72 CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 73 for (uint32_t i = 0; i < length; i++) { 74 auto array = CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 75 rootArray->Set(thread, i, array); 76 } 77 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 78 for (uint32_t i = 0; i < length; i++) { 79 auto array = CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 80 rootArray->Set(thread, i, array); 81 } 82 heap->CollectGarbage(TriggerGCType::OLD_GC); 83} 84 85HWTEST_F_L0(ConcurrentMarkingTest, ConcurrentMarkingWithOldSpace) 86{ 87 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 88 if (heap->GetConcurrentMarker()->IsEnabled()) { 89 heap->SetFullMarkRequestedState(false); 90 { 91 [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread); 92 uint32_t length = 1_KB; 93 for (uint32_t i = 0; i < length * 2; i++) { 94 [[maybe_unused]] auto array = 95 CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE); 96 } 97 98 heap->GetOldSpace()->SetInitialCapacity(static_cast<size_t>(length)); 99 EXPECT_FALSE(heap->IsConcurrentFullMark()); 100 heap->TryTriggerConcurrentMarking(); 101 EXPECT_TRUE(heap->IsConcurrentFullMark()); 102 } 103 } 104} 105 106HWTEST_F_L0(ConcurrentMarkingTest, ConcurrentMarkingWithNewSpace) 107{ 108 auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 109 heap->SetFullMarkRequestedState(false); 110 { 111 [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread); 112 uint32_t length = 1_KB; 113 for (uint32_t i = 0; i < length * 2; i++) { 114 [[maybe_unused]] auto array = 115 CreateTaggedArray(length, JSTaggedValue::Undefined(), MemSpaceType::SEMI_SPACE); 116 } 117 118 heap->GetNewSpace()->SetInitialCapacity(static_cast<size_t>(length)); 119 EXPECT_FALSE(heap->IsConcurrentFullMark()); 120 heap->TryTriggerConcurrentMarking(); 121 EXPECT_TRUE(!heap->IsConcurrentFullMark()); 122 } 123} 124 125HWTEST_F_L0(ConcurrentMarkingTest, ConcurrentMarkingWithFreshRegion) 126{ 127 Heap *heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap()); 128 if (heap->GetConcurrentMarker()->IsEnabled()) { 129 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 130 131 heap->CollectGarbage(TriggerGCType::FULL_GC); 132 JSHandle<TaggedArray> arr = factory->NewTaggedArray(1); 133 EXPECT_TRUE(!thread->IsConcurrentMarkingOrFinished()); 134 135 SemiSpace *space = heap->GetNewSpace(); 136 EXPECT_TRUE(space->Expand(false)); 137 Region *region = space->GetCurrentRegion(); 138 EXPECT_TRUE(!region->IsFreshRegion()); 139 140 JSHandle<JSHClass> hclass(thread, thread->GlobalConstants()->GetObjectClass().GetTaggedObject()); 141 uint32_t numInlinedProps = hclass->GetInlinedProperties(); 142 EXPECT_TRUE(numInlinedProps == JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); 143 uint32_t size = hclass->GetObjectSize(); 144 EXPECT_TRUE(size == JSObject::SIZE + numInlinedProps * sizeof(JSTaggedValue)); 145 uintptr_t addr = space->Allocate(size); 146 EXPECT_TRUE(addr != 0); 147 JSObject *obj = reinterpret_cast<JSObject*>(addr); 148 149 JSHandle<TaggedArray> emptyArray = factory->EmptyArray(); 150 factory->InitializeExtraProperties(hclass, obj, numInlinedProps); 151 obj->InitializeHash(); 152 obj->SetElements(thread, emptyArray, SKIP_BARRIER); 153 obj->SetProperties(thread, emptyArray, SKIP_BARRIER); 154 obj->SynchronizedSetClass(thread, *hclass); 155 156 arr->Set(thread, 0, JSTaggedValue(obj)); 157 158 heap->SetMarkType(MarkType::MARK_YOUNG); 159 heap->TriggerConcurrentMarking(); 160 EXPECT_TRUE(thread->IsConcurrentMarkingOrFinished()); 161 EXPECT_TRUE(region->IsHalfFreshRegion()); 162 region->SetRegionTypeFlag(RegionTypeFlag::FRESH); 163 EXPECT_TRUE(region->IsFreshRegion()); 164 165 heap->WaitConcurrentMarkingFinished(); 166 JSHandle<JSObject> objHandle(thread, obj); 167 heap->GetConcurrentMarker()->HandleMarkingFinished(); 168 } 169} 170 171HWTEST_F_L0(ConcurrentMarkingTest, ConcurrentMarkingRequestBySharedSize) 172{ 173 SharedHeap::GetInstance()->TryTriggerLocalConcurrentMarking(); 174} 175} // namespace panda::test 176