📄 objects-inl.h.svn-base
字号:
Failure* Failure::InternalError() { return Construct(INTERNAL_ERROR);}Failure* Failure::Exception() { return Construct(EXCEPTION);}Failure* Failure::OutOfMemoryException() { return Construct(OUT_OF_MEMORY_EXCEPTION);}int Failure::value() const { return reinterpret_cast<int>(this) >> kFailureTagSize;}Failure* Failure::Construct(Type type, int value) { int info = (value << kFailureTypeTagSize) | type; ASSERT(Smi::IsValid(info)); // Same validation check as in Smi return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);}bool Smi::IsValid(int value) {#ifdef DEBUG bool in_range = (value >= kMinValue) && (value <= kMaxValue);#endif // To be representable as an tagged small integer, the two // most-significant bits of 'value' must be either 00 or 11 due to // sign-extension. To check this we add 01 to the two // most-significant bits, and check if the most-significant bit is 0 // // CAUTION: The original code below: // bool result = ((value + 0x40000000) & 0x80000000) == 0; // may lead to incorrect results according to the C language spec, and // in fact doesn't work correctly with gcc4.1.1 in some cases: The // compiler may produce undefined results in case of signed integer // overflow. The computation must be done w/ unsigned ints. bool result = ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0; ASSERT(result == in_range); return result;}MapWord MapWord::FromMap(Map* map) { return MapWord(reinterpret_cast<uintptr_t>(map));}Map* MapWord::ToMap() { return reinterpret_cast<Map*>(value_);}bool MapWord::IsForwardingAddress() { // This function only works for map words that are heap object pointers. // Since it is a heap object, it has a map. We use that map's instance // type to detect if this map word is not actually a map (ie, it is a // forwarding address during a scavenge collection). return reinterpret_cast<HeapObject*>(value_)->map()->instance_type() != MAP_TYPE;}MapWord MapWord::FromForwardingAddress(HeapObject* object) { return MapWord(reinterpret_cast<uintptr_t>(object));}HeapObject* MapWord::ToForwardingAddress() { ASSERT(IsForwardingAddress()); return reinterpret_cast<HeapObject*>(value_);}bool MapWord::IsMarked() { return (value_ & kMarkingMask) == 0;}void MapWord::SetMark() { value_ &= ~kMarkingMask;}void MapWord::ClearMark() { value_ |= kMarkingMask;}bool MapWord::IsOverflowed() { return (value_ & kOverflowMask) != 0;}void MapWord::SetOverflow() { value_ |= kOverflowMask;}void MapWord::ClearOverflow() { value_ &= ~kOverflowMask;}MapWord MapWord::EncodeAddress(Address map_address, int offset) { // Offset is the distance in live bytes from the first live object in the // same page. The offset between two objects in the same page should not // exceed the object area size of a page. ASSERT(0 <= offset && offset < Page::kObjectAreaSize); int compact_offset = offset >> kObjectAlignmentBits; ASSERT(compact_offset < (1 << kForwardingOffsetBits)); Page* map_page = Page::FromAddress(map_address); ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index); int map_page_offset = map_page->Offset(map_address) >> kObjectAlignmentBits; uintptr_t encoding = (compact_offset << kForwardingOffsetShift) | (map_page_offset << kMapPageOffsetShift) | (map_page->mc_page_index << kMapPageIndexShift); return MapWord(encoding);}Address MapWord::DecodeMapAddress(MapSpace* map_space) { int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift; ASSERT_MAP_PAGE_INDEX(map_page_index); int map_page_offset = ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) << kObjectAlignmentBits; return (map_space->PageAddress(map_page_index) + map_page_offset);}int MapWord::DecodeOffset() { // The offset field is represented in the kForwardingOffsetBits // most-significant bits. int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits; ASSERT(0 <= offset && offset < Page::kObjectAreaSize); return offset;}MapWord MapWord::FromEncodedAddress(Address address) { return MapWord(reinterpret_cast<uintptr_t>(address));}Address MapWord::ToEncodedAddress() { return reinterpret_cast<Address>(value_);}#ifdef DEBUGvoid HeapObject::VerifyObjectField(int offset) { VerifyPointer(READ_FIELD(this, offset));}#endifMap* HeapObject::map() { return map_word().ToMap();}void HeapObject::set_map(Map* value) { set_map_word(MapWord::FromMap(value));}MapWord HeapObject::map_word() { return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));}void HeapObject::set_map_word(MapWord map_word) { // WRITE_FIELD does not update the remembered set, but there is no need // here. WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));}HeapObject* HeapObject::FromAddress(Address address) { ASSERT_TAG_ALIGNED(address); return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);}Address HeapObject::address() { return reinterpret_cast<Address>(this) - kHeapObjectTag;}int HeapObject::Size() { return SizeFromMap(map());}void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) { v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)), reinterpret_cast<Object**>(FIELD_ADDR(this, end)));}void HeapObject::IteratePointer(ObjectVisitor* v, int offset) { v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));}void HeapObject::CopyBody(JSObject* from) { ASSERT(map() == from->map()); ASSERT(Size() == from->Size()); int object_size = Size(); for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { Object* value = READ_FIELD(from, offset); // Note: WRITE_FIELD does not update the write barrier. WRITE_FIELD(this, offset, value); WRITE_BARRIER(this, offset); }}bool HeapObject::IsMarked() { return map_word().IsMarked();}void HeapObject::SetMark() { ASSERT(!IsMarked()); MapWord first_word = map_word(); first_word.SetMark(); set_map_word(first_word);}void HeapObject::ClearMark() { ASSERT(IsMarked()); MapWord first_word = map_word(); first_word.ClearMark(); set_map_word(first_word);}bool HeapObject::IsOverflowed() { return map_word().IsOverflowed();}void HeapObject::SetOverflow() { MapWord first_word = map_word(); first_word.SetOverflow(); set_map_word(first_word);}void HeapObject::ClearOverflow() { ASSERT(IsOverflowed()); MapWord first_word = map_word(); first_word.ClearOverflow(); set_map_word(first_word);}double HeapNumber::value() { return READ_DOUBLE_FIELD(this, kValueOffset);}void HeapNumber::set_value(double value) { WRITE_DOUBLE_FIELD(this, kValueOffset, value);}ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)ACCESSORS(JSObject, elements, HeapObject, kElementsOffset)void JSObject::initialize_properties() { ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());}void JSObject::initialize_elements() { ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());}ACCESSORS(Oddball, to_string, String, kToStringOffset)ACCESSORS(Oddball, to_number, Object, kToNumberOffset)int JSObject::GetHeaderSize() { switch (map()->instance_type()) { case JS_GLOBAL_OBJECT_TYPE: return JSGlobalObject::kSize; case JS_BUILTINS_OBJECT_TYPE: return JSBuiltinsObject::kSize; case JS_FUNCTION_TYPE: return JSFunction::kSize; case JS_VALUE_TYPE: return JSValue::kSize; case JS_ARRAY_TYPE: return JSValue::kSize; case JS_REGEXP_TYPE: return JSValue::kSize; case JS_OBJECT_TYPE: return JSObject::kHeaderSize; default: UNREACHABLE(); return 0; }}int JSObject::GetInternalFieldCount() { ASSERT(1 << kPointerSizeLog2 == kPointerSize); return (Size() - GetHeaderSize()) >> kPointerSizeLog2;}Object* JSObject::GetInternalField(int index) { ASSERT(index < GetInternalFieldCount() && index >= 0); return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));}void JSObject::SetInternalField(int index, Object* value) { ASSERT(index < GetInternalFieldCount() && index >= 0); int offset = GetHeaderSize() + (kPointerSize * index); WRITE_FIELD(this, offset, value); WRITE_BARRIER(this, offset);}void JSObject::InitializeBody(int object_size) { for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { WRITE_FIELD(this, offset, Heap::undefined_value()); }}void Struct::InitializeBody(int object_size) { for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { WRITE_FIELD(this, offset, Heap::undefined_value()); }}bool JSObject::HasFastProperties() { return !properties()->IsDictionary();}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<uint32_t>(value); if (value == static_cast<double>(uint_value)) { *index = uint_value; return true; } } return false;}bool Object::IsStringObjectWithCharacterAt(uint32_t index) { if (!this->IsJSValue()) return false; JSValue* js_value = JSValue::cast(this); if (!js_value->value()->IsString()) return false; String* str = String::cast(js_value->value()); if (index >= (uint32_t)str->length()) return false; return true;}Object* FixedArray::get(int index) { ASSERT(index >= 0 && index < this->length()); return READ_FIELD(this, kHeaderSize + index * kPointerSize);}void FixedArray::set(int index, Object* value) { ASSERT(index >= 0 && index < this->length()); int offset = kHeaderSize + index * kPointerSize; WRITE_FIELD(this, offset, value); WRITE_BARRIER(this, offset);}FixedArray::WriteBarrierMode FixedArray::GetWriteBarrierMode() { if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER; return UPDATE_WRITE_BARRIER;}void FixedArray::set(int index, Object* value, FixedArray::WriteBarrierMode mode) { ASSERT(index >= 0 && index < this->length()); int offset = kHeaderSize + index * kPointerSize; WRITE_FIELD(this, offset, value); if (mode == UPDATE_WRITE_BARRIER) { WRITE_BARRIER(this, offset); } else { ASSERT(mode == SKIP_WRITE_BARRIER); ASSERT(Heap::InNewSpace(this) || !Heap::InNewSpace(value)); }}void FixedArray::fast_set(FixedArray* array, int index, Object* value) { ASSERT(index >= 0 && index < array->length()); WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);}void FixedArray::set_undefined(int index) { ASSERT(index >= 0 && index < this->length()); ASSERT(!Heap::InNewSpace(Heap::undefined_value())); WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::undefined_value());}void FixedArray::set_null(int index) { ASSERT(index >= 0 && index < this->length()); ASSERT(!Heap::InNewSpace(Heap::null_value())); WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());}void FixedArray::set_the_hole(int index) { ASSERT(index >= 0 && index < this->length()); ASSERT(!Heap::InNewSpace(Heap::the_hole_value())); WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());}bool DescriptorArray::IsEmpty() { ASSERT(this == Heap::empty_descriptor_array() || this->length() > 2); return this == Heap::empty_descriptor_array();}void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { Object* tmp = array->get(first); fast_set(array, first, array->get(second)); fast_set(array, second, tmp);}int DescriptorArray::Search(String* name) { SLOW_ASSERT(IsSortedNoDuplicates()); // Check for empty descriptor array. int nof = number_of_descriptors(); if (nof == 0) return kNotFound; // Fast case: do linear search for small arrays. const int kMaxElementsForLinearSearch = 8; if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) { for (int number = 0; number < nof; number++) { if (name == GetKey(number)) return number; } return kNotFound; } // Slow case: perform binary search. return BinarySearch(name, 0, nof - 1);}String* DescriptorArray::GetKey(int descriptor_number) { ASSERT(descriptor_number < number_of_descriptors()); return String::cast(get(ToKeyIndex(descriptor_number)));}Object* DescriptorArray::GetValue(int descriptor_number) { ASSERT(descriptor_number < number_of_descriptors()); return GetContentArray()->get(ToValueIndex(descriptor_number));}Smi* DescriptorArray::GetDetails(int descriptor_number) { ASSERT(descriptor_number < number_of_descriptors()); return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));}void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { desc->Init(GetKey(descriptor_number), GetValue(descriptor_number), GetDetails(descriptor_number));}void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { // Range check. ASSERT(descriptor_number < number_of_descriptors()); // Make sure non of the elements in desc are in new space. ASSERT(!Heap::InNewSpace(desc->GetKey())); ASSERT(!Heap::InNewSpace(desc->GetValue())); fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey()); FixedArray* content_array = GetContentArray(); fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue()); fast_set(content_array, ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());}void DescriptorArray::Swap(int first, int second) { fast_swap(this, ToKeyIndex(first), ToKeyIndex(second)); FixedArray* content_array = GetContentArray(); fast_swap(content_array, ToValueIndex(first), ToValueIndex(second)); fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -