这篇文章主要讲解了“js引擎zone怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“js引擎zone怎么使用”吧!
zone也是用于内存管理的,不过他是增量分配,一次销毁的。下面是结构图。
zone.h
#ifndef V8_ZONE_H_#define V8_ZONE_H_namespace v8 { namespace internal {// The Zone supports very fast allocation of small chunks of// memory. The chunks cannot be deallocated individually, but instead// the Zone supports deallocating all chunks in one fast// operation. The Zone is used to hold temporary data structures like// the abstract syntax tree, which is deallocated after compilation.// Note: There is no need to initialize the Zone; the first time an// allocation is attempted, a segment of memory will be requested// through a call to malloc().// Note: The implementation is inherently not thread safe. Do not use// from multi-threaded code.class Zone { public: // Allocate 'size' bytes of memory in the Zone; expands the Zone by // allocating new segments of memory on demand using malloc(). // 分配size大小的内存 static inline void* New(int size); // Delete all objects and free all memory allocated in the Zone. // 一次性释放所有内存 static void DeleteAll(); private: // All pointers returned from New() have this alignment. static const int kAlignment = kPointerSize; // Never allocate segments smaller than this size in bytes. static const int kMinimumSegmentSize = 8 * KB; // Never keep segments larger than this size in bytes around. static const int kMaximumKeptSegmentSize = 64 * KB; // The Zone is intentionally a singleton; you should not try to // allocate instances of the class. // 不能new 只能调用Zone::New Zone() { UNREACHABLE(); } // Expand the Zone to hold at least 'size' more bytes and allocate // the bytes. Returns the address of the newly allocated chunk of // memory in the Zone. Should only be called if there isn't enough // room in the Zone already. // 扩展内存 static Address NewExpand(int size); // The free region in the current (front) segment is represented as // the half-open interval [position, limit). The 'position' variable // is guaranteed to be aligned as dictated by kAlignment. // 管理内存的首地址和大小限制 static Address position_; static Address limit_;};// ZoneObject is an abstraction that helps define classes of objects// allocated in the Zone. Use it as a base class; see ast.h.// 对Zone的封装new ZoneObject();即Zone::New(size);class ZoneObject { public: // Allocate a new ZoneObject of 'size' bytes in the Zone. void* operator new(size_t size) { return Zone::New(size); } // Ideally, the delete operator should be private instead of // public, but unfortuately the compiler sometimes synthesizes // (unused) destructors for classes derived from ZoneObject, which // require the operator to be visible. MSVC requires the delete // operator to be public. // ZoneObjects should never be deleted individually; use // Zone::DeleteAll() to delete all zone objects in one go. // 禁止delete该类的对象 void operator delete(void*, size_t) { UNREACHABLE(); }};/* 管理allow_allocation_字段, new AssertNoZoneAllocation的时候,保存当前的allow_allocation_, 设置allow_allocation_为false,析构后,恢复allow_allocation_的值*/ class AssertNoZoneAllocation { public: AssertNoZoneAllocation() : prev_(allow_allocation_) { allow_allocation_ = false; } ~AssertNoZoneAllocation() { allow_allocation_ = prev_; } static bool allow_allocation() { return allow_allocation_; } private: bool prev_; static bool allow_allocation_;};// The ZoneListAllocationPolicy is used to specialize the GenericList// implementation to allocate ZoneLists and their elements in the// Zone.class ZoneListAllocationPolicy { public: // Allocate 'size' bytes of memory in the zone. static void* New(int size) { return Zone::New(size); } // De-allocation attempts are silently ignored. static void Delete(void* p) { }};// ZoneLists are growable lists with constant-time access to the// elements. The list itself and all its elements are allocated in the// Zone. ZoneLists cannot be deleted individually; you can delete all// objects in the Zone by calling Zone::DeleteAll().template<typename T>// ZoneList本质上是一个list,ZoneListAllocationPolicy是list里的内存管理器class ZoneList: public List<T, ZoneListAllocationPolicy> { public: // Construct a new ZoneList with the given capacity; the length is // always zero. The capacity must be non-negative. explicit ZoneList(int capacity) : List<T, ZoneListAllocationPolicy>(capacity) { }};} } // namespace v8::internal#endif // V8_ZONE_H_
AI代码助手复制代码
zone-inl.h
#ifndef V8_ZONE_INL_H_#define V8_ZONE_INL_H_#include "zone.h"namespace v8 { namespace internal {inline void* Zone::New(int size) { ASSERT(AssertNoZoneAllocation::allow_allocation()); // Round up the requested size to fit the alignment. size = RoundUp(size, kAlignment); // Check if the requested size is available without expanding. // 当前的指针位置 Address result = position_; /* 一开始position和limit都是0,所以会分配一个segment,后续还需要分配的时候,如果segment 里的内存还可以满足,则不需要再分配一个新的segment,在原来的分配就行, 分配size后超过了限制,扩容的时候也是分配一个segment */ if ((position_ += size) > limit_) result = NewExpand(size); // Check that the result has the proper alignment and return it. ASSERT(IsAddressAligned(result, kAlignment, 0)); return reinterpret_cast<void*>(result);}} } // namespace v8::internal#endif // V8_ZONE_INL_H_
AI代码助手复制代码
zone.cc
#include "v8.h"#include "zone-inl.h"namespace v8 { namespace internal {Address Zone::position_ = 0;Address Zone::limit_ = 0;bool AssertNoZoneAllocation::allow_allocation_ = true;// Segments represent chunks of memory: They have starting address// (encoded in the this pointer) and a size in bytes. Segments are// chained together forming a LIFO structure with the newest segment// available as Segment::head(). Segments are allocated using malloc()// and de-allocated using free().class Segment { public: // 下一个节点 Segment* next() const { return next_; } // 断开指向下一个节点的指针 void clear_next() { next_ = NULL; } // 内存总大小 int size() const { return size_; } // 内存可用大小,前面有一个Segment对象 int capacity() const { return size_ - sizeof(Segment); } // 内存的开始地址,即Segement对象 Address start() const { return address(sizeof(Segment)); } // 结束地址即首地址加上size Address end() const { return address(size_); } // 返回第一个Segment节点 static Segment* head() { return head_; } static void set_head(Segment* head) { head_ = head; } // Creates a new segment, sets it size, and pushes it to the front // of the segment chain. Returns the new segment. // 新增一个Segment static Segment* New(int size) { Segment* result = reinterpret_cast<Segment*>(Malloced::New(size)); // 分配成功 if (result != NULL) { // 头插入插入链表,size是分配的总大小 result->next_ = head_; result->size_ = size; head_ = result; } return result; } // Deletes the given segment. Does not touch the segment chain. // 释放segment节点 static void Delete(Segment* segment) { Malloced::Delete(segment); } private: // Computes the address of the nth byte in this segment. // 首地址加上n个字节 Address address(int n) const { return Address(this) + n; } // 管理所有segment节点的头指针 static Segment* head_; // 每个segment节点的属性 Segment* next_; int size_;};Segment* Segment::head_ = NULL;void Zone::DeleteAll() {#ifdef DEBUG // Constant byte value used for zapping dead memory in debug mode. static const unsigned char kZapDeadByte = 0xcd;#endif // Find a segment with a suitable size to keep around. Segment* keep = Segment::head(); // 到末节点或者小于kMaximumKeptSegmentSize大小的节点 while (keep != NULL && keep->size() > kMaximumKeptSegmentSize) { keep = keep->next(); } // Traverse the chained list of segments, zapping (in debug mode) // and freeing every segment except the one we wish to keep. Segment* current = Segment::head(); // 处理keep节点,其余节点的内存都被释放 while (current != NULL) { Segment* next = current->next(); if (current == keep) { // Unlink the segment we wish to keep from the list. current->clear_next(); } else {#ifdef DEBUG // Zap the entire current segment (including the header). memset(current, kZapDeadByte, current->size());#endif Segment::Delete(current); } current = next; } // If we have found a segment we want to keep, we must recompute the // variables 'position' and 'limit' to prepare for future allocate // attempts. Otherwise, we must clear the position and limit to // force a new segment to be allocated on demand. // 更新属性,有保留的内存则用于下次分配 if (keep != NULL) { Address start = keep->start(); position_ = RoundUp(start, kAlignment); limit_ = keep->end();#ifdef DEBUG // Zap the contents of the kept segment (but not the header). memset(start, kZapDeadByte, keep->capacity());#endif } else { position_ = limit_ = 0; } // Update the head segment to be the kept segment (if any). // 更新头指针 Segment::set_head(keep);}Address Zone::NewExpand(int size) { // Make sure the requested size is already properly aligned and that // there isn't enough room in the Zone to satisfy the request. ASSERT(size == RoundDown(size, kAlignment)); ASSERT(position_ + size > limit_); // Compute the new segment size. We use a 'high water mark' // strategy, where we increase the segment size every time we expand // except that we employ a maximum segment size when we delete. This // is to avoid excessive malloc() and free() overhead. Segment* head = Segment::head(); int old_size = (head == NULL) ? 0 : head->size(); int new_size = sizeof(Segment) + kAlignment + size + (old_size << 1); if (new_size < kMinimumSegmentSize) new_size = kMinimumSegmentSize; // 分配一个新的segment节点插入到链表 Segment* segment = Segment::New(new_size); if (segment == NULL) V8::FatalProcessOutOfMemory("Zone"); // Recompute 'top' and 'limit' based on the new segment. Address result = RoundUp(segment->start(), kAlignment); // 更新属性,下次分配的时候使用 position_ = result + size; limit_ = segment->end(); ASSERT(position_ <= limit_); return result;}} } // namespace v8::internal
AI代码助手复制代码
感谢各位的阅读,以上就是“js引擎zone怎么使用”的内容了,经过本文的学习后,相信大家对js引擎zone怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/4217331/blog/4379689