[vm] Create a common base class for TextBuffer/ZoneTextBuffer.

Generally, methods that take a *TextBuffer pointer do not care how the
internal buffer is allocated, and so they could be used for either if
both were subclasses of a base class that contained the printing
methods.  This CL makes that base class, and now TextBuffer and
ZoneTextBuffer now share the exact same set of methods for printing to
the internal buffer.

Since the base class is in platform, this does mean dropping the
overload of AddString for Dart String objects that was part of
ZoneTextBuffer.  Instead, this CL just adds an intermediate call to
ToCString() for the small number of callers that used the overload,
keeping the printing interface the same for both.

In addition, one use of TextBuffer that then re-allocated the buffer
contents into the zone manually has been replaced with a ZoneTextBuffer
instead.

Change-Id: I438a085e7e20d55d93987fd7f36afd636f95955f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/157741
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
This commit is contained in:
Tess Strickland 2020-08-07 18:09:35 +00:00 committed by commit-bot@chromium.org
parent e51623f81a
commit fa03ee7782
26 changed files with 192 additions and 226 deletions

View file

@ -608,7 +608,7 @@ static void WriteLoadingUnitManifest(File* manifest_file,
line.Printf("{ \"id\": %" Pd ", \"path\": \"", id);
line.AddEscapedString(path);
line.Printf("\" }");
if (!manifest_file->Print("%s\n", line.buf())) {
if (!manifest_file->Print("%s\n", line.buffer())) {
PrintErrAndExit("Error: Unable to write file: %s\n\n",
loading_unit_manifest_filename);
}

View file

@ -61,7 +61,7 @@ class NamespaceImpl {
// Normalize it.
char result[PATH_MAX];
const intptr_t result_len =
File::CleanUnixPath(tbuf.buf(), result, PATH_MAX);
File::CleanUnixPath(tbuf.buffer(), result, PATH_MAX);
if (result_len < 0) {
errno = ENAMETOOLONG;
return false;

View file

@ -81,7 +81,7 @@ bool NamespaceImpl::SetCwd(Namespace* namespc, const char* new_path) {
// Normalize it.
char result[PATH_MAX];
const intptr_t result_len =
File::CleanUnixPath(tbuf.buf(), result, PATH_MAX);
File::CleanUnixPath(tbuf.buffer(), result, PATH_MAX);
if (result_len < 0) {
errno = ENAMETOOLONG;
return false;

View file

@ -61,7 +61,7 @@ class NamespaceImpl {
// Normalize it.
char result[PATH_MAX];
const intptr_t result_len =
File::CleanUnixPath(tbuf.buf(), result, PATH_MAX);
File::CleanUnixPath(tbuf.buffer(), result, PATH_MAX);
if (result_len < 0) {
errno = ENAMETOOLONG;
return false;

View file

@ -245,7 +245,8 @@ CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
SecureSocketUtils::FetchErrorString(filter->ssl_, &error_string);
CObjectArray* result = new CObjectArray(CObject::NewArray(2));
result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
result->SetAt(1, new CObjectString(CObject::NewString(error_string.buf())));
result->SetAt(1,
new CObjectString(CObject::NewString(error_string.buffer())));
return result;
}
}

View file

@ -54,7 +54,7 @@ void SecureSocketUtils::ThrowIOException(int status,
{
TextBuffer error_string(SSL_ERROR_MESSAGE_BUFFER_SIZE);
SecureSocketUtils::FetchErrorString(ssl, &error_string);
OSError os_error_struct(status, error_string.buf(), OSError::kBoringSSL);
OSError os_error_struct(status, error_string.buffer(), OSError::kBoringSSL);
Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
exception =
DartUtils::NewDartIOException(exception_type, message, os_error);

View file

@ -11,73 +11,46 @@
namespace dart {
TextBuffer::TextBuffer(intptr_t buf_size) {
ASSERT(buf_size > 0);
buf_ = reinterpret_cast<char*>(malloc(buf_size));
if (buf_ == NULL) {
OUT_OF_MEMORY();
}
buf_size_ = buf_size;
Clear();
}
TextBuffer::~TextBuffer() {
free(buf_);
buf_ = NULL;
}
void TextBuffer::Clear() {
msg_len_ = 0;
buf_[0] = '\0';
}
char* TextBuffer::Steal() {
char* r = buf_;
buf_ = NULL;
buf_size_ = 0;
msg_len_ = 0;
return r;
}
void TextBuffer::AddChar(char ch) {
EnsureCapacity(sizeof(ch));
buf_[msg_len_] = ch;
msg_len_++;
buf_[msg_len_] = '\0';
}
void TextBuffer::AddRaw(const uint8_t* buffer, intptr_t buffer_length) {
EnsureCapacity(buffer_length);
memmove(&buf_[msg_len_], buffer, buffer_length);
msg_len_ += buffer_length;
buf_[msg_len_] = '\0';
}
intptr_t TextBuffer::Printf(const char* format, ...) {
intptr_t BaseTextBuffer::Printf(const char* format, ...) {
va_list args;
va_start(args, format);
intptr_t remaining = buf_size_ - msg_len_;
intptr_t remaining = capacity_ - length_;
ASSERT(remaining >= 0);
intptr_t len = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args);
intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args);
va_end(args);
if (len >= remaining) {
EnsureCapacity(len);
remaining = buf_size_ - msg_len_;
remaining = capacity_ - length_;
ASSERT(remaining > len);
va_list args2;
va_start(args2, format);
intptr_t len2 = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args2);
intptr_t len2 =
Utils::VSNPrint(buffer_ + length_, remaining, format, args2);
va_end(args2);
ASSERT(len == len2);
}
msg_len_ += len;
buf_[msg_len_] = '\0';
length_ += len;
buffer_[length_] = '\0';
return len;
}
void BaseTextBuffer::AddChar(char ch) {
EnsureCapacity(sizeof(ch));
buffer_[length_] = ch;
length_++;
buffer_[length_] = '\0';
}
void BaseTextBuffer::AddRaw(const uint8_t* buffer, intptr_t buffer_length) {
EnsureCapacity(buffer_length);
memmove(&buffer_[length_], buffer, buffer_length);
length_ += buffer_length;
buffer_[length_] = '\0';
}
// Write a UTF-32 code unit so it can be read by a JSON parser in a string
// literal. Use official encoding from JSON specification. http://json.org/
void TextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) {
void BaseTextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) {
switch (codeunit) {
case '"':
AddRaw(reinterpret_cast<uint8_t const*>("\\\""), 2);
@ -117,31 +90,54 @@ void TextBuffer::EscapeAndAddCodeUnit(uint32_t codeunit) {
// Write an incomplete UTF-16 code unit so it can be read by a JSON parser in a
// string literal.
void TextBuffer::EscapeAndAddUTF16CodeUnit(uint16_t codeunit) {
void BaseTextBuffer::EscapeAndAddUTF16CodeUnit(uint16_t codeunit) {
Printf("\\u%04X", codeunit);
}
void TextBuffer::AddString(const char* s) {
void BaseTextBuffer::AddString(const char* s) {
Printf("%s", s);
}
void TextBuffer::AddEscapedString(const char* s) {
void BaseTextBuffer::AddEscapedString(const char* s) {
intptr_t len = strlen(s);
for (int i = 0; i < len; i++) {
EscapeAndAddCodeUnit(s[i]);
}
}
TextBuffer::TextBuffer(intptr_t buf_size) {
ASSERT(buf_size > 0);
buffer_ = reinterpret_cast<char*>(malloc(buf_size));
if (buffer_ == nullptr) {
OUT_OF_MEMORY();
}
capacity_ = buf_size;
Clear();
}
TextBuffer::~TextBuffer() {
free(buffer_);
buffer_ = nullptr;
}
char* TextBuffer::Steal() {
char* r = buffer_;
buffer_ = nullptr;
capacity_ = 0;
length_ = 0;
return r;
}
void TextBuffer::EnsureCapacity(intptr_t len) {
intptr_t remaining = buf_size_ - msg_len_;
intptr_t remaining = capacity_ - length_;
if (remaining <= len) {
intptr_t new_size = buf_size_ + Utils::Maximum(buf_size_, len + 1);
char* new_buf = reinterpret_cast<char*>(realloc(buf_, new_size));
if (new_buf == NULL) {
intptr_t new_size = capacity_ + Utils::Maximum(capacity_, len + 1);
char* new_buf = reinterpret_cast<char*>(realloc(buffer_, new_size));
if (new_buf == nullptr) {
OUT_OF_MEMORY();
}
buf_ = new_buf;
buf_size_ = new_size;
buffer_ = new_buf;
capacity_ = new_size;
}
}

View file

@ -10,12 +10,11 @@
namespace dart {
// TextBuffer maintains a dynamic character buffer with a printf-style way to
// append text.
class TextBuffer : ValueObject {
// BaseTextBuffer maintains a dynamic character buffer with a printf-style way
// to append text. Internal buffer management is handled by subclasses.
class BaseTextBuffer : public ValueObject {
public:
explicit TextBuffer(intptr_t buf_size);
~TextBuffer();
virtual ~BaseTextBuffer() {}
intptr_t Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
void AddChar(char ch);
@ -25,25 +24,47 @@ class TextBuffer : ValueObject {
void AddEscapedString(const char* s);
void AddRaw(const uint8_t* buffer, intptr_t buffer_length);
void Clear();
// Returns a pointer to the current internal buffer. Whether the pointer is
// still valid after the BaseTextBuffer dies depends on the subclass.
char* buffer() const { return buffer_; }
intptr_t length() const { return length_; }
// Clears the stored contents. Unless specified otherwise by the subclass,
// should be assumed to invalidate the contents of previous calls to buffer().
virtual void Clear() = 0;
protected:
virtual void EnsureCapacity(intptr_t len) = 0;
char* buffer_ = nullptr;
intptr_t capacity_ = 0;
intptr_t length_ = 0;
};
// TextBuffer uses manual memory management for the character buffer. Unless
// Steal() is used, the internal buffer is deallocated when the object dies.
class TextBuffer : public BaseTextBuffer {
public:
explicit TextBuffer(intptr_t buf_size);
~TextBuffer();
// Resets the contents of the internal buffer.
void Clear() { set_length(0); }
char* buf() { return buf_; }
intptr_t length() { return msg_len_; }
void set_length(intptr_t len) {
ASSERT(len >= 0);
ASSERT(len <= msg_len_);
msg_len_ = len;
ASSERT(len <= length_);
length_ = len;
buffer_[len] = '\0';
}
// Steal ownership of the buffer pointer.
// Take ownership of the buffer contents. Future uses of the TextBuffer object
// will not affect the contents of the returned buffer.
// NOTE: TextBuffer is empty afterwards.
char* Steal();
private:
void EnsureCapacity(intptr_t len);
char* buf_;
intptr_t buf_size_;
intptr_t msg_len_;
};
class BufferFormatter : public ValueObject {

View file

@ -102,7 +102,7 @@ static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
if (results.serialized != nullptr) {
TextBuffer buf(1000);
results.serialized->SerializeTo(zone, &buf, "");
js.PrintProperty("serialized", buf.buf());
js.PrintProperty("serialized", buf.buffer());
}
if (results.error_message != nullptr) {
@ -112,7 +112,7 @@ static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
ASSERT(results.error_sexp != nullptr);
TextBuffer buf(1000);
results.error_sexp->SerializeTo(zone, &buf, "");
js.PrintProperty("expression", buf.buf());
js.PrintProperty("expression", buf.buffer());
auto const sexp_position =
GetSExpressionPosition(zone, results.serialized, results.error_sexp);
@ -121,7 +121,7 @@ static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
}
js.CloseObject();
THR_Print("Results of round trip serialization: %s\n", js.buffer()->buf());
THR_Print("Results of round trip serialization: %s\n", js.buffer()->buffer());
}
void FlowGraphDeserializer::RoundTripSerialization(CompilerPassState* state) {
@ -159,7 +159,7 @@ void FlowGraphDeserializer::RoundTripSerialization(CompilerPassState* state) {
if (FLAG_trace_round_trip_serialization && results.serialized != nullptr) {
TextBuffer buf(1000);
results.serialized->SerializeTo(zone, &buf, "");
THR_Print("Serialized flow graph:\n%s\n", buf.buf());
THR_Print("Serialized flow graph:\n%s\n", buf.buffer());
}
// For the deserializer, use the thread from the compiler pass and zone

View file

@ -10,6 +10,7 @@
#include "vm/compiler/method_recognizer.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/zone_text_buffer.h"
namespace dart {
@ -75,14 +76,9 @@ FlowGraphSerializer::~FlowGraphSerializer() {
object_store_->set_llvm_constant_hash_table(llvm_constant_map_.Release());
}
void FlowGraphSerializer::SerializeToBuffer(const FlowGraph* flow_graph,
TextBuffer* buffer) {
SerializeToBuffer(Thread::Current()->zone(), flow_graph, buffer);
}
void FlowGraphSerializer::SerializeToBuffer(Zone* zone,
const FlowGraph* flow_graph,
TextBuffer* buffer) {
BaseTextBuffer* buffer) {
ASSERT(buffer != nullptr);
auto const sexp = SerializeToSExp(zone, flow_graph);
if (FLAG_pretty_print_serialization) {
@ -93,10 +89,6 @@ void FlowGraphSerializer::SerializeToBuffer(Zone* zone,
buffer->AddString("\n\n");
}
SExpression* FlowGraphSerializer::SerializeToSExp(const FlowGraph* flow_graph) {
return SerializeToSExp(Thread::Current()->zone(), flow_graph);
}
SExpression* FlowGraphSerializer::SerializeToSExp(Zone* zone,
const FlowGraph* flow_graph) {
FlowGraphSerializer serializer(zone, flow_graph);
@ -163,7 +155,7 @@ SExpression* FlowGraphSerializer::BlockIdToSExp(intptr_t block_id) {
return new (zone()) SExpSymbol(OS::SCreate(zone(), "B%" Pd "", block_id));
}
void FlowGraphSerializer::SerializeCanonicalName(TextBuffer* b,
void FlowGraphSerializer::SerializeCanonicalName(BaseTextBuffer* b,
const Object& obj) {
ASSERT(!obj.IsNull());
if (obj.IsFunction()) {
@ -223,9 +215,9 @@ void FlowGraphSerializer::SerializeCanonicalName(TextBuffer* b,
SExpression* FlowGraphSerializer::CanonicalNameToSExp(const Object& obj) {
ASSERT(!obj.IsNull());
TextBuffer b(100);
ZoneTextBuffer b(zone_, 100);
SerializeCanonicalName(&b, obj);
return new (zone()) SExpSymbol(OS::SCreate(zone(), "%s", b.buf()));
return new (zone()) SExpSymbol(b.buffer());
}
SExpSymbol* FlowGraphSerializer::BlockEntryKindToTag(BlockEntryKind k) {

View file

@ -50,12 +50,9 @@ class FlowGraphSerializer : ValueObject {
SExpSymbol* BlockEntryKindToTag(BlockEntryKind k);
static bool BlockEntryKindHasInitialDefs(BlockEntryKind kind);
static void SerializeToBuffer(const FlowGraph* flow_graph,
TextBuffer* buffer);
static void SerializeToBuffer(Zone* zone,
const FlowGraph* flow_graph,
TextBuffer* buffer);
static SExpression* SerializeToSExp(const FlowGraph* flow_graph);
BaseTextBuffer* buffer);
static SExpression* SerializeToSExp(Zone* zone, const FlowGraph* flow_graph);
const FlowGraph* flow_graph() const { return flow_graph_; }
@ -69,7 +66,7 @@ class FlowGraphSerializer : ValueObject {
SExpression* UseToSExp(const Definition* definition);
// Helper method for creating canonical names.
void SerializeCanonicalName(TextBuffer* b, const Object& obj);
void SerializeCanonicalName(BaseTextBuffer* b, const Object& obj);
// Methods for serializing Dart values. If the argument
// value is the null object, the null pointer is returned.

View file

@ -7,6 +7,7 @@
#include <ctype.h>
#include "platform/utils.h"
#include "vm/double_conversion.h"
#include "vm/zone_text_buffer.h"
namespace dart {
@ -18,13 +19,9 @@ SExpression* SExpression::FromCString(Zone* zone, const char* str) {
}
const char* SExpression::ToCString(Zone* zone) const {
TextBuffer buf(1 * KB);
ZoneTextBuffer buf(zone, 1 * KB);
SerializeToLine(&buf);
auto const buf_len = buf.length();
char* ret = zone->Alloc<char>(buf_len + 1);
strncpy(ret, buf.buf(), buf_len);
ret[buf_len] = '\0';
return ret;
return buf.buffer();
}
bool SExpBool::Equals(SExpression* sexp) const {
@ -36,7 +33,7 @@ bool SExpBool::Equals(bool val) const {
return value() == val;
}
void SExpBool::SerializeToLine(TextBuffer* buffer) const {
void SExpBool::SerializeToLine(BaseTextBuffer* buffer) const {
buffer->AddString(value() ? SExpParser::kBoolTrueSymbol
: SExpParser::kBoolFalseSymbol);
}
@ -50,7 +47,7 @@ bool SExpDouble::Equals(double val) const {
return value() == val;
}
void SExpDouble::SerializeToLine(TextBuffer* buffer) const {
void SExpDouble::SerializeToLine(BaseTextBuffer* buffer) const {
// Use existing Dart serialization for Doubles.
const intptr_t kBufSize = 128;
char strbuf[kBufSize];
@ -67,7 +64,7 @@ bool SExpInteger::Equals(int64_t val) const {
return value() == val;
}
void SExpInteger::SerializeToLine(TextBuffer* buffer) const {
void SExpInteger::SerializeToLine(BaseTextBuffer* buffer) const {
buffer->Printf("%" Pd64 "", value());
}
@ -80,10 +77,12 @@ bool SExpString::Equals(const char* str) const {
return strcmp(value(), str) == 0;
}
void SExpString::SerializeToLine(TextBuffer* buffer) const {
buffer->AddChar('"');
buffer->AddEscapedString(value());
buffer->AddChar('"');
void SExpString::SerializeToLine(BaseTextBuffer* buffer) const {
TextBuffer buf(80);
buf.AddChar('"');
buf.AddEscapedString(value());
buf.AddChar('"');
buffer->AddString(buf.buffer());
}
bool SExpSymbol::Equals(SExpression* sexp) const {
@ -95,7 +94,7 @@ bool SExpSymbol::Equals(const char* str) const {
return strcmp(value(), str) == 0;
}
void SExpSymbol::SerializeToLine(TextBuffer* buffer) const {
void SExpSymbol::SerializeToLine(BaseTextBuffer* buffer) const {
buffer->AddString(value());
}
@ -128,9 +127,9 @@ const char* const SExpList::kElemIndent = " ";
const char* const SExpList::kExtraIndent = " ";
static intptr_t HandleLineBreaking(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
SExpression* element,
TextBuffer* line_buffer,
BaseTextBuffer* line_buffer,
const char* sub_indent,
intptr_t width,
bool leading_space,
@ -141,7 +140,7 @@ static intptr_t HandleLineBreaking(Zone* zone,
if ((leading_length + single_line_width) < remaining) {
if (leading_space) buffer->AddChar(' ');
buffer->AddString(line_buffer->buf());
buffer->AddString(line_buffer->buffer());
line_buffer->Clear();
return remaining - (leading_length + single_line_width);
}
@ -150,7 +149,7 @@ static intptr_t HandleLineBreaking(Zone* zone,
const intptr_t line_used = buffer->length() - old_length + 1;
remaining = width - line_used;
if ((single_line_width < remaining) || element->IsAtom()) {
buffer->AddString(line_buffer->buf());
buffer->AddString(line_buffer->buffer());
line_buffer->Clear();
return remaining - single_line_width;
}
@ -161,7 +160,7 @@ static intptr_t HandleLineBreaking(Zone* zone,
// Assumes that we are starting on a line after [indent] amount of space.
void SExpList::SerializeTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
intptr_t width) const {
TextBuffer single_line(width);
@ -177,14 +176,14 @@ void SExpList::SerializeTo(Zone* zone,
if (!extra_info_.IsEmpty()) {
SerializeExtraInfoToLine(&single_line);
if (single_line.length() < remaining - 1) {
buffer->Printf(" %s", single_line.buf());
buffer->Printf(" %s", single_line.buffer());
} else {
const intptr_t old_length = buffer->length();
buffer->Printf("\n%s", sub_indent);
const intptr_t line_used = buffer->length() - old_length + 1;
remaining = width - line_used;
if (single_line.length() < remaining) {
buffer->AddString(single_line.buf());
buffer->AddString(single_line.buffer());
} else {
SerializeExtraInfoTo(zone, buffer, sub_indent, width);
}
@ -193,7 +192,7 @@ void SExpList::SerializeTo(Zone* zone,
buffer->AddChar(')');
}
void SExpList::SerializeToLine(TextBuffer* buffer) const {
void SExpList::SerializeToLine(BaseTextBuffer* buffer) const {
buffer->AddChar('(');
for (intptr_t i = 0; i < contents_.length(); i++) {
if (i != 0) buffer->AddChar(' ');
@ -207,7 +206,7 @@ void SExpList::SerializeToLine(TextBuffer* buffer) const {
}
void SExpList::SerializeExtraInfoTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
int width) const {
const char* sub_indent = OS::SCreate(zone, "%s%s", indent, kExtraIndent);
@ -226,7 +225,7 @@ void SExpList::SerializeExtraInfoTo(Zone* zone,
buffer->Printf("\n%s}", indent);
}
void SExpList::SerializeExtraInfoToLine(TextBuffer* buffer) const {
void SExpList::SerializeExtraInfoToLine(BaseTextBuffer* buffer) const {
buffer->AddString("{");
auto it = ExtraIterator();
while (auto kv = it.Next()) {

View file

@ -81,10 +81,10 @@ class SExpression : public ZoneAllocated {
virtual const char* DebugName() const = 0;
virtual bool Equals(SExpression* sexp) const = 0;
virtual void SerializeTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
intptr_t width = 80) const = 0;
virtual void SerializeToLine(TextBuffer* buffer) const = 0;
virtual void SerializeToLine(BaseTextBuffer* buffer) const = 0;
private:
// Starting character position of the s-expression in the original
@ -100,7 +100,7 @@ class SExpAtom : public SExpression {
virtual const SExpAtom* AsAtom() const { return this; }
// No atoms have sub-elements, so they always print to a single line.
virtual void SerializeTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
intptr_t width = 80) const {
SerializeToLine(buffer);
@ -124,7 +124,7 @@ class SExpAtom : public SExpression {
value_type value() const { return val_; } \
virtual bool Equals(SExpression* sexp) const; \
bool Equals(value_type val) const; \
virtual void SerializeToLine(TextBuffer* buffer) const; \
virtual void SerializeToLine(BaseTextBuffer* buffer) const; \
DEFINE_S_EXPRESSION_TYPE_CHECK(name) \
private: \
value_type const val_; \
@ -168,20 +168,20 @@ class SExpList : public SExpression {
DEFINE_S_EXPRESSION_TYPE_CHECK(List)
virtual bool Equals(SExpression* sexp) const;
virtual void SerializeTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
intptr_t width = 80) const;
virtual void SerializeToLine(TextBuffer* buffer) const;
virtual void SerializeToLine(BaseTextBuffer* buffer) const;
private:
static const char* const kElemIndent;
static const char* const kExtraIndent;
void SerializeExtraInfoTo(Zone* zone,
TextBuffer* buffer,
BaseTextBuffer* buffer,
const char* indent,
int width) const;
void SerializeExtraInfoToLine(TextBuffer* buffer) const;
void SerializeExtraInfoToLine(BaseTextBuffer* buffer) const;
ZoneGrowableArray<SExpression*> contents_;
ExtraInfoHashMap extra_info_;

View file

@ -191,13 +191,13 @@ ISOLATE_UNIT_TEST_CASE(DeserializeSExpRoundTrip) {
TextBuffer buf(100);
sexp->SerializeTo(zone, &buf, "", 9999);
SExpression* round_trip = SExpression::FromCString(zone, buf.buf());
SExpression* round_trip = SExpression::FromCString(zone, buf.buffer());
CheckDeserializedSExpParts(round_trip);
EXPECT(sexp->Equals(round_trip));
char* const old_serialization = buf.Steal();
round_trip->SerializeTo(zone, &buf, "", 9999);
char* const new_serialization = buf.buf();
char* const new_serialization = buf.buffer();
EXPECT_STREQ(old_serialization, new_serialization);
free(old_serialization);
}

View file

@ -562,7 +562,7 @@ COMPILER_PASS(SerializeGraph, {
FlowGraphSerializer::SerializeToBuffer(stack_zone.GetZone(), flow_graph,
&buffer);
file_write(buffer.buf(), buffer.length(), stream);
file_write(buffer.buffer(), buffer.length(), stream);
}
});
#endif

View file

@ -855,7 +855,7 @@ static void PrintLLVMConstantPool(Thread* T, Isolate* I) {
}
b.AddString("End of function pool.\n\n");
}
THR_Print("%s", b.buf());
THR_Print("%s", b.buffer());
}
#endif

View file

@ -774,7 +774,7 @@ const char* Dwarf::Deobfuscate(const char* cstr) {
i += offset;
}
if (!changed) return cstr;
return OS::SCreate(zone_, "%s", buffer.buf());
return OS::SCreate(zone_, "%s", buffer.buffer());
}
Trie<const char>* Dwarf::CreateReverseObfuscationTrie(Zone* zone) {

View file

@ -15,9 +15,9 @@ namespace dart {
TEST_CASE(JSON_TextBuffer) {
TextBuffer w(5); // Small enough to make buffer grow at least once.
w.Printf("{ \"%s\" : %d", "length", 175);
EXPECT_STREQ("{ \"length\" : 175", w.buf());
EXPECT_STREQ("{ \"length\" : 175", w.buffer());
w.Printf(", \"%s\" : \"%s\" }", "command", "stopIt");
EXPECT_STREQ("{ \"length\" : 175, \"command\" : \"stopIt\" }", w.buf());
EXPECT_STREQ("{ \"length\" : 175, \"command\" : \"stopIt\" }", w.buffer());
}
TEST_CASE(JSON_JSONStream_Primitives) {

View file

@ -69,7 +69,7 @@ void JSONWriter::OpenObject(const char* property_name) {
void JSONWriter::UncloseObject() {
intptr_t len = buffer_.length();
ASSERT(len > 0);
ASSERT(buffer_.buf()[len - 1] == '}');
ASSERT(buffer_.buffer()[len - 1] == '}');
open_objects_++;
buffer_.set_length(len - 1);
}
@ -315,7 +315,7 @@ void JSONWriter::PrintCommaIfNeeded() {
}
bool JSONWriter::NeedComma() {
const char* buffer = buffer_.buf();
const char* buffer = buffer_.buffer();
intptr_t length = buffer_.length();
if (length == 0) {
return false;

View file

@ -17,7 +17,7 @@ class JSONWriter : ValueObject {
explicit JSONWriter(intptr_t buf_size = 256);
TextBuffer* buffer() { return &buffer_; }
const char* ToCString() { return buffer_.buf(); }
const char* ToCString() { return buffer_.buffer(); }
void Steal(char** buffer, intptr_t* buffer_length);

View file

@ -8,6 +8,7 @@
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/text_buffer.h"
#include "platform/unaligned.h"
#include "platform/unicode.h"
#include "vm/bit_vector.h"
@ -183,7 +184,7 @@ ClassPtr Object::weak_serialization_reference_class_ =
const double MegamorphicCache::kLoadFactor = 0.50;
static void AppendSubString(ZoneTextBuffer* buffer,
static void AppendSubString(BaseTextBuffer* buffer,
const char* name,
intptr_t start_pos,
intptr_t len) {
@ -5941,7 +5942,7 @@ void TypeArguments::PrintSubvectorName(
intptr_t from_index,
intptr_t len,
NameVisibility name_visibility,
ZoneTextBuffer* printer,
BaseTextBuffer* printer,
NameDisambiguation name_disambiguation /* = NameDisambiguation::kNo */)
const {
printer->AddString("<");
@ -8900,7 +8901,7 @@ StringPtr Function::UserVisibleSignature() const {
void Function::PrintSignatureParameters(Thread* thread,
Zone* zone,
NameVisibility name_visibility,
ZoneTextBuffer* printer) const {
BaseTextBuffer* printer) const {
AbstractType& param_type = AbstractType::Handle(zone);
const intptr_t num_params = NumParameters();
const intptr_t num_fixed_params = num_fixed_parameters();
@ -8941,7 +8942,7 @@ void Function::PrintSignatureParameters(Thread* thread,
if (num_opt_named_params > 0) {
name = ParameterNameAt(i);
printer->AddString(" ");
printer->AddString(name);
printer->AddString(name.ToCString());
}
if (i != (num_params - 1)) {
printer->AddString(", ");
@ -8993,7 +8994,7 @@ intptr_t Function::ComputeClosureHash() const {
}
void Function::PrintSignature(NameVisibility name_visibility,
ZoneTextBuffer* printer) const {
BaseTextBuffer* printer) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
@ -9279,7 +9280,7 @@ StringPtr Function::QualifiedUserVisibleName() const {
}
void Function::PrintName(const NameFormattingParams& params,
ZoneTextBuffer* printer) const {
BaseTextBuffer* printer) const {
// If |this| is the generated asynchronous body closure, use the
// name of the parent function.
Function& fun = Function::Handle(raw());
@ -19220,14 +19221,14 @@ StringPtr AbstractType::UserVisibleName() const {
void AbstractType::PrintName(
NameVisibility name_visibility,
ZoneTextBuffer* printer,
BaseTextBuffer* printer,
NameDisambiguation name_disambiguation /* = NameDisambiguation::kNo */)
const {
ASSERT(name_visibility != kScrubbedName);
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Class& cls = Class::Handle(zone);
String& class_name = String::Handle(zone);
String& name_str = String::Handle(zone);
if (IsTypeParameter()) {
const TypeParameter& param = TypeParameter::Cast(*this);
@ -19249,7 +19250,8 @@ void AbstractType::PrintName(
}
}
printer->AddString(String::Handle(zone, param.name()));
name_str = param.name();
printer->AddString(name_str.ToCString());
printer->AddString(NullabilitySuffix(name_visibility));
return;
}
@ -19275,10 +19277,10 @@ void AbstractType::PrintName(
}
// Instead of printing the actual signature, use the typedef name with
// its type arguments, if any.
class_name = cls.Name(); // Typedef name.
name_str = cls.Name(); // Typedef name.
if (!IsFinalized() || IsBeingFinalized()) {
// TODO(regis): Check if this is dead code.
printer->AddString(class_name);
printer->AddString(name_str.ToCString());
printer->AddString(NullabilitySuffix(name_visibility));
return;
}
@ -19287,8 +19289,8 @@ void AbstractType::PrintName(
// Do not print the full vector, but only the declared type parameters.
num_type_params = cls.NumTypeParameters();
if (name_visibility == kInternalName) {
class_name = cls.Name();
printer->AddString(class_name);
name_str = cls.Name();
printer->AddString(name_str.ToCString());
} else {
ASSERT(name_visibility == kUserVisibleName);
// Map internal types to their corresponding public interfaces.
@ -21021,18 +21023,21 @@ void TypeParameter::set_flags(uint8_t flags) const {
const char* TypeParameter::ToCString() const {
Thread* thread = Thread::Current();
ZoneTextBuffer printer(thread->zone());
auto& name_str = String::Handle(thread->zone(), name());
printer.Printf("TypeParameter: name ");
printer.AddString(String::Handle(name()));
printer.AddString(name_str.ToCString());
printer.AddString(NullabilitySuffix(kInternalName));
printer.Printf("; index: %" Pd ";", index());
if (IsFunctionTypeParameter()) {
const Function& function = Function::Handle(parameterized_function());
printer.Printf(" function: ");
printer.AddString(String::Handle(function.name()));
name_str = function.name();
printer.AddString(name_str.ToCString());
} else {
const Class& cls = Class::Handle(parameterized_class());
printer.Printf(" class: ");
printer.AddString(String::Handle(cls.Name()));
name_str = cls.Name();
printer.AddString(name_str.ToCString());
}
printer.Printf("; bound: ");
const AbstractType& upper_bound = AbstractType::Handle(bound());
@ -24320,7 +24325,7 @@ StackTracePtr StackTrace::New(const Array& code_array,
#if defined(DART_PRECOMPILED_RUNTIME)
// Prints the best representation(s) for the call address.
static void PrintNonSymbolicStackFrameBody(ZoneTextBuffer* buffer,
static void PrintNonSymbolicStackFrameBody(BaseTextBuffer* buffer,
uword call_addr,
uword isolate_instructions,
uword vm_instructions,
@ -24356,12 +24361,12 @@ static void PrintNonSymbolicStackFrameBody(ZoneTextBuffer* buffer,
}
#endif
static void PrintSymbolicStackFrameIndex(ZoneTextBuffer* buffer,
static void PrintSymbolicStackFrameIndex(BaseTextBuffer* buffer,
intptr_t frame_index) {
buffer->Printf("#%-6" Pd "", frame_index);
}
static void PrintSymbolicStackFrameBody(ZoneTextBuffer* buffer,
static void PrintSymbolicStackFrameBody(BaseTextBuffer* buffer,
const char* function_name,
const char* url,
intptr_t line = -1,
@ -24377,7 +24382,7 @@ static void PrintSymbolicStackFrameBody(ZoneTextBuffer* buffer,
}
static void PrintSymbolicStackFrame(Zone* zone,
ZoneTextBuffer* buffer,
BaseTextBuffer* buffer,
const Function& function,
TokenPosition token_pos,
intptr_t frame_index) {

View file

@ -71,7 +71,7 @@ REUSABLE_HANDLE_LIST(REUSABLE_FORWARD_DECLARATION)
#undef REUSABLE_FORWARD_DECLARATION
class Symbols;
class ZoneTextBuffer;
class BaseTextBuffer;
#if defined(DEBUG)
#define CHECK_HANDLE() CheckHandle();
@ -2478,7 +2478,7 @@ class Function : public Object {
const char* NameCString(NameVisibility name_visibility) const;
void PrintName(const NameFormattingParams& params,
ZoneTextBuffer* printer) const;
BaseTextBuffer* printer) const;
StringPtr QualifiedScrubbedName() const;
StringPtr QualifiedUserVisibleName() const;
@ -2552,7 +2552,7 @@ class Function : public Object {
StringPtr UserVisibleSignature() const;
void PrintSignature(NameVisibility name_visibility,
ZoneTextBuffer* printer) const;
BaseTextBuffer* printer) const;
// Returns true if the signature of this function is instantiated, i.e. if it
// does not involve generic parameter types or generic result type.
@ -3792,7 +3792,7 @@ class Function : public Object {
void PrintSignatureParameters(Thread* thread,
Zone* zone,
NameVisibility name_visibility,
ZoneTextBuffer* printer) const;
BaseTextBuffer* printer) const;
// Returns true if the type of the formal parameter at the given position in
// this function is contravariant with the type of the other formal parameter
@ -7583,7 +7583,7 @@ class TypeArguments : public Instance {
intptr_t from_index,
intptr_t len,
NameVisibility name_visibility,
ZoneTextBuffer* printer,
BaseTextBuffer* printer,
NameDisambiguation name_disambiguation = NameDisambiguation::kNo) const;
// Check if the subvector of length 'len' starting at 'from_index' of this
@ -7910,7 +7910,7 @@ class AbstractType : public Instance {
// type arguments, if any.
void PrintName(
NameVisibility visibility,
ZoneTextBuffer* printer,
BaseTextBuffer* printer,
NameDisambiguation name_disambiguation = NameDisambiguation::kNo) const;
// Add the class name and URI of each occuring type to the uris

View file

@ -643,7 +643,7 @@ void HeapSnapshotWriter::Flush(bool last) {
}
Service::SendEventWithData(Service::heapsnapshot_stream.id(), "HeapSnapshot",
kMetadataReservation, js.buffer()->buf(),
kMetadataReservation, js.buffer()->buffer(),
js.buffer()->length(), buffer_, size_);
buffer_ = nullptr;
size_ = 0;

View file

@ -1142,7 +1142,7 @@ void Service::HandleEvent(ServiceEvent* event) {
event->stream_info()->consumer() != nullptr) {
auto length = js.buffer()->length();
event->stream_info()->consumer()(
reinterpret_cast<uint8_t*>(js.buffer()->buf()), length);
reinterpret_cast<uint8_t*>(js.buffer()->buffer()), length);
}
}
@ -1623,8 +1623,9 @@ void Service::SendEchoEvent(Isolate* isolate, const char* text) {
data[reservation + 0] = 0;
data[reservation + 1] = 128;
data[reservation + 2] = 255;
SendEventWithData(echo_stream.id(), "_Echo", reservation, js.buffer()->buf(),
js.buffer()->length(), data, data_size);
SendEventWithData(echo_stream.id(), "_Echo", reservation,
js.buffer()->buffer(), js.buffer()->length(), data,
data_size);
}
static bool TriggerEchoEvent(Thread* thread, JSONStream* js) {

View file

@ -14,51 +14,13 @@
namespace dart {
ZoneTextBuffer::ZoneTextBuffer(Zone* zone, intptr_t initial_capacity)
: zone_(zone), buffer_(NULL), length_(0), capacity_(0) {
: zone_(zone) {
ASSERT(initial_capacity > 0);
buffer_ = reinterpret_cast<char*>(zone->Alloc<char>(initial_capacity));
capacity_ = initial_capacity;
buffer_[length_] = '\0';
}
intptr_t ZoneTextBuffer::Printf(const char* format, ...) {
va_list args;
va_start(args, format);
intptr_t remaining = capacity_ - length_;
ASSERT(remaining >= 0);
intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args);
va_end(args);
if (len >= remaining) {
EnsureCapacity(len);
remaining = capacity_ - length_;
ASSERT(remaining > len);
va_list args2;
va_start(args2, format);
intptr_t len2 =
Utils::VSNPrint(buffer_ + length_, remaining, format, args2);
va_end(args2);
ASSERT(len == len2);
}
length_ += len;
buffer_[length_] = '\0';
return len;
}
void ZoneTextBuffer::AddChar(char ch) {
EnsureCapacity(sizeof(ch));
buffer_[length_] = ch;
length_++;
buffer_[length_] = '\0';
}
void ZoneTextBuffer::AddString(const char* s) {
Printf("%s", s);
}
void ZoneTextBuffer::AddString(const String& s) {
Printf("%s", s.ToCString());
}
void ZoneTextBuffer::Clear() {
const intptr_t initial_capacity = 64;
buffer_ = reinterpret_cast<char*>(zone_->Alloc<char>(initial_capacity));

View file

@ -5,6 +5,7 @@
#ifndef RUNTIME_VM_ZONE_TEXT_BUFFER_H_
#define RUNTIME_VM_ZONE_TEXT_BUFFER_H_
#include "platform/text_buffer.h"
#include "vm/allocation.h"
#include "vm/globals.h"
@ -13,29 +14,20 @@ namespace dart {
class String;
class Zone;
// TextBuffer maintains a dynamic character buffer with a printf-style way to
// append text.
class ZoneTextBuffer : ValueObject {
// ZoneTextBuffer allocates the character buffer in the given zone. Thus,
// pointers returned by buffer() have the same lifetime as the zone.
class ZoneTextBuffer : public BaseTextBuffer {
public:
explicit ZoneTextBuffer(Zone* zone, intptr_t initial_capacity = 64);
~ZoneTextBuffer() {}
intptr_t Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
void AddChar(char ch);
void AddString(const char* s);
void AddString(const String& s);
char* buffer() { return buffer_; }
intptr_t length() const { return length_; }
// Allocates a new internal buffer. Thus, the contents of buffers returned by
// previous calls to buffer() are no longer affected by this object.
void Clear();
private:
void EnsureCapacity(intptr_t len);
Zone* zone_;
char* buffer_;
intptr_t length_;
intptr_t capacity_;
};
} // namespace dart