1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_STRING_STREAM_H_
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_STRING_STREAM_H_
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/allocation.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/handles.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/vector.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Forward declarations.
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass ByteArray;
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StringAllocator {
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~StringAllocator() { }
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a number of bytes.
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual char* allocate(unsigned bytes) = 0;
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate a larger number of bytes and copy the old buffer to the new one.
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bytes is an input and output parameter passing the old size of the buffer
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and returning the new size.  If allocation fails then we return the old
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // buffer and do not increase the size.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual char* grow(unsigned* bytes) = 0;
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Normal allocator uses new[] and delete[].
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass HeapStringAllocator final : public StringAllocator {
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~HeapStringAllocator() { DeleteArray(space_); }
35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* allocate(unsigned bytes) override;
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* grow(unsigned* bytes) override;
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* space_;
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass FixedStringAllocator final : public StringAllocator {
44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FixedStringAllocator(char* buffer, unsigned length)
46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : buffer_(buffer), length_(length) {}
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~FixedStringAllocator() override{};
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* allocate(unsigned bytes) override;
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* grow(unsigned* bytes) override;
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  char* buffer_;
53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned length_;
54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(FixedStringAllocator);
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass StringStream final {
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  class FmtElm final {
5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch   public:
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(int value) : FmtElm(INT) {  // NOLINT
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_int_ = value;
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    explicit FmtElm(double value) : FmtElm(DOUBLE) {  // NOLINT
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_double_ = value;
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(const char* value) : FmtElm(C_STR) {  // NOLINT
6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_c_str_ = value;
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(const Vector<const uc16>& value) : FmtElm(LC_STR) {  // NOLINT
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_lc_str_ = &value;
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(Object* value) : FmtElm(OBJ) {  // NOLINT
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_obj_ = value;
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(Handle<Object> value) : FmtElm(HANDLE) {  // NOLINT
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_handle_ = value.location();
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm(void* value) : FmtElm(POINTER) {  // NOLINT
7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      data_.u_pointer_ = value;
8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch   private:
8362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    friend class StringStream;
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#ifdef DEBUG
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Type type_;
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    explicit FmtElm(Type type) : type_(type) {}
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#else
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    explicit FmtElm(Type) {}
9162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#endif
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    union {
9462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      int u_int_;
9562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      double u_double_;
9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      const char* u_c_str_;
9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      const Vector<const uc16>* u_lc_str_;
9862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Object* u_obj_;
9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Object** u_handle_;
10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      void* u_pointer_;
10162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } data_;
10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  };
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  StringStream(StringAllocator* allocator,
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               ObjectPrintMode object_print_mode = kPrintObjectVerbose)
108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : allocator_(allocator),
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        object_print_mode_(object_print_mode),
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        capacity_(kInitialCapacity),
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        length_(0),
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        buffer_(allocator_->allocate(kInitialCapacity)) {
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_[0] = 0;
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool Put(char c);
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool Put(String* str);
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool Put(String* str, int start, int end);
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Add(const char* format) { Add(CStrVector(format)); }
12062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Add(Vector<const char> format) { Add(format, Vector<FmtElm>()); }
12162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Args>
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Add(const char* format, Args... args) {
12462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Add(CStrVector(format), args...);
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
12762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <typename... Args>
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Add(Vector<const char> format, Args... args) {
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    FmtElm elems[]{args...};
13062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Add(format, ArrayVector(elems));
13162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Getting the message out.
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void OutputToFile(FILE* out);
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void OutputToStdOut() { OutputToFile(stdout); }
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Log(Isolate* isolate);
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> ToString(Isolate* isolate);
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::unique_ptr<char[]> ToCString() const;
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length() const { return length_; }
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object printing support.
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintName(Object* o);
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintFixedArray(FixedArray* array, unsigned int limit);
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintByteArray(ByteArray* ba);
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintUsingMap(JSObject* js_object);
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintPrototype(JSFunction* fun, Object* receiver);
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintSecurityTokenIfChanged(Object* function);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: Returns the code in the output parameter.
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintFunction(Object* function, Object* receiver, Code** code);
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the stream.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Reset() {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    length_ = 0;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_[0] = 0;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mentioned object cache support.
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrintMentionedObjectCache(Isolate* isolate);
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ClearMentionedObjectCache(Isolate* isolate);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsMentionedObjectCacheClear(Isolate* isolate);
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kInitialCapacity = 16;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
16762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void Add(Vector<const char> format, Vector<FmtElm> elms);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintObject(Object* obj);
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringAllocator* allocator_;
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ObjectPrintMode object_print_mode_;
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned capacity_;
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unsigned length_;  // does not include terminating 0-character
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* buffer_;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool full() const { return (capacity_ - length_) == 1; }
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int space() const { return capacity_ - length_; }
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_STRING_STREAM_H_
186