RegExp getFlags IR 优化

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IARK97
Signed-off-by: jiangmengyang <jiangmengyang3@huawei.com>
Change-Id: Iae8bcfcda15d28446a4189e6c3eca2cb6871dcd6
This commit is contained in:
jiangmengyang 2024-09-13 15:07:58 +08:00
parent fd401c22e5
commit 3e146639be
12 changed files with 295 additions and 9 deletions

View File

@ -2056,7 +2056,8 @@ void Builtins::InitializeRegExp(const JSHandle<GlobalEnv> &env)
FunctionLength::ZERO);
JSHandle<JSFunction>(execFunc)->SetLexicalEnv(thread_, env);
JSHandle<JSTaggedValue> flagsGetter = CreateGetter(env, RegExp::GetFlags, "flags", FunctionLength::ZERO);
JSHandle<JSTaggedValue> flagsGetter = CreateGetter(env, RegExp::GetFlags, "flags", FunctionLength::ZERO,
kungfu::BuiltinsStubCSigns::RegExpGetFlags);
JSHandle<JSTaggedValue> flagsKey(globalConstants->GetHandledFlagsString());
SetGetter(regPrototype, flagsKey, flagsGetter);
JSHandle<JSFunction>(flagsGetter)->SetLexicalEnv(thread_, env);
@ -2887,16 +2888,19 @@ void Builtins::SetStringTagSymbol(const JSHandle<GlobalEnv> &env, const JSHandle
}
JSHandle<JSTaggedValue> Builtins::CreateGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const
std::string_view name, int length,
kungfu::BuiltinsStubCSigns::ID builtinId) const
{
JSHandle<JSTaggedValue> funcName(factory_->NewFromUtf8ReadOnly(name));
return CreateGetter(env, func, funcName, length);
return CreateGetter(env, func, funcName, length, builtinId);
}
JSHandle<JSTaggedValue> Builtins::CreateGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
JSHandle<JSTaggedValue> key, int length) const
JSHandle<JSTaggedValue> key, int length,
kungfu::BuiltinsStubCSigns::ID builtinId) const
{
JSHandle<JSFunction> function = factory_->NewJSFunction(env, reinterpret_cast<void *>(func));
JSHandle<JSFunction> function = factory_->NewJSFunction(env, reinterpret_cast<void *>(func),
FunctionKind::GETTER_FUNCTION, builtinId);
JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(length));
JSHandle<JSTaggedValue> prefix = thread_->GlobalConstants()->GetHandledGetString();
JSFunction::SetFunctionName(thread_, JSHandle<JSFunctionBase>(function), key, prefix);

View File

@ -336,10 +336,16 @@ private:
void SetStringTagSymbol(const JSHandle<GlobalEnv> &env, const JSHandle<JSObject> &obj,
std::string_view key) const;
JSHandle<JSTaggedValue> CreateGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
std::string_view name, int length) const;
std::string_view name, int length,
kungfu::BuiltinsStubCSigns::ID builtinId =
kungfu::BuiltinsStubCSigns::INVALID) const;
JSHandle<JSTaggedValue> CreateGetter(const JSHandle<GlobalEnv> &env, EcmaEntrypoint func,
JSHandle<JSTaggedValue> key, int length) const;
JSHandle<JSTaggedValue> key, int length,
kungfu::BuiltinsStubCSigns::ID builtinId =
kungfu::BuiltinsStubCSigns::INVALID) const;
void SetConstant(const JSHandle<JSObject> &obj, std::string_view key, JSTaggedValue value) const;

View File

