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