1 /** 2 * Copyright (c) 2022-2024 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 #ifndef PANDA_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 16 #define PANDA_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 17 18 #include "runtime/coroutines/coroutine_context.h" 19 #include "plugins/ets/runtime/ets_napi_env.h" 20 #include "runtime/coroutines/coroutine.h" 21 #include "runtime/coroutines/coroutine_manager.h" 22 23 namespace ark::ets { 24 class PandaEtsVM; 25 26 /// @brief The eTS coroutine. It is aware of the native interface and reference storage existance. 27 class EtsCoroutine : public Coroutine { 28 public: 29 NO_COPY_SEMANTIC(EtsCoroutine); 30 NO_MOVE_SEMANTIC(EtsCoroutine); 31 32 /** 33 * @brief EtsCoroutine factory: the preferrable way to create a coroutine. See CoroutineManager::CoroutineFactory 34 * for details. 35 * 36 * Since C++ requires function type to exactly match the formal parameter type, we have to make this factory a 37 * template. The sole purpose for this is to be able to return both Coroutine* and EtsCoroutine* 38 */ 39 template <class T> 40 static T *Create(Runtime *runtime, PandaVM *vm, PandaString name, CoroutineContext *context, 41 std::optional<EntrypointInfo> &&epInfo = std::nullopt) 42 { 43 mem::InternalAllocatorPtr allocator = runtime->GetInternalAllocator(); 44 auto co = allocator->New<EtsCoroutine>(os::thread::GetCurrentThreadId(), allocator, vm, std::move(name), 45 context, std::move(epInfo)); 46 co->Initialize(); 47 return co; 48 } 49 ~EtsCoroutine() override = default; 50 CastFromThread(Thread * thread)51 static EtsCoroutine *CastFromThread(Thread *thread) 52 { 53 ASSERT(thread != nullptr); 54 return static_cast<EtsCoroutine *>(thread); 55 } 56 GetCurrent()57 static EtsCoroutine *GetCurrent() 58 { 59 Coroutine *co = Coroutine::GetCurrent(); 60 if ((co != nullptr) && co->GetThreadLang() == ark::panda_file::SourceLang::ETS) { 61 return CastFromThread(co); 62 } 63 return nullptr; 64 } 65 SetPromiseClass(void * promiseClass)66 void SetPromiseClass(void *promiseClass) 67 { 68 promiseClassPtr_ = promiseClass; 69 } 70 GetTlsPromiseClassPointerOffset()71 static constexpr uint32_t GetTlsPromiseClassPointerOffset() 72 { 73 return MEMBER_OFFSET(EtsCoroutine, promiseClassPtr_); 74 } 75 GetUndefinedObject()76 ALWAYS_INLINE ObjectHeader *GetUndefinedObject() const 77 { 78 return undefinedObj_; 79 } 80 81 // For mainthread initializer SetUndefinedObject(ObjectHeader * obj)82 void SetUndefinedObject(ObjectHeader *obj) 83 { 84 undefinedObj_ = obj; 85 } 86 GetTlsUndefinedObjectOffset()87 static constexpr uint32_t GetTlsUndefinedObjectOffset() 88 { 89 return MEMBER_OFFSET(EtsCoroutine, undefinedObj_); 90 } 91 92 PANDA_PUBLIC_API PandaEtsVM *GetPandaVM() const; 93 PANDA_PUBLIC_API CoroutineManager *GetCoroutineManager() const; 94 GetEtsNapiEnv()95 PandaEtsNapiEnv *GetEtsNapiEnv() const 96 { 97 return etsNapiEnv_.get(); 98 } 99 100 void Initialize() override; 101 void RequestCompletion(Value returnValue) override; 102 void FreeInternalMemory() override; 103 104 protected: 105 // we would like everyone to use the factory to create a EtsCoroutine 106 explicit EtsCoroutine(ThreadId id, mem::InternalAllocatorPtr allocator, PandaVM *vm, PandaString name, 107 CoroutineContext *context, std::optional<EntrypointInfo> &&epInfo); 108 109 private: 110 panda_file::Type GetReturnType(); 111 EtsObject *GetReturnValueAsObject(panda_file::Type returnType, Value returnValue); 112 EtsObject *GetValueFromPromiseSync(EtsPromise *promise); 113 114 std::unique_ptr<PandaEtsNapiEnv> etsNapiEnv_; 115 void *promiseClassPtr_ {nullptr}; 116 117 ObjectHeader *undefinedObj_ {}; 118 119 // Allocator calls our protected ctor 120 friend class mem::Allocator; 121 }; 122 } // namespace ark::ets 123 124 #endif // PANDA_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 125