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:
parent
5f1eb434ee
commit
73fc440870
@ -87,17 +87,20 @@ class CallbackInfo {
|
|||||||
static inline CallbackInfo* New(Isolate* isolate,
|
static inline CallbackInfo* New(Isolate* isolate,
|
||||||
Local<ArrayBuffer> object,
|
Local<ArrayBuffer> object,
|
||||||
FreeCallback callback,
|
FreeCallback callback,
|
||||||
|
char* data,
|
||||||
void* hint = 0);
|
void* hint = 0);
|
||||||
private:
|
private:
|
||||||
static void WeakCallback(const WeakCallbackInfo<CallbackInfo>&);
|
static void WeakCallback(const WeakCallbackInfo<CallbackInfo>&);
|
||||||
inline void WeakCallback(Isolate* isolate, char* const data);
|
inline void WeakCallback(Isolate* isolate);
|
||||||
inline CallbackInfo(Isolate* isolate,
|
inline CallbackInfo(Isolate* isolate,
|
||||||
Local<ArrayBuffer> object,
|
Local<ArrayBuffer> object,
|
||||||
FreeCallback callback,
|
FreeCallback callback,
|
||||||
|
char* data,
|
||||||
void* hint);
|
void* hint);
|
||||||
~CallbackInfo();
|
~CallbackInfo();
|
||||||
Persistent<ArrayBuffer> persistent_;
|
Persistent<ArrayBuffer> persistent_;
|
||||||
FreeCallback const callback_;
|
FreeCallback const callback_;
|
||||||
|
char* const data_;
|
||||||
void* const hint_;
|
void* const hint_;
|
||||||
DISALLOW_COPY_AND_ASSIGN(CallbackInfo);
|
DISALLOW_COPY_AND_ASSIGN(CallbackInfo);
|
||||||
};
|
};
|
||||||
@ -111,27 +114,27 @@ void CallbackInfo::Free(char* data, void*) {
|
|||||||
CallbackInfo* CallbackInfo::New(Isolate* isolate,
|
CallbackInfo* CallbackInfo::New(Isolate* isolate,
|
||||||
Local<ArrayBuffer> object,
|
Local<ArrayBuffer> object,
|
||||||
FreeCallback callback,
|
FreeCallback callback,
|
||||||
|
char* data,
|
||||||
void* hint) {
|
void* hint) {
|
||||||
return new CallbackInfo(isolate, object, callback, hint);
|
return new CallbackInfo(isolate, object, callback, data, hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CallbackInfo::CallbackInfo(Isolate* isolate,
|
CallbackInfo::CallbackInfo(Isolate* isolate,
|
||||||
Local<ArrayBuffer> object,
|
Local<ArrayBuffer> object,
|
||||||
FreeCallback callback,
|
FreeCallback callback,
|
||||||
|
char* data,
|
||||||
void* hint)
|
void* hint)
|
||||||
: persistent_(isolate, object),
|
: persistent_(isolate, object),
|
||||||
callback_(callback),
|
callback_(callback),
|
||||||
|
data_(data),
|
||||||
hint_(hint) {
|
hint_(hint) {
|
||||||
ArrayBuffer::Contents obj_c = object->GetContents();
|
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)
|
if (object->ByteLength() != 0)
|
||||||
CHECK_NE(data, nullptr);
|
CHECK_NE(data_, nullptr);
|
||||||
|
|
||||||
object->SetAlignedPointerInInternalField(kBufferInternalFieldIndex, data);
|
persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter);
|
||||||
|
|
||||||
persistent_.SetWeak(this, WeakCallback,
|
|
||||||
v8::WeakCallbackType::kInternalFields);
|
|
||||||
persistent_.SetWrapperClassId(BUFFER_ID);
|
persistent_.SetWrapperClassId(BUFFER_ID);
|
||||||
persistent_.MarkIndependent();
|
persistent_.MarkIndependent();
|
||||||
isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this));
|
isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this));
|
||||||
@ -146,15 +149,13 @@ CallbackInfo::~CallbackInfo() {
|
|||||||
void CallbackInfo::WeakCallback(
|
void CallbackInfo::WeakCallback(
|
||||||
const WeakCallbackInfo<CallbackInfo>& data) {
|
const WeakCallbackInfo<CallbackInfo>& data) {
|
||||||
CallbackInfo* self = data.GetParameter();
|
CallbackInfo* self = data.GetParameter();
|
||||||
self->WeakCallback(
|
self->WeakCallback(data.GetIsolate());
|
||||||
data.GetIsolate(),
|
|
||||||
static_cast<char*>(data.GetInternalField(kBufferInternalFieldIndex)));
|
|
||||||
delete self;
|
delete self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CallbackInfo::WeakCallback(Isolate* isolate, char* const data) {
|
void CallbackInfo::WeakCallback(Isolate* isolate) {
|
||||||
callback_(data, hint_);
|
callback_(data_, hint_);
|
||||||
int64_t change_in_bytes = -static_cast<int64_t>(sizeof(*this));
|
int64_t change_in_bytes = -static_cast<int64_t>(sizeof(*this));
|
||||||
isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
|
isolate->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
|
||||||
}
|
}
|
||||||
@ -370,7 +371,7 @@ MaybeLocal<Object> New(Environment* env,
|
|||||||
if (!mb.FromMaybe(false))
|
if (!mb.FromMaybe(false))
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
|
|
||||||
CallbackInfo::New(env->isolate(), ab, callback, hint);
|
CallbackInfo::New(env->isolate(), ab, callback, data, hint);
|
||||||
return scope.Escape(ui);
|
return scope.Escape(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,10 +13,6 @@ namespace Buffer {
|
|||||||
static const unsigned int kMaxLength =
|
static const unsigned int kMaxLength =
|
||||||
sizeof(int32_t) == sizeof(intptr_t) ? 0x3fffffff : 0x7fffffff;
|
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 typedef void (*FreeCallback)(char* data, void* hint);
|
||||||
|
|
||||||
NODE_EXTERN bool HasInstance(v8::Local<v8::Value> val);
|
NODE_EXTERN bool HasInstance(v8::Local<v8::Value> val);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user