/* * Copyright (c) 2024 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. */ #include "ecmascript/compiler/builtins/builtins_collator_stub_builder.h" #include "ecmascript/compiler/new_object_stub_builder.h" namespace panda::ecmascript::kungfu { void BuiltinsCollatorStubBuilder::ResolvedOptions(GateRef glue, GateRef thisValue, [[maybe_unused]] GateRef numArgs, Variable* res, Label* exit, Label* slowPath) { auto env = GetEnvironment(); Label entryPass(env); env->SubCfgEntry(&entryPass); Label isHeapObject(env); Label isJsCollator(env); BRANCH_LIKELY(TaggedIsHeapObject(thisValue), &isHeapObject, slowPath); Bind(&isHeapObject); BRANCH_LIKELY(IsJSCollator(thisValue), &isJsCollator, slowPath); Bind(&isJsCollator); GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit())); GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset); GateRef funCtor = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX); NewObjectStubBuilder newObjectStubBuilder(this); GateRef initialOptions = newObjectStubBuilder.NewJSObjectByConstructor(glue, funCtor, funCtor); DEFVARIABLE(options, VariableType::JS_ANY(), initialOptions); // [[Locale]] GateRef localeKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::LOCALE_STRING_INDEX); GateRef locale = Load(VariableType::JS_ANY(), thisValue, IntPtr(JSCollator::LOCALE_OFFSET)); CreateDataPropertyOrThrow(glue, *options, localeKey, locale); ReturnExceptionIfAbruptCompletion(glue); // [[Usage]] GateRef usageKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::USAGE_INDEX); GateRef usage = GetBitField(thisValue); usage = UsageOptionsToEcmaString(glue, usage); CreateDataProperty(glue, *options, usageKey, usage); // [[Sensitivity]] GateRef sensitivityKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SENSITIVITY_INDEX); GateRef sensitivity = GetBitField(thisValue); sensitivity = SensitivityOptionsToEcmaString(glue, sensitivity); CreateDataProperty(glue, *options, sensitivityKey, sensitivity); // [[IgnorePunctuation]] GateRef ignorePunctuationKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::IGNORE_PUNCTUATION_INDEX); GateRef ignorePunctuation = GetBitField(thisValue); ignorePunctuation = BooleanToTaggedBooleanPtr(TruncInt32ToInt1(ignorePunctuation)); CreateDataProperty(glue, *options, ignorePunctuationKey, ignorePunctuation); // [[Collation]] Label undefined(env); Label notUndefined(env); GateRef collation = Load(VariableType::JS_ANY(), thisValue, IntPtr(JSCollator::COLLATION_OFFSET)); GateRef collationKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::COLLATION_STRING_CLASS_INDEX); DEFVARIABLE(collationVar, VariableType::JS_ANY(), collation); BRANCH_NO_WEIGHT(TaggedIsUndefined(*collationVar), &undefined, ¬Undefined); Bind(&undefined); { collationVar = CallRuntime(glue, RTSTUB_ID(GetCollationValueFromIcuCollator), {thisValue}); Jump(¬Undefined); } Bind(¬Undefined); CreateDataProperty(glue, *options, collationKey, *collationVar); // [[Numeric]] GateRef numericKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::NUMERIC_STRING_CLASS_INDEX); GateRef numeric = GetBitField(thisValue); numeric = BooleanToTaggedBooleanPtr(TruncInt32ToInt1(numeric)); CreateDataProperty(glue, *options, numericKey, numeric); // [[CaseFirst]] GateRef caseFirstKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::CASE_FIRST_STRING_CLASS_INDEX); GateRef caseFirst = GetBitField(thisValue); caseFirst = CaseFirstOptionsToEcmaString(glue, caseFirst); CreateDataProperty(glue, *options, caseFirstKey, caseFirst); res->WriteVariable(*options); Jump(exit); env->SubCfgExit(); } template GateRef BuiltinsCollatorStubBuilder::GetBitField(GateRef collator) { GateRef bitFieldOffset = IntPtr(JSCollator::BIT_FIELD_OFFSET); GateRef bitfield = Load(VariableType::INT32(), collator, bitFieldOffset); GateRef bits = Int32And(Int32LSR(bitfield, Int32(BitType::START_BIT)), Int32((1LU << BitType::SIZE) - 1)); return bits; } GateRef BuiltinsCollatorStubBuilder::UsageOptionsToEcmaString(GateRef glue, GateRef usage) { auto env = GetEnvironment(); Label subEntry(env); env->SubCfgEntry(&subEntry); Label exit(env); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label sort(env); Label next(env); Label search(env); Label fatal(env); BRANCH_NO_WEIGHT(Int32Equal(usage, Int32(static_cast(UsageOption::SORT))), &sort, &next) Bind(&sort); { result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SORT_INDEX); Jump(&exit); } Bind(&next); BRANCH_NO_WEIGHT(Int32Equal(usage, Int32(static_cast(UsageOption::SEARCH))), &search, &fatal) Bind(&search); { result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SEARCH_INDEX); Jump(&exit); } Bind(&fatal); { FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))}); Jump(&exit); } Bind(&exit); auto ret = *result; env->SubCfgExit(); return ret; } GateRef BuiltinsCollatorStubBuilder::SensitivityOptionsToEcmaString(GateRef glue, GateRef sensitivity) { auto env = GetEnvironment(); Label subEntry(env); env->SubCfgEntry(&subEntry); Label exit(env); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label undefined(env); Label fatal(env); Label labels[SENSITIVITY_OPTION_CASES_NUM] = {Label(env), Label(env), Label(env), Label(env), undefined}; Switch(ZExtInt32ToInt64(sensitivity), &fatal, SensitivityOptionCases, labels, SENSITIVITY_OPTION_CASES_NUM); for (size_t i = 0; i < SENSITIVITY_OPTION_CASES_NUM - 1; i++) { Bind(&labels[i]); result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, SensitivityOptionIndexes[i]); Jump(&exit); } Bind(&undefined); { Jump(&exit); } Bind(&fatal); { FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))}); Jump(&exit); } Bind(&exit); auto ret = *result; env->SubCfgExit(); return ret; } GateRef BuiltinsCollatorStubBuilder::CaseFirstOptionsToEcmaString(GateRef glue, GateRef sensitivity) { auto env = GetEnvironment(); Label subEntry(env); env->SubCfgEntry(&subEntry); Label exit(env); DEFVARIABLE(result, VariableType::JS_ANY(), Undefined()); Label fatal(env); Label labels[CASE_FIRST_OPTION_NUM] = {Label(env), Label(env), Label(env), Label(env)}; Switch(ZExtInt32ToInt64(sensitivity), &fatal, CaseFirstOptionCases, labels, CASE_FIRST_OPTION_NUM); for (size_t i = 0; i < CASE_FIRST_OPTION_NUM; i++) { Bind(&labels[i]); result = GetGlobalConstantValue(VariableType::JS_ANY(), glue, CaseFirstOptionIndexes[i]); Jump(&exit); } Bind(&fatal); { FatalPrint(glue, {Int32(GET_MESSAGE_STRING_ID(ThisBranchIsUnreachable))}); Jump(&exit); } Bind(&exit); auto ret = *result; env->SubCfgExit(); return ret; } int64_t BuiltinsCollatorStubBuilder::SensitivityOptionCases[SENSITIVITY_OPTION_CASES_NUM] = { static_cast(SensitivityOption::BASE), static_cast(SensitivityOption::ACCENT), static_cast(SensitivityOption::CASE), static_cast(SensitivityOption::VARIANT), static_cast(SensitivityOption::UNDEFINED) }; ConstantIndex BuiltinsCollatorStubBuilder::SensitivityOptionIndexes[SENSITIVITY_OPTION_CASES_NUM - 1] = { ConstantIndex::BASE_INDEX, ConstantIndex::ACCENT_INDEX, ConstantIndex::CASE_INDEX, ConstantIndex::VARIANT_INDEX }; int64_t BuiltinsCollatorStubBuilder::CaseFirstOptionCases[CASE_FIRST_OPTION_NUM] = { static_cast(CaseFirstOption::UPPER), static_cast(CaseFirstOption::LOWER), static_cast(CaseFirstOption::FALSE_OPTION), static_cast(CaseFirstOption::UNDEFINED) }; ConstantIndex BuiltinsCollatorStubBuilder::CaseFirstOptionIndexes[CASE_FIRST_OPTION_NUM] = { ConstantIndex::UPPER_INDEX, ConstantIndex::LOWER_INDEX, ConstantIndex::FALSE_STRING_INDEX, ConstantIndex::UPPER_INDEX }; }