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