js引擎HeadNumber类是怎么实现的
发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容介绍了"js引擎HeadNumber类是怎么实现的"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所
千家信息网最后更新 2026年10月31日js引擎HeadNumber类是怎么实现的
本篇内容介绍了"js引擎HeadNumber类是怎么实现的"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
1 HeadNumber
HeadNumber类的代码比较少。
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
// 存储了数字的堆对象
class HeapNumber: public HeapObject {
public:
// [value]: number value.
inline double value();
inline void set_value(double value);
// Casting.
static inline HeapNumber* cast(Object* obj);
// Dispatched behavior.
Object* HeapNumberToBoolean();
// Layout description.
// kSize之前的空间存储map对象的指针
static const int kValueOffset = HeapObject::kSize;
// kValueOffset - kSize之间存储数字的值
static const int kSize = kValueOffset + kDoubleSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
};
我们看看他的实现。
// 读出double类型的值
#define READ_DOUBLE_FIELD(p, offset) \
(*reinterpret_cast(FIELD_ADDR(p, offset)))
// 写入double类型的值
#define WRITE_DOUBLE_FIELD(p, offset, value) \
(*reinterpret_cast(FIELD_ADDR(p, offset)) = value)
// 读写属性的值
double HeapNumber::value() {
return READ_DOUBLE_FIELD(this, kValueOffset);
}
// 写double值到对象
void HeapNumber::set_value(double value) {
WRITE_DOUBLE_FIELD(this, kValueOffset, value);
}
Object* HeapNumber::HeapNumberToBoolean() {
// NaN, +0, and -0 should return the false object
switch (fpclassify(value())) {
case FP_NAN: // fall through
case FP_ZERO: return Heap::false_value();
default: return Heap::true_value();
}
}
还有一个函数就是cast,实现如下:
CAST_ACCESSOR(HeapNumber)
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
ASSERT(object->Is##type()); \
return reinterpret_cast(object); \
CAST_ACCESSOR(HeapNumber);
宏展开后
HeapNumber* HeapNumber::cast(Object* object) { \
ASSERT(object->IsHeapNumber()); \
return reinterpret_cast(object); \
至此HeapNumber分析完了。接着看下一个类Array。
2 Array
// Abstract super class arrays. It provides length behavior.
class Array: public HeapObject {
public:
// [length]: length of the array.
inline int length();
inline void set_length(int value);
// Convert an object to an array index.
// Returns true if the conversion succeeded.
static inline bool IndexFromObject(Object* object, uint32_t* index);
// Layout descriptor.
static const int kLengthOffset = HeapObject::kSize;
static const int kHeaderSize = kLengthOffset + kIntSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Array);
};
我们发现数组的对象内存布局中,只有一个属性。就是保存length大小的。首先看看读写length属性的实现。
#define INT_ACCESSORS(holder, name, offset) \
int holder::name() { return READ_INT_FIELD(this, offset); } \
void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
// 定义数组的length和set_length函数,属性在对象的偏移的kLengthOffset,紧跟着map指针
INT_ACCESSORS(Array, length, kLengthOffset);
再继续看IndexFromObject的实现。
bool Array::IndexFromObject(Object* object, uint32_t* index) {
if (object->IsSmi()) {
int value = Smi::cast(object)->value();
if (value < 0) return false;
*index = value;
return true;
}
if (object->IsHeapNumber()) {
double value = HeapNumber::cast(object)->value();
uint32_t uint_value = static_cast(value);
if (value == static_cast(uint_value)) {
*index = uint_value;
return true;
}
}
return false;
}
该函数就是把一个对象(底层是表示数字的)转成一个数组索引。数组类也分析完了。我们继续。
3 ByteArray
// ByteArray represents fixed sized byte arrays. Used by the outside world,
// such as PCRE, and also by the memory allocator and garbage collector to
// fill in free blocks in the heap.
class ByteArray: public Array {
public:
// Setter and getter.
inline byte get(int index);
inline void set(int index, byte value);
// Treat contents as an int array.
inline int get_int(int index);
/*
ByteArray类没有定义自己的属性,他是根据length算出对象的大小,
然后在分配内存的时候,多分配一块存储数组元素的内存
const int kObjectAlignmentBits = 2;
const int kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;
#define OBJECT_SIZE_ALIGN(value) ((value + kObjectAlignmentMask) & ~kObjectAlignmentMask)
由此可知,按四个字节对齐。OBJECT_SIZE_ALIGN的作用的是不够4字节的,会多分配几个字节,使得按四字节对齐。~kObjectAlignmentMask是低两位是0,即按四字节对齐。比如value已经4字节对齐了,则(4 + 0 +3) & ~3 =4,如果value没有对齐,假设是5,则(4 + 1 +3) & ~3 = 8;如果value等于6,(4 + 2 + 3) & ~3 = 8;以此类推。
*/
static int SizeFor(int length) {
return kHeaderSize + OBJECT_SIZE_ALIGN(length);
}
// We use byte arrays for free blocks in the heap. Given a desired size in
// bytes that is a multiple of the word size and big enough to hold a byte
// array, this function returns the number of elements a byte array should
// have.
static int LengthFor(int size_in_bytes) {
ASSERT(IsAligned(size_in_bytes, kPointerSize));
ASSERT(size_in_bytes >= kHeaderSize);
return size_in_bytes - kHeaderSize;
}
// Returns data start address.
inline Address GetDataStartAddress();
// Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray* FromDataStartAddress(Address address);
// Casting.
static inline ByteArray* cast(Object* obj);
// Dispatched behavior.
int ByteArraySize() { return SizeFor(length()); }
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
在分析实现之前我们先看一下ByteArray的对象是怎么被分配的。
Handle Factory::NewByteArray(int length) {
ASSERT(0 <= length);
CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length), ByteArray);
}
Object* Heap::AllocateByteArray(int length) {
int size = ByteArray::SizeFor(length);
AllocationSpace space = size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE;
Object* result = AllocateRaw(size, space);
if (result->IsFailure()) return result;
reinterpret_cast(result)->set_map(byte_array_map());
reinterpret_cast(result)->set_length(length);
return result;
}
我们看到,首先通过ByteArray::SizeFor算出对象所需的内存大小size。然后分配一块大小为size的内存。然后返回这块内存的地址。这时候我们就可以使用这块内存。我们看看怎么使用的。内存布局如下。
byte ByteArray::get(int index) {
ASSERT(index >= 0 && index < this->length());
// 根据索引返回数组中对应元素的值,kHeaderSize是第一个元素的地址,kCharSize是1,即一个字节
return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}
void ByteArray::set(int index, byte value) {
ASSERT(index >= 0 && index < this->length());
WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
}
// 把四个元素(四个字节)的内容作为一个值。即ByteArray变成IntArray
int ByteArray::get_int(int index) {
ASSERT(index >= 0 && (index * kIntSize) < this->length());
return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
}
ByteArray* ByteArray::FromDataStartAddress(Address address) {
ASSERT_TAG_ALIGNED(address);
return reinterpret_cast(address - kHeaderSize + kHeapObjectTag);
}
// 返回数组元素的首地址,地址的低位是用作标记,要先减掉。kHeaderSize是第一个元素在对象内存空间的偏移
Address ByteArray::GetDataStartAddress() {
/*
typedef uint8_t byte;
typedef byte* Address;
*/
return reinterpret_cast(this) - kHeapObjectTag + kHeaderSize;
}
"js引擎HeadNumber类是怎么实现的"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
对象
内存
字节
数组
元素
属性
分配
地址
大小
存储
内容
函数
就是
数字
分析
引擎
完了
布局
指针
更多
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
深圳市人人互联网科技有限公司
互联网科技资迅
腾讯阿里互联网科技
世界互联网领先科技成果
奇酷互联网络科技公司
广州善班互联网科技
互联网 新科技
亿人帮互联网科技
新华互联网科技校企合作
哈尔滨秒房互联网科技有限公司
南山科技园互联网公司有哪些
宝灵互联网科技有限公司
智腾互联网科技有限公司
富国互联网科技002692
互联网领先科技活动
互联网科技收购价值
兰石爱特工业互联网科技分公司
西安左小互联网科技有限公司
保山浩联互联网科技有限公司
科技互联网企业在行动
咖啡豆
互联网科技公司发展
西安互联网科技
狮子座互联网科技培训
互联网科技生活的内容
卫星互联网科技股票
科技与互联网的利与弊
山东有哪些互联网科技公司
第三届互联网大会安防黑科技
科技互联网企业在行动