@ -118,6 +118,7 @@ libark_jsoptimizer_sources = [
"builtins/builtins_object_stub_builder.cpp",
"builtins/builtins_proxy_stub_builder.cpp",
"builtins/builtins_reflect_stub_builder.cpp",
"builtins/builtins_regexp_stub_builder.cpp",
"builtins/builtins_string_stub_builder.cpp",
"builtins/builtins_stubs.cpp",
"builtins/builtins_typedarray_stub_builder.cpp",

View File

@ -48,7 +48,8 @@ namespace panda::ecmascript::kungfu {
BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
BUILTINS_WITH_DATAVIEW_STUB_BUILDER(K) \
BUILTINS_WITH_REFLECT_STUB_BUILDER(T) \
BUILTINS_WITH_COLLATOR_STUB_BUILDER(V)
BUILTINS_WITH_COLLATOR_STUB_BUILDER(V) \
BUILTINS_WITH_REGEXP_STUB_BUILDER(V)
#define BUILTINS_WITH_STRING_STUB_BUILDER(V) \
V(CharAt, String, Hole()) \
@ -162,6 +163,9 @@ namespace panda::ecmascript::kungfu {
#define BUILTINS_WITH_COLLATOR_STUB_BUILDER(V) \
V(ResolvedOptions, Collator, Undefined())
#define BUILTINS_WITH_REGEXP_STUB_BUILDER(V) \
V(GetFlags, RegExp, Undefined())
#define BUILTINS_WITH_TYPEDARRAY_STUB_BUILDER(V) \
V(Reverse, TypedArray, Undefined()) \
V(LastIndexOf, TypedArray, Undefined()) \

View File

@ -0,0 +1,165 @@
/*
* 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_regexp_stub_builder.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/regexp/regexp_parser.h"
namespace panda::ecmascript::kungfu {
void BuiltinsRegExpStubBuilder::GetFlags(GateRef glue, GateRef thisValue,
[[maybe_unused]] GateRef numArgs, Variable* result, Label* exit, Label *slowPath)
{
auto env = GetEnvironment();
Label isEcmaObject(env);
BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
Bind(&isEcmaObject);
Label fastRegExpPath(env);
GateRef fastRegExp = CallRuntime(glue, RTSTUB_ID(IsFastRegExp), { thisValue });
BRANCH(TaggedIsTrue(fastRegExp), slowPath, &fastRegExpPath);
Bind(&fastRegExpPath);
{
Label hasException(env);
DEFVARIABLE(bitFlagsStr, VariableType::INT32(), Int32(0));
GateRef globalResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::GLOBAL_STRING_INDEX);
Label notHasException(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException);
Bind(&notHasException);
Label globalKey(env);
Label notGlobalKey(env);
BRANCH(TaggedIsTrue(globalResult), &globalKey, &notGlobalKey);
Bind(&globalKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_GLOBAL));
Jump(&notGlobalKey);
}
Bind(&notGlobalKey);
GateRef ignoreCaseResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::IGNORE_CASE_INDEX);
Label notHasException1(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException1);
Bind(&notHasException1);
Label ignoreCaseKey(env);
Label notIgnoreCaseKey(env);
BRANCH(TaggedIsTrue(ignoreCaseResult), &ignoreCaseKey, &notIgnoreCaseKey);
Bind(&ignoreCaseKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_IGNORECASE));
Jump(&notIgnoreCaseKey);
}
Bind(&notIgnoreCaseKey);
GateRef multilineResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::MULTILINE_INDEX);
Label notHasException2(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException2);
Bind(&notHasException2);
Label multilineKey(env);
Label notMultilineKey(env);
BRANCH(TaggedIsTrue(multilineResult), &multilineKey, &notMultilineKey);
Bind(&multilineKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_MULTILINE));
Jump(&notMultilineKey);
}
Bind(&notMultilineKey);
GateRef dotAllResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::DOT_ALL_INDEX);
Label notHasException3(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException3);
Bind(&notHasException3);
Label dotAllKey(env);
Label notDotAllKey(env);
BRANCH(TaggedIsTrue(dotAllResult), &dotAllKey, &notDotAllKey);
Bind(&dotAllKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_DOTALL));
Jump(&notDotAllKey);
}
Bind(&notDotAllKey);
GateRef unicodeResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::UNICODE_INDEX);
Label notHasException4(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException4);
Bind(&notHasException4);
Label unicodeKey(env);
Label notUnicodeKey(env);
BRANCH(TaggedIsTrue(unicodeResult), &unicodeKey, &notUnicodeKey);
Bind(&unicodeKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_UTF16));
Jump(&notUnicodeKey);
}
Bind(&notUnicodeKey);
GateRef stickyResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::STICKY_INDEX);
Label notHasException5(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException5);
Bind(&notHasException5);
Label stickyKey(env);
Label notStickyKey(env);
BRANCH(TaggedIsTrue(stickyResult), &stickyKey, &notStickyKey);
Bind(&stickyKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_STICKY));
Jump(&notStickyKey);
}
Bind(&notStickyKey);
GateRef indicesResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::HAS_INDICES_INDEX);
Label notHasException6(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException6);
Bind(&notHasException6);
Label hasIndicesKey(env);
Label notHasIndicesKey(env);
BRANCH(TaggedIsTrue(indicesResult), &hasIndicesKey, &notHasIndicesKey);
Bind(&hasIndicesKey);
{
bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_HASINDICES));
Jump(&notHasIndicesKey);
}
Bind(&notHasIndicesKey);
GateRef flagsStr = CallRuntime(glue, RTSTUB_ID(GetAllFlagsInternal), { IntToTaggedInt(*bitFlagsStr)});
result->WriteVariable(flagsStr);
Jump(exit);
Bind(&hasException);
{
result->WriteVariable(GetGlobalConstantValue(VariableType::JS_POINTER(),
glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX));
Jump(exit);
}
}
}
GateRef BuiltinsRegExpStubBuilder::TryToFastGetProperty(GateRef glue, GateRef thisValue, ConstantIndex constIndex)
{
auto env = GetEnvironment();
Label entry(env);
Label exit(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, constIndex);
GateRef property = FastGetPropertyByName(glue, thisValue, key, ProfileOperation());
Label hasException(env);
Label notHasException(env);
BRANCH(HasPendingException(glue), &hasException, &notHasException);
Bind(&hasException);
{
result = Exception();
Jump(&exit);
}
Bind(&notHasException);
{
result = FastToBoolean(property);
Jump(&exit);
}
Bind(&exit);
auto res = *result;
env->SubCfgExit();
return res;
}
} // namespace panda::ecmascript::kungfu

View File

@ -0,0 +1,41 @@
/*
* 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.
*/
#ifndef ECMASCRIPT_COMPILER_BUILTINS_REGEXP_STUB_BUILDER_H
#define ECMASCRIPT_COMPILER_BUILTINS_REGEXP_STUB_BUILDER_H
#include "ecmascript/compiler/builtins/builtins_stubs.h"
namespace panda::ecmascript::kungfu {
class BuiltinsRegExpStubBuilder : public BuiltinsStubBuilder {
public:
explicit BuiltinsRegExpStubBuilder(StubBuilder *parent)
: BuiltinsStubBuilder(parent) {}
BuiltinsRegExpStubBuilder(CallSignature *callSignature, Environment *env)
: BuiltinsStubBuilder(callSignature, env) {}
explicit BuiltinsRegExpStubBuilder(Environment* env): BuiltinsStubBuilder(env) {}
~BuiltinsRegExpStubBuilder() override = default;
NO_MOVE_SEMANTIC(BuiltinsRegExpStubBuilder);
NO_COPY_SEMANTIC(BuiltinsRegExpStubBuilder);
void GenerateCircuit() override {}
GateRef TryToFastGetProperty(GateRef glue, GateRef thisValue, ConstantIndex constIndex);
#define DECLARE_BUILTINS_REGEXP_STUB_BUILDER(method, ...) \
void method(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *res, Label *exit, Label *slowPath);
BUILTINS_WITH_REGEXP_STUB_BUILDER(DECLARE_BUILTINS_REGEXP_STUB_BUILDER)
#undef DECLARE_BUILTINS_REGEXP_STUB_BUILDER
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BUILTINS_REGEXP_STUB_BUILDER_H

View File

@ -21,6 +21,7 @@
#include "ecmascript/compiler/builtins/builtins_dataview_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_function_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_string_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_regexp_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_number_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_proxy_stub_builder.h"
#include "ecmascript/compiler/builtins/builtins_reflect_stub_builder.h"

View File

@ -540,6 +540,7 @@ class ObjectFactory;
V(EthioaaString, ETHIOAA_INDEX, "ethioaa") \
V(StickyString, STICKY_INDEX, "sticky") \
V(HasIndicesString, HAS_INDICES_INDEX, "hasIndices") \
V(DotAllString, DOT_ALL_INDEX, "dotAll") \
V(MultilineString, MULTILINE_INDEX, "multiline") \
V(IgnoreCaseString, IGNORE_CASE_INDEX, "ignoreCase") \
V(IndicesString, INDICES_INDEX, "indices") \

View File

@ -480,7 +480,9 @@ namespace panda::ecmascript {
V(SuperCallForwardAllArgs) \
V(OptSuperCallForwardAllArgs) \
V(GetCollationValueFromIcuCollator) \
V(DecodeURIComponent)
V(DecodeURIComponent) \
V(IsFastRegExp) \
V(GetAllFlagsInternal)
#define RUNTIME_STUB_LIST(V) \

View File

@ -4057,6 +4057,61 @@ DEF_RUNTIME_STUBS(GetCollationValueFromIcuCollator)
return thread->GlobalConstants()->GetDefaultString().GetRawData();
}
DEF_RUNTIME_STUBS(IsFastRegExp)
{
RUNTIME_STUBS_HEADER(IsFastRegExp);
JSHandle<JSObject> thisValue = GetHArg<JSObject>(argv, argc, 0); // 0: means the zeroth parameter
JSHandle<JSTaggedValue> thisObjVal(thisValue);
bool result = builtins::BuiltinsRegExp::IsFastRegExp(thread, thisObjVal);
return JSTaggedValue(result).GetRawData();
}
DEF_RUNTIME_STUBS(GetAllFlagsInternal)
{
RUNTIME_STUBS_HEADER(GetAllFlagsInternal);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
uint8_t *flagsStr = new uint8_t[RegExpParser::FLAG_NUM + 1]; // FLAG_NUM flags + '\0'
if (flagsStr == nullptr) {
LOG_ECMA(FATAL) << "BuiltinsRegExp::GetAllFlagsInternal:flagsStr is nullptr";
}
size_t flagsLen = 0;
JSHandle<JSTaggedValue> value = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
int64 bigFlagsStr = value->GetInt();
if (bigFlagsStr & RegExpParser::FLAG_HASINDICES) {
flagsStr[flagsLen] = 'd';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_GLOBAL) {
flagsStr[flagsLen] = 'g';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_IGNORECASE) {
flagsStr[flagsLen] = 'i';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_MULTILINE) {
flagsStr[flagsLen] = 'm';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_DOTALL) {
flagsStr[flagsLen] = 's';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_UTF16) {
flagsStr[flagsLen] = 'u';
flagsLen++;
}
if (bigFlagsStr & RegExpParser::FLAG_STICKY) {
flagsStr[flagsLen] = 'y';
flagsLen++;
}
flagsStr[flagsLen] = '\0';
JSHandle<EcmaString> flagsString = factory->NewFromUtf8(flagsStr, flagsLen);
delete[] flagsStr;
return flagsString.GetTaggedValue().GetRawData();
}
void RuntimeStubs::Initialize(JSThread *thread)
{
#define DEF_RUNTIME_STUB(name) kungfu::RuntimeStubCSigns::ID_##name

View File

@ -163,3 +163,4 @@ true
true
true
true
dgimsuy

View File

@ -672,3 +672,8 @@ pattern = /\d$/gm;
result = string.match(pattern);
print(1 == result.length);
print('9' == result[0]);
// test getFlags
const res = /abc/giymsud;
res.lastIndex = -1;
print(res.flags);