|
5 | 5 | #include"node_buffer.h" |
6 | 6 | #include"node_http2.h" |
7 | 7 | #include"node_http2_state.h" |
| 8 | +#include"node_mem-inl.h" |
8 | 9 | #include"node_perf.h" |
9 | 10 | #include"node_revert.h" |
10 | 11 | #include"util-inl.h" |
@@ -505,101 +506,20 @@ Http2Session::Callbacks::~Callbacks() { |
505 | 506 | nghttp2_session_callbacks_del(callbacks); |
506 | 507 | } |
507 | 508 |
|
508 | | -// Track memory allocated by nghttp2 using a custom allocator. |
509 | | -classHttp2Session::MemoryAllocatorInfo { |
510 | | -public: |
511 | | -explicitMemoryAllocatorInfo(Http2Session* session) |
512 | | - : info({ session, H2Malloc, H2Free, H2Calloc, H2Realloc }) {} |
513 | | - |
514 | | -staticvoid* H2Malloc(size_t size, void* user_data) { |
515 | | -returnH2Realloc(nullptr, size, user_data); |
516 | | - } |
517 | | - |
518 | | -staticvoid* H2Calloc(size_t nmemb, size_t size, void* user_data) { |
519 | | -size_t real_size = MultiplyWithOverflowCheck(nmemb, size); |
520 | | -void* mem = H2Malloc(real_size, user_data); |
521 | | -if (mem != nullptr) |
522 | | -memset(mem, 0, real_size); |
523 | | -return mem; |
524 | | - } |
525 | | - |
526 | | -staticvoidH2Free(void* ptr, void* user_data) { |
527 | | -if (ptr == nullptr) return; // free(null); happens quite often. |
528 | | -void* result = H2Realloc(ptr, 0, user_data); |
529 | | -CHECK_NULL(result); |
530 | | - } |
531 | | - |
532 | | -staticvoid* H2Realloc(void* ptr, size_t size, void* user_data) { |
533 | | - Http2Session* session = static_cast<Http2Session*>(user_data); |
534 | | -size_t previous_size = 0; |
535 | | -char* original_ptr = nullptr; |
536 | | - |
537 | | -// We prepend each allocated buffer with a size_t containing the full |
538 | | -// size of the allocation. |
539 | | -if (size > 0) size += sizeof(size_t); |
540 | | - |
541 | | -if (ptr != nullptr) { |
542 | | -// We are free()ing or re-allocating. |
543 | | - original_ptr = static_cast<char*>(ptr) - sizeof(size_t); |
544 | | - previous_size = *reinterpret_cast<size_t*>(original_ptr); |
545 | | -// This means we called StopTracking() on this pointer before. |
546 | | -if (previous_size == 0) { |
547 | | -// Fall back to the standard Realloc() function. |
548 | | -char* ret = UncheckedRealloc(original_ptr, size); |
549 | | -if (ret != nullptr) |
550 | | - ret += sizeof(size_t); |
551 | | -return ret; |
552 | | - } |
553 | | - } |
554 | | -CHECK_GE(session->current_nghttp2_memory_, previous_size); |
555 | | - |
556 | | -// TODO(addaleax): Add the following, and handle NGHTTP2_ERR_NOMEM properly |
557 | | -// everywhere: |
558 | | -// |
559 | | -// if (size > previous_size && |
560 | | -// !session->IsAvailableSessionMemory(size - previous_size)) { |
561 | | -// return nullptr; |
562 | | -//} |
563 | | - |
564 | | -char* mem = UncheckedRealloc(original_ptr, size); |
565 | | - |
566 | | -if (mem != nullptr) { |
567 | | -// Adjust the memory info counter. |
568 | | -// TODO(addaleax): Avoid the double bookkeeping we do with |
569 | | -// current_nghttp2_memory_ + AdjustAmountOfExternalAllocatedMemory |
570 | | -// and provide versions of our memory allocation utilities that take an |
571 | | -// Environment*/Isolate* parameter and call the V8 method transparently. |
572 | | -constint64_t new_size = size - previous_size; |
573 | | - session->current_nghttp2_memory_ += new_size; |
574 | | - session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( |
575 | | - new_size); |
576 | | - *reinterpret_cast<size_t*>(mem) = size; |
577 | | - mem += sizeof(size_t); |
578 | | - } elseif (size == 0) { |
579 | | - session->current_nghttp2_memory_ -= previous_size; |
580 | | - session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( |
581 | | - -static_cast<int64_t>(previous_size)); |
582 | | - } |
583 | | - |
584 | | -return mem; |
585 | | - } |
586 | | - |
587 | | -staticvoidStopTracking(Http2Session* session, void* ptr) { |
588 | | -size_t* original_ptr = reinterpret_cast<size_t*>( |
589 | | -static_cast<char*>(ptr) - sizeof(size_t)); |
590 | | - session->current_nghttp2_memory_ -= *original_ptr; |
591 | | - session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory( |
592 | | - -static_cast<int64_t>(*original_ptr)); |
593 | | - *original_ptr = 0; |
594 | | - } |
| 509 | +voidHttp2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) { |
| 510 | +StopTrackingMemory(buf); |
| 511 | +} |
595 | 512 |
|
596 | | -inline nghttp2_mem* operator*() { return &info; } |
| 513 | +voidHttp2Session::CheckAllocatedSize(size_t previous_size) const { |
| 514 | +CHECK_GE(current_nghttp2_memory_, previous_size); |
| 515 | +} |
597 | 516 |
|
598 | | - nghttp2_mem info; |
599 | | -}; |
| 517 | +voidHttp2Session::IncreaseAllocatedSize(size_t size) { |
| 518 | + current_nghttp2_memory_ += size; |
| 519 | +} |
600 | 520 |
|
601 | | -voidHttp2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) { |
602 | | -MemoryAllocatorInfo::StopTracking(this, buf); |
| 521 | +voidHttp2Session::DecreaseAllocatedSize(size_t size) { |
| 522 | +current_nghttp2_memory_ -= size; |
603 | 523 | } |
604 | 524 |
|
605 | 525 | Http2Session::Http2Session(Environment* env, |
@@ -636,14 +556,14 @@ Http2Session::Http2Session(Environment* env, |
636 | 556 | nghttp2_session_server_new3 : |
637 | 557 | nghttp2_session_client_new3; |
638 | 558 |
|
639 | | -MemoryAllocatorInfo allocator_info(this); |
| 559 | +nghttp2_mem alloc_info = MakeAllocator(); |
640 | 560 |
|
641 | 561 | // This should fail only if the system is out of memory, which |
642 | 562 | // is going to cause lots of other problems anyway, or if any |
643 | 563 | // of the options are out of acceptable range, which we should |
644 | 564 | // be catching before it gets this far. Either way, crash if this |
645 | 565 | // fails. |
646 | | -CHECK_EQ(fn(&session_, callbacks, this, *opts, *allocator_info), 0); |
| 566 | +CHECK_EQ(fn(&session_, callbacks, this, *opts, &alloc_info), 0); |
647 | 567 |
|
648 | 568 | outgoing_storage_.reserve(1024); |
649 | 569 | outgoing_buffers_.reserve(32); |
|
0 commit comments