From b5bbf957a859c44b2a108b3bb60443b18516dbdd Mon Sep 17 00:00:00 2001 From: "vitalyr@chromium.org" Date: Wed, 18 Aug 2010 13:00:38 +0000 Subject: [PATCH] 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 --- src/heap.cc | 20 ++++++++++---------- src/objects-debug.cc | 5 +++-- src/objects-inl.h | 22 +++++++++++++++------- src/objects.cc | 32 -------------------------------- src/objects.h | 20 +++++++++++--------- test/cctest/test-heap.cc | 4 ++-- 6 files changed, 41 insertions(+), 62 deletions(-) diff --git a/src/heap.cc b/src/heap.cc index 5f46fa7..ff92384 100644 --- a/src/heap.cc +++ b/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)); diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 0a97128..91aba26 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -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()); } diff --git a/src/objects-inl.h b/src/objects-inl.h index c70ab02..7bd4514 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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(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(this)->length()); + } if (instance_type == BYTE_ARRAY_TYPE) { return reinterpret_cast(this)->ByteArraySize(); } - // Otherwise do the general size computation. - return SlowSizeFromMap(map); + if (instance_type == STRING_TYPE) { + return SeqTwoByteString::SizeFor( + reinterpret_cast(this)->length()); + } + ASSERT(instance_type == CODE_TYPE); + return reinterpret_cast(this)->CodeSize(); } diff --git a/src/objects.cc b/src/objects.cc index 8359aa3..87a7efd 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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(instance_type); - - if (instance_type < FIRST_NONSTRING_TYPE - && (StringShape(instance_type).IsSequential())) { - if ((type & kStringEncodingMask) == kAsciiStringTag) { - SeqAsciiString* seq_ascii_this = reinterpret_cast(this); - return seq_ascii_this->SeqAsciiStringSize(instance_type); - } else { - SeqTwoByteString* self = reinterpret_cast(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(this)->ByteArraySize(); - case CODE_TYPE: - return reinterpret_cast(this)->CodeSize(); - case MAP_TYPE: - return Map::kSize; - default: - return map->instance_size(); - } -} - - void HeapObject::Iterate(ObjectVisitor* v) { // Handle header IteratePointer(v, kMapOffset); diff --git a/src/objects.h b/src/objects.h index 65e0f36..06b12c4 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 9d5e1f1..605d883 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -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); } -- 2.7.4