Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_STRING_STREAM_H_
6 : #define V8_STRING_STREAM_H_
7 :
8 : #include "src/allocation.h"
9 : #include "src/handles.h"
10 : #include "src/objects/heap-object.h"
11 : #include "src/vector.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // Forward declarations.
17 : class ByteArray;
18 :
19 112743 : class StringAllocator {
20 : public:
21 2469 : virtual ~StringAllocator() = default;
22 : // Allocate a number of bytes.
23 : virtual char* allocate(unsigned bytes) = 0;
24 : // Allocate a larger number of bytes and copy the old buffer to the new one.
25 : // bytes is an input and output parameter passing the old size of the buffer
26 : // and returning the new size. If allocation fails then we return the old
27 : // buffer and do not increase the size.
28 : virtual char* grow(unsigned* bytes) = 0;
29 : };
30 :
31 :
32 : // Normal allocator uses new[] and delete[].
33 112728 : class HeapStringAllocator final : public StringAllocator {
34 : public:
35 112728 : ~HeapStringAllocator() override { DeleteArray(space_); }
36 : char* allocate(unsigned bytes) override;
37 : char* grow(unsigned* bytes) override;
38 :
39 : private:
40 : char* space_;
41 : };
42 :
43 :
44 : class FixedStringAllocator final : public StringAllocator {
45 : public:
46 : FixedStringAllocator(char* buffer, unsigned length)
47 15 : : buffer_(buffer), length_(length) {}
48 0 : ~FixedStringAllocator() override = default;
49 :
50 : char* allocate(unsigned bytes) override;
51 : char* grow(unsigned* bytes) override;
52 :
53 : private:
54 : char* buffer_;
55 : unsigned length_;
56 : DISALLOW_COPY_AND_ASSIGN(FixedStringAllocator);
57 : };
58 :
59 : class StringStream final {
60 : class FmtElm final {
61 : public:
62 : FmtElm(int value) : FmtElm(INT) { // NOLINT
63 41815 : data_.u_int_ = value;
64 : }
65 : explicit FmtElm(double value) : FmtElm(DOUBLE) { // NOLINT
66 0 : data_.u_double_ = value;
67 : }
68 : FmtElm(const char* value) : FmtElm(C_STR) { // NOLINT
69 51188 : data_.u_c_str_ = value;
70 : }
71 : FmtElm(const Vector<const uc16>& value) : FmtElm(LC_STR) { // NOLINT
72 : data_.u_lc_str_ = &value;
73 : }
74 : FmtElm(Object value) : FmtElm(OBJ) { // NOLINT
75 10864 : data_.u_obj_ = value.ptr();
76 : }
77 : FmtElm(Handle<Object> value) : FmtElm(HANDLE) { // NOLINT
78 : data_.u_handle_ = value.location();
79 : }
80 : FmtElm(void* value) : FmtElm(POINTER) { // NOLINT
81 45177 : data_.u_pointer_ = value;
82 : }
83 :
84 : private:
85 : friend class StringStream;
86 : enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };
87 :
88 : #ifdef DEBUG
89 : Type type_;
90 : explicit FmtElm(Type type) : type_(type) {}
91 : #else
92 : explicit FmtElm(Type) {}
93 : #endif
94 :
95 : union {
96 : int u_int_;
97 : double u_double_;
98 : const char* u_c_str_;
99 : const Vector<const uc16>* u_lc_str_;
100 : Address u_obj_;
101 : Address* u_handle_;
102 : void* u_pointer_;
103 : } data_;
104 : };
105 :
106 : public:
107 : enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
108 : StringStream(StringAllocator* allocator,
109 : ObjectPrintMode object_print_mode = kPrintObjectVerbose)
110 : : allocator_(allocator),
111 : object_print_mode_(object_print_mode),
112 : capacity_(kInitialCapacity),
113 : length_(0),
114 112743 : buffer_(allocator_->allocate(kInitialCapacity)) {
115 112743 : buffer_[0] = 0;
116 : }
117 :
118 : bool Put(char c);
119 : bool Put(String str);
120 : bool Put(String str, int start, int end);
121 353954 : void Add(const char* format) { Add(CStrVector(format)); }
122 260751 : void Add(Vector<const char> format) { Add(format, Vector<FmtElm>()); }
123 :
124 : template <typename... Args>
125 98713 : void Add(const char* format, Args... args) {
126 : Add(CStrVector(format), args...);
127 98713 : }
128 :
129 : template <typename... Args>
130 : void Add(Vector<const char> format, Args... args) {
131 1205 : FmtElm elems[]{args...};
132 98713 : Add(format, ArrayVector(elems));
133 : }
134 :
135 : // Getting the message out.
136 : void OutputToFile(FILE* out);
137 0 : void OutputToStdOut() { OutputToFile(stdout); }
138 : void Log(Isolate* isolate);
139 : Handle<String> ToString(Isolate* isolate);
140 : std::unique_ptr<char[]> ToCString() const;
141 : int length() const { return length_; }
142 :
143 : // Object printing support.
144 : void PrintName(Object o);
145 : void PrintFixedArray(FixedArray array, unsigned int limit);
146 : void PrintByteArray(ByteArray ba);
147 : void PrintUsingMap(JSObject js_object);
148 : void PrintPrototype(JSFunction fun, Object receiver);
149 : void PrintSecurityTokenIfChanged(JSFunction function);
150 : // NOTE: Returns the code in the output parameter.
151 : void PrintFunction(JSFunction function, Object receiver, Code* code);
152 :
153 : // Reset the stream.
154 : void Reset() {
155 : length_ = 0;
156 : buffer_[0] = 0;
157 : }
158 :
159 : // Mentioned object cache support.
160 : void PrintMentionedObjectCache(Isolate* isolate);
161 : static void ClearMentionedObjectCache(Isolate* isolate);
162 : #ifdef DEBUG
163 : bool IsMentionedObjectCacheClear(Isolate* isolate);
164 : #endif
165 :
166 : static const int kInitialCapacity = 16;
167 :
168 : private:
169 : void Add(Vector<const char> format, Vector<FmtElm> elms);
170 : void PrintObject(Object obj);
171 :
172 : StringAllocator* allocator_;
173 : ObjectPrintMode object_print_mode_;
174 : unsigned capacity_;
175 : unsigned length_; // does not include terminating 0-character
176 : char* buffer_;
177 :
178 3522908 : bool full() const { return (capacity_ - length_) == 1; }
179 : int space() const { return capacity_ - length_; }
180 :
181 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
182 : };
183 :
184 : } // namespace internal
185 : } // namespace v8
186 :
187 : #endif // V8_STRING_STREAM_H_
|