1/*
2 * Copyright (c) 2022 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#include "ecmascript/compiler/hash_stub_builder.h"
17
18namespace panda::ecmascript::kungfu {
19
20GateRef HashStubBuilder::GetHash(GateRef key)
21{
22    auto env = GetEnvironment();
23    Label entryLabel(env);
24    Label exit(env);
25    env->SubCfgEntry(&entryLabel);
26    DEFVARIABLE(res, VariableType::INT32(), Int32(0));
27    Label intKey(env);
28    Label symbolCheck(env);
29    BRANCH(TaggedIsInt(key), &intKey, &symbolCheck);
30    Bind(&intKey);
31    res = TaggedGetInt(key);
32    Jump(&exit);
33    Bind(&symbolCheck);
34    Label slowGetHash(env);
35    Label symbolKey(env);
36    Label stringCheck(env);
37    BRANCH(TaggedIsSymbol(key), &symbolKey, &stringCheck);
38
39    Bind(&symbolKey);
40    res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET));
41    Jump(&exit);
42    Bind(&stringCheck);
43    Label stringKey(env);
44    Label objectCheck(env);
45    BRANCH(TaggedIsString(key), &stringKey, &objectCheck);
46    Bind(&stringKey);
47    res = GetHashcodeFromString(glue_, key);
48    Jump(&exit);
49
50    Bind(&objectCheck);
51    Label heapObjectKey(env);
52    Label numberCheck(env);
53    BRANCH(TaggedIsHeapObject(key), &heapObjectKey, &numberCheck);
54
55    Bind(&heapObjectKey);
56    Label ecmaObjectKey(env);
57    BRANCH(TaggedObjectIsEcmaObject(key), &ecmaObjectKey, &slowGetHash);
58    Bind(&ecmaObjectKey);
59    CalcHashcodeForObject(glue_, key, &res, &exit);
60
61    Bind(&numberCheck);
62    Label numberKey(env);
63    BRANCH(TaggedIsNumber(key), &numberKey, &slowGetHash);
64
65    Bind(&numberKey);
66    CalcHashcodeForNumber(key, &res, &exit);
67
68    Bind(&slowGetHash);
69    res = GetInt32OfTInt(CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key }));
70    Jump(&exit);
71
72    Bind(&exit);
73    auto ret = *res;
74    env->SubCfgExit();
75    return ret;
76}
77
78void HashStubBuilder::CalcHashcodeForNumber(GateRef key, Variable *res, Label *exit)
79{
80    auto env = GetEnvironment();
81    Label doubleKey(env);
82    Label intKey(env);
83    BRANCH(TaggedIsDouble(key), &doubleKey, &intKey);
84    Bind(&doubleKey);
85    {
86        CalcHashcodeForDouble(key, res, exit);
87    }
88    Bind(&intKey);
89    {
90        *res = CalcHashcodeForInt(key);
91        Jump(exit);
92    }
93}
94}  // namespace panda::ecmascript::kungfu
95