Make instance_size immediately useful for all fixed size objects.
For variable sized objects this field doesn't really make any sense so by putting a special value there we can improve SizeFromMap(). Review URL: http://codereview.chromium.org/3127016 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5301 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5a25c6d787
commit
b5bbf957a8
20
src/heap.cc
20
src/heap.cc
@ -1413,7 +1413,7 @@ bool Heap::CreateInitialMaps() {
|
||||
set_meta_map(new_meta_map);
|
||||
new_meta_map->set_map(new_meta_map);
|
||||
|
||||
obj = AllocatePartialMap(FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
|
||||
obj = AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_fixed_array_map(Map::cast(obj));
|
||||
|
||||
@ -1455,7 +1455,7 @@ bool Heap::CreateInitialMaps() {
|
||||
oddball_map()->set_prototype(null_value());
|
||||
oddball_map()->set_constructor(null_value());
|
||||
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_fixed_cow_array_map(Map::cast(obj));
|
||||
ASSERT(fixed_array_map() != fixed_cow_array_map());
|
||||
@ -1475,17 +1475,17 @@ bool Heap::CreateInitialMaps() {
|
||||
roots_[entry.index] = Map::cast(obj);
|
||||
}
|
||||
|
||||
obj = AllocateMap(STRING_TYPE, SeqTwoByteString::kAlignedSize);
|
||||
obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_undetectable_string_map(Map::cast(obj));
|
||||
Map::cast(obj)->set_is_undetectable();
|
||||
|
||||
obj = AllocateMap(ASCII_STRING_TYPE, SeqAsciiString::kAlignedSize);
|
||||
obj = AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_undetectable_ascii_string_map(Map::cast(obj));
|
||||
Map::cast(obj)->set_is_undetectable();
|
||||
|
||||
obj = AllocateMap(BYTE_ARRAY_TYPE, ByteArray::kAlignedSize);
|
||||
obj = AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_byte_array_map(Map::cast(obj));
|
||||
|
||||
@ -1528,7 +1528,7 @@ bool Heap::CreateInitialMaps() {
|
||||
if (obj->IsFailure()) return false;
|
||||
set_external_float_array_map(Map::cast(obj));
|
||||
|
||||
obj = AllocateMap(CODE_TYPE, Code::kHeaderSize);
|
||||
obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_code_map(Map::cast(obj));
|
||||
|
||||
@ -1552,19 +1552,19 @@ bool Heap::CreateInitialMaps() {
|
||||
roots_[entry.index] = Map::cast(obj);
|
||||
}
|
||||
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_hash_table_map(Map::cast(obj));
|
||||
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_context_map(Map::cast(obj));
|
||||
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_catch_context_map(Map::cast(obj));
|
||||
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, HeapObject::kHeaderSize);
|
||||
obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
if (obj->IsFailure()) return false;
|
||||
set_global_context_map(Map::cast(obj));
|
||||
|
||||
|
@ -640,8 +640,9 @@ void Map::MapPrint() {
|
||||
void Map::MapVerify() {
|
||||
ASSERT(!Heap::InNewSpace(this));
|
||||
ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
|
||||
ASSERT(kPointerSize <= instance_size()
|
||||
&& instance_size() < Heap::Capacity());
|
||||
ASSERT(instance_size() == kVariableSizeSentinel ||
|
||||
(kPointerSize <= instance_size() &&
|
||||
instance_size() < Heap::Capacity()));
|
||||
VerifyHeapPointer(prototype());
|
||||
VerifyHeapPointer(instance_descriptors());
|
||||
}
|
||||
|
@ -2111,20 +2111,28 @@ int Map::pre_allocated_property_fields() {
|
||||
|
||||
|
||||
int HeapObject::SizeFromMap(Map* map) {
|
||||
InstanceType instance_type = map->instance_type();
|
||||
int instance_size = map->instance_size();
|
||||
if (instance_size != kVariableSizeSentinel) return instance_size;
|
||||
// We can ignore the "symbol" bit becase it is only set for symbols
|
||||
// and implies a string type.
|
||||
int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
|
||||
// Only inline the most frequent cases.
|
||||
if (instance_type == JS_OBJECT_TYPE ||
|
||||
(instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
|
||||
(kStringTag | kConsStringTag) ||
|
||||
instance_type == JS_ARRAY_TYPE) return map->instance_size();
|
||||
if (instance_type == FIXED_ARRAY_TYPE) {
|
||||
return FixedArray::BodyDescriptor::SizeOf(map, this);
|
||||
}
|
||||
if (instance_type == ASCII_STRING_TYPE) {
|
||||
return SeqAsciiString::SizeFor(
|
||||
reinterpret_cast<SeqAsciiString*>(this)->length());
|
||||
}
|
||||
if (instance_type == BYTE_ARRAY_TYPE) {
|
||||
return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
|
||||
}
|
||||
// Otherwise do the general size computation.
|
||||
return SlowSizeFromMap(map);
|
||||
if (instance_type == STRING_TYPE) {
|
||||
return SeqTwoByteString::SizeFor(
|
||||
reinterpret_cast<SeqTwoByteString*>(this)->length());
|
||||
}
|
||||
ASSERT(instance_type == CODE_TYPE);
|
||||
return reinterpret_cast<Code*>(this)->CodeSize();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1024,38 +1024,6 @@ void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
|
||||
}
|
||||
|
||||
|
||||
int HeapObject::SlowSizeFromMap(Map* map) {
|
||||
// Avoid calling functions such as FixedArray::cast during GC, which
|
||||
// read map pointer of this object again.
|
||||
InstanceType instance_type = map->instance_type();
|
||||
uint32_t type = static_cast<uint32_t>(instance_type);
|
||||
|
||||
if (instance_type < FIRST_NONSTRING_TYPE
|
||||
&& (StringShape(instance_type).IsSequential())) {
|
||||
if ((type & kStringEncodingMask) == kAsciiStringTag) {
|
||||
SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
|
||||
return seq_ascii_this->SeqAsciiStringSize(instance_type);
|
||||
} else {
|
||||
SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
|
||||
return self->SeqTwoByteStringSize(instance_type);
|
||||
}
|
||||
}
|
||||
|
||||
switch (instance_type) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
return FixedArray::BodyDescriptor::SizeOf(map, this);
|
||||
case BYTE_ARRAY_TYPE:
|
||||
return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
|
||||
case CODE_TYPE:
|
||||
return reinterpret_cast<Code*>(this)->CodeSize();
|
||||
case MAP_TYPE:
|
||||
return Map::kSize;
|
||||
default:
|
||||
return map->instance_size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HeapObject::Iterate(ObjectVisitor* v) {
|
||||
// Handle header
|
||||
IteratePointer(v, kMapOffset);
|
||||
|
@ -201,6 +201,10 @@ enum PropertyNormalizationMode {
|
||||
};
|
||||
|
||||
|
||||
// Instance size sentinel for objects of variable size.
|
||||
static const int kVariableSizeSentinel = 0;
|
||||
|
||||
|
||||
// All Maps have a field instance_type containing a InstanceType.
|
||||
// It describes the type of the instances.
|
||||
//
|
||||
@ -304,11 +308,11 @@ enum PropertyNormalizationMode {
|
||||
// iterate over them.
|
||||
#define STRING_TYPE_LIST(V) \
|
||||
V(SYMBOL_TYPE, \
|
||||
SeqTwoByteString::kAlignedSize, \
|
||||
kVariableSizeSentinel, \
|
||||
symbol, \
|
||||
Symbol) \
|
||||
V(ASCII_SYMBOL_TYPE, \
|
||||
SeqAsciiString::kAlignedSize, \
|
||||
kVariableSizeSentinel, \
|
||||
ascii_symbol, \
|
||||
AsciiSymbol) \
|
||||
V(CONS_SYMBOL_TYPE, \
|
||||
@ -332,11 +336,11 @@ enum PropertyNormalizationMode {
|
||||
external_ascii_symbol, \
|
||||
ExternalAsciiSymbol) \
|
||||
V(STRING_TYPE, \
|
||||
SeqTwoByteString::kAlignedSize, \
|
||||
kVariableSizeSentinel, \
|
||||
string, \
|
||||
String) \
|
||||
V(ASCII_STRING_TYPE, \
|
||||
SeqAsciiString::kAlignedSize, \
|
||||
kVariableSizeSentinel, \
|
||||
ascii_string, \
|
||||
AsciiString) \
|
||||
V(CONS_STRING_TYPE, \
|
||||
@ -358,7 +362,7 @@ enum PropertyNormalizationMode {
|
||||
V(EXTERNAL_ASCII_STRING_TYPE, \
|
||||
ExternalAsciiString::kSize, \
|
||||
external_ascii_string, \
|
||||
ExternalAsciiString) \
|
||||
ExternalAsciiString)
|
||||
|
||||
// A struct is a simple object a set of object-valued fields. Including an
|
||||
// object type in this causes the compiler to generate most of the boilerplate
|
||||
@ -1100,10 +1104,6 @@ class HeapObject: public Object {
|
||||
// as above, for the single element at "offset"
|
||||
inline void IteratePointer(ObjectVisitor* v, int offset);
|
||||
|
||||
// Computes the object size from the map.
|
||||
// Should only be used from SizeFromMap.
|
||||
int SlowSizeFromMap(Map* map);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
|
||||
};
|
||||
@ -2993,6 +2993,8 @@ class Code: public HeapObject {
|
||||
class Map: public HeapObject {
|
||||
public:
|
||||
// Instance size.
|
||||
// Size in bytes or kVariableSizeSentinel if instances do not have
|
||||
// a fixed size.
|
||||
inline int instance_size();
|
||||
inline void set_instance_size(int value);
|
||||
|
||||
|
@ -36,8 +36,8 @@ TEST(HeapMaps) {
|
||||
InitializeVM();
|
||||
CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
|
||||
CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
|
||||
CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
|
||||
CheckMap(Heap::string_map(), STRING_TYPE, SeqTwoByteString::kAlignedSize);
|
||||
CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
||||
CheckMap(Heap::string_map(), STRING_TYPE, kVariableSizeSentinel);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user