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));
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());
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));
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));
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));
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());
}
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();
}
}
-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);
};
+// 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.
//
// 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, \
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, \
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
// 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);
};
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);
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);
}