js引擎v8源码解析之allocation(基于0.1.5)

2019-07-30 18:31:37 浏览数 (1)

代码语言:javascript复制
#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

代码语言:javascript复制
#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] = '';
  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

0 人点赞