11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/strings/string-stream.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <memory> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/base/vector.h" 101cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h" 111cb0ef41Sopenharmony_ci#include "src/logging/log.h" 121cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 131cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 141cb0ef41Sopenharmony_ci#include "src/objects/prototype.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cistatic const int kMentionedObjectCacheMaxSize = 256; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cichar* HeapStringAllocator::allocate(unsigned bytes) { 221cb0ef41Sopenharmony_ci space_ = NewArray<char>(bytes); 231cb0ef41Sopenharmony_ci return space_; 241cb0ef41Sopenharmony_ci} 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cichar* FixedStringAllocator::allocate(unsigned bytes) { 271cb0ef41Sopenharmony_ci CHECK_LE(bytes, length_); 281cb0ef41Sopenharmony_ci return buffer_; 291cb0ef41Sopenharmony_ci} 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_cichar* FixedStringAllocator::grow(unsigned* old) { 321cb0ef41Sopenharmony_ci *old = length_; 331cb0ef41Sopenharmony_ci return buffer_; 341cb0ef41Sopenharmony_ci} 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_cibool StringStream::Put(char c) { 371cb0ef41Sopenharmony_ci if (full()) return false; 381cb0ef41Sopenharmony_ci DCHECK(length_ < capacity_); 391cb0ef41Sopenharmony_ci // Since the trailing '\0' is not accounted for in length_ fullness is 401cb0ef41Sopenharmony_ci // indicated by a difference of 1 between length_ and capacity_. Thus when 411cb0ef41Sopenharmony_ci // reaching a difference of 2 we need to grow the buffer. 421cb0ef41Sopenharmony_ci if (length_ == capacity_ - 2) { 431cb0ef41Sopenharmony_ci unsigned new_capacity = capacity_; 441cb0ef41Sopenharmony_ci char* new_buffer = allocator_->grow(&new_capacity); 451cb0ef41Sopenharmony_ci if (new_capacity > capacity_) { 461cb0ef41Sopenharmony_ci capacity_ = new_capacity; 471cb0ef41Sopenharmony_ci buffer_ = new_buffer; 481cb0ef41Sopenharmony_ci } else { 491cb0ef41Sopenharmony_ci // Reached the end of the available buffer. 501cb0ef41Sopenharmony_ci DCHECK_GE(capacity_, 5); 511cb0ef41Sopenharmony_ci length_ = capacity_ - 1; // Indicate fullness of the stream. 521cb0ef41Sopenharmony_ci buffer_[length_ - 4] = '.'; 531cb0ef41Sopenharmony_ci buffer_[length_ - 3] = '.'; 541cb0ef41Sopenharmony_ci buffer_[length_ - 2] = '.'; 551cb0ef41Sopenharmony_ci buffer_[length_ - 1] = '\n'; 561cb0ef41Sopenharmony_ci buffer_[length_] = '\0'; 571cb0ef41Sopenharmony_ci return false; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci buffer_[length_] = c; 611cb0ef41Sopenharmony_ci buffer_[length_ + 1] = '\0'; 621cb0ef41Sopenharmony_ci length_++; 631cb0ef41Sopenharmony_ci return true; 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci// A control character is one that configures a format element. For 671cb0ef41Sopenharmony_ci// instance, in %.5s, .5 are control characters. 681cb0ef41Sopenharmony_cistatic bool IsControlChar(char c) { 691cb0ef41Sopenharmony_ci switch (c) { 701cb0ef41Sopenharmony_ci case '0': 711cb0ef41Sopenharmony_ci case '1': 721cb0ef41Sopenharmony_ci case '2': 731cb0ef41Sopenharmony_ci case '3': 741cb0ef41Sopenharmony_ci case '4': 751cb0ef41Sopenharmony_ci case '5': 761cb0ef41Sopenharmony_ci case '6': 771cb0ef41Sopenharmony_ci case '7': 781cb0ef41Sopenharmony_ci case '8': 791cb0ef41Sopenharmony_ci case '9': 801cb0ef41Sopenharmony_ci case '.': 811cb0ef41Sopenharmony_ci case '-': 821cb0ef41Sopenharmony_ci return true; 831cb0ef41Sopenharmony_ci default: 841cb0ef41Sopenharmony_ci return false; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_civoid StringStream::Add(base::Vector<const char> format, 891cb0ef41Sopenharmony_ci base::Vector<FmtElm> elms) { 901cb0ef41Sopenharmony_ci // If we already ran out of space then return immediately. 911cb0ef41Sopenharmony_ci if (full()) return; 921cb0ef41Sopenharmony_ci int offset = 0; 931cb0ef41Sopenharmony_ci int elm = 0; 941cb0ef41Sopenharmony_ci while (offset < format.length()) { 951cb0ef41Sopenharmony_ci if (format[offset] != '%' || elm == elms.length()) { 961cb0ef41Sopenharmony_ci Put(format[offset]); 971cb0ef41Sopenharmony_ci offset++; 981cb0ef41Sopenharmony_ci continue; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci // Read this formatting directive into a temporary buffer 1011cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 24> temp; 1021cb0ef41Sopenharmony_ci int format_length = 0; 1031cb0ef41Sopenharmony_ci // Skip over the whole control character sequence until the 1041cb0ef41Sopenharmony_ci // format element type 1051cb0ef41Sopenharmony_ci temp[format_length++] = format[offset++]; 1061cb0ef41Sopenharmony_ci while (offset < format.length() && IsControlChar(format[offset])) 1071cb0ef41Sopenharmony_ci temp[format_length++] = format[offset++]; 1081cb0ef41Sopenharmony_ci if (offset >= format.length()) return; 1091cb0ef41Sopenharmony_ci char type = format[offset]; 1101cb0ef41Sopenharmony_ci temp[format_length++] = type; 1111cb0ef41Sopenharmony_ci temp[format_length] = '\0'; 1121cb0ef41Sopenharmony_ci offset++; 1131cb0ef41Sopenharmony_ci FmtElm current = elms[elm++]; 1141cb0ef41Sopenharmony_ci switch (type) { 1151cb0ef41Sopenharmony_ci case 's': { 1161cb0ef41Sopenharmony_ci DCHECK_EQ(FmtElm::C_STR, current.type_); 1171cb0ef41Sopenharmony_ci const char* value = current.data_.u_c_str_; 1181cb0ef41Sopenharmony_ci Add(value); 1191cb0ef41Sopenharmony_ci break; 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci case 'w': { 1221cb0ef41Sopenharmony_ci DCHECK_EQ(FmtElm::LC_STR, current.type_); 1231cb0ef41Sopenharmony_ci base::Vector<const base::uc16> value = *current.data_.u_lc_str_; 1241cb0ef41Sopenharmony_ci for (int i = 0; i < value.length(); i++) 1251cb0ef41Sopenharmony_ci Put(static_cast<char>(value[i])); 1261cb0ef41Sopenharmony_ci break; 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci case 'o': { 1291cb0ef41Sopenharmony_ci DCHECK_EQ(FmtElm::OBJ, current.type_); 1301cb0ef41Sopenharmony_ci Object obj(current.data_.u_obj_); 1311cb0ef41Sopenharmony_ci PrintObject(obj); 1321cb0ef41Sopenharmony_ci break; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci case 'k': { 1351cb0ef41Sopenharmony_ci DCHECK_EQ(FmtElm::INT, current.type_); 1361cb0ef41Sopenharmony_ci int value = current.data_.u_int_; 1371cb0ef41Sopenharmony_ci if (0x20 <= value && value <= 0x7F) { 1381cb0ef41Sopenharmony_ci Put(value); 1391cb0ef41Sopenharmony_ci } else if (value <= 0xFF) { 1401cb0ef41Sopenharmony_ci Add("\\x%02x", value); 1411cb0ef41Sopenharmony_ci } else { 1421cb0ef41Sopenharmony_ci Add("\\u%04x", value); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci break; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci case 'i': 1471cb0ef41Sopenharmony_ci case 'd': 1481cb0ef41Sopenharmony_ci case 'u': 1491cb0ef41Sopenharmony_ci case 'x': 1501cb0ef41Sopenharmony_ci case 'c': 1511cb0ef41Sopenharmony_ci case 'X': { 1521cb0ef41Sopenharmony_ci int value = current.data_.u_int_; 1531cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 24> formatted; 1541cb0ef41Sopenharmony_ci int length = SNPrintF(formatted, temp.begin(), value); 1551cb0ef41Sopenharmony_ci Add(base::Vector<const char>(formatted.begin(), length)); 1561cb0ef41Sopenharmony_ci break; 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci case 'f': 1591cb0ef41Sopenharmony_ci case 'g': 1601cb0ef41Sopenharmony_ci case 'G': 1611cb0ef41Sopenharmony_ci case 'e': 1621cb0ef41Sopenharmony_ci case 'E': { 1631cb0ef41Sopenharmony_ci double value = current.data_.u_double_; 1641cb0ef41Sopenharmony_ci int inf = std::isinf(value); 1651cb0ef41Sopenharmony_ci if (inf == -1) { 1661cb0ef41Sopenharmony_ci Add("-inf"); 1671cb0ef41Sopenharmony_ci } else if (inf == 1) { 1681cb0ef41Sopenharmony_ci Add("inf"); 1691cb0ef41Sopenharmony_ci } else if (std::isnan(value)) { 1701cb0ef41Sopenharmony_ci Add("nan"); 1711cb0ef41Sopenharmony_ci } else { 1721cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 28> formatted; 1731cb0ef41Sopenharmony_ci SNPrintF(formatted, temp.begin(), value); 1741cb0ef41Sopenharmony_ci Add(formatted.begin()); 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci break; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci case 'p': { 1791cb0ef41Sopenharmony_ci void* value = current.data_.u_pointer_; 1801cb0ef41Sopenharmony_ci base::EmbeddedVector<char, 20> formatted; 1811cb0ef41Sopenharmony_ci SNPrintF(formatted, temp.begin(), value); 1821cb0ef41Sopenharmony_ci Add(formatted.begin()); 1831cb0ef41Sopenharmony_ci break; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci default: 1861cb0ef41Sopenharmony_ci UNREACHABLE(); 1871cb0ef41Sopenharmony_ci } 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // Verify that the buffer is 0-terminated 1911cb0ef41Sopenharmony_ci DCHECK_EQ(buffer_[length_], '\0'); 1921cb0ef41Sopenharmony_ci} 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_civoid StringStream::PrintObject(Object o) { 1951cb0ef41Sopenharmony_ci o.ShortPrint(this); 1961cb0ef41Sopenharmony_ci if (o.IsString()) { 1971cb0ef41Sopenharmony_ci if (String::cast(o).length() <= String::kMaxShortPrintLength) { 1981cb0ef41Sopenharmony_ci return; 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci } else if (o.IsNumber() || o.IsOddball()) { 2011cb0ef41Sopenharmony_ci return; 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci if (o.IsHeapObject() && object_print_mode_ == kPrintObjectVerbose) { 2041cb0ef41Sopenharmony_ci // TODO(delphick): Consider whether we can get the isolate without using 2051cb0ef41Sopenharmony_ci // TLS. 2061cb0ef41Sopenharmony_ci Isolate* isolate = Isolate::Current(); 2071cb0ef41Sopenharmony_ci DebugObjectCache* debug_object_cache = 2081cb0ef41Sopenharmony_ci isolate->string_stream_debug_object_cache(); 2091cb0ef41Sopenharmony_ci for (size_t i = 0; i < debug_object_cache->size(); i++) { 2101cb0ef41Sopenharmony_ci if (*(*debug_object_cache)[i] == o) { 2111cb0ef41Sopenharmony_ci Add("#%d#", static_cast<int>(i)); 2121cb0ef41Sopenharmony_ci return; 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci if (debug_object_cache->size() < kMentionedObjectCacheMaxSize) { 2161cb0ef41Sopenharmony_ci Add("#%d#", static_cast<int>(debug_object_cache->size())); 2171cb0ef41Sopenharmony_ci debug_object_cache->push_back(handle(HeapObject::cast(o), isolate)); 2181cb0ef41Sopenharmony_ci } else { 2191cb0ef41Sopenharmony_ci Add("@%p", o); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci } 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_cistd::unique_ptr<char[]> StringStream::ToCString() const { 2251cb0ef41Sopenharmony_ci char* str = NewArray<char>(length_ + 1); 2261cb0ef41Sopenharmony_ci MemCopy(str, buffer_, length_); 2271cb0ef41Sopenharmony_ci str[length_] = '\0'; 2281cb0ef41Sopenharmony_ci return std::unique_ptr<char[]>(str); 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_civoid StringStream::Log(Isolate* isolate) { 2321cb0ef41Sopenharmony_ci LOG(isolate, StringEvent("StackDump", buffer_)); 2331cb0ef41Sopenharmony_ci} 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_civoid StringStream::OutputToFile(FILE* out) { 2361cb0ef41Sopenharmony_ci // Dump the output to stdout, but make sure to break it up into 2371cb0ef41Sopenharmony_ci // manageable chunks to avoid losing parts of the output in the OS 2381cb0ef41Sopenharmony_ci // printing code. This is a problem on Windows in particular; see 2391cb0ef41Sopenharmony_ci // the VPrint() function implementations in platform-win32.cc. 2401cb0ef41Sopenharmony_ci unsigned position = 0; 2411cb0ef41Sopenharmony_ci for (unsigned next; (next = position + 2048) < length_; position = next) { 2421cb0ef41Sopenharmony_ci char save = buffer_[next]; 2431cb0ef41Sopenharmony_ci buffer_[next] = '\0'; 2441cb0ef41Sopenharmony_ci internal::PrintF(out, "%s", &buffer_[position]); 2451cb0ef41Sopenharmony_ci buffer_[next] = save; 2461cb0ef41Sopenharmony_ci } 2471cb0ef41Sopenharmony_ci internal::PrintF(out, "%s", &buffer_[position]); 2481cb0ef41Sopenharmony_ci} 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ciHandle<String> StringStream::ToString(Isolate* isolate) { 2511cb0ef41Sopenharmony_ci return isolate->factory() 2521cb0ef41Sopenharmony_ci ->NewStringFromUtf8(base::Vector<const char>(buffer_, length_)) 2531cb0ef41Sopenharmony_ci .ToHandleChecked(); 2541cb0ef41Sopenharmony_ci} 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_civoid StringStream::ClearMentionedObjectCache(Isolate* isolate) { 2571cb0ef41Sopenharmony_ci isolate->set_string_stream_current_security_token(Object()); 2581cb0ef41Sopenharmony_ci if (isolate->string_stream_debug_object_cache() == nullptr) { 2591cb0ef41Sopenharmony_ci isolate->set_string_stream_debug_object_cache(new DebugObjectCache()); 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci isolate->string_stream_debug_object_cache()->clear(); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci#ifdef DEBUG 2651cb0ef41Sopenharmony_cibool StringStream::IsMentionedObjectCacheClear(Isolate* isolate) { 2661cb0ef41Sopenharmony_ci return object_print_mode_ == kPrintObjectConcise || 2671cb0ef41Sopenharmony_ci isolate->string_stream_debug_object_cache()->size() == 0; 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci#endif 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_cibool StringStream::Put(String str) { return Put(str, 0, str.length()); } 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_cibool StringStream::Put(String str, int start, int end) { 2741cb0ef41Sopenharmony_ci StringCharacterStream stream(str, start); 2751cb0ef41Sopenharmony_ci for (int i = start; i < end && stream.HasMore(); i++) { 2761cb0ef41Sopenharmony_ci uint16_t c = stream.GetNext(); 2771cb0ef41Sopenharmony_ci if (c >= 127 || c < 32) { 2781cb0ef41Sopenharmony_ci c = '?'; 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci if (!Put(static_cast<char>(c))) { 2811cb0ef41Sopenharmony_ci return false; // Output was truncated. 2821cb0ef41Sopenharmony_ci } 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci return true; 2851cb0ef41Sopenharmony_ci} 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_civoid StringStream::PrintName(Object name) { 2881cb0ef41Sopenharmony_ci if (name.IsString()) { 2891cb0ef41Sopenharmony_ci String str = String::cast(name); 2901cb0ef41Sopenharmony_ci if (str.length() > 0) { 2911cb0ef41Sopenharmony_ci Put(str); 2921cb0ef41Sopenharmony_ci } else { 2931cb0ef41Sopenharmony_ci Add("/* anonymous */"); 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci } else { 2961cb0ef41Sopenharmony_ci Add("%o", name); 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci} 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_civoid StringStream::PrintUsingMap(JSObject js_object) { 3011cb0ef41Sopenharmony_ci Map map = js_object.map(); 3021cb0ef41Sopenharmony_ci DescriptorArray descs = map.instance_descriptors(js_object.GetIsolate()); 3031cb0ef41Sopenharmony_ci for (InternalIndex i : map.IterateOwnDescriptors()) { 3041cb0ef41Sopenharmony_ci PropertyDetails details = descs.GetDetails(i); 3051cb0ef41Sopenharmony_ci if (details.location() == PropertyLocation::kField) { 3061cb0ef41Sopenharmony_ci DCHECK_EQ(PropertyKind::kData, details.kind()); 3071cb0ef41Sopenharmony_ci Object key = descs.GetKey(i); 3081cb0ef41Sopenharmony_ci if (key.IsString() || key.IsNumber()) { 3091cb0ef41Sopenharmony_ci int len = 3; 3101cb0ef41Sopenharmony_ci if (key.IsString()) { 3111cb0ef41Sopenharmony_ci len = String::cast(key).length(); 3121cb0ef41Sopenharmony_ci } 3131cb0ef41Sopenharmony_ci for (; len < 18; len++) Put(' '); 3141cb0ef41Sopenharmony_ci if (key.IsString()) { 3151cb0ef41Sopenharmony_ci Put(String::cast(key)); 3161cb0ef41Sopenharmony_ci } else { 3171cb0ef41Sopenharmony_ci key.ShortPrint(); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci Add(": "); 3201cb0ef41Sopenharmony_ci FieldIndex index = FieldIndex::ForDescriptor(map, i); 3211cb0ef41Sopenharmony_ci Object value = js_object.RawFastPropertyAt(index); 3221cb0ef41Sopenharmony_ci Add("%o\n", value); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci} 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_civoid StringStream::PrintFixedArray(FixedArray array, unsigned int limit) { 3291cb0ef41Sopenharmony_ci ReadOnlyRoots roots = array.GetReadOnlyRoots(); 3301cb0ef41Sopenharmony_ci for (unsigned int i = 0; i < 10 && i < limit; i++) { 3311cb0ef41Sopenharmony_ci Object element = array.get(i); 3321cb0ef41Sopenharmony_ci if (element.IsTheHole(roots)) continue; 3331cb0ef41Sopenharmony_ci for (int len = 1; len < 18; len++) { 3341cb0ef41Sopenharmony_ci Put(' '); 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci Add("%d: %o\n", i, array.get(i)); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci if (limit >= 10) { 3391cb0ef41Sopenharmony_ci Add(" ...\n"); 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci} 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_civoid StringStream::PrintByteArray(ByteArray byte_array) { 3441cb0ef41Sopenharmony_ci unsigned int limit = byte_array.length(); 3451cb0ef41Sopenharmony_ci for (unsigned int i = 0; i < 10 && i < limit; i++) { 3461cb0ef41Sopenharmony_ci byte b = byte_array.get(i); 3471cb0ef41Sopenharmony_ci Add(" %d: %3d 0x%02x", i, b, b); 3481cb0ef41Sopenharmony_ci if (b >= ' ' && b <= '~') { 3491cb0ef41Sopenharmony_ci Add(" '%c'", b); 3501cb0ef41Sopenharmony_ci } else if (b == '\n') { 3511cb0ef41Sopenharmony_ci Add(" '\n'"); 3521cb0ef41Sopenharmony_ci } else if (b == '\r') { 3531cb0ef41Sopenharmony_ci Add(" '\r'"); 3541cb0ef41Sopenharmony_ci } else if (b >= 1 && b <= 26) { 3551cb0ef41Sopenharmony_ci Add(" ^%c", b + 'A' - 1); 3561cb0ef41Sopenharmony_ci } 3571cb0ef41Sopenharmony_ci Add("\n"); 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci if (limit >= 10) { 3601cb0ef41Sopenharmony_ci Add(" ...\n"); 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci} 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_civoid StringStream::PrintMentionedObjectCache(Isolate* isolate) { 3651cb0ef41Sopenharmony_ci if (object_print_mode_ == kPrintObjectConcise) return; 3661cb0ef41Sopenharmony_ci DebugObjectCache* debug_object_cache = 3671cb0ef41Sopenharmony_ci isolate->string_stream_debug_object_cache(); 3681cb0ef41Sopenharmony_ci Add("-- ObjectCacheKey --\n\n"); 3691cb0ef41Sopenharmony_ci for (size_t i = 0; i < debug_object_cache->size(); i++) { 3701cb0ef41Sopenharmony_ci HeapObject printee = *(*debug_object_cache)[i]; 3711cb0ef41Sopenharmony_ci Add(" #%d# %p: ", static_cast<int>(i), 3721cb0ef41Sopenharmony_ci reinterpret_cast<void*>(printee.ptr())); 3731cb0ef41Sopenharmony_ci printee.ShortPrint(this); 3741cb0ef41Sopenharmony_ci Add("\n"); 3751cb0ef41Sopenharmony_ci if (printee.IsJSObject()) { 3761cb0ef41Sopenharmony_ci if (printee.IsJSPrimitiveWrapper()) { 3771cb0ef41Sopenharmony_ci Add(" value(): %o\n", 3781cb0ef41Sopenharmony_ci JSPrimitiveWrapper::cast(printee).value()); 3791cb0ef41Sopenharmony_ci } 3801cb0ef41Sopenharmony_ci PrintUsingMap(JSObject::cast(printee)); 3811cb0ef41Sopenharmony_ci if (printee.IsJSArray()) { 3821cb0ef41Sopenharmony_ci JSArray array = JSArray::cast(printee); 3831cb0ef41Sopenharmony_ci if (array.HasObjectElements()) { 3841cb0ef41Sopenharmony_ci unsigned int limit = FixedArray::cast(array.elements()).length(); 3851cb0ef41Sopenharmony_ci unsigned int length = 3861cb0ef41Sopenharmony_ci static_cast<uint32_t>(JSArray::cast(array).length().Number()); 3871cb0ef41Sopenharmony_ci if (length < limit) limit = length; 3881cb0ef41Sopenharmony_ci PrintFixedArray(FixedArray::cast(array.elements()), limit); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci } 3911cb0ef41Sopenharmony_ci } else if (printee.IsByteArray()) { 3921cb0ef41Sopenharmony_ci PrintByteArray(ByteArray::cast(printee)); 3931cb0ef41Sopenharmony_ci } else if (printee.IsFixedArray()) { 3941cb0ef41Sopenharmony_ci unsigned int limit = FixedArray::cast(printee).length(); 3951cb0ef41Sopenharmony_ci PrintFixedArray(FixedArray::cast(printee), limit); 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci} 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_civoid StringStream::PrintSecurityTokenIfChanged(JSFunction fun) { 4011cb0ef41Sopenharmony_ci Object token = fun.native_context().security_token(); 4021cb0ef41Sopenharmony_ci Isolate* isolate = fun.GetIsolate(); 4031cb0ef41Sopenharmony_ci if (token != isolate->string_stream_current_security_token()) { 4041cb0ef41Sopenharmony_ci Add("Security context: %o\n", token); 4051cb0ef41Sopenharmony_ci isolate->set_string_stream_current_security_token(token); 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci} 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_civoid StringStream::PrintFunction(JSFunction fun, Object receiver, Code* code) { 4101cb0ef41Sopenharmony_ci PrintPrototype(fun, receiver); 4111cb0ef41Sopenharmony_ci *code = FromCodeT(fun.code()); 4121cb0ef41Sopenharmony_ci} 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_civoid StringStream::PrintPrototype(JSFunction fun, Object receiver) { 4151cb0ef41Sopenharmony_ci Object name = fun.shared().Name(); 4161cb0ef41Sopenharmony_ci bool print_name = false; 4171cb0ef41Sopenharmony_ci Isolate* isolate = fun.GetIsolate(); 4181cb0ef41Sopenharmony_ci if (receiver.IsNullOrUndefined(isolate) || receiver.IsTheHole(isolate) || 4191cb0ef41Sopenharmony_ci receiver.IsJSProxy()) { 4201cb0ef41Sopenharmony_ci print_name = true; 4211cb0ef41Sopenharmony_ci } else if (!isolate->context().is_null()) { 4221cb0ef41Sopenharmony_ci if (!receiver.IsJSObject()) { 4231cb0ef41Sopenharmony_ci receiver = receiver.GetPrototypeChainRootMap(isolate).prototype(); 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci for (PrototypeIterator iter(isolate, JSObject::cast(receiver), 4271cb0ef41Sopenharmony_ci kStartAtReceiver); 4281cb0ef41Sopenharmony_ci !iter.IsAtEnd(); iter.Advance()) { 4291cb0ef41Sopenharmony_ci if (iter.GetCurrent().IsJSProxy()) break; 4301cb0ef41Sopenharmony_ci Object key = iter.GetCurrent<JSObject>().SlowReverseLookup(fun); 4311cb0ef41Sopenharmony_ci if (!key.IsUndefined(isolate)) { 4321cb0ef41Sopenharmony_ci if (!name.IsString() || !key.IsString() || 4331cb0ef41Sopenharmony_ci !String::cast(name).Equals(String::cast(key))) { 4341cb0ef41Sopenharmony_ci print_name = true; 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci if (name.IsString() && String::cast(name).length() == 0) { 4371cb0ef41Sopenharmony_ci print_name = false; 4381cb0ef41Sopenharmony_ci } 4391cb0ef41Sopenharmony_ci name = key; 4401cb0ef41Sopenharmony_ci break; 4411cb0ef41Sopenharmony_ci } 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci } 4441cb0ef41Sopenharmony_ci PrintName(name); 4451cb0ef41Sopenharmony_ci // Also known as - if the name in the function doesn't match the name under 4461cb0ef41Sopenharmony_ci // which it was looked up. 4471cb0ef41Sopenharmony_ci if (print_name) { 4481cb0ef41Sopenharmony_ci Add("(aka "); 4491cb0ef41Sopenharmony_ci PrintName(fun.shared().Name()); 4501cb0ef41Sopenharmony_ci Put(')'); 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci} 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_cichar* HeapStringAllocator::grow(unsigned* bytes) { 4551cb0ef41Sopenharmony_ci unsigned new_bytes = *bytes * 2; 4561cb0ef41Sopenharmony_ci // Check for overflow. 4571cb0ef41Sopenharmony_ci if (new_bytes <= *bytes) { 4581cb0ef41Sopenharmony_ci return space_; 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci char* new_space = NewArray<char>(new_bytes); 4611cb0ef41Sopenharmony_ci if (new_space == nullptr) { 4621cb0ef41Sopenharmony_ci return space_; 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci MemCopy(new_space, space_, *bytes); 4651cb0ef41Sopenharmony_ci *bytes = new_bytes; 4661cb0ef41Sopenharmony_ci DeleteArray(space_); 4671cb0ef41Sopenharmony_ci space_ = new_space; 4681cb0ef41Sopenharmony_ci return new_space; 4691cb0ef41Sopenharmony_ci} 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci} // namespace internal 4721cb0ef41Sopenharmony_ci} // namespace v8 473