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 PANDA_PLUGINS_ETS_ERROR_H 17 #define PANDA_PLUGINS_ETS_ERROR_H 18 19 #include "plugins/ets/runtime/ets_platform_types.h" 20 #include "plugins/ets/runtime/types/ets_object.h" 21 #include "plugins/ets/runtime/types/ets_string.h" 22 #include "plugins/ets/runtime/types/ets_array.h" 23 #include "plugins/ets/runtime/types/ets_stacktrace_element.h" 24 25 namespace ark::ets { 26 27 namespace test { 28 class EtsErrorTest; 29 } // namespace test 30 31 // class Error is mirror class for escompat.Error 32 // Currently, there is no necessity to declare this class as mirror in yaml files, 33 // this this class is auxiliary for describing std.core error classes as mirror classes. 34 class Error : public EtsObject { 35 public: 36 NO_COPY_SEMANTIC(Error); 37 NO_MOVE_SEMANTIC(Error); 38 39 Error() = delete; 40 ~Error() = delete; 41 Create(EtsCoroutine * coro,EtsClass * klass)42 static Error *Create(EtsCoroutine *coro, EtsClass *klass) 43 { 44 return FromEtsObject(EtsObject::Create(coro, klass)); 45 } 46 FromEtsObject(EtsObject * object)47 static Error *FromEtsObject(EtsObject *object) 48 { 49 return static_cast<Error *>(object); 50 } 51 AsObject()52 EtsObject *AsObject() 53 { 54 return this; 55 } 56 AsObject()57 const EtsObject *AsObject() const 58 { 59 return this; 60 } 61 SetName(EtsCoroutine * coro,EtsString * name)62 void SetName(EtsCoroutine *coro, EtsString *name) 63 { 64 ASSERT(name != nullptr); 65 ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, name_), name->GetCoreType()); 66 } 67 SetMessage(EtsCoroutine * coro,EtsString * msg)68 void SetMessage(EtsCoroutine *coro, EtsString *msg) 69 { 70 ASSERT(msg != nullptr); 71 ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, message_), msg->GetCoreType()); 72 } 73 SetStack(EtsCoroutine * coro,EtsString * stack)74 void SetStack(EtsCoroutine *coro, EtsString *stack) 75 { 76 ASSERT(stack != nullptr); 77 ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, stack_), stack->GetCoreType()); 78 } 79 SetStackLines(EtsCoroutine * coro,EtsTypedObjectArray<EtsStackTraceElement> * stackLines)80 void SetStackLines(EtsCoroutine *coro, EtsTypedObjectArray<EtsStackTraceElement> *stackLines) 81 { 82 ASSERT(stackLines != nullptr); 83 ObjectAccessor::SetObject(coro, this, MEMBER_OFFSET(Error, stackLines_), stackLines->GetCoreType()); 84 } 85 86 private: 87 ObjectPointer<EtsString> name_; 88 ObjectPointer<EtsString> message_; 89 ObjectPointer<EtsTypedObjectArray<EtsStackTraceElement>> stackLines_; 90 ObjectPointer<EtsString> stack_; // non-mandatory field in `class Error` 91 ObjectPointer<EtsObject> cause_; // non-mandatory field in `class Error` 92 93 friend class test::EtsErrorTest; 94 }; 95 96 // Purpose of this class is to have preallocated OOM object in runtime, that can be useful in situation 97 // when all heap is filled and we don't have space to allocate stdlib OOM error. 98 class EtsOutOfMemoryError final : public Error { 99 public: 100 static constexpr std::string_view OOM_ERROR_NAME = "OutOfMemoryError"; 101 // Default message should be empty string to avoid allocations in .toString() 102 // NOLINTNEXTLINE(readability-redundant-string-init) 103 static constexpr std::string_view DEFAULT_OOM_MSG = ""; 104 static constexpr std::string_view DEFAULT_OOM_STACK = "Heap is full, no space to collect stack"; 105 106 public: 107 NO_COPY_SEMANTIC(EtsOutOfMemoryError); 108 NO_MOVE_SEMANTIC(EtsOutOfMemoryError); 109 110 EtsOutOfMemoryError() = delete; 111 ~EtsOutOfMemoryError() = delete; 112 Create(EtsCoroutine * coro)113 static EtsOutOfMemoryError *Create(EtsCoroutine *coro) 114 { 115 [[maybe_unused]] EtsHandleScope scope(coro); 116 117 auto oomH = EtsHandle<EtsOutOfMemoryError>( 118 coro, FromError(Error::Create(coro, PlatformTypes(coro)->coreOutOfMemoryError))); 119 120 ASSERT(oomH.GetPtr() != nullptr); 121 auto *name = EtsString::CreateFromMUtf8(OOM_ERROR_NAME.data()); 122 oomH->SetName(coro, name); 123 124 auto *message = EtsString::CreateFromMUtf8(DEFAULT_OOM_MSG.data()); 125 oomH->SetMessage(coro, message); 126 127 auto *stack = EtsString::CreateFromMUtf8(DEFAULT_OOM_STACK.data()); 128 oomH->SetStack(coro, stack); 129 130 auto *stackLines = 131 EtsTypedObjectArray<EtsStackTraceElement>::Create(PlatformTypes(coro)->coreStackTraceElement, 0U); 132 oomH->SetStackLines(coro, stackLines); 133 134 return oomH.GetPtr(); 135 } 136 FromError(Error * error)137 static EtsOutOfMemoryError *FromError(Error *error) 138 { 139 ASSERT(error->GetClass()->GetDescriptor() == panda_file_items::class_descriptors::OUT_OF_MEMORY_ERROR); 140 return static_cast<EtsOutOfMemoryError *>(error); 141 } 142 }; 143 144 } // namespace ark::ets 145 146 #endif // PANDA_PLUGINS_ETS_ERROR_H 147