const intptr_t kPointerAlignment = (1 << kPointerSizeLog2);
const intptr_t kPointerAlignmentMask = kPointerAlignment - 1;
+// Desired alignment for maps.
+#if V8_HOST_ARCH_64_BIT
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits;
+#else
+const intptr_t kMapAlignmentBits = kObjectAlignmentBits + 3;
+#endif
+const intptr_t kMapAlignment = (1 << kMapAlignmentBits);
+const intptr_t kMapAlignmentMask = kMapAlignment - 1;
// Tag information for Failure.
const int kFailureTag = 3;
#endif
+// Number of bits to represent the page size for paged spaces. The value of 13
+// gives 8K bytes per page.
+const int kPageSizeBits = 13;
+
+
// Constants relevant to double precision floating point numbers.
// Quiet NaNs have bits 51 to 62 set, possibly the sign bit, and no
#define POINTER_SIZE_ALIGN(value) \
(((value) + kPointerAlignmentMask) & ~kPointerAlignmentMask)
+// MAP_SIZE_ALIGN returns the value aligned as a map pointer.
+#define MAP_SIZE_ALIGN(value) \
+ (((value) + kMapAlignmentMask) & ~kMapAlignmentMask)
+
// The expression OFFSET_OF(type, field) computes the byte-offset
// of the specified field relative to the containing type. This
// corresponds to 'offsetof' (in stddef.h), except that it doesn't
#endif
Object* result = map_space_->AllocateRaw(Map::kSize);
if (result->IsFailure()) old_gen_exhausted_ = true;
+#ifdef DEBUG
+ if (!result->IsFailure()) {
+ // Maps have their own alignment.
+ CHECK((OffsetFrom(result) & kMapAlignmentMask) == kHeapObjectTag);
+ }
+#endif
return result;
}
map->set_unused_property_fields(0);
map->set_bit_field(0);
map->set_bit_field2(0);
+
+ // If the map object is aligned fill the padding area with Smi 0 objects.
+ if (Map::kPadStart < Map::kSize) {
+ memset(reinterpret_cast<byte*>(map) + Map::kPadStart - kHeapObjectTag,
+ 0,
+ Map::kSize - Map::kPadStart);
+ }
return map;
}
// The number of MapSpace pages is limited by the way we pack
// Map pointers during GC.
static const int kMaxMapSpaceSize =
- (1 << MapWord::kMapPageIndexBits) * Page::kPageSize;
+ (1 << (MapWord::kMapPageIndexBits)) * Page::kPageSize;
#if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB;
// space are encoded in their map pointer word (along with an encoding of
// their map pointers).
//
-// 31 21 20 10 9 0
-// +-----------------+------------------+-----------------+
-// |forwarding offset|page offset of map|page index of map|
-// +-----------------+------------------+-----------------+
-// 11 bits 11 bits 10 bits
+// The excact encoding is described in the comments for class MapWord in
+// objects.h.
//
// An address range [start, end) can have both live and non-live objects.
// Maximal non-live regions are marked so they can be skipped on subsequent
// exceed the object area size of a page.
ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
- int compact_offset = offset >> kObjectAlignmentBits;
+ uintptr_t 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 map_page_offset =
+ map_page->Offset(map_address) >> kMapAlignmentBits;
uintptr_t encoding =
(compact_offset << kForwardingOffsetShift) |
ASSERT_MAP_PAGE_INDEX(map_page_index);
int map_page_offset = static_cast<int>(
- ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
- << kObjectAlignmentBits);
+ ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
+ kMapAlignmentBits);
return (map_space->PageAddress(map_page_index) + map_page_offset);
}
static const int kOverflowBit = 1; // overflow bit
static const int kOverflowMask = (1 << kOverflowBit); // overflow mask
- // Forwarding pointers and map pointer encoding
- // 31 21 20 10 9 0
+ // Forwarding pointers and map pointer encoding. On 32 bit all the bits are
+ // used.
// +-----------------+------------------+-----------------+
// |forwarding offset|page offset of map|page index of map|
// +-----------------+------------------+-----------------+
- // 11 bits 11 bits 10 bits
- static const int kMapPageIndexBits = 10;
- static const int kMapPageOffsetBits = 11;
- static const int kForwardingOffsetBits = 11;
+ // ^ ^ ^
+ // | | |
+ // | | kMapPageIndexBits
+ // | kMapPageOffsetBits
+ // kForwardingOffsetBits
+ static const int kMapPageOffsetBits = kPageSizeBits - kMapAlignmentBits;
+ static const int kForwardingOffsetBits = kPageSizeBits - kObjectAlignmentBits;
+#ifdef V8_HOST_ARCH_64_BIT
+ static const int kMapPageIndexBits = 16;
+#else
+ // Use all the 32-bits to encode on a 32-bit platform.
+ static const int kMapPageIndexBits =
+ 32 - (kMapPageOffsetBits + kForwardingOffsetBits);
+#endif
static const int kMapPageIndexShift = 0;
static const int kMapPageOffsetShift =
static const int kForwardingOffsetShift =
kMapPageOffsetShift + kMapPageOffsetBits;
- // 0x000003FF
- static const uint32_t kMapPageIndexMask =
+ // Bit masks covering the different parts the encoding.
+ static const uintptr_t kMapPageIndexMask =
(1 << kMapPageOffsetShift) - 1;
-
- // 0x001FFC00
- static const uint32_t kMapPageOffsetMask =
+ static const uintptr_t kMapPageOffsetMask =
((1 << kForwardingOffsetShift) - 1) & ~kMapPageIndexMask;
-
- // 0xFFE00000
- static const uint32_t kForwardingOffsetMask =
+ static const uintptr_t kForwardingOffsetMask =
~(kMapPageIndexMask | kMapPageOffsetMask);
private:
// [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, FixedArray)
- // Returns a copy of the map.
Object* CopyDropDescriptors();
// Returns a copy of the map, with all transitions dropped from the
static const int kInstanceDescriptorsOffset =
kConstructorOffset + kPointerSize;
static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
- static const int kSize = kCodeCacheOffset + kPointerSize;
+ static const int kPadStart = kCodeCacheOffset + kPointerSize;
+ static const int kSize = MAP_SIZE_ALIGN(kPadStart);
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
return HeapObject::FromAddress(pages_[space][0] + offset);
}
ASSERT(SpaceIsPaged(space));
- int page_of_pointee = offset >> Page::kPageSizeBits;
+ int page_of_pointee = offset >> kPageSizeBits;
Address object_address = pages_[space][page_of_pointee] +
(offset & Page::kPageAlignmentMask);
return HeapObject::FromAddress(object_address);
int offset = CurrentAllocationAddress(space) - address;
bool from_start = true;
if (SpaceIsPaged(space)) {
- if ((CurrentAllocationAddress(space) >> Page::kPageSizeBits) ==
- (address >> Page::kPageSizeBits)) {
+ if ((CurrentAllocationAddress(space) >> kPageSizeBits) ==
+ (address >> kPageSizeBits)) {
from_start = false;
address = offset;
}
// start+size. Page::kPageSize is a power of two so we can divide by
// shifting.
return static_cast<int>((RoundDown(start + size, Page::kPageSize)
- - RoundUp(start, Page::kPageSize)) >> Page::kPageSizeBits);
+ - RoundUp(start, Page::kPageSize)) >> kPageSizeBits);
}
if (size_ + static_cast<int>(chunk_size) > capacity_) {
// Request as many pages as we can.
chunk_size = capacity_ - size_;
- requested_pages = static_cast<int>(chunk_size >> Page::kPageSizeBits);
+ requested_pages = static_cast<int>(chunk_size >> kPageSizeBits);
if (requested_pages <= 0) return Page::FromAddress(NULL);
}
// Some assertion macros used in the debugging mode.
-#define ASSERT_PAGE_ALIGNED(address) \
+#define ASSERT_PAGE_ALIGNED(address) \
ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0)
-#define ASSERT_OBJECT_ALIGNED(address) \
+#define ASSERT_OBJECT_ALIGNED(address) \
ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0)
-#define ASSERT_OBJECT_SIZE(size) \
+#define ASSERT_MAP_ALIGNED(address) \
+ ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0)
+
+#define ASSERT_OBJECT_SIZE(size) \
ASSERT((0 < size) && (size <= Page::kMaxHeapObjectSize))
-#define ASSERT_PAGE_OFFSET(offset) \
- ASSERT((Page::kObjectStartOffset <= offset) \
+#define ASSERT_PAGE_OFFSET(offset) \
+ ASSERT((Page::kObjectStartOffset <= offset) \
&& (offset <= Page::kPageSize))
-#define ASSERT_MAP_PAGE_INDEX(index) \
+#define ASSERT_MAP_PAGE_INDEX(index) \
ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex))
// For this reason we add an offset to get room for the Page data at the start.
//
// The mark-compact collector transforms a map pointer into a page index and a
-// page offset. The map space can have up to 1024 pages, and 8M bytes (1024 *
-// 8K) in total. Because a map pointer is aligned to the pointer size (4
-// bytes), 11 bits are enough to encode the page offset. 21 bits (10 for the
-// page index + 11 for the offset in the page) are required to encode a map
-// pointer.
+// page offset. The excact encoding is described in the comments for
+// class MapWord in objects.h.
//
// The only way to get a page pointer is by calling factory methods:
// Page* p = Page::FromAddress(addr); or
static void set_rset_state(RSetState state) { rset_state_ = state; }
#endif
- // 8K bytes per page.
- static const int kPageSizeBits = 13;
-
// Page size in bytes. This must be a multiple of the OS page size.
static const int kPageSize = 1 << kPageSizeBits;
#endif
// Due to encoding limitation, we can only have 8K chunks.
- static const int kMaxNofChunks = 1 << Page::kPageSizeBits;
+ static const int kMaxNofChunks = 1 << kPageSizeBits;
// If a chunk has at least 16 pages, the maximum heap size is about
// 8K * 8K * 16 = 1G bytes.
#ifdef V8_TARGET_ARCH_X64
# Very slow on ARM, contains no architecture dependent code.
unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm)
+# Skip long running test in debug.
+regress/regress-524: PASS, SKIP if $mode == debug
[ $arch == arm ]
--- /dev/null
+// Copyright 2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test allocation of a large number of maps.
+
+var i = 500000
+var a = new Array(i)
+for (var j = 0; j < i; j++) { var o = {}; o.x = 42; delete o.x; a[j] = o; }