ywx fb265d5ea5 Fix for-in bug
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IBOJPH?from=project-issue
Signed-off-by: ywx <yinwuxiao@huawei.com>
Change-Id: I61fc22946332cfde815cf9433d7ac98a46ea6231
2025-03-27 17:09:34 +08:00

112 lines
5.3 KiB
C++

/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_ENUM_CACHE_H
#define ECMASCRIPT_ENUM_CACHE_H
#include "ecmascript/ecma_macros.h"
#include "ecmascript/mem/barriers.h"
// EnumCacheKind is only used in for-in.
enum class EnumCacheKind : uint8_t {
NONE, // No Cache, go slow path
SIMPLE, // Simple enum cache
PROTOCHAIN, // Prototype chain info enum cache
};
// +---------------+-------------------------------------------+-------------------------------------------------+
// | EnumCacheKind | Status Description | Valid Conditions |
// +---------------+-------------------------------------------+-------------------------------------------------+
// | None | - Uninitialized or in SlowPath mode. | - None (No additional conditions required) |
// | | No active cache optimization. | |
// +---------------+-------------------------------------------+-------------------------------------------------+
// | SIMPLE | - Fast path for simple enum cache check. | - Receiver's proto is NOT a HeapObject, |
// | | Indicates: | OR |
// | | • Properties exist ONLY on the object | - Receiver.proto.ProtoChainInfoEnumCache == |
// | | itself (no prototype chain properties) | Undefined. (Ensure no keys on prototype chain)|
// | | • NO elements (indexed properties) on | |
// | | self/proto | |
// +---------------+-------------------------------------------+-------------------------------------------------+
// | PROTOCHAIN | - Fast path for protochain enum cache. | - Receiver's proto is a HeapObject, AND |
// | | Indicates: | - Receiver.ProtoChainInfoEnumCache == |
// | | • Properties exist on the object itself | receiver.proto.EnumCacheAll (Cache matches |
// | | or prototype chain | prototype's full enum cache), AND |
// | | • NO elements (indexed properties) on | - Receiver.ProtoChainInfoEnumCache != Null |
// | | self/proto | (Valid cache exists). |
// +---------------+-------------------------------------------+-------------------------------------------------+
namespace panda {
namespace ecmascript {
class EnumCache : public TaggedObject {
public:
CAST_CHECK(EnumCache, IsEnumCache);
static constexpr size_t ENUM_CACHE_OWN_OFFSET = TaggedObjectSize();
static bool CheckSelfAndProtoEnumCache(JSTaggedValue enumCacheOwn, JSTaggedValue enumCacheProto)
{
if (!enumCacheOwn.IsEnumCache() || !enumCacheProto.IsEnumCache()) {
return false;
}
auto keyOwn = EnumCache::Cast(enumCacheOwn.GetTaggedObject())->GetProtoChainInfoEnumCache();
auto keyProto = EnumCache::Cast(enumCacheProto.GetTaggedObject())->GetEnumCacheAll();
if (keyOwn != keyProto || keyOwn == JSTaggedValue::Null()) {
return false;
}
return true;
}
inline bool IsEnumCacheAllValid() const
{
return GetEnumCacheAll() != JSTaggedValue::Null();
}
inline bool IsEnumCacheOwnValid() const
{
return GetEnumCacheOwn() != JSTaggedValue::Null();
}
inline bool IsEnumCacheProtoInfoUndefined() const
{
return GetProtoChainInfoEnumCache() == JSTaggedValue::Undefined();
}
inline void SetInvalidState(const JSThread *thread)
{
SetEnumCacheAll(thread, JSTaggedValue::Null());
SetProtoChainInfoEnumCache(thread, JSTaggedValue::Null());
}
// EnumCacheOwn holds enum keys on itself.
ACCESSORS(EnumCacheOwn, ENUM_CACHE_OWN_OFFSET, ENUM_CACHE_ALL_OFFSET);
// EnumCacheAll holds all enum keys on the prototype chain, including its own keys.
ACCESSORS(EnumCacheAll, ENUM_CACHE_ALL_OFFSET, PROTO_CHAIN_INFO_ENUM_CACHE_OFFSET);
// ProtoChainInfoEnumCache holds all enum keys on the prototype chain, excluding its own keys.
ACCESSORS(ProtoChainInfoEnumCache, PROTO_CHAIN_INFO_ENUM_CACHE_OFFSET, ENUM_CACHE_KIND_OFFSET);
ACCESSORS_PRIMITIVE_FIELD(EnumCacheKind, uint32_t, ENUM_CACHE_KIND_OFFSET, LAST_OFFSET);
DEFINE_ALIGN_SIZE(LAST_OFFSET);
DECL_VISIT_OBJECT(ENUM_CACHE_OWN_OFFSET, ENUM_CACHE_KIND_OFFSET)
DECL_DUMP()
};
} // namespace ecmascript
} // namespace panda
#endif // ECMASCRIPT_IC_ENUM_CACHE_H