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