9#include "hwy/highway.h"
79 template <
typename SrcChar,
typename DestChar>
82 if (
sizeof(DestChar) == 1) {
89 static_cast<std::make_unsigned_t<SrcChar>
>(c);
105 constexpr size_t length =
N - 1;
106 static_assert(length > 0);
109 const uint8_t* chars =
reinterpret_cast<const uint8_t*
>(
literal);
120 template <
typename SrcChar>
129 template <
typename SrcChar>
165 string->GetCharVector<uint8_t>(no_gc).begin(), length);
170 string->GetCharVector<uint16_t>(no_gc).begin(), length);
176 string->GetCharVector<uint8_t>(no_gc).begin(), length);
180 string->GetCharVector<uint16_t>(no_gc).begin(), length);
191 const bool representation_ok =
195 if (representation_ok) {
196 size_t length =
string->length();
208 template <
typename SrcChar>
212 if (
sizeof(SrcChar) == 1) {
227 template <
typename SrcChar>
229 if (from == to)
return;
241 template <
bool deferred_
string_key>
263 template <ElementsKind kind>
266 template <ElementsKind kind>
269 template <ElementsKind kind,
typename T>
272 bool can_treat_hole_as_undefined);
277 template <
bool raw_json>
280 template <
typename DestChar>
289 const uint8_t* u =
reinterpret_cast<const uint8_t*
>(
s);
290 while (*u !=
'\0')
Append(*(u++));
295 reinterpret_cast<const uint8_t*
>(str.data()), str.length()),
309 template <
typename SrcChar>
311 if (from == to)
return;
341 isolate->main_thread_local_heap()->AddGCEpilogueCallback(
352 if (string->map() == roots.internalized_one_byte_string_map()) {
371 :
static_cast<Tagged_t>(
string.ptr());
389 template <
typename SrcChar,
typename DestChar,
bool raw_json>
394 template <
typename SrcChar,
typename DestChar,
bool raw_json>
400 template <
typename DestChar>
458constexpr int kJsonEscapeTableEntrySize = 8;
462constexpr const char*
const JsonEscapeTable =
463 "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 "
464 "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 "
465 "\\b\0 \\t\0 \\n\0 \\u000b\0 "
466 "\\f\0 \\r\0 \\u000e\0 \\u000f\0 "
467 "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 "
468 "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 "
469 "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 "
470 "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 "
471 " \0 !\0 \\\"\0 #\0 "
486 "\\\\\0 ]\0 ^\0 _\0 ";
488constexpr bool JsonDoNotEscapeFlagTable[] = {
489 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
490 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
491 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
492 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
493 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
494 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
495 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
496 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
497 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
498 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
499 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
502template <
typename Char>
503constexpr bool DoNotEscape(Char c);
506constexpr bool DoNotEscape(uint8_t c) {
508 return JsonDoNotEscapeFlagTable[c];
512constexpr bool DoNotEscape(uint16_t c) {
514 return (c >= 0x20 && c <= 0x21) ||
515 (c >= 0x23 && c != 0x5C && (c < 0xD800 || c > 0xDFFF));
519constexpr bool NeedsEscape(uint32_t input) {
520 constexpr uint32_t mask_0x20 = 0x20202020u;
521 constexpr uint32_t mask_0x22 = 0x22222222u;
522 constexpr uint32_t mask_0x5c = 0x5C5C5C5Cu;
523 constexpr uint32_t mask_0x01 = 0x01010101u;
524 constexpr uint32_t mask_msb = 0x80808080u;
526 const uint32_t has_lt_0x20 = input - mask_0x20;
528 const uint32_t has_0x22 = (input ^ mask_0x22) - mask_0x01;
530 const uint32_t has_0x5c = (input ^ mask_0x5c) - mask_0x01;
532 const uint32_t result_mask = ~input & mask_msb;
533 const uint32_t
result = ((has_lt_0x20 | has_0x22 | has_0x5c) & result_mask);
537bool CanFastSerializeJSArray(Isolate* isolate,
Tagged<JSArray> object) {
540 if (!Protectors::IsNoElementsIntact(isolate))
return false;
541 Tagged<Map> map =
object->map(isolate);
544 return native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) == proto;
551 if (!raw_object->HasFastProperties())
return false;
552 auto roots = ReadOnlyRoots(isolate);
553 auto elements = raw_object->elements();
554 return elements == roots.empty_fixed_array() ||
555 elements == roots.empty_slow_element_dictionary();
562 encoding_(
String::ONE_BYTE_ENCODING),
564 two_byte_ptr_(nullptr),
566 part_length_(kInitialPartLength),
568 stack_nesting_level_(0),
572 key_cache_(isolate) {
634 if (
IsNumber(*element) || IsString(*element)) {
637 }
else if (IsJSPrimitiveWrapper(*element)) {
640 if (
IsNumber(*value) || IsString(*value)) {
645 if (
key.is_null())
continue;
650 if (!set_candidate.
ToHandle(&set)) {
658 }
else if (IsCallable(*replacer)) {
667 if (IsJSPrimitiveWrapper(*gap)) {
670 if (IsString(*value)) {
679 if (IsString(*gap)) {
681 if (gap_string->length() > 0) {
682 uint32_t gap_length = std::min(gap_string->length(), 10u);
685 for (uint32_t
i = 0;
i < gap_length;
i++) {
691 gap_[gap_length] =
'\0';
698 for (uint32_t
i = 0;
i < gap_length;
i++)
gap_[
i] =
' ';
699 gap_[gap_length] =
'\0';
715 if (!IsCallable(*fun))
return object;
746 initial_holder,
NONE);
765 if (check.HasOverflowed()) {
773 size_t size =
stack_.size();
774 for (
size_t i = 0;
i <
size; ++
i) {
780 MessageTemplate::kCircularStructure, circle_description);
848 if (key_as_string->length() == 0) {
861 static constexpr uint32_t kBufferSize =
sizeof(
"-2147483648") - 1;
862 char chars[kBufferSize];
879 size_t index = start_index;
880 const size_t stack_size =
stack_.size();
885 const size_t prefix_end =
887 for (; index < prefix_end; ++
index) {
900 for (; index < stack_size; ++
index) {
915 !iter.
IsAtEnd(); iter.Advance()) {
916 if (iter.GetCurrent()->map()->may_have_interesting_properties()) {
923template <
bool deferred_
string_key>
935 if (!
IsSmi(*
object)) {
938 if ((InstanceTypeChecker::IsJSReceiver(instance_type) &&
940 InstanceTypeChecker::IsBigInt(instance_type)) {
957 if (
IsSmi(*
object)) {
964 switch (instance_type) {
965 case HEAP_NUMBER_TYPE:
970 *
factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
992 case JS_PRIMITIVE_WRAPPER_TYPE:
1001 case JS_RAW_JSON_TYPE:
1006 if (raw_json_obj->HasInitialLayout(
isolate_)) {
1019 JSObject::GetProperty(
isolate_, raw_json_obj,
1021 .ToHandleChecked());
1028#if V8_ENABLE_WEBASSEMBLY
1029 case WASM_STRUCT_TYPE:
1030 case WASM_ARRAY_TYPE:
1034 if (InstanceTypeChecker::IsString(instance_type)) {
1042 CHECK(IsJSReceiver(*
object));
1046 if (InstanceTypeChecker::IsJSProxy(instance_type)) {
1050 DCHECK(IsJSObject(*
object));
1061 if (IsString(raw)) {
1072 }
else if (IsBigInt(raw)) {
1074 *
factory()->NewTypeError(MessageTemplate::kBigIntSerializeJSON));
1076 }
else if (IsBoolean(raw)) {
1093 static constexpr uint32_t kBufferSize =
sizeof(
"-2147483648") - 1;
1094 char chars[kBufferSize];
1101 if (std::isinf(number) || std::isnan(number)) {
1105 static constexpr uint32_t kBufferSize = 100;
1106 char chars[kBufferSize];
1115 uint32_t length = 0;
1117 DCHECK(!IsAccessCheckNeeded(*
object));
1124 if (stack_push !=
SUCCESS)
return stack_push;
1128 uint32_t slow_path_index = 0;
1131#define CASE_WITH_INTERRUPT(kind) \
1133 result = SerializeFixedArrayWithInterruptCheck<kind>(object, length, \
1134 &slow_path_index); \
1136#define CASE_WITH_TRANSITION(kind) \
1138 result = SerializeFixedArrayWithPossibleTransitions<kind>( \
1139 object, length, &slow_path_index); \
1142 switch (object->GetElementsKind()) {
1153#undef CASE_WITH_TRANSITION
1154#undef CASE_WITH_INTERRUPT
1168template <ElementsKind kind>
1176 constexpr uint32_t kInterruptLength = 4000;
1177 uint32_t limit = std::min(length, kInterruptLength);
1178 constexpr uint32_t kMaxAllowedFastPackedLength =
1179 std::numeric_limits<uint32_t>::max() - kInterruptLength;
1183 bool bailout_on_hole =
1184 is_holey ? !CanFastSerializeJSArray(
isolate_, *array) :
true;
1188 for (;
i < limit;
i++) {
1190 Cast<ArrayT>(array->elements()),
i, *array, bailout_on_hole);
1191 if constexpr (is_holey) {
1193 *slow_path_index =
i;
1202 DCHECK_LT(limit, kMaxAllowedFastPackedLength);
1203 limit = std::min(length, limit + kInterruptLength);
1212template <ElementsKind kind>
1221 bool should_check_treat_hole_as_undefined =
true;
1223 if (array->length() != *old_length ||
kind != array->GetElementsKind()) {
1225 *slow_path_index =
i;
1230 if (is_holey && IsTheHole(current_element)) {
1231 if (should_check_treat_hole_as_undefined) {
1232 if (!CanFastSerializeJSArray(
isolate_, *array)) {
1233 *slow_path_index =
i;
1236 should_check_treat_hole_as_undefined =
false;
1249 if constexpr (is_holey) {
1250 should_check_treat_hole_as_undefined =
true;
1257template <ElementsKind kind,
typename T>
1260 bool bailout_on_hole) {
1262 if (elements->is_the_hole(
isolate_,
i)) {
1288 static constexpr uint32_t kMaxSerializableArrayLength =
1290 if (length > kMaxSerializableArrayLength) {
1323 !CanFastSerializeJSObject(*
object,
isolate_)) {
1329 if (stack_push !=
SUCCESS)
return stack_push;
1336 DCHECK(!IsJSGlobalProxy(*
object));
1337 DCHECK(!object->HasIndexedInterceptor());
1338 DCHECK(!object->HasNamedInterceptor());
1341 if (map->NumberOfOwnDescriptors() == 0) {
1347 if (stack_push !=
SUCCESS)
return stack_push;
1357 map->instance_descriptors(cage_base);
1360 if (!IsString(name, cage_base))
continue;
1362 details = descriptors->GetDetails(
i);
1367 *map == object->map(cage_base)) {
1373 property =
handle(object->RawFastPropertyAt(field_index),
isolate_);
1435 if (stack_push !=
SUCCESS)
return stack_push;
1467template <
typename SrcChar,
typename DestChar,
bool raw_json>
1472 DCHECK(
sizeof(DestChar) >=
sizeof(SrcChar));
1473 bool required_escaping =
false;
1474 size_t uncopied_src_index = 0;
1475 for (
size_t i = 0;
i < src.
size();
i++) {
1477 if (raw_json || DoNotEscape(c)) {
1479 }
else if (
sizeof(SrcChar) != 1 &&
1481 static_cast<SrcChar
>(0xDFFF))) {
1483 required_escaping =
true;
1491 if (
i + 1 < src.
size()) {
1493 SrcChar next = src[
i + 1];
1495 static_cast<SrcChar
>(0xDFFF))) {
1505 std::string_view hex =
1513 std::string_view hex =
1523 std::string_view hex =
1527 uncopied_src_index =
i + 1;
1529 required_escaping =
true;
1532 dest->
AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
1533 uncopied_src_index =
i + 1;
1537 return required_escaping;
1540template <
typename SrcChar,
typename DestChar,
bool raw_json>
1543 bool required_escaping =
false;
1553 vector, &no_extend);
1556 (string->IsFlat() &&
1558 size_t uncopied_src_index = 0;
1559 for (
size_t i = 0;
i < vector.
size();
i++) {
1560 SrcChar c = vector.at(
i);
1561 if (raw_json || DoNotEscape(c)) {
1563 }
else if (
sizeof(SrcChar) != 1 &&
1565 static_cast<SrcChar
>(0xDFFF))) {
1567 required_escaping =
true;
1575 if (
i + 1 < vector.
size()) {
1577 SrcChar next = vector.at(
i + 1);
1579 static_cast<SrcChar
>(0xDFFF))) {
1589 std::string_view hex =
1597 std::string_view hex =
1607 std::string_view hex =
1611 uncopied_src_index =
i + 1;
1613 required_escaping =
true;
1616 AppendCString(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
1617 uncopied_src_index =
i + 1;
1623 return required_escaping;
1626template <
typename DestChar>
1630 if (
key->map() != roots.internalized_one_byte_string_map()) {
1636 size_t length =
key->length();
1637 size_t copy_length =
length;
1638 if constexpr (
sizeof(DestChar) == 1) {
1643 constexpr int kRounding = 4;
1645 copy_length =
RoundUp(length, kRounding);
1651 size_t required_length = copy_length + 3;
1661 key.address() +
key->Size());
1664 DCHECK(DoNotEscape(chars[
i]));
1674 if (
gap_ ==
nullptr)
return;
1692 bool wrote_simple =
false;
1701 if (!wrote_simple) {
1703 if (!required_escaping) {
1712template <
bool raw_json>
1716 auto string = *object;
1768template <
typename Char>
1775 template <
typename SrcChar>
1776 requires(
sizeof(Char) >=
sizeof(SrcChar))
1782 template <
typename SrcChar>
1783 requires(
sizeof(Char) >=
sizeof(SrcChar))
1784 void Append(
const SrcChar* chars,
size_t length) {
1792 current_requested_capacity_ =
size;
1811 template <
typename Dst>
1821 size_t segment_length = segment.
size();
1823 dst += segment_length;
1855 const size_t new_segment_size =
1882 DCHECK_LE(size, current_requested_capacity_);
1883 current_requested_capacity_ -=
size;
1896 size_t current_requested_capacity_;
1957 template <ElementsKind kind,
bool with_
interrupt_check>
1969 template <ResumeJSObjectMode mode>
2042 return js_object_.in_object_properties_start;
2095 bool with_interrupt_check) {
2098 if (with_interrupt_check) {
2104 if (with_interrupt_check) {
2133template <
typename Char>
2139 template <
typename DstChar>
2146 template <
typename OldChar>
2147 requires(
sizeof(OldChar) <
sizeof(Char))
2163 template <
bool no_escaping>
2166 template <
typename StringT,
bool no_escaping>
2169 template <
typename StringT>
2180 template <ResumeJSObjectMode mode>
2183 uint16_t nof_descriptors, uint8_t in_object_properties,
2187 template <ElementsKind kind>
2190 template <ElementsKind kind>
2193 template <ElementsKind kind,
bool with_
interrupt_checks,
typename T>
2201 template <
typename SrcChar>
2205 template <
typename SrcChar>
2213 constexpr size_t length =
N - 1;
2214 static_assert(length > 0);
2216 const uint8_t* chars =
reinterpret_cast<const uint8_t*
>(
literal);
2217 buffer_.Append(chars, length);
2222 constexpr size_t length =
N - 1;
2223 static_assert(length > 0);
2229 buffer_.Append(
reinterpret_cast<const unsigned char*
>(chars), len);
2248 template <
typename SrcChar>
2249 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
2253 template <
typename SrcChar>
2257 template <
typename SrcChar>
2258 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
2260 size_t uncopied_src_index,
2263 template <
typename SrcChar>
2264 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
2266 size_t start,
size_t uncopied_src_index,
2269 template <
typename SrcChar>
2270 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
2274 template <
typename SrcChar>
2275 requires(
sizeof(SrcChar) ==
sizeof(
base::uc16))
2307 if (
V8_UNLIKELY(map->may_have_interesting_properties()))
return false;
2311 return V8_LIKELY(proto == initial_proto);
2314V8_INLINE bool CanFastSerializeJSObjectFastPath(
2318 if (
V8_UNLIKELY(!object->HasFastProperties()))
return false;
2319 auto roots = ReadOnlyRoots(isolate);
2320 auto elements =
object->elements();
2321 if (
V8_UNLIKELY(elements != roots.empty_fixed_array() &&
2322 elements != roots.empty_slow_element_dictionary())) {
2325 if (
V8_UNLIKELY(map->may_have_interesting_properties()))
return false;
2329 return V8_LIKELY(proto == initial_proto);
2334template <
typename Char>
2338 buffer_(isolate->allocator()),
2339 map_cache_(&
zone_) {}
2341template <
typename Char>
2346 static constexpr uint32_t kBufferSize =
sizeof(
"-2147483648") - 1;
2347 char chars[kBufferSize];
2353template <
typename Char>
2355 if (
V8_UNLIKELY(std::isinf(number) || std::isnan(number))) {
2356 AppendCStringLiteral(
"null");
2359 static constexpr uint32_t kBufferSize = 100;
2360 char chars[kBufferSize];
2366template <
typename Char>
2367template <
bool no_escaping>
2371#if V8_STATIC_ROOTS_BOOL
2375 if (map == roots.internalized_one_byte_string_map()) {
2377 no_escaping>(
key, comma,
2379 }
else if (map == roots.external_internalized_one_byte_string_map() ||
2381 roots.uncached_external_internalized_one_byte_string_map()) {
2383 no_escaping>(
key, comma,
2386 if constexpr (is_one_byte) {
2391 if constexpr (no_escaping) {
2397 if (map == roots.internalized_two_byte_string_map()) {
2398 return SerializeObjectKey<SeqTwoByteString, no_escaping>(
key, comma,
2401 map == roots.external_internalized_two_byte_string_map() ||
2402 map == roots.uncached_external_internalized_two_byte_string_map()) {
2403 return SerializeObjectKey<ExternalTwoByteString, no_escaping>(
2410 switch (instance_type) {
2413 no_escaping>(
key, comma,
2418 no_escaping>(
key, comma,
2421 return SerializeObjectKey<SeqTwoByteString, no_escaping>(
key, comma,
2425 return SerializeObjectKey<ExternalTwoByteString, no_escaping>(
key, comma,
2438size_t MaxEscapedStringLength(uint32_t length) {
return length << 3; }
2442template <
typename Char>
2443template <
typename StringT,
bool no_escaping>
2447 using StringChar = StringT::Char;
2448 if constexpr (is_one_byte &&
sizeof(StringChar) == 2) {
2452 if constexpr (no_escaping) {
2459 const StringChar* chars;
2460 if constexpr (
requires {
string->GetChars(no_gc); }) {
2461 chars =
string->GetChars(no_gc);
2463 chars =
string->GetChars();
2465 const uint32_t length =
string->length();
2467 if constexpr (no_escaping) {
2470 max_length = MaxEscapedStringLength(length);
2473 EnsureCapacity(max_length);
2474 SeparatorUnchecked(comma);
2475 AppendCharacterUnchecked(
'"');
2477 if constexpr (no_escaping) {
2478 AppendStringNoEscapes(chars, length, no_gc);
2481 bool needs_escaping = AppendString(chars, length, no_gc);
2486 AppendCharacterUnchecked(
'"');
2487 AppendCharacterUnchecked(
':');
2492template <
typename Char>
2493template <
typename StringT>
2496 using StringChar = StringT::Char;
2497 if constexpr (is_one_byte &&
sizeof(StringChar) == 2) {
2501 const StringChar* chars;
2502 if constexpr (
requires {
string->GetChars(no_gc); }) {
2503 chars =
string->GetChars(no_gc);
2505 chars =
string->GetChars();
2507 const uint32_t length =
string->length();
2508 EnsureCapacity(MaxEscapedStringLength(length) + 2 );
2509 AppendCharacterUnchecked(
'"');
2510 AppendString(chars, length, no_gc);
2511 AppendCharacterUnchecked(
'"');
2516template <
typename Char>
2523 if (
IsSmi(
object)) {
2530 switch (instance_type) {
2533 return SerializeString<SeqOneByteString>(obj, no_gc);
2538 return SerializeString<ExternalOneByteString>(obj, no_gc);
2541 if (IsExternalString(actual)) {
2542 return SerializeString<ExternalOneByteString>(actual, no_gc);
2544 return SerializeString<SeqOneByteString>(actual, no_gc);
2549 return SerializeString<SeqTwoByteString>(obj, no_gc);
2554 return SerializeString<ExternalTwoByteString>(obj, no_gc);
2556 if constexpr (is_one_byte) {
2560 if (IsExternalString(actual)) {
2561 return SerializeString<ExternalTwoByteString>(actual, no_gc);
2563 return SerializeString<SeqTwoByteString>(actual, no_gc);
2567 case HEAP_NUMBER_TYPE:
2573 AppendCStringLiteral(
"false");
2576 AppendCStringLiteral(
"true");
2579 AppendCStringLiteral(
"null");
2586 case JS_PRIMITIVE_WRAPPER_TYPE:
2588 case JS_OBJECT_TYPE:
2607 if (!it.IsFound()) {
2614 if (!IsJSFunction(*fun)) {
2622template <
typename Char>
2633 if (IsSymbol(raw)) {
2641 auto elements = obj->elements();
2642 if (
V8_UNLIKELY(elements != roots.empty_fixed_array() &&
2643 elements != roots.empty_slow_element_dictionary())) {
2647 AppendCStringLiteral(
"{}");
2649 }
else if (IsString(raw)) {
2659 Builtin::kStringPrototypeToString)) {
2668 return SerializeString<SeqOneByteString>(str, no_gc);
2671 return SerializeString<SeqTwoByteString>(str, no_gc);
2674 return SerializeString<ExternalOneByteString>(str, no_gc);
2677 return SerializeString<ExternalTwoByteString>(str, no_gc);
2680 string = str->actual();
2697 Builtin::kNumberPrototypeValueOf)) {
2704 DCHECK(IsHeapNumber(raw));
2707 }
else if (IsBoolean(raw)) {
2709 AppendCStringLiteral(
"true");
2711 AppendCStringLiteral(
"false");
2714 }
else if (IsBigInt(raw)) {
2721template <
typename Char>
2725 if (
V8_UNLIKELY(!CanFastSerializeJSObjectFastPath(
2726 obj, initial_jsobject_proto_, map,
isolate_))) {
2729 AppendCharacter(
'{');
2730 const uint16_t nof_descriptors = map->NumberOfOwnDescriptors();
2731 const uint8_t in_object_properties = map->GetInObjectProperties();
2732 const uint8_t in_object_properties_start =
2733 map->GetInObjectPropertiesStartInWords();
2735 auto mode = map_cache_.find(map);
2736 if (mode == map_cache_.end()) {
2737 return ResumeJSObject<ResumeJSObjectMode::kBuildingMapCache>(
2738 obj, map, 0, nof_descriptors, in_object_properties,
2739 in_object_properties_start, descriptors,
false, no_gc);
2740 }
else if (mode->second ==
true) {
2741 return ResumeJSObject<ResumeJSObjectMode::kWithMapCache>(
2742 obj, map, 0, nof_descriptors, in_object_properties,
2743 in_object_properties_start, descriptors,
false, no_gc);
2745 return ResumeJSObject<ResumeJSObjectMode::kWithoutMapCache>(
2746 obj, map, 0, nof_descriptors, in_object_properties,
2747 in_object_properties_start, descriptors,
false, no_gc);
2751template <
typename Char>
2752template <ResumeJSObjectMode mode>
2755 uint16_t nof_descriptors, uint8_t in_object_properties,
2764 std::numeric_limits<uint16_t>::max());
2766 const uint16_t descriptor_idx =
static_cast<uint16_t
>(
i.as_uint32());
2773 map_cache_[
map] =
false;
2780 map_cache_[
map] =
false;
2790 DCHECK_EQ(descriptor_idx, descriptors->GetDetails(
i).field_index());
2791 property_index = descriptor_idx;
2793 const bool is_inobject = property_index < in_object_properties;
2799 property_index -= in_object_properties;
2800 property = obj->property_array(cage_base)->get(cage_base, property_index);
2803 if (
V8_UNLIKELY(IsUndefined(property) || IsSymbol(property))) {
2807 DCHECK(IsInternalizedString(name));
2812 SerializeObjectKey<true>(key_name, comma, no_gc);
2815 key_result = SerializeObjectKey<false>(key_name, comma, no_gc);
2824 if constexpr (is_one_byte) {
2828 obj, map, descriptor_idx + 1, nof_descriptors,
2829 in_object_properties, in_object_properties_start,
2831 if (IsJSObject(property)) {
2833 }
else if (IsJSArray(property)) {
2836 stack_.emplace_back(
2839 stack_.emplace_back(
2849 map_cache_[
map] =
false;
2861 result = TrySerializeSimpleObject(property);
2872 obj, map, descriptor_idx + 1, nof_descriptors, in_object_properties,
2873 in_object_properties_start, descriptors));
2877 if constexpr (is_one_byte) {
2879 obj, map, descriptor_idx + 1, nof_descriptors,
2880 in_object_properties, in_object_properties_start, descriptors));
2891 AppendCharacter(
'}');
2893 map_cache_.try_emplace(map,
true);
2898template <
typename Char>
2902 array, initial_jsarray_proto_,
isolate_))) {
2905 AppendCharacter(
'[');
2908 switch (array->GetElementsKind()) {
2911 if constexpr (IsHoleyElementsKind(kind)) { \
2912 if (V8_UNLIKELY(!Protectors::IsNoElementsIntact(isolate_))) { \
2916 if (V8_UNLIKELY(length > kArrayInterruptLength)) { \
2917 return SerializeFixedArrayWithInterruptCheck<kind>(elements, 0, length); \
2919 return SerializeFixedArray<kind>(elements, 0, length); \
2934template <
typename Char>
2935template <ElementsKind kind>
2943 uint32_t limit = std::min(length, kArrayInterruptLength);
2944 constexpr uint32_t kMaxAllowedFastPackedLength =
2945 std::numeric_limits<uint32_t>::max() - kArrayInterruptLength;
2951 uint32_t
i = start_index;
2953 for (;
i < limit;
i++) {
2959 AppendCharacter(
']');
2962 DCHECK_LT(limit, kMaxAllowedFastPackedLength);
2963 limit = std::min(length, limit + kArrayInterruptLength);
2980template <
typename Char>
2981template <ElementsKind kind>
2987 for (uint32_t
i = start_index;
i <
length;
i++) {
2992 AppendCharacter(
']');
2996template <
typename Char>
2997template <ElementsKind kind,
bool with_
interrupt_checks,
typename T>
2999 Tagged<T> elements, uint32_t
i, uint32_t length) {
3001 if (elements->is_the_hole(
isolate_,
i)) {
3003 SeparatorUnchecked(
i > 0);
3004 AppendCStringLiteralUnchecked(
"null");
3013 SerializeDouble(elements->get_scalar(
i));
3023 AppendCStringLiteral(
"null");
3026 if constexpr (is_one_byte) {
3027 DCHECK(IsString(obj) || IsStringWrapper(obj));
3030 elements,
i + 1, length));
3040 elements,
i + 1, length));
3053template <
typename Char>
3054template <
typename OldChar>
3055 requires(
sizeof(OldChar) <
sizeof(Char))
3065 stack_ = old_stringifier.
stack_;
3078 cont = stack_.back();
3095 if (stack_.empty())
return result;
3097 cont = stack_.back();
3102 return SerializeObject(cont, no_gc);
3105template <
typename Char>
3109 if (!
object.
IsSmi() && (IsJSObject(
object) || IsJSArray(
object))) {
3118 initial_jsobject_proto_ =
native_context->initial_object_prototype();
3119 initial_jsarray_proto_ =
native_context->initial_array_prototype();
3122 initial_jsarray_proto_->map()->may_have_interesting_properties())) {
3126 ->may_have_interesting_properties())) {
3131 initial_jsarray_proto_->map()->prototype();
3132 if (
V8_UNLIKELY(jsarray_proto_proto != initial_jsobject_proto_)) {
3142 if constexpr (is_one_byte) {
3144 DCHECK(IsString(
object) || IsStringWrapper(
object));
3157template <
typename Char>
3163 uint32_t interrupt_budget = kGlobalInterruptBudget;
3169 result = HandleInterruptAndCheckCycle();
3171 interrupt_budget = kGlobalInterruptBudget;
3173 switch (cont.
type()) {
3179 result = ResumeJSObject<ResumeJSObjectMode::kBuildingMapCache>(
3187 result = ResumeJSObject<ResumeJSObjectMode::kWithMapCache>(
3195 result = ResumeJSObject<ResumeJSObjectMode::kWithoutMapCache>(
3207 result = SerializeFixedArray<PACKED_ELEMENTS>(
3212 result = SerializeFixedArray<HOLEY_ELEMENTS>(
3217 result = SerializeFixedArrayWithInterruptCheck<PACKED_ELEMENTS>(
3222 result = SerializeFixedArrayWithInterruptCheck<HOLEY_ELEMENTS>(
3233 if (stack_.empty())
return SUCCESS;
3234 cont = stack_.back();
3239template <
typename Char>
3265template <
typename Char>
3267 std::unordered_set<Address> set;
3268 for (uint32_t
i = 0;
i < stack_.
size();
i++) {
3277 set.insert(obj.
ptr());
3282template <
typename Char>
3283template <
typename SrcChar>
3284 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
3286 const SrcChar* chars,
size_t length,
3288 constexpr int kUseSimdLengthThreshold = 32;
3289 if (length >= kUseSimdLengthThreshold) {
3290 return AppendStringSIMD(chars, length, no_gc);
3292 return AppendStringSWAR(chars, length, 0, 0, no_gc);
3295template <
typename Char>
3296template <
typename SrcChar>
3298 const SrcChar* chars,
size_t length,
3300 buffer_.Append(chars, length);
3303template <
typename Char>
3304template <
typename SrcChar>
3305 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
3307 const SrcChar* chars,
size_t length,
size_t start,
3309 bool needs_escaping =
false;
3311 SrcChar c = chars[
i];
3312 if (
V8_LIKELY(DoNotEscape(c)))
continue;
3313 needs_escaping =
true;
3314 buffer_.Append(chars + uncopied_src_index,
i - uncopied_src_index);
3315 AppendCStringUnchecked(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
3316 uncopied_src_index =
i + 1;
3318 if (
V8_LIKELY(uncopied_src_index < length)) {
3319 buffer_.Append(chars + uncopied_src_index, length - uncopied_src_index);
3321 return needs_escaping;
3324template <
typename Char>
3325template <
typename SrcChar>
3326 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
3329 const SrcChar* chars,
size_t length,
size_t start,
3331 using PackedT = uint32_t;
3332 static constexpr size_t stride =
sizeof(PackedT);
3334 for (;
i + (stride - 1) <
length;
i += stride) {
3335 PackedT packed = *
reinterpret_cast<const PackedT*
>(chars +
i);
3338 return AppendStringScalar(chars, length,
i, uncopied_src_index, no_gc);
3341template <
typename Char>
3342template <
typename SrcChar>
3343 requires(
sizeof(SrcChar) ==
sizeof(uint8_t))
3345 const SrcChar* chars,
size_t length,
3347 namespace hw = hwy::HWY_NAMESPACE;
3349 bool needs_escaping =
false;
3350 size_t uncopied_src_index = 0;
3351 const SrcChar* block = chars;
3353 hw::FixedTag<SrcChar, 16> tag;
3354 static constexpr size_t stride = hw::Lanes(tag);
3356 const auto mask_0x20 = hw::Set(tag, 0x20);
3357 const auto mask_0x22 = hw::Set(tag, 0x22);
3358 const auto mask_0x5c = hw::Set(tag, 0x5c);
3360 for (; block + (stride - 1) <
end; block += stride) {
3361 const auto input = hw::LoadU(tag, block);
3362 const auto has_lower_than_0x20 = input < mask_0x20;
3363 const auto has_0x22 = input == mask_0x22;
3364 const auto has_0x5c = input == mask_0x5c;
3365 const auto result = hw::Or(hw::Or(has_lower_than_0x20, has_0x22), has_0x5c);
3370 needs_escaping =
true;
3371 size_t index = hw::FindKnownFirstTrue(tag,
result);
3372 Char found_char = block[
index];
3373 const size_t char_index = block - chars +
index;
3374 const size_t copy_length = char_index - uncopied_src_index;
3375 buffer_.Append(chars + uncopied_src_index, copy_length);
3376 AppendCStringUnchecked(
3377 &JsonEscapeTable[found_char * kJsonEscapeTableEntrySize]);
3378 uncopied_src_index = char_index + 1;
3386 const size_t start_index = block - chars;
3387 return AppendStringSWAR(chars, length, start_index, uncopied_src_index,
3392template <
typename Char>
3393template <
typename SrcChar>
3394 requires(
sizeof(SrcChar) ==
sizeof(
base::uc16))
3396 const SrcChar* chars,
size_t length,
3398 bool needs_escaping =
false;
3399 uint32_t uncopied_src_index = 0;
3402 SrcChar c = chars[
i];
3403 if (
V8_LIKELY(DoNotEscape(c)))
continue;
3404 needs_escaping =
true;
3405 if (
sizeof(SrcChar) != 1 &&
base::IsInRange(c,
static_cast<SrcChar
>(0xD800),
3406 static_cast<SrcChar
>(0xDFFF))) {
3408 buffer_.Append(chars + uncopied_src_index,
i - uncopied_src_index);
3414 if (
i + 1 < length) {
3416 SrcChar next = chars[
i + 1];
3418 static_cast<SrcChar
>(0xDFFF))) {
3421 AppendCharacterUnchecked(c);
3422 AppendCharacterUnchecked(next);
3427 AppendCStringLiteralUnchecked(
"\\u");
3428 std::string_view hex =
3430 AppendStringUnchecked(hex);
3435 AppendCStringLiteralUnchecked(
"\\u");
3436 std::string_view hex =
3438 AppendStringUnchecked(hex);
3445 AppendCStringLiteralUnchecked(
"\\u");
3446 std::string_view hex =
3448 AppendStringUnchecked(hex);
3450 uncopied_src_index =
i + 1;
3452 buffer_.Append(chars + uncopied_src_index,
i - uncopied_src_index);
3454 AppendCStringUnchecked(&JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
3455 uncopied_src_index =
i + 1;
3458 if (uncopied_src_index < length) {
3459 buffer_.Append(chars + uncopied_src_index, length - uncopied_src_index);
3461 return needs_escaping;
3466bool CanUseFastStringifier(DirectHandle<JSAny> replacer,
3467 DirectHandle<Object> gap) {
3469 return v8_flags.json_stringify_fast_path && IsUndefined(*replacer) &&
3473MaybeDirectHandle<Object> FastJsonStringify(Isolate* isolate,
3474 Handle<JSAny>
object) {
3477 FastJsonStringifier<uint8_t> one_byte_stringifier(isolate);
3478 std::optional<FastJsonStringifier<base::uc16>> two_byte_stringifier;
3480 one_byte_stringifier.SerializeObject(*
object, no_gc);
3481 bool result_is_one_byte =
true;
3483 if (
result == CHANGE_ENCODING) {
3484 two_byte_stringifier.emplace(isolate);
3485 result = two_byte_stringifier->ResumeFrom(one_byte_stringifier, no_gc);
3487 result_is_one_byte =
false;
3491 if (result_is_one_byte) {
3492 const size_t length = one_byte_stringifier.ResultLength();
3493 DirectHandle<SeqOneByteString> ret;
3496 if (length > String::kMaxLength) {
3501 isolate->factory()->NewRawOneByteString(
static_cast<int>(length)));
3503 one_byte_stringifier.CopyResultTo(ret->GetChars(no_gc));
3506 DCHECK(two_byte_stringifier.has_value());
3507 const size_t one_byte_length = one_byte_stringifier.ResultLength();
3508 const size_t two_byte_length = two_byte_stringifier->ResultLength();
3509 const size_t total_length = one_byte_length + two_byte_length;
3510 DirectHandle<SeqTwoByteString> ret;
3513 if (total_length > String::kMaxLength) {
3517 isolate->factory()->NewRawTwoByteString(
3518 static_cast<int>(total_length)));
3520 base::uc16* chars = ret->GetChars(no_gc);
3521 if (one_byte_length > 0) {
3522 one_byte_stringifier.CopyResultTo(chars);
3525 two_byte_stringifier->CopyResultTo(chars + one_byte_length);
3528 }
else if (
result == UNDEFINED) {
3529 return isolate->factory()->undefined_value();
3530 }
else if (
result == SLOW_PATH) {
3533 JsonStringifier stringifier(isolate);
3534 Handle<JSAny> undefined = isolate->factory()->undefined_value();
3535 return stringifier.Stringify(
object, undefined, undefined);
3538 CHECK(isolate->has_exception());
3539 return MaybeDirectHandle<Object>();
3547 if (CanUseFastStringifier(replacer, gap)) {
3548 return FastJsonStringify(isolate,
object);
3551 return stringifier.
Stringify(
object, replacer, gap);
V8_INLINE T FromJust() const &
V8_INLINE bool IsNothing() const
constexpr size_t size() const
constexpr T * begin() const
constexpr T * end() const
static constexpr const char * kLinePrefix
void AppendNormalLine(DirectHandle< Object > key, DirectHandle< Object > object)
IncrementalStringBuilder builder_
void AppendClosingLine(DirectHandle< Object > closing_key)
void AppendStartLine(DirectHandle< Object > start_object)
static constexpr const char * kEndPrefix
MaybeDirectHandle< String > Finish()
void AppendKey(DirectHandle< Object > key)
void AppendSmi(Tagged< Smi > smi)
CircularStructureMessageBuilder(Isolate *isolate)
void AppendConstructorName(DirectHandle< Object > object)
static constexpr const char * kStartPrefix
uint32_t array_length() const
Tagged< DescriptorArray > object_descriptors() const
static constexpr ContinuationRecord ForJSArrayResume(Tagged< FixedArrayBase > obj, uint32_t index, uint32_t length)
@ kObjectResume_WithMapCache
@ kObjectResume_BuildingMapCache
@ kObjectResume_WithoutMapCache
@ kArrayResume_Holey_WithInterrupts
@ kArrayResume_WithInterrupts
static constexpr bool IsObjectResumeType(Type type)
static constexpr Type ContinuationTypeFromResult(FastJsonStringifierResult result)
constexpr ContinuationRecord(Type type, Tagged< ObjectT > obj, uint32_t index, uint32_t length)
uint8_t in_object_properties
Tagged< JSArray > js_array() const
static constexpr ContinuationRecord ForJSObjectResume(Tagged< JSAny > obj, Tagged< Map > map, uint16_t descriptor_idx, uint16_t nof_descriptors, uint8_t in_object_properties, uint8_t in_object_properties_start, Tagged< DescriptorArray > descriptors)
struct v8::internal::ContinuationRecord::@88::@92 object_key_
static constexpr ContinuationRecord ForObjectKey(Tagged< String > key, bool comma)
Tagged< DescriptorArray > descriptors
static constexpr ContinuationRecord ForJSArray(Tagged< JSAny > obj)
static constexpr ContinuationRecord ForSimpleObject(Tagged< JSAny > obj)
static constexpr ContinuationRecord ForJSObject(Tagged< JSAny > obj)
Tagged< JSAny > simple_object() const
struct v8::internal::ContinuationRecord::@88::@91 js_object_
UnionOf< JSAny, FixedArrayBase > ObjectT
Tagged< ObjectT > object() const
static consteval Type ContinuationTypeForArray(ElementsKind kind, bool with_interrupt_check)
uint8_t object_in_object_properties_start() const
Tagged< FixedArrayBase > array_elements() const
Tagged< JSObject > js_object() const
uint16_t object_nof_descriptors() const
uint8_t in_object_properties_start
struct v8::internal::ContinuationRecord::@88::@90 js_array_
bool object_key_comma() const
static constexpr ContinuationRecord ForJSAny(Tagged< JSAny > obj, FastJsonStringifierResult result)
constexpr ContinuationRecord(Type type, Tagged< ObjectT > obj, Tagged< Map > map, uint16_t descriptor_idx, uint16_t nof_descriptors, uint8_t in_object_properties, uint8_t in_object_properties_start, Tagged< DescriptorArray > descriptors)
uint16_t object_descriptor_idx() const
uint32_t array_index() const
uint8_t object_in_object_properties() const
static constexpr bool IsArrayResumeType(Type type)
Tagged< String > object_key() const
Tagged< Map > object_map() const
Tagged< ObjectT > object_
constexpr ContinuationRecord(Type type, Tagged< ObjectT > obj, bool comma)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
MaybeHandle< String > NewStringFromOneByte(base::Vector< const uint8_t > string, AllocationType allocation=AllocationType::kYoung)
V8_WARN_UNUSED_RESULT Handle< String > NumberToString(DirectHandle< Object > number, NumberCacheMode mode=NumberCacheMode::kBoth)
Handle< JSObject > NewJSObject(DirectHandle< JSFunction > constructor, AllocationType allocation=AllocationType::kYoung, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
DirectHandle< Object > NewInvalidStringLengthError()
Handle< OrderedHashSet > NewOrderedHashSet()
V8_WARN_UNUSED_RESULT MaybeHandle< String > NewStringFromTwoByte(base::Vector< const base::uc16 > str, AllocationType allocation=AllocationType::kYoung)
Handle< String > InternalizeString(base::Vector< const char > str, bool convert_encoding=false)
V8_INLINE void AppendStringUnchecked(std::string_view str)
void CopyResultTo(DstChar *out_buffer)
V8_INLINE void AppendCharacterUnchecked(SrcChar c)
V8_NOINLINE FastJsonStringifierResult ResumeFrom(FastJsonStringifier< OldChar > &old_stringifier, const DisallowGarbageCollection &no_gc)
V8_INLINE bool AppendString(const SrcChar *chars, size_t length, const DisallowGarbageCollection &no_gc)
FastJsonStringifierResult SerializeJSArray(Tagged< JSArray > array)
V8_INLINE void Separator(bool comma)
static constexpr uint32_t kGlobalInterruptBudget
size_t ResultLength() const
FastJsonStringifierResult TrySerializeSimpleObject(Tagged< JSAny > object)
V8_NOINLINE FastJsonStringifierResult SerializeJSPrimitiveWrapper(Tagged< JSPrimitiveWrapper > obj, const DisallowGarbageCollection &no_gc)
V8_INLINE FastJsonStringifierResult SerializeString(Tagged< HeapObject > str, const DisallowGarbageCollection &no_gc)
V8_INLINE FastJsonStringifierResult SerializeObject(Tagged< JSAny > object, const DisallowGarbageCollection &no_gc)
void SerializeDouble(double number)
V8_INLINE bool AppendString(const SrcChar *chars, size_t length, const DisallowGarbageCollection &no_gc)
OutBuffer< Char > buffer_
V8_INLINE void AppendCStringUnchecked(const char *chars)
V8_INLINE FastJsonStringifierResult SerializeFixedArray(Tagged< FixedArrayBase > array, uint32_t start_idx, uint32_t length)
V8_INLINE void AppendCStringUnchecked(const char *chars, size_t len)
V8_INLINE bool AppendStringSWAR(const SrcChar *chars, size_t length, size_t start, size_t uncopied_src_index, const DisallowGarbageCollection &no_gc)
V8_INLINE void SeparatorUnchecked(bool comma)
V8_INLINE void AppendCStringLiteralUnchecked(const char(&literal)[N])
Tagged< HeapObject > initial_jsarray_proto_
FastJsonStringifierObjectKeyResult SerializeObjectKey(Tagged< String > key, bool comma, const DisallowGarbageCollection &no_gc)
V8_INLINE void AppendStringNoEscapes(const SrcChar *chars, size_t length, const DisallowGarbageCollection &no_gc)
V8_INLINE FastJsonStringifierResult SerializeJSObject(Tagged< JSObject > obj, const DisallowGarbageCollection &no_gc)
bool AppendStringScalar(const SrcChar *chars, size_t length, size_t start, size_t uncopied_src_index, const DisallowGarbageCollection &no_gc)
V8_NOINLINE FastJsonStringifierResult HandleInterruptAndCheckCycle()
V8_INLINE void AppendCString(const char *chars, size_t len)
V8_INLINE void AppendCStringLiteral(const char(&literal)[N])
ZoneUnorderedMap< Tagged< Map >, bool, Object::Hasher > map_cache_
FastJsonStringifierResult SerializeFixedArrayWithInterruptCheck(Tagged< FixedArrayBase > elements, uint32_t start_index, uint32_t length)
V8_INLINE bool AppendStringSIMD(const SrcChar *chars, size_t length, const DisallowGarbageCollection &no_gc)
V8_INLINE FastJsonStringifierResult ResumeJSObject(Tagged< JSObject > obj, Tagged< Map > map, uint16_t start_descriptor_idx, uint16_t nof_descriptors, uint8_t in_object_properties, uint8_t in_object_properties_start, Tagged< DescriptorArray > descriptors, bool comma, const DisallowGarbageCollection &no_gc)
base::SmallVector< ContinuationRecord, 16 > stack_
V8_INLINE void SerializeSmi(Tagged< Smi > object)
V8_INLINE FastJsonStringifierResult SerializeFixedArrayElement(Tagged< T > elements, uint32_t i, uint32_t length)
friend class FastJsonStringifier
V8_NOINLINE bool CheckCycle()
V8_INLINE void AppendString(std::string_view str)
V8_INLINE void AppendCharacter(SrcChar c)
V8_INLINE void EnsureCapacity(size_t size)
static constexpr uint32_t kArrayInterruptLength
V8_INLINE void AppendCString(const char *chars)
static constexpr bool is_one_byte
Tagged< HeapObject > initial_jsobject_proto_
static FieldIndex ForDetails(Tagged< Map > map, PropertyDetails details)
static constexpr int kMaxLength
V8_INLINE bool is_null() const
HandleType< T > CloseAndEscape(HandleType< T > handle_value)
V8_INLINE void AppendCString(const SrcChar *s)
MaybeDirectHandle< String > Finish()
V8_INLINE void AppendCharacter(uint8_t c)
V8_INLINE void AppendString(std::string_view str)
V8_INLINE void AppendCStringLiteral(const char(&literal)[N])
Tagged< Object > Throw(Tagged< Object > exception, MessageLocation *location=nullptr)
StackGuard * stack_guard()
v8::internal::Factory * factory()
LocalHeap * main_thread_local_heap()
Tagged< Object > StackOverflow()
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static Handle< JSAny > FastPropertyAt(Isolate *isolate, DirectHandle< JSObject > object, Representation representation, FieldIndex index)
static const int kRawJsonInitialIndex
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetElement(Isolate *isolate, DirectHandle< JSReceiver > receiver, uint32_t index)
static DirectHandle< String > GetConstructorName(Isolate *isolate, DirectHandle< JSReceiver > receiver)
V8_INLINE void AppendSubstring(const SrcChar *src, size_t from, size_t to)
V8_INLINE void Append(DestChar c)
V8_INLINE void AppendCString(const char *s)
NoExtendBuilder(DestChar *start, size_t *current_index)
V8_INLINE void AppendChars(base::Vector< const uint8_t > chars, size_t length)
V8_INLINE void AppendString(std::string_view str)
static constexpr size_t kIndexMask
SimplePropertyKeyCache(Isolate *isolate)
void TryInsert(Tagged< String > string)
static constexpr size_t kSizeBits
Tagged_t MaybeCompress(Tagged< String > string)
static void UpdatePointersCallback(void *cache)
~SimplePropertyKeyCache()
bool Contains(Tagged< String > string)
size_t GetIndex(Tagged< String > string)
static constexpr size_t kSize
V8_INLINE void Separator(bool first)
V8_INLINE void AppendCharacter(uint8_t c)
uint8_t one_byte_array_[kInitialPartLength]
bool InitializeGap(Handle< Object > gap)
V8_INLINE Result SerializeJSArray(Handle< JSArray > object, Handle< Object > key)
V8_INLINE Result SerializeFixedArrayWithInterruptCheck(DirectHandle< JSArray > array, uint32_t length, uint32_t *slow_path_index)
V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > Stringify(Handle< JSAny > object, Handle< JSAny > replacer, Handle< Object > gap)
Result SerializeJSPrimitiveWrapper(Handle< JSPrimitiveWrapper > object, Handle< Object > key)
static constexpr int kCircularErrorMessagePostfixCount
bool SerializeString(Handle< String > object)
Result Serialize_(Handle< JSAny > object, bool comma, Handle< Object > key)
DirectHandle< JSReceiver > CurrentHolder(DirectHandle< Object > value, DirectHandle< Object > inital_holder)
V8_NOINLINE void Extend()
base::uc16 * two_byte_ptr_
static constexpr int kCircularErrorMessagePrefixCount
static V8_INLINE bool SerializeStringUnchecked_(base::Vector< const SrcChar > src, NoExtendBuilder< DestChar > *dest)
String::Encoding encoding_
V8_INLINE Result SerializeProperty(Handle< JSAny > object, bool deferred_comma, Handle< String > deferred_key)
static constexpr size_t kMaxPartLength
V8_INLINE Result SerializeHeapNumber(DirectHandle< HeapNumber > object)
static constexpr size_t kPartLengthGrowthFactor
V8_INLINE void AppendCString(const SrcChar *s)
V8_INLINE Result SerializeJSObject(Handle< JSObject > object, Handle< Object > key)
V8_INLINE Result SerializeObject(Handle< JSAny > obj)
void AppendStringByCopy(Tagged< String > string, size_t length, const DisallowGarbageCollection &no_gc)
bool InitializeReplacer(Handle< JSAny > replacer)
JsonStringifier(Isolate *isolate)
Handle< String > ConstructCircularStructureErrorMessage(DirectHandle< Object > last_key, size_t start_index)
V8_INLINE bool SerializeString_(Tagged< String > string, const DisallowGarbageCollection &no_gc)
V8_NOINLINE void ChangeEncoding()
Result SerializeSmi(Tagged< Smi > object)
Result SerializeArrayLikeSlow(DirectHandle< JSReceiver > object, uint32_t start, uint32_t length)
Handle< FixedArray > property_list_
V8_INLINE bool CurrentPartCanFit(size_t length)
V8_INLINE void AppendCStringLiteral(const char(&literal)[N])
V8_WARN_UNUSED_RESULT MaybeHandle< JSAny > ApplyToJsonFunction(Handle< JSAny > object, DirectHandle< Object > key)
SimplePropertyKeyCache key_cache_
V8_INLINE void Append(SrcChar c)
static constexpr size_t kInitialPartLength
Result SerializeDouble(double number)
void AppendSubstringByCopy(const SrcChar *src, size_t count)
Result SerializeJSProxy(Handle< JSProxy > object, Handle< Object > key)
V8_NOINLINE void NewLineOutline()
V8_INLINE Result SerializeElement(Isolate *isolate, Handle< JSAny > object, int i)
V8_INLINE void AppendString(std::basic_string_view< SrcChar > s)
bool HasValidCurrentIndex() const
V8_INLINE Result SerializeFixedArrayElement(Tagged< T > elements, uint32_t i, Tagged< JSArray > array, bool can_treat_hole_as_undefined)
V8_WARN_UNUSED_RESULT MaybeHandle< JSAny > ApplyReplacerFunction(Handle< JSAny > value, DirectHandle< Object > key, DirectHandle< Object > initial_holder)
V8_INLINE bool EscapedLengthIfCurrentPartFits(size_t length)
V8_NOINLINE void AppendSubstring(const SrcChar *src, size_t from, size_t to)
V8_INLINE Result SerializeFixedArrayWithPossibleTransitions(DirectHandle< JSArray > array, uint32_t length, uint32_t *slow_path_index)
Result SerializeJSReceiverSlow(DirectHandle< JSReceiver > object)
Handle< JSReceiver > replacer_function_
V8_INLINE void SerializeDeferredKey(bool deferred_comma, Handle< Object > deferred_key)
std::pair< Handle< Object >, Handle< Object > > KeyObject
std::vector< KeyObject > stack_
Result StackPush(Handle< Object > object, Handle< Object > key)
V8_INLINE void Unindent()
V8_NOINLINE void AppendString(Handle< String > string_handle)
bool TrySerializeSimplePropertyKey(Tagged< String > string, const DisallowGarbageCollection &no_gc)
static MaybeHandle< FixedArray > GetKeys(Isolate *isolate, DirectHandle< JSReceiver > object, KeyCollectionMode mode, PropertyFilter filter, GetKeysConversion keys_conversion=GetKeysConversion::kKeepNumbers, bool is_for_in=false, bool skip_indices=false)
void RemoveGCEpilogueCallback(GCEpilogueCallback *callback, void *data)
@ PROTOTYPE_CHAIN_SKIP_INTERCEPTOR
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(Handle< S > *out) const
static bool ToArrayLength(Tagged< Object > obj, uint32_t *index)
static V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType ToString(Isolate *isolate, HandleType< T > input)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetPropertyOrElement(Isolate *isolate, DirectHandle< JSAny > object, DirectHandle< Name > name)
static V8_WARN_UNUSED_RESULT HandleType< Number >::MaybeType ToNumber(Isolate *isolate, HandleType< T > input)
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetLengthFromArrayLike(Isolate *isolate, DirectHandle< JSReceiver > object)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
static bool ToUint32(Tagged< Object > obj, uint32_t *value)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetElement(Isolate *isolate, DirectHandle< JSAny > object, uint32_t index)
static constexpr uint8_t kNull
static constexpr uint8_t kFalse
static constexpr uint8_t kTrue
static Handle< FixedArray > ConvertToKeysArray(Isolate *isolate, Handle< OrderedHashSet > table, GetKeysConversion convert)
static HandleType< OrderedHashSet >::MaybeType Add(Isolate *isolate, HandleType< OrderedHashSet > table, DirectHandle< Object > value)
V8_INLINE size_t SegmentFreeChars() const
V8_NOINLINE V8_PRESERVE_MOST void Extend(size_t min_size)
static constexpr size_t kStackBufferSize
static constexpr uint8_t kNumVariableSegments
V8_INLINE void AppendCharacter(SrcChar c)
V8_INLINE size_t StackBufferLength() const
std::optional< Zone > zone_
void Append(const SrcChar *chars, size_t length)
static constexpr uint32_t kInitialSegmentSize
V8_INLINE size_t SegmentCapacity(size_t segment)
static constexpr uint32_t kMaxSegmentSize
V8_INLINE size_t CurSegmentCapacity()
static constexpr uint8_t kInitialSegmentSizeHighestBit
AccountingAllocator * allocator_
V8_INLINE size_t CurSegmentLength() const
size_t stack_buffer_size_
static constexpr uint8_t kMaxSegmentSizeHighestBit
OutBuffer(AccountingAllocator *allocator)
std::optional< ZoneList< base::Vector< Char > > > segments_
V8_INLINE bool ZoneUsed() const
Char stack_buffer_[kStackBufferSize]
void EnsureCapacity(size_t size)
V8_INLINE void ReduceCurrentCapacity(size_t size)
PropertyLocation location() const
Representation representation() const
PropertyKind kind() const
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
static constexpr Tagged< Smi > FromInt(int value)
static constexpr int kMinValue
static constexpr Tagged< Smi > zero()
static constexpr int kMaxValue
Tagged< Object > HandleInterrupts(InterruptLevel level=InterruptLevel::kAnyEffect)
V8_INLINE bool InterruptRequested()
static void WriteToFlat(Tagged< String > source, SinkCharT *sink, uint32_t start, uint32_t length)
static const uint32_t kMaxLength
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static const int32_t kMaxOneByteCharCode
static bool IsOneByteRepresentationUnderneath(Tagged< String > string)
static PtrType Relaxed_Load(Tagged< HeapObject > host, int offset=0)
V8_INLINE constexpr StorageType ptr() const
static V8_INLINE Tagged_t CompressObject(Address tagged)
base::OwnedVector< uint8_t > buffer_
#define COMPRESS_POINTERS_BOOL
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
base::Vector< const DirectHandle< Object > > args
#define CASE_WITH_INTERRUPT(kind)
#define CASE_WITH_TRANSITION(kind)
ZoneVector< RpoNumber > & result
FunctionLiteral * literal
constexpr bool IsPowerOfTwo(T value)
constexpr unsigned CountLeadingZeros32(uint32_t value)
constexpr Vector< T > ArrayVector(T(&arr)[N])
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
constexpr Vector< T > VectorOf(T *start, size_t size)
Vector< const uint8_t > OneByteVector(const char *data, size_t length)
V8_INLINE constexpr bool IsTwoByteString(InstanceType instance_type)
void DeleteArray(T *array)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
uint32_t DoubleToUint32(double x)
constexpr int kTaggedSize
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
constexpr bool IsHoleyElementsKind(ElementsKind kind)
constexpr intptr_t kObjectAlignment
bool Is(IndirectHandle< U > value)
bool IsNumber(Tagged< Object > obj)
FastJsonStringifierResult
bool IsCustomElementsReceiverMap(Tagged< Map > map)
Tagged(T object) -> Tagged< T >
bool MayHaveInterestingProperties(Isolate *isolate, Tagged< JSReceiver > object)
constexpr bool IsSmiElementsKind(ElementsKind kind)
static constexpr char kJsonStringifierZoneName[]
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
std::string_view IntToStringView(int n, base::Vector< char > buffer)
kInterpreterTrampolineOffset Tagged< HeapObject >
constexpr bool IsObjectElementsKind(ElementsKind kind)
void MemsetTagged(Tagged_t *start, Tagged< MaybeObject > value, size_t counter)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
PerThreadAssertScopeDebugOnly< true, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > AllowGarbageCollection
V8_INLINE PtrComprCageBase GetPtrComprCageBase()
FastJsonStringifierObjectKeyResult
constexpr int kDoubleToRadixMaxChars
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
constexpr int kBitsPerInt
typename detail::FlattenUnionHelper< Union<>, Ts... >::type UnionOf
@ UNCACHED_EXTERNAL_INTERNALIZED_ONE_BYTE_STRING_TYPE
@ SEQ_ONE_BYTE_STRING_TYPE
@ UNCACHED_EXTERNAL_TWO_BYTE_STRING_TYPE
@ UNCACHED_EXTERNAL_INTERNALIZED_TWO_BYTE_STRING_TYPE
@ UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE
@ EXTERNAL_TWO_BYTE_STRING_TYPE
@ SEQ_TWO_BYTE_STRING_TYPE
@ THIN_ONE_BYTE_STRING_TYPE
@ EXTERNAL_INTERNALIZED_TWO_BYTE_STRING_TYPE
@ EXTERNAL_INTERNALIZED_ONE_BYTE_STRING_TYPE
@ EXTERNAL_ONE_BYTE_STRING_TYPE
@ INTERNALIZED_ONE_BYTE_STRING_TYPE
@ INTERNALIZED_TWO_BYTE_STRING_TYPE
@ THIN_TWO_BYTE_STRING_TYPE
refactor address components for immediate indexing make OptimizeMaglevOnNextCall optimize to turbofan instead of maglev filter for tracing turbofan compilation trace turbo cfg trace TurboFan s graph trimmer trace TurboFan s control equivalence trace TurboFan s register allocator trace stack load store counters for optimized code in run fuzzing &&concurrent_recompilation trace_turbo trace_turbo_scheduled trace_turbo_stack_accesses verify TurboFan machine graph of code stubs enable FixedArray bounds checks print TurboFan statistics of wasm compilations maximum cumulative size of bytecode considered for inlining scale factor of bytecode size used to calculate the inlining budget * KB
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
static const int kMaxNumberOfDescriptors
void CopyChars(DstType *dst, const SrcType *src, size_t count) V8_NONNULL(1
V8_EXPORT_PRIVATE FlagValues v8_flags
MaybeDirectHandle< Object > JsonStringify(Isolate *isolate, Handle< JSAny > object, Handle< JSAny > replacer, Handle< Object > gap)
std::string_view DoubleToStringView(double v, base::Vector< char > buffer)
constexpr bool IsDoubleElementsKind(ElementsKind kind)
std::string_view DoubleToRadixStringView(double value, int radix, base::Vector< char > buffer)
!IsContextMap !IsContextMap Tagged< NativeContext >
constexpr uint32_t kMaxUInt32
T * NewArray(size_t size)
!IsContextMap !IsContextMap native_context
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
base::Vector< const char > contents
#define DCHECK_LE(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
constexpr T RoundUp(T x, intptr_t m)
#define V8_CLANG_NO_SANITIZE(what)
defined(V8_TRIVIAL_ABI)
#define V8_LIKELY(condition)
#define V8_WARN_UNUSED_RESULT
#define V8_UNLIKELY(condition)
#define V8_INLINE_STATEMENT