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 #ifndef ECMASCRIPT_ACCESSOR_DATA_H 17 #define ECMASCRIPT_ACCESSOR_DATA_H 18 19 #include "ecmascript/ecma_macros.h" 20 #include "ecmascript/js_hclass.h" 21 #include "ecmascript/js_native_pointer.h" 22 #include "ecmascript/js_tagged_value.h" 23 #include "ecmascript/record.h" 24 25 namespace panda::ecmascript { 26 class AccessorData final : public Record { 27 public: 28 using InternalGetFunc = JSTaggedValue (*)(JSThread *, const JSHandle<JSObject> &); 29 using InternalSetFunc = bool (*)(JSThread *, const JSHandle<JSObject> &, const JSHandle<JSTaggedValue> &, bool); 30 Cast(ObjectHeader * object)31 static AccessorData *Cast(ObjectHeader *object) 32 { 33 ASSERT(JSTaggedValue(object).IsAccessorData() || JSTaggedValue(object).IsInternalAccessor()); 34 return static_cast<AccessorData *>(object); 35 } 36 IsInternal()37 inline bool IsInternal() const 38 { 39 return GetClass()->IsInternalAccessor(); 40 } 41 HasSetter()42 inline bool HasSetter() const 43 { 44 return !GetSetter().IsUndefined(); 45 } 46 CallInternalGet(JSThread * thread,const JSHandle<JSObject> & obj)47 JSTaggedValue CallInternalGet(JSThread *thread, const JSHandle<JSObject> &obj) const 48 { 49 ASSERT(GetGetter().IsJSNativePointer()); 50 JSNativePointer *getter = JSNativePointer::Cast(GetGetter().GetTaggedObject()); 51 auto getFunc = reinterpret_cast<InternalGetFunc>(getter->GetExternalPointer()); 52 return getFunc(thread, obj); 53 } 54 55 bool CallInternalSet(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &value, 56 bool mayThrow = false) const 57 { 58 ASSERT(GetSetter().IsJSNativePointer()); 59 JSNativePointer *setter = JSNativePointer::Cast(GetSetter().GetTaggedObject()); 60 auto setFunc = reinterpret_cast<InternalSetFunc>(setter->GetExternalPointer()); 61 return setFunc(thread, obj, value, mayThrow); 62 } 63 64 static constexpr size_t GETTER_OFFSET = Record::SIZE; 65 ACCESSORS(Getter, GETTER_OFFSET, SETTER_OFFSET); 66 ACCESSORS(Setter, SETTER_OFFSET, SIZE); 67 68 DECL_DUMP() 69 DECL_VISIT_OBJECT(GETTER_OFFSET, SIZE) 70 }; 71 72 enum class CompletionRecordType : uint8_t { 73 NORMAL = 0U, 74 BREAK, 75 CONTINUE, 76 RETURN, 77 THROW 78 }; 79 80 class CompletionRecord final : public Record { 81 public: Cast(ObjectHeader * object)82 static CompletionRecord *Cast(ObjectHeader *object) 83 { 84 ASSERT(JSTaggedValue(object).IsCompletionRecord()); 85 return static_cast<CompletionRecord *>(object); 86 } 87 IsThrow()88 bool IsThrow() const 89 { 90 return GetType() == CompletionRecordType::THROW; 91 } 92 93 static constexpr size_t VALUE_OFFSET = Record::SIZE; 94 ACCESSORS(Value, VALUE_OFFSET, BIT_FIELD_OFFSET) 95 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 96 DEFINE_ALIGN_SIZE(LAST_OFFSET); 97 98 // define BitField 99 static constexpr size_t TYPE_BITS = 3; 100 FIRST_BIT_FIELD(BitField, Type, CompletionRecordType, TYPE_BITS) 101 102 DECL_DUMP() 103 104 DECL_VISIT_OBJECT(VALUE_OFFSET, BIT_FIELD_OFFSET) 105 }; 106 } // namespace panda::ecmascript 107 #endif // ECMASCRIPT_ACCESSOR_DATA_H 108