buffer: fix buffer alignment restriction

Recent phantom weakness API changes to buffer, ebbbc5a, ending up
introducing an alignment restriction on the native buffer pointers.
It turns out that there are uses in the modules ecosystem that rely
on the ability to create buffers with unaligned pointers (e.g.
node-ffi).

It turns out there is a simpler solution possible here. As a side
effect this also removes the need to have to reserve the first
internal field on buffers.

PR-URL: https://github.com/nodejs/node/pull/5752
Reviewed-By: trevnorris - Trevor Norris <trev.norris@gmail.com>
Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Ali Ijaz Sheikh 2016-03-16 17:46:01 -07:00
parent 5f1eb434ee
commit 73fc440870
2 changed files with 15 additions and 18 deletions

View File

@ -87,17 +87,20 @@ class CallbackInfo {
static inline CallbackInfo* New(Isolate* isolate,
Local<ArrayBuffer> object,
FreeCallback callback,
char* data,
void* hint = 0);
private:
static void WeakCallback(const WeakCallbackInfo<CallbackInfo>&);
inline void WeakCallback(Isolate* isolate, char* const data);
inline void WeakCallback(Isolate* isolate);
inline CallbackInfo(Isolate* isolate,
Local<ArrayBuffer> object,
FreeCallback callback,
char* data,
void* hint);
~CallbackInfo();
Persistent<ArrayBuffer> persistent_;
FreeCallback const callback_;
char* const data_;
void* const hint_;
DISALLOW_COPY_AND_ASSIGN(CallbackInfo);
};
@ -111,27 +114,27 @@ void CallbackInfo::Free(char* data, void*) {
CallbackInfo* CallbackInfo::New(Isolate* isolate,
Local<ArrayBuffer> object,
FreeCallback callback,
char* data,
void* hint) {
return new CallbackInfo(isolate, object, callback, hint);
return new CallbackInfo(isolate, object, callback, data, hint);
}
CallbackInfo::CallbackInfo(Isolate* isolate,
Local<ArrayBuffer> object,
FreeCallback callback,
char* data,
void* hint)
: persistent_(isolate, object),
callback_(callback),
data_(data),
hint_(hint) {
ArrayBuffer::Contents obj_c = object->GetContents();
char* const data = static_cast<char*>(obj_c.Data());
CHECK_EQ(data_, static_cast<char*>(obj_c.Data()));
if (object->ByteLength() != 0)
CHECK_NE(data, nullptr);
CHECK_NE(data_, nullptr);
object->SetAlignedPointerInInternalField(kBufferInternalFieldIndex, data);
persistent_.SetWeak(this, WeakCallback,
v8::WeakCallbackType::kInternalFields);
persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
persistent_.SetWrapperClassId(BUFFER_ID);
persistent_.MarkIndependent();
isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this));
@ -146,15 +149,13 @@ CallbackInfo::~CallbackInfo() {
void CallbackInfo::WeakCallback(
const WeakCallbackInfo<CallbackInfo>& data) {
CallbackInfo* self = data.GetParameter();
self->WeakCallback(
data.GetIsolate(),
static_cast<char*>(data.GetInternalField(kBufferInternalFieldIndex)));
self->WeakCallback(data.GetIsolate());
delete self;
}
void CallbackInfo::WeakCallback(Isolate* isolate, char* const data) {
callback_(data, hint_);
void CallbackInfo::WeakCallback(Isolate* isolate) {
callback_(data_, hint_);
int64_t change_in_bytes = -static_cast<int64_t>(sizeof(*this));
isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
}
@ -370,7 +371,7 @@ MaybeLocal<Object> New(Environment* env,
if (!mb.FromMaybe(false))
return Local<Object>();
CallbackInfo::New(env->isolate(), ab, callback, hint);
CallbackInfo::New(env->isolate(), ab, callback, data, hint);
return scope.Escape(ui);
}

View File

@ -13,10 +13,6 @@ namespace Buffer {
static const unsigned int kMaxLength =
sizeof(int32_t) == sizeof(intptr_t) ? 0x3fffffff : 0x7fffffff;
// Buffers have two internal fields, the first of which is reserved for use by
// Node.
static const unsigned int kBufferInternalFieldIndex = 0;
NODE_EXTERN typedef void (*FreeCallback)(char* data, void* hint);
NODE_EXTERN bool HasInstance(v8::Local<v8::Value> val);