这篇文章将为大家详细讲解有关怎么进行基于js引擎v8源码解析allocation,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
#ifndef V8_ALLOCATION_H_#define V8_ALLOCATION_H_namespace v8 { namespace internal {// A class that controls whether allocation is allowed. This is for// the C++ heap only!class NativeAllocationChecker { public: typedef enum { ALLOW, DISALLOW } NativeAllocationAllowed; explicit inline NativeAllocationChecker(NativeAllocationAllowed allowed) : allowed_(allowed) {#ifdef DEBUG if (allowed == DISALLOW) { allocation_disallowed_++; }#endif } ~NativeAllocationChecker() {#ifdef DEBUG if (allowed_ == DISALLOW) { allocation_disallowed_--; }#endif ASSERT(allocation_disallowed_ >= 0); } static inline bool allocation_allowed() { return allocation_disallowed_ == 0; } private: // This static counter ensures that NativeAllocationCheckers can be nested. static int allocation_disallowed_; // This flag applies to this particular instance. NativeAllocationAllowed allowed_;};// Superclass for classes managed with new & delete.// 管理内存的类,对c函数进行了封装class Malloced { public: void* operator new(size_t size) { return New(size); } void operator delete(void* p) { Delete(p); } static void FatalProcessOutOfMemory(); static void* New(size_t size); static void Delete(void* p);};// A macro is used for defining the base class used for embedded instances.// The reason is some compilers allocate a minimum of one word for the// superclass. The macro prevents the use of new & delete in debug mode.// In release mode we are not willing to pay this overhead.#ifdef DEBUG// Superclass for classes with instances allocated inside stack// activations or inside other objects.class Embedded { public: void* operator new(size_t size); void operator delete(void* p);};#define BASE_EMBEDDED : public Embedded#else#define BASE_EMBEDDED#endif// Superclass for classes only using statics.// 类里只有静态成员class AllStatic {#ifdef DEBUG public: void* operator new(size_t size); void operator delete(void* p);#endif};// 新建一个T类型的数组template <typename T>static T* NewArray(int size) { ASSERT(NativeAllocationChecker::allocation_allowed()); T* result = new T[size]; if (result == NULL) Malloced::FatalProcessOutOfMemory(); return result;}template <typename T>static void DeleteArray(T* array) { delete[] array;}// The normal strdup function uses malloc. This version of StrDup// uses new and calls the FatalProcessOutOfMemory handler if// allocation fails.// 复制字符串char* StrDup(const char* str);// Allocation policy for allocating in the C free store using malloc// and free. Used as the default policy for lists.class FreeStoreAllocationPolicy { public: INLINE(static void* New(size_t size)) { return Malloced::New(size); } INLINE(static void Delete(void* p)) { Malloced::Delete(p); }};// Allocation policy for allocating in preallocated space.// Used as an allocation policy for ScopeInfo when generating// stack traces.// 内存管理 class PreallocatedStorage : public AllStatic { public: // 管理内存的大小 explicit PreallocatedStorage(size_t size); size_t size() { return size_; } static void* New(size_t size); static void Delete(void* p); // Preallocate a set number of bytes. static void Init(size_t size); private: size_t size_; // 链表 PreallocatedStorage* previous_; PreallocatedStorage* next_; static bool preallocated_; // 已分配出去的内存链表 static PreallocatedStorage in_use_list_; // 空闲链表 static PreallocatedStorage free_list_; // 链表操作函数 void LinkTo(PreallocatedStorage* other); void Unlink(); DISALLOW_IMPLICIT_CONSTRUCTORS(PreallocatedStorage);};} } // namespace v8::internal#endif // V8_ALLOCATION_H_
AI代码助手复制代码
allocation.cc
#include <stdlib.h>#include "v8.h"namespace v8 { namespace internal {// 对c函数的封装void* Malloced::New(size_t size) { ASSERT(NativeAllocationChecker::allocation_allowed()); void* result = malloc(size); if (result == NULL) V8::FatalProcessOutOfMemory("Malloced operator new"); return result;}void Malloced::Delete(void* p) { free(p);}void Malloced::FatalProcessOutOfMemory() { V8::FatalProcessOutOfMemory("Out of memory");}#ifdef DEBUGstatic void* invalid = static_cast<void*>(NULL);void* Embedded::operator new(size_t size) { UNREACHABLE(); return invalid;}void Embedded::operator delete(void* p) { UNREACHABLE();}void* AllStatic::operator new(size_t size) { UNREACHABLE(); return invalid;}void AllStatic::operator delete(void* p) { UNREACHABLE();}#endif// 复制字符串char* StrDup(const char* str) { int length = strlen(str); // 申请一个字符数组 char* result = NewArray<char>(length + 1); // 复制过去 memcpy(result, str, length * kCharSize); result[length] = '\0'; return result;}int NativeAllocationChecker::allocation_disallowed_ = 0;// 初始化属性PreallocatedStorage PreallocatedStorage::in_use_list_(0);PreallocatedStorage PreallocatedStorage::free_list_(0);bool PreallocatedStorage::preallocated_ = false;// 申请一块内存对其进行管理void PreallocatedStorage::Init(size_t size) { ASSERT(free_list_.next_ == &free_list_); ASSERT(free_list_.previous_ == &free_list_); // 申请size个字节,前n个字节是一个PreallocatedStorage对象 PreallocatedStorage* free_chunk = reinterpret_cast<PreallocatedStorage*>(new char[size]); // 初始化链表,双向循环链表 free_list_.next_ = free_list_.previous_ = free_chunk; free_chunk->next_ = free_chunk->previous_ = &free_list_; // 大小是申请的大小减去一个PreallocatedStorage对象 free_chunk->size_ = size - sizeof(PreallocatedStorage); // 已经分配了内存 preallocated_ = true;}// 从预分配的内存里分配一块内存void* PreallocatedStorage::New(size_t size) { // 没有使用预分配内存,则直接到底层申请一块新的内存,否则从预分配的内存里分配 if (!preallocated_) { return FreeStoreAllocationPolicy::New(size); } ASSERT(free_list_.next_ != &free_list_); ASSERT(free_list_.previous_ != &free_list_); /* ~(kPointerSize - 1)是使高n位取反,n取决于kPointerSize的大小,即1的位置。 size + (kPointerSize - 1)是如果没有按kPointerSize对齐则向上取整。 */ size = (size + kPointerSize - 1) & ~(kPointerSize - 1); // Search for exact fit. // 从预分配的内存里找到等于size的块 for (PreallocatedStorage* storage = free_list_.next_; storage != &free_list_; storage = storage->next_) { if (storage->size_ == size) { // 找到后,把该块从链表中删除,并插入到已分配链表中 storage->Unlink(); storage->LinkTo(&in_use_list_); // 返回存储数据的首地址,前面存储了一个PreallocatedStorage对象 return reinterpret_cast<void*>(storage + 1); } } // Search for first fit. // 没有大小等于size的块,则找比size大的块 for (PreallocatedStorage* storage = free_list_.next_; storage != &free_list_; storage = storage->next_) { // 多出来的那一块还需要一个PreallocatedStorage对象进行管理 if (storage->size_ >= size + sizeof(PreallocatedStorage)) { storage->Unlink(); storage->LinkTo(&in_use_list_); // 分配一部分出去,storage + 1即可用于存储数据的首地址,加上size得到还剩下的空闲内存首地址 PreallocatedStorage* left_over = reinterpret_cast<PreallocatedStorage*>( reinterpret_cast<char*>(storage + 1) + size); // 剩下的大小等于本来的大小减去size-一个PreallocatedStorage对象 left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage); ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) == storage->size_); // 更新原来的storage的大小,为请求的size,stroage被切分了 storage->size_ = size; // 剩下的插入空闲链表 left_over->LinkTo(&free_list_); // 返回可用于存储数据的首地址 return reinterpret_cast<void*>(storage + 1); } } // Allocation failure. ASSERT(false); return NULL;}// We don't attempt to coalesce.// 释放内存,不作合并处理,p是存储数据的首地址void PreallocatedStorage::Delete(void* p) { if (p == NULL) { return; } // 参考New if (!preallocated_) { FreeStoreAllocationPolicy::Delete(p); return; } // 转成PreallocatedStorage指针,减一则指向管理这块内存的PreallocatedStorage对象 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; ASSERT(storage->next_->previous_ == storage); ASSERT(storage->previous_->next_ == storage); // 脱离原来的链表,插入空闲链表 storage->Unlink(); storage->LinkTo(&free_list_);}// 插入双向循环链表void PreallocatedStorage::LinkTo(PreallocatedStorage* other) { next_ = other->next_; other->next_->previous_ = this; previous_ = other; other->next_ = this;}void PreallocatedStorage::Unlink() { next_->previous_ = previous_; previous_->next_ = next_;}PreallocatedStorage::PreallocatedStorage(size_t size) : size_(size) { previous_ = next_ = this;}} } // namespace v8::internalAI代码助手复制代码
关于怎么进行基于js引擎v8源码解析allocation就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/4217331/blog/4379693