• 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 #include "common_interfaces/objects/string/base_string-inl2.h"
28 
29 namespace panda::ecmascript {
30 /* static */
CreateEmptyString(const EcmaVM * vm)31 inline EcmaString *EcmaString::CreateEmptyString(const EcmaVM *vm)
32 {
33     auto string = vm->GetFactory()->AllocNonMovableLineStringObject(BaseString::SIZE);
34     string->InitLengthAndFlags(0, true);
35     string->SetMixHashcode(0);
36     return string;
37 }
38 
39 #if ENABLE_NEXT_OPTIMIZATION && defined(USE_CMC_GC)
40 /* static */
CreateFromUtf8(const EcmaVM * vm,const uint8_t * utf8Data,uint32_t utf8Len,bool canBeCompress,MemSpaceType type)41 inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
42                                               bool canBeCompress, MemSpaceType type)
43 {
44     if (utf8Len == 0) {
45         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
46     }
47     auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* {
48         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
49         return EcmaString::AllocLineString(vm, size, type)->ToBaseString();
50     };
51     BaseString *str = BaseString::CreateFromUtf8(std::move(allocator), utf8Data, utf8Len, canBeCompress);
52     return EcmaString::FromBaseString(str);
53 }
54 #else
CreateFromUtf8(const EcmaVM * vm,const uint8_t * utf8Data,uint32_t utf8Len,bool canBeCompress,MemSpaceType type)55 inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len,
56                                               bool canBeCompress, MemSpaceType type)
57 {
58     if (utf8Len == 0) {
59         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
60     }
61     EcmaString *string = nullptr;
62     if (canBeCompress) {
63         string = CreateLineStringWithSpaceType(vm, utf8Len, true, type);
64         ASSERT(string != nullptr);
65         std::copy(utf8Data, utf8Data + utf8Len, string->GetDataUtf8Writable());
66     } else {
67         auto utf16Len = common::utf_helper::Utf8ToUtf16Size(utf8Data, utf8Len);
68         string = CreateLineStringWithSpaceType(vm, utf16Len, false, type);
69         ASSERT(string != nullptr);
70 
71         [[maybe_unused]] auto len =
72             common::utf_helper::ConvertRegionUtf8ToUtf16(utf8Data, string->GetDataUtf16Writable(), utf8Len, utf16Len);
73         ASSERT(len == utf16Len);
74     }
75 
76     ASSERT_PRINT(canBeCompress == CanBeCompressed(string), "Bad input canBeCompress!");
77     return string;
78 }
79 #endif
80 
81 /* static */
CreateFromUtf8CompressedSubString(const EcmaVM * vm,const JSHandle<EcmaString> & string,uint32_t offset,uint32_t utf8Len,MemSpaceType type)82 inline EcmaString *EcmaString::CreateFromUtf8CompressedSubString(const EcmaVM *vm, const JSHandle<EcmaString> &string,
83                                                                  uint32_t offset, uint32_t utf8Len, MemSpaceType type)
84 {
85     if (UNLIKELY(utf8Len == 0)) {
86         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
87     }
88 
89     auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* {
90         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
91         return EcmaString::AllocLineString(vm, size, type)->ToBaseString();
92     };
93     BaseString *str = BaseString::CreateFromUtf8CompressedSubString(std::move(allocator), string, offset, utf8Len);
94     return EcmaString::FromBaseString(str);
95 }
96 
CreateUtf16StringFromUtf8(const EcmaVM * vm,const uint8_t * utf8Data,uint32_t utf16Len,MemSpaceType type)97 inline EcmaString *EcmaString::CreateUtf16StringFromUtf8(const EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf16Len,
98     MemSpaceType type)
99 {
100     if (utf16Len == 0) {
101         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
102     }
103     auto string = CreateLineStringWithSpaceType(vm, utf16Len, false, type);
104     ASSERT(string != nullptr);
105     auto len = utf::ConvertRegionMUtf8ToUtf16(
106         utf8Data, string->GetDataUtf16Writable(), utf::Mutf8Size(utf8Data), utf16Len, 0);
107     if (len < utf16Len) {
108         string->TrimLineString(len);
109     }
110     ASSERT_PRINT(false == CanBeCompressed(string), "Bad input canBeCompress!");
111     return string;
112 }
113 
TrimLineString(uint32_t newLength)114 inline void EcmaString::TrimLineString(uint32_t newLength)
115 {
116     BaseString* baseThis = reinterpret_cast<BaseString*>(this);
117     reinterpret_cast<LineString *>(baseThis)->LineString::Trim(newLength);
118 }
119 
CreateFromUtf16(const EcmaVM * vm,const uint16_t * utf16Data,uint32_t utf16Len,bool canBeCompress,MemSpaceType type)120 inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len,
121                                                bool canBeCompress, MemSpaceType type)
122 {
123     if (utf16Len == 0) {
124         return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
125     }
126 
127     auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* {
128         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
129         return EcmaString::AllocLineString(vm, size, type)->ToBaseString();
130     };
131     BaseString *str = BaseString::CreateFromUtf16(std::move(allocator), utf16Data, utf16Len, canBeCompress);
132     return EcmaString::FromBaseString(str);
133 }
134 
135 /* static */
CreateLineString(const EcmaVM * vm,size_t length,bool compressed)136 inline EcmaString *EcmaString::CreateLineString(const EcmaVM *vm, size_t length, bool compressed)
137 {
138     auto allocator = [vm](size_t size, common::CommonType stringType) -> BaseObject* {
139         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
140         EcmaString* string = vm->GetFactory()->AllocLineStringObject(size);
141         return string;
142     };
143     BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed);
144     return EcmaString::FromBaseString(str);
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     auto allocator = [vm](size_t size, common::CommonType stringType) -> BaseObject* {
151         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
152         size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
153         EcmaString* string = vm->GetFactory()->AllocLineStringObjectNoGC(size);
154         return string;
155     };
156     BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed);
157     return EcmaString::FromBaseString(str);
158 }
159 
AllocLineString(const EcmaVM * vm,size_t size,MemSpaceType type)160 inline EcmaString* EcmaString::AllocLineString(const EcmaVM* vm, size_t size, MemSpaceType type)
161 {
162     EcmaString* string = nullptr;
163     switch (type) {
164         case MemSpaceType::SHARED_OLD_SPACE:
165             string = vm->GetFactory()->AllocOldSpaceLineStringObject(size);
166             break;
167         case MemSpaceType::SHARED_NON_MOVABLE:
168             string = vm->GetFactory()->AllocNonMovableLineStringObject(size);
169             break;
170         case MemSpaceType::SHARED_READ_ONLY_SPACE:
171             string = vm->GetFactory()->AllocReadOnlyLineStringObject(size);
172             break;
173         default:
174             LOG_ECMA(FATAL) << "this branch is unreachable";
175             UNREACHABLE();
176     }
177     return string;
178 }
179 
180 /* static */
CreateLineStringWithSpaceType(const EcmaVM * vm,size_t length,bool compressed,MemSpaceType type)181 inline EcmaString *EcmaString::CreateLineStringWithSpaceType(const EcmaVM *vm, size_t length, bool compressed,
182                                                              MemSpaceType type)
183 {
184     auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* {
185         ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string");
186         ASSERT(IsSMemSpace(type));
187         return AllocLineString(vm, size, type);
188     };
189     BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed);
190     return EcmaString::FromBaseString(str);
191 }
192 
CreateSlicedString(const EcmaVM * vm,JSHandle<EcmaString> parent,MemSpaceType type)193 inline SlicedEcmaString* EcmaString::CreateSlicedString(const EcmaVM* vm, JSHandle<EcmaString> parent,
194                                                         MemSpaceType type)
195 {
196     auto allocator = [vm, type](size_t, common::CommonType stringType) -> BaseObject* {
197         ASSERT(stringType == common::CommonType::SLICED_STRING && "Can only allocate sliced string");
198         EcmaString* string = vm->GetFactory()->AllocSlicedStringObject(type);
199         return string;
200     };
201     auto writeBarrier = [vm](void* obj, size_t offset, BaseObject* str) {
202         Barriers::SetObject<true>(vm->GetJSThread(), obj, offset, reinterpret_cast<JSTaggedType>(str));
203     };
204     SlicedString* slicedString = BaseString::CreateSlicedString(std::move(allocator), std::move(writeBarrier), parent);
205     return SlicedEcmaString::FromBaseString(slicedString);
206 }
207 
208 /*
209  * In the multi-thread optimization scenario, start the application.
210  * 1.The thread executes until CheckThread () acquires the lock.
211  * 2.At this time, the thread receives the SIGPROF signal, interrupts the current program execution,
212  * and enters the signal processing function.
213  * 3.When CreateTreeString()->GetJSThread()->CheckThread() is executed, the lock cannot be obtained
214  * and the system has to wait, causing a deadlock.
215  * Therefore, if the function is executed during signal processing, the thread ID is directly obtained and
216  * the thread detection is not performed, thereby avoiding deadlock.
217  */
218 
GetDebuggerThread(const EcmaVM * vm,JSThread ** thread)219 inline void GetDebuggerThread(const EcmaVM *vm, JSThread **thread)
220 {
221     if (vm->GetJsDebuggerManager()->GetSignalState()) {
222         *thread = vm->GetJSThreadNoCheck();
223     } else {
224         *thread = vm->GetJSThread();
225     }
226 }
227 
CreateTreeString(const EcmaVM * vm,const JSHandle<EcmaString> & left,const JSHandle<EcmaString> & right,uint32_t length,bool compressed)228 inline EcmaString *EcmaString::CreateTreeString(const EcmaVM *vm,
229     const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, uint32_t length, bool compressed)
230 {
231     ECMA_STRING_CHECK_LENGTH_AND_TRHOW(vm, length);
232     JSThread *thread = nullptr;
233     GetDebuggerThread(vm, &thread);
234 
235     auto allocator = [vm](size_t, common::CommonType stringType) -> BaseObject* {
236         ASSERT(stringType == common::CommonType::TREE_STRING && "Can only allocate tree string");
237         EcmaString* string = vm->GetFactory()->AllocTreeStringObject();
238         return string;
239     };
240     auto writeBarrier = [thread](void* obj, size_t offset, BaseObject* str) {
241         Barriers::SetObject<true>(thread, obj, offset, reinterpret_cast<JSTaggedType>(str));
242     };
243     TreeString* treeString = BaseString::CreateTreeString(std::move(allocator), std::move(writeBarrier), left, right,
244                                                           length, compressed);
245     return TreeEcmaString::FromBaseString(treeString);
246 }
247 
248 /* static */
FastSubUtf8String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)249 EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
250                                           uint32_t length)
251 {
252     JSHandle<EcmaString> string(vm->GetJSThread(), CreateLineString(vm, length, true));
253     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
254     FlatStringInfo srcFlat = FlattenAllString(vm, src);
255     Span<uint8_t> dst(string->GetDataUtf8Writable(), length);
256     Span<const uint8_t> source(srcFlat.GetDataUtf8() + start, length);
257     EcmaString::MemCopyChars(dst, length, source, length);
258 
259     ASSERT_PRINT(CanBeCompressed(*string), "canBeCompresse does not match the real value!");
260     return *string;
261 }
262 
263 /* static */
FastSubUtf16String(const EcmaVM * vm,const JSHandle<EcmaString> & src,uint32_t start,uint32_t length)264 EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle<EcmaString> &src, uint32_t start,
265                                            uint32_t length)
266 {
267     FlatStringInfo srcFlat = FlattenAllString(vm, src);
268     bool canBeCompressed = CanBeCompressed(srcFlat.GetDataUtf16() + start, length);
269     JSHandle<EcmaString> string(vm->GetJSThread(), CreateLineString(vm, length, canBeCompressed));
270     // maybe happen GC,so get srcFlat again
271     srcFlat = FlattenAllString(vm, src);
272     if (canBeCompressed) {
273         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
274         BaseString::CopyChars(string->GetDataUtf8Writable(), srcFlat.GetDataUtf16() + start, length);
275     } else {
276         uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t));
277         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
278         Span<uint16_t> dst(string->GetDataUtf16Writable(), length);
279         Span<const uint16_t> source(srcFlat.GetDataUtf16() + start, length);
280         EcmaString::MemCopyChars(dst, len, source, len);
281     }
282     ASSERT_PRINT(canBeCompressed == CanBeCompressed(*string), "canBeCompresse does not match the real value!");
283     return *string;
284 }
285 
GetDataUtf8()286 inline const uint8_t* EcmaString::GetDataUtf8() const
287 {
288     return ToBaseString()->GetDataUtf8();
289 }
290 
GetDataUtf16()291 inline const uint16_t* EcmaString::GetDataUtf16() const
292 {
293     return ToBaseString()->GetDataUtf16();
294 }
295 
296 // require is LineString
GetDataUtf8Writable()297 inline uint8_t* EcmaString::GetDataUtf8Writable()
298 {
299     return ToBaseString()->GetDataUtf8Writable();
300 }
301 
GetDataUtf16Writable()302 inline uint16_t* EcmaString::GetDataUtf16Writable()
303 {
304     return ToBaseString()->GetDataUtf16Writable();
305 }
306 
GetUtf8Length(const JSThread * thread,bool modify,bool isGetBufferSize)307 inline size_t EcmaString::GetUtf8Length(const JSThread *thread, bool modify, bool isGetBufferSize) const
308 {
309     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
310         return Barriers::GetTaggedObject(thread, obj, offset);
311     };
312     return ToBaseString()->GetUtf8Length(std::move(readBarrier), modify, isGetBufferSize);
313 }
314 
315 template <bool verify>
At(const JSThread * thread,int32_t index)316 uint16_t EcmaString::At(const JSThread *thread, int32_t index) const
317 {
318     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
319         return Barriers::GetTaggedObject(thread, obj, offset);
320     };
321     return ToBaseString()->At<verify>(std::move(readBarrier), index);
322 }
323 
WriteData(uint32_t index,uint16_t src)324 inline void EcmaString::WriteData(uint32_t index, uint16_t src)
325 {
326     return ToBaseString()->WriteData(index, src);
327 }
328 
FastToUtf8Span()329 inline Span<const uint8_t> EcmaString::FastToUtf8Span() const
330 {
331     uint32_t len = GetLength();
332     ASSERT(IsUtf8());
333     const uint8_t *data = GetDataUtf8();
334     return Span<const uint8_t>(data, len);
335 }
336 
IsFlat(const JSThread * thread)337 inline bool EcmaString::IsFlat(const JSThread *thread) const
338 {
339     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
340         return Barriers::GetTaggedObject(thread, obj, offset);
341     };
342     return ToBaseString()->IsFlat(std::move(readBarrier));
343 }
344 
345 template <typename Char>
WriteToFlat(const JSThread * thread,EcmaString * src,Char * buf,uint32_t maxLength)346 void EcmaString::WriteToFlat(const JSThread *thread, EcmaString *src, Char *buf, uint32_t maxLength)
347 {
348     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
349         return Barriers::GetTaggedObject(thread, obj, offset);
350     };
351     return BaseString::WriteToFlat(std::move(readBarrier), src->ToBaseString(), buf, maxLength);
352 }
353 
354 template <typename Char>
WriteToFlatWithPos(const JSThread * thread,EcmaString * src,Char * buf,uint32_t length,uint32_t pos)355 void EcmaString::WriteToFlatWithPos(const JSThread *thread, EcmaString *src, Char *buf, uint32_t length, uint32_t pos)
356 {
357     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
358         return Barriers::GetTaggedObject(thread, obj, offset);
359     };
360     return BaseString::WriteToFlatWithPos(std::move(readBarrier), src->ToBaseString(), buf, length, pos);
361 }
362 
363 // It allows user to copy into buffer even if maxLength < length
WriteUtf8(const JSThread * thread,uint8_t * buf,size_t maxLength,bool isWriteBuffer)364 inline size_t EcmaString::WriteUtf8(const JSThread *thread, uint8_t *buf, size_t maxLength, bool isWriteBuffer) const
365 {
366     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
367         return Barriers::GetTaggedObject(thread, obj, offset);
368     };
369     return ToBaseString()->WriteUtf8(std::move(readBarrier), buf, maxLength, isWriteBuffer);
370 }
371 
372 // It allows user to copy into buffer even if maxLength < length
WriteUtf16(const JSThread * thread,uint16_t * buf,uint32_t targetLength,uint32_t bufLength)373 inline size_t EcmaString::WriteUtf16(const JSThread *thread, uint16_t *buf, uint32_t targetLength,
374                                      uint32_t bufLength) const
375 {
376     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
377         return Barriers::GetTaggedObject(thread, obj, offset);
378     };
379     return ToBaseString()->WriteUtf16(std::move(readBarrier), buf, targetLength, bufLength);
380 }
381 
WriteOneByte(const JSThread * thread,uint8_t * buf,size_t maxLength)382 inline size_t EcmaString::WriteOneByte(const JSThread *thread, uint8_t *buf, size_t maxLength) const
383 {
384     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
385         return Barriers::GetTaggedObject(thread, obj, offset);
386     };
387     return ToBaseString()->WriteOneByte(std::move(readBarrier), buf, maxLength);
388 }
389 
CopyDataUtf16(const JSThread * thread,uint16_t * buf,uint32_t maxLength)390 inline uint32_t EcmaString::CopyDataUtf16(const JSThread *thread, uint16_t *buf, uint32_t maxLength) const
391 {
392     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
393         return Barriers::GetTaggedObject(thread, obj, offset);
394     };
395     return ToBaseString()->CopyDataUtf16(std::move(readBarrier), buf, maxLength);
396 }
397 
ToUtf8Span(const JSThread * thread,CVector<uint8_t> & buf,bool modify,bool cesu8)398 inline Span<const uint8_t> EcmaString::ToUtf8Span(const JSThread *thread, CVector<uint8_t> &buf, bool modify,
399                                                   bool cesu8)
400 {
401     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
402         return Barriers::GetTaggedObject(thread, obj, offset);
403     };
404     return ToBaseString()->ToUtf8Span(std::move(readBarrier), buf, modify, cesu8);
405 }
406 
DebuggerToUtf8Span(const JSThread * thread,CVector<uint8_t> & buf,bool modify)407 inline Span<const uint8_t> EcmaString::DebuggerToUtf8Span(const JSThread *thread, CVector<uint8_t> &buf, bool modify)
408 {
409     auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * {
410         return Barriers::GetTaggedObject(thread, obj, offset);
411     };
412     return ToBaseString()->DebuggerToUtf8Span(std::move(readBarrier), buf, modify);
413 }
414 
GetDataUtf8()415 inline const uint8_t *FlatStringInfo::GetDataUtf8() const
416 {
417     return string_->GetDataUtf8() + startIndex_;
418 }
419 
GetDataUtf16()420 inline const uint16_t *FlatStringInfo::GetDataUtf16() const
421 {
422     return string_->GetDataUtf16() + startIndex_;
423 }
424 
GetDataUtf8Writable()425 inline uint8_t *FlatStringInfo::GetDataUtf8Writable() const
426 {
427     return string_->GetDataUtf8Writable() + startIndex_;
428 }
429 
GetDataUtf16Writable()430 inline uint16_t *FlatStringInfo::GetDataUtf16Writable() const
431 {
432     return string_->GetDataUtf16Writable() + startIndex_;
433 }
434 
GetDataUtf8()435 inline const uint8_t *EcmaStringAccessor::GetDataUtf8()
436 {
437     return string_->GetDataUtf8();
438 }
439 
GetDataUtf16()440 inline const uint16_t *EcmaStringAccessor::GetDataUtf16()
441 {
442     return string_->GetDataUtf16();
443 }
444 
GetUtf8Length(const JSThread * thread,bool isGetBufferSize)445 inline size_t EcmaStringAccessor::GetUtf8Length(const JSThread *thread, bool isGetBufferSize) const
446 {
447     return string_->GetUtf8Length(thread, true, isGetBufferSize);
448 }
449 
450 template <RBMode mode>
ReadData(const JSThread * thread,EcmaString * dst,EcmaString * src,uint32_t start,uint32_t destSize,uint32_t length)451 inline void EcmaStringAccessor::ReadData(const JSThread *thread, EcmaString *dst, EcmaString *src, uint32_t start,
452                                          uint32_t destSize, uint32_t length)
453 {
454     dst->WriteData<mode>(thread, src, start, destSize, length);
455 }
456 
FastToUtf8Span()457 inline Span<const uint8_t> EcmaStringAccessor::FastToUtf8Span() const
458 {
459     return string_->FastToUtf8Span();
460 }
461 }  // namespace panda::ecmascript
462 #endif
463