14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_ELEMENTS_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_ELEMENTS_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/global_env_constants.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
214514f5e3Sopenharmony_ci#include "ecmascript/mem/c_containers.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript {
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ci#define ELEMENTS_KIND_INIT_HCLASS_LIST(V)           \
264514f5e3Sopenharmony_ci    V(NONE)                                         \
274514f5e3Sopenharmony_ci    V(HOLE)                                         \
284514f5e3Sopenharmony_ci    V(INT)                                          \
294514f5e3Sopenharmony_ci    V(NUMBER)                                       \
304514f5e3Sopenharmony_ci    V(STRING)                                       \
314514f5e3Sopenharmony_ci    V(OBJECT)                                       \
324514f5e3Sopenharmony_ci    V(TAGGED)                                       \
334514f5e3Sopenharmony_ci    V(HOLE_INT)                                     \
344514f5e3Sopenharmony_ci    V(HOLE_NUMBER)                                  \
354514f5e3Sopenharmony_ci    V(HOLE_STRING)                                  \
364514f5e3Sopenharmony_ci    V(HOLE_OBJECT)                                  \
374514f5e3Sopenharmony_ci    V(HOLE_TAGGED)
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_cienum class ElementsKind : uint8_t {
404514f5e3Sopenharmony_ci    NONE = 0x00UL,
414514f5e3Sopenharmony_ci    HOLE = 0x01UL,
424514f5e3Sopenharmony_ci    INT = 0x1UL << 1,      // 2
434514f5e3Sopenharmony_ci    NUMBER = (0x1UL << 2) | INT, // 6
444514f5e3Sopenharmony_ci    STRING = 0x1UL << 3,   // 8
454514f5e3Sopenharmony_ci    OBJECT = 0x1UL << 4,   // 16
464514f5e3Sopenharmony_ci    TAGGED = 0x1EUL,       // 30
474514f5e3Sopenharmony_ci    HOLE_INT = HOLE | INT,
484514f5e3Sopenharmony_ci    HOLE_NUMBER = HOLE | NUMBER,
494514f5e3Sopenharmony_ci    HOLE_STRING = HOLE | STRING,
504514f5e3Sopenharmony_ci    HOLE_OBJECT = HOLE | OBJECT,
514514f5e3Sopenharmony_ci    HOLE_TAGGED = HOLE | TAGGED,
524514f5e3Sopenharmony_ci    GENERIC = HOLE_TAGGED,
534514f5e3Sopenharmony_ci    DICTIONARY = HOLE_TAGGED,
544514f5e3Sopenharmony_ci};
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ciclass PUBLIC_API Elements {
574514f5e3Sopenharmony_cipublic:
584514f5e3Sopenharmony_ci    static CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> InitializeHClassMap();
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    static std::string GetString(ElementsKind kind);
614514f5e3Sopenharmony_ci    static bool IsInt(ElementsKind kind);
624514f5e3Sopenharmony_ci    static bool IsNumber(ElementsKind kind);
634514f5e3Sopenharmony_ci    static bool IsTagged(ElementsKind kind);
644514f5e3Sopenharmony_ci    static bool IsObject(ElementsKind kind);
654514f5e3Sopenharmony_ci    static bool IsHole(ElementsKind kind);
664514f5e3Sopenharmony_ci    static bool IsGeneric(ElementsKind kind)
674514f5e3Sopenharmony_ci    {
684514f5e3Sopenharmony_ci        return kind == ElementsKind::GENERIC;
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ci    static bool IsNone(ElementsKind kind)
724514f5e3Sopenharmony_ci    {
734514f5e3Sopenharmony_ci        return kind == ElementsKind::NONE;
744514f5e3Sopenharmony_ci    }
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ci    static bool IsComplex(ElementsKind kind)
774514f5e3Sopenharmony_ci    {
784514f5e3Sopenharmony_ci        return IsNumber(kind) || IsTagged(kind);
794514f5e3Sopenharmony_ci    }
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci    static bool IsInNumbers(ElementsKind kind)
824514f5e3Sopenharmony_ci    {
834514f5e3Sopenharmony_ci        return (static_cast<uint32_t>(kind) > static_cast<uint32_t>(ElementsKind::HOLE) &&
844514f5e3Sopenharmony_ci                static_cast<uint32_t>(kind) < static_cast<uint32_t>(ElementsKind::STRING));
854514f5e3Sopenharmony_ci    }
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ci    static bool IsHoleInt(ElementsKind kind)
884514f5e3Sopenharmony_ci    {
894514f5e3Sopenharmony_ci        return kind == ElementsKind::HOLE_INT;
904514f5e3Sopenharmony_ci    }
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_ci    static bool IsHoleNumber(ElementsKind kind)
934514f5e3Sopenharmony_ci    {
944514f5e3Sopenharmony_ci        return kind == ElementsKind::HOLE_NUMBER;
954514f5e3Sopenharmony_ci    }
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci    static ConstantIndex GetGlobalContantIndexByKind(ElementsKind kind);
984514f5e3Sopenharmony_ci    static ElementsKind MergeElementsKind(ElementsKind curKind, ElementsKind newKind);
994514f5e3Sopenharmony_ci    static ElementsKind FixElementsKind(ElementsKind oldKind);
1004514f5e3Sopenharmony_ci    static ElementsKind ToElementsKind(JSTaggedValue value, ElementsKind kind);
1014514f5e3Sopenharmony_ci    static void MigrateArrayWithKind(const JSThread *thread, const JSHandle<JSObject> &object,
1024514f5e3Sopenharmony_ci                                     const ElementsKind oldKind, const ElementsKind newKind);
1034514f5e3Sopenharmony_ciprivate:
1044514f5e3Sopenharmony_ci    static JSTaggedValue MigrateFromRawValueToHeapValue(const JSThread *thread, const JSHandle<JSObject> object,
1054514f5e3Sopenharmony_ci                                                         bool needCOW, bool isIntKind);
1064514f5e3Sopenharmony_ci    static void HandleIntKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
1074514f5e3Sopenharmony_ci                                       const ElementsKind newKind, bool needCOW);
1084514f5e3Sopenharmony_ci    static bool IsNumberKind(const ElementsKind kind);
1094514f5e3Sopenharmony_ci    static bool IsStringOrNoneOrHole(const ElementsKind kind);
1104514f5e3Sopenharmony_ci    static void HandleNumberKindMigration(const JSThread *thread,
1114514f5e3Sopenharmony_ci                                          const JSHandle<JSObject> &object,
1124514f5e3Sopenharmony_ci                                          const ElementsKind newKind, bool needCOW);
1134514f5e3Sopenharmony_ci    static void HandleOtherKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
1144514f5e3Sopenharmony_ci                                         const ElementsKind newKind, bool needCOW);
1154514f5e3Sopenharmony_ci    static JSTaggedValue MigrateFromHeapValueToRawValue(const JSThread *thread, const JSHandle<JSObject> object,
1164514f5e3Sopenharmony_ci                                                        bool needCOW, bool isIntKind);
1174514f5e3Sopenharmony_ci    static void MigrateFromHoleIntToHoleNumber(const JSThread *thread, const JSHandle<JSObject> object);
1184514f5e3Sopenharmony_ci    static void MigrateFromHoleNumberToHoleInt(const JSThread *thread, const JSHandle<JSObject> object);
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_ci};
1214514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
1224514f5e3Sopenharmony_ci#endif // ECMASCRIPT_ELEMENTS_H
123