2015-10-23 08:28:25 +00:00
|
|
|
// Copyright 2015 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef V8_ADDRESS_MAP_H_
|
|
|
|
#define V8_ADDRESS_MAP_H_
|
|
|
|
|
|
|
|
#include "src/assert-scope.h"
|
2016-06-09 17:58:10 +00:00
|
|
|
#include "src/base/hashmap.h"
|
2015-10-23 08:28:25 +00:00
|
|
|
#include "src/objects.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
class AddressMapBase {
|
|
|
|
protected:
|
2016-06-09 17:58:10 +00:00
|
|
|
static void SetValue(base::HashMap::Entry* entry, uint32_t v) {
|
2015-10-23 08:28:25 +00:00
|
|
|
entry->value = reinterpret_cast<void*>(v);
|
|
|
|
}
|
|
|
|
|
2016-06-09 17:58:10 +00:00
|
|
|
static uint32_t GetValue(base::HashMap::Entry* entry) {
|
2015-10-23 08:28:25 +00:00
|
|
|
return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry->value));
|
|
|
|
}
|
|
|
|
|
2016-06-09 17:58:10 +00:00
|
|
|
inline static base::HashMap::Entry* LookupEntry(base::HashMap* map,
|
|
|
|
HeapObject* obj,
|
|
|
|
bool insert) {
|
2015-10-23 08:28:25 +00:00
|
|
|
if (insert) {
|
|
|
|
map->LookupOrInsert(Key(obj), Hash(obj));
|
|
|
|
}
|
|
|
|
return map->Lookup(Key(obj), Hash(obj));
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static uint32_t Hash(HeapObject* obj) {
|
|
|
|
return static_cast<int32_t>(reinterpret_cast<intptr_t>(obj->address()));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void* Key(HeapObject* obj) {
|
|
|
|
return reinterpret_cast<void*>(obj->address());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class RootIndexMap : public AddressMapBase {
|
|
|
|
public:
|
|
|
|
explicit RootIndexMap(Isolate* isolate);
|
|
|
|
|
|
|
|
static const int kInvalidRootIndex = -1;
|
|
|
|
|
|
|
|
int Lookup(HeapObject* obj) {
|
2016-06-09 17:58:10 +00:00
|
|
|
base::HashMap::Entry* entry = LookupEntry(map_, obj, false);
|
2015-10-23 08:28:25 +00:00
|
|
|
if (entry) return GetValue(entry);
|
|
|
|
return kInvalidRootIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-06-09 17:58:10 +00:00
|
|
|
base::HashMap* map_;
|
2015-10-23 08:28:25 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(RootIndexMap);
|
|
|
|
};
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
class SerializerReference {
|
2015-10-23 08:28:25 +00:00
|
|
|
public:
|
2016-05-18 11:28:53 +00:00
|
|
|
SerializerReference() : bitfield_(Special(kInvalidValue)) {}
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 14:38:43 +00:00
|
|
|
static SerializerReference FromBitfield(uint32_t bitfield) {
|
|
|
|
return SerializerReference(bitfield);
|
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static SerializerReference BackReference(AllocationSpace space,
|
|
|
|
uint32_t chunk_index,
|
|
|
|
uint32_t chunk_offset) {
|
|
|
|
DCHECK(IsAligned(chunk_offset, kObjectAlignment));
|
|
|
|
DCHECK_NE(LO_SPACE, space);
|
|
|
|
return SerializerReference(
|
|
|
|
SpaceBits::encode(space) | ChunkIndexBits::encode(chunk_index) |
|
|
|
|
ChunkOffsetBits::encode(chunk_offset >> kObjectAlignmentBits));
|
|
|
|
}
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-08-10 06:31:13 +00:00
|
|
|
static SerializerReference MapReference(uint32_t index) {
|
|
|
|
return SerializerReference(SpaceBits::encode(MAP_SPACE) |
|
|
|
|
ValueIndexBits::encode(index));
|
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static SerializerReference LargeObjectReference(uint32_t index) {
|
|
|
|
return SerializerReference(SpaceBits::encode(LO_SPACE) |
|
|
|
|
ValueIndexBits::encode(index));
|
|
|
|
}
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static SerializerReference AttachedReference(uint32_t index) {
|
|
|
|
return SerializerReference(SpaceBits::encode(kAttachedReferenceSpace) |
|
|
|
|
ValueIndexBits::encode(index));
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static SerializerReference DummyReference() {
|
|
|
|
return SerializerReference(Special(kDummyValue));
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
bool is_valid() const { return bitfield_ != Special(kInvalidValue); }
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
bool is_back_reference() const {
|
|
|
|
return SpaceBits::decode(bitfield_) <= LAST_SPACE;
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AllocationSpace space() const {
|
2016-05-18 11:28:53 +00:00
|
|
|
DCHECK(is_back_reference());
|
|
|
|
return static_cast<AllocationSpace>(SpaceBits::decode(bitfield_));
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t chunk_offset() const {
|
2016-05-18 11:28:53 +00:00
|
|
|
DCHECK(is_back_reference());
|
2015-10-23 08:28:25 +00:00
|
|
|
return ChunkOffsetBits::decode(bitfield_) << kObjectAlignmentBits;
|
|
|
|
}
|
|
|
|
|
2016-08-10 06:31:13 +00:00
|
|
|
uint32_t map_index() const {
|
|
|
|
DCHECK(is_back_reference());
|
|
|
|
return ValueIndexBits::decode(bitfield_);
|
|
|
|
}
|
|
|
|
|
2015-10-23 08:28:25 +00:00
|
|
|
uint32_t large_object_index() const {
|
2016-05-18 11:28:53 +00:00
|
|
|
DCHECK(is_back_reference());
|
2016-08-10 06:31:13 +00:00
|
|
|
return ValueIndexBits::decode(bitfield_);
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t chunk_index() const {
|
2016-05-18 11:28:53 +00:00
|
|
|
DCHECK(is_back_reference());
|
2015-10-23 08:28:25 +00:00
|
|
|
return ChunkIndexBits::decode(bitfield_);
|
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
uint32_t back_reference() const {
|
|
|
|
DCHECK(is_back_reference());
|
2015-10-23 08:28:25 +00:00
|
|
|
return bitfield_ & (ChunkOffsetBits::kMask | ChunkIndexBits::kMask);
|
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
bool is_attached_reference() const {
|
|
|
|
return SpaceBits::decode(bitfield_) == kAttachedReferenceSpace;
|
|
|
|
}
|
|
|
|
|
|
|
|
int attached_reference_index() const {
|
|
|
|
DCHECK(is_attached_reference());
|
|
|
|
return ValueIndexBits::decode(bitfield_);
|
|
|
|
}
|
2015-10-23 08:28:25 +00:00
|
|
|
|
|
|
|
private:
|
2016-05-18 14:38:43 +00:00
|
|
|
explicit SerializerReference(uint32_t bitfield) : bitfield_(bitfield) {}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
inline static uint32_t Special(int value) {
|
|
|
|
return SpaceBits::encode(kSpecialValueSpace) |
|
|
|
|
ValueIndexBits::encode(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We use the 32-bit bitfield to encode either a back reference, a special
|
2016-05-18 14:38:43 +00:00
|
|
|
// value, or an attached reference index.
|
2016-05-18 11:28:53 +00:00
|
|
|
// Back reference:
|
|
|
|
// [ Space index ] [ Chunk index ] [ Chunk offset ]
|
|
|
|
// [ LO_SPACE ] [ large object index ]
|
|
|
|
// Special value
|
|
|
|
// [ kSpecialValueSpace ] [ Special value index ]
|
|
|
|
// Attached reference
|
|
|
|
// [ kAttachedReferenceSpace ] [ Attached reference index ]
|
|
|
|
|
2015-10-23 08:28:25 +00:00
|
|
|
static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
|
|
|
|
static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
|
2016-05-18 11:28:53 +00:00
|
|
|
static const int kValueIndexSize = kChunkOffsetSize + kChunkIndexSize;
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static const int kSpecialValueSpace = LAST_SPACE + 1;
|
|
|
|
static const int kAttachedReferenceSpace = kSpecialValueSpace + 1;
|
|
|
|
STATIC_ASSERT(kAttachedReferenceSpace < (1 << kSpaceTagSize));
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
static const int kInvalidValue = 0;
|
|
|
|
static const int kDummyValue = 1;
|
|
|
|
|
|
|
|
// The chunk offset can also be used to encode the index of special values.
|
2015-10-23 08:28:25 +00:00
|
|
|
class ChunkOffsetBits : public BitField<uint32_t, 0, kChunkOffsetSize> {};
|
|
|
|
class ChunkIndexBits
|
|
|
|
: public BitField<uint32_t, ChunkOffsetBits::kNext, kChunkIndexSize> {};
|
2016-05-18 11:28:53 +00:00
|
|
|
class ValueIndexBits : public BitField<uint32_t, 0, kValueIndexSize> {};
|
2016-05-18 14:38:43 +00:00
|
|
|
STATIC_ASSERT(ChunkIndexBits::kNext == ValueIndexBits::kNext);
|
2016-05-18 11:28:53 +00:00
|
|
|
class SpaceBits : public BitField<int, kValueIndexSize, kSpaceTagSize> {};
|
|
|
|
STATIC_ASSERT(SpaceBits::kNext == 32);
|
2015-10-23 08:28:25 +00:00
|
|
|
|
|
|
|
uint32_t bitfield_;
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
friend class SerializerReferenceMap;
|
|
|
|
};
|
2015-10-23 08:28:25 +00:00
|
|
|
|
|
|
|
// Mapping objects to their location after deserialization.
|
|
|
|
// This is used during building, but not at runtime by V8.
|
2016-05-18 11:28:53 +00:00
|
|
|
class SerializerReferenceMap : public AddressMapBase {
|
2015-10-23 08:28:25 +00:00
|
|
|
public:
|
2016-05-18 11:28:53 +00:00
|
|
|
SerializerReferenceMap()
|
2016-09-29 13:53:09 +00:00
|
|
|
: no_allocation_(), map_(), attached_reference_index_(0) {}
|
2015-10-23 08:28:25 +00:00
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
SerializerReference Lookup(HeapObject* obj) {
|
2016-06-09 17:58:10 +00:00
|
|
|
base::HashMap::Entry* entry = LookupEntry(&map_, obj, false);
|
2016-05-18 11:28:53 +00:00
|
|
|
return entry ? SerializerReference(GetValue(entry)) : SerializerReference();
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
void Add(HeapObject* obj, SerializerReference b) {
|
2015-10-23 08:28:25 +00:00
|
|
|
DCHECK(b.is_valid());
|
2016-05-18 14:38:43 +00:00
|
|
|
DCHECK_NULL(LookupEntry(&map_, obj, false));
|
2016-06-09 17:58:10 +00:00
|
|
|
base::HashMap::Entry* entry = LookupEntry(&map_, obj, true);
|
2016-05-18 11:28:53 +00:00
|
|
|
SetValue(entry, b.bitfield_);
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
2016-05-18 11:28:53 +00:00
|
|
|
SerializerReference AddAttachedReference(HeapObject* attached_reference) {
|
|
|
|
SerializerReference reference =
|
|
|
|
SerializerReference::AttachedReference(attached_reference_index_++);
|
|
|
|
Add(attached_reference, reference);
|
|
|
|
return reference;
|
2015-10-23 08:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
DisallowHeapAllocation no_allocation_;
|
2016-06-09 17:58:10 +00:00
|
|
|
base::HashMap map_;
|
2016-05-18 11:28:53 +00:00
|
|
|
int attached_reference_index_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(SerializerReferenceMap);
|
2015-10-23 08:28:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_ADDRESS_MAP_H_
|