From 5bc4efe8207b21a5884f62597af2dc4ff564a8d7 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 7 Sep 2010 23:48:42 -0700 Subject: [PATCH] Remove blobs, simplify SlowBuffer Implement SlowBuffer.prototype.slice in js --- lib/buffer.js | 14 +++++- src/node_buffer.cc | 118 ++++----------------------------------------- src/node_buffer.h | 7 ++- 3 files changed, 25 insertions(+), 114 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 351f4eac2e..f6fc756101 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -79,6 +79,19 @@ SlowBuffer.prototype.write = function (string, offset, encoding) { }; +// slice(start, end) +SlowBuffer.prototype.slice = function (start, end) { + if (end > this.length) { + throw new Error("oob"); + } + if (start > end) { + throw new Error("oob"); + } + + return new Buffer(this, end - start, +start); +}; + + // Buffer function Buffer (subject, encoding, offset) { @@ -318,4 +331,3 @@ Buffer.prototype.slice = function (start, end) { return new Buffer(this.parent, end - start, +start + this.offset); }; - diff --git a/src/node_buffer.cc b/src/node_buffer.cc index b85bae0098..f9d99b56c1 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -43,49 +43,6 @@ static Persistent write_sym; Persistent Buffer::constructor_template; -// Each javascript Buffer object is backed by a Blob object. -// the Blob is just a C-level chunk of bytes. -// It has a reference count. -struct Blob_ { - unsigned int refs; - size_t length; - char *data; -}; -typedef struct Blob_ Blob; - - -static inline Blob * blob_new(size_t length) { - Blob * blob = (Blob*) malloc(sizeof(Blob)); - if (!blob) return NULL; - - blob->data = (char*) malloc(length); - if (!blob->data) { - free(blob); - return NULL; - } - - V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Blob) + length); - blob->length = length; - blob->refs = 0; - return blob; -} - - -static inline void blob_ref(Blob *blob) { - blob->refs++; -} - - -static inline void blob_unref(Blob *blob) { - assert(blob->refs > 0); - if (--blob->refs == 0) { - //fprintf(stderr, "free %d bytes\n", blob->length); - V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Blob) + blob->length)); - free(blob->data); - free(blob); - } -} - static inline size_t base64_decoded_size(const char *src, size_t size) { const char *const end = src + size; const int remainder = size % 4; @@ -188,22 +145,6 @@ Handle Buffer::New(const Arguments &args) { size_t length = args[0]->Uint32Value(); buffer = new Buffer(length); - } else if (args[0]->IsArray()) { - Local a = Local::Cast(args[0]); - buffer = new Buffer(a->Length()); - char *p = buffer->data(); - for (int i = 0; i < a->Length(); i++) { - p[i] = a->Get(i)->Uint32Value(); - } - } else if (args[0]->IsString()) { - buffer = new Buffer(node::ByteLength(args[0]->ToString(), ParseEncoding(args[1], UTF8))); - - } else if (Buffer::HasInstance(args[0]) && args.Length() > 2) { - // var slice = new Buffer(buffer, 123, 130); - // args: parent, start, end - Buffer *parent = ObjectWrap::Unwrap(args[0]->ToObject()); - SLICE_ARGS(args[1], args[2]) - buffer = new Buffer(parent, start, end); } else { return ThrowException(Exception::TypeError(String::New("Bad argument"))); } @@ -219,40 +160,23 @@ Handle Buffer::New(const Arguments &args) { Buffer::Buffer(size_t length) : ObjectWrap() { - blob_ = blob_new(length); off_ = 0; length_ = length; + data_ = new char[length_]; - blob_ref(blob_); - - V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer)); -} - - -Buffer::Buffer(Buffer *parent, size_t start, size_t end) : ObjectWrap() { - blob_ = parent->blob_; - assert(blob_->refs > 0); - blob_ref(blob_); - - assert(start <= end); - off_ = parent->off_ + start; - length_ = end - start; - assert(length_ <= parent->length_); - - V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer)); + V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer) + length_); } Buffer::~Buffer() { - assert(blob_->refs > 0); //fprintf(stderr, "free buffer (%d refs left)\n", blob_->refs); - blob_unref(blob_); - V8::AdjustAmountOfExternalAllocatedMemory(-static_cast(sizeof(Buffer))); + delete data_; + V8::AdjustAmountOfExternalAllocatedMemory(-(sizeof(Buffer) + length_)); } char* Buffer::data() { - return blob_->data + off_; + return data_; } @@ -275,14 +199,6 @@ Handle Buffer::AsciiSlice(const Arguments &args) { Buffer *parent = ObjectWrap::Unwrap(args.This()); SLICE_ARGS(args[0], args[1]) -#if 0 - AsciiSliceExt *ext = new AsciiSliceExt(parent, start, end); - Local string = String::NewExternal(ext); - // There should be at least two references to the blob now - the parent - // and the slice. - assert(parent->blob_->refs >= 2); -#endif - char* data = parent->data() + start; Local string = String::New(data, end - start); @@ -386,15 +302,6 @@ Handle Buffer::Base64Slice(const Arguments &args) { } -Handle Buffer::Slice(const Arguments &args) { - HandleScope scope; - Local argv[3] = { args.This(), args[0], args[1] }; - Local slice = - constructor_template->GetFunction()->NewInstance(3, argv); - return scope.Close(slice); -} - - // var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd); Handle Buffer::Copy(const Arguments &args) { HandleScope scope; @@ -443,16 +350,10 @@ Handle Buffer::Copy(const Arguments &args) { source->length() - source_start); - if (target->blob_ == source->blob_) { - // need to use slightly slower memmove is the ranges might overlap - memmove((void*)(target->data() + target_start), - (const void*)(source->data() + source_start), - to_copy); - } else { - memcpy((void*)(target->data() + target_start), - (const void*)(source->data() + source_start), - to_copy); - } + // need to use slightly slower memmove is the ranges might overlap + memmove((void*)(target->data() + target_start), + (const void*)(source->data() + source_start), + to_copy); return scope.Close(Integer::New(to_copy)); } @@ -684,7 +585,6 @@ void Buffer::Initialize(Handle target) { NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice); NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice); NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice); - NODE_SET_PROTOTYPE_METHOD(constructor_template, "slice", Buffer::Slice); // TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice); // copy NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice); diff --git a/src/node_buffer.h b/src/node_buffer.h index f538f75099..b55b1d3ec2 100644 --- a/src/node_buffer.h +++ b/src/node_buffer.h @@ -41,7 +41,6 @@ class Buffer : public ObjectWrap { char* data(); size_t length() const { return length_; } - struct Blob_* blob() const { return blob_; } int AsciiWrite(char *string, int offset, int length); int Utf8Write(char *string, int offset, int length); @@ -67,9 +66,9 @@ class Buffer : public ObjectWrap { Buffer(size_t length); Buffer(Buffer *parent, size_t start, size_t end); - size_t off_; // offset inside blob_ - size_t length_; // length inside blob_ - struct Blob_ *blob_; + size_t off_; + size_t length_; + char* data_; };