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/base/small-vector.h"
10 : #include "src/handles.h"
11 : #include "src/objects/heap-object.h"
12 : #include "src/vector.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : // Forward declarations.
18 : class ByteArray;
19 :
20 142917 : class StringAllocator {
21 : public:
22 142917 : virtual ~StringAllocator() = default;
23 : // Allocate a number of bytes.
24 : virtual char* allocate(unsigned bytes) = 0;
25 : // Allocate a larger number of bytes and copy the old buffer to the new one.
26 : // bytes is an input and output parameter passing the old size of the buffer
27 : // and returning the new size. If allocation fails then we return the old
28 : // buffer and do not increase the size.
29 : virtual char* grow(unsigned* bytes) = 0;
30 : };
31 :
32 :
33 : // Normal allocator uses new[] and delete[].
34 89433 : class HeapStringAllocator final : public StringAllocator {
35 : public:
36 178866 : ~HeapStringAllocator() override { DeleteArray(space_); }
37 : char* allocate(unsigned bytes) override;
38 : char* grow(unsigned* bytes) override;
39 :
40 : private:
41 : char* space_;
42 : };
43 :
44 :
45 : class FixedStringAllocator final : public StringAllocator {
46 : public:
47 : FixedStringAllocator(char* buffer, unsigned length)
48 15 : : buffer_(buffer), length_(length) {}
49 15 : ~FixedStringAllocator() override = default;
50 :
51 : char* allocate(unsigned bytes) override;
52 : char* grow(unsigned* bytes) override;
53 :
54 : private:
55 : char* buffer_;
56 : unsigned length_;
57 : DISALLOW_COPY_AND_ASSIGN(FixedStringAllocator);
58 : };
59 :
60 : template <std::size_t kInlineSize>
61 53469 : class SmallStringOptimizedAllocator final : public StringAllocator {
62 : public:
63 : typedef base::SmallVector<char, kInlineSize> SmallVector;
64 :
65 : explicit SmallStringOptimizedAllocator(SmallVector* vector) V8_NOEXCEPT
66 53469 : : vector_(vector) {}
67 :
68 53469 : char* allocate(unsigned bytes) override {
69 53469 : vector_->resize_no_init(bytes);
70 53469 : return vector_->data();
71 : }
72 :
73 106830 : char* grow(unsigned* bytes) override {
74 106830 : unsigned new_bytes = *bytes * 2;
75 : // Check for overflow.
76 106830 : if (new_bytes <= *bytes) {
77 0 : return vector_->data();
78 : }
79 106830 : vector_->resize_no_init(new_bytes);
80 106830 : *bytes = new_bytes;
81 106830 : return vector_->data();
82 : }
83 :
84 : private:
85 : SmallVector* vector_;
86 : };
87 :
88 : class StringStream final {
89 : class FmtElm final {
90 : public:
91 : FmtElm(int value) : FmtElm(INT) { // NOLINT
92 148035 : data_.u_int_ = value;
93 : }
94 : explicit FmtElm(double value) : FmtElm(DOUBLE) { // NOLINT
95 : data_.u_double_ = value;
96 : }
97 : FmtElm(const char* value) : FmtElm(C_STR) { // NOLINT
98 157317 : data_.u_c_str_ = value;
99 : }
100 : FmtElm(const Vector<const uc16>& value) : FmtElm(LC_STR) { // NOLINT
101 : data_.u_lc_str_ = &value;
102 : }
103 : FmtElm(Object value) : FmtElm(OBJ) { // NOLINT
104 10679 : data_.u_obj_ = value.ptr();
105 : }
106 : FmtElm(Handle<Object> value) : FmtElm(HANDLE) { // NOLINT
107 : data_.u_handle_ = value.location();
108 : }
109 : FmtElm(void* value) : FmtElm(POINTER) { // NOLINT
110 22785 : data_.u_pointer_ = value;
111 : }
112 :
113 : private:
114 : friend class StringStream;
115 : enum Type { INT, DOUBLE, C_STR, LC_STR, OBJ, HANDLE, POINTER };
116 :
117 : #ifdef DEBUG
118 : Type type_;
119 : explicit FmtElm(Type type) : type_(type) {}
120 : #else
121 : explicit FmtElm(Type) {}
122 : #endif
123 :
124 : union {
125 : int u_int_;
126 : double u_double_;
127 : const char* u_c_str_;
128 : const Vector<const uc16>* u_lc_str_;
129 : Address u_obj_;
130 : Address* u_handle_;
131 : void* u_pointer_;
132 : } data_;
133 : };
134 :
135 : public:
136 : enum ObjectPrintMode { kPrintObjectConcise, kPrintObjectVerbose };
137 : explicit StringStream(StringAllocator* allocator,
138 : ObjectPrintMode object_print_mode = kPrintObjectVerbose)
139 : : allocator_(allocator),
140 : object_print_mode_(object_print_mode),
141 : capacity_(kInitialCapacity),
142 : length_(0),
143 142917 : buffer_(allocator_->allocate(kInitialCapacity)) {
144 142917 : buffer_[0] = 0;
145 : }
146 :
147 : bool Put(char c);
148 : bool Put(String str);
149 : bool Put(String str, int start, int end);
150 582522 : void Add(const char* format) { Add(CStrVector(format)); }
151 1228115 : void Add(Vector<const char> format) { Add(format, Vector<FmtElm>()); }
152 :
153 : template <typename... Args>
154 128927 : void Add(const char* format, Args... args) {
155 : Add(CStrVector(format), args...);
156 128927 : }
157 :
158 : template <typename... Args>
159 : void Add(Vector<const char> format, Args... args) {
160 54463 : FmtElm elems[]{args...};
161 128927 : Add(format, ArrayVector(elems));
162 : }
163 :
164 : // Getting the message out.
165 : void OutputToFile(FILE* out);
166 0 : void OutputToStdOut() { OutputToFile(stdout); }
167 : void Log(Isolate* isolate);
168 : Handle<String> ToString(Isolate* isolate);
169 : std::unique_ptr<char[]> ToCString() const;
170 53469 : int length() const { return length_; }
171 :
172 : // Object printing support.
173 : void PrintName(Object o);
174 : void PrintFixedArray(FixedArray array, unsigned int limit);
175 : void PrintByteArray(ByteArray ba);
176 : void PrintUsingMap(JSObject js_object);
177 : void PrintPrototype(JSFunction fun, Object receiver);
178 : void PrintSecurityTokenIfChanged(JSFunction function);
179 : // NOTE: Returns the code in the output parameter.
180 : void PrintFunction(JSFunction function, Object receiver, Code* code);
181 :
182 : // Reset the stream.
183 : void Reset() {
184 : length_ = 0;
185 : buffer_[0] = 0;
186 : }
187 :
188 : // Mentioned object cache support.
189 : void PrintMentionedObjectCache(Isolate* isolate);
190 : static void ClearMentionedObjectCache(Isolate* isolate);
191 : #ifdef DEBUG
192 : bool IsMentionedObjectCacheClear(Isolate* isolate);
193 : #endif
194 :
195 : static const int kInitialCapacity = 16;
196 :
197 : private:
198 : void Add(Vector<const char> format, Vector<FmtElm> elms);
199 : void PrintObject(Object obj);
200 :
201 : StringAllocator* allocator_;
202 : ObjectPrintMode object_print_mode_;
203 : unsigned capacity_;
204 : unsigned length_; // does not include terminating 0-character
205 : char* buffer_;
206 :
207 6116514 : bool full() const { return (capacity_ - length_) == 1; }
208 : int space() const { return capacity_ - length_; }
209 :
210 : DISALLOW_IMPLICIT_CONSTRUCTORS(StringStream);
211 : };
212 :
213 : } // namespace internal
214 : } // namespace v8
215 :
216 : #endif // V8_STRING_STREAM_H_
|