diff options
-rw-r--r-- | node.gyp | 2 | ||||
-rw-r--r-- | src/slab_allocator.cc | 127 | ||||
-rw-r--r-- | src/slab_allocator.h | 49 |
3 files changed, 178 insertions, 0 deletions
@@ -84,6 +84,7 @@ 'src/node_zlib.cc', 'src/pipe_wrap.cc', 'src/stream_wrap.cc', + 'src/slab_allocator.cc', 'src/tcp_wrap.cc', 'src/timer_wrap.cc', 'src/tty_wrap.cc', @@ -107,6 +108,7 @@ 'src/node_version.h', 'src/pipe_wrap.h', 'src/req_wrap.h', + 'src/slab_allocator.h', 'src/stream_wrap.h', 'src/v8_typed_array.h', 'deps/http_parser/http_parser.h', diff --git a/src/slab_allocator.cc b/src/slab_allocator.cc new file mode 100644 index 00000000000..504557a5559 --- /dev/null +++ b/src/slab_allocator.cc @@ -0,0 +1,127 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "v8.h" +#include "node.h" +#include "node_buffer.h" +#include "slab_allocator.h" +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + + +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Null; +using v8::Object; +using v8::Persistent; +using v8::String; +using v8::Value; + + +namespace node { + +SlabAllocator::SlabAllocator(unsigned int size) { + size_ = ROUND_UP(size ? size : 1, 8192); + initialized_ = false; +} + + +SlabAllocator::~SlabAllocator() { + if (!initialized_) return; + slab_sym_.Clear(); + slab_sym_.Dispose(); + slab_.Clear(); + slab_.Dispose(); +} + + +void SlabAllocator::Initialize() { + HandleScope scope; + char sym[256]; + snprintf(sym, sizeof(sym), "slab_%p", this); // namespace object key + offset_ = 0; + last_ptr_ = NULL; + initialized_ = true; + slab_sym_ = Persistent<String>::New(String::New(sym)); +} + + +static Local<Object> NewSlab(unsigned int size) { + HandleScope scope; + Local<Value> arg = Integer::NewFromUnsigned(ROUND_UP(size, 16)); + Local<Object> buf = Buffer::constructor_template + ->GetFunction() + ->NewInstance(1, &arg); + return scope.Close(buf); +} + + +char* SlabAllocator::Allocate(Handle<Object> obj, unsigned int size) { + HandleScope scope; + + assert(!obj.IsEmpty()); + + if (size == 0) return NULL; + if (!initialized_) Initialize(); + + if (size > size_) { + Local<Object> buf = NewSlab(size); + obj->SetHiddenValue(slab_sym_, buf); + return Buffer::Data(buf); + } + + if (slab_.IsEmpty() || offset_ + size > size_) { + slab_.Clear(); + slab_.Dispose(); + slab_ = Persistent<Object>::New(NewSlab(size_)); + offset_ = 0; + last_ptr_ = NULL; + } + + obj->SetHiddenValue(slab_sym_, slab_); + last_ptr_ = Buffer::Data(slab_) + offset_; + offset_ += size; + + return last_ptr_; +} + + +Local<Object> SlabAllocator::Shrink(Handle<Object> obj, + char* ptr, + unsigned int size) { + HandleScope scope; + Local<Value> slab_v = obj->GetHiddenValue(slab_sym_); + obj->SetHiddenValue(slab_sym_, Null()); + assert(!slab_v.IsEmpty()); + assert(slab_v->IsObject()); + Local<Object> slab = slab_v->ToObject(); + if (ptr && ptr == last_ptr_) { + last_ptr_ = NULL; + offset_ = ptr - Buffer::Data(slab) + ROUND_UP(size, 16); + } + return scope.Close(slab); +} + + +} // namespace node diff --git a/src/slab_allocator.h b/src/slab_allocator.h new file mode 100644 index 00000000000..6440bd4a070 --- /dev/null +++ b/src/slab_allocator.h @@ -0,0 +1,49 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "v8.h" + +namespace node { + +class SlabAllocator { +public: + SlabAllocator(unsigned int size = 10485760); // default to 10M + ~SlabAllocator(); + + // allocate memory from slab, attaches the slice to `obj` + char* Allocate(v8::Handle<v8::Object> obj, unsigned int size); + + // return excess memory to the slab, returns a handle to the parent buffer + v8::Local<v8::Object> Shrink(v8::Handle<v8::Object> obj, + char* ptr, + unsigned int size); + +private: + void Initialize(); + bool initialized_; + v8::Persistent<v8::Object> slab_; + v8::Persistent<v8::String> slab_sym_; + unsigned int offset_; + unsigned int size_; + char* last_ptr_; +}; + +} // namespace node |