IR for Intl.Collator.prototype.resolvedOptions

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAQ2T7
Signed-off-by: ZhouGuangyuan <zhouguangyuan1@huawei.com>
Change-Id: I01bfcc0e7af40714514ab22f643bae71f98b8947
This commit is contained in:
zhouguangyuan 2024-09-09 22:54:00 +08:00
parent dfc2b50b76
commit cea7ac93e1
12 changed files with 330 additions and 3 deletions

View File

@ -3465,7 +3465,8 @@ void Builtins::InitializeCollator(const JSHandle<GlobalEnv> &env)
SetAccessor(collatorPrototype, thread_->GlobalConstants()->GetHandledCompareString(), compareGetter, compareSetter);
// 11.3.4 Intl.Collator.prototype.resolvedOptions ()
SetFunction(env, collatorPrototype, "resolvedOptions", Collator::ResolvedOptions, FunctionLength::ZERO);
SetFunction(env, collatorPrototype, "resolvedOptions", Collator::ResolvedOptions, FunctionLength::ZERO,
kungfu::BuiltinsStubCSigns::CollatorResolvedOptions);
}
void Builtins::InitializePluralRules(const JSHandle<GlobalEnv> &env)

View File

@ -110,6 +110,7 @@ libark_jsoptimizer_sources = [
"bc_call_signature.cpp",
"builtins/builtins_array_stub_builder.cpp",
"builtins/builtins_call_signature.cpp",
"builtins/builtins_collator_stub_builder.cpp",
"builtins/builtins_collection_stub_builder.cpp",
"builtins/builtins_dataview_stub_builder.cpp",
"builtins/builtins_function_stub_builder.cpp",

View File

@ -46,7 +46,8 @@ namespace panda::ecmascript::kungfu {
BUILTINS_WITH_NUMBER_STUB_BUILDER(T) \
BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
BUILTINS_WITH_DATAVIEW_STUB_BUILDER(K) \
BUILTINS_WITH_REFLECT_STUB_BUILDER(T)
BUILTINS_WITH_REFLECT_STUB_BUILDER(T) \
BUILTINS_WITH_COLLATOR_STUB_BUILDER(V)
#define BUILTINS_WITH_STRING_STUB_BUILDER(V) \
V(CharAt, String, Hole()) \
@ -156,6 +157,9 @@ namespace panda::ecmascript::kungfu {
#define BUILTINS_WITH_REFLECT_STUB_BUILDER(V) \
V(Get, Reflect, Undefined())
#define BUILTINS_WITH_COLLATOR_STUB_BUILDER(V) \
V(ResolvedOptions, Collator, Undefined())
#define BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
V(Reverse, TypedArray, Undefined()) \
V(LastIndexOf, TypedArray, Undefined()) \

View File

@ -0,0 +1,238 @@
/*
* 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"
#include "ecmascript/js_collator.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<JSCollator::UsageBits>(thisValue);
usage = UsageOptionsToEcmaString(glue, usage);
CreateDataProperty(glue, *options, usageKey, usage);
// [[Sensitivity]]
GateRef sensitivityKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::SENSITIVITY_INDEX);
GateRef sensitivity = GetBitField<JSCollator::SensitivityBits>(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<JSCollator::IgnorePunctuationBits>(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, &notUndefined);
Bind(&undefined);
{
collationVar = CallRuntime(glue, RTSTUB_ID(GetCollationValueFromIcuCollator), {thisValue});
Jump(&notUndefined);
}
Bind(&notUndefined);
CreateDataProperty(glue, *options, collationKey, *collationVar);
// [[Numeric]]
GateRef numericKey = GetGlobalConstantValue(VariableType::JS_ANY(), glue,
ConstantIndex::NUMERIC_STRING_CLASS_INDEX);
GateRef numeric = GetBitField<JSCollator::NumericBits>(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<JSCollator::CaseFirstBits>(thisValue);
caseFirst = CaseFirstOptionsToEcmaString(glue, caseFirst);
CreateDataProperty(glue, *options, caseFirstKey, caseFirst);
res->WriteVariable(*options);
Jump(exit);
env->SubCfgExit();
}
template <typename BitType>
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<int32_t>(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<int32_t>(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<int64_t>(SensitivityOption::BASE), static_cast<int64_t>(SensitivityOption::ACCENT),
static_cast<int64_t>(SensitivityOption::CASE), static_cast<int64_t>(SensitivityOption::VARIANT),
static_cast<int64_t>(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<int64_t>(CaseFirstOption::UPPER), static_cast<int64_t>(CaseFirstOption::LOWER),
static_cast<int64_t>(CaseFirstOption::FALSE_OPTION), static_cast<int64_t>(CaseFirstOption::UNDEFINED)
};
ConstantIndex BuiltinsCollatorStubBuilder::CaseFirstOptionIndexes[CASE_FIRST_OPTION_NUM] = {
ConstantIndex::UPPER_INDEX, ConstantIndex::LOWER_INDEX,
ConstantIndex::FALSE_STRING_INDEX, ConstantIndex::UPPER_INDEX
};
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2023-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.
*/
#ifndef ECMASCRIPT_COMPILER_BUILTINS_COLLATOR_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_COLLATOR_STUB_BUILDER_H
#include <ecmascript/js_collator.h>
#include "ecmascript/compiler/builtins/builtins_stubs.h"
namespace panda::ecmascript::kungfu {
class BuiltinsCollatorStubBuilder : public BuiltinsStubBuilder {
public:
explicit BuiltinsCollatorStubBuilder(BuiltinsStubBuilder *parent) : BuiltinsStubBuilder(parent) {}
~BuiltinsCollatorStubBuilder() override = default;
NO_MOVE_SEMANTIC(BuiltinsCollatorStubBuilder);
NO_COPY_SEMANTIC(BuiltinsCollatorStubBuilder);
void GenerateCircuit() override {}
void ResolvedOptions(GateRef glue, GateRef thisValue, GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
private:
template <typename BitType>
GateRef GetBitField(GateRef collator);
GateRef UsageOptionsToEcmaString(GateRef glue, GateRef usage);
GateRef SensitivityOptionsToEcmaString(GateRef glue, GateRef sensitivity);
GateRef CaseFirstOptionsToEcmaString(GateRef glue, GateRef sensitivity);
static constexpr size_t SENSITIVITY_OPTION_CASES_NUM = 5;
static int64_t SensitivityOptionCases[SENSITIVITY_OPTION_CASES_NUM];
static ConstantIndex SensitivityOptionIndexes[SENSITIVITY_OPTION_CASES_NUM - 1];
static constexpr size_t CASE_FIRST_OPTION_NUM = 4;
static int64_t CaseFirstOptionCases[CASE_FIRST_OPTION_NUM];
static ConstantIndex CaseFirstOptionIndexes[CASE_FIRST_OPTION_NUM];
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_COLLATOR_STUB_BUILDER_H

View File

@ -27,6 +27,7 @@
#include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
#include "ecmascript/compiler/builtins/containers_vector_stub_builder.h"
#include "ecmascript/compiler/builtins/containers_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_collator_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_collection_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
#include "ecmascript/compiler/codegen/llvm/llvm_ir_builder.h"

View File

@ -1601,6 +1601,12 @@ inline GateRef StubBuilder::IsJSAPIArrayList(GateRef obj)
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_API_ARRAY_LIST)));
}
inline GateRef StubBuilder::IsJSCollator(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_COLLATOR)));
}
inline GateRef StubBuilder::IsJSObjectType(GateRef obj, JSType jsType)
{
auto env = GetEnvironment();

View File

@ -466,6 +466,7 @@ ShortcutBoolOr([&]{ return first; }, [&]{ return second; })
GateRef IsJSAPILinkedList(GateRef obj);
GateRef IsJSAPIList(GateRef obj);
GateRef IsJSAPIArrayList(GateRef obj);
GateRef IsJSCollator(GateRef obj);
GateRef IsJSObjectType(GateRef obj, JSType jsType);
GateRef IsJSRegExp(GateRef obj);
GateRef GetTarget(GateRef proxyObj);

View File

@ -478,7 +478,8 @@ namespace panda::ecmascript {
V(SetPrototypeTransition) \
V(GetSharedModule) \
V(SuperCallForwardAllArgs) \
V(OptSuperCallForwardAllArgs)
V(OptSuperCallForwardAllArgs) \
V(GetCollationValueFromIcuCollator)
#define RUNTIME_STUB_LIST(V) \

View File

@ -3994,6 +3994,22 @@ DEF_RUNTIME_STUBS(FunctionPrototypeCall)
return JSFunction::Call(info).GetRawData();
}
DEF_RUNTIME_STUBS(GetCollationValueFromIcuCollator)
{
RUNTIME_STUBS_HEADER(GetCollationValueFromIcuCollator);
JSHandle<JSCollator> collator = GetHArg<JSCollator>(argv, argc, 0); // 0: means the zeroth parameter
UErrorCode status = U_ZERO_ERROR;
icu::Collator *icuCollator = collator->GetIcuCollator();
icu::Locale icu_locale(icuCollator->getLocale(ULOC_VALID_LOCALE, status));
std::string collation_value =
icu_locale.getUnicodeKeywordValue<std::string>("co", status);
if (collation_value != "search" && collation_value != "") {
return thread->GetEcmaVM()->GetFactory()->NewFromStdString(collation_value).GetTaggedValue().GetRawData();
}
return thread->GlobalConstants()->GetDefaultString().GetRawData();
}
void RuntimeStubs::Initialize(JSThread *thread)
{
#define DEF_RUNTIME_STUB(name) kungfu::RuntimeStubCSigns::ID_##name

View File

@ -22,3 +22,4 @@ true
true
true
true
true

View File

@ -57,3 +57,12 @@ try {
print(o instanceof c);
}
}
{
try {
const proto = this.Intl.Collator.prototype;
proto.resolvedOptions();
} catch (err) {
print(err instanceof TypeError);
}
}