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_string-inl.h" 17#include "ecmascript/ecma_vm.h" 18#include "ecmascript/global_env.h" 19#include "ecmascript/js_array.h" 20#include "ecmascript/js_function.h" 21#include "ecmascript/js_hclass.h" 22#include "ecmascript/js_object-inl.h" 23#include "ecmascript/js_primitive_ref.h" 24#include "ecmascript/js_tagged_value-inl.h" 25#include "ecmascript/lexical_env.h" 26#include "ecmascript/object_factory.h" 27#include "ecmascript/tagged_array-inl.h" 28#include "ecmascript/tests/test_helper.h" 29 30using namespace panda; 31 32using namespace panda::ecmascript; 33 34namespace panda::test { 35class ObjectFactoryTest : public BaseTestWithScope<false> { 36}; 37 38JSHandle<GlobalEnv> GetGlobal(JSThread *thread) 39{ 40 return thread->GetEcmaVM()->GetGlobalEnv(); 41} 42 43HWTEST_F_L0(ObjectFactoryTest, NewJSObjectByConstructor) 44{ 45 thread->GetEcmaVM()->SetEnableForceGC(false); 46 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 47 JSHandle<JSTaggedValue> objFun = GetGlobal(thread)->GetObjectFunction(); 48 49 // check mem alloc 50 JSHandle<JSObject> newObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun); 51 JSHandle<JSHClass> newObjCls(thread, newObj->GetJSHClass()); 52 EXPECT_TRUE(*newObj != nullptr); 53 EXPECT_TRUE(*newObjCls != nullptr); 54 55 // check feild 56 EXPECT_EQ(newObj->GetProperties(), thread->GlobalConstants()->GetEmptyArray()); 57 EXPECT_EQ(newObj->GetElements(), thread->GlobalConstants()->GetEmptyArray()); 58 EXPECT_TRUE(JSTaggedValue(*newObj).IsECMAObject()); 59 60 // check jshclass 61 JSHClass *cls = *newObjCls; 62 EXPECT_TRUE(cls->GetObjectSize() == 63 JSObject::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize()); 64 EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue()); 65 EXPECT_TRUE(cls->GetObjectType() == JSType::JS_OBJECT); 66 67 // check gc handle update 68 auto *prototype = cls->GetPrototype().GetTaggedObject(); 69 thread->GetEcmaVM()->CollectGarbage(TriggerGCType::FULL_GC); 70 // After FullGC 71 if (thread->GetEcmaVM()->GetJSOptions().EnableSnapshotDeserialize()) { 72 EXPECT_TRUE(prototype == newObjCls->GetPrototype().GetTaggedObject()); 73 } else { 74 EXPECT_TRUE(prototype != newObjCls->GetPrototype().GetTaggedObject()); 75 } 76 thread->GetEcmaVM()->SetEnableForceGC(true); 77} 78 79HWTEST_F_L0(ObjectFactoryTest, NewJSFunction) 80{ 81 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 82 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 83 84 // check mem alloc 85 JSHandle<JSFunction> newFun = factory->NewJSFunction(env); 86 JSHandle<JSHClass> newFunCls(thread, newFun->GetJSHClass()); 87 EXPECT_TRUE(*newFun != nullptr); 88 EXPECT_TRUE(*newFunCls != nullptr); 89 90 // check feild 91 EXPECT_EQ(newFun->GetProperties(), thread->GlobalConstants()->GetEmptyArray()); 92 EXPECT_EQ(newFun->GetElements(), thread->GlobalConstants()->GetEmptyArray()); 93 EXPECT_EQ(newFun->GetProtoOrHClass(), JSTaggedValue::Hole()); 94 EXPECT_EQ(newFun->GetHomeObject(), JSTaggedValue::Undefined()); 95 EXPECT_TRUE(JSTaggedValue(*newFun).IsJSFunction()); 96 97 // check jshclass 98 JSHClass *cls = *newFunCls; 99 EXPECT_TRUE(cls->GetObjectSize() == 100 JSFunction::SIZE + JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS * JSTaggedValue::TaggedTypeSize()); 101 EXPECT_TRUE(cls->GetPrototype() == GetGlobal(thread)->GetFunctionPrototype().GetTaggedValue()); 102 EXPECT_TRUE(cls->GetObjectType() == JSType::JS_FUNCTION); 103 EXPECT_TRUE(cls->IsCallable()); 104 EXPECT_TRUE(cls->IsExtensible()); 105 EXPECT_TRUE(!cls->IsConstructor()); 106} 107 108HWTEST_F_L0(ObjectFactoryTest, NewJSBoundFunction) 109{ 110 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 111 112 // test prepare 113 JSHandle<JSFunction> funFun(GetGlobal(thread)->GetObjectFunction()); 114 JSHandle<JSTaggedValue> bound(thread, GetGlobal(thread)->GetObjectFunctionPrototype().GetTaggedValue()); 115 const JSHandle<TaggedArray> array(thread->GlobalConstants()->GetHandledEmptyArray()); 116 117 // check mem alloc 118 JSHandle<JSBoundFunction> newBoundFun = 119 factory->NewJSBoundFunction(JSHandle<JSTaggedValue>::Cast(funFun), bound, array); 120 JSHandle<JSHClass> newBoundFunCls(thread, newBoundFun->GetJSHClass()); 121 EXPECT_TRUE(*newBoundFun != nullptr); 122 EXPECT_TRUE(*newBoundFunCls != nullptr); 123} 124 125HWTEST_F_L0(ObjectFactoryTest, NewJSPrimitiveRef) 126{ 127 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 128 129 // test prepare 130 JSHandle<JSFunction> numberFun(GetGlobal(thread)->GetNumberFunction()); 131 JSHandle<JSTaggedValue> primitive(thread, JSTaggedValue(1)); 132 133 // check mem alloc 134 JSHandle<JSPrimitiveRef> newPrimitive = factory->NewJSPrimitiveRef(numberFun, primitive); 135 JSHandle<JSHClass> newPrimitiveCls(thread, newPrimitive->GetJSHClass()); 136 EXPECT_TRUE(*newPrimitive != nullptr); 137 EXPECT_TRUE(*newPrimitiveCls != nullptr); 138 139 EXPECT_TRUE(newPrimitive->GetValue() == JSTaggedValue(1)); 140} 141 142HWTEST_F_L0(ObjectFactoryTest, NewLexicalEnv) 143{ 144 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 145 146 // check mem alloc 147 JSHandle<LexicalEnv> newLexicalEnv = factory->NewLexicalEnv(0); 148 JSHandle<JSHClass> newLexicalEnvCls(thread, newLexicalEnv->GetClass()); 149 EXPECT_TRUE(*newLexicalEnv != nullptr); 150 EXPECT_TRUE(*newLexicalEnvCls != nullptr); 151} 152 153HWTEST_F_L0(ObjectFactoryTest, NewJSArray) 154{ 155 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 156 157 // check mem alloc 158 JSHandle<JSArray> newJSAarray = factory->NewJSArray(); 159 JSHandle<JSHClass> newJSArrayCls(thread, newJSAarray->GetJSHClass()); 160 EXPECT_TRUE(*newJSAarray != nullptr); 161 EXPECT_TRUE(*newJSArrayCls != nullptr); 162} 163 164HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArray) 165{ 166 constexpr uint32_t SHORT_ELEMENT_NUMS = 20; 167 constexpr uint32_t LONG_ELEMENT_NUMS = 100; 168 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 169 JSHandle<TaggedArray> shortTaggedarray = factory->NewTaggedArray(SHORT_ELEMENT_NUMS); 170 // init tagggedArray 171 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) { 172 shortTaggedarray->Set(thread, i, JSTaggedValue(i)); 173 } 174 JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS, 175 SHORT_ELEMENT_NUMS); 176 JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS, 177 SHORT_ELEMENT_NUMS); 178 // check 179 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) { 180 EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i)); 181 EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i)); 182 } 183 for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) { 184 EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole()); 185 } 186} 187 188HWTEST_F_L0(ObjectFactoryTest, NewAndCopyTaggedArrayNeedBarrier) 189{ 190 constexpr uint32_t SHORT_ELEMENT_NUMS = 20; 191 constexpr uint32_t LONG_ELEMENT_NUMS = 100; 192 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 193 JSHandle<TaggedArray> shortTaggedarray = factory->NewTaggedArray(SHORT_ELEMENT_NUMS); 194 // init tagggedArray 195 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 196 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) { 197 JSHandle<JSFunction> newFun = factory->NewJSFunction(env); 198 shortTaggedarray->Set(thread, i, newFun); 199 } 200 JSHandle<TaggedArray> copiedShort = factory->NewAndCopyTaggedArray(shortTaggedarray, SHORT_ELEMENT_NUMS, 201 SHORT_ELEMENT_NUMS); 202 JSHandle<TaggedArray> copiedLong = factory->NewAndCopyTaggedArray(shortTaggedarray, LONG_ELEMENT_NUMS, 203 SHORT_ELEMENT_NUMS); 204 // check 205 for (uint32_t i = 0; i < SHORT_ELEMENT_NUMS; i++) { 206 EXPECT_EQ(copiedShort->Get(thread, i), shortTaggedarray->Get(thread, i)); 207 EXPECT_EQ(copiedLong->Get(thread, i), shortTaggedarray->Get(thread, i)); 208 } 209 for (uint32_t i = SHORT_ELEMENT_NUMS; i < LONG_ELEMENT_NUMS; i++) { 210 EXPECT_EQ(copiedLong->Get(thread, i), JSTaggedValue::Hole()); 211 } 212} 213} // namespace panda::test 214