这篇文章将为大家详细讲解有关怎么进行基于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就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。