Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_OBJECTS_JS_OBJECTS_H_
6 : #define V8_OBJECTS_JS_OBJECTS_H_
7 :
8 : #include "src/objects.h"
9 : #include "src/objects/embedder-data-slot.h"
10 : #include "src/objects/property-array.h"
11 : #include "torque-generated/class-definitions-from-dsl.h"
12 :
13 : // Has to be the last include (doesn't have include guards):
14 : #include "src/objects/object-macros.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : enum InstanceType : uint16_t;
20 : class JSGlobalObject;
21 : class JSGlobalProxy;
22 :
23 : // JSReceiver includes types on which properties can be defined, i.e.,
24 : // JSObject and JSProxy.
25 : class JSReceiver : public HeapObject {
26 : public:
27 : NEVER_READ_ONLY_SPACE
28 : // Returns true if there is no slow (ie, dictionary) backing store.
29 : inline bool HasFastProperties() const;
30 :
31 : // Returns the properties array backing store if it
32 : // exists. Otherwise, returns an empty_property_array when there's a
33 : // Smi (hash code) or an empty_fixed_array for a fast properties
34 : // map.
35 : inline PropertyArray property_array() const;
36 :
37 : // Gets slow properties for non-global objects.
38 : inline NameDictionary property_dictionary() const;
39 :
40 : // Sets the properties backing store and makes sure any existing hash is moved
41 : // to the new properties store. To clear out the properties store, pass in the
42 : // empty_fixed_array(), the hash will be maintained in this case as well.
43 : void SetProperties(HeapObject properties);
44 :
45 : // There are five possible values for the properties offset.
46 : // 1) EmptyFixedArray/EmptyPropertyDictionary - This is the standard
47 : // placeholder.
48 : //
49 : // 2) Smi - This is the hash code of the object.
50 : //
51 : // 3) PropertyArray - This is similar to a FixedArray but stores
52 : // the hash code of the object in its length field. This is a fast
53 : // backing store.
54 : //
55 : // 4) NameDictionary - This is the dictionary-mode backing store.
56 : //
57 : // 4) GlobalDictionary - This is the backing store for the
58 : // GlobalObject.
59 : //
60 : // This is used only in the deoptimizer and heap. Please use the
61 : // above typed getters and setters to access the properties.
62 : DECL_ACCESSORS(raw_properties_or_hash, Object)
63 :
64 : inline void initialize_properties();
65 :
66 : // Deletes an existing named property in a normalized object.
67 : static void DeleteNormalizedProperty(Handle<JSReceiver> object, int entry);
68 :
69 : DECL_CAST(JSReceiver)
70 :
71 : // ES6 section 7.1.1 ToPrimitive
72 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> ToPrimitive(
73 : Handle<JSReceiver> receiver,
74 : ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
75 :
76 : // ES6 section 7.1.1.1 OrdinaryToPrimitive
77 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> OrdinaryToPrimitive(
78 : Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint);
79 :
80 : static MaybeHandle<NativeContext> GetFunctionRealm(
81 : Handle<JSReceiver> receiver);
82 :
83 : // Get the first non-hidden prototype.
84 : static inline MaybeHandle<Object> GetPrototype(Isolate* isolate,
85 : Handle<JSReceiver> receiver);
86 :
87 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasInPrototypeChain(
88 : Isolate* isolate, Handle<JSReceiver> object, Handle<Object> proto);
89 :
90 : // Reads all enumerable own properties of source and adds them to
91 : // target, using either Set or CreateDataProperty depending on the
92 : // use_set argument. This only copies values not present in the
93 : // maybe_excluded_properties list.
94 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetOrCopyDataProperties(
95 : Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
96 : const ScopedVector<Handle<Object>>* excluded_properties = nullptr,
97 : bool use_set = true);
98 :
99 : // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
100 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasProperty(LookupIterator* it);
101 : V8_WARN_UNUSED_RESULT static inline Maybe<bool> HasProperty(
102 : Handle<JSReceiver> object, Handle<Name> name);
103 : V8_WARN_UNUSED_RESULT static inline Maybe<bool> HasElement(
104 : Handle<JSReceiver> object, uint32_t index);
105 :
106 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasOwnProperty(
107 : Handle<JSReceiver> object, Handle<Name> name);
108 : V8_WARN_UNUSED_RESULT static inline Maybe<bool> HasOwnProperty(
109 : Handle<JSReceiver> object, uint32_t index);
110 :
111 : V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetProperty(
112 : Isolate* isolate, Handle<JSReceiver> receiver, const char* key);
113 : V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetProperty(
114 : Isolate* isolate, Handle<JSReceiver> receiver, Handle<Name> name);
115 : V8_WARN_UNUSED_RESULT static inline MaybeHandle<Object> GetElement(
116 : Isolate* isolate, Handle<JSReceiver> receiver, uint32_t index);
117 :
118 : // Implementation of ES6 [[Delete]]
119 : V8_WARN_UNUSED_RESULT static Maybe<bool> DeletePropertyOrElement(
120 : Handle<JSReceiver> object, Handle<Name> name,
121 : LanguageMode language_mode = LanguageMode::kSloppy);
122 : V8_WARN_UNUSED_RESULT static Maybe<bool> DeleteProperty(
123 : Handle<JSReceiver> object, Handle<Name> name,
124 : LanguageMode language_mode = LanguageMode::kSloppy);
125 : V8_WARN_UNUSED_RESULT static Maybe<bool> DeleteProperty(
126 : LookupIterator* it, LanguageMode language_mode);
127 : V8_WARN_UNUSED_RESULT static Maybe<bool> DeleteElement(
128 : Handle<JSReceiver> object, uint32_t index,
129 : LanguageMode language_mode = LanguageMode::kSloppy);
130 :
131 : V8_WARN_UNUSED_RESULT static Object DefineProperty(Isolate* isolate,
132 : Handle<Object> object,
133 : Handle<Object> name,
134 : Handle<Object> attributes);
135 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> DefineProperties(
136 : Isolate* isolate, Handle<Object> object, Handle<Object> properties);
137 :
138 : // "virtual" dispatcher to the correct [[DefineOwnProperty]] implementation.
139 : V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnProperty(
140 : Isolate* isolate, Handle<JSReceiver> object, Handle<Object> key,
141 : PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw);
142 :
143 : // ES6 7.3.4 (when passed kDontThrow)
144 : V8_WARN_UNUSED_RESULT static Maybe<bool> CreateDataProperty(
145 : Isolate* isolate, Handle<JSReceiver> object, Handle<Name> key,
146 : Handle<Object> value, Maybe<ShouldThrow> should_throw);
147 : V8_WARN_UNUSED_RESULT static Maybe<bool> CreateDataProperty(
148 : LookupIterator* it, Handle<Object> value,
149 : Maybe<ShouldThrow> should_throw);
150 :
151 : // ES6 9.1.6.1
152 : V8_WARN_UNUSED_RESULT static Maybe<bool> OrdinaryDefineOwnProperty(
153 : Isolate* isolate, Handle<JSObject> object, Handle<Object> key,
154 : PropertyDescriptor* desc, Maybe<ShouldThrow> should_throw);
155 : V8_WARN_UNUSED_RESULT static Maybe<bool> OrdinaryDefineOwnProperty(
156 : LookupIterator* it, PropertyDescriptor* desc,
157 : Maybe<ShouldThrow> should_throw);
158 : // ES6 9.1.6.2
159 : V8_WARN_UNUSED_RESULT static Maybe<bool> IsCompatiblePropertyDescriptor(
160 : Isolate* isolate, bool extensible, PropertyDescriptor* desc,
161 : PropertyDescriptor* current, Handle<Name> property_name,
162 : Maybe<ShouldThrow> should_throw);
163 : // ES6 9.1.6.3
164 : // |it| can be NULL in cases where the ES spec passes |undefined| as the
165 : // receiver. Exactly one of |it| and |property_name| must be provided.
166 : V8_WARN_UNUSED_RESULT static Maybe<bool> ValidateAndApplyPropertyDescriptor(
167 : Isolate* isolate, LookupIterator* it, bool extensible,
168 : PropertyDescriptor* desc, PropertyDescriptor* current,
169 : Maybe<ShouldThrow> should_throw, Handle<Name> property_name);
170 :
171 : V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static Maybe<bool>
172 : GetOwnPropertyDescriptor(Isolate* isolate, Handle<JSReceiver> object,
173 : Handle<Object> key, PropertyDescriptor* desc);
174 : V8_WARN_UNUSED_RESULT static Maybe<bool> GetOwnPropertyDescriptor(
175 : LookupIterator* it, PropertyDescriptor* desc);
176 :
177 : typedef PropertyAttributes IntegrityLevel;
178 :
179 : // ES6 7.3.14 (when passed kDontThrow)
180 : // 'level' must be SEALED or FROZEN.
181 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetIntegrityLevel(
182 : Handle<JSReceiver> object, IntegrityLevel lvl, ShouldThrow should_throw);
183 :
184 : // ES6 7.3.15
185 : // 'level' must be SEALED or FROZEN.
186 : V8_WARN_UNUSED_RESULT static Maybe<bool> TestIntegrityLevel(
187 : Handle<JSReceiver> object, IntegrityLevel lvl);
188 :
189 : // ES6 [[PreventExtensions]] (when passed kDontThrow)
190 : V8_WARN_UNUSED_RESULT static Maybe<bool> PreventExtensions(
191 : Handle<JSReceiver> object, ShouldThrow should_throw);
192 :
193 : V8_WARN_UNUSED_RESULT static Maybe<bool> IsExtensible(
194 : Handle<JSReceiver> object);
195 :
196 : // Returns the class name ([[Class]] property in the specification).
197 : V8_EXPORT_PRIVATE String class_name();
198 :
199 : // Returns the constructor (the function that was used to instantiate the
200 : // object).
201 : static MaybeHandle<JSFunction> GetConstructor(Handle<JSReceiver> receiver);
202 :
203 : // Returns the constructor name (the name (possibly, inferred name) of the
204 : // function that was used to instantiate the object).
205 : static Handle<String> GetConstructorName(Handle<JSReceiver> receiver);
206 :
207 : Handle<NativeContext> GetCreationContext();
208 :
209 : V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
210 : GetPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name);
211 : V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
212 : GetOwnPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name);
213 : V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
214 : GetOwnPropertyAttributes(Handle<JSReceiver> object, uint32_t index);
215 :
216 : V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
217 : GetElementAttributes(Handle<JSReceiver> object, uint32_t index);
218 : V8_WARN_UNUSED_RESULT static inline Maybe<PropertyAttributes>
219 : GetOwnElementAttributes(Handle<JSReceiver> object, uint32_t index);
220 :
221 : V8_WARN_UNUSED_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes(
222 : LookupIterator* it);
223 :
224 : // Set the object's prototype (only JSReceiver and null are allowed values).
225 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetPrototype(
226 : Handle<JSReceiver> object, Handle<Object> value, bool from_javascript,
227 : ShouldThrow should_throw);
228 :
229 : inline static Handle<Object> GetDataProperty(Handle<JSReceiver> object,
230 : Handle<Name> name);
231 : static Handle<Object> GetDataProperty(LookupIterator* it);
232 :
233 : // Retrieves a permanent object identity hash code. The undefined value might
234 : // be returned in case no hash was created yet.
235 : Object GetIdentityHash();
236 :
237 : // Retrieves a permanent object identity hash code. May create and store a
238 : // hash code if needed and none exists.
239 : static Smi CreateIdentityHash(Isolate* isolate, JSReceiver key);
240 : Smi GetOrCreateIdentityHash(Isolate* isolate);
241 :
242 : // Stores the hash code. The hash passed in must be masked with
243 : // JSReceiver::kHashMask.
244 : void SetIdentityHash(int masked_hash);
245 :
246 : // ES6 [[OwnPropertyKeys]] (modulo return type)
247 : V8_WARN_UNUSED_RESULT static inline MaybeHandle<FixedArray> OwnPropertyKeys(
248 : Handle<JSReceiver> object);
249 :
250 : V8_WARN_UNUSED_RESULT static MaybeHandle<FixedArray> GetOwnValues(
251 : Handle<JSReceiver> object, PropertyFilter filter,
252 : bool try_fast_path = true);
253 :
254 : V8_WARN_UNUSED_RESULT static MaybeHandle<FixedArray> GetOwnEntries(
255 : Handle<JSReceiver> object, PropertyFilter filter,
256 : bool try_fast_path = true);
257 :
258 : V8_WARN_UNUSED_RESULT static Handle<FixedArray> GetOwnElementIndices(
259 : Isolate* isolate, Handle<JSReceiver> receiver, Handle<JSObject> object);
260 :
261 : static const int kHashMask = PropertyArray::HashField::kMask;
262 :
263 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, JSRECEIVER_FIELDS)
264 : static const int kHeaderSize = kSize;
265 :
266 : bool HasProxyInPrototype(Isolate* isolate);
267 :
268 : bool HasComplexElements();
269 :
270 689267 : OBJECT_CONSTRUCTORS(JSReceiver, HeapObject);
271 : };
272 :
273 : // The JSObject describes real heap allocated JavaScript objects with
274 : // properties.
275 : // Note that the map of JSObject changes during execution to enable inline
276 : // caching.
277 : class JSObject : public JSReceiver {
278 : public:
279 : static bool IsUnmodifiedApiObject(FullObjectSlot o);
280 :
281 : static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> New(
282 : Handle<JSFunction> constructor, Handle<JSReceiver> new_target,
283 : Handle<AllocationSite> site);
284 :
285 : static MaybeHandle<NativeContext> GetFunctionRealm(Handle<JSObject> object);
286 :
287 : // 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
288 : // Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
289 : static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> ObjectCreate(
290 : Isolate* isolate, Handle<Object> prototype);
291 :
292 : // [elements]: The elements (properties with names that are integers).
293 : //
294 : // Elements can be in two general modes: fast and slow. Each mode
295 : // corresponds to a set of object representations of elements that
296 : // have something in common.
297 : //
298 : // In the fast mode elements is a FixedArray and so each element can
299 : // be quickly accessed. This fact is used in the generated code. The
300 : // elements array can have one of three maps in this mode:
301 : // fixed_array_map, sloppy_arguments_elements_map or
302 : // fixed_cow_array_map (for copy-on-write arrays). In the latter case
303 : // the elements array may be shared by a few objects and so before
304 : // writing to any element the array must be copied. Use
305 : // EnsureWritableFastElements in this case.
306 : //
307 : // In the slow mode the elements is either a NumberDictionary, a
308 : // FixedArray parameter map for a (sloppy) arguments object.
309 : DECL_ACCESSORS(elements, FixedArrayBase)
310 : inline void initialize_elements();
311 : static inline void SetMapAndElements(Handle<JSObject> object, Handle<Map> map,
312 : Handle<FixedArrayBase> elements);
313 : inline ElementsKind GetElementsKind() const;
314 : ElementsAccessor* GetElementsAccessor();
315 : // Returns true if an object has elements of PACKED_SMI_ELEMENTS or
316 : // HOLEY_SMI_ELEMENTS ElementsKind.
317 : inline bool HasSmiElements();
318 : // Returns true if an object has elements of PACKED_ELEMENTS or
319 : // HOLEY_ELEMENTS ElementsKind.
320 : inline bool HasObjectElements();
321 : // Returns true if an object has elements of PACKED_SMI_ELEMENTS,
322 : // HOLEY_SMI_ELEMENTS, PACKED_ELEMENTS, or HOLEY_ELEMENTS.
323 : inline bool HasSmiOrObjectElements();
324 : // Returns true if an object has any of the "fast" elements kinds.
325 : inline bool HasFastElements();
326 : // Returns true if an object has any of the PACKED elements kinds.
327 : inline bool HasFastPackedElements();
328 : // Returns true if an object has elements of PACKED_DOUBLE_ELEMENTS or
329 : // HOLEY_DOUBLE_ELEMENTS ElementsKind.
330 : inline bool HasDoubleElements();
331 : // Returns true if an object has elements of HOLEY_SMI_ELEMENTS,
332 : // HOLEY_DOUBLE_ELEMENTS, or HOLEY_ELEMENTS ElementsKind.
333 : inline bool HasHoleyElements();
334 : inline bool HasSloppyArgumentsElements();
335 : inline bool HasStringWrapperElements();
336 : inline bool HasDictionaryElements();
337 :
338 : inline bool HasFixedTypedArrayElements();
339 :
340 : inline bool HasFixedUint8ClampedElements();
341 : inline bool HasFixedArrayElements();
342 : inline bool HasFixedInt8Elements();
343 : inline bool HasFixedUint8Elements();
344 : inline bool HasFixedInt16Elements();
345 : inline bool HasFixedUint16Elements();
346 : inline bool HasFixedInt32Elements();
347 : inline bool HasFixedUint32Elements();
348 : inline bool HasFixedFloat32Elements();
349 : inline bool HasFixedFloat64Elements();
350 : inline bool HasFixedBigInt64Elements();
351 : inline bool HasFixedBigUint64Elements();
352 :
353 : inline bool HasFastArgumentsElements();
354 : inline bool HasSlowArgumentsElements();
355 : inline bool HasFastStringWrapperElements();
356 : inline bool HasSlowStringWrapperElements();
357 : bool HasEnumerableElements();
358 :
359 : inline NumberDictionary element_dictionary(); // Gets slow elements.
360 :
361 : // Requires: HasFastElements().
362 : static void EnsureWritableFastElements(Handle<JSObject> object);
363 :
364 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithInterceptor(
365 : LookupIterator* it, Maybe<ShouldThrow> should_throw,
366 : Handle<Object> value);
367 :
368 : // The API currently still wants DefineOwnPropertyIgnoreAttributes to convert
369 : // AccessorInfo objects to data fields. We allow FORCE_FIELD as an exception
370 : // to the default behavior that calls the setter.
371 : enum AccessorInfoHandling { FORCE_FIELD, DONT_FORCE_FIELD };
372 :
373 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
374 : DefineOwnPropertyIgnoreAttributes(
375 : LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
376 : AccessorInfoHandling handling = DONT_FORCE_FIELD);
377 :
378 : V8_WARN_UNUSED_RESULT static Maybe<bool> DefineOwnPropertyIgnoreAttributes(
379 : LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
380 : Maybe<ShouldThrow> should_throw,
381 : AccessorInfoHandling handling = DONT_FORCE_FIELD);
382 :
383 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
384 : SetOwnPropertyIgnoreAttributes(Handle<JSObject> object, Handle<Name> name,
385 : Handle<Object> value,
386 : PropertyAttributes attributes);
387 :
388 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
389 : SetOwnElementIgnoreAttributes(Handle<JSObject> object, uint32_t index,
390 : Handle<Object> value,
391 : PropertyAttributes attributes);
392 :
393 : // Equivalent to one of the above depending on whether |name| can be converted
394 : // to an array index.
395 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
396 : DefinePropertyOrElementIgnoreAttributes(Handle<JSObject> object,
397 : Handle<Name> name,
398 : Handle<Object> value,
399 : PropertyAttributes attributes = NONE);
400 :
401 : // Adds or reconfigures a property to attributes NONE. It will fail when it
402 : // cannot.
403 : V8_WARN_UNUSED_RESULT static Maybe<bool> CreateDataProperty(
404 : LookupIterator* it, Handle<Object> value,
405 : Maybe<ShouldThrow> should_throw = Just(kDontThrow));
406 :
407 : static void AddProperty(Isolate* isolate, Handle<JSObject> object,
408 : Handle<Name> name, Handle<Object> value,
409 : PropertyAttributes attributes);
410 :
411 : // {name} must be a UTF-8 encoded, null-terminated string.
412 : static void AddProperty(Isolate* isolate, Handle<JSObject> object,
413 : const char* name, Handle<Object> value,
414 : PropertyAttributes attributes);
415 :
416 : static void AddDataElement(Handle<JSObject> receiver, uint32_t index,
417 : Handle<Object> value,
418 : PropertyAttributes attributes);
419 :
420 : // Extend the receiver with a single fast property appeared first in the
421 : // passed map. This also extends the property backing store if necessary.
422 : static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
423 :
424 : // Migrates the given object to a map whose field representations are the
425 : // lowest upper bound of all known representations for that field.
426 : static void MigrateInstance(Handle<JSObject> instance);
427 :
428 : // Migrates the given object only if the target map is already available,
429 : // or returns false if such a map is not yet available.
430 : static bool TryMigrateInstance(Handle<JSObject> instance);
431 :
432 : // Sets the property value in a normalized object given (key, value, details).
433 : // Handles the special representation of JS global objects.
434 : static void SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
435 : Handle<Object> value,
436 : PropertyDetails details);
437 : static void SetDictionaryElement(Handle<JSObject> object, uint32_t index,
438 : Handle<Object> value,
439 : PropertyAttributes attributes);
440 : static void SetDictionaryArgumentsElement(Handle<JSObject> object,
441 : uint32_t index,
442 : Handle<Object> value,
443 : PropertyAttributes attributes);
444 :
445 : static void OptimizeAsPrototype(Handle<JSObject> object,
446 : bool enable_setup_mode = true);
447 : static void ReoptimizeIfPrototype(Handle<JSObject> object);
448 : static void MakePrototypesFast(Handle<Object> receiver,
449 : WhereToStart where_to_start, Isolate* isolate);
450 : static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate);
451 : static void UpdatePrototypeUserRegistration(Handle<Map> old_map,
452 : Handle<Map> new_map,
453 : Isolate* isolate);
454 : static bool UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate);
455 : static Map InvalidatePrototypeChains(Map map);
456 : static void InvalidatePrototypeValidityCell(JSGlobalObject global);
457 :
458 : // Updates prototype chain tracking information when an object changes its
459 : // map from |old_map| to |new_map|.
460 : static void NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
461 : Isolate* isolate);
462 :
463 : // Utility used by many Array builtins and runtime functions
464 : static inline bool PrototypeHasNoElements(Isolate* isolate, JSObject object);
465 :
466 : // To be passed to PrototypeUsers::Compact.
467 : static void PrototypeRegistryCompactionCallback(HeapObject value,
468 : int old_index, int new_index);
469 :
470 : // Retrieve interceptors.
471 : inline InterceptorInfo GetNamedInterceptor();
472 : inline InterceptorInfo GetIndexedInterceptor();
473 :
474 : // Used from JSReceiver.
475 : V8_WARN_UNUSED_RESULT static Maybe<PropertyAttributes>
476 : GetPropertyAttributesWithInterceptor(LookupIterator* it);
477 : V8_WARN_UNUSED_RESULT static Maybe<PropertyAttributes>
478 : GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it);
479 :
480 : // Defines an AccessorPair property on the given object.
481 : // TODO(mstarzinger): Rename to SetAccessor().
482 : static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object,
483 : Handle<Name> name,
484 : Handle<Object> getter,
485 : Handle<Object> setter,
486 : PropertyAttributes attributes);
487 : static MaybeHandle<Object> DefineAccessor(LookupIterator* it,
488 : Handle<Object> getter,
489 : Handle<Object> setter,
490 : PropertyAttributes attributes);
491 :
492 : // Defines an AccessorInfo property on the given object.
493 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> SetAccessor(
494 : Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> info,
495 : PropertyAttributes attributes);
496 :
497 : // The result must be checked first for exceptions. If there's no exception,
498 : // the output parameter |done| indicates whether the interceptor has a result
499 : // or not.
500 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor(
501 : LookupIterator* it, bool* done);
502 :
503 : static void ValidateElements(JSObject object);
504 :
505 : // Makes sure that this object can contain HeapObject as elements.
506 : static inline void EnsureCanContainHeapObjectElements(Handle<JSObject> obj);
507 :
508 : // Makes sure that this object can contain the specified elements.
509 : // TSlot here is either ObjectSlot or FullObjectSlot.
510 : template <typename TSlot>
511 : static inline void EnsureCanContainElements(Handle<JSObject> object,
512 : TSlot elements, uint32_t count,
513 : EnsureElementsMode mode);
514 : static inline void EnsureCanContainElements(Handle<JSObject> object,
515 : Handle<FixedArrayBase> elements,
516 : uint32_t length,
517 : EnsureElementsMode mode);
518 : static void EnsureCanContainElements(Handle<JSObject> object,
519 : Arguments* arguments, uint32_t first_arg,
520 : uint32_t arg_count,
521 : EnsureElementsMode mode);
522 :
523 : // Would we convert a fast elements array to dictionary mode given
524 : // an access at key?
525 : bool WouldConvertToSlowElements(uint32_t index);
526 :
527 : static const uint32_t kMinAddedElementsCapacity = 16;
528 :
529 : // Computes the new capacity when expanding the elements of a JSObject.
530 : static uint32_t NewElementsCapacity(uint32_t old_capacity) {
531 : // (old_capacity + 50%) + kMinAddedElementsCapacity
532 1433629 : return old_capacity + (old_capacity >> 1) + kMinAddedElementsCapacity;
533 : }
534 :
535 : // These methods do not perform access checks!
536 : template <AllocationSiteUpdateMode update_or_check =
537 : AllocationSiteUpdateMode::kUpdate>
538 : static bool UpdateAllocationSite(Handle<JSObject> object,
539 : ElementsKind to_kind);
540 :
541 : // Lookup interceptors are used for handling properties controlled by host
542 : // objects.
543 : inline bool HasNamedInterceptor();
544 : inline bool HasIndexedInterceptor();
545 :
546 : // Support functions for v8 api (needed for correct interceptor behavior).
547 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasRealNamedProperty(
548 : Handle<JSObject> object, Handle<Name> name);
549 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasRealElementProperty(
550 : Handle<JSObject> object, uint32_t index);
551 : V8_WARN_UNUSED_RESULT static Maybe<bool> HasRealNamedCallbackProperty(
552 : Handle<JSObject> object, Handle<Name> name);
553 :
554 : // Get the header size for a JSObject. Used to compute the index of
555 : // embedder fields as well as the number of embedder fields.
556 : // The |function_has_prototype_slot| parameter is needed only for
557 : // JSFunction objects.
558 : static int GetHeaderSize(InstanceType instance_type,
559 : bool function_has_prototype_slot = false);
560 : static inline int GetHeaderSize(const Map map);
561 : inline int GetHeaderSize() const;
562 :
563 : static inline int GetEmbedderFieldsStartOffset(const Map map);
564 : inline int GetEmbedderFieldsStartOffset();
565 :
566 : static inline int GetEmbedderFieldCount(const Map map);
567 : inline int GetEmbedderFieldCount() const;
568 : inline int GetEmbedderFieldOffset(int index);
569 : inline Object GetEmbedderField(int index);
570 : inline void SetEmbedderField(int index, Object value);
571 : inline void SetEmbedderField(int index, Smi value);
572 :
573 : // Returns true when the object is potentially a wrapper that gets special
574 : // garbage collection treatment.
575 : // TODO(mlippautz): Make check exact and replace the pattern match in
576 : // Heap::TracePossibleWrapper.
577 : bool IsApiWrapper();
578 :
579 : // Same as IsApiWrapper() but also allow dropping the wrapper on minor GCs.
580 : bool IsDroppableApiWrapper();
581 :
582 : // Returns a new map with all transitions dropped from the object's current
583 : // map and the ElementsKind set.
584 : static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
585 : ElementsKind to_kind);
586 : static void TransitionElementsKind(Handle<JSObject> object,
587 : ElementsKind to_kind);
588 :
589 : // Always use this to migrate an object to a new map.
590 : // |expected_additional_properties| is only used for fast-to-slow transitions
591 : // and ignored otherwise.
592 : static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
593 : int expected_additional_properties = 0);
594 :
595 : // Forces a prototype without any of the checks that the regular SetPrototype
596 : // would do.
597 : static void ForceSetPrototype(Handle<JSObject> object, Handle<Object> proto);
598 :
599 : // Convert the object to use the canonical dictionary
600 : // representation. If the object is expected to have additional properties
601 : // added this number can be indicated to have the backing store allocated to
602 : // an initial capacity for holding these properties.
603 : static void NormalizeProperties(Handle<JSObject> object,
604 : PropertyNormalizationMode mode,
605 : int expected_additional_properties,
606 : const char* reason);
607 :
608 : // Convert and update the elements backing store to be a
609 : // NumberDictionary dictionary. Returns the backing after conversion.
610 : static Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object);
611 :
612 : void RequireSlowElements(NumberDictionary dictionary);
613 :
614 : // Transform slow named properties to fast variants.
615 : static void MigrateSlowToFast(Handle<JSObject> object,
616 : int unused_property_fields, const char* reason);
617 :
618 : inline bool IsUnboxedDoubleField(FieldIndex index);
619 :
620 : // Access fast-case object properties at index.
621 : static Handle<Object> FastPropertyAt(Handle<JSObject> object,
622 : Representation representation,
623 : FieldIndex index);
624 : inline Object RawFastPropertyAt(FieldIndex index);
625 : inline double RawFastDoublePropertyAt(FieldIndex index);
626 : inline uint64_t RawFastDoublePropertyAsBitsAt(FieldIndex index);
627 :
628 : inline void FastPropertyAtPut(FieldIndex index, Object value);
629 : inline void RawFastPropertyAtPut(FieldIndex index, Object value);
630 : inline void RawFastDoublePropertyAsBitsAtPut(FieldIndex index, uint64_t bits);
631 : inline void WriteToField(int descriptor, PropertyDetails details,
632 : Object value);
633 :
634 : // Access to in object properties.
635 : inline int GetInObjectPropertyOffset(int index);
636 : inline Object InObjectPropertyAt(int index);
637 : inline Object InObjectPropertyAtPut(
638 : int index, Object value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
639 :
640 : // Set the object's prototype (only JSReceiver and null are allowed values).
641 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetPrototype(
642 : Handle<JSObject> object, Handle<Object> value, bool from_javascript,
643 : ShouldThrow should_throw);
644 :
645 : // Makes the object prototype immutable
646 : // Never called from JavaScript
647 : static void SetImmutableProto(Handle<JSObject> object);
648 :
649 : // Initializes the body starting at |start_offset|. It is responsibility of
650 : // the caller to initialize object header. Fill the pre-allocated fields with
651 : // pre_allocated_value and the rest with filler_value.
652 : // Note: this call does not update write barrier, the caller is responsible
653 : // to ensure that |filler_value| can be collected without WB here.
654 : inline void InitializeBody(Map map, int start_offset,
655 : Object pre_allocated_value, Object filler_value);
656 :
657 : // Check whether this object references another object
658 : bool ReferencesObject(Object obj);
659 :
660 : V8_WARN_UNUSED_RESULT static Maybe<bool> TestIntegrityLevel(
661 : Handle<JSObject> object, IntegrityLevel lvl);
662 :
663 : V8_WARN_UNUSED_RESULT static Maybe<bool> PreventExtensions(
664 : Handle<JSObject> object, ShouldThrow should_throw);
665 :
666 : static bool IsExtensible(Handle<JSObject> object);
667 :
668 : DECL_CAST(JSObject)
669 :
670 : // Dispatched behavior.
671 : void JSObjectShortPrint(StringStream* accumulator);
672 : DECL_PRINTER(JSObject)
673 : DECL_VERIFIER(JSObject)
674 : #ifdef OBJECT_PRINT
675 : bool PrintProperties(std::ostream& os); // NOLINT
676 : void PrintElements(std::ostream& os); // NOLINT
677 : #endif
678 : #if defined(DEBUG) || defined(OBJECT_PRINT)
679 : void PrintTransitions(std::ostream& os); // NOLINT
680 : #endif
681 :
682 : static void PrintElementsTransition(FILE* file, Handle<JSObject> object,
683 : ElementsKind from_kind,
684 : Handle<FixedArrayBase> from_elements,
685 : ElementsKind to_kind,
686 : Handle<FixedArrayBase> to_elements);
687 :
688 : void PrintInstanceMigration(FILE* file, Map original_map, Map new_map);
689 :
690 : #ifdef DEBUG
691 : // Structure for collecting spill information about JSObjects.
692 : class SpillInformation {
693 : public:
694 : void Clear();
695 : void Print();
696 : int number_of_objects_;
697 : int number_of_objects_with_fast_properties_;
698 : int number_of_objects_with_fast_elements_;
699 : int number_of_fast_used_fields_;
700 : int number_of_fast_unused_fields_;
701 : int number_of_slow_used_properties_;
702 : int number_of_slow_unused_properties_;
703 : int number_of_fast_used_elements_;
704 : int number_of_fast_unused_elements_;
705 : int number_of_slow_used_elements_;
706 : int number_of_slow_unused_elements_;
707 : };
708 :
709 : void IncrementSpillStatistics(Isolate* isolate, SpillInformation* info);
710 : #endif
711 :
712 : #ifdef VERIFY_HEAP
713 : // If a GC was caused while constructing this object, the elements pointer
714 : // may point to a one pointer filler map. The object won't be rooted, but
715 : // our heap verification code could stumble across it.
716 : bool ElementsAreSafeToExamine() const;
717 : #endif
718 :
719 : Object SlowReverseLookup(Object value);
720 :
721 : // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
722 : // Also maximal value of JSArray's length property.
723 : static const uint32_t kMaxElementCount = 0xffffffffu;
724 :
725 : // Constants for heuristics controlling conversion of fast elements
726 : // to slow elements.
727 :
728 : // Maximal gap that can be introduced by adding an element beyond
729 : // the current elements length.
730 : static const uint32_t kMaxGap = 1024;
731 :
732 : // Maximal length of fast elements array that won't be checked for
733 : // being dense enough on expansion.
734 : static const int kMaxUncheckedFastElementsLength = 5000;
735 :
736 : // Same as above but for old arrays. This limit is more strict. We
737 : // don't want to be wasteful with long lived objects.
738 : static const int kMaxUncheckedOldFastElementsLength = 500;
739 :
740 : // This constant applies only to the initial map of "global.Object" and
741 : // not to arbitrary other JSObject maps.
742 : static const int kInitialGlobalObjectUnusedPropertiesCount = 4;
743 :
744 : static const int kMaxInstanceSize = 255 * kTaggedSize;
745 :
746 : // When extending the backing storage for property values, we increase
747 : // its size by more than the 1 entry necessary, so sequentially adding fields
748 : // to the same object requires fewer allocations and copies.
749 : static const int kFieldsAdded = 3;
750 : STATIC_ASSERT(kMaxNumberOfDescriptors + kFieldsAdded <=
751 : PropertyArray::kMaxLength);
752 :
753 : // Layout description.
754 : #define JS_OBJECT_FIELDS(V) \
755 : V(kElementsOffset, kTaggedSize) \
756 : /* Header size. */ \
757 : V(kHeaderSize, 0) \
758 : V(kOptionalEmbedderFieldPadding, \
759 : POINTER_SIZE_PADDING(kOptionalEmbedderFieldPadding)) \
760 : /* Header size aligned to kSystemPointerSize. */ \
761 : V(kHeaderSizeForEmbedderFields, 0)
762 :
763 : DEFINE_FIELD_OFFSET_CONSTANTS(JSReceiver::kHeaderSize, JS_OBJECT_FIELDS)
764 : #undef JS_OBJECT_FIELDS
765 :
766 : STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize);
767 : static const int kMaxInObjectProperties =
768 : (kMaxInstanceSize - kHeaderSize) >> kTaggedSizeLog2;
769 : STATIC_ASSERT(kMaxInObjectProperties <= kMaxNumberOfDescriptors);
770 :
771 : STATIC_ASSERT(kHeaderSizeForEmbedderFields ==
772 : Internals::kJSObjectHeaderSizeForEmbedderFields);
773 : static const int kMaxFirstInobjectPropertyOffset =
774 : (1 << kFirstInobjectPropertyOffsetBitCount) - 1;
775 : static const int kMaxEmbedderFields =
776 : (kMaxFirstInobjectPropertyOffset - kHeaderSizeForEmbedderFields) /
777 : kEmbedderDataSlotSize;
778 : STATIC_ASSERT(kHeaderSizeForEmbedderFields +
779 : kMaxEmbedderFields * kEmbedderDataSlotSizeInTaggedSlots <=
780 : kMaxInstanceSize);
781 :
782 : class BodyDescriptor;
783 :
784 : class FastBodyDescriptor;
785 :
786 : // Gets the number of currently used elements.
787 : int GetFastElementsUsage();
788 :
789 : static bool AllCanRead(LookupIterator* it);
790 : static bool AllCanWrite(LookupIterator* it);
791 :
792 : private:
793 : friend class JSReceiver;
794 : friend class Object;
795 :
796 : // Used from Object::GetProperty().
797 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object>
798 : GetPropertyWithFailedAccessCheck(LookupIterator* it);
799 :
800 : V8_WARN_UNUSED_RESULT static Maybe<bool> SetPropertyWithFailedAccessCheck(
801 : LookupIterator* it, Handle<Object> value,
802 : Maybe<ShouldThrow> should_throw);
803 :
804 : V8_WARN_UNUSED_RESULT static Maybe<bool> DeletePropertyWithInterceptor(
805 : LookupIterator* it, ShouldThrow should_throw);
806 :
807 : bool ReferencesObjectFromElements(FixedArray elements, ElementsKind kind,
808 : Object object);
809 :
810 : // Helper for fast versions of preventExtensions, seal, and freeze.
811 : // attrs is one of NONE, SEALED, or FROZEN (depending on the operation).
812 : template <PropertyAttributes attrs>
813 : V8_WARN_UNUSED_RESULT static Maybe<bool> PreventExtensionsWithTransition(
814 : Handle<JSObject> object, ShouldThrow should_throw);
815 :
816 40270791 : OBJECT_CONSTRUCTORS(JSObject, JSReceiver);
817 : };
818 :
819 : // JSAccessorPropertyDescriptor is just a JSObject with a specific initial
820 : // map. This initial map adds in-object properties for "get", "set",
821 : // "enumerable" and "configurable" properties, as assigned by the
822 : // FromPropertyDescriptor function for regular accessor properties.
823 : class JSAccessorPropertyDescriptor : public JSObject {
824 : public:
825 : // Layout description.
826 : #define JS_ACCESSOR_PROPERTY_DESCRIPTOR_FIELDS(V) \
827 : V(kGetOffset, kTaggedSize) \
828 : V(kSetOffset, kTaggedSize) \
829 : V(kEnumerableOffset, kTaggedSize) \
830 : V(kConfigurableOffset, kTaggedSize) \
831 : /* Total size. */ \
832 : V(kSize, 0)
833 :
834 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
835 : JS_ACCESSOR_PROPERTY_DESCRIPTOR_FIELDS)
836 : #undef JS_ACCESSOR_PROPERTY_DESCRIPTOR_FIELDS
837 :
838 : // Indices of in-object properties.
839 : static const int kGetIndex = 0;
840 : static const int kSetIndex = 1;
841 : static const int kEnumerableIndex = 2;
842 : static const int kConfigurableIndex = 3;
843 :
844 : private:
845 : DISALLOW_IMPLICIT_CONSTRUCTORS(JSAccessorPropertyDescriptor);
846 : };
847 :
848 : // JSDataPropertyDescriptor is just a JSObject with a specific initial map.
849 : // This initial map adds in-object properties for "value", "writable",
850 : // "enumerable" and "configurable" properties, as assigned by the
851 : // FromPropertyDescriptor function for regular data properties.
852 : class JSDataPropertyDescriptor : public JSObject {
853 : public:
854 : // Layout description.
855 : #define JS_DATA_PROPERTY_DESCRIPTOR_FIELDS(V) \
856 : V(kValueOffset, kTaggedSize) \
857 : V(kWritableOffset, kTaggedSize) \
858 : V(kEnumerableOffset, kTaggedSize) \
859 : V(kConfigurableOffset, kTaggedSize) \
860 : /* Total size. */ \
861 : V(kSize, 0)
862 :
863 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
864 : JS_DATA_PROPERTY_DESCRIPTOR_FIELDS)
865 : #undef JS_DATA_PROPERTY_DESCRIPTOR_FIELDS
866 :
867 : // Indices of in-object properties.
868 : static const int kValueIndex = 0;
869 : static const int kWritableIndex = 1;
870 : static const int kEnumerableIndex = 2;
871 : static const int kConfigurableIndex = 3;
872 :
873 : private:
874 : DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataPropertyDescriptor);
875 : };
876 :
877 : // JSIteratorResult is just a JSObject with a specific initial map.
878 : // This initial map adds in-object properties for "done" and "value",
879 : // as specified by ES6 section 25.1.1.3 The IteratorResult Interface
880 : class JSIteratorResult : public JSObject {
881 : public:
882 : DECL_ACCESSORS(value, Object)
883 :
884 : DECL_ACCESSORS(done, Object)
885 :
886 : // Layout description.
887 : #define JS_ITERATOR_RESULT_FIELDS(V) \
888 : V(kValueOffset, kTaggedSize) \
889 : V(kDoneOffset, kTaggedSize) \
890 : /* Total size. */ \
891 : V(kSize, 0)
892 :
893 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
894 : JS_ITERATOR_RESULT_FIELDS)
895 : #undef JS_ITERATOR_RESULT_FIELDS
896 :
897 : // Indices of in-object properties.
898 : static const int kValueIndex = 0;
899 : static const int kDoneIndex = 1;
900 :
901 : DECL_CAST(JSIteratorResult)
902 :
903 : OBJECT_CONSTRUCTORS(JSIteratorResult, JSObject);
904 : };
905 :
906 : // JSBoundFunction describes a bound function exotic object.
907 : class JSBoundFunction : public JSObject {
908 : public:
909 : // [bound_target_function]: The wrapped function object.
910 : inline Object raw_bound_target_function() const;
911 : DECL_ACCESSORS(bound_target_function, JSReceiver)
912 :
913 : // [bound_this]: The value that is always passed as the this value when
914 : // calling the wrapped function.
915 : DECL_ACCESSORS(bound_this, Object)
916 :
917 : // [bound_arguments]: A list of values whose elements are used as the first
918 : // arguments to any call to the wrapped function.
919 : DECL_ACCESSORS(bound_arguments, FixedArray)
920 :
921 : static MaybeHandle<String> GetName(Isolate* isolate,
922 : Handle<JSBoundFunction> function);
923 : static Maybe<int> GetLength(Isolate* isolate,
924 : Handle<JSBoundFunction> function);
925 : static MaybeHandle<NativeContext> GetFunctionRealm(
926 : Handle<JSBoundFunction> function);
927 :
928 : DECL_CAST(JSBoundFunction)
929 :
930 : // Dispatched behavior.
931 : DECL_PRINTER(JSBoundFunction)
932 : DECL_VERIFIER(JSBoundFunction)
933 :
934 : // The bound function's string representation implemented according
935 : // to ES6 section 19.2.3.5 Function.prototype.toString ( ).
936 : static Handle<String> ToString(Handle<JSBoundFunction> function);
937 :
938 : // Layout description.
939 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JSBOUND_FUNCTION_FIELDS)
940 :
941 : OBJECT_CONSTRUCTORS(JSBoundFunction, JSObject);
942 : };
943 :
944 : // JSFunction describes JavaScript functions.
945 : class JSFunction : public JSObject {
946 : public:
947 : // [prototype_or_initial_map]:
948 : DECL_ACCESSORS(prototype_or_initial_map, Object)
949 :
950 : // [shared]: The information about the function that
951 : // can be shared by instances.
952 : DECL_ACCESSORS(shared, SharedFunctionInfo)
953 :
954 : static const int kLengthDescriptorIndex = 0;
955 : static const int kNameDescriptorIndex = 1;
956 : // Home object descriptor index when function has a [[HomeObject]] slot.
957 : static const int kMaybeHomeObjectDescriptorIndex = 2;
958 :
959 : // [context]: The context for this function.
960 : inline Context context();
961 : inline bool has_context() const;
962 : inline void set_context(Object context);
963 : inline JSGlobalProxy global_proxy();
964 : inline NativeContext native_context();
965 :
966 : static Handle<Object> GetName(Isolate* isolate, Handle<JSFunction> function);
967 : static Maybe<int> GetLength(Isolate* isolate, Handle<JSFunction> function);
968 : static Handle<NativeContext> GetFunctionRealm(Handle<JSFunction> function);
969 :
970 : // [code]: The generated code object for this function. Executed
971 : // when the function is invoked, e.g. foo() or new foo(). See
972 : // [[Call]] and [[Construct]] description in ECMA-262, section
973 : // 8.6.2, page 27.
974 : inline Code code() const;
975 : inline void set_code(Code code);
976 : inline void set_code_no_write_barrier(Code code);
977 :
978 : // Get the abstract code associated with the function, which will either be
979 : // a Code object or a BytecodeArray.
980 : inline AbstractCode abstract_code();
981 :
982 : // Tells whether or not this function is interpreted.
983 : //
984 : // Note: function->IsInterpreted() does not necessarily return the same value
985 : // as function->shared()->IsInterpreted() because the closure might have been
986 : // optimized.
987 : inline bool IsInterpreted();
988 :
989 : // Tells whether or not this function checks its optimization marker in its
990 : // feedback vector.
991 : inline bool ChecksOptimizationMarker();
992 :
993 : // Tells whether or not this function holds optimized code.
994 : //
995 : // Note: Returning false does not necessarily mean that this function hasn't
996 : // been optimized, as it may have optimized code on its feedback vector.
997 : inline bool IsOptimized();
998 :
999 : // Tells whether or not this function has optimized code available to it,
1000 : // either because it is optimized or because it has optimized code in its
1001 : // feedback vector.
1002 : inline bool HasOptimizedCode();
1003 :
1004 : // Tells whether or not this function has a (non-zero) optimization marker.
1005 : inline bool HasOptimizationMarker();
1006 :
1007 : // Mark this function for lazy recompilation. The function will be recompiled
1008 : // the next time it is executed.
1009 : void MarkForOptimization(ConcurrencyMode mode);
1010 :
1011 : // Tells whether or not the function is already marked for lazy recompilation.
1012 : inline bool IsMarkedForOptimization();
1013 : inline bool IsMarkedForConcurrentOptimization();
1014 :
1015 : // Tells whether or not the function is on the concurrent recompilation queue.
1016 : inline bool IsInOptimizationQueue();
1017 :
1018 : // Clears the optimized code slot in the function's feedback vector.
1019 : inline void ClearOptimizedCodeSlot(const char* reason);
1020 :
1021 : // Sets the optimization marker in the function's feedback vector.
1022 : inline void SetOptimizationMarker(OptimizationMarker marker);
1023 :
1024 : // Clears the optimization marker in the function's feedback vector.
1025 : inline void ClearOptimizationMarker();
1026 :
1027 : // If slack tracking is active, it computes instance size of the initial map
1028 : // with minimum permissible object slack. If it is not active, it simply
1029 : // returns the initial map's instance size.
1030 : int ComputeInstanceSizeWithMinSlack(Isolate* isolate);
1031 :
1032 : // Completes inobject slack tracking on initial map if it is active.
1033 : inline void CompleteInobjectSlackTrackingIfActive();
1034 :
1035 : // [raw_feedback_cell]: Gives raw access to the FeedbackCell used to hold the
1036 : /// FeedbackVector eventually. Generally this shouldn't be used to get the
1037 : // feedback_vector, instead use feedback_vector() which correctly deals with
1038 : // the JSFunction's bytecode being flushed.
1039 : DECL_ACCESSORS(raw_feedback_cell, FeedbackCell)
1040 :
1041 : // feedback_vector() can be used once the function is compiled.
1042 : inline FeedbackVector feedback_vector() const;
1043 : inline bool has_feedback_vector() const;
1044 : static void EnsureFeedbackVector(Handle<JSFunction> function);
1045 :
1046 : // Unconditionally clear the type feedback vector.
1047 : void ClearTypeFeedbackInfo();
1048 :
1049 : // Resets function to clear compiled data after bytecode has been flushed.
1050 : inline bool NeedsResetDueToFlushedBytecode();
1051 : inline void ResetIfBytecodeFlushed();
1052 :
1053 : inline bool has_prototype_slot() const;
1054 :
1055 : // The initial map for an object created by this constructor.
1056 : inline Map initial_map();
1057 : static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
1058 : Handle<Object> prototype);
1059 : inline bool has_initial_map();
1060 : static void EnsureHasInitialMap(Handle<JSFunction> function);
1061 :
1062 : // Creates a map that matches the constructor's initial map, but with
1063 : // [[prototype]] being new.target.prototype. Because new.target can be a
1064 : // JSProxy, this can call back into JavaScript.
1065 : static V8_WARN_UNUSED_RESULT MaybeHandle<Map> GetDerivedMap(
1066 : Isolate* isolate, Handle<JSFunction> constructor,
1067 : Handle<JSReceiver> new_target);
1068 :
1069 : // Get and set the prototype property on a JSFunction. If the
1070 : // function has an initial map the prototype is set on the initial
1071 : // map. Otherwise, the prototype is put in the initial map field
1072 : // until an initial map is needed.
1073 : inline bool has_prototype();
1074 : inline bool has_instance_prototype();
1075 : inline Object prototype();
1076 : inline Object instance_prototype();
1077 : inline bool has_prototype_property();
1078 : inline bool PrototypeRequiresRuntimeLookup();
1079 : static void SetPrototype(Handle<JSFunction> function, Handle<Object> value);
1080 :
1081 : // Returns if this function has been compiled to native code yet.
1082 : inline bool is_compiled() const;
1083 :
1084 : static int GetHeaderSize(bool function_has_prototype_slot) {
1085 : return function_has_prototype_slot ? JSFunction::kSizeWithPrototype
1086 471729 : : JSFunction::kSizeWithoutPrototype;
1087 : }
1088 :
1089 : // Prints the name of the function using PrintF.
1090 : void PrintName(FILE* out = stdout);
1091 :
1092 : DECL_CAST(JSFunction)
1093 :
1094 : // Calculate the instance size and in-object properties count.
1095 : static V8_WARN_UNUSED_RESULT int CalculateExpectedNofProperties(
1096 : Isolate* isolate, Handle<JSFunction> function);
1097 : static void CalculateInstanceSizeHelper(InstanceType instance_type,
1098 : bool has_prototype_slot,
1099 : int requested_embedder_fields,
1100 : int requested_in_object_properties,
1101 : int* instance_size,
1102 : int* in_object_properties);
1103 :
1104 : // Dispatched behavior.
1105 : DECL_PRINTER(JSFunction)
1106 : DECL_VERIFIER(JSFunction)
1107 :
1108 : // The function's name if it is configured, otherwise shared function info
1109 : // debug name.
1110 : static Handle<String> GetName(Handle<JSFunction> function);
1111 :
1112 : // ES6 section 9.2.11 SetFunctionName
1113 : // Because of the way this abstract operation is used in the spec,
1114 : // it should never fail, but in practice it will fail if the generated
1115 : // function name's length exceeds String::kMaxLength.
1116 : static V8_WARN_UNUSED_RESULT bool SetName(Handle<JSFunction> function,
1117 : Handle<Name> name,
1118 : Handle<String> prefix);
1119 :
1120 : // The function's displayName if it is set, otherwise name if it is
1121 : // configured, otherwise shared function info
1122 : // debug name.
1123 : static Handle<String> GetDebugName(Handle<JSFunction> function);
1124 :
1125 : // The function's string representation implemented according to
1126 : // ES6 section 19.2.3.5 Function.prototype.toString ( ).
1127 : static Handle<String> ToString(Handle<JSFunction> function);
1128 :
1129 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JSFUNCTION_FIELDS)
1130 :
1131 : static constexpr int kSizeWithoutPrototype = kPrototypeOrInitialMapOffset;
1132 : static constexpr int kSizeWithPrototype = kSize;
1133 :
1134 28012335 : OBJECT_CONSTRUCTORS(JSFunction, JSObject);
1135 : };
1136 :
1137 : // JSGlobalProxy's prototype must be a JSGlobalObject or null,
1138 : // and the prototype is hidden. JSGlobalProxy always delegates
1139 : // property accesses to its prototype if the prototype is not null.
1140 : //
1141 : // A JSGlobalProxy can be reinitialized which will preserve its identity.
1142 : //
1143 : // Accessing a JSGlobalProxy requires security check.
1144 :
1145 : class JSGlobalProxy : public JSObject {
1146 : public:
1147 : // [native_context]: the owner native context of this global proxy object.
1148 : // It is null value if this object is not used by any context.
1149 : DECL_ACCESSORS(native_context, Object)
1150 :
1151 : DECL_CAST(JSGlobalProxy)
1152 :
1153 : inline bool IsDetachedFrom(JSGlobalObject global) const;
1154 :
1155 : static int SizeWithEmbedderFields(int embedder_field_count);
1156 :
1157 : // Dispatched behavior.
1158 : DECL_PRINTER(JSGlobalProxy)
1159 : DECL_VERIFIER(JSGlobalProxy)
1160 :
1161 : // Layout description.
1162 : #define JS_GLOBAL_PROXY_FIELDS(V) \
1163 : V(kNativeContextOffset, kTaggedSize) \
1164 : /* Header size. */ \
1165 : V(kSize, 0)
1166 :
1167 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_GLOBAL_PROXY_FIELDS)
1168 : #undef JS_GLOBAL_PROXY_FIELDS
1169 :
1170 56879 : OBJECT_CONSTRUCTORS(JSGlobalProxy, JSObject);
1171 : };
1172 :
1173 : // JavaScript global object.
1174 : class JSGlobalObject : public JSObject {
1175 : public:
1176 : // [native context]: the natives corresponding to this global object.
1177 : DECL_ACCESSORS(native_context, NativeContext)
1178 :
1179 : // [global proxy]: the global proxy object of the context
1180 : DECL_ACCESSORS(global_proxy, JSObject)
1181 :
1182 : // Gets global object properties.
1183 : inline GlobalDictionary global_dictionary();
1184 : inline void set_global_dictionary(GlobalDictionary dictionary);
1185 :
1186 : static void InvalidatePropertyCell(Handle<JSGlobalObject> object,
1187 : Handle<Name> name);
1188 : // Ensure that the global object has a cell for the given property name.
1189 : static Handle<PropertyCell> EnsureEmptyPropertyCell(
1190 : Handle<JSGlobalObject> global, Handle<Name> name,
1191 : PropertyCellType cell_type, int* entry_out = nullptr);
1192 :
1193 : DECL_CAST(JSGlobalObject)
1194 :
1195 : inline bool IsDetached();
1196 :
1197 : // Dispatched behavior.
1198 : DECL_PRINTER(JSGlobalObject)
1199 : DECL_VERIFIER(JSGlobalObject)
1200 :
1201 : // Layout description.
1202 : #define JS_GLOBAL_OBJECT_FIELDS(V) \
1203 : V(kNativeContextOffset, kTaggedSize) \
1204 : V(kGlobalProxyOffset, kTaggedSize) \
1205 : /* Header size. */ \
1206 : V(kHeaderSize, 0) \
1207 : V(kSize, 0)
1208 :
1209 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_GLOBAL_OBJECT_FIELDS)
1210 : #undef JS_GLOBAL_OBJECT_FIELDS
1211 :
1212 0 : OBJECT_CONSTRUCTORS(JSGlobalObject, JSObject);
1213 : };
1214 :
1215 : // Representation for JS Wrapper objects, String, Number, Boolean, etc.
1216 : class JSValue : public JSObject {
1217 : public:
1218 : // [value]: the object being wrapped.
1219 : DECL_ACCESSORS(value, Object)
1220 :
1221 : DECL_CAST(JSValue)
1222 :
1223 : // Dispatched behavior.
1224 : DECL_PRINTER(JSValue)
1225 : DECL_VERIFIER(JSValue)
1226 :
1227 : // Layout description.
1228 : #define JS_VALUE_FIELDS(V) \
1229 : V(kValueOffset, kTaggedSize) \
1230 : /* Header size. */ \
1231 : V(kSize, 0)
1232 :
1233 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_VALUE_FIELDS)
1234 : #undef JS_VALUE_FIELDS
1235 :
1236 6070 : OBJECT_CONSTRUCTORS(JSValue, JSObject);
1237 : };
1238 :
1239 : class DateCache;
1240 :
1241 : // Representation for JS date objects.
1242 : class JSDate : public JSObject {
1243 : public:
1244 : static V8_WARN_UNUSED_RESULT MaybeHandle<JSDate> New(
1245 : Handle<JSFunction> constructor, Handle<JSReceiver> new_target, double tv);
1246 :
1247 : // If one component is NaN, all of them are, indicating a NaN time value.
1248 : // [value]: the time value.
1249 : DECL_ACCESSORS(value, Object)
1250 : // [year]: caches year. Either undefined, smi, or NaN.
1251 : DECL_ACCESSORS(year, Object)
1252 : // [month]: caches month. Either undefined, smi, or NaN.
1253 : DECL_ACCESSORS(month, Object)
1254 : // [day]: caches day. Either undefined, smi, or NaN.
1255 : DECL_ACCESSORS(day, Object)
1256 : // [weekday]: caches day of week. Either undefined, smi, or NaN.
1257 : DECL_ACCESSORS(weekday, Object)
1258 : // [hour]: caches hours. Either undefined, smi, or NaN.
1259 : DECL_ACCESSORS(hour, Object)
1260 : // [min]: caches minutes. Either undefined, smi, or NaN.
1261 : DECL_ACCESSORS(min, Object)
1262 : // [sec]: caches seconds. Either undefined, smi, or NaN.
1263 : DECL_ACCESSORS(sec, Object)
1264 : // [cache stamp]: sample of the date cache stamp at the
1265 : // moment when chached fields were cached.
1266 : DECL_ACCESSORS(cache_stamp, Object)
1267 :
1268 : DECL_CAST(JSDate)
1269 :
1270 : // Returns the time value (UTC) identifying the current time.
1271 : static double CurrentTimeValue(Isolate* isolate);
1272 :
1273 : // Returns the date field with the specified index.
1274 : // See FieldIndex for the list of date fields.
1275 : // Arguments and result are raw Address values because this is called
1276 : // via ExternalReference.
1277 : // {raw_date} is a tagged Object pointer.
1278 : // {smi_index} is a tagged Smi.
1279 : // The return value is a tagged Object pointer.
1280 : static Address GetField(Address raw_date, Address smi_index);
1281 :
1282 : static Handle<Object> SetValue(Handle<JSDate> date, double v);
1283 :
1284 : void SetValue(Object value, bool is_value_nan);
1285 :
1286 : // Dispatched behavior.
1287 : DECL_PRINTER(JSDate)
1288 : DECL_VERIFIER(JSDate)
1289 :
1290 : // The order is important. It must be kept in sync with date macros
1291 : // in macros.py.
1292 : enum FieldIndex {
1293 : kDateValue,
1294 : kYear,
1295 : kMonth,
1296 : kDay,
1297 : kWeekday,
1298 : kHour,
1299 : kMinute,
1300 : kSecond,
1301 : kFirstUncachedField,
1302 : kMillisecond = kFirstUncachedField,
1303 : kDays,
1304 : kTimeInDay,
1305 : kFirstUTCField,
1306 : kYearUTC = kFirstUTCField,
1307 : kMonthUTC,
1308 : kDayUTC,
1309 : kWeekdayUTC,
1310 : kHourUTC,
1311 : kMinuteUTC,
1312 : kSecondUTC,
1313 : kMillisecondUTC,
1314 : kDaysUTC,
1315 : kTimeInDayUTC,
1316 : kTimezoneOffset
1317 : };
1318 :
1319 : // Layout description.
1320 : #define JS_DATE_FIELDS(V) \
1321 : V(kValueOffset, kTaggedSize) \
1322 : V(kYearOffset, kTaggedSize) \
1323 : V(kMonthOffset, kTaggedSize) \
1324 : V(kDayOffset, kTaggedSize) \
1325 : V(kWeekdayOffset, kTaggedSize) \
1326 : V(kHourOffset, kTaggedSize) \
1327 : V(kMinOffset, kTaggedSize) \
1328 : V(kSecOffset, kTaggedSize) \
1329 : V(kCacheStampOffset, kTaggedSize) \
1330 : /* Header size. */ \
1331 : V(kSize, 0)
1332 :
1333 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_DATE_FIELDS)
1334 : #undef JS_DATE_FIELDS
1335 :
1336 : private:
1337 : inline Object DoGetField(FieldIndex index);
1338 :
1339 : Object GetUTCField(FieldIndex index, double value, DateCache* date_cache);
1340 :
1341 : // Computes and caches the cacheable fields of the date.
1342 : inline void SetCachedFields(int64_t local_time_ms, DateCache* date_cache);
1343 :
1344 : OBJECT_CONSTRUCTORS(JSDate, JSObject);
1345 : };
1346 :
1347 : // Representation of message objects used for error reporting through
1348 : // the API. The messages are formatted in JavaScript so this object is
1349 : // a real JavaScript object. The information used for formatting the
1350 : // error messages are not directly accessible from JavaScript to
1351 : // prevent leaking information to user code called during error
1352 : // formatting.
1353 : class JSMessageObject : public JSObject {
1354 : public:
1355 : // [type]: the type of error message.
1356 : inline MessageTemplate type() const;
1357 : inline void set_type(MessageTemplate value);
1358 :
1359 : // [arguments]: the arguments for formatting the error message.
1360 : DECL_ACCESSORS(argument, Object)
1361 :
1362 : // [script]: the script from which the error message originated.
1363 : DECL_ACCESSORS(script, Script)
1364 :
1365 : // [stack_frames]: an array of stack frames for this error object.
1366 : DECL_ACCESSORS(stack_frames, Object)
1367 :
1368 : // [start_position]: the start position in the script for the error message.
1369 : inline int start_position() const;
1370 : inline void set_start_position(int value);
1371 :
1372 : // [end_position]: the end position in the script for the error message.
1373 : inline int end_position() const;
1374 : inline void set_end_position(int value);
1375 :
1376 : // Returns the line number for the error message (1-based), or
1377 : // Message::kNoLineNumberInfo if the line cannot be determined.
1378 : int GetLineNumber() const;
1379 :
1380 : // Returns the offset of the given position within the containing line.
1381 : int GetColumnNumber() const;
1382 :
1383 : // Returns the source code line containing the given source
1384 : // position, or the empty string if the position is invalid.
1385 : Handle<String> GetSourceLine() const;
1386 :
1387 : inline int error_level() const;
1388 : inline void set_error_level(int level);
1389 :
1390 : DECL_CAST(JSMessageObject)
1391 :
1392 : // Dispatched behavior.
1393 : DECL_PRINTER(JSMessageObject)
1394 : DECL_VERIFIER(JSMessageObject)
1395 :
1396 : // Layout description.
1397 : #define JS_MESSAGE_FIELDS(V) \
1398 : /* Tagged fields. */ \
1399 : V(kTypeOffset, kTaggedSize) \
1400 : V(kArgumentsOffset, kTaggedSize) \
1401 : V(kScriptOffset, kTaggedSize) \
1402 : V(kStackFramesOffset, kTaggedSize) \
1403 : V(kPointerFieldsEndOffset, 0) \
1404 : /* Raw data fields. */ \
1405 : /* TODO(ishell): store as int32 instead of Smi. */ \
1406 : V(kStartPositionOffset, kTaggedSize) \
1407 : V(kEndPositionOffset, kTaggedSize) \
1408 : V(kErrorLevelOffset, kTaggedSize) \
1409 : /* Total size. */ \
1410 : V(kSize, 0)
1411 :
1412 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_MESSAGE_FIELDS)
1413 : #undef JS_MESSAGE_FIELDS
1414 :
1415 : typedef FixedBodyDescriptor<HeapObject::kMapOffset, kPointerFieldsEndOffset,
1416 : kSize>
1417 : BodyDescriptor;
1418 :
1419 : OBJECT_CONSTRUCTORS(JSMessageObject, JSObject);
1420 : };
1421 :
1422 : // The [Async-from-Sync Iterator] object
1423 : // (proposal-async-iteration/#sec-async-from-sync-iterator-objects)
1424 : // An object which wraps an ordinary Iterator and converts it to behave
1425 : // according to the Async Iterator protocol.
1426 : // (See https://tc39.github.io/proposal-async-iteration/#sec-iteration)
1427 : class JSAsyncFromSyncIterator : public JSObject {
1428 : public:
1429 : DECL_CAST(JSAsyncFromSyncIterator)
1430 : DECL_PRINTER(JSAsyncFromSyncIterator)
1431 : DECL_VERIFIER(JSAsyncFromSyncIterator)
1432 :
1433 : // Async-from-Sync Iterator instances are ordinary objects that inherit
1434 : // properties from the %AsyncFromSyncIteratorPrototype% intrinsic object.
1435 : // Async-from-Sync Iterator instances are initially created with the internal
1436 : // slots listed in Table 4.
1437 : // (proposal-async-iteration/#table-async-from-sync-iterator-internal-slots)
1438 : DECL_ACCESSORS(sync_iterator, JSReceiver)
1439 :
1440 : // The "next" method is loaded during GetIterator, and is not reloaded for
1441 : // subsequent "next" invocations.
1442 : DECL_ACCESSORS(next, Object)
1443 :
1444 : // Layout description.
1445 : #define JS_ASYNC_FROM_SYNC_ITERATOR_FIELDS(V) \
1446 : V(kSyncIteratorOffset, kTaggedSize) \
1447 : V(kNextOffset, kTaggedSize) \
1448 : /* Total size. */ \
1449 : V(kSize, 0)
1450 :
1451 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
1452 : JS_ASYNC_FROM_SYNC_ITERATOR_FIELDS)
1453 : #undef JS_ASYNC_FROM_SYNC_ITERATOR_FIELDS
1454 :
1455 : OBJECT_CONSTRUCTORS(JSAsyncFromSyncIterator, JSObject);
1456 : };
1457 :
1458 : class JSStringIterator : public JSObject {
1459 : public:
1460 : // Dispatched behavior.
1461 : DECL_PRINTER(JSStringIterator)
1462 : DECL_VERIFIER(JSStringIterator)
1463 :
1464 : DECL_CAST(JSStringIterator)
1465 :
1466 : // [string]: the [[IteratedString]] inobject property.
1467 : DECL_ACCESSORS(string, String)
1468 :
1469 : // [index]: The [[StringIteratorNextIndex]] inobject property.
1470 : inline int index() const;
1471 : inline void set_index(int value);
1472 :
1473 : // Layout description.
1474 : #define JS_STRING_ITERATOR_FIELDS(V) \
1475 : V(kStringOffset, kTaggedSize) \
1476 : V(kNextIndexOffset, kTaggedSize) \
1477 : /* Total size. */ \
1478 : V(kSize, 0)
1479 :
1480 : DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
1481 : JS_STRING_ITERATOR_FIELDS)
1482 : #undef JS_STRING_ITERATOR_FIELDS
1483 :
1484 : OBJECT_CONSTRUCTORS(JSStringIterator, JSObject);
1485 : };
1486 :
1487 : } // namespace internal
1488 : } // namespace v8
1489 :
1490 : #include "src/objects/object-macros-undef.h"
1491 :
1492 : #endif // V8_OBJECTS_JS_OBJECTS_H_
|