• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_string_stub_builder.h"
17 
18 #include "ecmascript/compiler/builtins/builtins_stubs.h"
19 #include "ecmascript/compiler/new_object_stub_builder.h"
20 
21 namespace panda::ecmascript::kungfu {
StringAt(GateRef obj,GateRef index)22 GateRef BuiltinsStringStubBuilder::StringAt(GateRef obj, GateRef index)
23 {
24     auto env = GetEnvironment();
25     Label entry(env);
26     env->SubCfgEntry(&entry);
27     DEFVARIABLE(result, VariableType::INT32(), Int32(0));
28 
29     Label exit(env);
30     Label isUtf16(env);
31     Label isUtf8(env);
32     Label doIntOp(env);
33     Label leftIsNumber(env);
34     Label rightIsNumber(env);
35     GateRef dataUtf16 = GetNormalStringData(obj);
36     Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
37     Bind(&isUtf16);
38     {
39         result = ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(dataUtf16,
40             PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint16_t))))));
41         Jump(&exit);
42     }
43     Bind(&isUtf8);
44     {
45         result = ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(dataUtf16,
46             PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint8_t))))));
47         Jump(&exit);
48     }
49     Bind(&exit);
50     auto ret = *result;
51     env->SubCfgExit();
52     return ret;
53 }
54 
CreateFromEcmaString(GateRef glue,GateRef obj,GateRef index)55 GateRef BuiltinsStringStubBuilder::CreateFromEcmaString(GateRef glue, GateRef obj, GateRef index)
56 {
57     auto env = GetEnvironment();
58     Label entry(env);
59     env->SubCfgEntry(&entry);
60     DEFVARIABLE(result, VariableType::JS_POINTER(), Hole());
61     DEFVARIABLE(canBeCompressed, VariableType::BOOL(), False());
62     DEFVARIABLE(data, VariableType::INT16(), Int32(0));
63 
64     Label exit(env);
65     Label isUtf16(env);
66     Label isUtf8(env);
67     Label allocString(env);
68     GateRef dataUtf = GetNormalStringData(obj);
69     Branch(IsUtf16String(obj), &isUtf16, &isUtf8);
70     Bind(&isUtf16);
71     {
72         GateRef dataAddr = PtrAdd(dataUtf, PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint16_t))));
73         data = Load(VariableType::INT16(), dataAddr);
74         canBeCompressed = CanBeCompressed(dataAddr, Int32(1), true);
75         Jump(&allocString);
76     }
77     Bind(&isUtf8);
78     {
79         GateRef dataAddr = PtrAdd(dataUtf, PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint8_t))));
80         data = ZExtInt8ToInt16(Load(VariableType::INT8(), dataAddr));
81         canBeCompressed = CanBeCompressed(dataAddr, Int32(1), false);
82         Jump(&allocString);
83     }
84     Bind(&allocString);
85     {
86         Label afterNew(env);
87         Label isUtf8Next(env);
88         Label isUtf16Next(env);
89         NewObjectStubBuilder newBuilder(this);
90         newBuilder.SetParameters(glue, 0);
91         Branch(*canBeCompressed, &isUtf8Next, &isUtf16Next);
92         Bind(&isUtf8Next);
93         {
94             newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), true);
95         }
96         Bind(&isUtf16Next);
97         {
98             newBuilder.AllocLineStringObject(&result, &afterNew, Int32(1), false);
99         }
100         Bind(&afterNew);
101         {
102             Label isUtf8Copy(env);
103             Label isUtf16Copy(env);
104             GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
105             Branch(*canBeCompressed, &isUtf8Copy, &isUtf16Copy);
106             Bind(&isUtf8Copy);
107             {
108                 Store(VariableType::INT8(), glue, dst, IntPtr(0), TruncInt16ToInt8(*data));
109                 Jump(&exit);
110             }
111             Bind(&isUtf16Copy);
112             {
113                 Store(VariableType::INT16(), glue, dst, IntPtr(0), *data);
114                 Jump(&exit);
115             }
116         }
117     }
118     Bind(&exit);
119     auto ret = *result;
120     env->SubCfgExit();
121     return ret;
122 }
123 
FastSubString(GateRef glue,GateRef thisValue,GateRef from,GateRef len)124 GateRef BuiltinsStringStubBuilder::FastSubString(GateRef glue, GateRef thisValue, GateRef from, GateRef len)
125 {
126     auto env = GetEnvironment();
127     Label entry(env);
128     env->SubCfgEntry(&entry);
129     DEFVARIABLE(result, VariableType::JS_POINTER(), thisValue);
130 
131     Label exit(env);
132     Label lenEqualZero(env);
133     Label lenNotEqualZero(env);
134     Label fromEqualZero(env);
135     Label next(env);
136     Label isUtf8(env);
137     Label isUtf16(env);
138 
139     Branch(Int32Equal(len, Int32(0)), &lenEqualZero, &lenNotEqualZero);
140     Bind(&lenEqualZero);
141     {
142         result = GetGlobalConstantValue(
143             VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
144         Jump(&exit);
145     }
146     Bind(&lenNotEqualZero);
147     {
148         Branch(Int32Equal(from, Int32(0)), &fromEqualZero, &next);
149         Bind(&fromEqualZero);
150         {
151             GateRef thisLen = GetLengthFromString(thisValue);
152             Branch(Int32Equal(len, thisLen), &exit, &next);
153         }
154         Bind(&next);
155         {
156             Branch(IsUtf8String(thisValue), &isUtf8, &isUtf16);
157             Bind(&isUtf8);
158             {
159                 result = FastSubUtf8String(glue, thisValue, from, len);
160                 Jump(&exit);
161             }
162             Bind(&isUtf16);
163             {
164                 result = FastSubUtf16String(glue, thisValue, from, len);
165                 Jump(&exit);
166             }
167         }
168     }
169     Bind(&exit);
170     auto ret = *result;
171     env->SubCfgExit();
172     return ret;
173 }
174 
FastSubUtf8String(GateRef glue,GateRef thisValue,GateRef from,GateRef len)175 GateRef BuiltinsStringStubBuilder::FastSubUtf8String(GateRef glue, GateRef thisValue, GateRef from, GateRef len)
176 {
177     auto env = GetEnvironment();
178     Label entry(env);
179     env->SubCfgEntry(&entry);
180     DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
181     Label exit(env);
182 
183     NewObjectStubBuilder newBuilder(this);
184     newBuilder.SetParameters(glue, 0);
185     Label afterNew(env);
186     newBuilder.AllocLineStringObject(&result, &afterNew, len, true);
187     Bind(&afterNew);
188     {
189         GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
190         GateRef source = PtrAdd(GetNormalStringData(thisValue), ZExtInt32ToPtr(from));
191         CopyChars(glue, dst, source, len, IntPtr(sizeof(uint8_t)), VariableType::INT8());
192         Jump(&exit);
193     }
194     Bind(&exit);
195     auto ret = *result;
196     env->SubCfgExit();
197     return ret;
198 }
199 
FastSubUtf16String(GateRef glue,GateRef thisValue,GateRef from,GateRef len)200 GateRef BuiltinsStringStubBuilder::FastSubUtf16String(GateRef glue, GateRef thisValue, GateRef from, GateRef len)
201 {
202     auto env = GetEnvironment();
203     Label entry(env);
204     env->SubCfgEntry(&entry);
205     DEFVARIABLE(result, VariableType::JS_POINTER(), Undefined());
206 
207     Label exit(env);
208     Label isUtf16(env);
209     Label isUtf8(env);
210     Label isUtf8Next(env);
211     Label isUtf16Next(env);
212 
213     GateRef fromOffset = PtrMul(ZExtInt32ToPtr(from), IntPtr(sizeof(uint16_t) / sizeof(uint8_t)));
214     GateRef source = PtrAdd(GetNormalStringData(thisValue), fromOffset);
215     GateRef canBeCompressed = CanBeCompressed(source, len, true);
216     NewObjectStubBuilder newBuilder(this);
217     newBuilder.SetParameters(glue, 0);
218     Label afterNew(env);
219     Branch(canBeCompressed, &isUtf8, &isUtf16);
220     Bind(&isUtf8);
221     {
222         newBuilder.AllocLineStringObject(&result, &afterNew, len, true);
223     }
224     Bind(&isUtf16);
225     {
226         newBuilder.AllocLineStringObject(&result, &afterNew, len, false);
227     }
228     Bind(&afterNew);
229     {
230         GateRef source1 = PtrAdd(GetNormalStringData(thisValue), fromOffset);
231         GateRef dst = PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET));
232         Branch(canBeCompressed, &isUtf8Next, &isUtf16Next);
233         Bind(&isUtf8Next);
234         {
235             CopyUtf16AsUtf8(glue, source1, dst, len);
236             Jump(&exit);
237         }
238         Bind(&isUtf16Next);
239         {
240             CopyChars(glue, dst, source1, len, IntPtr(sizeof(uint16_t)), VariableType::INT16());
241             Jump(&exit);
242         }
243     }
244     Bind(&exit);
245     auto ret = *result;
246     env->SubCfgExit();
247     return ret;
248 }
249 
CopyChars(GateRef glue,GateRef dst,GateRef source,GateRef sourceLength,GateRef size,VariableType type)250 void BuiltinsStringStubBuilder::CopyChars(GateRef glue, GateRef dst, GateRef source,
251     GateRef sourceLength, GateRef size, VariableType type)
252 {
253     auto env = GetEnvironment();
254     Label entry(env);
255     env->SubCfgEntry(&entry);
256     DEFVARIABLE(dstTmp, VariableType::JS_ANY(), dst);
257     DEFVARIABLE(sourceTmp, VariableType::JS_ANY(), source);
258     DEFVARIABLE(len, VariableType::INT32(), sourceLength);
259     Label loopHead(env);
260     Label loopEnd(env);
261     Label next(env);
262     Label exit(env);
263     Jump(&loopHead);
264 
265     LoopBegin(&loopHead);
266     {
267         Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
268         Bind(&next);
269         {
270             len = Int32Sub(*len, Int32(1));
271             GateRef i = Load(type, *sourceTmp);
272             Store(type, glue, *dstTmp, IntPtr(0), i);
273             Jump(&loopEnd);
274         }
275     }
276     Bind(&loopEnd);
277     sourceTmp = PtrAdd(*sourceTmp, size);
278     dstTmp = PtrAdd(*dstTmp, size);
279     LoopEnd(&loopHead);
280 
281     Bind(&exit);
282     env->SubCfgExit();
283     return;
284 }
285 
CanBeCompressed(GateRef data,GateRef len,bool isUtf16)286 GateRef BuiltinsStringStubBuilder::CanBeCompressed(GateRef data, GateRef len, bool isUtf16)
287 {
288     auto env = GetEnvironment();
289     Label entry(env);
290     env->SubCfgEntry(&entry);
291     DEFVARIABLE(result, VariableType::BOOL(), True());
292     DEFVARIABLE(i, VariableType::INT32(), Int32(0));
293     Label loopHead(env);
294     Label loopEnd(env);
295     Label nextCount(env);
296     Label isNotASCIICharacter(env);
297     Label exit(env);
298     Jump(&loopHead);
299     LoopBegin(&loopHead);
300     {
301         Branch(Int32LessThan(*i, len), &nextCount, &exit);
302         Bind(&nextCount);
303         {
304             if (isUtf16) {
305                 GateRef tmp = Load(VariableType::INT16(), data,
306                     PtrMul(ZExtInt32ToPtr(*i), IntPtr(sizeof(uint16_t))));
307                 Branch(IsASCIICharacter(ZExtInt16ToInt32(tmp)), &loopEnd, &isNotASCIICharacter);
308             } else {
309                 GateRef tmp = Load(VariableType::INT8(), data,
310                     PtrMul(ZExtInt32ToPtr(*i), IntPtr(sizeof(uint8_t))));
311                 Branch(IsASCIICharacter(ZExtInt8ToInt32(tmp)), &loopEnd, &isNotASCIICharacter);
312             }
313             Bind(&isNotASCIICharacter);
314             {
315                 result = False();
316                 Jump(&exit);
317             }
318         }
319     }
320     Bind(&loopEnd);
321     i = Int32Add(*i, Int32(1));
322     LoopEnd(&loopHead);
323 
324     Bind(&exit);
325     auto ret = *result;
326     env->SubCfgExit();
327     return ret;
328 }
329 
CopyUtf16AsUtf8(GateRef glue,GateRef src,GateRef dst,GateRef sourceLength)330 void BuiltinsStringStubBuilder::CopyUtf16AsUtf8(GateRef glue, GateRef src, GateRef dst,
331     GateRef sourceLength)
332 {
333     auto env = GetEnvironment();
334     Label entry(env);
335     env->SubCfgEntry(&entry);
336     DEFVARIABLE(dstTmp, VariableType::JS_ANY(), dst);
337     DEFVARIABLE(sourceTmp, VariableType::JS_ANY(), src);
338     DEFVARIABLE(len, VariableType::INT32(), sourceLength);
339     Label loopHead(env);
340     Label loopEnd(env);
341     Label next(env);
342     Label exit(env);
343     Jump(&loopHead);
344     LoopBegin(&loopHead);
345     {
346         Branch(Int32GreaterThan(*len, Int32(0)), &next, &exit);
347         Bind(&next);
348         {
349             len = Int32Sub(*len, Int32(1));
350             GateRef i = Load(VariableType::INT16(), *sourceTmp);
351             Store(VariableType::INT8(), glue, *dstTmp, IntPtr(0), TruncInt16ToInt8(i));
352             Jump(&loopEnd);
353         }
354     }
355 
356     Bind(&loopEnd);
357     sourceTmp = PtrAdd(*sourceTmp, IntPtr(sizeof(uint16_t)));
358     dstTmp = PtrAdd(*dstTmp, IntPtr(sizeof(uint8_t)));
359     LoopEnd(&loopHead);
360 
361     Bind(&exit);
362     env->SubCfgExit();
363     return;
364 }
365 
GetUtf16Data(GateRef stringData,GateRef index)366 GateRef BuiltinsStringStubBuilder::GetUtf16Data(GateRef stringData, GateRef index)
367 {
368     return ZExtInt16ToInt32(Load(VariableType::INT16(), PtrAdd(stringData,
369         PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint16_t))))));
370 }
371 
IsASCIICharacter(GateRef data)372 GateRef BuiltinsStringStubBuilder::IsASCIICharacter(GateRef data)
373 {
374     return Int32LessThan(Int32Sub(data, Int32(1)), Int32(base::utf_helper::UTF8_1B_MAX));
375 }
376 
GetUtf8Data(GateRef stringData,GateRef index)377 GateRef BuiltinsStringStubBuilder::GetUtf8Data(GateRef stringData, GateRef index)
378 {
379     return ZExtInt8ToInt32(Load(VariableType::INT8(), PtrAdd(stringData,
380         PtrMul(ZExtInt32ToPtr(index), IntPtr(sizeof(uint8_t))))));
381 }
382 
StringIndexOf(GateRef lhsData,bool lhsIsUtf8,GateRef rhsData,bool rhsIsUtf8,GateRef pos,GateRef max,GateRef rhsCount)383 GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhsData, bool lhsIsUtf8, GateRef rhsData, bool rhsIsUtf8,
384                                                  GateRef pos, GateRef max, GateRef rhsCount)
385 {
386     auto env = GetEnvironment();
387     Label entry(env);
388     env->SubCfgEntry(&entry);
389     DEFVARIABLE(i, VariableType::INT32(), pos);
390     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
391     DEFVARIABLE(j, VariableType::INT32(), Int32(0));
392     DEFVARIABLE(k, VariableType::INT32(), Int32(1));
393     Label exit(env);
394     Label next(env);
395     Label continueFor(env);
396     Label lhsNotEqualFirst(env);
397     Label continueCount(env);
398     Label lessEnd(env);
399     Label equalEnd(env);
400     Label loopHead(env);
401     Label loopEnd(env);
402     Label nextCount(env);
403     Label nextCount1(env);
404     Label nextCount2(env);
405     GateRef first;
406     if (rhsIsUtf8) {
407         first = ZExtInt8ToInt32(Load(VariableType::INT8(), rhsData));
408     } else {
409         first = ZExtInt16ToInt32(Load(VariableType::INT16(), rhsData));
410     }
411     Jump(&loopHead);
412     LoopBegin(&loopHead);
413     Branch(Int32LessThanOrEqual(*i, max), &next, &exit);
414     Bind(&next);
415     {
416         Label loopHead1(env);
417         Label loopEnd1(env);
418         GateRef lhsTemp;
419         if (lhsIsUtf8) {
420             lhsTemp = GetUtf8Data(lhsData, *i);
421         } else {
422             lhsTemp = GetUtf16Data(lhsData, *i);
423         }
424         Branch(Int32NotEqual(lhsTemp, first), &nextCount1, &nextCount);
425         Bind(&nextCount1);
426         {
427             i = Int32Add(*i, Int32(1));
428             Jump(&loopHead1);
429         }
430         LoopBegin(&loopHead1);
431         {
432             Branch(Int32LessThanOrEqual(*i, max), &continueFor, &nextCount);
433             Bind(&continueFor);
434             {
435                 GateRef lhsTemp1;
436                 if (lhsIsUtf8) {
437                     lhsTemp1 = GetUtf8Data(lhsData, *i);
438                 } else {
439                     lhsTemp1 = GetUtf16Data(lhsData, *i);
440                 }
441                 Branch(Int32NotEqual(lhsTemp1, first), &lhsNotEqualFirst, &nextCount);
442                 Bind(&lhsNotEqualFirst);
443                 {
444                     i = Int32Add(*i, Int32(1));
445                     Jump(&loopEnd1);
446                 }
447             }
448         }
449         Bind(&loopEnd1);
450         LoopEnd(&loopHead1);
451         Bind(&nextCount);
452         {
453             Branch(Int32LessThanOrEqual(*i, max), &continueCount, &loopEnd);
454             Bind(&continueCount);
455             {
456                 Label loopHead2(env);
457                 Label loopEnd2(env);
458                 j = Int32Add(*i, Int32(1));
459                 GateRef end = Int32Sub(Int32Add(*j, rhsCount), Int32(1));
460                 k = Int32(1);
461                 Jump(&loopHead2);
462                 LoopBegin(&loopHead2);
463                 {
464                     Branch(Int32LessThan(*j, end), &lessEnd, &nextCount2);
465                     Bind(&lessEnd);
466                     {
467                         GateRef lhsTemp2;
468                         if (lhsIsUtf8) {
469                             lhsTemp2 = GetUtf8Data(lhsData, *j);
470                         } else {
471                             lhsTemp2 = GetUtf16Data(lhsData, *j);
472                         }
473                         GateRef rhsTemp;
474                         if (rhsIsUtf8) {
475                             rhsTemp = GetUtf8Data(rhsData, *k);
476                         } else {
477                             rhsTemp = GetUtf16Data(rhsData, *k);
478                         }
479                         Branch(Int32Equal(lhsTemp2, rhsTemp), &loopEnd2, &nextCount2);
480                     }
481                 }
482                 Bind(&loopEnd2);
483                 j = Int32Add(*j, Int32(1));
484                 k = Int32Add(*k, Int32(1));
485                 LoopEnd(&loopHead2);
486                 Bind(&nextCount2);
487                 {
488                     Branch(Int32Equal(*j, end), &equalEnd, &loopEnd);
489                     Bind(&equalEnd);
490                     result = *i;
491                     Jump(&exit);
492                 }
493             }
494         }
495     }
496     Bind(&loopEnd);
497     i = Int32Add(*i, Int32(1));
498     LoopEnd(&loopHead);
499 
500     Bind(&exit);
501     auto ret = *result;
502     env->SubCfgExit();
503     return ret;
504 }
505 
StringIndexOf(GateRef lhs,GateRef rhs,GateRef pos)506 GateRef BuiltinsStringStubBuilder::StringIndexOf(GateRef lhs, GateRef rhs, GateRef pos)
507 {
508     auto env = GetEnvironment();
509     Label entry(env);
510     env->SubCfgEntry(&entry);
511     DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
512     DEFVARIABLE(posTag, VariableType::INT32(), pos);
513     Label exit(env);
514     Label rhsCountEqualZero(env);
515     Label nextCount(env);
516     Label rhsCountNotEqualZero(env);
517     Label posLessZero(env);
518     Label posNotLessZero(env);
519     Label maxNotLessZero(env);
520     Label rhsIsUtf8(env);
521     Label rhsIsUtf16(env);
522     Label posRMaxNotGreaterLhs(env);
523 
524     GateRef lhsCount = GetLengthFromString(lhs);
525     GateRef rhsCount = GetLengthFromString(rhs);
526 
527     Branch(Int32GreaterThan(pos, lhsCount), &exit, &nextCount);
528     Bind(&nextCount);
529     {
530         Branch(Int32Equal(rhsCount, Int32(0)), &rhsCountEqualZero, &rhsCountNotEqualZero);
531         Bind(&rhsCountEqualZero);
532         {
533             result = pos;
534             Jump(&exit);
535         }
536         Bind(&rhsCountNotEqualZero);
537         {
538             Branch(Int32LessThan(pos, Int32(0)), &posLessZero, &posNotLessZero);
539             Bind(&posLessZero);
540             {
541                 posTag = Int32(0);
542                 Jump(&posNotLessZero);
543             }
544             Bind(&posNotLessZero);
545             {
546                 GateRef max = Int32Sub(lhsCount, rhsCount);
547                 Branch(Int32LessThan(max, Int32(0)), &exit, &maxNotLessZero);
548                 Bind(&maxNotLessZero);
549                 {
550                     GateRef posRMax = Int32Add(*posTag, rhsCount);
551                     Branch(Int32GreaterThan(posRMax, lhsCount), &exit, &posRMaxNotGreaterLhs);
552                     Bind(&posRMaxNotGreaterLhs);
553                     GateRef rhsData = GetNormalStringData(rhs);
554                     GateRef lhsData = GetNormalStringData(lhs);
555                     Branch(IsUtf8String(rhs), &rhsIsUtf8, &rhsIsUtf16);
556                     Bind(&rhsIsUtf8);
557                     {
558                         Label lhsIsUtf8(env);
559                         Label lhsIsUtf16(env);
560                         Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
561                         Bind(&lhsIsUtf8);
562                         {
563                             result = StringIndexOf(lhsData, true, rhsData, true, *posTag, max, rhsCount);
564                             Jump(&exit);
565                         }
566                         Bind(&lhsIsUtf16);
567                         {
568                             result = StringIndexOf(lhsData, false, rhsData, true, *posTag, max, rhsCount);
569                             Jump(&exit);
570                         }
571                     }
572                     Bind(&rhsIsUtf16);
573                     {
574                         Label lhsIsUtf8(env);
575                         Label lhsIsUtf16(env);
576                         Branch(IsUtf8String(lhs), &lhsIsUtf8, &lhsIsUtf16);
577                         Bind(&lhsIsUtf8);
578                         {
579                             result = StringIndexOf(lhsData, true, rhsData, false, *posTag, max, rhsCount);
580                             Jump(&exit);
581                         }
582                         Bind(&lhsIsUtf16);
583                         {
584                             result = StringIndexOf(lhsData, false, rhsData, false, *posTag, max, rhsCount);
585                             Jump(&exit);
586                         }
587                     }
588                 }
589             }
590         }
591     }
592     Bind(&exit);
593     auto ret = *result;
594     env->SubCfgExit();
595     return ret;
596 }
597 }  // namespace panda::ecmascript::kungfu
598