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_object.h" 23 #include "ecmascript/js_tagged_value.h" 24 #include "ecmascript/mem/slots.h" 25 #include "ecmascript/mem/visitor.h" 26 #include "ecmascript/record.h" 27 28 namespace panda::ecmascript { 29 class InternalAccessor final : public Record { 30 public: 31 using InternalGetFunc = JSTaggedValue (*)(JSThread *, const JSHandle<JSObject> &); 32 using InternalSetFunc = bool (*)(JSThread *, const JSHandle<JSObject> &, const JSHandle<JSTaggedValue> &, bool); 33 34 CAST_CHECK(InternalAccessor, IsInternalAccessor); 35 HasSetter() const36 inline bool HasSetter() const 37 { 38 return GetSetter() != nullptr; 39 } 40 41 static constexpr size_t GETTER_OFFSET = Record::SIZE; 42 ACCESSORS_FIXED_SIZE_FIELD(Getter, InternalGetFunc, JSTaggedType, GETTER_OFFSET, SETTER_OFFSET) 43 ACCESSORS_FIXED_SIZE_FIELD(Setter, InternalSetFunc, JSTaggedType, SETTER_OFFSET, SIZE) 44 45 DECL_VISIT_NATIVE_FIELD(GETTER_OFFSET, SIZE) 46 }; 47 48 class AccessorData final : public Record { 49 public: Cast(TaggedObject *object)50 static AccessorData *Cast(TaggedObject *object) 51 { 52 ASSERT(JSTaggedValue(object).IsAccessorData() || JSTaggedValue(object).IsInternalAccessor()); 53 return static_cast<AccessorData *>(object); 54 } 55 IsInternal() const56 inline bool IsInternal() const 57 { 58 return GetClass()->IsInternalAccessor(); 59 } 60 HasSetter() const61 inline bool HasSetter() const 62 { 63 auto setter = GetSetter(); 64 // When the raw data is 0, means the InternalAccessor's setter is nullptr. 65 return !(setter.IsUndefined() || setter.GetRawData() == 0U); 66 } 67 CallInternalGet(JSThread *thread, const JSHandle<JSObject> &obj) const68 JSTaggedValue CallInternalGet(JSThread *thread, const JSHandle<JSObject> &obj) const 69 { 70 ASSERT(IsInternal()); 71 auto getFunc = InternalAccessor::ConstCast(this)->GetGetter(); 72 return getFunc(thread, obj); 73 } 74 CallInternalSet(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &value, bool mayThrow = false) const75 bool CallInternalSet(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &value, 76 bool mayThrow = false) const 77 { 78 ASSERT(IsInternal()); 79 auto setFunc = InternalAccessor::ConstCast(this)->GetSetter(); 80 return setFunc(thread, obj, value, mayThrow); 81 } 82 83 static constexpr size_t GETTER_OFFSET = Record::SIZE; 84 ACCESSORS(Getter, GETTER_OFFSET, SETTER_OFFSET); 85 ACCESSORS(Setter, SETTER_OFFSET, SIZE); 86 87 DECL_DUMP() 88 DECL_VISIT_OBJECT(GETTER_OFFSET, SIZE) 89 }; 90 91 static_assert(AccessorData::SIZE == InternalAccessor::SIZE && 92 AccessorData::GETTER_OFFSET == InternalAccessor::GETTER_OFFSET && 93 AccessorData::SETTER_OFFSET == InternalAccessor::SETTER_OFFSET); 94 95 enum class CompletionRecordType : uint8_t { 96 NORMAL = 0U, 97 BREAK, 98 CONTINUE, 99 RETURN, 100 THROW 101 }; 102 103 class CompletionRecord final : public Record { 104 public: Cast(TaggedObject *object)105 static CompletionRecord *Cast(TaggedObject *object) 106 { 107 ASSERT(JSTaggedValue(object).IsCompletionRecord()); 108 return static_cast<CompletionRecord *>(object); 109 } 110 IsThrow() const111 bool IsThrow() const 112 { 113 return GetType() == CompletionRecordType::THROW; 114 } 115 116 static constexpr size_t VALUE_OFFSET = Record::SIZE; 117 ACCESSORS(Value, VALUE_OFFSET, BIT_FIELD_OFFSET) 118 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 119 DEFINE_ALIGN_SIZE(LAST_OFFSET); 120 121 // define BitField 122 static constexpr size_t TYPE_BITS = 3; 123 FIRST_BIT_FIELD(BitField, Type, CompletionRecordType, TYPE_BITS) 124 125 DECL_DUMP() 126 127 DECL_VISIT_OBJECT(VALUE_OFFSET, BIT_FIELD_OFFSET) 128 }; 129 } // namespace panda::ecmascript 130 #endif // ECMASCRIPT_ACCESSOR_DATA_H 131