1 /* 2 * Copyright (c) 2025 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 #ifndef ECMASCRIPT_BASE_GC_HELPER_H 17 #define ECMASCRIPT_BASE_GC_HELPER_H 18 19 #include "ecmascript/mem/barriers.h" 20 #include "ecmascript/js_function.h" 21 #include "ecmascript/js_generator_object.h" 22 #include "ecmascript/mem/tagged_object.h" 23 #include "ecmascript/tagged_array.h" 24 25 namespace panda::ecmascript::base { 26 class GCHelper { 27 public: CopyCallTarget(const JSThread * thread,void * callTargetToRef)28 static inline void CopyCallTarget(const JSThread *thread, void *callTargetToRef) 29 { 30 if (!JSTaggedValue(static_cast<JSTaggedType>(ToUintPtr(callTargetToRef))).IsHeapObject()) { 31 return; 32 } 33 Barriers::UpdateSlot(thread, callTargetToRef, TaggedObject::HCLASS_OFFSET); 34 if (JSTaggedValue(reinterpret_cast<TaggedObject*>(callTargetToRef)).IsJSProxy()) { 35 // JSProxy 36 TaggedObject *methodToRef = 37 reinterpret_cast<TaggedObject *>(Barriers::UpdateSlot(thread, callTargetToRef, JSProxy::METHOD_OFFSET)); 38 Barriers::UpdateSlot(thread, methodToRef, Method::CONSTANT_POOL_OFFSET); 39 } else if (JSTaggedValue(reinterpret_cast<TaggedObject*>(callTargetToRef)).IsJSFunctionBase()) { 40 // JSFunctionBase 41 TaggedObject *methodToRef = reinterpret_cast<TaggedObject *>( 42 Barriers::UpdateSlot(thread, callTargetToRef, JSFunctionBase::METHOD_OFFSET)); 43 Barriers::UpdateSlot(thread, methodToRef, Method::CONSTANT_POOL_OFFSET); 44 // JSFunction : FunctionBase 45 if (JSTaggedValue(reinterpret_cast<TaggedObject*>(callTargetToRef)).IsJSFunction()) { 46 TaggedObject *profileTypeInfoToRef = reinterpret_cast<TaggedObject *>( 47 Barriers::UpdateSlot(thread, callTargetToRef, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET)); 48 Barriers::UpdateSlot(thread, profileTypeInfoToRef, ProfileTypeInfoCell::VALUE_OFFSET); 49 Barriers::UpdateSlot(thread, callTargetToRef, JSFunction::LEXICAL_ENV_OFFSET); 50 } 51 // BoundFunction : FunctionBase 52 if (JSTaggedValue(reinterpret_cast<TaggedObject*>(callTargetToRef)).IsBoundFunction()) { 53 auto toTaggedArray = reinterpret_cast<TaggedObject *>( 54 Barriers::UpdateSlot(thread, callTargetToRef, JSBoundFunction::BOUND_ARGUMENTS_OFFSET)); 55 auto boundTargetToRef = reinterpret_cast<TaggedObject *>( 56 Barriers::UpdateSlot(thread, callTargetToRef, JSBoundFunction::BOUND_TARGET_OFFSET)); 57 Barriers::UpdateSlot(thread, callTargetToRef, JSBoundFunction::BOUND_THIS_OFFSET); 58 CopyCallTarget(thread, boundTargetToRef); 59 60 uintptr_t argvAddr = ToUintPtr(toTaggedArray) + TaggedArray::DATA_OFFSET; 61 void *argvToRef = reinterpret_cast<void *>(argvAddr); 62 uint64_t argc = 63 static_cast<uint64_t>(Barriers::GetPrimitive<uint32_t>(toTaggedArray, TaggedArray::LENGTH_OFFSET)); 64 CopyArgvArray(thread, argvToRef, argc); 65 } 66 } else { 67 ASSERT(!JSTaggedValue(reinterpret_cast<TaggedObject*>(callTargetToRef)).IsCallable()); 68 } 69 } 70 CopyArgvArray(const JSThread * thread,void * argvToRef,uint64_t argc)71 static inline void CopyArgvArray(const JSThread *thread, void *argvToRef, uint64_t argc) 72 { 73 for (uint64_t i = 0; i < argc; i++) { 74 size_t offset = i * sizeof(JSTaggedType); 75 Barriers::UpdateSlot(thread, argvToRef, offset); 76 } 77 } 78 CopyGeneratorContext(const JSThread * thread,void * contextToRef)79 static inline void CopyGeneratorContext(const JSThread *thread, void *contextToRef) 80 { 81 Barriers::UpdateSlot(thread, contextToRef, GeneratorContext::GENERATOR_METHOD_OFFSET); 82 Barriers::UpdateSlot(thread, contextToRef, GeneratorContext::GENERATOR_THIS_OFFSET); 83 Barriers::UpdateSlot(thread, contextToRef, GeneratorContext::GENERATOR_LEXICALENV_OFFSET); 84 Barriers::UpdateSlot(thread, contextToRef, GeneratorContext::GENERATOR_ACC_OFFSET); 85 TaggedObject *toTaggedArray = reinterpret_cast<TaggedObject *>( 86 Barriers::UpdateSlot(thread, contextToRef, GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET)); 87 uintptr_t argvAddr = ToUintPtr(toTaggedArray) + TaggedArray::DATA_OFFSET; 88 void *argvToRef = reinterpret_cast<void *>(argvAddr); 89 uint64_t argc = static_cast<uint64_t>( 90 Barriers::GetPrimitive<uint32_t>(contextToRef, GeneratorContext::GENERATOR_NREGS_OFFSET)); 91 CopyArgvArray(thread, argvToRef, argc); 92 } 93 }; 94 } 95 #endif // ECMASCRIPT_BASE_GC_HELPER_H 96