-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
buffer: construct Buffers in JS #2866
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
const binding = process.binding('buffer'); | ||
const internalUtil = require('internal/util'); | ||
const bindingObj = {}; | ||
|
||
exports.Buffer = Buffer; | ||
exports.SlowBuffer = SlowBuffer; | ||
|
@@ -14,11 +15,19 @@ Buffer.poolSize = 8 * 1024; | |
var poolSize, poolOffset, allocPool; | ||
|
||
|
||
binding.setupBufferJS(Buffer.prototype, bindingObj); | ||
const flags = bindingObj.flags; | ||
const kNoZeroFill = 0; | ||
|
||
|
||
function createPool() { | ||
poolSize = Buffer.poolSize; | ||
allocPool = binding.create(poolSize); | ||
flags[kNoZeroFill] = 1; | ||
allocPool = new Uint8Array(poolSize); | ||
Object.setPrototypeOf(allocPool, Buffer.prototype); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hahaha, this one is better! :) Are you afraid of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You sure about this? I have seen the disassembly output, and it looked like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was when |
||
poolOffset = 0; | ||
} | ||
createPool(); | ||
|
||
|
||
function alignPool() { | ||
|
@@ -46,30 +55,28 @@ function Buffer(arg) { | |
|
||
// Unusual. | ||
return fromObject(arg); | ||
}; | ||
} | ||
|
||
Buffer.prototype.__proto__ = Uint8Array.prototype; | ||
Buffer.__proto__ = Uint8Array; | ||
|
||
|
||
binding.setupBufferJS(Buffer.prototype); | ||
// Buffer prototype must be past before creating our first pool. | ||
createPool(); | ||
|
||
|
||
function SlowBuffer(length) { | ||
if (+length != length) | ||
length = 0; | ||
return binding.create(+length); | ||
}; | ||
flags[kNoZeroFill] = 1; | ||
const ui8 = new Uint8Array(+length); | ||
Object.setPrototypeOf(ui8, Buffer.prototype); | ||
return ui8; | ||
} | ||
|
||
SlowBuffer.prototype.__proto__ = Buffer.prototype; | ||
SlowBuffer.__proto__ = Buffer; | ||
|
||
|
||
function allocate(size) { | ||
if (size === 0) | ||
return binding.create(0); | ||
return SlowBuffer(0); | ||
if (size < (Buffer.poolSize >>> 1)) { | ||
if (size > (poolSize - poolOffset)) | ||
createPool(); | ||
|
@@ -78,7 +85,10 @@ function allocate(size) { | |
alignPool(); | ||
return b; | ||
} else { | ||
return binding.create(size); | ||
flags[kNoZeroFill] = 1; | ||
const ui8 = new Uint8Array(size); | ||
Object.setPrototypeOf(ui8, Buffer.prototype); | ||
return ui8; | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -339,6 +339,27 @@ class Environment { | |
DISALLOW_COPY_AND_ASSIGN(TickInfo); | ||
}; | ||
|
||
class ArrayBufferAllocator { | ||
public: | ||
inline uint32_t* fields(); | ||
inline int fields_count() const; | ||
inline bool no_zero_fill() const; | ||
inline void reset_fill_flag(); | ||
|
||
private: | ||
friend class Environment; // So we can call the constructor. | ||
inline ArrayBufferAllocator(); | ||
|
||
enum Fields { | ||
kNoZeroFill, | ||
kFieldsCount | ||
}; | ||
|
||
uint32_t fields_[kFieldsCount]; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(ArrayBufferAllocator); | ||
}; | ||
|
||
typedef void (*HandleCleanupCb)(Environment* env, | ||
uv_handle_t* handle, | ||
void* arg); | ||
|
@@ -401,6 +422,7 @@ class Environment { | |
inline AsyncHooks* async_hooks(); | ||
inline DomainFlag* domain_flag(); | ||
inline TickInfo* tick_info(); | ||
inline ArrayBufferAllocator* array_buffer_allocator(); | ||
inline uint64_t timer_base() const; | ||
|
||
static inline Environment* from_cares_timer_handle(uv_timer_t* handle); | ||
|
@@ -510,6 +532,7 @@ class Environment { | |
AsyncHooks async_hooks_; | ||
DomainFlag domain_flag_; | ||
TickInfo tick_info_; | ||
ArrayBufferAllocator array_buffer_allocator_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Who sets this thing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't understand. this class is setup like all the other instance utility classes in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mmm.. but it will be allocated twice now? Once here, and once below when you do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, are those two different? Argh... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's call it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hah! sounds good. :) |
||
const uint64_t timer_base_; | ||
uv_timer_t cares_timer_handle_; | ||
ares_channel cares_channel_; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -890,6 +890,14 @@ Local<Value> WinapiErrnoException(Isolate* isolate, | |
#endif | ||
|
||
|
||
void* ArrayBufferAllocator::Allocate(size_t size) { | ||
if (env_ == nullptr || !env_->array_buffer_allocator()->no_zero_fill()) | ||
return calloc(size, 1); | ||
env_->array_buffer_allocator()->reset_fill_flag(); | ||
return malloc(size); | ||
} | ||
|
||
|
||
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) { | ||
Environment* env = Environment::GetCurrent(args); | ||
|
||
|
@@ -3875,8 +3883,8 @@ Environment* CreateEnvironment(Isolate* isolate, | |
static void StartNodeInstance(void* arg) { | ||
NodeInstanceData* instance_data = static_cast<NodeInstanceData*>(arg); | ||
Isolate::CreateParams params; | ||
ArrayBufferAllocator array_buffer_allocator; | ||
params.array_buffer_allocator = &array_buffer_allocator; | ||
ArrayBufferAllocator* array_buffer_allocator = new ArrayBufferAllocator(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Who is going to destroy this thing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gah. This is remnants of two different implementations. It shouldn't be instantiated this way. The entire thing can be a struct in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. partial nm on that. it's cleaned up below after the isolate has been disposed. |
||
params.array_buffer_allocator = array_buffer_allocator; | ||
Isolate* isolate = Isolate::New(params); | ||
if (track_heap_objects) { | ||
isolate->GetHeapProfiler()->StartTrackingHeapObjects(true); | ||
|
@@ -3892,6 +3900,7 @@ static void StartNodeInstance(void* arg) { | |
HandleScope handle_scope(isolate); | ||
Local<Context> context = Context::New(isolate); | ||
Environment* env = CreateEnvironment(isolate, context, instance_data); | ||
array_buffer_allocator->set_env(env); | ||
Context::Scope context_scope(context); | ||
if (instance_data->is_main()) | ||
env->set_using_abort_on_uncaught_exc(abort_on_uncaught_exception); | ||
|
@@ -3938,13 +3947,15 @@ static void StartNodeInstance(void* arg) { | |
__lsan_do_leak_check(); | ||
#endif | ||
|
||
array_buffer_allocator->set_env(nullptr); | ||
env->Dispose(); | ||
env = nullptr; | ||
} | ||
|
||
CHECK_NE(isolate, nullptr); | ||
isolate->Dispose(); | ||
isolate = nullptr; | ||
delete array_buffer_allocator; | ||
if (instance_data->is_main()) | ||
node_isolate = nullptr; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about making this one-byte Uint8Array instead, and passing it to the C++?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm, you did it this way :)