怎么进行基于js引擎v8源码解析allocation

发布时间:2021-12-09 09:47:37 作者:柒染
来源:亿速云 阅读:86

这篇文章将为大家详细讲解有关怎么进行基于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_

             

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 DEBUG

static 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::internal


关于怎么进行基于js引擎v8源码解析allocation就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. 如何进行ThreadPoolExecutor 源码解析
  2. 如何对FastLeaderElection进行源码解析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

js

上一篇:HDFS工作机制是什么

下一篇:HDFS基本概念是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》