From d75f5c8d0ecdf400933b601ed07b064dbfe27bf6 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Mon, 1 Jun 2015 12:29:17 -0600 Subject: [PATCH] buffer: finish implementing FreeCallback Passing a FreeCallback to Buffer::New() now uses externalized ArrayBuffer's. PR-URL: https://github.com/nodejs/io.js/pull/1825 Reviewed-By: Ben Noordhuis --- src/node_buffer.cc | 120 +++++++++++++++++++++++++++++++++++++++++---- src/node_buffer.h | 8 +-- 2 files changed, 116 insertions(+), 12 deletions(-) diff --git a/src/node_buffer.cc b/src/node_buffer.cc index d3398075d06412..57268e749da6e4 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -13,6 +13,8 @@ #include #include +#define BUFFER_ID 0xB0E4 + #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define CHECK_NOT_OOB(r) \ @@ -73,12 +75,103 @@ using v8::Isolate; using v8::Local; using v8::Number; using v8::Object; +using v8::Persistent; using v8::String; using v8::Uint32; using v8::Uint8Array; using v8::Value; +using v8::WeakCallbackData; + + +class CallbackInfo { + public: + static inline void Free(char* data, void* hint); + static inline CallbackInfo* New(Isolate* isolate, + Handle object, + FreeCallback callback, + void* hint = 0); + inline void Dispose(Isolate* isolate); + inline Persistent* persistent(); + private: + static void WeakCallback(const WeakCallbackData&); + inline void WeakCallback(Isolate* isolate, Local object); + inline CallbackInfo(Isolate* isolate, + Handle object, + FreeCallback callback, + void* hint); + ~CallbackInfo(); + Persistent persistent_; + FreeCallback const callback_; + void* const hint_; + DISALLOW_COPY_AND_ASSIGN(CallbackInfo); +}; + + +void CallbackInfo::Free(char* data, void*) { + ::free(data); +} + + +CallbackInfo* CallbackInfo::New(Isolate* isolate, + Handle object, + FreeCallback callback, + void* hint) { + return new CallbackInfo(isolate, object, callback, hint); +} + + +void CallbackInfo::Dispose(Isolate* isolate) { + WeakCallback(isolate, PersistentToLocal(isolate, persistent_)); +} + + +Persistent* CallbackInfo::persistent() { + return &persistent_; +} + + +CallbackInfo::CallbackInfo(Isolate* isolate, + Handle object, + FreeCallback callback, + void* hint) + : persistent_(isolate, object), + callback_(callback), + hint_(hint) { + persistent_.SetWeak(this, WeakCallback); + persistent_.SetWrapperClassId(BUFFER_ID); + persistent_.MarkIndependent(); + isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); +} + + +CallbackInfo::~CallbackInfo() { + persistent_.Reset(); +} + + +void CallbackInfo::WeakCallback( + const WeakCallbackData& data) { + data.GetParameter()->WeakCallback(data.GetIsolate(), data.GetValue()); +} +void CallbackInfo::WeakCallback(Isolate* isolate, Local object) { + ARGS_THIS_DEC(obj); + SPREAD_ARG(object, obj); + CHECK_EQ(obj_offset, 0); + CHECK_EQ(obj_c.ByteLength(), obj_length); + + obj->Buffer()->Neuter(); + callback_(obj_data, hint_); + int64_t change_in_bytes = -static_cast(sizeof(*this)); + isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); + + delete this; +} + + +// Buffer methods + bool HasInstance(Handle val) { return val->IsObject() && HasInstance(val.As()); } @@ -277,7 +370,7 @@ Local New(Environment* env, const char* data, size_t length) { Local New(Isolate* isolate, char* data, size_t length, - smalloc::FreeCallback callback, + FreeCallback callback, void* hint) { Environment* env = Environment::GetCurrent(isolate); EscapableHandleScope handle_scope(env->isolate()); @@ -289,19 +382,28 @@ Local New(Isolate* isolate, Local New(Environment* env, char* data, size_t length, - smalloc::FreeCallback callback, + FreeCallback callback, void* hint) { EscapableHandleScope scope(env->isolate()); - // TODO(trevnorris): IMPLEMENT - CHECK_LE(length, kMaxLength); - - Local arg = Uint32::NewFromUnsigned(env->isolate(), length); - Local obj = env->buffer_constructor_function()->NewInstance(1, &arg); + if (using_old_buffer) { + CHECK_LE(length, kMaxLength); + Local arg = Uint32::NewFromUnsigned(env->isolate(), length); + Local obj = + env->buffer_constructor_function()->NewInstance(1, &arg); + smalloc::Alloc(env, obj, data, length, callback, hint); + return scope.Escape(obj); + } - smalloc::Alloc(env, obj, data, length, callback, hint); + if (!IsValidSmi(length)) { + return Local(); + } - return scope.Escape(obj); + Local ab = ArrayBuffer::New(env->isolate(), data, length); + Local ui = Uint8Array::New(ab, 0, length); + ui->SetPrototype(env->buffer_prototype_object()); + CallbackInfo::New(env->isolate(), ui, callback, hint); + return scope.Escape(ui); } diff --git a/src/node_buffer.h b/src/node_buffer.h index 4b1b2cd8591ee1..568b68f83dbd5c 100644 --- a/src/node_buffer.h +++ b/src/node_buffer.h @@ -14,6 +14,8 @@ namespace Buffer { static const unsigned int kMaxLength = smalloc::kMaxLength; +NODE_EXTERN typedef void (*FreeCallback)(char* data, void* hint); + NODE_EXTERN bool HasInstance(v8::Handle val); NODE_EXTERN bool HasInstance(v8::Handle val); NODE_EXTERN char* Data(v8::Handle val); @@ -49,12 +51,12 @@ NODE_DEPRECATED("Use New(isolate, ...)", NODE_EXTERN v8::Local New(v8::Isolate* isolate, char* data, size_t length, - smalloc::FreeCallback callback, + FreeCallback callback, void* hint); NODE_DEPRECATED("Use New(isolate, ...)", inline v8::Local New(char* data, size_t length, - smalloc::FreeCallback callback, + FreeCallback callback, void* hint) { return New(v8::Isolate::GetCurrent(), data, length, callback, hint); }) @@ -93,7 +95,7 @@ v8::Local New(Environment* env, const char* data, size_t len); v8::Local New(Environment* env, char* data, size_t length, - smalloc::FreeCallback callback, + FreeCallback callback, void* hint); v8::Local Use(Environment* env, char* data, size_t length); #endif // defined(NODE_WANT_INTERNALS)