diff options
Diffstat (limited to 'chromium/v8/src/objects.h')
-rw-r--r-- | chromium/v8/src/objects.h | 1603 |
1 files changed, 869 insertions, 734 deletions
diff --git a/chromium/v8/src/objects.h b/chromium/v8/src/objects.h index 225a7db42e0..c55c5c97805 100644 --- a/chromium/v8/src/objects.h +++ b/chromium/v8/src/objects.h @@ -1,4 +1,4 @@ -// Copyright 2012 the V8 project authors. All rights reserved. +// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -11,6 +11,7 @@ #include "src/assert-scope.h" #include "src/bailout-reason.h" #include "src/base/bits.h" +#include "src/base/flags.h" #include "src/base/smart-pointers.h" #include "src/builtins.h" #include "src/checks.h" @@ -50,6 +51,7 @@ // - JSArrayBufferView // - JSTypedArray // - JSDataView +// - JSBoundFunction // - JSCollection // - JSSet // - JSMap @@ -62,15 +64,12 @@ // - JSFunction // - JSGeneratorObject // - JSModule -// - GlobalObject -// - JSGlobalObject -// - JSBuiltinsObject +// - JSGlobalObject // - JSGlobalProxy // - JSValue // - JSDate // - JSMessageObject // - JSProxy -// - JSFunctionProxy // - FixedArrayBase // - ByteArray // - BytecodeArray @@ -87,6 +86,7 @@ // - OrderedHashSet // - OrderedHashMap // - Context +// - TypeFeedbackMetadata // - TypeFeedbackVector // - ScopeInfo // - TransitionArray @@ -143,7 +143,6 @@ // - FunctionTemplateInfo // - ObjectTemplateInfo // - Script -// - TypeSwitchInfo // - DebugInfo // - BreakPointInfo // - CodeCache @@ -179,7 +178,7 @@ enum class ToPrimitiveHint { kDefault, kNumber, kString }; enum class OrdinaryToPrimitiveHint { kNumber, kString }; -enum TypeofMode { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; +enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; enum MutableMode { @@ -411,6 +410,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; V(FIXED_DOUBLE_ARRAY_TYPE) \ V(SHARED_FUNCTION_INFO_TYPE) \ V(WEAK_CELL_TYPE) \ + V(TRANSITION_ARRAY_TYPE) \ \ V(JS_MESSAGE_OBJECT_TYPE) \ \ @@ -421,7 +421,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; V(JS_GENERATOR_OBJECT_TYPE) \ V(JS_MODULE_TYPE) \ V(JS_GLOBAL_OBJECT_TYPE) \ - V(JS_BUILTINS_OBJECT_TYPE) \ V(JS_GLOBAL_PROXY_TYPE) \ V(JS_ARRAY_TYPE) \ V(JS_ARRAY_BUFFER_TYPE) \ @@ -435,10 +434,11 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; V(JS_ITERATOR_RESULT_TYPE) \ V(JS_WEAK_MAP_TYPE) \ V(JS_WEAK_SET_TYPE) \ + V(JS_PROMISE_TYPE) \ V(JS_REGEXP_TYPE) \ \ + V(JS_BOUND_FUNCTION_TYPE) \ V(JS_FUNCTION_TYPE) \ - V(JS_FUNCTION_PROXY_TYPE) \ V(DEBUG_INFO_TYPE) \ V(BREAK_POINT_INFO_TYPE) @@ -513,7 +513,6 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \ V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \ V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \ - V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \ V(SCRIPT, Script, script) \ V(ALLOCATION_SITE, AllocationSite, allocation_site) \ V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \ @@ -702,6 +701,7 @@ enum InstanceType { SHARED_FUNCTION_INFO_TYPE, CELL_TYPE, WEAK_CELL_TYPE, + TRANSITION_ARRAY_TYPE, PROPERTY_CELL_TYPE, PROTOTYPE_INFO_TYPE, SLOPPY_BLOCK_WITH_EVAL_CONTEXT_EXTENSION_TYPE, @@ -709,11 +709,9 @@ enum InstanceType { // All the following types are subtypes of JSReceiver, which corresponds to // objects in the JS sense. The first and the last type in this range are // the two forms of function. This organization enables using the same - // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the - // NONCALLABLE_JS_OBJECT range. - JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE - JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE - JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE + // compares for checking the JS_RECEIVER and the NONCALLABLE_JS_OBJECT range. + JS_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE + JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE JS_MESSAGE_OBJECT_TYPE, JS_DATE_TYPE, JS_OBJECT_TYPE, @@ -721,7 +719,6 @@ enum InstanceType { JS_GENERATOR_OBJECT_TYPE, JS_MODULE_TYPE, JS_GLOBAL_OBJECT_TYPE, - JS_BUILTINS_OBJECT_TYPE, JS_GLOBAL_PROXY_TYPE, JS_ARRAY_TYPE, JS_ARRAY_BUFFER_TYPE, @@ -734,7 +731,9 @@ enum InstanceType { JS_ITERATOR_RESULT_TYPE, JS_WEAK_MAP_TYPE, JS_WEAK_SET_TYPE, + JS_PROMISE_TYPE, JS_REGEXP_TYPE, + JS_BOUND_FUNCTION_TYPE, JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE // Pseudo-types @@ -747,6 +746,8 @@ enum InstanceType { FIRST_NONSTRING_TYPE = SYMBOL_TYPE, FIRST_PRIMITIVE_TYPE = FIRST_NAME_TYPE, LAST_PRIMITIVE_TYPE = ODDBALL_TYPE, + FIRST_FUNCTION_TYPE = JS_BOUND_FUNCTION_TYPE, + LAST_FUNCTION_TYPE = JS_FUNCTION_TYPE, // Boundaries for testing for a fixed typed array. FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE, LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE, @@ -757,23 +758,11 @@ enum InstanceType { // are not continuous in this enum! The enum ranges instead reflect the // external class names, where proxies are treated as either ordinary objects, // or functions. - FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE, + FIRST_JS_RECEIVER_TYPE = JS_PROXY_TYPE, LAST_JS_RECEIVER_TYPE = LAST_TYPE, // Boundaries for testing the types represented as JSObject FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE, LAST_JS_OBJECT_TYPE = LAST_TYPE, - // Boundaries for testing the types represented as JSProxy - FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE, - LAST_JS_PROXY_TYPE = JS_PROXY_TYPE, - // Boundaries for testing whether the type is a JavaScript object. - FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE, - LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE, - // Boundaries for testing the types for which typeof is "object". - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE, - LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE, - // Note that the types for which typeof is "function" are not continuous. - // Define this so that we can put assertions on discrete checks. - NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2 }; STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType); @@ -782,6 +771,9 @@ STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType); STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType); +std::ostream& operator<<(std::ostream& os, InstanceType instance_type); + + #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \ V(FAST_ELEMENTS_SUB_TYPE) \ V(DICTIONARY_ELEMENTS_SUB_TYPE) \ @@ -790,14 +782,13 @@ STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType); V(MAP_CODE_CACHE_SUB_TYPE) \ V(SCOPE_INFO_SUB_TYPE) \ V(STRING_TABLE_SUB_TYPE) \ - V(DESCRIPTOR_ARRAY_SUB_TYPE) \ - V(TRANSITION_ARRAY_SUB_TYPE) + V(DESCRIPTOR_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 + LAST_FIXED_ARRAY_SUB_TYPE = DESCRIPTOR_ARRAY_SUB_TYPE }; @@ -850,20 +841,22 @@ class ConsString; class ElementsAccessor; class FixedArrayBase; class FunctionLiteral; -class GlobalObject; -class JSBuiltinsObject; +class JSGlobalObject; +class KeyAccumulator; class LayoutDescriptor; class LiteralsArray; class LookupIterator; class ObjectHashTable; class ObjectVisitor; class PropertyCell; +class PropertyDescriptor; class SafepointEntry; class SharedFunctionInfo; class StringStream; class TypeFeedbackInfo; class TypeFeedbackVector; class WeakCell; +class TransitionArray; // We cannot just say "class HeapType;" if it is created from a template... =8-? template<class> class TypeImpl; @@ -943,6 +936,7 @@ template <class C> inline bool Is(Object* obj); V(DescriptorArray) \ V(TransitionArray) \ V(LiteralsArray) \ + V(TypeFeedbackMetadata) \ V(TypeFeedbackVector) \ V(DeoptimizationInputData) \ V(DeoptimizationOutputData) \ @@ -956,6 +950,7 @@ template <class C> inline bool Is(Object* obj); V(ScriptContextTable) \ V(NativeContext) \ V(ScopeInfo) \ + V(JSBoundFunction) \ V(JSFunction) \ V(Code) \ V(Oddball) \ @@ -972,7 +967,6 @@ template <class C> inline bool Is(Object* obj); V(JSTypedArray) \ V(JSDataView) \ V(JSProxy) \ - V(JSFunctionProxy) \ V(JSSet) \ V(JSMap) \ V(JSSetIterator) \ @@ -991,9 +985,7 @@ template <class C> inline bool Is(Object* obj); V(PolymorphicCodeCacheHashTable) \ V(MapCache) \ V(Primitive) \ - V(GlobalObject) \ V(JSGlobalObject) \ - V(JSBuiltinsObject) \ V(JSGlobalProxy) \ V(UndetectableObject) \ V(AccessCheckNeeded) \ @@ -1004,6 +996,9 @@ template <class C> inline bool Is(Object* obj); V(WeakHashTable) \ V(OrderedHashTable) +// The element types selection for CreateListFromArrayLike. +enum class ElementTypes { kAll, kStringAndSymbol }; + // Object is the abstract superclass for all classes in the // object hierarchy. // Object does not use any virtual functions to avoid the @@ -1027,6 +1022,25 @@ class Object { CERTAINLY_NOT_STORE_FROM_KEYED }; + enum ShouldThrow { THROW_ON_ERROR, DONT_THROW }; + +#define RETURN_FAILURE(isolate, should_throw, call) \ + do { \ + if ((should_throw) == DONT_THROW) { \ + return Just(false); \ + } else { \ + isolate->Throw(*isolate->factory()->call); \ + return Nothing<bool>(); \ + } \ + } while (false) + +#define MAYBE_RETURN(call, value) \ + do { \ + if ((call).IsNothing()) return value; \ + } while (false) + +#define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>()) + INLINE(bool IsFixedArrayBase() const); INLINE(bool IsExternal() const); INLINE(bool IsAccessorInfo() const); @@ -1037,13 +1051,18 @@ class Object { STRUCT_LIST(DECLARE_STRUCT_PREDICATE) #undef DECLARE_STRUCT_PREDICATE + // ES6, section 7.2.2 IsArray. NOT to be confused with %_IsArray. + MUST_USE_RESULT static Maybe<bool> IsArray(Handle<Object> object); + + // Test for JSBoundFunction or JSFunction. + INLINE(bool IsFunction() const); + // ES6, section 7.2.3 IsCallable. INLINE(bool IsCallable() const); // ES6, section 7.2.4 IsConstructor. INLINE(bool IsConstructor() const); - INLINE(bool IsSpecObject()) const; INLINE(bool IsTemplateInfo()) const; INLINE(bool IsNameDictionary() const); INLINE(bool IsGlobalDictionary() const); @@ -1084,6 +1103,8 @@ class Object { // 1 all refer to the same property, so this helper will return true. inline bool KeyEquals(Object* other); + inline bool FilterKey(PropertyFilter filter); + Handle<HeapType> OptimalType(Isolate* isolate, Representation representation); inline static Handle<Object> NewStorageFor(Isolate* isolate, @@ -1154,6 +1175,13 @@ class Object { MUST_USE_RESULT static MaybeHandle<Object> GetMethod( Handle<JSReceiver> receiver, Handle<Name> name); + // ES6 section 7.3.17 CreateListFromArrayLike + MUST_USE_RESULT static MaybeHandle<FixedArray> CreateListFromArrayLike( + Isolate* isolate, Handle<Object> object, ElementTypes element_types); + + // Check whether |object| is an instance of Error or NativeError. + static bool IsErrorObject(Isolate* isolate, Handle<Object> object); + // ES6 section 12.5.6 The typeof Operator static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object); @@ -1211,17 +1239,23 @@ class Object { MUST_USE_RESULT static MaybeHandle<Object> GetProperty( LookupIterator* it, LanguageMode language_mode = SLOPPY); - // Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5. + // ES6 [[Set]] (when passed DONT_THROW) + // Invariants for this and related functions (unless stated otherwise): + // 1) When the result is Nothing, an exception is pending. + // 2) When passed THROW_ON_ERROR, the result is never Just(false). + // In some cases, an exception is thrown regardless of the ShouldThrow + // argument. These cases are either in accordance with the spec or not + // covered by it (eg., concerning API callbacks). + MUST_USE_RESULT static Maybe<bool> SetProperty(LookupIterator* it, + Handle<Object> value, + LanguageMode language_mode, + StoreFromKeyed store_mode); MUST_USE_RESULT static MaybeHandle<Object> SetProperty( Handle<Object> object, Handle<Name> name, Handle<Object> value, LanguageMode language_mode, StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); - MUST_USE_RESULT static MaybeHandle<Object> SetProperty( - LookupIterator* it, Handle<Object> value, LanguageMode language_mode, - StoreFromKeyed store_mode); - - MUST_USE_RESULT static MaybeHandle<Object> SetSuperProperty( + MUST_USE_RESULT static Maybe<bool> SetSuperProperty( LookupIterator* it, Handle<Object> value, LanguageMode language_mode, StoreFromKeyed store_mode); @@ -1230,22 +1264,28 @@ class Object { MUST_USE_RESULT static MaybeHandle<Object> ReadAbsentProperty( Isolate* isolate, Handle<Object> receiver, Handle<Object> name, LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty( - LookupIterator* it, Handle<Object> value, LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty( + MUST_USE_RESULT static Maybe<bool> CannotCreateProperty( Isolate* isolate, Handle<Object> receiver, Handle<Object> name, - Handle<Object> value, LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> RedefineNonconfigurableProperty( + Handle<Object> value, ShouldThrow should_throw); + MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty( + LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); + MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty( + Isolate* isolate, Handle<Object> receiver, Handle<Object> name, + Handle<Object> value, ShouldThrow should_throw); + MUST_USE_RESULT static Maybe<bool> RedefineIncompatibleProperty( Isolate* isolate, Handle<Object> name, Handle<Object> value, - LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty( - LookupIterator* it, Handle<Object> value); - MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty( + ShouldThrow should_throw); + MUST_USE_RESULT static Maybe<bool> SetDataProperty(LookupIterator* it, + Handle<Object> value); + MUST_USE_RESULT static Maybe<bool> AddDataProperty( LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, - LanguageMode language_mode, StoreFromKeyed store_mode); + ShouldThrow should_throw, StoreFromKeyed store_mode); MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( Handle<Object> object, Handle<Name> name, LanguageMode language_mode = SLOPPY); + MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( + Handle<JSReceiver> holder, Handle<Name> name, Handle<Object> receiver, + LanguageMode language_mode = SLOPPY); MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( Isolate* isolate, Handle<Object> object, const char* key, LanguageMode language_mode = SLOPPY); @@ -1255,16 +1295,15 @@ class Object { MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor( LookupIterator* it, LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor( - LookupIterator* it, Handle<Object> value, LanguageMode language_mode); + MUST_USE_RESULT static Maybe<bool> SetPropertyWithAccessor( + LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter( Handle<Object> receiver, Handle<JSReceiver> getter); - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithDefinedSetter( - Handle<Object> receiver, - Handle<JSReceiver> setter, - Handle<Object> value); + MUST_USE_RESULT static Maybe<bool> SetPropertyWithDefinedSetter( + Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value, + ShouldThrow should_throw); MUST_USE_RESULT static inline MaybeHandle<Object> GetElement( Isolate* isolate, Handle<Object> object, uint32_t index, @@ -1274,10 +1313,13 @@ class Object { Isolate* isolate, Handle<Object> object, uint32_t index, Handle<Object> value, LanguageMode language_mode); - static inline Handle<Object> GetPrototypeSkipHiddenPrototypes( - Isolate* isolate, Handle<Object> receiver); + // Get the first non-hidden prototype. + static inline MaybeHandle<Object> GetPrototype(Isolate* isolate, + Handle<Object> receiver); - bool HasInPrototypeChain(Isolate* isolate, Object* object); + MUST_USE_RESULT static Maybe<bool> HasInPrototypeChain(Isolate* isolate, + Handle<Object> object, + Handle<Object> proto); // Returns the permanent hash code associated with this object. May return // undefined if not yet created. @@ -1304,6 +1346,10 @@ class Object { // by ES6 Map and Set. bool SameValueZero(Object* other); + // ES6 section 9.4.2.3 ArraySpeciesCreate (part of it) + MUST_USE_RESULT static MaybeHandle<Object> ArraySpeciesConstructor( + Isolate* isolate, Handle<Object> original_array); + // Tries to convert an object to an array length. Returns true and sets the // output parameter if it succeeds. inline bool ToArrayLength(uint32_t* index); @@ -1325,6 +1371,10 @@ class Object { inline void VerifyApiCallResultType(); + // ES6 19.1.3.6 Object.prototype.toString + MUST_USE_RESULT static MaybeHandle<String> ObjectProtoToString( + Isolate* isolate, Handle<Object> object); + // Prints this object without details. void ShortPrint(FILE* out = stdout); @@ -1357,7 +1407,8 @@ class Object { Map* GetRootMap(Isolate* isolate); // Helper for SetProperty and SetSuperProperty. - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyInternal( + // Return value is only meaningful if [found] is set to true on return. + MUST_USE_RESULT static Maybe<bool> SetPropertyInternal( LookupIterator* it, Handle<Object> value, LanguageMode language_mode, StoreFromKeyed store_mode, bool* found); @@ -1471,13 +1522,6 @@ class MapWord BASE_EMBEDDED { }; -// The content of an heap object (except for the map pointer). kTaggedValues -// objects can contain both heap pointers and Smis, kMixedValues can contain -// heap pointers, Smis, and raw values (e.g. doubles or strings), and kRawValues -// objects can contain raw values and Smis. -enum class HeapObjectContents { kTaggedValues, kMixedValues, kRawValues }; - - // HeapObject is the superclass for all classes describing heap allocated // objects. class HeapObject: public Object { @@ -1522,21 +1566,38 @@ class HeapObject: public Object { return reinterpret_cast<Address>(this) - kHeapObjectTag; } - // Iterates over pointers contained in the object (including the Map) + // Iterates over pointers contained in the object (including the Map). + // If it's not performance critical iteration use the non-templatized + // version. void Iterate(ObjectVisitor* v); + template <typename ObjectVisitor> + inline void IterateFast(ObjectVisitor* v); + // Iterates over all pointers contained in the object except the // first map pointer. The object type is given in the first // parameter. This function does not access the map pointer in the // object, and so is safe to call while the map pointer is modified. + // If it's not performance critical iteration use the non-templatized + // version. + void IterateBody(ObjectVisitor* v); void IterateBody(InstanceType type, int object_size, ObjectVisitor* v); + template <typename ObjectVisitor> + inline void IterateBodyFast(ObjectVisitor* v); + + template <typename ObjectVisitor> + inline void IterateBodyFast(InstanceType type, int object_size, + ObjectVisitor* v); + + // Returns true if the object contains a tagged value at given offset. + // It is used for invalid slots filtering. If the offset points outside + // of the object or to the map word, the result is UNDEFINED (!!!). + bool IsValidSlot(int offset); + // Returns the heap object's size in bytes inline int Size(); - // Indicates what type of values this heap object may contain. - inline HeapObjectContents ContentType(); - // Given a heap object's map pointer, returns the heap size in bytes // Useful when the map pointer field is used for other purposes. // GC internal. @@ -1590,58 +1651,17 @@ class HeapObject: public Object { STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset); - protected: - // helpers for calling an ObjectVisitor to iterate over pointers in the - // half-open range [start, end) specified as integer offsets - inline void IteratePointers(ObjectVisitor* v, int start, int end); - // as above, for the single element at "offset" - inline void IteratePointer(ObjectVisitor* v, int offset); - // as above, for the next code link of a code object. - inline void IterateNextCodeLink(ObjectVisitor* v, int offset); - private: DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject); }; -// 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. -template<int start_offset, int end_offset, int size> -class FixedBodyDescriptor { - public: - static const int kStartOffset = start_offset; - static const int kEndOffset = end_offset; - static const int kSize = size; +template <int start_offset, int end_offset, int size> +class FixedBodyDescriptor; - static inline void IterateBody(HeapObject* obj, ObjectVisitor* v); - template<typename StaticVisitor> - static inline void IterateBody(HeapObject* obj) { - StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset), - HeapObject::RawField(obj, end_offset)); - } -}; - - -// This class describes a body of an object of a variable size -// in which all pointer fields are located in the [start_offset, object_size) -// interval. -template<int start_offset> -class FlexibleBodyDescriptor { - public: - static const int kStartOffset = start_offset; - - static inline void IterateBody(HeapObject* obj, - int object_size, - ObjectVisitor* v); - - template<typename StaticVisitor> - static inline void IterateBody(HeapObject* obj, int object_size) { - StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset), - HeapObject::RawField(obj, object_size)); - } -}; +template <int start_offset> +class FlexibleBodyDescriptor; // The HeapNumber class describes heap allocated numbers that cannot be @@ -1775,10 +1795,26 @@ enum AccessorComponent { }; +enum GetKeysConversion { KEEP_NUMBERS, CONVERT_TO_STRING }; + + // JSReceiver includes types on which properties can be defined, i.e., // JSObject and JSProxy. class JSReceiver: public HeapObject { public: + // [properties]: Backing storage for properties. + // properties is a FixedArray in the fast case and a Dictionary in the + // slow case. + DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties. + inline void initialize_properties(); + inline bool HasFastProperties(); + // Gets slow properties for non-global objects. + inline NameDictionary* property_dictionary(); + + // Deletes an existing named property in a normalized object. + static void DeleteNormalizedProperty(Handle<JSReceiver> object, + Handle<Name> name, int entry); + DECLARE_CAST(JSReceiver) // ES6 section 7.1.1 ToPrimitive @@ -1788,38 +1824,105 @@ class JSReceiver: public HeapObject { MUST_USE_RESULT static MaybeHandle<Object> OrdinaryToPrimitive( Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint); + static MaybeHandle<Context> GetFunctionRealm(Handle<JSReceiver> receiver); + // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6. + MUST_USE_RESULT static Maybe<bool> HasProperty(LookupIterator* it); MUST_USE_RESULT static inline Maybe<bool> HasProperty( Handle<JSReceiver> object, Handle<Name> name); - MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(Handle<JSReceiver>, - Handle<Name> name); MUST_USE_RESULT static inline Maybe<bool> HasElement( Handle<JSReceiver> object, uint32_t index); - MUST_USE_RESULT static inline Maybe<bool> HasOwnElement( - Handle<JSReceiver> object, uint32_t index); - // Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7. - MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyOrElement( + MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty( + Handle<JSReceiver> object, Handle<Name> name); + + // Implementation of ES6 [[Delete]] + MUST_USE_RESULT static Maybe<bool> DeletePropertyOrElement( Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode = SLOPPY); - MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty( + MUST_USE_RESULT static Maybe<bool> DeleteProperty( Handle<JSReceiver> object, Handle<Name> name, LanguageMode language_mode = SLOPPY); - MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty( - LookupIterator* it, LanguageMode language_mode); - MUST_USE_RESULT static MaybeHandle<Object> DeleteElement( + MUST_USE_RESULT static Maybe<bool> DeleteProperty(LookupIterator* it, + LanguageMode language_mode); + MUST_USE_RESULT static Maybe<bool> DeleteElement( Handle<JSReceiver> object, uint32_t index, LanguageMode language_mode = SLOPPY); + MUST_USE_RESULT static Object* DefineProperty(Isolate* isolate, + Handle<Object> object, + Handle<Object> name, + Handle<Object> attributes); + MUST_USE_RESULT static MaybeHandle<Object> DefineProperties( + Isolate* isolate, Handle<Object> object, Handle<Object> properties); + + // "virtual" dispatcher to the correct [[DefineOwnProperty]] implementation. + MUST_USE_RESULT static Maybe<bool> DefineOwnProperty( + Isolate* isolate, Handle<JSReceiver> object, Handle<Object> key, + PropertyDescriptor* desc, ShouldThrow should_throw); + + // ES6 7.3.4 (when passed DONT_THROW) + MUST_USE_RESULT static Maybe<bool> CreateDataProperty( + LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); + + // ES6 9.1.6.1 + MUST_USE_RESULT static Maybe<bool> OrdinaryDefineOwnProperty( + Isolate* isolate, Handle<JSObject> object, Handle<Object> key, + PropertyDescriptor* desc, ShouldThrow should_throw); + MUST_USE_RESULT static Maybe<bool> OrdinaryDefineOwnProperty( + LookupIterator* it, PropertyDescriptor* desc, ShouldThrow should_throw); + // ES6 9.1.6.2 + MUST_USE_RESULT static Maybe<bool> IsCompatiblePropertyDescriptor( + Isolate* isolate, bool extensible, PropertyDescriptor* desc, + PropertyDescriptor* current, Handle<Name> property_name, + ShouldThrow should_throw); + // ES6 9.1.6.3 + // |it| can be NULL in cases where the ES spec passes |undefined| as the + // receiver. Exactly one of |it| and |property_name| must be provided. + MUST_USE_RESULT static Maybe<bool> ValidateAndApplyPropertyDescriptor( + Isolate* isolate, LookupIterator* it, bool extensible, + PropertyDescriptor* desc, PropertyDescriptor* current, + ShouldThrow should_throw, Handle<Name> property_name = Handle<Name>()); + + MUST_USE_RESULT static Maybe<bool> GetOwnPropertyDescriptor( + Isolate* isolate, Handle<JSReceiver> object, Handle<Object> key, + PropertyDescriptor* desc); + MUST_USE_RESULT static Maybe<bool> GetOwnPropertyDescriptor( + LookupIterator* it, PropertyDescriptor* desc); + + typedef PropertyAttributes IntegrityLevel; + + // ES6 7.3.14 (when passed DONT_THROW) + // 'level' must be SEALED or FROZEN. + MUST_USE_RESULT static Maybe<bool> SetIntegrityLevel( + Handle<JSReceiver> object, IntegrityLevel lvl, ShouldThrow should_throw); + + // ES6 7.3.15 + // 'level' must be SEALED or FROZEN. + MUST_USE_RESULT static Maybe<bool> TestIntegrityLevel( + Handle<JSReceiver> object, IntegrityLevel lvl); + + // ES6 [[PreventExtensions]] (when passed DONT_THROW) + MUST_USE_RESULT static Maybe<bool> PreventExtensions( + Handle<JSReceiver> object, ShouldThrow should_throw); + + MUST_USE_RESULT static Maybe<bool> IsExtensible(Handle<JSReceiver> object); + // Tests for the fast common case for property enumeration. bool IsSimpleEnum(); // Returns the class name ([[Class]] property in the specification). String* class_name(); + // Returns the builtin string tag used in Object.prototype.toString. + MUST_USE_RESULT static MaybeHandle<String> BuiltinStringTag( + Handle<JSReceiver> object); + // Returns the constructor name (the name (possibly, inferred name) of the // function that was used to instantiate the object). - String* constructor_name(); + static Handle<String> GetConstructorName(Handle<JSReceiver> receiver); + + Context* GetCreationContext(); MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetPropertyAttributes( Handle<JSReceiver> object, Handle<Name> name); @@ -1834,6 +1937,12 @@ class JSReceiver: public HeapObject { MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes( LookupIterator* it); + // Set the object's prototype (only JSReceiver and null are allowed values). + MUST_USE_RESULT static Maybe<bool> SetPrototype(Handle<JSReceiver> object, + Handle<Object> value, + bool from_javascript, + ShouldThrow should_throw); + static Handle<Object> GetDataProperty(Handle<JSReceiver> object, Handle<Name> name); @@ -1851,11 +1960,22 @@ class JSReceiver: public HeapObject { enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS }; + // ES6 [[OwnPropertyKeys]] (modulo return type) + MUST_USE_RESULT static MaybeHandle<FixedArray> OwnPropertyKeys( + Handle<JSReceiver> object) { + return GetKeys(object, JSReceiver::OWN_ONLY, ALL_PROPERTIES, + CONVERT_TO_STRING); + } + // Computes the enumerable keys for a JSObject. Used for implementing // "for (n in object) { }". MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys( - Handle<JSReceiver> object, - KeyCollectionType type); + Handle<JSReceiver> object, KeyCollectionType type, PropertyFilter filter, + GetKeysConversion keys_conversion = KEEP_NUMBERS); + + // Layout description. + static const int kPropertiesOffset = HeapObject::kHeaderSize; + static const int kHeaderSize = HeapObject::kHeaderSize + kPointerSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); @@ -1868,17 +1988,15 @@ class JSReceiver: public HeapObject { // caching. class JSObject: public JSReceiver { public: - // [properties]: Backing storage for properties. - // properties is a FixedArray in the fast case and a Dictionary in the - // slow case. - DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties. - inline void initialize_properties(); - inline bool HasFastProperties(); - // Gets slow properties for non-global objects. - inline NameDictionary* property_dictionary(); + static MUST_USE_RESULT MaybeHandle<JSObject> New( + Handle<JSFunction> constructor, Handle<JSReceiver> new_target, + Handle<AllocationSite> site = Handle<AllocationSite>::null()); + // Gets global object properties. inline GlobalDictionary* global_dictionary(); + static MaybeHandle<Context> GetFunctionRealm(Handle<JSObject> object); + // [elements]: The elements (properties with names that are integers). // // Elements can be in two general modes: fast and slow. Each mode @@ -1954,7 +2072,7 @@ class JSObject: public JSReceiver { static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object, uint32_t limit); - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor( + MUST_USE_RESULT static Maybe<bool> SetPropertyWithInterceptor( LookupIterator* it, Handle<Object> value); // SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to @@ -1965,6 +2083,11 @@ class JSObject: public JSReceiver { LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING); + MUST_USE_RESULT static Maybe<bool> DefineOwnPropertyIgnoreAttributes( + LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, + ShouldThrow should_throw, + ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING); + MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes( Handle<JSObject> object, Handle<Name> name, Handle<Object> value, PropertyAttributes attributes, @@ -1991,6 +2114,9 @@ class JSObject: public JSReceiver { static void AddProperty(Handle<JSObject> object, Handle<Name> name, Handle<Object> value, PropertyAttributes attributes); + MUST_USE_RESULT static Maybe<bool> AddDataElement( + Handle<JSObject> receiver, uint32_t index, Handle<Object> value, + PropertyAttributes attributes, ShouldThrow should_throw); MUST_USE_RESULT static MaybeHandle<Object> AddDataElement( Handle<JSObject> receiver, uint32_t index, Handle<Object> value, PropertyAttributes attributes); @@ -2024,6 +2150,9 @@ class JSObject: public JSReceiver { PrototypeOptimizationMode mode); static void ReoptimizeIfPrototype(Handle<JSObject> object); static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate); + static void UpdatePrototypeUserRegistration(Handle<Map> old_map, + Handle<Map> new_map, + Isolate* isolate); static bool UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate); static void InvalidatePrototypeChains(Map* map); @@ -2035,7 +2164,7 @@ class JSObject: public JSReceiver { // Retrieve interceptors. InterceptorInfo* GetNamedInterceptor(); - InterceptorInfo* GetIndexedInterceptor(); + inline InterceptorInfo* GetIndexedInterceptor(); // Used from JSReceiver. MUST_USE_RESULT static Maybe<PropertyAttributes> @@ -2057,6 +2186,10 @@ class JSObject: public JSReceiver { Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes); + static MaybeHandle<Object> DefineAccessor(LookupIterator* it, + Handle<Object> getter, + Handle<Object> setter, + PropertyAttributes attributes); // Defines an AccessorInfo property on the given object. MUST_USE_RESULT static MaybeHandle<Object> SetAccessor( @@ -2138,15 +2271,6 @@ class JSObject: public JSReceiver { inline bool HasNamedInterceptor(); inline bool HasIndexedInterceptor(); - // Computes the enumerable keys from interceptors. Used for debug mirrors and - // by JSReceiver::GetKeys. - MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForNamedInterceptor( - Handle<JSObject> object, - Handle<JSReceiver> receiver); - MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForIndexedInterceptor( - Handle<JSObject> object, - Handle<JSReceiver> receiver); - // Support functions for v8 api (needed for correct interceptor behavior). MUST_USE_RESULT static Maybe<bool> HasRealNamedProperty( Handle<JSObject> object, Handle<Name> name); @@ -2157,36 +2281,31 @@ class JSObject: public JSReceiver { // Get the header size for a JSObject. Used to compute the index of // internal fields as well as the number of internal fields. + static inline int GetHeaderSize(InstanceType instance_type); inline int GetHeaderSize(); + static inline int GetInternalFieldCount(Map* map); inline int GetInternalFieldCount(); inline int GetInternalFieldOffset(int index); inline Object* GetInternalField(int index); inline void SetInternalField(int index, Object* value); inline void SetInternalField(int index, Smi* value); - // Returns the number of properties on this object filtering out properties - // with the specified attributes (ignoring interceptors). - int NumberOfOwnProperties(PropertyAttributes filter = NONE); - // Fill in details for properties into storage starting at the specified - // index. Returns the number of properties added. - int GetOwnPropertyNames(FixedArray* storage, int index, - PropertyAttributes filter = NONE); + void CollectOwnPropertyNames(KeyAccumulator* keys, + PropertyFilter filter = ALL_PROPERTIES); // Returns the number of properties on this object filtering out properties // with the specified attributes (ignoring interceptors). - int NumberOfOwnElements(PropertyAttributes filter); - // Returns the number of enumerable elements (ignoring interceptors). - int NumberOfEnumElements(); + // TODO(jkummerow): Deprecated, only used by Object.observe. + int NumberOfOwnElements(PropertyFilter filter); // Returns the number of elements on this object filtering out elements // with the specified attributes (ignoring interceptors). - int GetOwnElementKeys(FixedArray* storage, PropertyAttributes filter); - // Count and fill in the enumerable elements into storage. - // (storage->length() == NumberOfEnumElements()). - // If storage is NULL, will count the elements without adding - // them to any storage. - // Returns the number of enumerable elements. - int GetEnumElementKeys(FixedArray* storage); + // TODO(jkummerow): Deprecated, only used by Object.observe. + int GetOwnElementKeys(FixedArray* storage, PropertyFilter filter); + + static void CollectOwnElementKeys(Handle<JSObject> object, + KeyAccumulator* keys, + PropertyFilter filter); static Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, bool cache_result); @@ -2247,32 +2366,26 @@ class JSObject: public JSReceiver { = UPDATE_WRITE_BARRIER); // Set the object's prototype (only JSReceiver and null are allowed values). - MUST_USE_RESULT static MaybeHandle<Object> SetPrototype( - Handle<JSObject> object, Handle<Object> value, bool from_javascript); + MUST_USE_RESULT static Maybe<bool> SetPrototype(Handle<JSObject> object, + Handle<Object> value, + bool from_javascript, + ShouldThrow should_throw); - // Initializes the body after properties slot, properties slot is - // initialized by set_properties. Fill the pre-allocated fields with + // Initializes the body starting at |start_offset|. It is responsibility of + // the caller to initialize object header. Fill the pre-allocated fields with // pre_allocated_value and the rest with filler_value. // Note: this call does not update write barrier, the caller is responsible // to ensure that |filler_value| can be collected without WB here. - inline void InitializeBody(Map* map, - Object* pre_allocated_value, - Object* filler_value); + inline void InitializeBody(Map* map, int start_offset, + Object* pre_allocated_value, Object* filler_value); // Check whether this object references another object bool ReferencesObject(Object* obj); - // Disalow further properties to be added to the oject. - MUST_USE_RESULT static MaybeHandle<Object> PreventExtensions( - Handle<JSObject> object); + MUST_USE_RESULT static Maybe<bool> PreventExtensions( + Handle<JSObject> object, ShouldThrow should_throw); - bool IsExtensible(); - - // ES5 Object.seal - MUST_USE_RESULT static MaybeHandle<Object> Seal(Handle<JSObject> object); - - // ES5 Object.freeze - MUST_USE_RESULT static MaybeHandle<Object> Freeze(Handle<JSObject> object); + static bool IsExtensible(Handle<JSObject> object); // Called the first time an object is observed with ES7 Object.observe. static void SetObserved(Handle<JSObject> object); @@ -2359,10 +2472,6 @@ class JSObject: public JSReceiver { // don't want to be wasteful with long lived objects. static const int kMaxUncheckedOldFastElementsLength = 500; - // Note that Page::kMaxRegularHeapObjectSize puts a limit on - // permissible values (see the DCHECK in heap.cc). - static const int kInitialMaxFastElementArray = 100000; - // This constant applies only to the initial map of "global.Object" and // not to arbitrary other JSObject maps. static const int kInitialGlobalObjectUnusedPropertiesCount = 4; @@ -2374,18 +2483,12 @@ class JSObject: public JSReceiver { static const int kFieldsAdded = 3; // Layout description. - static const int kPropertiesOffset = HeapObject::kHeaderSize; - static const int kElementsOffset = kPropertiesOffset + kPointerSize; + static const int kElementsOffset = JSReceiver::kHeaderSize; static const int kHeaderSize = kElementsOffset + kPointerSize; STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize); - class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> { - public: - static inline int SizeOf(Map* map, HeapObject* object); - }; - - Context* GetCreationContext(); + typedef FlexibleBodyDescriptor<JSReceiver::kPropertiesOffset> BodyDescriptor; // Enqueue change record for Object.observe. May cause GC. MUST_USE_RESULT static MaybeHandle<Object> EnqueueChangeRecord( @@ -2395,10 +2498,6 @@ class JSObject: public JSReceiver { // Gets the number of currently used elements. int GetFastElementsUsage(); - // Deletes an existing named property in a normalized object. - static void DeleteNormalizedProperty(Handle<JSObject> object, - Handle<Name> name, int entry); - static bool AllCanRead(LookupIterator* it); static bool AllCanWrite(LookupIterator* it); @@ -2415,8 +2514,8 @@ class JSObject: public JSReceiver { MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck( LookupIterator* it); - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck( - LookupIterator* it, Handle<Object> value); + MUST_USE_RESULT static Maybe<bool> SetPropertyWithFailedAccessCheck( + LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); // Add a property to a slow-case object. static void AddSlowProperty(Handle<JSObject> object, @@ -2424,7 +2523,7 @@ class JSObject: public JSReceiver { Handle<Object> value, PropertyAttributes attributes); - MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor( + MUST_USE_RESULT static Maybe<bool> DeletePropertyWithInterceptor( LookupIterator* it); bool ReferencesObjectFromElements(FixedArray* elements, @@ -2456,8 +2555,12 @@ class JSObject: public JSReceiver { // Helper for fast versions of preventExtensions, seal, and freeze. // attrs is one of NONE, SEALED, or FROZEN (depending on the operation). template <PropertyAttributes attrs> - MUST_USE_RESULT static MaybeHandle<Object> PreventExtensionsWithTransition( - Handle<JSObject> object); + MUST_USE_RESULT static Maybe<bool> PreventExtensionsWithTransition( + Handle<JSObject> object, ShouldThrow should_throw); + + MUST_USE_RESULT static Maybe<bool> SetPrototypeUnobserved( + Handle<JSObject> object, Handle<Object> value, bool from_javascript, + ShouldThrow should_throw); DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject); }; @@ -2519,8 +2622,6 @@ class FixedArray: public FixedArrayBase { // Shrink length and insert filler objects. void Shrink(int length); - enum KeyFilter { ALL_KEYS, NON_SYMBOL_KEYS }; - // Copy a sub array from the receiver to dest. void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); @@ -2560,10 +2661,7 @@ class FixedArray: public FixedArrayBase { // object, the prefix of this array is sorted. void SortPairs(FixedArray* numbers, uint32_t len); - class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> { - public: - static inline int SizeOf(Map* map, HeapObject* object); - }; + typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor; protected: // Set operation on FixedArray without using write barriers. Can @@ -2572,13 +2670,6 @@ class FixedArray: public FixedArrayBase { int index, Object* value); - // Set operation on FixedArray without incremental write barrier. Can - // only be used if the object is guaranteed to be white (whiteness witness - // is present). - static inline void NoIncrementalWriteBarrierSet(FixedArray* array, - int index, - Object* value); - private: STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize); @@ -2717,6 +2808,7 @@ class ArrayList : public FixedArray { inline Object** Slot(int index); inline void Set(int index, Object* obj); inline void Clear(int index, Object* undefined); + bool IsFull(); DECLARE_CAST(ArrayList) private: @@ -2768,9 +2860,9 @@ class DescriptorArray: public FixedArray { // Initialize or change the enum cache, // using the supplied storage for the small "bridge". - void SetEnumCache(FixedArray* bridge_storage, - FixedArray* new_cache, - Object* new_index_cache); + static void SetEnumCache(Handle<DescriptorArray> descriptors, + Isolate* isolate, Handle<FixedArray> new_cache, + Handle<FixedArray> new_index_cache); bool CanHoldValue(int descriptor, Object* value); @@ -2827,6 +2919,8 @@ class DescriptorArray: public FixedArray { // necessary. INLINE(int SearchWithCache(Name* name, Map* map)); + bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors); + // Allocates a DescriptorArray, but returns the singleton // empty descriptor array object if number_of_descriptors is 0. static Handle<DescriptorArray> Allocate(Isolate* isolate, @@ -2887,23 +2981,6 @@ class DescriptorArray: public FixedArray { } private: - // 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(DescriptorArray* array); - inline ~WhitenessWitness(); - - private: - IncrementalMarking* marking_; - }; - // An entry in a DescriptorArray, represented as an (array, index) pair. class Entry { public: @@ -2939,11 +3016,9 @@ class DescriptorArray: public FixedArray { // Transfer a complete descriptor from the src descriptor array to this // descriptor array. - void CopyFrom(int index, DescriptorArray* src, const WhitenessWitness&); + void CopyFrom(int index, DescriptorArray* src); - inline void Set(int descriptor_number, - Descriptor* desc, - const WhitenessWitness&); + inline void SetDescriptor(int descriptor_number, Descriptor* desc); // Swap first and second descriptor. inline void SwapSortedKeys(int first, int second); @@ -3146,6 +3221,9 @@ class HashTable : public HashTableBase { Key key, PretenureFlag pretenure = NOT_TENURED); + // Returns true if this table has sufficient capacity for adding n elements. + bool HasSufficientCapacity(int n); + // Sets the capacity of the hash table. void SetCapacity(int capacity) { // To scale a computed hash code to fit within the hash table, we @@ -3301,12 +3379,13 @@ class Dictionary: public HashTable<Derived, Shape, Key> { // Returns the number of elements in the dictionary filtering out properties // with the specified attributes. - int NumberOfElementsFilterAttributes(PropertyAttributes filter); + // TODO(jkummerow): Deprecated, only used by Object.observe. + int NumberOfElementsFilterAttributes(PropertyFilter filter); // Returns the number of enumerable elements in the dictionary. + // TODO(jkummerow): Deprecated, only used by Object.observe. int NumberOfEnumElements() { - return NumberOfElementsFilterAttributes( - static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC)); + return NumberOfElementsFilterAttributes(ENUMERABLE_STRINGS); } // Returns true if the dictionary contains any elements that are non-writable, @@ -3317,8 +3396,13 @@ class Dictionary: public HashTable<Derived, Shape, Key> { // Fill in details for properties into storage. // Returns the number of properties added. - int CopyKeysTo(FixedArray* storage, int index, PropertyAttributes filter, + // TODO(jkummerow): Deprecated, only used by Object.observe. + int CopyKeysTo(FixedArray* storage, int index, PropertyFilter filter, SortMode sort_mode); + // Collect the keys into the given KeyAccumulator, in ascending chronological + // order of property creation. + static void CollectKeysTo(Handle<Dictionary<Derived, Shape, Key> > dictionary, + KeyAccumulator* keys, PropertyFilter filter); // Copies enumerable keys to preallocated fixed array. void CopyEnumKeysTo(FixedArray* storage); @@ -3339,6 +3423,9 @@ class Dictionary: public HashTable<Derived, Shape, Key> { int at_least_space_for, PretenureFlag pretenure = NOT_TENURED); + // Ensures that a new dictionary is created when the capacity is checked. + void SetRequiresCopyOnCapacityChange(); + // Ensure enough space for n additional elements. static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key); @@ -3948,6 +4035,9 @@ class ScopeInfo : public FixedArray { // or context-allocated? bool HasAllocatedReceiver(); + // Does this scope declare a "new.target" binding? + bool HasNewTarget(); + // Is this scope the scope of a named function expression? bool HasFunctionName(); @@ -4156,9 +4246,10 @@ class ScopeInfo : public FixedArray { class ReceiverVariableField : public BitField<VariableAllocationInfo, DeclarationScopeField::kNext, 2> {}; + class HasNewTargetField + : public BitField<bool, ReceiverVariableField::kNext, 1> {}; class FunctionVariableField - : public BitField<VariableAllocationInfo, ReceiverVariableField::kNext, - 2> {}; + : public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {}; class FunctionVariableMode : public BitField<VariableMode, FunctionVariableField::kNext, 3> {}; class AsmModuleField : public BitField<bool, FunctionVariableMode::kNext, 1> { @@ -4293,7 +4384,6 @@ class BytecodeArray : public FixedArrayBase { // Dispatched behavior. inline int BytecodeArraySize(); - inline void BytecodeArrayIterateBody(ObjectVisitor* v); DECLARE_PRINTER(BytecodeArray) DECLARE_VERIFIER(BytecodeArray) @@ -4313,6 +4403,8 @@ class BytecodeArray : public FixedArrayBase { // Maximal length of a single BytecodeArray. static const int kMaxLength = kMaxSize - kHeaderSize; + class BodyDescriptor; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArray); }; @@ -4336,7 +4428,6 @@ class FreeSpace: public HeapObject { // Accessors for the next field. inline FreeSpace* next(); - inline FreeSpace** next_address(); inline void set_next(FreeSpace* next); inline static FreeSpace* cast(HeapObject* obj); @@ -4379,11 +4470,6 @@ class FixedTypedArrayBase: public FixedArrayBase { DECL_ACCESSORS(external_pointer, void) // Dispatched behavior. - inline void FixedTypedArrayBaseIterateBody(ObjectVisitor* v); - - template <typename StaticVisitor> - inline void FixedTypedArrayBaseIterateBody(); - DECLARE_CAST(FixedTypedArrayBase) static const int kBasePointerOffset = FixedArrayBase::kHeaderSize; @@ -4393,6 +4479,8 @@ class FixedTypedArrayBase: public FixedArrayBase { static const int kDataOffset = kHeaderSize; + class BodyDescriptor; + inline int size(); static inline int TypedArraySize(InstanceType type, int length); @@ -4705,9 +4793,9 @@ class Code: public HeapObject { NUMBER_OF_KINDS }; - // No more than 16 kinds. The value is currently encoded in four bits in + // No more than 32 kinds. The value is currently encoded in five bits in // Flags. - STATIC_ASSERT(NUMBER_OF_KINDS <= 16); + STATIC_ASSERT(NUMBER_OF_KINDS <= 32); static const char* Kind2String(Kind kind); @@ -4809,6 +4897,7 @@ class Code: public HeapObject { inline bool is_to_boolean_ic_stub(); inline bool is_keyed_stub(); inline bool is_optimized_code(); + inline bool is_interpreter_entry_trampoline(); inline bool embeds_maps_weakly(); inline bool IsCodeStubOrIC(); @@ -4890,12 +4979,6 @@ class Code: public HeapObject { // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in. inline uint16_t to_boolean_state(); - // [has_function_cache]: For kind STUB tells whether there is a function - // cache is passed to the stub. - inline bool has_function_cache(); - inline void set_has_function_cache(bool flag); - - // [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether // the code is going to be deoptimized because of dead embedded maps. inline bool marked_for_deoptimization(); @@ -5020,10 +5103,6 @@ class Code: public HeapObject { // Dispatched behavior. inline int CodeSize(); - inline void CodeIterateBody(ObjectVisitor* v); - - template<typename StaticVisitor> - inline void CodeIterateBody(Heap* heap); DECLARE_PRINTER(Code) DECLARE_VERIFIER(Code) @@ -5122,6 +5201,8 @@ class Code: public HeapObject { static const int kHeaderSize = (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask; + class BodyDescriptor; + // Byte offsets within kKindSpecificFlags1Offset. static const int kFullCodeFlags = kKindSpecificFlags1Offset; class FullCodeFlagsHasDeoptimizationSupportField: @@ -5133,19 +5214,18 @@ class Code: public HeapObject { class ProfilerTicksField : public BitField<int, 4, 28> {}; // Flags layout. BitField<type, shift, size>. - class ICStateField : public BitField<InlineCacheState, 0, 4> {}; - class TypeField : public BitField<StubType, 4, 1> {}; - class CacheHolderField : public BitField<CacheHolderFlag, 5, 2> {}; - class KindField : public BitField<Kind, 7, 4> {}; + class ICStateField : public BitField<InlineCacheState, 0, 3> {}; + class TypeField : public BitField<StubType, 3, 1> {}; + class CacheHolderField : public BitField<CacheHolderFlag, 4, 2> {}; + class KindField : public BitField<Kind, 6, 5> {}; class ExtraICStateField: public BitField<ExtraICState, 11, PlatformSmiTagging::kSmiValueSize - 11 + 1> {}; // NOLINT // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION) static const int kStackSlotsFirstBit = 0; static const int kStackSlotsBitCount = 24; - static const int kHasFunctionCacheBit = + static const int kMarkedForDeoptimizationBit = kStackSlotsFirstBit + kStackSlotsBitCount; - static const int kMarkedForDeoptimizationBit = kHasFunctionCacheBit + 1; static const int kIsTurbofannedBit = kMarkedForDeoptimizationBit + 1; static const int kCanHaveWeakObjects = kIsTurbofannedBit + 1; @@ -5154,10 +5234,8 @@ class Code: public HeapObject { class StackSlotsField: public BitField<int, kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT - class HasFunctionCacheField : public BitField<bool, kHasFunctionCacheBit, 1> { - }; // NOLINT class MarkedForDeoptimizationField - : public BitField<bool, kMarkedForDeoptimizationBit, 1> {}; // NOLINT + : public BitField<bool, kMarkedForDeoptimizationBit, 1> {}; // NOLINT class IsTurbofannedField : public BitField<bool, kIsTurbofannedBit, 1> { }; // NOLINT class CanHaveWeakObjectsField @@ -5217,24 +5295,24 @@ class Code: public HeapObject { }; -// This class describes the layout of dependent codes array of a map. The -// array is partitioned into several groups of dependent codes. Each group -// contains codes with the same dependency on the map. The array has the -// following layout for n dependency groups: -// -// +----+----+-----+----+---------+----------+-----+---------+-----------+ -// | C1 | C2 | ... | Cn | group 1 | group 2 | ... | group n | undefined | -// +----+----+-----+----+---------+----------+-----+---------+-----------+ +// Dependent code is a singly linked list of fixed arrays. Each array contains +// code objects in weak cells for one dependent group. The suffix of the array +// can be filled with the undefined value if the number of codes is less than +// the length of the array. // -// The first n elements are Smis, each of them specifies the number of codes -// in the corresponding group. The subsequent elements contain grouped code -// objects in weak cells. The suffix of the array can be filled with the -// undefined value if the number of codes is less than the length of the -// array. The order of the code objects within a group is not preserved. +// +------+-----------------+--------+--------+-----+--------+-----------+-----+ +// | next | count & group 1 | code 1 | code 2 | ... | code n | undefined | ... | +// +------+-----------------+--------+--------+-----+--------+-----------+-----+ +// | +// V +// +------+-----------------+--------+--------+-----+--------+-----------+-----+ +// | next | count & group 2 | code 1 | code 2 | ... | code m | undefined | ... | +// +------+-----------------+--------+--------+-----+--------+-----------+-----+ +// | +// V +// empty_fixed_array() // -// All code indexes used in the class are counted starting from the first -// code object of the first group. In other words, code index 0 corresponds -// to array index n = kCodesStartIndex. +// The list of fixed arrays is ordered by dependency groups. class DependentCode: public FixedArray { public: @@ -5269,19 +5347,8 @@ class DependentCode: public FixedArray { static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1; - // Array for holding the index of the first code object of each group. - // The last element stores the total number of code objects. - class GroupStartIndexes { - public: - explicit GroupStartIndexes(DependentCode* entries); - void Recompute(DependentCode* entries); - int at(int i) { return start_indexes_[i]; } - int number_of_entries() { return start_indexes_[kGroupCount]; } - private: - int start_indexes_[kGroupCount + 1]; - }; - bool Contains(DependencyGroup group, WeakCell* code_cell); + bool IsEmpty(DependencyGroup group); static Handle<DependentCode> InsertCompilationDependencies( Handle<DependentCode> entries, DependencyGroup group, @@ -5305,8 +5372,12 @@ class DependentCode: public FixedArray { // The following low-level accessors should only be used by this class // and the mark compact collector. - inline int number_of_entries(DependencyGroup group); - inline void set_number_of_entries(DependencyGroup group, int value); + inline DependentCode* next_link(); + inline void set_next_link(DependentCode* next); + inline int count(); + inline void set_count(int value); + inline DependencyGroup group(); + inline void set_group(DependencyGroup group); inline Object* object_at(int i); inline void set_object_at(int i, Object* object); inline void clear_at(int i); @@ -5320,10 +5391,9 @@ class DependentCode: public FixedArray { static Handle<DependentCode> Insert(Handle<DependentCode> entries, DependencyGroup group, Handle<Object> object); + static Handle<DependentCode> New(DependencyGroup group, Handle<Object> object, + Handle<DependentCode> next); static Handle<DependentCode> EnsureSpace(Handle<DependentCode> entries); - // Make a room at the end of the given group by moving out the first - // code objects of the subsequent groups. - inline void ExtendGroup(DependencyGroup group); // Compact by removing cleared weak cells and return true if there was // any cleared weak cell. bool Compact(); @@ -5331,7 +5401,14 @@ class DependentCode: public FixedArray { if (number_of_entries < 5) return number_of_entries + 1; return number_of_entries * 5 / 4; } - static const int kCodesStartIndex = kGroupCount; + inline int flags(); + inline void set_flags(int flags); + class GroupField : public BitField<int, 0, 3> {}; + class CountField : public BitField<int, 3, 27> {}; + STATIC_ASSERT(kGroupCount <= GroupField::kMax + 1); + static const int kNextLinkIndex = 0; + static const int kFlagsIndex = 1; + static const int kCodesStartIndex = 2; }; @@ -5367,6 +5444,8 @@ class Map: public HeapObject { static const int kNoConstructorFunctionIndex = 0; inline int GetConstructorFunctionIndex(); inline void SetConstructorFunctionIndex(int value); + static MaybeHandle<JSFunction> GetConstructorFunction( + Handle<Map> map, Handle<Context> native_context); // Instance type. inline InstanceType instance_type(); @@ -5401,18 +5480,66 @@ class Map: public HeapObject { class IsUnstable : public BitField<bool, 24, 1> {}; class IsMigrationTarget : public BitField<bool, 25, 1> {}; class IsStrong : public BitField<bool, 26, 1> {}; - // Bit 27 is free. + class NewTargetIsBase : public BitField<bool, 27, 1> {}; + // Bit 28 is free. // Keep this bit field at the very end for better code in // Builtins::kJSConstructStubGeneric stub. - // This counter is used for in-object slack tracking and for map aging. + // This counter is used for in-object slack tracking. // The in-object slack tracking is considered enabled when the counter is - // in the range [kSlackTrackingCounterStart, kSlackTrackingCounterEnd]. - class Counter : public BitField<int, 28, 4> {}; - static const int kSlackTrackingCounterStart = 14; - static const int kSlackTrackingCounterEnd = 8; - static const int kRetainingCounterStart = kSlackTrackingCounterEnd - 1; - static const int kRetainingCounterEnd = 0; + // non zero. + class ConstructionCounter : public BitField<int, 29, 3> {}; + static const int kSlackTrackingCounterStart = 7; + static const int kSlackTrackingCounterEnd = 1; + static const int kNoSlackTracking = 0; + STATIC_ASSERT(kSlackTrackingCounterStart <= ConstructionCounter::kMax); + + + // Inobject slack tracking is the way to reclaim unused inobject space. + // + // The instance size is initially determined by adding some slack to + // expected_nof_properties (to allow for a few extra properties added + // after the constructor). There is no guarantee that the extra space + // will not be wasted. + // + // Here is the algorithm to reclaim the unused inobject space: + // - Detect the first constructor call for this JSFunction. + // When it happens enter the "in progress" state: initialize construction + // counter in the initial_map. + // - While the tracking is in progress initialize unused properties of a new + // object with one_pointer_filler_map instead of undefined_value (the "used" + // part is initialized with undefined_value as usual). This way they can + // be resized quickly and safely. + // - Once enough objects have been created compute the 'slack' + // (traverse the map transition tree starting from the + // initial_map and find the lowest value of unused_property_fields). + // - Traverse the transition tree again and decrease the instance size + // of every map. Existing objects will resize automatically (they are + // filled with one_pointer_filler_map). All further allocations will + // use the adjusted instance size. + // - SharedFunctionInfo's expected_nof_properties left unmodified since + // allocations made using different closures could actually create different + // kind of objects (see prototype inheritance pattern). + // + // Important: inobject slack tracking is not attempted during the snapshot + // creation. + + static const int kGenerousAllocationCount = + kSlackTrackingCounterStart - kSlackTrackingCounterEnd + 1; + + // Starts the tracking by initializing object constructions countdown counter. + void StartInobjectSlackTracking(); + + // True if the object constructions countdown counter is a range + // [kSlackTrackingCounterEnd, kSlackTrackingCounterStart]. + inline bool IsInobjectSlackTrackingInProgress(); + + // Does the tracking step. + inline void InobjectSlackTrackingStep(); + + // Completes inobject slack tracking for the transition tree starting at this + // initial map. + void CompleteInobjectSlackTracking(); // Tells whether the object in the prototype property will be used // for instances created from this function. If the prototype @@ -5424,7 +5551,7 @@ class Map: public HeapObject { // Tells whether the instance has a [[Construct]] internal method. // This property is implemented according to ES6, section 7.2.4. - inline void set_is_constructor(bool value); + inline void set_is_constructor(); inline bool is_constructor() const; // Tells whether the instance with this map should be ignored by the @@ -5460,6 +5587,8 @@ class Map: public HeapObject { inline void set_is_strong(); inline bool is_strong(); + inline void set_new_target_is_base(bool value); + inline bool new_target_is_base(); inline void set_is_extensible(bool value); inline bool is_extensible(); inline void set_is_prototype_map(bool value); @@ -5550,10 +5679,6 @@ class Map: public HeapObject { static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode, const char* reason); - // Returns the constructor name (the name (possibly, inferred name) of the - // function that was used to instantiate the object). - String* constructor_name(); - // 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. @@ -5636,8 +5761,8 @@ class Map: public HeapObject { inline bool is_stable(); inline void set_migration_target(bool value); inline bool is_migration_target(); - inline void set_counter(int value); - inline int counter(); + inline void set_construction_counter(int value); + inline int construction_counter(); inline void deprecate(); inline bool is_deprecated(); inline bool CanBeDeprecated(); @@ -5653,6 +5778,10 @@ class Map: public HeapObject { // gathering type feedback. Use TryUpdate in those cases instead. static Handle<Map> Update(Handle<Map> map); + static inline Handle<Map> CopyInitialMap(Handle<Map> map); + static Handle<Map> CopyInitialMap(Handle<Map> map, int instance_size, + int in_object_properties, + int unused_property_fields); static Handle<Map> CopyDropDescriptors(Handle<Map> map); static Handle<Map> CopyInsertDescriptor(Handle<Map> map, Descriptor* descriptor, @@ -5684,6 +5813,11 @@ class Map: public HeapObject { ElementsKind kind, TransitionFlag flag); + static Handle<Map> AsLanguageMode(Handle<Map> initial_map, + LanguageMode language_mode, + FunctionKind kind); + + static Handle<Map> CopyForObserved(Handle<Map> map); static Handle<Map> CopyForPreventExtensions(Handle<Map> map, @@ -5729,7 +5863,7 @@ class Map: public HeapObject { // Returns the number of properties described in instance_descriptors // filtering out properties with the specified attributes. int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS, - PropertyAttributes filter = NONE); + PropertyFilter filter = ALL_PROPERTIES); DECLARE_CAST(Map) @@ -5779,7 +5913,9 @@ class Map: public HeapObject { inline bool CanTransition(); + inline bool IsBooleanMap(); inline bool IsPrimitiveMap(); + inline bool IsJSReceiverMap(); inline bool IsJSObjectMap(); inline bool IsJSArrayMap(); inline bool IsJSFunctionMap(); @@ -5787,7 +5923,8 @@ class Map: public HeapObject { inline bool IsJSProxyMap(); inline bool IsJSGlobalProxyMap(); inline bool IsJSGlobalObjectMap(); - inline bool IsGlobalObjectMap(); + inline bool IsJSTypedArrayMap(); + inline bool IsJSDataViewMap(); inline bool CanOmitMapChecks(); @@ -5926,9 +6063,9 @@ class Map: public HeapObject { static void TraceAllTransitions(Map* map); #endif - static inline Handle<Map> CopyInstallDescriptorsForTesting( - Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors, - Handle<LayoutDescriptor> layout_descriptor); + static inline Handle<Map> AddMissingTransitionsForTesting( + Handle<Map> split_map, Handle<DescriptorArray> descriptors, + Handle<LayoutDescriptor> full_layout_descriptor); private: static void ConnectTransition(Handle<Map> parent, Handle<Map> child, @@ -5939,9 +6076,13 @@ class Map: public HeapObject { static Handle<Map> ShareDescriptor(Handle<Map> map, Handle<DescriptorArray> descriptors, Descriptor* descriptor); - static Handle<Map> CopyInstallDescriptors( - Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors, - Handle<LayoutDescriptor> layout_descriptor); + static Handle<Map> AddMissingTransitions( + Handle<Map> map, Handle<DescriptorArray> descriptors, + Handle<LayoutDescriptor> full_layout_descriptor); + static void InstallDescriptors( + Handle<Map> parent_map, Handle<Map> child_map, int new_descriptor, + Handle<DescriptorArray> descriptors, + Handle<LayoutDescriptor> full_layout_descriptor); static Handle<Map> CopyAddDescriptor(Handle<Map> map, Descriptor* descriptor, TransitionFlag flag); @@ -5969,10 +6110,10 @@ class Map: public HeapObject { inline void NotifyLeafMapLayoutChange(); void DeprecateTransitionTree(); - bool DeprecateTarget(PropertyKind kind, Name* key, - PropertyAttributes attributes, - DescriptorArray* new_descriptors, - LayoutDescriptor* new_layout_descriptor); + + void ReplaceDescriptors(DescriptorArray* new_descriptors, + LayoutDescriptor* new_layout_descriptor); + Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors); @@ -6052,8 +6193,6 @@ class PrototypeInfo : public Struct { // given receiver embed the currently valid cell for that receiver's prototype // during their compilation and check it on execution. DECL_ACCESSORS(validity_cell, Object) - // [constructor_name]: User-friendly name of the original constructor. - DECL_ACCESSORS(constructor_name, Object) DECLARE_CAST(PrototypeInfo) @@ -6345,8 +6484,8 @@ class SharedFunctionInfo: public HeapObject { inline void ReplaceCode(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) + // and a shared literals array. + DECL_ACCESSORS(optimized_code_map, FixedArray) // Returns entry from optimized code map for specified context and OSR entry. // Note that {code == nullptr, literals == nullptr} indicates no matching @@ -6358,6 +6497,11 @@ class SharedFunctionInfo: public HeapObject { // Clear optimized code map. void ClearOptimizedCodeMap(); + // We have a special root FixedArray with the right shape and values + // to represent the cleared optimized code map. This predicate checks + // if that root is installed. + inline bool OptimizedCodeMapIsCleared() const; + // Removes a specific optimized code object from the optimized code map. // In case of non-OSR the code reference is cleared from the cache entry but // the entry itself is left in the map in order to proceed sharing literals. @@ -6371,13 +6515,17 @@ class SharedFunctionInfo: public HeapObject { Handle<Code> code); // Add a new entry to the optimized code map for context-dependent code. - // |code| is either a code object or an undefined value. In the latter case - // the entry just maps |native_context, osr_ast_id| pair to |literals| array. - static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared, - Handle<Context> native_context, - Handle<HeapObject> code, - Handle<LiteralsArray> literals, - BailoutId osr_ast_id); + inline static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared, + Handle<Context> native_context, + Handle<Code> code, + Handle<LiteralsArray> literals, + BailoutId osr_ast_id); + + // We may already have cached the code, but want to store literals in the + // cache. + inline static void AddLiteralsToOptimizedCodeMap( + Handle<SharedFunctionInfo> shared, Handle<Context> native_context, + Handle<LiteralsArray> literals); // Set up the link between shared function info and the script. The shared // function info is added to the list on the script. @@ -6385,9 +6533,8 @@ class SharedFunctionInfo: public HeapObject { Handle<Object> script_object); // Layout description of the optimized code map. - static const int kNextMapIndex = 0; - static const int kSharedCodeIndex = 1; - static const int kEntriesStart = 2; + static const int kSharedCodeIndex = 0; + static const int kEntriesStart = 1; static const int kContextOffset = 0; static const int kCachedCodeOffset = 1; static const int kLiteralsOffset = 2; @@ -6579,10 +6726,6 @@ class SharedFunctionInfo: public HeapObject { // see a binding for it. DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous) - // Indicates whether the function is a bound function created using - // the bind function. - DECL_BOOLEAN_ACCESSORS(bound) - // Indicates that the function is anonymous (the name field can be set // through the API, which does not change this flag). DECL_BOOLEAN_ACCESSORS(is_anonymous) @@ -6683,12 +6826,9 @@ class SharedFunctionInfo: public HeapObject { // Source size of this function. int SourceSize(); - // Calculate the instance size. - int CalculateInstanceSize(); - - // Calculate the number of in-object properties. - int CalculateInObjectProperties(); - + // Returns `false` if formal parameters include rest parameters, optional + // parameters, or destructuring parameters. + // TODO(caitp): make this a flag set during parsing inline bool has_simple_parameters(); // Initialize a SharedFunctionInfo from a parsed function literal. @@ -6701,9 +6841,7 @@ class SharedFunctionInfo: public HeapObject { void ResetForNewContext(int new_ic_age); - // Iterate over all shared function infos that are created from a script. - // That excludes shared function infos created for API functions and C++ - // builtins. + // Iterate over all shared function infos. class Iterator { public: explicit Iterator(Isolate* isolate); @@ -6776,15 +6914,14 @@ class SharedFunctionInfo: public HeapObject { // Total size. static const int kSize = kProfilerTicksOffset + kPointerSize; #else - // The only reason to use smi fields instead of int fields - // is to allow iteration without maps decoding during - // garbage collections. - // To avoid wasting space on 64-bit architectures we use - // the following trick: we group integer fields into pairs -// The least significant integer in each pair is shifted left by 1. -// By doing this we guarantee that LSB of each kPointerSize aligned -// word is not set and thus this word cannot be treated as pointer -// to HeapObject during old space traversal. +// The only reason to use smi fields instead of int fields is to allow +// iteration without maps decoding during garbage collections. +// To avoid wasting space on 64-bit architectures we use the following trick: +// we group integer fields into pairs +// The least significant integer in each pair is shifted left by 1. By doing +// this we guarantee that LSB of each kPointerSize aligned word is not set and +// thus this word cannot be treated as pointer to HeapObject during old space +// traversal. #if V8_TARGET_LITTLE_ENDIAN static const int kLengthOffset = kLastPointerFieldOffset + kPointerSize; static const int kFormalParameterCountOffset = @@ -6866,6 +7003,7 @@ class SharedFunctionInfo: public HeapObject { // Bit positions in compiler_hints. enum CompilerHints { + // byte 0 kAllowLazyCompilation, kAllowLazyCompilationWithoutContext, kOptimizationDisabled, @@ -6874,29 +7012,47 @@ class SharedFunctionInfo: public HeapObject { kStrongModeFunction, kUsesArguments, kNeedsHomeObject, + // byte 1 kHasDuplicateParameters, kForceInline, - kBoundFunction, + kIsAsmFunction, kIsAnonymous, kNameShouldPrintAsAnonymous, kIsFunction, kDontCrankshaft, kDontFlush, - kIsArrow, + // byte 2 + kFunctionKind, + kIsArrow = kFunctionKind, kIsGenerator, kIsConciseMethod, kIsAccessorFunction, kIsDefaultConstructor, kIsSubclassConstructor, kIsBaseConstructor, - kInClassLiteral, - kIsAsmFunction, + kIsInObjectLiteral, + // byte 3 kDeserialized, kNeverCompiled, - kCompilerHintsCount // Pseudo entry + kCompilerHintsCount, // Pseudo entry }; // Add hints for other modes when they're added. STATIC_ASSERT(LANGUAGE_END == 3); + // kFunctionKind has to be byte-aligned + STATIC_ASSERT((kFunctionKind % kBitsPerByte) == 0); +// Make sure that FunctionKind and byte 2 are in sync: +#define ASSERT_FUNCTION_KIND_ORDER(functionKind, compilerFunctionKind) \ + STATIC_ASSERT(FunctionKind::functionKind == \ + 1 << (compilerFunctionKind - kFunctionKind)) + ASSERT_FUNCTION_KIND_ORDER(kArrowFunction, kIsArrow); + ASSERT_FUNCTION_KIND_ORDER(kGeneratorFunction, kIsGenerator); + ASSERT_FUNCTION_KIND_ORDER(kConciseMethod, kIsConciseMethod); + ASSERT_FUNCTION_KIND_ORDER(kAccessorFunction, kIsAccessorFunction); + ASSERT_FUNCTION_KIND_ORDER(kDefaultConstructor, kIsDefaultConstructor); + ASSERT_FUNCTION_KIND_ORDER(kSubclassConstructor, kIsSubclassConstructor); + ASSERT_FUNCTION_KIND_ORDER(kBaseConstructor, kIsBaseConstructor); + ASSERT_FUNCTION_KIND_ORDER(kInObjectLiteral, kIsInObjectLiteral); +#undef ASSERT_FUNCTION_KIND_ORDER class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 8> {}; @@ -6923,46 +7079,44 @@ class SharedFunctionInfo: public HeapObject { public: // Constants for optimizing codegen for strict mode function and + // native tests when using integer-width instructions. + static const int kStrictModeBit = + kStrictModeFunction + kCompilerHintsSmiTagSize; + static const int kStrongModeBit = + kStrongModeFunction + kCompilerHintsSmiTagSize; + static const int kNativeBit = kNative + kCompilerHintsSmiTagSize; + + static const int kClassConstructorBits = + FunctionKind::kClassConstructor + << (kFunctionKind + kCompilerHintsSmiTagSize); + + // Constants for optimizing codegen for strict mode function and // native tests. // Allows to use byte-width instructions. - static const int kStrictModeBitWithinByte = - (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte; - static const int kStrongModeBitWithinByte = - (kStrongModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte; - - static const int kNativeBitWithinByte = - (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte; + static const int kStrictModeBitWithinByte = kStrictModeBit % kBitsPerByte; + static const int kStrongModeBitWithinByte = kStrongModeBit % kBitsPerByte; + static const int kNativeBitWithinByte = kNativeBit % kBitsPerByte; - static const int kBoundBitWithinByte = - (kBoundFunction + kCompilerHintsSmiTagSize) % kBitsPerByte; + static const int kClassConstructorBitsWithinByte = + FunctionKind::kClassConstructor << kCompilerHintsSmiTagSize; + STATIC_ASSERT(kClassConstructorBitsWithinByte < (1 << kBitsPerByte)); #if defined(V8_TARGET_LITTLE_ENDIAN) - static const int kStrictModeByteOffset = kCompilerHintsOffset + - (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte; - static const int kStrongModeByteOffset = - kCompilerHintsOffset + - (kStrongModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte; - static const int kNativeByteOffset = kCompilerHintsOffset + - (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte; - static const int kBoundByteOffset = - kCompilerHintsOffset + - (kBoundFunction + kCompilerHintsSmiTagSize) / kBitsPerByte; +#define BYTE_OFFSET(compiler_hint) \ + kCompilerHintsOffset + \ + (compiler_hint + kCompilerHintsSmiTagSize) / kBitsPerByte #elif defined(V8_TARGET_BIG_ENDIAN) - static const int kStrictModeByteOffset = kCompilerHintsOffset + - (kCompilerHintsSize - 1) - - ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte); - static const int kStrongModeByteOffset = - kCompilerHintsOffset + (kCompilerHintsSize - 1) - - ((kStrongModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte); - static const int kNativeByteOffset = kCompilerHintsOffset + - (kCompilerHintsSize - 1) - - ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte); - static const int kBoundByteOffset = - kCompilerHintsOffset + (kCompilerHintsSize - 1) - - ((kBoundFunction + kCompilerHintsSmiTagSize) / kBitsPerByte); +#define BYTE_OFFSET(compiler_hint) \ + kCompilerHintsOffset + (kCompilerHintsSize - 1) - \ + ((compiler_hint + kCompilerHintsSmiTagSize) / kBitsPerByte) #else #error Unknown byte ordering #endif + static const int kStrictModeByteOffset = BYTE_OFFSET(kStrictModeFunction); + static const int kStrongModeByteOffset = BYTE_OFFSET(kStrongModeFunction); + static const int kNativeByteOffset = BYTE_OFFSET(kNative); + static const int kFunctionKindByteOffset = BYTE_OFFSET(kFunctionKind); +#undef BYTE_OFFSET private: // Returns entry from optimized code map for specified context and OSR entry. @@ -6971,6 +7125,13 @@ class SharedFunctionInfo: public HeapObject { int SearchOptimizedCodeMapEntry(Context* native_context, BailoutId osr_ast_id); + // If code is undefined, then existing code won't be overwritten. + static void AddToOptimizedCodeMapInternal(Handle<SharedFunctionInfo> shared, + Handle<Context> native_context, + Handle<HeapObject> code, + Handle<LiteralsArray> literals, + BailoutId osr_ast_id); + DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo); }; @@ -7063,6 +7224,64 @@ class JSModule: public JSObject { }; +// JSBoundFunction describes a bound function exotic object. +class JSBoundFunction : public JSObject { + public: + // [length]: The bound function "length" property. + DECL_ACCESSORS(length, Object) + + // [name]: The bound function "name" property. + DECL_ACCESSORS(name, Object) + + // [bound_target_function]: The wrapped function object. + DECL_ACCESSORS(bound_target_function, JSReceiver) + + // [bound_this]: The value that is always passed as the this value when + // calling the wrapped function. + DECL_ACCESSORS(bound_this, Object) + + // [bound_arguments]: A list of values whose elements are used as the first + // arguments to any call to the wrapped function. + DECL_ACCESSORS(bound_arguments, FixedArray) + + // [creation_context]: The native context in which the function was bound. + // TODO(bmeurer, verwaest): Can we (mis)use (unused) constructor field in + // the Map instead of putting this into the object? Only required for + // JSReceiver::GetCreationContext() anyway. + DECL_ACCESSORS(creation_context, Context) + + static MaybeHandle<Context> GetFunctionRealm( + Handle<JSBoundFunction> function); + + DECLARE_CAST(JSBoundFunction) + + // Dispatched behavior. + DECLARE_PRINTER(JSBoundFunction) + DECLARE_VERIFIER(JSBoundFunction) + + // The bound function's string representation implemented according + // to ES6 section 19.2.3.5 Function.prototype.toString ( ). + static Handle<String> ToString(Handle<JSBoundFunction> function); + + // Layout description. + static const int kBoundTargetFunctionOffset = JSObject::kHeaderSize; + static const int kBoundThisOffset = kBoundTargetFunctionOffset + kPointerSize; + static const int kBoundArgumentsOffset = kBoundThisOffset + kPointerSize; + static const int kCreationContextOffset = + kBoundArgumentsOffset + kPointerSize; + static const int kLengthOffset = kCreationContextOffset + kPointerSize; + static const int kNameOffset = kLengthOffset + kPointerSize; + static const int kSize = kNameOffset + kPointerSize; + + // Indices of in-object properties. + static const int kLengthIndex = 0; + static const int kNameIndex = 1; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(JSBoundFunction); +}; + + // JSFunction describes JavaScript functions. class JSFunction: public JSObject { public: @@ -7077,6 +7296,9 @@ class JSFunction: public JSObject { inline Context* context(); inline void set_context(Object* context); inline JSObject* global_proxy(); + inline Context* native_context(); + + static Handle<Context> GetFunctionRealm(Handle<JSFunction> function); // [code]: The generated code object for this function. Executed // when the function is invoked, e.g. foo() or new foo(). See @@ -7087,18 +7309,9 @@ class JSFunction: public JSObject { inline void set_code_no_write_barrier(Code* code); inline void ReplaceCode(Code* code); - // Tells whether this function is builtin. - inline bool IsBuiltin(); - // Tells whether this function inlines the given shared function info. bool Inlines(SharedFunctionInfo* candidate); - // Tells whether this function should be subject to debugging. - inline bool IsSubjectToDebugging(); - - // Tells whether or not the function needs arguments adaption. - inline bool NeedsArgumentsAdaption(); - // Tells whether or not this function has been optimized. inline bool IsOptimized(); @@ -7115,49 +7328,10 @@ class JSFunction: public JSObject { // Tells whether or not the function is on the concurrent recompilation queue. inline bool IsInOptimizationQueue(); - // Inobject slack tracking is the way to reclaim unused inobject space. - // - // The instance size is initially determined by adding some slack to - // expected_nof_properties (to allow for a few extra properties added - // after the constructor). There is no guarantee that the extra space - // will not be wasted. - // - // Here is the algorithm to reclaim the unused inobject space: - // - Detect the first constructor call for this JSFunction. - // When it happens enter the "in progress" state: initialize construction - // counter in the initial_map. - // - While the tracking is in progress create objects filled with - // one_pointer_filler_map instead of undefined_value. This way they can be - // resized quickly and safely. - // - Once enough objects have been created compute the 'slack' - // (traverse the map transition tree starting from the - // initial_map and find the lowest value of unused_property_fields). - // - Traverse the transition tree again and decrease the instance size - // of every map. Existing objects will resize automatically (they are - // filled with one_pointer_filler_map). All further allocations will - // use the adjusted instance size. - // - SharedFunctionInfo's expected_nof_properties left unmodified since - // allocations made using different closures could actually create different - // kind of objects (see prototype inheritance pattern). - // - // Important: inobject slack tracking is not attempted during the snapshot - // creation. + // Completes inobject slack tracking on initial map if it is active. + inline void CompleteInobjectSlackTrackingIfActive(); - // True if the initial_map is set and the object constructions countdown - // counter is not zero. - static const int kGenerousAllocationCount = - Map::kSlackTrackingCounterStart - Map::kSlackTrackingCounterEnd + 1; - inline bool IsInobjectSlackTrackingInProgress(); - - // Starts the tracking. - // Initializes object constructions countdown counter in the initial map. - void StartInobjectSlackTracking(); - - // Completes the tracking. - void CompleteInobjectSlackTracking(); - - // [literals_or_bindings]: Fixed array holding either - // the materialized literals or the bindings of a bound function. + // [literals]: Fixed array holding the materialized literals. // // If the function contains object, regexp or array literals, the // literals array prefix contains the object, regexp, and array @@ -7166,17 +7340,7 @@ class JSFunction: public JSObject { // or array functions. Performing a dynamic lookup, we might end up // using the functions from a new context that we should not have // access to. - // - // On bound functions, the array is a (copy-on-write) fixed-array containing - // the function that was bound, bound this-value and any bound - // arguments. Bound functions never contain literals. - DECL_ACCESSORS(literals_or_bindings, FixedArray) - - inline LiteralsArray* literals(); - inline void set_literals(LiteralsArray* literals); - - inline FixedArray* function_bindings(); - inline void set_function_bindings(FixedArray* bindings); + DECL_ACCESSORS(literals, LiteralsArray) // The initial map for an object created by this constructor. inline Map* initial_map(); @@ -7185,6 +7349,13 @@ class JSFunction: public JSObject { inline bool has_initial_map(); static void EnsureHasInitialMap(Handle<JSFunction> function); + // Creates a map that matches the constructor's initial map, but with + // [[prototype]] being new.target.prototype. Because new.target can be a + // JSProxy, this can call back into JavaScript. + static MUST_USE_RESULT MaybeHandle<Map> GetDerivedMap( + Isolate* isolate, Handle<JSFunction> constructor, + Handle<JSReceiver> new_target); + // Get and set the prototype property on a JSFunction. If the // function has an initial map the prototype is set on the initial // map. Otherwise, the prototype is put in the initial map field @@ -7202,25 +7373,9 @@ class JSFunction: public JSObject { // [[Construct]] from this function will not be allowed. bool RemovePrototype(); - // Accessor for this function's initial map's [[class]] - // property. This is primarily used by ECMA native functions. This - // method sets the class_name field of this function's initial map - // to a given value. It creates an initial map if this function does - // not have one. Note that this method does not copy the initial map - // if it has one already, but simply replaces it with the new value. - // Instances created afterwards will have a map whose [[class]] is - // set to 'value', but there is no guarantees on instances created - // before. - void SetInstanceClassName(String* name); - // Returns if this function has been compiled to native code yet. inline bool is_compiled(); - // Returns `false` if formal parameters include rest parameters, optional - // parameters, or destructuring parameters. - // TODO(caitp): make this a flag set during parsing - inline bool has_simple_parameters(); - // [next_function_link]: Links functions into various lists, e.g. the list // of optimized functions hanging off the native_context. The CodeFlusher // uses this link to chain together flushing candidates. Treated weakly @@ -7232,9 +7387,35 @@ class JSFunction: public JSObject { DECLARE_CAST(JSFunction) - // Iterates the objects, including code objects indirectly referenced - // through pointers to the first instruction in the code object. - void JSFunctionIterateBody(int object_size, ObjectVisitor* v); + // Calculate the instance size and in-object properties count. + void CalculateInstanceSize(InstanceType instance_type, + int requested_internal_fields, int* instance_size, + int* in_object_properties); + void CalculateInstanceSizeForDerivedClass(InstanceType instance_type, + int requested_internal_fields, + int* instance_size, + int* in_object_properties); + + // Visiting policy flags define whether the code entry or next function + // should be visited or not. + enum BodyVisitingPolicy { + kVisitCodeEntry = 1 << 0, + kVisitNextFunction = 1 << 1, + + kSkipCodeEntryAndNextFunction = 0, + kVisitCodeEntryAndNextFunction = kVisitCodeEntry | kVisitNextFunction + }; + // Iterates the function object according to the visiting policy. + template <BodyVisitingPolicy> + class BodyDescriptorImpl; + + // Visit the whole object. + typedef BodyDescriptorImpl<kVisitCodeEntryAndNextFunction> BodyDescriptor; + + // Don't visit next function. + typedef BodyDescriptorImpl<kVisitCodeEntry> BodyDescriptorStrongCode; + typedef BodyDescriptorImpl<kSkipCodeEntryAndNextFunction> + BodyDescriptorWeakCode; // Dispatched behavior. DECLARE_PRINTER(JSFunction) @@ -7248,26 +7429,29 @@ class JSFunction: public JSObject { // The function's name if it is configured, otherwise shared function info // debug name. + static Handle<String> GetName(Handle<JSFunction> function); + + // The function's displayName if it is set, otherwise name if it is + // configured, otherwise shared function info + // debug name. static Handle<String> GetDebugName(Handle<JSFunction> function); + // The function's string representation implemented according to + // ES6 section 19.2.3.5 Function.prototype.toString ( ). + static Handle<String> ToString(Handle<JSFunction> function); + // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to // kSize) is weak and has special handling during garbage collection. - static const int kCodeEntryOffset = JSObject::kHeaderSize; - static const int kPrototypeOrInitialMapOffset = - kCodeEntryOffset + kPointerSize; + static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize; static const int kSharedFunctionInfoOffset = kPrototypeOrInitialMapOffset + kPointerSize; static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize; static const int kLiteralsOffset = kContextOffset + kPointerSize; static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize; - static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset; + static const int kCodeEntryOffset = kNonWeakFieldsEndOffset; + static const int kNextFunctionLinkOffset = kCodeEntryOffset + kPointerSize; static const int kSize = kNextFunctionLinkOffset + kPointerSize; - // Layout of the bound-function binding array. - static const int kBoundFunctionIndex = 0; - static const int kBoundThisIndex = 1; - static const int kBoundArgumentsStartIndex = 2; - private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction); }; @@ -7292,7 +7476,7 @@ class JSGlobalProxy : public JSObject { DECLARE_CAST(JSGlobalProxy) - inline bool IsDetachedFrom(GlobalObject* global) const; + inline bool IsDetachedFrom(JSGlobalObject* global) const; // Dispatched behavior. DECLARE_PRINTER(JSGlobalProxy) @@ -7308,41 +7492,22 @@ class JSGlobalProxy : public JSObject { }; -// Common super class for JavaScript global objects and the special -// builtins global objects. -class GlobalObject: public JSObject { +// JavaScript global object. +class JSGlobalObject : public JSObject { public: - // [builtins]: the object holding the runtime routines written in JS. - DECL_ACCESSORS(builtins, JSBuiltinsObject) - // [native context]: the natives corresponding to this global object. DECL_ACCESSORS(native_context, Context) // [global proxy]: the global proxy object of the context DECL_ACCESSORS(global_proxy, JSObject) - DECLARE_CAST(GlobalObject) - static void InvalidatePropertyCell(Handle<GlobalObject> object, + static void InvalidatePropertyCell(Handle<JSGlobalObject> object, Handle<Name> name); // Ensure that the global object has a cell for the given property name. - static Handle<PropertyCell> EnsurePropertyCell(Handle<GlobalObject> global, + static Handle<PropertyCell> EnsurePropertyCell(Handle<JSGlobalObject> global, Handle<Name> name); - // Layout description. - static const int kBuiltinsOffset = JSObject::kHeaderSize; - static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize; - static const int kGlobalProxyOffset = kNativeContextOffset + kPointerSize; - static const int kHeaderSize = kGlobalProxyOffset + kPointerSize; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject); -}; - - -// JavaScript global object. -class JSGlobalObject: public GlobalObject { - public: DECLARE_CAST(JSGlobalObject) inline bool IsDetached(); @@ -7352,31 +7517,16 @@ class JSGlobalObject: public GlobalObject { DECLARE_VERIFIER(JSGlobalObject) // Layout description. - static const int kSize = GlobalObject::kHeaderSize; + static const int kNativeContextOffset = JSObject::kHeaderSize; + static const int kGlobalProxyOffset = kNativeContextOffset + kPointerSize; + static const int kHeaderSize = kGlobalProxyOffset + kPointerSize; + static const int kSize = kHeaderSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject); }; -// Builtins global object which holds the runtime routines written in -// JavaScript. -class JSBuiltinsObject: public GlobalObject { - public: - DECLARE_CAST(JSBuiltinsObject) - - // Dispatched behavior. - DECLARE_PRINTER(JSBuiltinsObject) - DECLARE_VERIFIER(JSBuiltinsObject) - - // Layout description. - static const int kSize = GlobalObject::kHeaderSize; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject); -}; - - // Representation for JS Wrapper objects, String, Number, Boolean, etc. class JSValue: public JSObject { public: @@ -7403,6 +7553,10 @@ class DateCache; // Representation for JS date objects. class JSDate: public JSObject { public: + static MUST_USE_RESULT MaybeHandle<JSDate> New(Handle<JSFunction> constructor, + Handle<JSReceiver> new_target, + double tv); + // If one component is NaN, all of them are, indicating a NaN time value. // [value]: the time value. DECL_ACCESSORS(value, Object) @@ -7426,10 +7580,15 @@ class JSDate: public JSObject { DECLARE_CAST(JSDate) + // Returns the time value (UTC) identifying the current time. + static double CurrentTimeValue(Isolate* isolate); + // Returns the date field with the specified index. // See FieldIndex for the list of date fields. static Object* GetField(Object* date, Smi* index); + static Handle<Object> SetValue(Handle<JSDate> date, double v); + void SetValue(Object* value, bool is_value_nan); // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] @@ -7569,28 +7728,28 @@ class JSRegExp: public JSObject { // IRREGEXP_NATIVE: Compiled to native code with Irregexp. enum Type { NOT_COMPILED, ATOM, IRREGEXP }; enum Flag { - NONE = 0, - GLOBAL = 1, - IGNORE_CASE = 2, - MULTILINE = 4, - STICKY = 8, - UNICODE_ESCAPES = 16 - }; - - class Flags { - public: - explicit Flags(uint32_t value) : value_(value) { } - bool is_global() { return (value_ & GLOBAL) != 0; } - bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; } - bool is_multiline() { return (value_ & MULTILINE) != 0; } - bool is_sticky() { return (value_ & STICKY) != 0; } - bool is_unicode() { return (value_ & UNICODE_ESCAPES) != 0; } - uint32_t value() { return value_; } - private: - uint32_t value_; + kNone = 0, + kGlobal = 1 << 0, + kIgnoreCase = 1 << 1, + kMultiline = 1 << 2, + kSticky = 1 << 3, + kUnicode = 1 << 4, }; + typedef base::Flags<Flag> Flags; DECL_ACCESSORS(data, Object) + DECL_ACCESSORS(flags, Object) + DECL_ACCESSORS(source, Object) + + static MaybeHandle<JSRegExp> New(Handle<String> source, Flags flags); + static MaybeHandle<JSRegExp> New(Handle<String> source, Handle<String> flags); + static Handle<JSRegExp> Copy(Handle<JSRegExp> regexp); + + static MaybeHandle<JSRegExp> Initialize(Handle<JSRegExp> regexp, + Handle<String> source, Flags flags); + static MaybeHandle<JSRegExp> Initialize(Handle<JSRegExp> regexp, + Handle<String> source, + Handle<String> flags_string); inline Type TypeTag(); inline int CaptureCount(); @@ -7619,10 +7778,13 @@ class JSRegExp: public JSObject { DECLARE_CAST(JSRegExp) // Dispatched behavior. + DECLARE_PRINTER(JSRegExp) DECLARE_VERIFIER(JSRegExp) static const int kDataOffset = JSObject::kHeaderSize; - static const int kSize = kDataOffset + kPointerSize; + static const int kSourceOffset = kDataOffset + kPointerSize; + static const int kFlagsOffset = kSourceOffset + kPointerSize; + static const int kSize = kFlagsOffset + kPointerSize; // Indices in the data array. static const int kTagIndex = 0; @@ -7671,12 +7833,8 @@ class JSRegExp: public JSObject { FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize; // In-object fields. - static const int kSourceFieldIndex = 0; - static const int kGlobalFieldIndex = 1; - static const int kIgnoreCaseFieldIndex = 2; - static const int kMultilineFieldIndex = 3; - static const int kLastIndexFieldIndex = 4; - static const int kInObjectFieldCount = 5; + static const int kLastIndexFieldIndex = 0; + static const int kInObjectFieldCount = 1; // The uninitialized value for a regexp code object. static const int kUninitializedValue = -1; @@ -7691,6 +7849,8 @@ class JSRegExp: public JSObject { static const int kCodeAgeMask = 0xff; }; +DEFINE_OPERATORS_FOR_FLAGS(JSRegExp::Flags) + class CompilationCacheShape : public BaseShape<HashTableKey*> { public: @@ -8001,7 +8161,7 @@ class AllocationSite: public Struct { // Increments the mementos found counter and returns true when the first // memento was found for a given allocation site. - inline bool IncrementMementoFoundCount(); + inline bool IncrementMementoFoundCount(int increment = 1); inline void IncrementMementoCreateCount(); @@ -8374,6 +8534,11 @@ class Symbol: public Name { // be used to designate own properties of objects. DECL_BOOLEAN_ACCESSORS(is_private) + // [is_well_known_symbol]: Whether this is a spec-defined well-known symbol, + // or not. Well-known symbols do not throw when an access check fails during + // a load. + DECL_BOOLEAN_ACCESSORS(is_well_known_symbol) + DECLARE_CAST(Symbol) // Dispatched behavior. @@ -8391,6 +8556,7 @@ class Symbol: public Name { private: static const int kPrivateBit = 0; + static const int kWellKnownSymbolBit = 1; const char* PrivateSymbolToName() const; @@ -9034,11 +9200,7 @@ class ExternalOneByteString : public ExternalString { DECLARE_CAST(ExternalOneByteString) - // Garbage collection support. - inline void ExternalOneByteStringIterateBody(ObjectVisitor* v); - - template <typename StaticVisitor> - inline void ExternalOneByteStringIterateBody(); + class BodyDescriptor; private: DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString); @@ -9073,11 +9235,7 @@ class ExternalTwoByteString: public ExternalString { DECLARE_CAST(ExternalTwoByteString) - // Garbage collection support. - inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v); - - template<typename StaticVisitor> - inline void ExternalTwoByteStringIterateBody(); + class BodyDescriptor; private: DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString); @@ -9371,7 +9529,7 @@ class WeakCell : public HeapObject { DECL_ACCESSORS(next, Object) - inline void clear_next(Heap* heap); + inline void clear_next(Object* the_hole_value); inline bool next_cleared(); @@ -9395,117 +9553,108 @@ class WeakCell : public HeapObject { // The JSProxy describes EcmaScript Harmony proxies class JSProxy: public JSReceiver { public: + MUST_USE_RESULT static MaybeHandle<JSProxy> New(Isolate* isolate, + Handle<Object>, + Handle<Object>); + // [handler]: The handler property. DECL_ACCESSORS(handler, Object) - + // [target]: The target property. + DECL_ACCESSORS(target, JSReceiver) // [hash]: The hash code property (undefined if not initialized yet). DECL_ACCESSORS(hash, Object) - DECLARE_CAST(JSProxy) + static MaybeHandle<Context> GetFunctionRealm(Handle<JSProxy> proxy); - MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler( - Handle<JSProxy> proxy, - Handle<Object> receiver, - Handle<Name> name); + DECLARE_CAST(JSProxy) - // If the handler defines an accessor property with a setter, invoke it. - // If it defines an accessor property without a setter, or a data property - // that is read-only, throw. In all these cases set '*done' to true, - // otherwise set it to false. - MUST_USE_RESULT - static MaybeHandle<Object> SetPropertyViaPrototypesWithHandler( - Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, - Handle<Object> value, LanguageMode language_mode, bool* done); + INLINE(bool IsRevoked() const); + static void Revoke(Handle<JSProxy> proxy); + + // ES6 9.5.1 + static MaybeHandle<Object> GetPrototype(Handle<JSProxy> receiver); + + // ES6 9.5.2 + MUST_USE_RESULT static Maybe<bool> SetPrototype(Handle<JSProxy> proxy, + Handle<Object> value, + bool from_javascript, + ShouldThrow should_throw); + // ES6 9.5.3 + MUST_USE_RESULT static Maybe<bool> IsExtensible(Handle<JSProxy> proxy); + + // ES6 9.5.4 (when passed DONT_THROW) + MUST_USE_RESULT static Maybe<bool> PreventExtensions( + Handle<JSProxy> proxy, ShouldThrow should_throw); + + // ES6 9.5.5 + MUST_USE_RESULT static Maybe<bool> GetOwnPropertyDescriptor( + Isolate* isolate, Handle<JSProxy> proxy, Handle<Name> name, + PropertyDescriptor* desc); + + // ES6 9.5.6 + MUST_USE_RESULT static Maybe<bool> DefineOwnProperty( + Isolate* isolate, Handle<JSProxy> object, Handle<Object> key, + PropertyDescriptor* desc, ShouldThrow should_throw); + + // ES6 9.5.7 + MUST_USE_RESULT static Maybe<bool> HasProperty(Isolate* isolate, + Handle<JSProxy> proxy, + Handle<Name> name); - MUST_USE_RESULT static Maybe<PropertyAttributes> - GetPropertyAttributesWithHandler(Handle<JSProxy> proxy, - Handle<Object> receiver, - Handle<Name> name); - MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler( - Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, - Handle<Object> value, LanguageMode language_mode); + // ES6 9.5.8 + MUST_USE_RESULT static MaybeHandle<Object> GetProperty( + Isolate* isolate, Handle<JSProxy> proxy, Handle<Name> name, + Handle<Object> receiver, LanguageMode language_mode); + + // ES6 9.5.9 + MUST_USE_RESULT static Maybe<bool> SetProperty(Handle<JSProxy> proxy, + Handle<Name> name, + Handle<Object> value, + Handle<Object> receiver, + LanguageMode language_mode); + + // ES6 9.5.10 (when passed SLOPPY) + MUST_USE_RESULT static Maybe<bool> DeletePropertyOrElement( + Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode); - // Turn the proxy into an (empty) JSObject. - static void Fix(Handle<JSProxy> proxy); + // ES6 9.5.11 + MUST_USE_RESULT static Maybe<bool> Enumerate(Isolate* isolate, + Handle<JSReceiver> receiver, + Handle<JSProxy> proxy, + KeyAccumulator* accumulator); - // Initializes the body after the handler slot. - inline void InitializeBody(int object_size, Object* value); + // ES6 9.5.12 + MUST_USE_RESULT static Maybe<bool> OwnPropertyKeys( + Isolate* isolate, Handle<JSReceiver> receiver, Handle<JSProxy> proxy, + PropertyFilter filter, KeyAccumulator* accumulator); - // Invoke a trap by name. If the trap does not exist on this's handler, - // but derived_trap is non-NULL, invoke that instead. May cause GC. - MUST_USE_RESULT static MaybeHandle<Object> CallTrap( - Handle<JSProxy> proxy, - const char* name, - Handle<Object> derived_trap, - int argc, - Handle<Object> args[]); + MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes( + LookupIterator* it); // Dispatched behavior. DECLARE_PRINTER(JSProxy) DECLARE_VERIFIER(JSProxy) - // Layout description. We add padding so that a proxy has the same - // size as a virgin JSObject. This is essential for becoming a JSObject - // upon freeze. - static const int kHandlerOffset = HeapObject::kHeaderSize; + // Layout description. + static const int kTargetOffset = JSReceiver::kHeaderSize; + static const int kHandlerOffset = kTargetOffset + kPointerSize; static const int kHashOffset = kHandlerOffset + kPointerSize; - static const int kPaddingOffset = kHashOffset + kPointerSize; - static const int kSize = JSObject::kHeaderSize; - static const int kHeaderSize = kPaddingOffset; - static const int kPaddingSize = kSize - kPaddingOffset; - - STATIC_ASSERT(kPaddingSize >= 0); - - typedef FixedBodyDescriptor<kHandlerOffset, - kPaddingOffset, - kSize> BodyDescriptor; - - private: - friend class JSReceiver; - - MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler( - Handle<JSProxy> proxy, Handle<Name> name); + static const int kSize = kHashOffset + kPointerSize; - MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler( - Handle<JSProxy> proxy, Handle<Name> name, LanguageMode language_mode); + typedef FixedBodyDescriptor<JSReceiver::kPropertiesOffset, kSize, kSize> + BodyDescriptor; MUST_USE_RESULT Object* GetIdentityHash(); static Handle<Smi> GetOrCreateIdentityHash(Handle<JSProxy> proxy); - DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy); -}; - - -class JSFunctionProxy: public JSProxy { - public: - // [call_trap]: The call trap. - DECL_ACCESSORS(call_trap, JSReceiver) - - // [construct_trap]: The construct trap. - DECL_ACCESSORS(construct_trap, Object) - - DECLARE_CAST(JSFunctionProxy) - - // Dispatched behavior. - DECLARE_PRINTER(JSFunctionProxy) - DECLARE_VERIFIER(JSFunctionProxy) - - // Layout description. - static const int kCallTrapOffset = JSProxy::kPaddingOffset; - static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize; - static const int kPaddingOffset = kConstructTrapOffset + kPointerSize; - static const int kSize = JSFunction::kSize; - static const int kPaddingSize = kSize - kPaddingOffset; - - STATIC_ASSERT(kPaddingSize >= 0); - - typedef FixedBodyDescriptor<kHandlerOffset, - kConstructTrapOffset + kPointerSize, - kSize> BodyDescriptor; - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy); + static Maybe<bool> AddPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy, + Handle<Symbol> private_name, + PropertyDescriptor* desc, + ShouldThrow should_throw); + + DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy); }; @@ -9715,6 +9864,20 @@ class JSWeakCollection: public JSObject { static const int kNextOffset = kTableOffset + kPointerSize; static const int kSize = kNextOffset + kPointerSize; + // Visiting policy defines whether the table and next collection fields + // should be visited or not. + enum BodyVisitingPolicy { kVisitStrong, kVisitWeak }; + + // Iterates the function object according to the visiting policy. + template <BodyVisitingPolicy> + class BodyDescriptorImpl; + + // Visit the whole object. + typedef BodyDescriptorImpl<kVisitStrong> BodyDescriptor; + + // Don't visit table and next collection fields. + typedef BodyDescriptorImpl<kVisitWeak> BodyDescriptorWeak; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection); }; @@ -9793,11 +9956,6 @@ class JSArrayBuffer: public JSObject { DECLARE_VERIFIER(JSArrayBuffer) static const int kByteLengthOffset = JSObject::kHeaderSize; - - // NOTE: GC will visit objects fields: - // 1. From JSObject::BodyDescriptor::kStartOffset to kByteLengthOffset + - // kPointerSize - // 2. From start of the internal fields and up to the end of them static const int kBackingStoreOffset = kByteLengthOffset + kPointerSize; static const int kBitFieldSlot = kBackingStoreOffset + kPointerSize; #if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT @@ -9810,11 +9968,9 @@ class JSArrayBuffer: public JSObject { static const int kSizeWithInternalFields = kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize; - template <typename StaticVisitor> - static inline void JSArrayBufferIterateBody(Heap* heap, HeapObject* obj); - - static inline void JSArrayBufferIterateBody(HeapObject* obj, - ObjectVisitor* v); + // Iterates all fields in the object including internal ones except + // kBackingStoreOffset and kBitFieldSlot. + class BodyDescriptor; class IsExternal : public BitField<bool, 1, 1> {}; class IsNeuterable : public BitField<bool, 2, 1> {}; @@ -9920,12 +10076,6 @@ class Foreign: public HeapObject { DECLARE_CAST(Foreign) // Dispatched behavior. - inline void ForeignIterateBody(ObjectVisitor* v); - - template<typename StaticVisitor> - inline void ForeignIterateBody(); - - // Dispatched behavior. DECLARE_PRINTER(Foreign) DECLARE_VERIFIER(Foreign) @@ -9936,6 +10086,8 @@ class Foreign: public HeapObject { STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset); + class BodyDescriptor; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign); }; @@ -9957,7 +10109,6 @@ class JSArray: public JSObject { static bool HasReadOnlyLength(Handle<JSArray> array); static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); - static MaybeHandle<Object> ReadOnlyLengthError(Handle<JSArray> array); // Initialize the array with the given capacity. The function may // fail due to out-of-memory situations, but only if the requested @@ -9981,6 +10132,19 @@ class JSArray: public JSObject { static inline void SetContent(Handle<JSArray> array, Handle<FixedArrayBase> storage); + // ES6 9.4.2.1 + MUST_USE_RESULT static Maybe<bool> DefineOwnProperty( + Isolate* isolate, Handle<JSArray> o, Handle<Object> name, + PropertyDescriptor* desc, ShouldThrow should_throw); + + static bool AnythingToArrayLength(Isolate* isolate, + Handle<Object> length_object, + uint32_t* output); + MUST_USE_RESULT static Maybe<bool> ArraySetLength(Isolate* isolate, + Handle<JSArray> a, + PropertyDescriptor* desc, + ShouldThrow should_throw); + DECLARE_CAST(JSArray) // Dispatched behavior. @@ -9994,6 +10158,14 @@ class JSArray: public JSObject { static const int kLengthOffset = JSObject::kHeaderSize; static const int kSize = kLengthOffset + kPointerSize; + // 600 * KB is the Page::kMaxRegularHeapObjectSize defined in spaces.h which + // we do not want to include in objects.h + // Note that Page::kMaxRegularHeapObjectSize has to be in sync with + // kInitialMaxFastElementArray which is checked in a DCHECK in heap.cc. + static const int kInitialMaxFastElementArray = + (600 * KB - FixedArray::kHeaderSize - kSize - AllocationMemento::kSize) / + kPointerSize; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray); }; @@ -10162,6 +10334,7 @@ class AccessCheckInfo: public Struct { public: DECL_ACCESSORS(named_callback, Object) DECL_ACCESSORS(indexed_callback, Object) + DECL_ACCESSORS(callback, Object) DECL_ACCESSORS(data, Object) DECLARE_CAST(AccessCheckInfo) @@ -10172,7 +10345,8 @@ class AccessCheckInfo: public Struct { static const int kNamedCallbackOffset = HeapObject::kHeaderSize; static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize; - static const int kDataOffset = kIndexedCallbackOffset + kPointerSize; + static const int kCallbackOffset = kIndexedCallbackOffset + kPointerSize; + static const int kDataOffset = kCallbackOffset + kPointerSize; static const int kSize = kDataOffset + kPointerSize; private: @@ -10223,6 +10397,7 @@ class CallHandlerInfo: public Struct { public: DECL_ACCESSORS(callback, Object) DECL_ACCESSORS(data, Object) + DECL_ACCESSORS(fast_handler, Object) DECLARE_CAST(CallHandlerInfo) @@ -10232,7 +10407,8 @@ class CallHandlerInfo: public Struct { static const int kCallbackOffset = HeapObject::kHeaderSize; static const int kDataOffset = kCallbackOffset + kPointerSize; - static const int kSize = kDataOffset + kPointerSize; + static const int kFastHandlerOffset = kDataOffset + kPointerSize; + static const int kSize = kFastHandlerOffset + kPointerSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo); @@ -10254,7 +10430,9 @@ class TemplateInfo: public Struct { static const int kPropertyListOffset = kNumberOfProperties + kPointerSize; static const int kPropertyAccessorsOffset = kPropertyListOffset + kPointerSize; - static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize; + static const int kPropertyIntrinsicsOffset = + kPropertyAccessorsOffset + kPointerSize; + static const int kHeaderSize = kPropertyIntrinsicsOffset + kPointerSize; private: DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo); @@ -10359,21 +10537,6 @@ class ObjectTemplateInfo: public TemplateInfo { }; -class TypeSwitchInfo: public Struct { - public: - DECL_ACCESSORS(types, Object) - - DECLARE_CAST(TypeSwitchInfo) - - // Dispatched behavior. - DECLARE_PRINTER(TypeSwitchInfo) - DECLARE_VERIFIER(TypeSwitchInfo) - - static const int kTypesOffset = Struct::kHeaderSize; - static const int kSize = kTypesOffset + kPointerSize; -}; - - // The DebugInfo class holds additional information for a function being // debugged. class DebugInfo: public Struct { @@ -10577,13 +10740,6 @@ class ObjectVisitor BASE_EMBEDDED { }; -class StructBodyDescriptor : public - FlexibleBodyDescriptor<HeapObject::kHeaderSize> { - public: - static inline int SizeOf(Map* map, HeapObject* object); -}; - - // BooleanBit is a helper class for setting and getting a bit in an integer. class BooleanBit : public AllStatic { public: @@ -10602,28 +10758,7 @@ class BooleanBit : public AllStatic { }; -class KeyAccumulator final BASE_EMBEDDED { - public: - explicit KeyAccumulator(Isolate* isolate) : isolate_(isolate), length_(0) {} - - void AddKey(Handle<Object> key, int check_limit); - void AddKeys(Handle<FixedArray> array, FixedArray::KeyFilter filter); - void AddKeys(Handle<JSObject> array, FixedArray::KeyFilter filter); - void PrepareForComparisons(int count); - Handle<FixedArray> GetKeys(); - - int GetLength() { return length_; } - - private: - void EnsureCapacity(int capacity); - void Grow(); - - Isolate* isolate_; - Handle<FixedArray> keys_; - Handle<OrderedHashSet> set_; - int length_; - DISALLOW_COPY_AND_ASSIGN(KeyAccumulator); -}; -} } // namespace v8::internal +} // NOLINT, false-positive due to second-order macros. +} // NOLINT, false-positive due to second-order macros. #endif // V8_OBJECTS_H_ |