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_regexp_stub_builder.h"
17#include "ecmascript/compiler/new_object_stub_builder.h"
18#include "ecmascript/regexp/regexp_parser.h"
19namespace panda::ecmascript::kungfu {
20
21void BuiltinsRegExpStubBuilder::GetFlags(GateRef glue, GateRef thisValue,
22    [[maybe_unused]] GateRef numArgs, Variable* result, Label* exit, Label *slowPath)
23{
24    auto env = GetEnvironment();
25    Label isEcmaObject(env);
26    BRANCH(IsEcmaObject(thisValue), &isEcmaObject, slowPath);
27    Bind(&isEcmaObject);
28    Label fastRegExpPath(env);
29    GateRef fastRegExp = CallNGCRuntime(glue, RTSTUB_ID(IsFastRegExp), {glue, thisValue});
30    BRANCH(fastRegExp, slowPath, &fastRegExpPath);
31    Bind(&fastRegExpPath);
32    {
33        Label hasException(env);
34        DEFVARIABLE(bitFlagsStr, VariableType::INT32(), Int32(0));
35        GateRef globalResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::GLOBAL_STRING_INDEX);
36        Label notHasException(env);
37        BRANCH(HasPendingException(glue), &hasException, &notHasException);
38        Bind(&notHasException);
39        Label globalKey(env);
40        Label notGlobalKey(env);
41        BRANCH(TaggedIsTrue(globalResult), &globalKey, &notGlobalKey);
42        Bind(&globalKey);
43        {
44            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_GLOBAL));
45            Jump(&notGlobalKey);
46        }
47        Bind(&notGlobalKey);
48        GateRef ignoreCaseResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::IGNORE_CASE_INDEX);
49        Label notHasException1(env);
50        BRANCH(HasPendingException(glue), &hasException, &notHasException1);
51        Bind(&notHasException1);
52        Label ignoreCaseKey(env);
53        Label notIgnoreCaseKey(env);
54        BRANCH(TaggedIsTrue(ignoreCaseResult), &ignoreCaseKey, &notIgnoreCaseKey);
55        Bind(&ignoreCaseKey);
56        {
57            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_IGNORECASE));
58            Jump(&notIgnoreCaseKey);
59        }
60        Bind(&notIgnoreCaseKey);
61        GateRef multilineResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::MULTILINE_INDEX);
62        Label notHasException2(env);
63        BRANCH(HasPendingException(glue), &hasException, &notHasException2);
64        Bind(&notHasException2);
65        Label multilineKey(env);
66        Label notMultilineKey(env);
67        BRANCH(TaggedIsTrue(multilineResult), &multilineKey, &notMultilineKey);
68        Bind(&multilineKey);
69        {
70            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_MULTILINE));
71            Jump(&notMultilineKey);
72        }
73        Bind(&notMultilineKey);
74        GateRef dotAllResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::DOT_ALL_INDEX);
75        Label notHasException3(env);
76        BRANCH(HasPendingException(glue), &hasException, &notHasException3);
77        Bind(&notHasException3);
78        Label dotAllKey(env);
79        Label notDotAllKey(env);
80        BRANCH(TaggedIsTrue(dotAllResult), &dotAllKey, &notDotAllKey);
81        Bind(&dotAllKey);
82        {
83            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_DOTALL));
84            Jump(&notDotAllKey);
85        }
86        Bind(&notDotAllKey);
87        GateRef unicodeResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::UNICODE_INDEX);
88        Label notHasException4(env);
89        BRANCH(HasPendingException(glue), &hasException, &notHasException4);
90        Bind(&notHasException4);
91        Label unicodeKey(env);
92        Label notUnicodeKey(env);
93        BRANCH(TaggedIsTrue(unicodeResult), &unicodeKey, &notUnicodeKey);
94        Bind(&unicodeKey);
95        {
96            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_UTF16));
97            Jump(&notUnicodeKey);
98        }
99        Bind(&notUnicodeKey);
100        GateRef stickyResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::STICKY_INDEX);
101        Label notHasException5(env);
102        BRANCH(HasPendingException(glue), &hasException, &notHasException5);
103        Bind(&notHasException5);
104        Label stickyKey(env);
105        Label notStickyKey(env);
106        BRANCH(TaggedIsTrue(stickyResult), &stickyKey, &notStickyKey);
107        Bind(&stickyKey);
108        {
109            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_STICKY));
110            Jump(&notStickyKey);
111        }
112        Bind(&notStickyKey);
113        GateRef indicesResult = TryToFastGetProperty(glue, thisValue, ConstantIndex::HAS_INDICES_INDEX);
114        Label notHasException6(env);
115        BRANCH(HasPendingException(glue), &hasException, &notHasException6);
116        Bind(&notHasException6);
117        Label hasIndicesKey(env);
118        Label notHasIndicesKey(env);
119        BRANCH(TaggedIsTrue(indicesResult), &hasIndicesKey, &notHasIndicesKey);
120        Bind(&hasIndicesKey);
121        {
122            bitFlagsStr = Int32Or(*bitFlagsStr, Int32(RegExpParser::FLAG_HASINDICES));
123            Jump(&notHasIndicesKey);
124        }
125        Bind(&notHasIndicesKey);
126        GateRef flagsStr = CallRuntime(glue, RTSTUB_ID(GetAllFlagsInternal), { IntToTaggedInt(*bitFlagsStr)});
127        result->WriteVariable(flagsStr);
128        Jump(exit);
129        Bind(&hasException);
130        {
131            result->WriteVariable(GetGlobalConstantValue(VariableType::JS_POINTER(),
132                glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX));
133            Jump(exit);
134        }
135    }
136}
137
138GateRef BuiltinsRegExpStubBuilder::TryToFastGetProperty(GateRef glue, GateRef thisValue, ConstantIndex constIndex)
139{
140    auto env = GetEnvironment();
141    Label entry(env);
142    Label exit(env);
143    env->SubCfgEntry(&entry);
144    DEFVARIABLE(result, VariableType::JS_ANY(), TaggedFalse());
145    GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, constIndex);
146    GateRef property = FastGetPropertyByName(glue, thisValue, key, ProfileOperation());
147    Label hasException(env);
148    Label notHasException(env);
149    BRANCH(HasPendingException(glue), &hasException, &notHasException);
150    Bind(&hasException);
151    {
152        result = Exception();
153        Jump(&exit);
154    }
155    Bind(&notHasException);
156    {
157        result = FastToBoolean(property);
158        Jump(&exit);
159    }
160    Bind(&exit);
161    auto res = *result;
162    env->SubCfgExit();
163    return res;
164}
165}  // namespace panda::ecmascript::kungfu
166