New version of v8 from bleeding edge at revision 3649
diff --git a/src/objects.h b/src/objects.h
index 671978a..40be0df 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -204,14 +204,13 @@
// instance_type is JS_OBJECT_TYPE.
//
// The names of the string instance types are intended to systematically
-// mirror their encoding in the instance_type field of the map. The length
-// (SHORT, MEDIUM, or LONG) is always mentioned. The default encoding is
-// considered TWO_BYTE. It is not mentioned in the name. ASCII encoding is
-// mentioned explicitly in the name. Likewise, the default representation is
-// considered sequential. It is not mentioned in the name. The other
-// representations (eg, CONS, EXTERNAL) are explicitly mentioned.
-// Finally, the string is either a SYMBOL_TYPE (if it is a symbol) or a
-// STRING_TYPE (if it is not a symbol).
+// mirror their encoding in the instance_type field of the map. The default
+// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
+// encoding is mentioned explicitly in the name. Likewise, the default
+// representation is considered sequential. It is not mentioned in the
+// name. The other representations (eg, CONS, EXTERNAL) are explicitly
+// mentioned. Finally, the string is either a SYMBOL_TYPE (if it is a
+// symbol) or a STRING_TYPE (if it is not a symbol).
//
// NOTE: The following things are some that depend on the string types having
// instance_types that are less than those of all other types:
@@ -237,11 +236,11 @@
V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE) \
\
V(MAP_TYPE) \
- V(HEAP_NUMBER_TYPE) \
- V(FIXED_ARRAY_TYPE) \
V(CODE_TYPE) \
V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
V(ODDBALL_TYPE) \
+ \
+ V(HEAP_NUMBER_TYPE) \
V(PROXY_TYPE) \
V(BYTE_ARRAY_TYPE) \
V(PIXEL_ARRAY_TYPE) \
@@ -257,6 +256,7 @@
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
V(FILLER_TYPE) \
\
+ V(FIXED_ARRAY_TYPE) \
V(ACCESSOR_INFO_TYPE) \
V(ACCESS_CHECK_INFO_TYPE) \
V(INTERCEPTOR_INFO_TYPE) \
@@ -383,11 +383,12 @@
const uint32_t kStringTag = 0x0;
const uint32_t kNotStringTag = 0x80;
-// If bit 7 is clear, bit 5 indicates that the string is a symbol (if set) or
-// not (if cleared).
-const uint32_t kIsSymbolMask = 0x20;
+// Bit 6 indicates that the object is a symbol (if set) or not (if cleared).
+// There are not enough types that the non-string types (with bit 7 set) can
+// have bit 6 set too.
+const uint32_t kIsSymbolMask = 0x40;
const uint32_t kNotSymbolTag = 0x0;
-const uint32_t kSymbolTag = 0x20;
+const uint32_t kSymbolTag = 0x40;
// If bit 7 is clear then bit 2 indicates whether the string consists of
// two-byte characters or one-byte characters.
@@ -418,6 +419,7 @@
enum InstanceType {
+ // String types.
SYMBOL_TYPE = kSymbolTag | kSeqStringTag,
ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
CONS_SYMBOL_TYPE = kSymbolTag | kConsStringTag,
@@ -433,56 +435,66 @@
EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
- MAP_TYPE = kNotStringTag,
- HEAP_NUMBER_TYPE,
- FIXED_ARRAY_TYPE,
+ // Objects allocated in their own spaces (never in new space).
+ MAP_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE
CODE_TYPE,
ODDBALL_TYPE,
JS_GLOBAL_PROPERTY_CELL_TYPE,
+
+ // "Data", objects that cannot contain non-map-word pointers to heap
+ // objects.
+ HEAP_NUMBER_TYPE,
PROXY_TYPE,
BYTE_ARRAY_TYPE,
PIXEL_ARRAY_TYPE,
- EXTERNAL_BYTE_ARRAY_TYPE,
+ EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
EXTERNAL_SHORT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
EXTERNAL_INT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
- EXTERNAL_FLOAT_ARRAY_TYPE,
- FILLER_TYPE,
- SMI_TYPE,
+ EXTERNAL_FLOAT_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
+ FILLER_TYPE, // LAST_DATA_TYPE
+ // Structs.
ACCESSOR_INFO_TYPE,
ACCESS_CHECK_INFO_TYPE,
INTERCEPTOR_INFO_TYPE,
- SHARED_FUNCTION_INFO_TYPE,
CALL_HANDLER_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
OBJECT_TEMPLATE_INFO_TYPE,
SIGNATURE_INFO_TYPE,
TYPE_SWITCH_INFO_TYPE,
+ SCRIPT_TYPE,
#ifdef ENABLE_DEBUGGER_SUPPORT
DEBUG_INFO_TYPE,
BREAK_POINT_INFO_TYPE,
#endif
- SCRIPT_TYPE,
- JS_VALUE_TYPE,
+ FIXED_ARRAY_TYPE,
+ SHARED_FUNCTION_INFO_TYPE,
+
+ JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
JS_OBJECT_TYPE,
JS_CONTEXT_EXTENSION_OBJECT_TYPE,
JS_GLOBAL_OBJECT_TYPE,
JS_BUILTINS_OBJECT_TYPE,
JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE,
- JS_REGEXP_TYPE,
+ JS_REGEXP_TYPE, // LAST_JS_OBJECT_TYPE
JS_FUNCTION_TYPE,
// Pseudo-types
- FIRST_NONSTRING_TYPE = MAP_TYPE,
FIRST_TYPE = 0x0,
- INVALID_TYPE = FIRST_TYPE - 1,
LAST_TYPE = JS_FUNCTION_TYPE,
+ INVALID_TYPE = FIRST_TYPE - 1,
+ FIRST_NONSTRING_TYPE = MAP_TYPE,
+ // Boundaries for testing for an external array.
+ FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
+ LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_FLOAT_ARRAY_TYPE,
+ // Boundary for promotion to old data space/old pointer space.
+ LAST_DATA_TYPE = FILLER_TYPE,
// Boundaries for testing the type is a JavaScript "object". Note that
// function objects are not counted as objects, even though they are
// implemented as such; only values whose typeof is "object" are included.
@@ -892,15 +904,25 @@
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 =
@@ -908,16 +930,12 @@
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:
@@ -1491,6 +1509,10 @@
#endif
Object* SlowReverseLookup(Object* value);
+ // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
+ // Also maximal value of JSArray's length property.
+ static const uint32_t kMaxElementCount = 0xffffffffu;
+
static const uint32_t kMaxGap = 1024;
static const int kMaxFastElementsLength = 5000;
static const int kInitialMaxFastElementArray = 100000;
@@ -1617,8 +1639,14 @@
// Casting.
static inline FixedArray* cast(Object* obj);
- // Align data at kPointerSize, even if Array.kHeaderSize isn't aligned.
- static const int kHeaderSize = POINTER_SIZE_ALIGN(Array::kHeaderSize);
+ static const int kHeaderSize = Array::kAlignedSize;
+
+ // Maximal allowed size, in bytes, of a single FixedArray.
+ // Prevents overflowing size computations, as well as extreme memory
+ // consumption.
+ static const int kMaxSize = 512 * MB;
+ // Maximally allowed length of a FixedArray.
+ static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Dispatched behavior.
int FixedArraySize() { return SizeFor(length()); }
@@ -1662,6 +1690,7 @@
public:
// Is this the singleton empty_descriptor_array?
inline bool IsEmpty();
+
// Returns the number of descriptors in the array.
int number_of_descriptors() {
return IsEmpty() ? 0 : length() - kFirstIndex;
@@ -1801,12 +1830,14 @@
static int ToKeyIndex(int descriptor_number) {
return descriptor_number+kFirstIndex;
}
+
+ static int ToDetailsIndex(int descriptor_number) {
+ return (descriptor_number << 1) + 1;
+ }
+
static int ToValueIndex(int descriptor_number) {
return descriptor_number << 1;
}
- static int ToDetailsIndex(int descriptor_number) {
- return( descriptor_number << 1) + 1;
- }
bool is_null_descriptor(int descriptor_number) {
return PropertyDetails(GetDetails(descriptor_number)).type() ==
@@ -1866,6 +1897,11 @@
return Smi::cast(get(kNumberOfElementsIndex))->value();
}
+ // Returns the number of deleted elements in the hash table.
+ int NumberOfDeletedElements() {
+ return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
+ }
+
// Returns the capacity of the hash table.
int Capacity() {
return Smi::cast(get(kCapacityIndex))->value();
@@ -1877,8 +1913,14 @@
// ElementRemoved should be called whenever an element is removed from
// a hash table.
- void ElementRemoved() { SetNumberOfElements(NumberOfElements() - 1); }
- void ElementsRemoved(int n) { SetNumberOfElements(NumberOfElements() - n); }
+ void ElementRemoved() {
+ SetNumberOfElements(NumberOfElements() - 1);
+ SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
+ }
+ void ElementsRemoved(int n) {
+ SetNumberOfElements(NumberOfElements() - n);
+ SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
+ }
// Returns a new HashTable object. Might return Failure.
static Object* Allocate(int at_least_space_for);
@@ -1905,17 +1947,24 @@
}
static const int kNumberOfElementsIndex = 0;
- static const int kCapacityIndex = 1;
- static const int kPrefixStartIndex = 2;
- static const int kElementsStartIndex =
+ static const int kNumberOfDeletedElementsIndex = 1;
+ static const int kCapacityIndex = 2;
+ static const int kPrefixStartIndex = 3;
+ static const int kElementsStartIndex =
kPrefixStartIndex + Shape::kPrefixSize;
- static const int kEntrySize = Shape::kEntrySize;
- static const int kElementsStartOffset =
+ static const int kEntrySize = Shape::kEntrySize;
+ static const int kElementsStartOffset =
kHeaderSize + kElementsStartIndex * kPointerSize;
// Constant used for denoting a absent entry.
static const int kNotFound = -1;
+ // Maximal capacity of HashTable. Based on maximal length of underlying
+ // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
+ // cannot overflow.
+ static const int kMaxCapacity =
+ (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
+
// Find entry for key otherwise return -1.
int FindEntry(Key key);
@@ -1935,12 +1984,18 @@
fast_set(this, kNumberOfElementsIndex, Smi::FromInt(nof));
}
+ // Update the number of deleted elements in the hash table.
+ void SetNumberOfDeletedElements(int nod) {
+ fast_set(this, kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
+ }
+
// Sets the capacity of the hash table.
void SetCapacity(int capacity) {
// To scale a computed hash code to fit within the hash table, we
// use bit-wise AND with a mask, so the capacity must be positive
// and non-zero.
ASSERT(capacity > 0);
+ ASSERT(capacity <= kMaxCapacity);
fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
}
@@ -1951,6 +2006,14 @@
return (hash + GetProbeOffset(number)) & (size - 1);
}
+ static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
+ return hash & (size - 1);
+ }
+
+ static uint32_t NextProbe(uint32_t last, uint32_t number, uint32_t size) {
+ return (last + number) & (size - 1);
+ }
+
// Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, Key key);
};
@@ -2280,6 +2343,11 @@
static const int kHeaderSize = Array::kHeaderSize;
static const int kAlignedSize = Array::kAlignedSize;
+ // Maximal memory consumption for a single ByteArray.
+ static const int kMaxSize = 512 * MB;
+ // Maximal length of a single ByteArray.
+ static const int kMaxLength = kMaxSize - kHeaderSize;
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};
@@ -2821,6 +2889,14 @@
return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
}
+ inline void set_is_extensible() {
+ set_bit_field2(bit_field2() | (1 << kIsExtensible));
+ }
+
+ inline bool is_extensible() {
+ return ((1 << kIsExtensible) & bit_field2()) != 0;
+ }
+
// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_is_access_check_needed(bool access_check_needed);
@@ -2838,7 +2914,6 @@
// [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
@@ -2906,7 +2981,8 @@
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;
@@ -2938,6 +3014,7 @@
// Bit positions for bit field 2
static const int kNeedsLoading = 0;
+ static const int kIsExtensible = 1;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
@@ -3566,6 +3643,14 @@
static const int kIrregexpCaptureCountIndex = kDataIndex + 3;
static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
+
+ // Offsets directly into the data fixed array.
+ static const int kDataTagOffset =
+ FixedArray::kHeaderSize + kTagIndex * kPointerSize;
+ static const int kDataAsciiCodeOffset =
+ FixedArray::kHeaderSize + kIrregexpASCIICodeIndex * kPointerSize;
+ static const int kIrregexpCaptureCountOffset =
+ FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
};
@@ -3989,6 +4074,12 @@
static const int kHeaderSize = String::kSize;
static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
+ // Maximal memory usage for a single sequential ASCII string.
+ static const int kMaxSize = 512 * MB;
+ // Maximal length of a single sequential ASCII string.
+ // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
+ static const int kMaxLength = (kMaxSize - kHeaderSize);
+
// Support for StringInputBuffer.
inline void SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset,
@@ -4035,6 +4126,12 @@
static const int kHeaderSize = String::kSize;
static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
+ // Maximal memory usage for a single sequential two-byte string.
+ static const int kMaxSize = 512 * MB;
+ // Maximal length of a single sequential two-byte string.
+ // Q.v. String::kMaxLength which is the maximal size of concatenated strings.
+ static const int kMaxLength = (kMaxSize - kHeaderSize) / sizeof(uint16_t);
+
// Support for StringInputBuffer.
inline void SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* buffer,
unsigned* offset_ptr,