• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #ifndef ECMASCRIPT_STRING_INL_H
17 #define ECMASCRIPT_STRING_INL_H
18 
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/base/string_helper.h"
21 #include "ecmascript/ecma_vm.h"
22 #include "ecmascript/js_handle.h"
23 #include "ecmascript/js_tagged_value-inl.h"
24 #include "ecmascript/mem/space.h"
25 #include "ecmascript/object_factory-inl.h"
26 #include "ecmascript/debugger/js_debugger_manager.h"
27 
28 namespace panda::ecmascript {
29 /* static */
CreateEmptyString(const EcmaVM * vm)30 inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm)
31 {
32     auto string = vm->GetFactory()->AllocNonMovableLineStringObject(EcmaString::SIZE);
33     string->SetLength(0, true);
34     string->SetRawHashcode(0);
35     return string;
36 }
37 
38 /* static */
CreateFromUtf8(const EcmaVM * vm,const uint8_t * utf8Data,uint32_t utf8Len,bool canBeCompress,MemSpaceType type,bool isConstantString,uint32_t idOffset)39 inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
40                                               bool canBeCompress, MemSpaceType type, bool isConstantString,
41                                               uint32_t idOffset)
42 {
43     if (utf8Len == 0) {
44         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
45     }
46     EcmaString *string = nullptr;
47     if (canBeCompress) {
48         if (isConstantString) {
49             string = CreateConstantString(vm, utf8Data, utf8Len, canBeCompress, type, idOffset);
50         } else {
51             string = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
52             ASSERT(string != nullptr);
53             std::copy(utf8Data, utf8Data + utf8Len, string->GetDataUtf8Writable());
54         }
55     } else {
56         auto utf16Len = base::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
57         string = CreateLineStringWithSpaceType(vm, utf16Len, false, type);
58         ASSERT(string != nullptr);
59 
60         [[maybe_unused]] auto len =
61             base::utf_helper::ConvertRegionUtf8ToUtf16(utf8Data, string->GetDataUtf16Writable(), utf8Len, utf16Len);
62         ASSERT(len == utf16Len);
63     }
64 
65     ASSERT_PRINT(canBeCompress == CanBeCompressed(string), "Bad input canBeCompress!");
66     return string;
67 }
68 
69 /* static */
CreateFromUtf8CompressedSubString(const EcmaVM * vm,const JSHandle<EcmaString> & string,uint32_t offset,uint32_t utf8Len,MemSpaceType type)70 inline EcmaString *EcmaString::CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle<EcmaString> &string,
71                                                                  uint32_t offset, uint32_t utf8Len, MemSpaceType type)
72 {
73     if (UNLIKELY(utf8Len == 0)) {
74         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
75     }
76     EcmaString *subString = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
77     ASSERT(subString != nullptr);
78 
79     auto *utf8Data = string->GetDataUtf8() + offset;
80     std::copy(utf8Data, utf8Data + utf8Len, subString->GetDataUtf8Writable());
81     ASSERT_PRINT(CanBeCompressed(subString), "String cannot be compressed!");
82     return subString;
83 }
84 
CreateUtf16StringFromUtf8(const EcmaVM * vm,const uint8_t * utf8Data,uint32_t utf16Len,MemSpaceType type)85 inline EcmaString *EcmaString::CreateUtf16StringFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf16Len,
86     MemSpaceType type)
87 {
88     if (utf16Len == 0) {
89         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
90     }
91     auto string = CreateLineStringWithSpaceType(vm, utf16Len, false, type);
92     ASSERT(string != nullptr);
93     auto len = utf::ConvertRegionMUtf8ToUtf16(
94         utf8Data, string->GetDataUtf16Writable(), utf::Mutf8Size(utf8Data), utf16Len, 0);
95     if (len < utf16Len) {
96         string->TrimLineString(vm->GetJSThread(), len);
97     }
98     ASSERT_PRINT(false == CanBeCompressed(string), "Bad input canBeCompress!");
99     return string;
100 }
101 
TrimLineString(const JSThread * thread,uint32_t newLength)102 inline void EcmaString::TrimLineString(const JSThread *thread, uint32_t newLength)
103 {
104     ASSERT(IsLineString());
105     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
106     uint32_t oldLength = GetLength();
107     ASSERT(oldLength > newLength);
108     size_t trimBytes = (oldLength - newLength) * (IsUtf8() ? sizeof(uint8_t) : sizeof(uint16_t));
109     size_t size = IsUtf8() ? LineEcmaString::ComputeSizeUtf8(newLength) : LineEcmaString::ComputeSizeUtf16(newLength);
110     factory->FillFreeObject(ToUintPtr(this) + size, trimBytes, RemoveSlots::YES, ToUintPtr(this));
111     SetLength(newLength, CanBeCompressed(this));
112 }
113 
CreateFromUtf16(const EcmaVM * vm,const uint16_t * utf16Data,uint32_t utf16Len,bool canBeCompress,MemSpaceType type)114 inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
115                                                bool canBeCompress, MemSpaceType type)
116 {
117     if (utf16Len == 0) {
118         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
119     }
120     auto string = CreateLineStringWithSpaceType(vm, utf16Len, canBeCompress, type);
121     ASSERT(string != nullptr);
122 
123     if (canBeCompress) {
124         CopyChars(string->GetDataUtf8Writable(), utf16Data, utf16Len);
125     } else {
126         uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t));
127         if (memcpy_s(string->GetDataUtf16Writable(), len, utf16Data, len) != EOK) {
128             LOG_FULL(FATAL) << "memcpy_s failed";
129             UNREACHABLE();
130         }
131     }
132 
133     ASSERT_PRINT(canBeCompress == CanBeCompressed(string), "Bad input canBeCompress!");
134     return string;
135 }
136 
137 /* static */
CreateLineString(const EcmaVM * vm,size_t length,bool compressed)138 inline EcmaString *EcmaString::CreateLineString(const EcmaVM *vm, size_t length, bool compressed)
139 {
140     size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
141     auto string = vm->GetFactory()->AllocLineStringObject(size);
142     string->SetLength(length, compressed);
143     string->SetRawHashcode(0);
144     return string;
145 }
146 
147 /* static */
CreateLineStringNoGC(const EcmaVM * vm,size_t length,bool compressed)148 inline EcmaString *EcmaString::CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed)
149 {
150     size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
151     size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
152     auto string = vm->GetFactory()->AllocLineStringObjectNoGC(size);
153     string->SetLength(length, compressed);
154     string->SetRawHashcode(0);
155     return string;
156 }
157 
158 /* static */
CreateLineStringWithSpaceType(const EcmaVM * vm,size_t length,bool compressed,MemSpaceType type)159 inline EcmaString *EcmaString::CreateLineStringWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
160                                                              MemSpaceType type)
161 {
162     ASSERT(IsSMemSpace(type));
163     size_t size = compressed ? LineEcmaString::ComputeSizeUtf8(length) : LineEcmaString::ComputeSizeUtf16(length);
164     EcmaString *string = nullptr;
165     switch (type) {
166         case MemSpaceType::SHARED_OLD_SPACE:
167             string = vm->GetFactory()->AllocOldSpaceLineStringObject(size);
168             break;
169         case MemSpaceType::SHARED_NON_MOVABLE:
170             string = vm->GetFactory()->AllocNonMovableLineStringObject(size);
171             break;
172         case MemSpaceType::SHARED_READ_ONLY_SPACE:
173             string = vm->GetFactory()->AllocReadOnlyLineStringObject(size);
174             break;
175         default:
176             LOG_ECMA(FATAL) << "this branch is unreachable";
177             UNREACHABLE();
178     }
179     string->SetLength(length, compressed);
180     string->SetRawHashcode(0);
181     return string;
182 }
183 
CreateSlicedString(const EcmaVM * vm,MemSpaceType type)184 inline SlicedString *EcmaString::CreateSlicedString(const EcmaVM *vm, MemSpaceType type)
185 {
186     auto slicedString = SlicedString::Cast(vm->GetFactory()->AllocSlicedStringObject(type));
187     slicedString->SetRawHashcode(0);
188     slicedString->SetParent(vm->GetJSThread(), JSTaggedValue::Undefined(), BarrierMode::SKIP_BARRIER);
189     return slicedString;
190 }
191 
CreateConstantString(const EcmaVM * vm,const uint8_t * utf8Data,size_t length,bool compressed,MemSpaceType type,uint32_t idOffset)192 inline EcmaString *EcmaString::CreateConstantString(const EcmaVM *vm, const uint8_t *utf8Data,
193     size_t length, bool compressed, MemSpaceType type, uint32_t idOffset)
194 {
195     ASSERT(IsSMemSpace(type));
196     auto string = ConstantString::Cast(vm->GetFactory()->AllocConstantStringObject(type));
197     auto thread = vm->GetJSThread();
198     string->SetLength(length, compressed);
199     string->SetRawHashcode(0);
200     string->SetConstantData(const_cast<uint8_t *>(utf8Data));
201     // The string might be serialized, the const data will be replaced by index in the panda file.
202     string->SetEntityId(idOffset);
203     string->SetRelocatedData(thread, JSTaggedValue::Undefined(), BarrierMode::SKIP_BARRIER);
204     return string;
205 }
206 
207 /*
208  * In the multi-thread optimization scenario, start the application.
209  * 1.The thread executes until CheckThread () acquires the lock.
210  * 2.At this time, the thread receives the SIGPROF signal, interrupts the current program execution,
211  * and enters the signal processing function.
212  * 3.When CreateTreeString()->GetJSThread()->CheckThread() is executed, the lock cannot be obtained
213  * and the system has to wait, causing a deadlock.
214  * Therefore, if the function is executed during signal processing, the thread ID is directly obtained and
215  * the thread detection is not performed, thereby avoiding deadlock.
216  */
217 
GetDebuggerThread(const EcmaVM * vm,JSThread ** thread)218 inline void GetDebuggerThread(const EcmaVM *vm, JSThread **thread)
219 {
220     if (vm->GetJsDebuggerManager()->GetSignalState()) {
221         *thread = vm->GetJSThreadNoCheck();
222     } else {
223         *thread = vm->GetJSThread();
224     }
225 }
226 
CreateTreeString(const EcmaVM * vm,const JSHandle<EcmaString> & left,const JSHandle<EcmaString> & right,uint32_t length,bool compressed)227 inline EcmaString *EcmaString::CreateTreeString(const EcmaVM *vm,
228     const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, uint32_t length, bool compressed)
229 {
230     ECMA_STRING_CHECK_LENGTH_AND_TRHOW(vm, length);
231     JSThread *thread = nullptr;
232     GetDebuggerThread(vm, &thread);
233     auto string = TreeEcmaString::Cast(vm->GetFactory()->AllocTreeStringObject());
234     string->SetLength(length, compressed);
235     string->SetRawHashcode(0);
236     string->SetFirst(thread, left.GetTaggedValue());
237     string->SetSecond(thread, right.GetTaggedValue());
238     return string;
239 }
240 
241 /* static */
FastSubUtf8String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)242 EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
243                                           uint32_t length)
244 {
245     JSHandle<EcmaString> string(vm->GetJSThread(), CreateLineString(vm, length, true));
246     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
247     FlatStringInfo srcFlat = FlattenAllString(vm, src);
248     Span<uint8_t> dst(string->GetDataUtf8Writable(), length);
249     Span<const uint8_t> source(srcFlat.GetDataUtf8() + start, length);
250     EcmaString::MemCopyChars(dst, length, source, length);
251 
252     ASSERT_PRINT(CanBeCompressed(*string), "canBeCompresse does not match the real value!");
253     return *string;
254 }
255 
256 /* static */
FastSubUtf16String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)257 EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
258                                            uint32_t length)
259 {
260     FlatStringInfo srcFlat = FlattenAllString(vm, src);
261     bool canBeCompressed = CanBeCompressed(srcFlat.GetDataUtf16() + start, length);
262     JSHandle<EcmaString> string(vm->GetJSThread(), CreateLineString(vm, length, canBeCompressed));
263     // maybe happen GC,so get srcFlat again
264     srcFlat = FlattenAllString(vm, src);
265     if (canBeCompressed) {
266         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
267         CopyChars(string->GetDataUtf8Writable(), srcFlat.GetDataUtf16() + start, length);
268     } else {
269         uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t));
270         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
271         Span<uint16_t> dst(string->GetDataUtf16Writable(), length);
272         Span<const uint16_t> source(srcFlat.GetDataUtf16() + start, length);
273         EcmaString::MemCopyChars(dst, len, source, len);
274     }
275     ASSERT_PRINT(canBeCompressed == CanBeCompressed(*string), "canBeCompresse does not match the real value!");
276     return *string;
277 }
278 
GetData()279 inline uint16_t *EcmaString::GetData() const
280 {
281     ASSERT_PRINT(IsLineString(), "EcmaString: Read data from not LineString");
282     return LineEcmaString::Cast(this)->GetData();
283 }
284 
GetDataUtf8()285 inline const uint8_t *EcmaString::GetDataUtf8() const
286 {
287     ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
288     if (IsLineString()) {
289         return reinterpret_cast<uint8_t *>(GetData());
290     }
291     return ConstantString::Cast(this)->GetConstantData();
292 }
293 
GetDataUtf16()294 inline const uint16_t *EcmaString::GetDataUtf16() const
295 {
296     LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
297     return GetData();
298 }
299 
GetDataUtf8Writable()300 inline uint8_t *EcmaString::GetDataUtf8Writable()
301 {
302     ASSERT_PRINT(IsUtf8(), "EcmaString: Read data as utf8 for utf16 string");
303     if (IsConstantString()) {
304         return ConstantString::Cast(this)->GetConstantData();
305     }
306     return reinterpret_cast<uint8_t *>(GetData());
307 }
308 
GetDataUtf16Writable()309 inline uint16_t *EcmaString::GetDataUtf16Writable()
310 {
311     LOG_ECMA_IF(!IsUtf16(), FATAL) << "EcmaString: Read data as utf16 for utf8 string";
312     return GetData();
313 }
314 
GetUtf8Length(bool modify,bool isGetBufferSize)315 inline size_t EcmaString::GetUtf8Length(bool modify, bool isGetBufferSize) const
316 {
317     if (!IsUtf16()) {
318         return GetLength() + 1;  // add place for zero in the end
319     }
320     CVector<uint16_t> tmpBuf;
321     const uint16_t *data = GetUtf16DataFlat(this, tmpBuf);
322     return base::utf_helper::Utf16ToUtf8Size(data, GetLength(), modify, isGetBufferSize);
323 }
324 
325 template<bool verify>
At(int32_t index)326 inline uint16_t EcmaString::At(int32_t index) const
327 {
328     int32_t length = static_cast<int32_t>(GetLength());
329     if constexpr (verify) {
330         if ((index < 0) || (index >= length)) {
331             return 0;
332         }
333     }
334     switch (GetStringType()) {
335         case JSType::LINE_STRING:
336             return LineEcmaString::Cast(this)->Get<verify>(index);
337         case JSType::CONSTANT_STRING:
338             return ConstantString::Cast(this)->Get<verify>(index);
339         case JSType::SLICED_STRING:
340             return SlicedString::Cast(this)->Get<verify>(index);
341         case JSType::TREE_STRING:
342             return TreeEcmaString::Cast(this)->Get<verify>(index);
343         default:
344             LOG_ECMA(FATAL) << "this branch is unreachable";
345             UNREACHABLE();
346     }
347 }
348 
FastToUtf8Span()349 inline Span<const uint8_t> EcmaString::FastToUtf8Span() const
350 {
351     uint32_t strLen = GetLength();
352     ASSERT(IsUtf8());
353     const uint8_t *data = GetDataUtf8();
354     return Span<const uint8_t>(data, strLen);
355 }
356 
WriteData(uint32_t index,uint16_t src)357 inline void EcmaString::WriteData(uint32_t index, uint16_t src)
358 {
359     ASSERT(index < GetLength());
360     ASSERT(IsLineString());
361     LineEcmaString::Cast(this)->Set(index, src);
362 }
363 
IsFlat()364 inline bool EcmaString::IsFlat() const
365 {
366     if (!JSTaggedValue(this).IsTreeString()) {
367         return true;
368     }
369     return TreeEcmaString::Cast(this)->IsFlat();
370 }
371 
372 template <typename Char>
WriteToFlat(EcmaString * src,Char * buf,uint32_t maxLength)373 void EcmaString::WriteToFlat(EcmaString *src, Char *buf, uint32_t maxLength)
374 {
375     DISALLOW_GARBAGE_COLLECTION;
376     uint32_t length = src->GetLength();
377     if (length == 0) {
378         return;
379     }
380     while (true) {
381         ASSERT(length <= maxLength && length > 0);
382         ASSERT(length <= src->GetLength());
383         switch (src->GetStringType()) {
384             case JSType::LINE_STRING: {
385                 if (src->IsUtf8()) {
386                     CopyChars(buf, src->GetDataUtf8(), length);
387                 } else {
388                     CopyChars(buf, src->GetDataUtf16(), length);
389                 }
390                 return;
391             }
392             case JSType::CONSTANT_STRING: {
393                 ASSERT(src->IsUtf8());
394                 CopyChars(buf, src->GetDataUtf8(), length);
395                 return;
396             }
397             case JSType::TREE_STRING: {
398                 TreeEcmaString *treeSrc = TreeEcmaString::Cast(src);
399                 EcmaString *first = EcmaString::Cast(treeSrc->GetFirst());
400                 EcmaString *second = EcmaString::Cast(treeSrc->GetSecond());
401                 uint32_t firstLength = first->GetLength();
402                 uint32_t secondLength = second->GetLength();
403                 if (secondLength >= firstLength) {
404                     // second string is longer. So recurse over first.
405                     WriteToFlat(first, buf, maxLength);
406                     if (first == second) {
407                         CopyChars(buf + firstLength, buf, firstLength);
408                         return;
409                     }
410                     buf += firstLength;
411                     maxLength -= firstLength;
412                     src = second;
413                     length -= firstLength;
414                 } else {
415                     // first string is longer.  So recurse over second.
416                     if (secondLength > 0) {
417                         if (secondLength == 1) {
418                             buf[firstLength] = static_cast<Char>(second->At<false>(0));
419                         } else if ((second->IsLineOrConstantString()) && second->IsUtf8()) {
420                             CopyChars(buf + firstLength, second->GetDataUtf8(), secondLength);
421                         } else {
422                             WriteToFlat(second, buf + firstLength, maxLength - firstLength);
423                         }
424                     }
425                     maxLength = firstLength;
426                     src = first;
427                     length -= secondLength;
428                 }
429                 continue;
430             }
431             case JSType::SLICED_STRING: {
432                 EcmaString *parent = EcmaString::Cast(SlicedString::Cast(src)->GetParent());
433                 if (src->IsUtf8()) {
434                     CopyChars(buf, parent->GetDataUtf8() + SlicedString::Cast(src)->GetStartIndex(), length);
435                 } else {
436                     CopyChars(buf, parent->GetDataUtf16() + SlicedString::Cast(src)->GetStartIndex(), length);
437                 }
438                 return;
439             }
440             default:
441                 LOG_ECMA(FATAL) << "this branch is unreachable";
442                 UNREACHABLE();
443         }
444     }
445 }
446 
447 template <typename Char>
WriteToFlatWithPos(EcmaString * src,Char * buf,uint32_t length,uint32_t pos)448 void EcmaString::WriteToFlatWithPos(EcmaString *src, Char *buf, uint32_t length, uint32_t pos)
449 {
450     DISALLOW_GARBAGE_COLLECTION;
451     [[ maybe_unused ]] uint32_t maxLength = src->GetLength();
452     if (length == 0) {
453         return;
454     }
455     while (true) {
456         ASSERT(length + pos <= maxLength && length > 0);
457         ASSERT(length <= src->GetLength());
458         ASSERT(pos >= 0);
459         switch (src->GetStringType()) {
460             case JSType::LINE_STRING: {
461                 if (src->IsUtf8()) {
462                     CopyChars(buf, src->GetDataUtf8() + pos, length);
463                 } else {
464                     CopyChars(buf, src->GetDataUtf16() + pos, length);
465                 }
466                 return;
467             }
468             case JSType::CONSTANT_STRING: {
469                 ASSERT(src->IsUtf8());
470                 CopyChars(buf, src->GetDataUtf8() + pos, length);
471                 return;
472             }
473             case JSType::TREE_STRING: {
474                 TreeEcmaString *treeSrc = TreeEcmaString::Cast(src);
475                 EcmaString *first = EcmaString::Cast(treeSrc->GetFirst());
476                 ASSERT(first->IsLineString());
477                 src = first;
478                 continue;
479             }
480             case JSType::SLICED_STRING: {
481                 EcmaString *parent = EcmaString::Cast(SlicedString::Cast(src)->GetParent());
482                 if (src->IsUtf8()) {
483                     CopyChars(buf, parent->GetDataUtf8() + SlicedString::Cast(src)->GetStartIndex() + pos, length);
484                 } else {
485                     CopyChars(buf, parent->GetDataUtf16() + SlicedString::Cast(src)->GetStartIndex() + pos, length);
486                 }
487                 return;
488             }
489             default:
490                 LOG_ECMA(FATAL) << "this branch is unreachable";
491                 UNREACHABLE();
492         }
493     }
494 }
495 
GetDataUtf8()496 inline const uint8_t *FlatStringInfo::GetDataUtf8() const
497 {
498     return string_->GetDataUtf8() + startIndex_;
499 }
500 
GetDataUtf16()501 inline const uint16_t *FlatStringInfo::GetDataUtf16() const
502 {
503     return string_->GetDataUtf16() + startIndex_;
504 }
505 
GetDataUtf8Writable()506 inline uint8_t *FlatStringInfo::GetDataUtf8Writable() const
507 {
508     return string_->GetDataUtf8Writable() + startIndex_;
509 }
510 
GetDataUtf16Writable()511 inline uint16_t *FlatStringInfo::GetDataUtf16Writable() const
512 {
513     return string_->GetDataUtf16Writable() + startIndex_;
514 }
515 
GetDataUtf8()516 inline const uint8_t *EcmaStringAccessor::GetDataUtf8()
517 {
518     return string_->GetDataUtf8();
519 }
520 
GetDataUtf16()521 inline const uint16_t *EcmaStringAccessor::GetDataUtf16()
522 {
523     return string_->GetDataUtf16();
524 }
525 
GetUtf8Length(bool isGetBufferSize)526 inline size_t EcmaStringAccessor::GetUtf8Length(bool isGetBufferSize) const
527 {
528     return string_->GetUtf8Length(true, isGetBufferSize);
529 }
530 
ReadData(EcmaString * dst,EcmaString * src,uint32_t start,uint32_t destSize,uint32_t length)531 inline void EcmaStringAccessor::ReadData(EcmaString *dst, EcmaString *src,
532     uint32_t start, uint32_t destSize, uint32_t length)
533 {
534     dst->WriteData(src, start, destSize, length);
535 }
536 
FastToUtf8Span()537 inline Span<const uint8_t> EcmaStringAccessor::FastToUtf8Span()
538 {
539     return string_->FastToUtf8Span();
540 }
541 }  // namespace panda::ecmascript
542 #endif
543