aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/objects.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects.h')
-rw-r--r--deps/v8/src/objects.h850
1 files changed, 523 insertions, 327 deletions
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 88e3243fc2..45a2ac0d8f 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -33,7 +33,7 @@
#include "elements-kind.h"
#include "list.h"
#include "property-details.h"
-#include "smart-array-pointer.h"
+#include "smart-pointers.h"
#include "unicode-inl.h"
#if V8_TARGET_ARCH_ARM
#include "arm/constants-arm.h"
@@ -84,6 +84,7 @@
// - Context
// - JSFunctionResultCache
// - ScopeInfo
+// - TransitionArray
// - FixedDoubleArray
// - ExternalArray
// - ExternalPixelArray
@@ -170,17 +171,18 @@ enum CreationFlag {
};
-// Indicates whether the search function should expect a sorted or an unsorted
-// array as input.
-enum SearchMode {
- EXPECT_SORTED,
- EXPECT_UNSORTED
+// Indicates whether transitions can be added to a source map or not.
+enum TransitionFlag {
+ INSERT_TRANSITION,
+ OMIT_TRANSITION
};
// Instance size sentinel for objects of variable size.
const int kVariableSizeSentinel = 0;
+const int kStubMajorKeyBits = 6;
+const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
// All Maps have a field instance_type containing a InstanceType.
// It describes the type of the instances.
@@ -653,6 +655,25 @@ STATIC_CHECK(ODDBALL_TYPE == Internals::kOddballType);
STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
+#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
+ V(FAST_ELEMENTS_SUB_TYPE) \
+ V(DICTIONARY_ELEMENTS_SUB_TYPE) \
+ V(FAST_PROPERTIES_SUB_TYPE) \
+ V(DICTIONARY_PROPERTIES_SUB_TYPE) \
+ V(MAP_CODE_CACHE_SUB_TYPE) \
+ V(SCOPE_INFO_SUB_TYPE) \
+ V(SYMBOL_TABLE_SUB_TYPE) \
+ V(DESCRIPTOR_ARRAY_SUB_TYPE) \
+ V(TRANSITION_ARRAY_SUB_TYPE)
+
+enum FixedArraySubInstanceType {
+#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
+ FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
+#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
+ LAST_FIXED_ARRAY_SUB_TYPE = TRANSITION_ARRAY_SUB_TYPE
+};
+
+
enum CompareResult {
LESS = -1,
EQUAL = 0,
@@ -780,14 +801,14 @@ class MaybeObject BASE_EMBEDDED {
V(JSModule) \
V(Map) \
V(DescriptorArray) \
+ V(TransitionArray) \
V(DeoptimizationInputData) \
V(DeoptimizationOutputData) \
V(TypeFeedbackCells) \
V(FixedArray) \
V(FixedDoubleArray) \
V(Context) \
- V(GlobalContext) \
- V(ModuleContext) \
+ V(NativeContext) \
V(ScopeInfo) \
V(JSFunction) \
V(Code) \
@@ -883,8 +904,8 @@ class Object : public MaybeObject {
Object* ToBoolean(); // ECMA-262 9.2.
// Convert to a JSObject if needed.
- // global_context is used when creating wrapper object.
- MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
+ // native_context is used when creating wrapper object.
+ MUST_USE_RESULT MaybeObject* ToObject(Context* native_context);
// Converts this to a Smi if possible.
// Failure is returned otherwise.
@@ -949,6 +970,8 @@ class Object : public MaybeObject {
static void VerifyPointer(Object* p);
#endif
+ inline void VerifyApiCallResultType();
+
// Prints this object without details.
inline void ShortPrint() {
ShortPrint(stdout);
@@ -1233,9 +1256,6 @@ class HeapObject: public Object {
};
-#define SLOT_ADDR(obj, offset) \
- reinterpret_cast<Object**>((obj)->address() + offset)
-
// This class describes a body of an object of a fixed size
// in which all pointer fields are located in the [start_offset, end_offset)
// interval.
@@ -1250,8 +1270,8 @@ class FixedBodyDescriptor {
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj) {
- StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
- SLOT_ADDR(obj, end_offset));
+ StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
+ HeapObject::RawField(obj, end_offset));
}
};
@@ -1270,13 +1290,11 @@ class FlexibleBodyDescriptor {
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
- StaticVisitor::VisitPointers(SLOT_ADDR(obj, start_offset),
- SLOT_ADDR(obj, object_size));
+ StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
+ HeapObject::RawField(obj, object_size));
}
};
-#undef SLOT_ADDR
-
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
@@ -1435,6 +1453,9 @@ class JSReceiver: public HeapObject {
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
+ // Return the constructor function (may be Heap::null_value()).
+ inline Object* GetConstructor();
+
// Set the object's prototype (only JSReceiver and null are allowed).
MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
bool skip_hidden_prototypes);
@@ -1707,7 +1728,7 @@ class JSObject: public JSReceiver {
static int GetIdentityHash(Handle<JSObject> obj);
MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag);
- MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag);
+ MUST_USE_RESULT MaybeObject* SetIdentityHash(Smi* hash, CreationFlag flag);
static Handle<Object> DeleteProperty(Handle<JSObject> obj,
Handle<String> name);
@@ -1870,7 +1891,7 @@ class JSObject: public JSReceiver {
void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
- void LookupCallback(String* name, LookupResult* result);
+ void LookupCallbackProperty(String* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
@@ -1898,7 +1919,8 @@ class JSObject: public JSReceiver {
// new_map.
MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
String* name,
- Object* value);
+ Object* value,
+ int field_index);
// Add a constant function property to a fast-case object.
// This leaves a CONSTANT_TRANSITION in the old map, and
@@ -1931,19 +1953,15 @@ class JSObject: public JSReceiver {
MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
- // Converts a descriptor of any other type to a real field,
- // backed by the properties array. Descriptors of visible
- // types, such as CONSTANT_FUNCTION, keep their enumeration order.
- // Converts the descriptor on the original object's map to a
- // map transition, and the the new field is on the object's new map.
- MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
+ // Replaces an existing transition with a transition to a map with a FIELD.
+ MUST_USE_RESULT MaybeObject* ConvertTransitionToMapTransition(
+ int transition_index,
String* name,
Object* new_value,
PropertyAttributes attributes);
- // Converts a descriptor of any other type to a real field,
- // backed by the properties array. Descriptors of visible
- // types, such as CONSTANT_FUNCTION, keep their enumeration order.
+ // Converts a descriptor of any other type to a real field, backed by the
+ // properties array.
MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
String* name,
Object* new_value,
@@ -2056,6 +2074,10 @@ class JSObject: public JSReceiver {
PrintElements(stdout);
}
void PrintElements(FILE* out);
+ inline void PrintTransitions() {
+ PrintTransitions(stdout);
+ }
+ void PrintTransitions(FILE* out);
#endif
void PrintElementsTransition(
@@ -2209,18 +2231,23 @@ class JSObject: public JSReceiver {
Object* getter,
Object* setter,
PropertyAttributes attributes);
- void LookupInDescriptor(String* name, LookupResult* result);
-
- // Returns the hidden properties backing store object, currently
- // a StringDictionary, stored on this object.
- // If no hidden properties object has been put on this object,
- // return undefined, unless create_if_absent is true, in which case
- // a new dictionary is created, added to this object, and returned.
- MUST_USE_RESULT MaybeObject* GetHiddenPropertiesDictionary(
- bool create_if_absent);
- // Updates the existing hidden properties dictionary.
- MUST_USE_RESULT MaybeObject* SetHiddenPropertiesDictionary(
- StringDictionary* dictionary);
+
+
+ enum InitializeHiddenProperties {
+ CREATE_NEW_IF_ABSENT,
+ ONLY_RETURN_INLINE_VALUE
+ };
+
+ // If create_if_absent is true, return the hash table backing store
+ // for hidden properties. If there is no backing store, allocate one.
+ // If create_if_absent is false, return the hash table backing store
+ // or the inline stored identity hash, whatever is found.
+ MUST_USE_RESULT MaybeObject* GetHiddenPropertiesHashTable(
+ InitializeHiddenProperties init_option);
+ // Set the hidden property backing store to either a hash table or
+ // the inline-stored identity hash.
+ MUST_USE_RESULT MaybeObject* SetHiddenPropertiesHashTable(
+ Object* value);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
};
@@ -2244,6 +2271,8 @@ class FixedArrayBase: public HeapObject {
class FixedDoubleArray;
+class IncrementalMarking;
+
// FixedArray describes fixed-sized arrays with element type Object*.
class FixedArray: public FixedArrayBase {
@@ -2339,6 +2368,23 @@ class FixedArray: public FixedArrayBase {
}
};
+ // WhitenessWitness is used to prove that a descriptor array is white
+ // (unmarked), so incremental write barriers can be skipped because the
+ // marking invariant cannot be broken and slots pointing into evacuation
+ // candidates will be discovered when the object is scanned. A witness is
+ // always stack-allocated right after creating an array. By allocating a
+ // witness, incremental marking is globally disabled. The witness is then
+ // passed along wherever needed to statically prove that the array is known to
+ // be white.
+ class WhitenessWitness {
+ public:
+ inline explicit WhitenessWitness(FixedArray* array);
+ inline ~WhitenessWitness();
+
+ private:
+ IncrementalMarking* marking_;
+ };
+
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
@@ -2413,31 +2459,19 @@ class FixedDoubleArray: public FixedArrayBase {
};
-class IncrementalMarking;
-
-
// DescriptorArrays are fixed arrays used to hold instance descriptors.
// The format of the these objects is:
-// TODO(1399): It should be possible to make room for bit_field3 in the map
-// without overloading the instance descriptors field in the map
-// (and storing it in the DescriptorArray when the map has one).
-// [0]: storage for bit_field3 for Map owning this object (Smi)
-// [1]: point to a fixed array with (value, detail) pairs.
-// [2]: next enumeration index (Smi), or pointer to small fixed array:
-// [0]: next enumeration index (Smi)
-// [1]: pointer to fixed array with enum cache
-// [3]: first key
-// [length() - 1]: last key
-//
+// [0]: Either Smi(0) if uninitialized, or a pointer to small fixed array:
+// [0]: pointer to fixed array with enum cache
+// [1]: either Smi(0) or pointer to fixed array with indices
+// [1]: first key
+// [length() - kDescriptorSize]: last key
class DescriptorArray: public FixedArray {
public:
// Returns true for both shared empty_descriptor_array and for smis, which the
// map uses to encode additional bit fields when the descriptor array is not
// yet used.
inline bool IsEmpty();
- inline bool MayContainTransitions();
-
- DECL_ACCESSORS(elements_transition_map, Map)
// Returns the number of descriptors in the array.
int number_of_descriptors() {
@@ -2446,51 +2480,25 @@ class DescriptorArray: public FixedArray {
return len <= kFirstIndex ? 0 : (len - kFirstIndex) / kDescriptorSize;
}
- int NextEnumerationIndex() {
- if (IsEmpty()) return PropertyDetails::kInitialIndex;
- Object* obj = get(kEnumerationIndexIndex);
- if (obj->IsSmi()) {
- return Smi::cast(obj)->value();
- } else {
- Object* index = FixedArray::cast(obj)->get(kEnumCacheBridgeEnumIndex);
- return Smi::cast(index)->value();
- }
- }
+ inline int number_of_entries() { return number_of_descriptors(); }
+ inline int NextEnumerationIndex() { return number_of_descriptors() + 1; }
- // Set next enumeration index and flush any enum cache.
- void SetNextEnumerationIndex(int value) {
- if (!IsEmpty()) {
- set(kEnumerationIndexIndex, Smi::FromInt(value));
- }
- }
bool HasEnumCache() {
- return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
+ return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi();
}
Object* GetEnumCache() {
ASSERT(HasEnumCache());
- FixedArray* bridge = FixedArray::cast(get(kEnumerationIndexIndex));
+ FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
return bridge->get(kEnumCacheBridgeCacheIndex);
}
Object** GetEnumCacheSlot() {
ASSERT(HasEnumCache());
return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
- kEnumerationIndexOffset);
- }
-
- Object** GetTransitionsSlot() {
- ASSERT(elements_transition_map() != NULL);
- return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
- kTransitionsOffset);
+ kEnumCacheOffset);
}
- // TODO(1399): It should be possible to make room for bit_field3 in the map
- // without overloading the instance descriptors field in the map
- // (and storing it in the DescriptorArray when the map has one).
- inline int bit_field3_storage();
- inline void set_bit_field3_storage(int value);
-
// Initialize or change the enum cache,
// using the supplied storage for the small "bridge".
void SetEnumCache(FixedArray* bridge_storage,
@@ -2502,34 +2510,16 @@ class DescriptorArray: public FixedArray {
inline Object** GetKeySlot(int descriptor_number);
inline Object* GetValue(int descriptor_number);
inline Object** GetValueSlot(int descriptor_number);
- inline void SetNullValueUnchecked(int descriptor_number, Heap* heap);
inline PropertyDetails GetDetails(int descriptor_number);
- inline void SetDetailsUnchecked(int descriptor_number, Smi* value);
inline PropertyType GetType(int descriptor_number);
inline int GetFieldIndex(int descriptor_number);
inline JSFunction* GetConstantFunction(int descriptor_number);
inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number);
- inline bool IsProperty(int descriptor_number);
- inline bool IsTransitionOnly(int descriptor_number);
- inline bool IsNullDescriptor(int descriptor_number);
- // WhitenessWitness is used to prove that a specific descriptor array is white
- // (unmarked), so incremental write barriers can be skipped because the
- // marking invariant cannot be broken and slots pointing into evacuation
- // candidates will be discovered when the object is scanned. A witness is
- // always stack-allocated right after creating a descriptor array. By
- // allocating a witness, incremental marking is globally disabled. The witness
- // is then passed along wherever needed to statically prove that the
- // descriptor array is known to be white.
- class WhitenessWitness {
- public:
- inline explicit WhitenessWitness(DescriptorArray* array);
- inline ~WhitenessWitness();
-
- private:
- IncrementalMarking* marking_;
- };
+ inline String* GetSortedKey(int descriptor_number);
+ inline int GetSortedKeyIndex(int descriptor_number);
+ inline void SetSortedKey(int pointer, int descriptor_number);
// Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc);
@@ -2537,48 +2527,23 @@ class DescriptorArray: public FixedArray {
Descriptor* desc,
const WhitenessWitness&);
- // Transfer a complete descriptor from the src descriptor array to the dst
- // one, dropping map transitions in CALLBACKS.
- static void CopyFrom(Handle<DescriptorArray> dst,
- int dst_index,
- Handle<DescriptorArray> src,
- int src_index,
- const WhitenessWitness& witness);
+ // Append automatically sets the enumeration index. This should only be used
+ // to add descriptors in bulk at the end, followed by sorting the descriptor
+ // array.
+ inline void Append(Descriptor* desc,
+ const WhitenessWitness&,
+ int number_of_set_descriptors);
// Transfer a complete descriptor from the src descriptor array to this
- // descriptor array, dropping map transitions in CALLBACKS.
- MUST_USE_RESULT MaybeObject* CopyFrom(int dst_index,
- DescriptorArray* src,
- int src_index,
- const WhitenessWitness&);
-
- // Copy the descriptor array, insert a new descriptor and optionally
- // remove map transitions. If the descriptor is already present, it is
- // replaced. If a replaced descriptor is a real property (not a transition
- // or null), its enumeration index is kept as is.
- // If adding a real property, map transitions must be removed. If adding
- // a transition, they must not be removed. All null descriptors are removed.
- MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
- TransitionFlag transition_flag);
-
- // Indicates whether the search function should expect a sorted or an unsorted
- // descriptor array as input.
- enum SharedMode {
- MAY_BE_SHARED,
- CANNOT_BE_SHARED
- };
-
- // Return a copy of the array with all transitions and null descriptors
- // removed. Return a Failure object in case of an allocation failure.
- MUST_USE_RESULT MaybeObject* RemoveTransitions(SharedMode shared_mode);
+ // descriptor array.
+ void CopyFrom(int dst_index,
+ DescriptorArray* src,
+ int src_index,
+ const WhitenessWitness&);
// Sort the instance descriptors by the hash codes of their keys.
- // Does not check for duplicates.
- void SortUnchecked(const WhitenessWitness&);
-
- // Sort the instance descriptors by the hash codes of their keys.
- // Checks the result for duplicates.
- void Sort(const WhitenessWitness&);
+ void Sort();
+ inline void SwapSortedKeys(int first, int second);
// Search the instance descriptors for given name.
INLINE(int Search(String* name));
@@ -2590,21 +2555,9 @@ class DescriptorArray: public FixedArray {
// Tells whether the name is present int the array.
bool Contains(String* name) { return kNotFound != Search(name); }
- // Perform a binary search in the instance descriptors represented
- // by this fixed array. low and high are descriptor indices. If there
- // are three instance descriptors in this array it should be called
- // with low=0 and high=2.
- int BinarySearch(String* name, int low, int high);
-
- // Perform a linear search in the instance descriptors represented
- // by this fixed array. len is the number of descriptor indices that are
- // valid.
- int LinearSearch(SearchMode mode, String* name, int len);
-
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
- MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors,
- SharedMode shared_mode);
+ MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
// Casting.
static inline DescriptorArray* cast(Object* obj);
@@ -2612,28 +2565,20 @@ class DescriptorArray: public FixedArray {
// Constant for denoting key was not found.
static const int kNotFound = -1;
- static const int kBitField3StorageIndex = 0;
- static const int kEnumerationIndexIndex = 1;
- static const int kTransitionsIndex = 2;
- static const int kFirstIndex = 3;
+ static const int kEnumCacheIndex = 0;
+ static const int kFirstIndex = 1;
// The length of the "bridge" to the enum cache.
- static const int kEnumCacheBridgeLength = 3;
- static const int kEnumCacheBridgeEnumIndex = 0;
- static const int kEnumCacheBridgeCacheIndex = 1;
- static const int kEnumCacheBridgeIndicesCacheIndex = 2;
+ static const int kEnumCacheBridgeLength = 2;
+ static const int kEnumCacheBridgeCacheIndex = 0;
+ static const int kEnumCacheBridgeIndicesCacheIndex = 1;
// Layout description.
- static const int kBitField3StorageOffset = FixedArray::kHeaderSize;
- static const int kEnumerationIndexOffset =
- kBitField3StorageOffset + kPointerSize;
- static const int kTransitionsOffset = kEnumerationIndexOffset + kPointerSize;
- static const int kFirstOffset = kTransitionsOffset + kPointerSize;
+ static const int kEnumCacheOffset = FixedArray::kHeaderSize;
+ static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
// Layout description for the bridge array.
- static const int kEnumCacheBridgeEnumOffset = FixedArray::kHeaderSize;
- static const int kEnumCacheBridgeCacheOffset =
- kEnumCacheBridgeEnumOffset + kPointerSize;
+ static const int kEnumCacheBridgeCacheOffset = FixedArray::kHeaderSize;
// Layout of descriptor.
static const int kDescriptorKey = 0;
@@ -2664,6 +2609,12 @@ class DescriptorArray: public FixedArray {
// fit in a page).
static const int kMaxNumberOfDescriptors = 1024 + 512;
+ // Returns the fixed array length required to hold number_of_descriptors
+ // descriptors.
+ static int LengthFor(int number_of_descriptors) {
+ return ToKeyIndex(number_of_descriptors);
+ }
+
private:
// An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry {
@@ -2702,7 +2653,7 @@ class DescriptorArray: public FixedArray {
static inline void NoIncrementalWriteBarrierSwap(
FixedArray* array, int first, int second);
- // Swap descriptor first and second.
+ // Swap first and second descriptor.
inline void NoIncrementalWriteBarrierSwapDescriptors(
int first, int second);
@@ -2710,6 +2661,14 @@ class DescriptorArray: public FixedArray {
};
+template<typename T>
+inline int LinearSearch(T* array, String* name, int len);
+
+
+template<typename T>
+inline int Search(T* array, String* name);
+
+
// HashTable is a subclass of FixedArray that implements a hash table
// that uses open addressing and quadratic probing.
//
@@ -2762,6 +2721,11 @@ class BaseShape {
template<typename Shape, typename Key>
class HashTable: public FixedArray {
public:
+ enum MinimumCapacity {
+ USE_DEFAULT_MINIMUM_CAPACITY,
+ USE_CUSTOM_MINIMUM_CAPACITY
+ };
+
// Wrapper methods
inline uint32_t Hash(Key key) {
if (Shape::UsesSeed) {
@@ -2814,6 +2778,7 @@ class HashTable: public FixedArray {
// Returns a new HashTable object. Might return Failure.
MUST_USE_RESULT static MaybeObject* Allocate(
int at_least_space_for,
+ MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY,
PretenureFlag pretenure = NOT_TENURED);
// Computes the required capacity for a table holding the given
@@ -3091,6 +3056,7 @@ class Dictionary: public HashTable<Shape, Key> {
// Accessors for next enumeration index.
void SetNextEnumerationIndex(int index) {
+ ASSERT(index != 0);
this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}
@@ -3164,7 +3130,9 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
}
// Copies enumerable keys to preallocated fixed array.
- void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
+ FixedArray* CopyEnumKeysTo(FixedArray* storage);
+ static void DoGenerateNewEnumerationIndices(
+ Handle<StringDictionary> dictionary);
// For transforming properties of a JSObject.
MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
@@ -3174,8 +3142,6 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
// Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry.
int FindEntry(String* key);
-
- bool ContainsTransition(int entry);
};
@@ -3321,12 +3287,12 @@ class ObjectHashTable: public HashTable<ObjectHashTableShape<2>, Object*> {
return reinterpret_cast<ObjectHashTable*>(obj);
}
- // Looks up the value associated with the given key. The undefined value is
+ // Looks up the value associated with the given key. The hole value is
// returned in case the key is not present.
Object* Lookup(Object* key);
// Adds (or overwrites) the value associated with the given key. Mapping a
- // key to the undefined value causes removal of the whole entry.
+ // key to the hole value causes removal of the whole entry.
MUST_USE_RESULT MaybeObject* Put(Object* key, Object* value);
private:
@@ -3523,7 +3489,7 @@ class ScopeInfo : public FixedArray {
FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
#undef DECL_INDEX
#undef FOR_EACH_NUMERIC_FIELD
- kVariablePartIndex
+ kVariablePartIndex
};
// The layout of the variable part of a ScopeInfo is as follows:
@@ -4024,7 +3990,7 @@ class DeoptimizationInputData: public FixedArray {
static const int kFirstDeoptEntryIndex = 5;
// Offsets of deopt entry elements relative to the start of the entry.
- static const int kAstIdOffset = 0;
+ static const int kAstIdRawOffset = 0;
static const int kTranslationIndexOffset = 1;
static const int kArgumentsStackHeightOffset = 2;
static const int kPcOffset = 3;
@@ -4056,13 +4022,21 @@ class DeoptimizationInputData: public FixedArray {
set(IndexForEntry(i) + k##name##Offset, value); \
}
- DEFINE_ENTRY_ACCESSORS(AstId, Smi)
+ DEFINE_ENTRY_ACCESSORS(AstIdRaw, Smi)
DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
DEFINE_ENTRY_ACCESSORS(Pc, Smi)
#undef DEFINE_ENTRY_ACCESSORS
+ BailoutId AstId(int i) {
+ return BailoutId(AstIdRaw(i)->value());
+ }
+
+ void SetAstId(int i, BailoutId value) {
+ SetAstIdRaw(i, Smi::FromInt(value.ToInt()));
+ }
+
int DeoptCount() {
return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
}
@@ -4097,8 +4071,15 @@ class DeoptimizationInputData: public FixedArray {
class DeoptimizationOutputData: public FixedArray {
public:
int DeoptPoints() { return length() / 2; }
- Smi* AstId(int index) { return Smi::cast(get(index * 2)); }
- void SetAstId(int index, Smi* id) { set(index * 2, id); }
+
+ BailoutId AstId(int index) {
+ return BailoutId(Smi::cast(get(index * 2))->value());
+ }
+
+ void SetAstId(int index, BailoutId id) {
+ set(index * 2, Smi::FromInt(id.ToInt()));
+ }
+
Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
@@ -4133,8 +4114,8 @@ class TypeFeedbackCells: public FixedArray {
static int LengthOfFixedArray(int cell_count) { return cell_count * 2; }
// Accessors for AST ids associated with cache values.
- inline Smi* AstId(int index);
- inline void SetAstId(int index, Smi* id);
+ inline TypeFeedbackId AstId(int index);
+ inline void SetAstId(int index, TypeFeedbackId id);
// Accessors for global property cells holding the cache values.
inline JSGlobalPropertyCell* Cell(int index);
@@ -4174,30 +4155,49 @@ class Code: public HeapObject {
FLAGS_MAX_VALUE = kMaxInt
};
+#define CODE_KIND_LIST(V) \
+ V(FUNCTION) \
+ V(OPTIMIZED_FUNCTION) \
+ V(STUB) \
+ V(BUILTIN) \
+ V(LOAD_IC) \
+ V(KEYED_LOAD_IC) \
+ V(CALL_IC) \
+ V(KEYED_CALL_IC) \
+ V(STORE_IC) \
+ V(KEYED_STORE_IC) \
+ V(UNARY_OP_IC) \
+ V(BINARY_OP_IC) \
+ V(COMPARE_IC) \
+ V(TO_BOOLEAN_IC)
+
enum Kind {
- FUNCTION,
- OPTIMIZED_FUNCTION,
- STUB,
- BUILTIN,
- LOAD_IC,
- KEYED_LOAD_IC,
- CALL_IC,
- KEYED_CALL_IC,
- STORE_IC,
- KEYED_STORE_IC,
- UNARY_OP_IC,
- BINARY_OP_IC,
- COMPARE_IC,
- TO_BOOLEAN_IC,
- // No more than 16 kinds. The value currently encoded in four bits in
- // Flags.
+#define DEFINE_CODE_KIND_ENUM(name) name,
+ CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
+#undef DEFINE_CODE_KIND_ENUM
// Pseudo-kinds.
+ LAST_CODE_KIND = TO_BOOLEAN_IC,
REGEXP = BUILTIN,
FIRST_IC_KIND = LOAD_IC,
LAST_IC_KIND = TO_BOOLEAN_IC
};
+ // No more than 16 kinds. The value is currently encoded in four bits in
+ // Flags.
+ STATIC_ASSERT(LAST_CODE_KIND < 16);
+
+ // Types of stubs.
+ enum StubType {
+ NORMAL,
+ FIELD,
+ CONSTANT_FUNCTION,
+ CALLBACKS,
+ INTERCEPTOR,
+ MAP_TRANSITION,
+ NONEXISTENT
+ };
+
enum {
NUMBER_OF_KINDS = LAST_IC_KIND + 1
};
@@ -4210,7 +4210,7 @@ class Code: public HeapObject {
// Printing
static const char* Kind2String(Kind kind);
static const char* ICState2String(InlineCacheState state);
- static const char* PropertyType2String(PropertyType type);
+ static const char* StubType2String(StubType type);
static void PrintExtraICState(FILE* out, Kind kind, ExtraICState extra);
inline void Disassemble(const char* name) {
Disassemble(name, stdout);
@@ -4260,7 +4260,7 @@ class Code: public HeapObject {
inline Kind kind();
inline InlineCacheState ic_state(); // Only valid for IC stubs.
inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
- inline PropertyType type(); // Only valid for monomorphic IC stubs.
+ inline StubType type(); // Only valid for monomorphic IC stubs.
inline int arguments_count(); // Only valid for call IC stubs.
// Testers for IC stub kinds.
@@ -4403,19 +4403,19 @@ class Code: public HeapObject {
Kind kind,
InlineCacheState ic_state = UNINITIALIZED,
ExtraICState extra_ic_state = kNoExtraICState,
- PropertyType type = NORMAL,
+ StubType type = NORMAL,
int argc = -1,
InlineCacheHolderFlag holder = OWN_MAP);
static inline Flags ComputeMonomorphicFlags(
Kind kind,
- PropertyType type,
+ StubType type,
ExtraICState extra_ic_state = kNoExtraICState,
InlineCacheHolderFlag holder = OWN_MAP,
int argc = -1);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
- static inline PropertyType ExtractTypeFromFlags(Flags flags);
+ static inline StubType ExtractTypeFromFlags(Flags flags);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
@@ -4510,28 +4510,20 @@ class Code: public HeapObject {
static const int kICAgeOffset =
kGCMetadataOffset + kPointerSize;
static const int kFlagsOffset = kICAgeOffset + kIntSize;
- static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
- static const int kKindSpecificFlagsSize = 2 * kIntSize;
+ static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize;
+ static const int kKindSpecificFlags2Offset =
+ kKindSpecificFlags1Offset + kIntSize;
- static const int kHeaderPaddingStart = kKindSpecificFlagsOffset +
- kKindSpecificFlagsSize;
+ static const int kHeaderPaddingStart = kKindSpecificFlags2Offset + kIntSize;
// Add padding to align the instruction start following right after
// the Code object header.
static const int kHeaderSize =
(kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
- // Byte offsets within kKindSpecificFlagsOffset.
- static const int kStubMajorKeyOffset = kKindSpecificFlagsOffset;
- static const int kOptimizableOffset = kKindSpecificFlagsOffset;
- static const int kStackSlotsOffset = kKindSpecificFlagsOffset;
- static const int kCheckTypeOffset = kKindSpecificFlagsOffset;
-
- static const int kUnaryOpTypeOffset = kStubMajorKeyOffset + 1;
- static const int kBinaryOpTypeOffset = kStubMajorKeyOffset + 1;
- static const int kCompareStateOffset = kStubMajorKeyOffset + 1;
- static const int kToBooleanTypeOffset = kStubMajorKeyOffset + 1;
- static const int kHasFunctionCacheOffset = kStubMajorKeyOffset + 1;
+ // Byte offsets within kKindSpecificFlags1Offset.
+ static const int kOptimizableOffset = kKindSpecificFlags1Offset;
+ static const int kCheckTypeOffset = kKindSpecificFlags1Offset;
static const int kFullCodeFlags = kOptimizableOffset + 1;
class FullCodeFlagsHasDeoptimizationSupportField:
@@ -4539,26 +4531,90 @@ class Code: public HeapObject {
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
- static const int kBinaryOpReturnTypeOffset = kBinaryOpTypeOffset + 1;
-
- static const int kCompareOperationOffset = kCompareStateOffset + 1;
-
static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
static const int kProfilerTicksOffset = kAllowOSRAtLoopNestingLevelOffset + 1;
- static const int kSafepointTableOffsetOffset = kStackSlotsOffset + kIntSize;
- static const int kStackCheckTableOffsetOffset = kStackSlotsOffset + kIntSize;
-
// Flags layout. BitField<type, shift, size>.
class ICStateField: public BitField<InlineCacheState, 0, 3> {};
- class TypeField: public BitField<PropertyType, 3, 4> {};
- class CacheHolderField: public BitField<InlineCacheHolderFlag, 7, 1> {};
- class KindField: public BitField<Kind, 8, 4> {};
- class ExtraICStateField: public BitField<ExtraICState, 12, 2> {};
- class IsPregeneratedField: public BitField<bool, 14, 1> {};
+ class TypeField: public BitField<StubType, 3, 3> {};
+ class CacheHolderField: public BitField<InlineCacheHolderFlag, 6, 1> {};
+ class KindField: public BitField<Kind, 7, 4> {};
+ class ExtraICStateField: public BitField<ExtraICState, 11, 2> {};
+ class IsPregeneratedField: public BitField<bool, 13, 1> {};
+
+ // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
+ static const int kStackSlotsFirstBit = 0;
+ static const int kStackSlotsBitCount = 24;
+ static const int kUnaryOpTypeFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kUnaryOpTypeBitCount = 3;
+ static const int kBinaryOpTypeFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kBinaryOpTypeBitCount = 3;
+ static const int kBinaryOpResultTypeFirstBit =
+ kBinaryOpTypeFirstBit + kBinaryOpTypeBitCount;
+ static const int kBinaryOpResultTypeBitCount = 3;
+ static const int kCompareStateFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kCompareStateBitCount = 3;
+ static const int kCompareOperationFirstBit =
+ kCompareStateFirstBit + kCompareStateBitCount;
+ static const int kCompareOperationBitCount = 4;
+ static const int kToBooleanStateFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kToBooleanStateBitCount = 8;
+ static const int kHasFunctionCacheFirstBit =
+ kStackSlotsFirstBit + kStackSlotsBitCount;
+ static const int kHasFunctionCacheBitCount = 1;
+
+ STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
+ STATIC_ASSERT(kUnaryOpTypeFirstBit + kUnaryOpTypeBitCount <= 32);
+ STATIC_ASSERT(kBinaryOpTypeFirstBit + kBinaryOpTypeBitCount <= 32);
+ STATIC_ASSERT(kBinaryOpResultTypeFirstBit +
+ kBinaryOpResultTypeBitCount <= 32);
+ STATIC_ASSERT(kCompareStateFirstBit + kCompareStateBitCount <= 32);
+ STATIC_ASSERT(kCompareOperationFirstBit + kCompareOperationBitCount <= 32);
+ STATIC_ASSERT(kToBooleanStateFirstBit + kToBooleanStateBitCount <= 32);
+ STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
+
+ class StackSlotsField: public BitField<int,
+ kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
+ class UnaryOpTypeField: public BitField<int,
+ kUnaryOpTypeFirstBit, kUnaryOpTypeBitCount> {}; // NOLINT
+ class BinaryOpTypeField: public BitField<int,
+ kBinaryOpTypeFirstBit, kBinaryOpTypeBitCount> {}; // NOLINT
+ class BinaryOpResultTypeField: public BitField<int,
+ kBinaryOpResultTypeFirstBit, kBinaryOpResultTypeBitCount> {}; // NOLINT
+ class CompareStateField: public BitField<int,
+ kCompareStateFirstBit, kCompareStateBitCount> {}; // NOLINT
+ class CompareOperationField: public BitField<int,
+ kCompareOperationFirstBit, kCompareOperationBitCount> {}; // NOLINT
+ class ToBooleanStateField: public BitField<int,
+ kToBooleanStateFirstBit, kToBooleanStateBitCount> {}; // NOLINT
+ class HasFunctionCacheField: public BitField<bool,
+ kHasFunctionCacheFirstBit, kHasFunctionCacheBitCount> {}; // NOLINT
+
+ // KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION)
+ static const int kStubMajorKeyFirstBit = 0;
+ static const int kSafepointTableOffsetFirstBit =
+ kStubMajorKeyFirstBit + kStubMajorKeyBits;
+ static const int kSafepointTableOffsetBitCount = 26;
+
+ STATIC_ASSERT(kStubMajorKeyFirstBit + kStubMajorKeyBits <= 32);
+ STATIC_ASSERT(kSafepointTableOffsetFirstBit +
+ kSafepointTableOffsetBitCount <= 32);
+
+ class SafepointTableOffsetField: public BitField<int,
+ kSafepointTableOffsetFirstBit,
+ kSafepointTableOffsetBitCount> {}; // NOLINT
+ class StubMajorKeyField: public BitField<int,
+ kStubMajorKeyFirstBit, kStubMajorKeyBits> {}; // NOLINT
+
+ // KindSpecificFlags2 layout (FUNCTION)
+ class StackCheckTableOffsetField: public BitField<int, 0, 31> {};
// Signed field cannot be encoded using the BitField class.
- static const int kArgumentsCountShift = 15;
+ static const int kArgumentsCountShift = 14;
static const int kArgumentsCountMask = ~((1 << kArgumentsCountShift) - 1);
// This constant should be encodable in an ARM instruction.
@@ -4608,12 +4664,15 @@ class Map: public HeapObject {
inline void set_bit_field2(byte value);
// Bit field 3.
- // TODO(1399): It should be possible to make room for bit_field3 in the map
- // without overloading the instance descriptors field (and storing it in the
- // DescriptorArray when the map has one).
inline int bit_field3();
inline void set_bit_field3(int value);
+ class EnumLengthBits: public BitField<int, 0, 11> {};
+ class NumberOfOwnDescriptorsBits: public BitField<int, 11, 11> {};
+ class IsShared: public BitField<bool, 22, 1> {};
+ class FunctionWithPrototype: public BitField<bool, 23, 1> {};
+ class DictionaryMap: public BitField<bool, 24, 1> {};
+
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
// property is set to a value that is not a JSObject, the prototype
@@ -4733,8 +4792,16 @@ class Map: public HeapObject {
static bool IsValidElementsTransition(ElementsKind from_kind,
ElementsKind to_kind);
+ inline bool HasTransitionArray();
+ inline bool HasElementsTransition();
inline Map* elements_transition_map();
- inline void set_elements_transition_map(Map* transitioned_map);
+ MUST_USE_RESULT inline MaybeObject* set_elements_transition_map(
+ Map* transitioned_map);
+ inline void SetTransition(int index, Map* target);
+ MUST_USE_RESULT inline MaybeObject* AddTransition(String* key, Map* target);
+ DECL_ACCESSORS(transitions, TransitionArray)
+ inline void ClearTransitions(Heap* heap,
+ WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Tells whether the map is attached to SharedFunctionInfo
// (for inobject slack tracking).
@@ -4748,6 +4815,13 @@ class Map: public HeapObject {
inline void set_is_shared(bool value);
inline bool is_shared();
+ // Tells whether the map is used for JSObjects in dictionary mode (ie
+ // normalized objects, ie objects for which HasFastProperties returns false).
+ // A map can never be used for both dictionary mode and fast mode JSObjects.
+ // False by default and for HeapObjects that are not JSObjects.
+ inline void set_dictionary_map(bool value);
+ inline bool is_dictionary_map();
+
// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_is_access_check_needed(bool access_check_needed);
@@ -4761,16 +4835,15 @@ class Map: public HeapObject {
inline JSFunction* unchecked_constructor();
- // Should only be called by the code that initializes map to set initial valid
- // value of the instance descriptor member.
- inline void init_instance_descriptors();
-
// [instance descriptors]: describes the object.
- DECL_ACCESSORS(instance_descriptors, DescriptorArray)
-
- // Sets the instance descriptor array for the map to be an empty descriptor
- // array.
- inline void clear_instance_descriptors();
+ inline DescriptorArray* instance_descriptors();
+ MUST_USE_RESULT inline MaybeObject* SetDescriptors(
+ DescriptorArray* descriptors,
+ WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+ static void SetDescriptors(Handle<Map> map,
+ Handle<DescriptorArray> descriptors);
+ MUST_USE_RESULT inline MaybeObject* InitializeDescriptors(
+ DescriptorArray* descriptors);
// [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, Object)
@@ -4782,6 +4855,7 @@ class Map: public HeapObject {
inline Object* GetBackPointer();
inline void SetBackPointer(Object* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
+ inline void init_back_pointer(Object* undefined);
// [prototype transitions]: cache of prototype transitions.
// Prototype transition is a transition that happens
@@ -4791,27 +4865,29 @@ class Map: public HeapObject {
// 1: back pointer that overlaps with prototype transitions field.
// 2 + 2 * i: prototype
// 3 + 2 * i: target map
- DECL_ACCESSORS(prototype_transitions, FixedArray)
+ inline FixedArray* GetPrototypeTransitions();
+ MUST_USE_RESULT inline MaybeObject* SetPrototypeTransitions(
+ FixedArray* prototype_transitions);
+ inline bool HasPrototypeTransitions();
- inline void init_prototype_transitions(Object* undefined);
- inline HeapObject* unchecked_prototype_transitions();
+ inline HeapObject* UncheckedPrototypeTransitions();
+ inline TransitionArray* unchecked_transition_array();
- static const int kProtoTransitionHeaderSize = 2;
+ static const int kProtoTransitionHeaderSize = 1;
static const int kProtoTransitionNumberOfEntriesOffset = 0;
- static const int kProtoTransitionBackPointerOffset = 1;
static const int kProtoTransitionElementsPerEntry = 2;
static const int kProtoTransitionPrototypeOffset = 0;
static const int kProtoTransitionMapOffset = 1;
inline int NumberOfProtoTransitions() {
- FixedArray* cache = prototype_transitions();
+ FixedArray* cache = GetPrototypeTransitions();
if (cache->length() == 0) return 0;
return
Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
}
inline void SetNumberOfProtoTransitions(int value) {
- FixedArray* cache = prototype_transitions();
+ FixedArray* cache = GetPrototypeTransitions();
ASSERT(cache->length() != 0);
cache->set_unchecked(kProtoTransitionNumberOfEntriesOffset,
Smi::FromInt(value));
@@ -4820,19 +4896,67 @@ class Map: public HeapObject {
// Lookup in the map's instance descriptors and fill out the result
// with the given holder if the name is found. The holder may be
// NULL when this function is used from the compiler.
- void LookupInDescriptors(JSObject* holder,
- String* name,
- LookupResult* result);
+ inline void LookupDescriptor(JSObject* holder,
+ String* name,
+ LookupResult* result);
+
+ inline void LookupTransition(JSObject* holder,
+ String* name,
+ LookupResult* result);
+
+ // The size of transition arrays are limited so they do not end up in large
+ // object space. Otherwise ClearNonLiveTransitions would leak memory while
+ // applying in-place right trimming.
+ inline bool CanHaveMoreTransitions();
+
+ int LastAdded() {
+ int number_of_own_descriptors = NumberOfOwnDescriptors();
+ ASSERT(number_of_own_descriptors > 0);
+ return number_of_own_descriptors - 1;
+ }
+
+ int NumberOfOwnDescriptors() {
+ return NumberOfOwnDescriptorsBits::decode(bit_field3());
+ }
+ void SetNumberOfOwnDescriptors(int number) {
+ set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
+ }
+
+ int EnumLength() {
+ return EnumLengthBits::decode(bit_field3());
+ }
+
+ void SetEnumLength(int index) {
+ set_bit_field3(EnumLengthBits::update(bit_field3(), index));
+ }
+
+ MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
+ MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors();
MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
+ MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
+ DescriptorArray* descriptors,
+ String* name,
+ TransitionFlag flag);
+ MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
+ TransitionFlag flag);
+ MUST_USE_RESULT MaybeObject* CopyInsertDescriptor(Descriptor* descriptor,
+ TransitionFlag flag);
+ MUST_USE_RESULT MaybeObject* CopyReplaceDescriptor(Descriptor* descriptor,
+ int index,
+ TransitionFlag flag);
+ MUST_USE_RESULT MaybeObject* CopyAsElementsKind(ElementsKind kind,
+ TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
+ inline void AppendDescriptor(Descriptor* desc,
+ const DescriptorArray::WhitenessWitness&);
+
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
- MUST_USE_RESULT MaybeObject* CopyDropTransitions(
- DescriptorArray::SharedMode shared_mode);
+ MUST_USE_RESULT MaybeObject* Copy();
// Returns the property index for name (only valid for FAST MODE).
int PropertyIndexFor(String* name);
@@ -4861,6 +4985,11 @@ class Map: public HeapObject {
Handle<Code> code);
MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
+ // Extend the descriptor array of the map with the list of descriptors.
+ // In case of duplicates, the latest descriptor is used.
+ static void CopyAppendCallbackDescriptors(Handle<Map> map,
+ Handle<Object> descriptors);
+
// Returns the found code or undefined if absent.
Object* FindInCodeCache(String* name, Code::Flags flags);
@@ -4891,10 +5020,6 @@ class Map: public HeapObject {
// allowed.
Map* LookupElementsTransitionMap(ElementsKind elements_kind);
- // Adds a new transitions for changing the elements kind to |elements_kind|.
- MUST_USE_RESULT MaybeObject* CreateNextElementsTransition(
- ElementsKind elements_kind);
-
// Returns the transitioned map for this map with the most generic
// elements_kind that's found in |candidates|, or null handle if no match is
// found at all.
@@ -4906,8 +5031,8 @@ class Map: public HeapObject {
// holding weak references when incremental marking is used, because it also
// iterates over objects that are otherwise unreachable.
#ifdef DEBUG
- void ZapInstanceDescriptors();
void ZapPrototypeTransitions();
+ void ZapTransitions();
#endif
// Dispatched behavior.
@@ -4945,35 +5070,30 @@ class Map: public HeapObject {
static const int kMaxPreAllocatedPropertyFields = 255;
+ // Constant for denoting that the Enum Cache field was not yet used.
+ static const int kInvalidEnumCache = EnumLengthBits::kMax;
+
// Layout description.
static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
- // Storage for instance descriptors is overloaded to also contain additional
- // map flags when unused (bit_field3). When the map has instance descriptors,
- // the flags are transferred to the instance descriptor array and accessed
- // through an extra indirection.
- // TODO(1399): It should be possible to make room for bit_field3 in the map
- // without overloading the instance descriptors field, but the map is
- // currently perfectly aligned to 32 bytes and extending it at all would
- // double its size. After the increment GC work lands, this size restriction
- // could be loosened and bit_field3 moved directly back in the map.
- static const int kInstanceDescriptorsOrBitField3Offset =
+ // Storage for the transition array is overloaded to directly contain a back
+ // pointer if unused. When the map has transitions, the back pointer is
+ // transferred to the transition array and accessed through an extra
+ // indirection.
+ static const int kTransitionsOrBackPointerOffset =
kConstructorOffset + kPointerSize;
static const int kCodeCacheOffset =
- kInstanceDescriptorsOrBitField3Offset + kPointerSize;
- static const int kPrototypeTransitionsOrBackPointerOffset =
- kCodeCacheOffset + kPointerSize;
- static const int kPadStart =
- kPrototypeTransitionsOrBackPointerOffset + kPointerSize;
+ kTransitionsOrBackPointerOffset + kPointerSize;
+ static const int kBitField3Offset = kCodeCacheOffset + kPointerSize;
+ static const int kPadStart = kBitField3Offset + kPointerSize;
static const int kSize = MAP_POINTER_ALIGN(kPadStart);
// Layout of pointer fields. Heap iteration code relies on them
// being continuously allocated.
static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
- static const int kPointerFieldsEndOffset =
- kPrototypeTransitionsOrBackPointerOffset + kPointerSize;
+ static const int kPointerFieldsEndOffset = kBitField3Offset + kPointerSize;
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
@@ -5028,10 +5148,6 @@ class Map: public HeapObject {
static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) <<
Map::kElementsKindShift) - 1;
- // Bit positions for bit field 3
- static const int kIsShared = 0;
- static const int kFunctionWithPrototype = 1;
-
typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset,
kSize> BodyDescriptor;
@@ -5217,6 +5333,29 @@ class SharedFunctionInfo: public HeapObject {
// [code]: Function code.
DECL_ACCESSORS(code, Code)
+ // [optimized_code_map]: Map from native context to optimized code
+ // and a shared literals array or Smi 0 if none.
+ DECL_ACCESSORS(optimized_code_map, Object)
+
+ // Returns index i of the entry with the specified context. At position
+ // i - 1 is the context, position i the code, and i + 1 the literals array.
+ // Returns -1 when no matching entry is found.
+ int SearchOptimizedCodeMap(Context* native_context);
+
+ // Installs optimized code from the code map on the given closure. The
+ // index has to be consistent with a search result as defined above.
+ void InstallFromOptimizedCodeMap(JSFunction* function, int index);
+
+ // Clear optimized code map.
+ void ClearOptimizedCodeMap();
+
+ // Add a new entry to the optimized code map.
+ static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
+ Handle<Context> native_context,
+ Handle<Code> code,
+ Handle<FixedArray> literals);
+ static const int kEntryLength = 3;
+
// [scope_info]: Scope info.
DECL_ACCESSORS(scope_info, ScopeInfo)
@@ -5324,6 +5463,10 @@ class SharedFunctionInfo: public HeapObject {
// IsInobjectSlackTrackingInProgress is false after this call.
void CompleteInobjectSlackTracking();
+ // Invoked before pointers in SharedFunctionInfo are being marked.
+ // Also clears the optimized code map.
+ inline void BeforeVisitingPointers();
+
// Clears the initial_map before the GC marking phase to ensure the reference
// is weak. IsInobjectSlackTrackingInProgress is false after this call.
void DetachInitialMap();
@@ -5436,6 +5579,12 @@ class SharedFunctionInfo: public HeapObject {
// when doing GC if we expect that the function will no longer be used.
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
+ // Indicates if this function can be lazy compiled without a context.
+ // This is used to determine if we can force compilation without reaching
+ // the function through program execution but through other means (e.g. heap
+ // iteration by the debugger).
+ DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation_without_context)
+
// Indicates how many full GCs this function has survived with assigned
// code object. Used to determine when it is relatively safe to flush
// this code object and replace it with lazy compilation stub.
@@ -5500,6 +5649,9 @@ class SharedFunctionInfo: public HeapObject {
// Indicates that the function cannot be inlined.
DECL_BOOLEAN_ACCESSORS(dont_inline)
+ // Indicates that code for this function cannot be cached.
+ DECL_BOOLEAN_ACCESSORS(dont_cache)
+
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
@@ -5509,12 +5661,12 @@ class SharedFunctionInfo: public HeapObject {
// Disable (further) attempted optimization of all functions sharing this
// shared function info.
- void DisableOptimization();
+ void DisableOptimization(const char* reason);
// Lookup the bailout ID and ASSERT that it exists in the non-optimized
// code, returns whether it asserted (i.e., always true if assertions are
// disabled).
- bool VerifyBailoutId(int id);
+ bool VerifyBailoutId(BailoutId id);
// Check whether a inlined constructor can be generated with the given
// prototype.
@@ -5582,15 +5734,12 @@ class SharedFunctionInfo: public HeapObject {
void ResetForNewContext(int new_ic_age);
- // Helpers to compile the shared code. Returns true on success, false on
- // failure (e.g., stack overflow during compilation).
- static bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag);
+ // Helper to compile the shared code. Returns true on success, false on
+ // failure (e.g., stack overflow during compilation). This is only used by
+ // the debugger, it is not possible to compile without a context otherwise.
static bool CompileLazy(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag);
- void SharedFunctionInfoIterateBody(ObjectVisitor* v);
-
// Casting.
static inline SharedFunctionInfo* cast(Object* obj);
@@ -5601,7 +5750,8 @@ class SharedFunctionInfo: public HeapObject {
// Pointer fields.
static const int kNameOffset = HeapObject::kHeaderSize;
static const int kCodeOffset = kNameOffset + kPointerSize;
- static const int kScopeInfoOffset = kCodeOffset + kPointerSize;
+ static const int kOptimizedCodeMapOffset = kCodeOffset + kPointerSize;
+ static const int kScopeInfoOffset = kOptimizedCodeMapOffset + kPointerSize;
static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
static const int kInstanceClassNameOffset =
kConstructStubOffset + kPointerSize;
@@ -5719,6 +5869,7 @@ class SharedFunctionInfo: public HeapObject {
enum CompilerHints {
kHasOnlySimpleThisPropertyAssignments,
kAllowLazyCompilation,
+ kAllowLazyCompilationWithoutContext,
kLiveObjectsMayExist,
kCodeAgeShift,
kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
@@ -5733,6 +5884,7 @@ class SharedFunctionInfo: public HeapObject {
kIsFunction,
kDontOptimize,
kDontInline,
+ kDontCache,
kCompilerHintsCount // Pseudo entry
};
@@ -5799,6 +5951,9 @@ class JSModule: public JSObject {
// [context]: the context holding the module's locals, or undefined if none.
DECL_ACCESSORS(context, Object)
+ // [scope_info]: Scope info.
+ DECL_ACCESSORS(scope_info, ScopeInfo)
+
// Casting.
static inline JSModule* cast(Object* obj);
@@ -5815,7 +5970,8 @@ class JSModule: public JSObject {
// Layout description.
static const int kContextOffset = JSObject::kHeaderSize;
- static const int kSize = kContextOffset + kPointerSize;
+ static const int kScopeInfoOffset = kContextOffset + kPointerSize;
+ static const int kSize = kScopeInfoOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSModule);
@@ -5864,18 +6020,26 @@ class JSFunction: public JSObject {
// Mark this function for lazy recompilation. The function will be
// recompiled the next time it is executed.
void MarkForLazyRecompilation();
+ void MarkForParallelRecompilation();
// Helpers to compile this function. Returns true on success, false on
// failure (e.g., stack overflow during compilation).
+ static bool EnsureCompiled(Handle<JSFunction> function,
+ ClearExceptionFlag flag);
static bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag);
static bool CompileOptimized(Handle<JSFunction> function,
- int osr_ast_id,
+ BailoutId osr_ast_id,
ClearExceptionFlag flag);
// Tells whether or not the function is already marked for lazy
// recompilation.
inline bool IsMarkedForLazyRecompilation();
+ inline bool IsMarkedForParallelRecompilation();
+
+ // Tells whether or not the function is on the parallel
+ // recompilation queue.
+ inline bool IsInRecompileQueue();
// Check whether or not this function is inlineable.
bool IsInlineable();
@@ -5922,7 +6086,7 @@ class JSFunction: public JSObject {
// After prototype is removed, it will not be created when accessed, and
// [[Construct]] from this function will not be allowed.
- Object* RemovePrototype();
+ void RemovePrototype();
inline bool should_have_prototype();
// Accessor for this function's initial map's [[class]]
@@ -5934,7 +6098,7 @@ class JSFunction: public JSObject {
// Instances created afterwards will have a map whose [[class]] is
// set to 'value', but there is no guarantees on instances created
// before.
- Object* SetInstanceClassName(String* name);
+ void SetInstanceClassName(String* name);
// Returns if this function has been compiled to native code yet.
inline bool is_compiled();
@@ -5970,8 +6134,8 @@ class JSFunction: public JSObject {
// Returns the number of allocated literals.
inline int NumberOfLiterals();
- // Retrieve the global context from a function's literal array.
- static Context* GlobalContextFromLiterals(FixedArray* literals);
+ // Retrieve the native context from a function's literal array.
+ static Context* NativeContextFromLiterals(FixedArray* literals);
// Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
// kSize) is weak and has special handling during garbage collection.
@@ -5988,7 +6152,7 @@ class JSFunction: public JSObject {
// Layout of the literals array.
static const int kLiteralsPrefixSize = 1;
- static const int kLiteralGlobalContextIndex = 0;
+ static const int kLiteralNativeContextIndex = 0;
// Layout of the bound-function binding array.
static const int kBoundFunctionIndex = 0;
@@ -6010,9 +6174,9 @@ class JSFunction: public JSObject {
class JSGlobalProxy : public JSObject {
public:
- // [context]: the owner global context of this global proxy object.
+ // [native_context]: the owner native context of this global proxy object.
// It is null value if this object is not used by any context.
- DECL_ACCESSORS(context, Object)
+ DECL_ACCESSORS(native_context, Object)
// Casting.
static inline JSGlobalProxy* cast(Object* obj);
@@ -6029,8 +6193,8 @@ class JSGlobalProxy : public JSObject {
#endif
// Layout description.
- static const int kContextOffset = JSObject::kHeaderSize;
- static const int kSize = kContextOffset + kPointerSize;
+ static const int kNativeContextOffset = JSObject::kHeaderSize;
+ static const int kSize = kNativeContextOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
@@ -6047,7 +6211,10 @@ class GlobalObject: public JSObject {
// [builtins]: the object holding the runtime routines written in JS.
DECL_ACCESSORS(builtins, JSBuiltinsObject)
- // [global context]: the global context corresponding to this global object.
+ // [native context]: the natives corresponding to this global object.
+ DECL_ACCESSORS(native_context, Context)
+
+ // [global context]: the most recent (i.e. innermost) global context.
DECL_ACCESSORS(global_context, Context)
// [global receiver]: the global receiver object of the context
@@ -6078,7 +6245,8 @@ class GlobalObject: public JSObject {
// Layout description.
static const int kBuiltinsOffset = JSObject::kHeaderSize;
- static const int kGlobalContextOffset = kBuiltinsOffset + kPointerSize;
+ static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize;
+ static const int kGlobalContextOffset = kNativeContextOffset + kPointerSize;
static const int kGlobalReceiverOffset = kGlobalContextOffset + kPointerSize;
static const int kHeaderSize = kGlobalReceiverOffset + kPointerSize;
@@ -6524,13 +6692,15 @@ class CompilationCacheTable: public HashTable<CompilationCacheShape,
HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
- Object* Lookup(String* src);
+ Object* Lookup(String* src, Context* context);
Object* LookupEval(String* src,
Context* context,
LanguageMode language_mode,
int scope_position);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
- MUST_USE_RESULT MaybeObject* Put(String* src, Object* value);
+ MUST_USE_RESULT MaybeObject* Put(String* src,
+ Context* context,
+ Object* value);
MUST_USE_RESULT MaybeObject* PutEval(String* src,
Context* context,
SharedFunctionInfo* value,
@@ -6704,7 +6874,15 @@ class TypeFeedbackInfo: public Struct {
inline void set_ic_total_count(int count);
inline int ic_with_type_info_count();
- inline void set_ic_with_type_info_count(int count);
+ inline void change_ic_with_type_info_count(int count);
+
+ inline void initialize_storage();
+
+ inline void change_own_type_change_checksum();
+ inline int own_type_change_checksum();
+
+ inline void set_inlined_type_change_checksum(int checksum);
+ inline bool matches_inlined_type_change_checksum(int checksum);
DECL_ACCESSORS(type_feedback_cells, TypeFeedbackCells)
@@ -6720,14 +6898,25 @@ class TypeFeedbackInfo: public Struct {
void TypeFeedbackInfoVerify();
#endif
- static const int kIcTotalCountOffset = HeapObject::kHeaderSize;
- static const int kIcWithTypeinfoCountOffset =
- kIcTotalCountOffset + kPointerSize;
- static const int kTypeFeedbackCellsOffset =
- kIcWithTypeinfoCountOffset + kPointerSize;
+ static const int kStorage1Offset = HeapObject::kHeaderSize;
+ static const int kStorage2Offset = kStorage1Offset + kPointerSize;
+ static const int kTypeFeedbackCellsOffset = kStorage2Offset + kPointerSize;
static const int kSize = kTypeFeedbackCellsOffset + kPointerSize;
private:
+ static const int kTypeChangeChecksumBits = 7;
+
+ class ICTotalCountField: public BitField<int, 0,
+ kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
+ class OwnTypeChangeChecksum: public BitField<int,
+ kSmiValueSize - kTypeChangeChecksumBits,
+ kTypeChangeChecksumBits> {}; // NOLINT
+ class ICsWithTypeInfoCountField: public BitField<int, 0,
+ kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
+ class InlinedTypeChangeChecksum: public BitField<int,
+ kSmiValueSize - kTypeChangeChecksumBits,
+ kTypeChangeChecksumBits> {}; // NOLINT
+
DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackInfo);
};
@@ -7197,7 +7386,7 @@ class String: public HeapObject {
#ifdef V8_HOST_CAN_READ_UNALIGNED
ASSERT(kMaxAsciiCharCode == 0x7F);
const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
- while (chars <= limit - sizeof(uintptr_t)) {
+ while (chars + sizeof(uintptr_t) <= limit) {
if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
return false;
}
@@ -7456,7 +7645,8 @@ class ConsString: public String {
class SlicedString: public String {
public:
inline String* parent();
- inline void set_parent(String* parent);
+ inline void set_parent(String* parent,
+ WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline int offset();
inline void set_offset(int offset);
@@ -7759,6 +7949,14 @@ class JSGlobalPropertyCell: public HeapObject {
// Casting.
static inline JSGlobalPropertyCell* cast(Object* obj);
+ static inline JSGlobalPropertyCell* FromValueAddress(Address value) {
+ return cast(FromAddress(value - kValueOffset));
+ }
+
+ inline Address ValueAddress() {
+ return address() + kValueOffset;
+ }
+
#ifdef DEBUG
void JSGlobalPropertyCellVerify();
#endif
@@ -8214,7 +8412,7 @@ class AccessorPair: public Struct {
static inline AccessorPair* cast(Object* obj);
- MUST_USE_RESULT MaybeObject* CopyWithoutTransitions();
+ MUST_USE_RESULT MaybeObject* Copy();
Object* get(AccessorComponent component) {
return component == ACCESSOR_GETTER ? getter() : setter();
@@ -8702,8 +8900,6 @@ class ObjectVisitor BASE_EMBEDDED {
// Visit pointer embedded into a code object.
virtual void VisitEmbeddedPointer(RelocInfo* rinfo);
- virtual void VisitSharedFunctionInfo(SharedFunctionInfo* shared) {}
-
// Visits a contiguous arrays of external references (references to the C++
// heap) in the half-open range [start, end). Any or all of the values
// may be modified on return.