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