1 /* 2 * Copyright (c) 2023 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_PROPERTY_ACCESSOR_H 17 #define ECMASCRIPT_PROPERTY_ACCESSOR_H 18 19 #include "ecmascript/js_handle.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/js_thread.h" 22 #include "ecmascript/tagged_queue.h" 23 24 namespace panda::ecmascript { 25 class JSObject; 26 class TaggedArray; 27 class PropertyAccessor { 28 public: 29 PropertyAccessor(JSThread *thread, JSHandle<JSTaggedValue> object); 30 31 JSHandle<JSTaggedValue> GetKeysFast(); 32 JSHandle<JSTaggedValue> GetKeysSlow(); 33 34 JSHandle<JSTaggedValue> GetCachedHClass() const; 35 JSHandle<JSTaggedValue> GetEnumCache() const; 36 uint32_t GetActualKeyLength() const; 37 38 private: 39 void PreLoad(); 40 void CollectPrototypeInfo(); 41 void CopyKeyLengthToSelf(); 42 void InitSimplePropertiesEnumCache(); 43 void AccumulateKeyLength(uint32_t length); 44 void AccumulateShadowKeyLength(uint32_t length); 45 void PushRemainingKeys(JSHandle<JSObject> object, std::vector<JSHandle<TaggedArray>> &remainings); 46 void MergeRemainings(const std::vector<JSHandle<TaggedArray>> &remainings, 47 const std::vector<JSHandle<JSTaggedValue>> &visited); 48 void SetActualKeyLength(uint32_t length); 49 void AddUndefinedEndIfNeeded(JSHandle<TaggedArray> keys); 50 void AddUndefinedEndIfNeeded (JSHandle<TaggedArray> keys, 51 const uint32_t keyLength, const uint32_t acutalKeyLength); 52 void TryInitEnumCacheWithProtoChainInfo(); 53 bool HasPrototypeChainEnumCache(); 54 bool IsObjectWithoutKey() const; 55 56 void AddKey(const JSHandle<JSTaggedValue> &value, 57 JSHandle<TaggedArray>& allKeys, uint32_t& allKeysLength, 58 const JSHandle<TaggedArray> &keyArrayOnReceiver, 59 const JSHandle<TaggedQueue> &shadowQueueOnReceiver); 60 61 JSHandle<TaggedArray> CombineKeys(const JSHandle<TaggedArray> &keyArrayOnReceiver, 62 const JSHandle<TaggedArray> &keyArrayOnPrototypeChain, 63 const JSHandle<TaggedQueue> &shadowQueueOnReceiver); 64 65 std::pair<JSHandle<TaggedArray>, JSHandle<TaggedQueue>> GetOwnKeys(); 66 std::pair<JSHandle<TaggedArray>, JSHandle<TaggedQueue>> GetOwnKeysWithoutCache(); 67 std::pair<JSHandle<TaggedArray>, JSHandle<TaggedQueue>> GetOrSetOwnKeysWithoutElements(); 68 69 JSHandle<TaggedArray> GetChainKeys(const JSHandle<JSTaggedValue> &receiver, 70 const uint32_t keyLength, 71 const uint32_t shadowKeyLength); 72 73 JSHandle<TaggedArray> GetAndSetChainKeys(const JSHandle<JSTaggedValue> &proto, 74 const uint32_t keyLength, 75 const uint32_t shadowKeyLength); 76 77 JSHandle<JSTaggedValue> GetKeysFastWithoutCache(); 78 JSHandle<JSTaggedValue> GetKeysFastWithPrototypeChainEnumCache(); 79 80 JSThread *thread_{nullptr}; 81 JSMutableHandle<JSTaggedValue> receiver_; 82 JSMutableHandle<JSTaggedValue> fastKeysArray_; 83 JSMutableHandle<JSTaggedValue> cachedHClass_; 84 JSHandle<JSTaggedValue> enumCache_; 85 uint32_t keyLength_ {0}; 86 uint32_t shadowKeyLength_ {0}; 87 // receiver has no elements, and is not dictionary mode and has empty prototype 88 bool onlyHasSimpleProperties_ {true}; 89 bool hasSlowProperties_ {false}; 90 bool tryPrototypeChainEnumCache_{true}; 91 bool hasPrototypeChainEnumCache_{true}; 92 JSMutableHandle<TaggedArray> slowKeysArray_; 93 uint32_t acutalKeyLength_{0}; 94 uint32_t keyLengthSelf_{0}; 95 uint32_t shadowKeyLengthSelf_{0}; 96 }; 97 } // namespace panda::ecmascript 98 #endif // ECMASCRIPT_PROPERTY_ACCESSOR_H 99