js引擎v8源码分析之SemiSpace(基于v8 0.1.5)

theanarkh
发布于 2020-02-17 12:48:41
发布于 2020-02-17 12:48:41
SemiSpace的管理新生代内存的类,即我们常听到的from区和to区。from区和to区都由一个SemiSpace对象管理。SemiSpace只管理地址,不负责分配和释放管理的内存。下面是Semispace类的定义。
class SemiSpace BASE_EMBEDDED {
public:
SemiSpace(int initial_capacity, int maximum_capacity);
bool Setup(Address start, int size);
void TearDown();
bool HasBeenSetup() { return start_ != NULL; }
bool Double();
Address low() { return start_; }
Address high() { return low() + capacity_; }
Address age_mark() { return age_mark_; }
void set_age_mark(Address mark) { age_mark_ = mark; }
// 判断地址a是否在该对象管理的内存中,&address_mask即让a减去size-1的大小。如果等于start说明在管理范围内
bool Contains(Address a) {
return (reinterpret_cast<uint32_t>(a) & address_mask_) == reinterpret_cast<uint32_t>(start_);
}
// 类似上面的逻辑,但是堆对象低位是标记,判断时候需要处理一下,加SetUp
bool Contains(Object* o) {
return (reinterpret_cast<uint32_t>(o) & object_mask_) == object_expected_;
}
// 距离开始地址的p
int SpaceOffsetForAddress(Address addr) { return addr - low(); }
private:
int capacity_;
int maximum_capacity_;
Address start_;
Address age_mark_;
// 见SetUp函数
uint32_t address_mask_;
uint32_t object_mask_;
uint32_t object_expected_;
public:
TRACK_MEMORY("SemiSpace")
};
下面是SemiSpace类的实现。
SemiSpace
新建一个SemiSpace对象的时候默认初始化某些字段。这些字段的真正设置在SetUp函数。
SemiSpace::SemiSpace(int initial_capacity, int maximum_capacity)
: capacity_(initial_capacity),
maximum_capacity_(maximum_capacity),
start_(NULL),
age_mark_(NULL) {
}
Setup
Setup函数是初始化SemiSpace对象属性的函数
// 设置管理的地址范围
bool SemiSpace::Setup(Address start, int size) {
ASSERT(size == maximum_capacity_);
// 判断地址的有效性
if (!MemoryAllocator::CommitBlock(start, capacity_)) return false;
// 管理地址空间的首地址
start_ = start;
// 低于有效范围的掩码,即保证相与后的值小于等于管理的地址范围
address_mask_ = ~(size - 1);
// 计算堆对象地址掩码,低位是标记位,判断的时候需要保留,kHeapObjectTag是堆对象的标记
object_mask_ = address_mask_ | kHeapObjectTag;
// 见contains函数,对象地址里低位是标记位,判断的时候需要带上
object_expected_ = reinterpret_cast<uint32_t>(start) | kHeapObjectTag;
// gc相关
age_mark_ = start_;
return true;
}
TearDown
重置SemiSpace管理的地址,但不负责释放内存。
void SemiSpace::TearDown() {
start_ = NULL;
capacity_ = 0;
}
Double
“扩容”函数,只不负责内存的分配,只对管理的大小进行扩容。
bool SemiSpace::Double() {
// 内存在其他地方分配了,这里校验地址是否合法,即是否分配了
if (!MemoryAllocator::CommitBlock(high(), capacity_)) return false;
capacity_ *= 2;
return true;
}
SemiSpace的功能比较简单,有些属性的使用后续用到的时候再分析。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除
评论
登录后参与评论
目录