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