• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2024 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/builtins/builtins_collator_stub_builder.h"
17 
18 #include "ecmascript/compiler/new_object_stub_builder.h"
19 
20 namespace panda::ecmascript::kungfu {
ResolvedOptions(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * res,Label * exit,Label * slowPath)21 void BuiltinsCollatorStubBuilder::ResolvedOptions(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs,
22                                                   Variable* res, Label* exit,
23                                                   Label* slowPath)
24 {
25     auto env = GetEnvironment();
26     Label entryPass(env);
27     env->SubCfgEntry(&entryPass);
28 
29     Label isHeapObject(env);
30     Label isJsCollator(env);
31 
32     BRANCH_LIKELY(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath);
33     Bind(&isHeapObject);
34     BRANCH_LIKELY(IsJSCollator(glue, thisValue), &isJsCollator, slowPath);
35 
36     Bind(&isJsCollator);
37     GateRef globalEnv = GetCurrentGlobalEnv();
38     GateRef funCtor = GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
39 
40     NewObjectStubBuilder newObjectStubBuilder(this);
41     GateRef initialOptions = newObjectStubBuilder.NewJSObjectByConstructor(glue, funCtor, funCtor);
42     DEFVARIABLE(options, VariableType::JS_ANY(), initialOptions);
43 
44     // [[Locale]]
45     GateRef localeKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::LOCALE_STRING_INDEX);
46     GateRef locale = Load(VariableType::JS_ANY(), glue, thisValue, IntPtr(JSCollator::LOCALE_OFFSET));
47     CreateDataPropertyOrThrow(glue, *options, localeKey, locale);
48     ReturnExceptionIfAbruptCompletion(glue);
49 
50     // [[Usage]]
51     GateRef usageKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::USAGE_INDEX);
52     GateRef usage = GetBitField<JSCollator::UsageBits>(thisValue);
53     usage = UsageOptionsToEcmaString(glue, usage);
54     CreateDataProperty(glue, *options, usageKey, usage);
55 
56     // [[Sensitivity]]
57     GateRef sensitivityKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SENSITIVITY_INDEX);
58     GateRef sensitivity = GetBitField<JSCollator::SensitivityBits>(thisValue);
59     sensitivity = SensitivityOptionsToEcmaString(glue, sensitivity);
60     CreateDataProperty(glue, *options, sensitivityKey, sensitivity);
61 
62     // [[IgnorePunctuation]]
63     GateRef ignorePunctuationKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
64                                                           ConstantIndex::IGNORE_PUNCTUATION_INDEX);
65     GateRef ignorePunctuation = GetBitField<JSCollator::IgnorePunctuationBits>(thisValue);
66     ignorePunctuation = BooleanToTaggedBooleanPtr(TruncInt32ToInt1(ignorePunctuation));
67     CreateDataProperty(glue, *options, ignorePunctuationKey, ignorePunctuation);
68 
69     // [[Collation]]
70     Label undefined(env);
71     Label notUndefined(env);
72     GateRef collation = Load(VariableType::JS_ANY(), glue, thisValue, IntPtr(JSCollator::COLLATION_OFFSET));
73     GateRef collationKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
74                                                   ConstantIndex::COLLATION_STRING_CLASS_INDEX);
75     DEFVARIABLE(collationVar, VariableType::JS_ANY(), collation);
76     BRANCH_NO_WEIGHT(TaggedIsUndefined(*collationVar), &undefined, &notUndefined);
77     Bind(&undefined);
78     {
79         collationVar = CallRuntime(glue, RTSTUB_ID(GetCollationValueFromIcuCollator), {thisValue});
80         Jump(&notUndefined);
81     }
82     Bind(&notUndefined);
83     CreateDataProperty(glue, *options, collationKey, *collationVar);
84 
85     // [[Numeric]]
86     GateRef numericKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
87                                                 ConstantIndex::NUMERIC_STRING_CLASS_INDEX);
88     GateRef numeric = GetBitField<JSCollator::NumericBits>(thisValue);
89     numeric = BooleanToTaggedBooleanPtr(TruncInt32ToInt1(numeric));
90     CreateDataProperty(glue, *options, numericKey, numeric);
91 
92     // [[CaseFirst]]
93     GateRef caseFirstKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
94                                                   ConstantIndex::CASE_FIRST_STRING_CLASS_INDEX);
95     GateRef caseFirst = GetBitField<JSCollator::CaseFirstBits>(thisValue);
96     caseFirst = CaseFirstOptionsToEcmaString(glue, caseFirst);
97     CreateDataProperty(glue, *options, caseFirstKey, caseFirst);
98     res->WriteVariable(*options);
99     Jump(exit);
100     env->SubCfgExit();
101 }
102 
103 template <typename BitType>
GetBitField(GateRef collator)104 GateRef BuiltinsCollatorStubBuilder::GetBitField(GateRef collator)
105 {
106     GateRef bitFieldOffset = IntPtr(JSCollator::BIT_FIELD_OFFSET);
107     GateRef bitfield = LoadPrimitive(VariableType::INT32(), collator, bitFieldOffset);
108     GateRef bits = Int32And(Int32LSR(bitfield, Int32(BitType::START_BIT)),
109                             Int32((1LU << BitType::SIZE) - 1));
110     return bits;
111 }
112 
UsageOptionsToEcmaString(GateRef glue,GateRef usage)113 GateRef BuiltinsCollatorStubBuilder::UsageOptionsToEcmaString(GateRef glue, GateRef usage)
114 {
115     auto env = GetEnvironment();
116     Label subEntry(env);
117     env->SubCfgEntry(&subEntry);
118     Label exit(env);
119     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
120 
121     Label sort(env);
122     Label next(env);
123     Label search(env);
124     Label fatal(env);
125     BRANCH_NO_WEIGHT(Int32Equal(usage, Int32(static_cast<int32_t>(UsageOption::SORT))), &sort, &next)
126     Bind(&sort);
127     {
128         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SORT_INDEX);
129         Jump(&exit);
130     }
131 
132     Bind(&next);
133     BRANCH_NO_WEIGHT(Int32Equal(usage, Int32(static_cast<int32_t>(UsageOption::SEARCH))), &search, &fatal)
134     Bind(&search);
135     {
136         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SEARCH_INDEX);
137         Jump(&exit);
138     }
139     Bind(&fatal);
140     {
141         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))});
142         Jump(&exit);
143     }
144 
145     Bind(&exit);
146     auto ret = *result;
147     env->SubCfgExit();
148     return ret;
149 }
150 
SensitivityOptionsToEcmaString(GateRef glue,GateRef sensitivity)151 GateRef BuiltinsCollatorStubBuilder::SensitivityOptionsToEcmaString(GateRef glue, GateRef sensitivity)
152 {
153     auto env = GetEnvironment();
154     Label subEntry(env);
155     env->SubCfgEntry(&subEntry);
156     Label exit(env);
157 
158     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
159     Label undefined(env);
160     Label fatal(env);
161 
162     Label labels[SENSITIVITY_OPTION_CASES_NUM] = {Label(env), Label(env), Label(env), Label(env), undefined};
163     Switch(ZExtInt32ToInt64(sensitivity), &fatal, SensitivityOptionCases, labels, SENSITIVITY_OPTION_CASES_NUM);
164 
165     for (size_t i = 0; i < SENSITIVITY_OPTION_CASES_NUM - 1; i++) {
166         Bind(&labels[i]);
167         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, SensitivityOptionIndexes[i]);
168         Jump(&exit);
169     }
170 
171     Bind(&undefined);
172     {
173         Jump(&exit);
174     }
175     Bind(&fatal);
176     {
177         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))});
178         Jump(&exit);
179     }
180     Bind(&exit);
181     auto ret = *result;
182     env->SubCfgExit();
183     return ret;
184 }
185 
CaseFirstOptionsToEcmaString(GateRef glue,GateRef sensitivity)186 GateRef BuiltinsCollatorStubBuilder::CaseFirstOptionsToEcmaString(GateRef glue, GateRef sensitivity)
187 {
188     auto env = GetEnvironment();
189     Label subEntry(env);
190     env->SubCfgEntry(&subEntry);
191     Label exit(env);
192 
193     DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
194     Label fatal(env);
195 
196     Label labels[CASE_FIRST_OPTION_NUM] = {Label(env), Label(env), Label(env), Label(env)};
197     Switch(ZExtInt32ToInt64(sensitivity), &fatal, CaseFirstOptionCases, labels, CASE_FIRST_OPTION_NUM);
198 
199     for (size_t i = 0; i < CASE_FIRST_OPTION_NUM; i++) {
200         Bind(&labels[i]);
201         result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, CaseFirstOptionIndexes[i]);
202         Jump(&exit);
203     }
204 
205     Bind(&fatal);
206     {
207         FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))});
208         Jump(&exit);
209     }
210     Bind(&exit);
211     auto ret = *result;
212     env->SubCfgExit();
213     return ret;
214 }
215 
216 int64_t BuiltinsCollatorStubBuilder::SensitivityOptionCases[SENSITIVITY_OPTION_CASES_NUM] = {
217     static_cast<int64_t>(SensitivityOption::BASE), static_cast<int64_t>(SensitivityOption::ACCENT),
218     static_cast<int64_t>(SensitivityOption::CASE), static_cast<int64_t>(SensitivityOption::VARIANT),
219     static_cast<int64_t>(SensitivityOption::UNDEFINED)
220 };
221 
222 ConstantIndex BuiltinsCollatorStubBuilder::SensitivityOptionIndexes[SENSITIVITY_OPTION_CASES_NUM - 1] = {
223     ConstantIndex::BASE_INDEX, ConstantIndex::ACCENT_INDEX,
224     ConstantIndex::CASE_INDEX, ConstantIndex::VARIANT_INDEX
225 };
226 
227 int64_t BuiltinsCollatorStubBuilder::CaseFirstOptionCases[CASE_FIRST_OPTION_NUM] = {
228     static_cast<int64_t>(CaseFirstOption::UPPER), static_cast<int64_t>(CaseFirstOption::LOWER),
229     static_cast<int64_t>(CaseFirstOption::FALSE_OPTION), static_cast<int64_t>(CaseFirstOption::UNDEFINED)
230 };
231 
232 ConstantIndex BuiltinsCollatorStubBuilder::CaseFirstOptionIndexes[CASE_FIRST_OPTION_NUM] = {
233     ConstantIndex::UPPER_INDEX, ConstantIndex::LOWER_INDEX,
234     ConstantIndex::FALSE_STRING_INDEX, ConstantIndex::UPPER_INDEX
235 };
236 }
237