blob: c32f9f6cca9e70418328600cab3268ba82cc2e80 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
5#ifndef V8_OBJECTS_H_
6#define V8_OBJECTS_H_
7
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008#include <iosfwd>
9
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/allocation.h"
11#include "src/assert-scope.h"
12#include "src/bailout-reason.h"
13#include "src/base/bits.h"
14#include "src/builtins.h"
15#include "src/checks.h"
16#include "src/elements-kind.h"
17#include "src/field-index.h"
18#include "src/flags.h"
19#include "src/list.h"
20#include "src/property-details.h"
21#include "src/smart-pointers.h"
22#include "src/unicode-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023#include "src/unicode-decoder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/zone.h"
25
Steve Block3ce2e202009-11-05 08:53:23 +000026#if V8_TARGET_ARCH_ARM
Ben Murdochb8a8cc12014-11-26 15:28:44 +000027#include "src/arm/constants-arm.h" // NOLINT
28#elif V8_TARGET_ARCH_ARM64
29#include "src/arm64/constants-arm64.h" // NOLINT
Andrei Popescu31002712010-02-23 13:46:05 +000030#elif V8_TARGET_ARCH_MIPS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031#include "src/mips/constants-mips.h" // NOLINT
32#elif V8_TARGET_ARCH_MIPS64
33#include "src/mips64/constants-mips64.h" // NOLINT
Steve Block3ce2e202009-11-05 08:53:23 +000034#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +010035
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37//
Kristian Monsen50ef84f2010-07-29 15:18:00 +010038// Most object types in the V8 JavaScript are described in this file.
Steve Blocka7e24c12009-10-30 11:49:00 +000039//
40// Inheritance hierarchy:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000041// - Object
42// - Smi (immediate small integer)
43// - HeapObject (superclass for everything allocated in the heap)
44// - JSReceiver (suitable for property access)
45// - JSObject
46// - JSArray
47// - JSArrayBuffer
48// - JSArrayBufferView
49// - JSTypedArray
50// - JSDataView
51// - JSCollection
Ben Murdoch3ef787d2012-04-12 10:51:47 +010052// - JSSet
53// - JSMap
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054// - JSSetIterator
55// - JSMapIterator
56// - JSWeakCollection
Ben Murdoch69a99ed2011-11-30 16:03:39 +000057// - JSWeakMap
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058// - JSWeakSet
59// - JSRegExp
60// - JSFunction
61// - JSGeneratorObject
62// - JSModule
63// - GlobalObject
64// - JSGlobalObject
65// - JSBuiltinsObject
66// - JSGlobalProxy
67// - JSValue
68// - JSDate
69// - JSMessageObject
70// - JSProxy
71// - JSFunctionProxy
72// - FixedArrayBase
73// - ByteArray
74// - FixedArray
75// - DescriptorArray
76// - HashTable
77// - Dictionary
78// - StringTable
79// - CompilationCacheTable
80// - CodeCacheHashTable
81// - MapCache
82// - OrderedHashTable
83// - OrderedHashSet
84// - OrderedHashMap
85// - Context
86// - TypeFeedbackVector
87// - JSFunctionResultCache
88// - ScopeInfo
89// - TransitionArray
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090// - ScriptContextTable
91// - WeakFixedArray
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092// - FixedDoubleArray
93// - ExternalArray
94// - ExternalUint8ClampedArray
95// - ExternalInt8Array
96// - ExternalUint8Array
97// - ExternalInt16Array
98// - ExternalUint16Array
99// - ExternalInt32Array
100// - ExternalUint32Array
101// - ExternalFloat32Array
102// - Name
Steve Blocka7e24c12009-10-30 11:49:00 +0000103// - String
104// - SeqString
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105// - SeqOneByteString
Steve Blocka7e24c12009-10-30 11:49:00 +0000106// - SeqTwoByteString
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000107// - SlicedString
Steve Blocka7e24c12009-10-30 11:49:00 +0000108// - ConsString
Steve Blocka7e24c12009-10-30 11:49:00 +0000109// - ExternalString
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000110// - ExternalOneByteString
Steve Blocka7e24c12009-10-30 11:49:00 +0000111// - ExternalTwoByteString
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112// - InternalizedString
113// - SeqInternalizedString
114// - SeqOneByteInternalizedString
115// - SeqTwoByteInternalizedString
116// - ConsInternalizedString
117// - ExternalInternalizedString
118// - ExternalOneByteInternalizedString
119// - ExternalTwoByteInternalizedString
120// - Symbol
121// - HeapNumber
122// - Cell
123// - PropertyCell
124// - Code
125// - Map
126// - Oddball
127// - Foreign
128// - SharedFunctionInfo
129// - Struct
130// - Box
131// - DeclaredAccessorDescriptor
132// - AccessorInfo
133// - DeclaredAccessorInfo
134// - ExecutableAccessorInfo
135// - AccessorPair
136// - AccessCheckInfo
137// - InterceptorInfo
138// - CallHandlerInfo
139// - TemplateInfo
140// - FunctionTemplateInfo
141// - ObjectTemplateInfo
142// - Script
143// - SignatureInfo
144// - TypeSwitchInfo
145// - DebugInfo
146// - BreakPointInfo
147// - CodeCache
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148// - WeakCell
Steve Blocka7e24c12009-10-30 11:49:00 +0000149//
150// Formats of Object*:
151// Smi: [31 bit signed int] 0
152// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
Steve Blocka7e24c12009-10-30 11:49:00 +0000153
Steve Blocka7e24c12009-10-30 11:49:00 +0000154namespace v8 {
155namespace internal {
156
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157enum KeyedAccessStoreMode {
158 STANDARD_STORE,
159 STORE_TRANSITION_SMI_TO_OBJECT,
160 STORE_TRANSITION_SMI_TO_DOUBLE,
161 STORE_TRANSITION_DOUBLE_TO_OBJECT,
162 STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
163 STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
164 STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
165 STORE_AND_GROW_NO_TRANSITION,
166 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
167 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
168 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
169 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
170 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
171 STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
172 STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
173 STORE_NO_TRANSITION_HANDLE_COW
Ben Murdoch589d6972011-11-30 16:04:58 +0000174};
175
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176
177enum ContextualMode {
178 NOT_CONTEXTUAL,
179 CONTEXTUAL
Ben Murdochc7cc0282012-03-05 14:35:55 +0000180};
181
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182
183enum MutableMode {
184 MUTABLE,
185 IMMUTABLE
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100186};
187
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
190 STANDARD_STORE;
191STATIC_ASSERT(STANDARD_STORE == 0);
192STATIC_ASSERT(kGrowICDelta ==
193 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
194 STORE_TRANSITION_SMI_TO_OBJECT);
195STATIC_ASSERT(kGrowICDelta ==
196 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
197 STORE_TRANSITION_SMI_TO_DOUBLE);
198STATIC_ASSERT(kGrowICDelta ==
199 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
200 STORE_TRANSITION_DOUBLE_TO_OBJECT);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100201
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202
203static inline KeyedAccessStoreMode GetGrowStoreMode(
204 KeyedAccessStoreMode store_mode) {
205 if (store_mode < STORE_AND_GROW_NO_TRANSITION) {
206 store_mode = static_cast<KeyedAccessStoreMode>(
207 static_cast<int>(store_mode) + kGrowICDelta);
208 }
209 return store_mode;
210}
211
212
213static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) {
214 return store_mode > STANDARD_STORE &&
215 store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT &&
216 store_mode != STORE_AND_GROW_NO_TRANSITION;
217}
218
219
220static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
221 KeyedAccessStoreMode store_mode) {
222 if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
223 return store_mode;
224 }
225 if (store_mode >= STORE_AND_GROW_NO_TRANSITION) {
226 return STORE_AND_GROW_NO_TRANSITION;
227 }
228 return STANDARD_STORE;
229}
230
231
232static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
233 return store_mode >= STORE_AND_GROW_NO_TRANSITION &&
234 store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
235}
236
Steve Blocka7e24c12009-10-30 11:49:00 +0000237
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238enum IcCheckType { ELEMENT, PROPERTY };
239
240
Steve Blocka7e24c12009-10-30 11:49:00 +0000241// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
242enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
243
244
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245// Indicates whether a value can be loaded as a constant.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400246enum StoreMode { ALLOW_IN_DESCRIPTOR, FORCE_IN_OBJECT };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249// PropertyNormalizationMode is used to specify whether to keep
250// inobject properties when normalizing properties of a JSObject.
251enum PropertyNormalizationMode {
252 CLEAR_INOBJECT_PROPERTIES,
253 KEEP_INOBJECT_PROPERTIES
254};
255
256
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257// Indicates how aggressively the prototype should be optimized. FAST_PROTOTYPE
258// will give the fastest result by tailoring the map to the prototype, but that
259// will cause polymorphism with other objects. REGULAR_PROTOTYPE is to be used
260// (at least for now) when dynamically modifying the prototype chain of an
261// object using __proto__ or Object.setPrototypeOf.
262enum PrototypeOptimizationMode { REGULAR_PROTOTYPE, FAST_PROTOTYPE };
263
264
265// Indicates whether transitions can be added to a source map or not.
266enum TransitionFlag {
267 INSERT_TRANSITION,
268 OMIT_TRANSITION
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100269};
270
271
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272enum DebugExtraICState {
273 DEBUG_BREAK,
274 DEBUG_PREPARE_STEP_IN
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100275};
276
277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278// Indicates whether the transition is simple: the target map of the transition
279// either extends the current map with a new property, or it modifies the
280// property that was added last to the current map.
281enum SimpleTransitionFlag {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400282 SIMPLE_PROPERTY_TRANSITION,
283 PROPERTY_TRANSITION,
284 SPECIAL_TRANSITION
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285};
286
287
288// Indicates whether we are only interested in the descriptors of a particular
289// map, or in all descriptors in the descriptor array.
290enum DescriptorFlag {
291 ALL_DESCRIPTORS,
292 OWN_DESCRIPTORS
293};
294
295// The GC maintains a bit of information, the MarkingParity, which toggles
296// from odd to even and back every time marking is completed. Incremental
297// marking can visit an object twice during a marking phase, so algorithms that
298// that piggy-back on marking can use the parity to ensure that they only
299// perform an operation on an object once per marking phase: they record the
300// MarkingParity when they visit an object, and only re-visit the object when it
301// is marked again and the MarkingParity changes.
302enum MarkingParity {
303 NO_MARKING_PARITY,
304 ODD_MARKING_PARITY,
305 EVEN_MARKING_PARITY
306};
307
308// ICs store extra state in a Code object. The default extra state is
309// kNoExtraICState.
310typedef int ExtraICState;
311static const ExtraICState kNoExtraICState = 0;
312
Steve Block791712a2010-08-27 10:21:07 +0100313// Instance size sentinel for objects of variable size.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100314const int kVariableSizeSentinel = 0;
Steve Block791712a2010-08-27 10:21:07 +0100315
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316// We may store the unsigned bit field as signed Smi value and do not
317// use the sign bit.
318const int kStubMajorKeyBits = 7;
319const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
Steve Block791712a2010-08-27 10:21:07 +0100320
Steve Blocka7e24c12009-10-30 11:49:00 +0000321// All Maps have a field instance_type containing a InstanceType.
322// It describes the type of the instances.
323//
324// As an example, a JavaScript object is a heap object and its map
325// instance_type is JS_OBJECT_TYPE.
326//
327// The names of the string instance types are intended to systematically
Leon Clarkee46be812010-01-19 14:06:41 +0000328// mirror their encoding in the instance_type field of the map. The default
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329// encoding is considered TWO_BYTE. It is not mentioned in the name. ONE_BYTE
Leon Clarkee46be812010-01-19 14:06:41 +0000330// encoding is mentioned explicitly in the name. Likewise, the default
331// representation is considered sequential. It is not mentioned in the
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100332// name. The other representations (e.g. CONS, EXTERNAL) are explicitly
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333// mentioned. Finally, the string is either a STRING_TYPE (if it is a normal
334// string) or a INTERNALIZED_STRING_TYPE (if it is a internalized string).
Steve Blocka7e24c12009-10-30 11:49:00 +0000335//
336// NOTE: The following things are some that depend on the string types having
337// instance_types that are less than those of all other types:
338// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
339// Object::IsString.
340//
341// NOTE: Everything following JS_VALUE_TYPE is considered a
342// JSObject for GC purposes. The first four entries here have typeof
343// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344#define INSTANCE_TYPE_LIST(V) \
345 V(STRING_TYPE) \
346 V(ONE_BYTE_STRING_TYPE) \
347 V(CONS_STRING_TYPE) \
348 V(CONS_ONE_BYTE_STRING_TYPE) \
349 V(SLICED_STRING_TYPE) \
350 V(SLICED_ONE_BYTE_STRING_TYPE) \
351 V(EXTERNAL_STRING_TYPE) \
352 V(EXTERNAL_ONE_BYTE_STRING_TYPE) \
353 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
354 V(SHORT_EXTERNAL_STRING_TYPE) \
355 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE) \
356 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
357 \
358 V(INTERNALIZED_STRING_TYPE) \
359 V(ONE_BYTE_INTERNALIZED_STRING_TYPE) \
360 V(EXTERNAL_INTERNALIZED_STRING_TYPE) \
361 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
362 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
363 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \
364 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \
365 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
366 \
367 V(SYMBOL_TYPE) \
368 \
369 V(MAP_TYPE) \
370 V(CODE_TYPE) \
371 V(ODDBALL_TYPE) \
372 V(CELL_TYPE) \
373 V(PROPERTY_CELL_TYPE) \
374 \
375 V(HEAP_NUMBER_TYPE) \
376 V(MUTABLE_HEAP_NUMBER_TYPE) \
377 V(FOREIGN_TYPE) \
378 V(BYTE_ARRAY_TYPE) \
379 V(FREE_SPACE_TYPE) \
380 /* Note: the order of these external array */ \
381 /* types is relied upon in */ \
382 /* Object::IsExternalArray(). */ \
383 V(EXTERNAL_INT8_ARRAY_TYPE) \
384 V(EXTERNAL_UINT8_ARRAY_TYPE) \
385 V(EXTERNAL_INT16_ARRAY_TYPE) \
386 V(EXTERNAL_UINT16_ARRAY_TYPE) \
387 V(EXTERNAL_INT32_ARRAY_TYPE) \
388 V(EXTERNAL_UINT32_ARRAY_TYPE) \
389 V(EXTERNAL_FLOAT32_ARRAY_TYPE) \
390 V(EXTERNAL_FLOAT64_ARRAY_TYPE) \
391 V(EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE) \
392 \
393 V(FIXED_INT8_ARRAY_TYPE) \
394 V(FIXED_UINT8_ARRAY_TYPE) \
395 V(FIXED_INT16_ARRAY_TYPE) \
396 V(FIXED_UINT16_ARRAY_TYPE) \
397 V(FIXED_INT32_ARRAY_TYPE) \
398 V(FIXED_UINT32_ARRAY_TYPE) \
399 V(FIXED_FLOAT32_ARRAY_TYPE) \
400 V(FIXED_FLOAT64_ARRAY_TYPE) \
401 V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \
402 \
403 V(FILLER_TYPE) \
404 \
405 V(DECLARED_ACCESSOR_DESCRIPTOR_TYPE) \
406 V(DECLARED_ACCESSOR_INFO_TYPE) \
407 V(EXECUTABLE_ACCESSOR_INFO_TYPE) \
408 V(ACCESSOR_PAIR_TYPE) \
409 V(ACCESS_CHECK_INFO_TYPE) \
410 V(INTERCEPTOR_INFO_TYPE) \
411 V(CALL_HANDLER_INFO_TYPE) \
412 V(FUNCTION_TEMPLATE_INFO_TYPE) \
413 V(OBJECT_TEMPLATE_INFO_TYPE) \
414 V(SIGNATURE_INFO_TYPE) \
415 V(TYPE_SWITCH_INFO_TYPE) \
416 V(ALLOCATION_MEMENTO_TYPE) \
417 V(ALLOCATION_SITE_TYPE) \
418 V(SCRIPT_TYPE) \
419 V(CODE_CACHE_TYPE) \
420 V(POLYMORPHIC_CODE_CACHE_TYPE) \
421 V(TYPE_FEEDBACK_INFO_TYPE) \
422 V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
423 V(BOX_TYPE) \
424 \
425 V(FIXED_ARRAY_TYPE) \
426 V(FIXED_DOUBLE_ARRAY_TYPE) \
427 V(CONSTANT_POOL_ARRAY_TYPE) \
428 V(SHARED_FUNCTION_INFO_TYPE) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400429 V(WEAK_CELL_TYPE) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 \
431 V(JS_MESSAGE_OBJECT_TYPE) \
432 \
433 V(JS_VALUE_TYPE) \
434 V(JS_DATE_TYPE) \
435 V(JS_OBJECT_TYPE) \
436 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
437 V(JS_GENERATOR_OBJECT_TYPE) \
438 V(JS_MODULE_TYPE) \
439 V(JS_GLOBAL_OBJECT_TYPE) \
440 V(JS_BUILTINS_OBJECT_TYPE) \
441 V(JS_GLOBAL_PROXY_TYPE) \
442 V(JS_ARRAY_TYPE) \
443 V(JS_ARRAY_BUFFER_TYPE) \
444 V(JS_TYPED_ARRAY_TYPE) \
445 V(JS_DATA_VIEW_TYPE) \
446 V(JS_PROXY_TYPE) \
447 V(JS_SET_TYPE) \
448 V(JS_MAP_TYPE) \
449 V(JS_SET_ITERATOR_TYPE) \
450 V(JS_MAP_ITERATOR_TYPE) \
451 V(JS_WEAK_MAP_TYPE) \
452 V(JS_WEAK_SET_TYPE) \
453 V(JS_REGEXP_TYPE) \
454 \
455 V(JS_FUNCTION_TYPE) \
456 V(JS_FUNCTION_PROXY_TYPE) \
457 V(DEBUG_INFO_TYPE) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 V(BREAK_POINT_INFO_TYPE)
Steve Blocka7e24c12009-10-30 11:49:00 +0000459
460
461// Since string types are not consecutive, this macro is used to
462// iterate over them.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463#define STRING_TYPE_LIST(V) \
464 V(STRING_TYPE, kVariableSizeSentinel, string, String) \
465 V(ONE_BYTE_STRING_TYPE, kVariableSizeSentinel, one_byte_string, \
466 OneByteString) \
467 V(CONS_STRING_TYPE, ConsString::kSize, cons_string, ConsString) \
468 V(CONS_ONE_BYTE_STRING_TYPE, ConsString::kSize, cons_one_byte_string, \
469 ConsOneByteString) \
470 V(SLICED_STRING_TYPE, SlicedString::kSize, sliced_string, SlicedString) \
471 V(SLICED_ONE_BYTE_STRING_TYPE, SlicedString::kSize, sliced_one_byte_string, \
472 SlicedOneByteString) \
473 V(EXTERNAL_STRING_TYPE, ExternalTwoByteString::kSize, external_string, \
474 ExternalString) \
475 V(EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kSize, \
476 external_one_byte_string, ExternalOneByteString) \
477 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, ExternalTwoByteString::kSize, \
478 external_string_with_one_byte_data, ExternalStringWithOneByteData) \
479 V(SHORT_EXTERNAL_STRING_TYPE, ExternalTwoByteString::kShortSize, \
480 short_external_string, ShortExternalString) \
481 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kShortSize, \
482 short_external_one_byte_string, ShortExternalOneByteString) \
483 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, \
484 ExternalTwoByteString::kShortSize, \
485 short_external_string_with_one_byte_data, \
486 ShortExternalStringWithOneByteData) \
487 \
488 V(INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, internalized_string, \
489 InternalizedString) \
490 V(ONE_BYTE_INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, \
491 one_byte_internalized_string, OneByteInternalizedString) \
492 V(EXTERNAL_INTERNALIZED_STRING_TYPE, ExternalTwoByteString::kSize, \
493 external_internalized_string, ExternalInternalizedString) \
494 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, ExternalOneByteString::kSize, \
495 external_one_byte_internalized_string, ExternalOneByteInternalizedString) \
496 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \
497 ExternalTwoByteString::kSize, \
498 external_internalized_string_with_one_byte_data, \
499 ExternalInternalizedStringWithOneByteData) \
500 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE, \
501 ExternalTwoByteString::kShortSize, short_external_internalized_string, \
502 ShortExternalInternalizedString) \
503 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, \
504 ExternalOneByteString::kShortSize, \
505 short_external_one_byte_internalized_string, \
506 ShortExternalOneByteInternalizedString) \
507 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \
508 ExternalTwoByteString::kShortSize, \
509 short_external_internalized_string_with_one_byte_data, \
510 ShortExternalInternalizedStringWithOneByteData)
Steve Blocka7e24c12009-10-30 11:49:00 +0000511
512// A struct is a simple object a set of object-valued fields. Including an
513// object type in this causes the compiler to generate most of the boilerplate
514// code for the class including allocation and garbage collection routines,
515// casts and predicates. All you need to define is the class, methods and
516// object verification routines. Easy, no?
517//
518// Note that for subtle reasons related to the ordering or numerical values of
519// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
520// manually.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521#define STRUCT_LIST(V) \
522 V(BOX, Box, box) \
523 V(DECLARED_ACCESSOR_DESCRIPTOR, \
524 DeclaredAccessorDescriptor, \
525 declared_accessor_descriptor) \
526 V(DECLARED_ACCESSOR_INFO, DeclaredAccessorInfo, declared_accessor_info) \
527 V(EXECUTABLE_ACCESSOR_INFO, ExecutableAccessorInfo, executable_accessor_info)\
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100528 V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
Steve Blockd0582a62009-12-15 09:54:21 +0000529 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
530 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
531 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
532 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
533 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
534 V(SIGNATURE_INFO, SignatureInfo, signature_info) \
535 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
Steve Block6ded16b2010-05-10 14:33:55 +0100536 V(SCRIPT, Script, script) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 V(ALLOCATION_SITE, AllocationSite, allocation_site) \
538 V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000539 V(CODE_CACHE, CodeCache, code_cache) \
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100540 V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache) \
541 V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry) \
Steve Blockd0582a62009-12-15 09:54:21 +0000543 V(DEBUG_INFO, DebugInfo, debug_info) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000544 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
Steve Blocka7e24c12009-10-30 11:49:00 +0000545
546// We use the full 8 bits of the instance_type field to encode heap object
547// instance types. The high-order bit (bit 7) is set if the object is not a
548// string, and cleared if it is a string.
549const uint32_t kIsNotStringMask = 0x80;
550const uint32_t kStringTag = 0x0;
551const uint32_t kNotStringTag = 0x80;
552
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553// Bit 6 indicates that the object is an internalized string (if set) or not.
554// Bit 7 has to be clear as well.
555const uint32_t kIsNotInternalizedMask = 0x40;
556const uint32_t kNotInternalizedTag = 0x40;
557const uint32_t kInternalizedTag = 0x0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000558
Steve Blocka7e24c12009-10-30 11:49:00 +0000559// If bit 7 is clear then bit 2 indicates whether the string consists of
560// two-byte characters or one-byte characters.
561const uint32_t kStringEncodingMask = 0x4;
562const uint32_t kTwoByteStringTag = 0x0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563const uint32_t kOneByteStringTag = 0x4;
Steve Blocka7e24c12009-10-30 11:49:00 +0000564
565// If bit 7 is clear, the low-order 2 bits indicate the representation
566// of the string.
567const uint32_t kStringRepresentationMask = 0x03;
568enum StringRepresentationTag {
569 kSeqStringTag = 0x0,
570 kConsStringTag = 0x1,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000571 kExternalStringTag = 0x2,
572 kSlicedStringTag = 0x3
Steve Blocka7e24c12009-10-30 11:49:00 +0000573};
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000574const uint32_t kIsIndirectStringMask = 0x1;
575const uint32_t kIsIndirectStringTag = 0x1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0); // NOLINT
577STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0); // NOLINT
578STATIC_ASSERT((kConsStringTag &
579 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT
580STATIC_ASSERT((kSlicedStringTag &
581 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000582
583// Use this mask to distinguish between cons and slice only after making
584// sure that the string is one of the two (an indirect string).
585const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask));
Steve Blocka7e24c12009-10-30 11:49:00 +0000587
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100588// If bit 7 is clear, then bit 3 indicates whether this two-byte
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589// string actually contains one byte data.
590const uint32_t kOneByteDataHintMask = 0x08;
591const uint32_t kOneByteDataHintTag = 0x08;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100592
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100593// If bit 7 is clear and string representation indicates an external string,
594// then bit 4 indicates whether the data pointer is cached.
595const uint32_t kShortExternalStringMask = 0x10;
596const uint32_t kShortExternalStringTag = 0x10;
597
Steve Blocka7e24c12009-10-30 11:49:00 +0000598
599// A ConsString with an empty string as the right side is a candidate
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600// for being shortcut by the garbage collector. We don't allocate any
601// non-flat internalized strings, so we do not shortcut them thereby
602// avoiding turning internalized strings into strings. The bit-masks
603// below contain the internalized bit as additional safety.
604// See heap.cc, mark-compact.cc and objects-visiting.cc.
Steve Blocka7e24c12009-10-30 11:49:00 +0000605const uint32_t kShortcutTypeMask =
606 kIsNotStringMask |
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 kIsNotInternalizedMask |
Steve Blocka7e24c12009-10-30 11:49:00 +0000608 kStringRepresentationMask;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609const uint32_t kShortcutTypeTag = kConsStringTag | kNotInternalizedTag;
610
611static inline bool IsShortcutCandidate(int type) {
612 return ((type & kShortcutTypeMask) == kShortcutTypeTag);
613}
Steve Blocka7e24c12009-10-30 11:49:00 +0000614
615
616enum InstanceType {
Leon Clarkee46be812010-01-19 14:06:41 +0000617 // String types.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 INTERNALIZED_STRING_TYPE =
619 kTwoByteStringTag | kSeqStringTag | kInternalizedTag,
620 ONE_BYTE_INTERNALIZED_STRING_TYPE =
621 kOneByteStringTag | kSeqStringTag | kInternalizedTag,
622 EXTERNAL_INTERNALIZED_STRING_TYPE =
623 kTwoByteStringTag | kExternalStringTag | kInternalizedTag,
624 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE =
625 kOneByteStringTag | kExternalStringTag | kInternalizedTag,
626 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
627 EXTERNAL_INTERNALIZED_STRING_TYPE | kOneByteDataHintTag |
628 kInternalizedTag,
629 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE = EXTERNAL_INTERNALIZED_STRING_TYPE |
630 kShortExternalStringTag |
631 kInternalizedTag,
632 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE =
633 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kShortExternalStringTag |
634 kInternalizedTag,
635 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
636 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE |
637 kShortExternalStringTag | kInternalizedTag,
638 STRING_TYPE = INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
639 ONE_BYTE_STRING_TYPE =
640 ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
641 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag | kNotInternalizedTag,
642 CONS_ONE_BYTE_STRING_TYPE =
643 kOneByteStringTag | kConsStringTag | kNotInternalizedTag,
644 SLICED_STRING_TYPE =
645 kTwoByteStringTag | kSlicedStringTag | kNotInternalizedTag,
646 SLICED_ONE_BYTE_STRING_TYPE =
647 kOneByteStringTag | kSlicedStringTag | kNotInternalizedTag,
648 EXTERNAL_STRING_TYPE =
649 EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
650 EXTERNAL_ONE_BYTE_STRING_TYPE =
651 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
652 EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
653 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE |
654 kNotInternalizedTag,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100655 SHORT_EXTERNAL_STRING_TYPE =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
657 SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE =
658 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
659 SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
660 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE |
661 kNotInternalizedTag,
662
663 // Non-string names
664 SYMBOL_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000665
Leon Clarkee46be812010-01-19 14:06:41 +0000666 // Objects allocated in their own spaces (never in new space).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 MAP_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 CODE_TYPE,
669 ODDBALL_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 CELL_TYPE,
671 PROPERTY_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000672
673 // "Data", objects that cannot contain non-map-word pointers to heap
674 // objects.
675 HEAP_NUMBER_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676 MUTABLE_HEAP_NUMBER_TYPE,
Ben Murdoch257744e2011-11-30 15:57:28 +0000677 FOREIGN_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000678 BYTE_ARRAY_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100679 FREE_SPACE_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 EXTERNAL_INT8_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
681 EXTERNAL_UINT8_ARRAY_TYPE,
682 EXTERNAL_INT16_ARRAY_TYPE,
683 EXTERNAL_UINT16_ARRAY_TYPE,
684 EXTERNAL_INT32_ARRAY_TYPE,
685 EXTERNAL_UINT32_ARRAY_TYPE,
686 EXTERNAL_FLOAT32_ARRAY_TYPE,
687 EXTERNAL_FLOAT64_ARRAY_TYPE,
688 EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
689 FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE
690 FIXED_UINT8_ARRAY_TYPE,
691 FIXED_INT16_ARRAY_TYPE,
692 FIXED_UINT16_ARRAY_TYPE,
693 FIXED_INT32_ARRAY_TYPE,
694 FIXED_UINT32_ARRAY_TYPE,
695 FIXED_FLOAT32_ARRAY_TYPE,
696 FIXED_FLOAT64_ARRAY_TYPE,
697 FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000698 FIXED_DOUBLE_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000699 FILLER_TYPE, // LAST_DATA_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000700
Leon Clarkee46be812010-01-19 14:06:41 +0000701 // Structs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000702 DECLARED_ACCESSOR_DESCRIPTOR_TYPE,
703 DECLARED_ACCESSOR_INFO_TYPE,
704 EXECUTABLE_ACCESSOR_INFO_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100705 ACCESSOR_PAIR_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 ACCESS_CHECK_INFO_TYPE,
707 INTERCEPTOR_INFO_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000708 CALL_HANDLER_INFO_TYPE,
709 FUNCTION_TEMPLATE_INFO_TYPE,
710 OBJECT_TEMPLATE_INFO_TYPE,
711 SIGNATURE_INFO_TYPE,
712 TYPE_SWITCH_INFO_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713 ALLOCATION_SITE_TYPE,
714 ALLOCATION_MEMENTO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000715 SCRIPT_TYPE,
Steve Block6ded16b2010-05-10 14:33:55 +0100716 CODE_CACHE_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000717 POLYMORPHIC_CODE_CACHE_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100718 TYPE_FEEDBACK_INFO_TYPE,
719 ALIASED_ARGUMENTS_ENTRY_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 BOX_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 DEBUG_INFO_TYPE,
722 BREAK_POINT_INFO_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000723 FIXED_ARRAY_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000724 CONSTANT_POOL_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000725 SHARED_FUNCTION_INFO_TYPE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726 WEAK_CELL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000727
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100728 // All the following types are subtypes of JSReceiver, which corresponds to
729 // objects in the JS sense. The first and the last type in this range are
730 // the two forms of function. This organization enables using the same
731 // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the
732 // NONCALLABLE_JS_OBJECT range.
733 JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE
735 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
736 JS_MESSAGE_OBJECT_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100737 JS_DATE_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 JS_OBJECT_TYPE,
739 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740 JS_GENERATOR_OBJECT_TYPE,
741 JS_MODULE_TYPE,
Steve Blocka7e24c12009-10-30 11:49:00 +0000742 JS_GLOBAL_OBJECT_TYPE,
743 JS_BUILTINS_OBJECT_TYPE,
744 JS_GLOBAL_PROXY_TYPE,
745 JS_ARRAY_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 JS_ARRAY_BUFFER_TYPE,
747 JS_TYPED_ARRAY_TYPE,
748 JS_DATA_VIEW_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100749 JS_SET_TYPE,
750 JS_MAP_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751 JS_SET_ITERATOR_TYPE,
752 JS_MAP_ITERATOR_TYPE,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000753 JS_WEAK_MAP_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000754 JS_WEAK_SET_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100755 JS_REGEXP_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100756 JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
758 // Pseudo-types
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 FIRST_TYPE = 0x0,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100760 LAST_TYPE = JS_FUNCTION_TYPE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 FIRST_NAME_TYPE = FIRST_TYPE,
762 LAST_NAME_TYPE = SYMBOL_TYPE,
763 FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
764 LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
765 FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000766 // Boundaries for testing for an external array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000767 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_INT8_ARRAY_TYPE,
768 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE,
769 // Boundaries for testing for a fixed typed array.
770 FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE,
771 LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE,
Leon Clarkee46be812010-01-19 14:06:41 +0000772 // Boundary for promotion to old data space/old pointer space.
773 LAST_DATA_TYPE = FILLER_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000774 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
775 // Note that there is no range for JSObject or JSProxy, since their subtypes
776 // are not continuous in this enum! The enum ranges instead reflect the
777 // external class names, where proxies are treated as either ordinary objects,
778 // or functions.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100779 FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000780 LAST_JS_RECEIVER_TYPE = LAST_TYPE,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100781 // Boundaries for testing the types represented as JSObject
782 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
783 LAST_JS_OBJECT_TYPE = LAST_TYPE,
784 // Boundaries for testing the types represented as JSProxy
785 FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE,
786 LAST_JS_PROXY_TYPE = JS_PROXY_TYPE,
Ben Murdoch85b71792012-04-11 18:30:58 +0100787 // Boundaries for testing whether the type is a JavaScript object.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100788 FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE,
789 LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE,
790 // Boundaries for testing the types for which typeof is "object".
791 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE,
792 LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
793 // Note that the types for which typeof is "function" are not continuous.
794 // Define this so that we can put assertions on discrete checks.
795 NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
Steve Blocka7e24c12009-10-30 11:49:00 +0000796};
797
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100798const int kExternalArrayTypeCount =
799 LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000800
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
802STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
803STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType);
804STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType);
805
806
807#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
808 V(FAST_ELEMENTS_SUB_TYPE) \
809 V(DICTIONARY_ELEMENTS_SUB_TYPE) \
810 V(FAST_PROPERTIES_SUB_TYPE) \
811 V(DICTIONARY_PROPERTIES_SUB_TYPE) \
812 V(MAP_CODE_CACHE_SUB_TYPE) \
813 V(SCOPE_INFO_SUB_TYPE) \
814 V(STRING_TABLE_SUB_TYPE) \
815 V(DESCRIPTOR_ARRAY_SUB_TYPE) \
816 V(TRANSITION_ARRAY_SUB_TYPE)
817
818enum FixedArraySubInstanceType {
819#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
820 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
821#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
822 LAST_FIXED_ARRAY_SUB_TYPE = TRANSITION_ARRAY_SUB_TYPE
823};
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100824
825
Steve Blocka7e24c12009-10-30 11:49:00 +0000826enum CompareResult {
827 LESS = -1,
828 EQUAL = 0,
829 GREATER = 1,
830
831 NOT_EQUAL = GREATER
832};
833
834
835#define DECL_BOOLEAN_ACCESSORS(name) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 inline bool name() const; \
Steve Blocka7e24c12009-10-30 11:49:00 +0000837 inline void set_##name(bool value); \
838
839
840#define DECL_ACCESSORS(name, type) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 inline type* name() const; \
Steve Blocka7e24c12009-10-30 11:49:00 +0000842 inline void set_##name(type* value, \
843 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
844
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846#define DECLARE_CAST(type) \
847 INLINE(static type* cast(Object* object)); \
848 INLINE(static const type* cast(const Object* object));
849
850
851class AccessorPair;
852class AllocationSite;
853class AllocationSiteCreationContext;
854class AllocationSiteUsageContext;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400855class ConsString;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000856class DictionaryElementsAccessor;
857class ElementsAccessor;
858class FixedArrayBase;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000859class GlobalObject;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400860class LayoutDescriptor;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861class LookupIterator;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400862class ObjectVisitor;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000863class StringStream;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864class TypeFeedbackVector;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400865class WeakCell;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866// We cannot just say "class HeapType;" if it is created from a template... =8-?
867template<class> class TypeImpl;
868struct HeapTypeConfig;
869typedef TypeImpl<HeapTypeConfig> HeapType;
Steve Blocka7e24c12009-10-30 11:49:00 +0000870
871
872// A template-ized version of the IsXXX functions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873template <class C> inline bool Is(Object* obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000874
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875#ifdef VERIFY_HEAP
876#define DECLARE_VERIFIER(Name) void Name##Verify();
877#else
878#define DECLARE_VERIFIER(Name)
879#endif
Steve Block053d10c2011-06-13 19:13:29 +0100880
Ben Murdochb0fe1622011-05-05 13:52:32 +0100881#ifdef OBJECT_PRINT
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400882#define DECLARE_PRINTER(Name) void Name##Print(std::ostream& os); // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000883#else
884#define DECLARE_PRINTER(Name)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100885#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000886
Ben Murdochb8e0da22011-05-16 14:20:40 +0100887
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888#define OBJECT_TYPE_LIST(V) \
889 V(Smi) \
890 V(HeapObject) \
891 V(Number)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100892
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893#define HEAP_OBJECT_TYPE_LIST(V) \
894 V(HeapNumber) \
895 V(MutableHeapNumber) \
896 V(Name) \
897 V(UniqueName) \
898 V(String) \
899 V(SeqString) \
900 V(ExternalString) \
901 V(ConsString) \
902 V(SlicedString) \
903 V(ExternalTwoByteString) \
904 V(ExternalOneByteString) \
905 V(SeqTwoByteString) \
906 V(SeqOneByteString) \
907 V(InternalizedString) \
908 V(Symbol) \
909 \
910 V(ExternalArray) \
911 V(ExternalInt8Array) \
912 V(ExternalUint8Array) \
913 V(ExternalInt16Array) \
914 V(ExternalUint16Array) \
915 V(ExternalInt32Array) \
916 V(ExternalUint32Array) \
917 V(ExternalFloat32Array) \
918 V(ExternalFloat64Array) \
919 V(ExternalUint8ClampedArray) \
920 V(FixedTypedArrayBase) \
921 V(FixedUint8Array) \
922 V(FixedInt8Array) \
923 V(FixedUint16Array) \
924 V(FixedInt16Array) \
925 V(FixedUint32Array) \
926 V(FixedInt32Array) \
927 V(FixedFloat32Array) \
928 V(FixedFloat64Array) \
929 V(FixedUint8ClampedArray) \
930 V(ByteArray) \
931 V(FreeSpace) \
932 V(JSReceiver) \
933 V(JSObject) \
934 V(JSContextExtensionObject) \
935 V(JSGeneratorObject) \
936 V(JSModule) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400937 V(LayoutDescriptor) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000938 V(Map) \
939 V(DescriptorArray) \
940 V(TransitionArray) \
941 V(TypeFeedbackVector) \
942 V(DeoptimizationInputData) \
943 V(DeoptimizationOutputData) \
944 V(DependentCode) \
945 V(FixedArray) \
946 V(FixedDoubleArray) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400947 V(WeakFixedArray) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000948 V(ConstantPoolArray) \
949 V(Context) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400950 V(ScriptContextTable) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951 V(NativeContext) \
952 V(ScopeInfo) \
953 V(JSFunction) \
954 V(Code) \
955 V(Oddball) \
956 V(SharedFunctionInfo) \
957 V(JSValue) \
958 V(JSDate) \
959 V(JSMessageObject) \
960 V(StringWrapper) \
961 V(Foreign) \
962 V(Boolean) \
963 V(JSArray) \
964 V(JSArrayBuffer) \
965 V(JSArrayBufferView) \
966 V(JSTypedArray) \
967 V(JSDataView) \
968 V(JSProxy) \
969 V(JSFunctionProxy) \
970 V(JSSet) \
971 V(JSMap) \
972 V(JSSetIterator) \
973 V(JSMapIterator) \
974 V(JSWeakCollection) \
975 V(JSWeakMap) \
976 V(JSWeakSet) \
977 V(JSRegExp) \
978 V(HashTable) \
979 V(Dictionary) \
980 V(StringTable) \
981 V(JSFunctionResultCache) \
982 V(NormalizedMapCache) \
983 V(CompilationCacheTable) \
984 V(CodeCacheHashTable) \
985 V(PolymorphicCodeCacheHashTable) \
986 V(MapCache) \
987 V(Primitive) \
988 V(GlobalObject) \
989 V(JSGlobalObject) \
990 V(JSBuiltinsObject) \
991 V(JSGlobalProxy) \
992 V(UndetectableObject) \
993 V(AccessCheckNeeded) \
994 V(Cell) \
995 V(PropertyCell) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400996 V(WeakCell) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000997 V(ObjectHashTable) \
998 V(WeakHashTable) \
999 V(OrderedHashTable)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001000
Steve Blocka7e24c12009-10-30 11:49:00 +00001001// Object is the abstract superclass for all classes in the
1002// object hierarchy.
1003// Object does not use any virtual functions to avoid the
1004// allocation of the C++ vtable.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005// Since both Smi and HeapObject are subclasses of Object no
Steve Blocka7e24c12009-10-30 11:49:00 +00001006// data members can be present in Object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007class Object {
Steve Blocka7e24c12009-10-30 11:49:00 +00001008 public:
1009 // Type testing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 bool IsObject() const { return true; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012#define IS_TYPE_FUNCTION_DECL(type_) INLINE(bool Is##type_() const);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001013 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
1014 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
1015#undef IS_TYPE_FUNCTION_DECL
Steve Blocka7e24c12009-10-30 11:49:00 +00001016
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001017 // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
1018 // a keyed store is of the form a[expression] = foo.
1019 enum StoreFromKeyed {
1020 MAY_BE_STORE_FROM_KEYED,
1021 CERTAINLY_NOT_STORE_FROM_KEYED
1022 };
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001023
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001024 enum StorePropertyMode { NORMAL_PROPERTY, SUPER_PROPERTY };
1025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026 INLINE(bool IsFixedArrayBase() const);
1027 INLINE(bool IsExternal() const);
1028 INLINE(bool IsAccessorInfo() const);
Steve Blocka7e24c12009-10-30 11:49:00 +00001029
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030 INLINE(bool IsStruct() const);
1031#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \
1032 INLINE(bool Is##Name() const);
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
1034#undef DECLARE_STRUCT_PREDICATE
1035
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 INLINE(bool IsSpecObject()) const;
1037 INLINE(bool IsSpecFunction()) const;
1038 INLINE(bool IsTemplateInfo()) const;
1039 INLINE(bool IsNameDictionary() const);
1040 INLINE(bool IsSeededNumberDictionary() const);
1041 INLINE(bool IsUnseededNumberDictionary() const);
1042 INLINE(bool IsOrderedHashSet() const);
1043 INLINE(bool IsOrderedHashMap() const);
1044 bool IsCallable() const;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001045
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 // Oddball testing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 INLINE(bool IsUndefined() const);
1048 INLINE(bool IsNull() const);
1049 INLINE(bool IsTheHole() const);
1050 INLINE(bool IsException() const);
1051 INLINE(bool IsUninitialized() const);
1052 INLINE(bool IsTrue() const);
1053 INLINE(bool IsFalse() const);
1054 INLINE(bool IsArgumentsMarker() const);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001055
1056 // Filler objects (fillers and free space objects).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001057 INLINE(bool IsFiller() const);
Steve Blocka7e24c12009-10-30 11:49:00 +00001058
1059 // Extract the number.
1060 inline double Number();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001061 INLINE(bool IsNaN() const);
1062 INLINE(bool IsMinusZero() const);
1063 bool ToInt32(int32_t* value);
1064 bool ToUint32(uint32_t* value);
1065
1066 inline Representation OptimalRepresentation() {
1067 if (!FLAG_track_fields) return Representation::Tagged();
1068 if (IsSmi()) {
1069 return Representation::Smi();
1070 } else if (FLAG_track_double_fields && IsHeapNumber()) {
1071 return Representation::Double();
1072 } else if (FLAG_track_computed_fields && IsUninitialized()) {
1073 return Representation::None();
1074 } else if (FLAG_track_heap_object_fields) {
1075 DCHECK(IsHeapObject());
1076 return Representation::HeapObject();
1077 } else {
1078 return Representation::Tagged();
1079 }
1080 }
1081
1082 inline bool FitsRepresentation(Representation representation) {
1083 if (FLAG_track_fields && representation.IsNone()) {
1084 return false;
1085 } else if (FLAG_track_fields && representation.IsSmi()) {
1086 return IsSmi();
1087 } else if (FLAG_track_double_fields && representation.IsDouble()) {
1088 return IsMutableHeapNumber() || IsNumber();
1089 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
1090 return IsHeapObject();
1091 }
1092 return true;
1093 }
1094
1095 Handle<HeapType> OptimalType(Isolate* isolate, Representation representation);
1096
1097 inline static Handle<Object> NewStorageFor(Isolate* isolate,
1098 Handle<Object> object,
1099 Representation representation);
1100
1101 inline static Handle<Object> WrapForRead(Isolate* isolate,
1102 Handle<Object> object,
1103 Representation representation);
Steve Blocka7e24c12009-10-30 11:49:00 +00001104
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001105 // Returns true if the object is of the correct type to be used as a
1106 // implementation of a JSObject's elements.
1107 inline bool HasValidElements();
1108
Steve Blocka7e24c12009-10-30 11:49:00 +00001109 inline bool HasSpecificClassOf(String* name);
1110
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001111 bool BooleanValue(); // ECMA-262 9.2.
Steve Blocka7e24c12009-10-30 11:49:00 +00001112
1113 // Convert to a JSObject if needed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 // native_context is used when creating wrapper object.
1115 static inline MaybeHandle<JSReceiver> ToObject(Isolate* isolate,
1116 Handle<Object> object);
1117 static MaybeHandle<JSReceiver> ToObject(Isolate* isolate,
1118 Handle<Object> object,
1119 Handle<Context> context);
Steve Blocka7e24c12009-10-30 11:49:00 +00001120
1121 // Converts this to a Smi if possible.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 static MUST_USE_RESULT inline MaybeHandle<Smi> ToSmi(Isolate* isolate,
1123 Handle<Object> object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001124
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125 MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it);
Steve Blocka7e24c12009-10-30 11:49:00 +00001126
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001127 // Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5.
1128 MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
1129 Handle<Object> object, Handle<Name> key, Handle<Object> value,
1130 StrictMode strict_mode,
1131 StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 MUST_USE_RESULT static MaybeHandle<Object> SetProperty(
1134 LookupIterator* it, Handle<Object> value, StrictMode strict_mode,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001135 StoreFromKeyed store_mode,
1136 StorePropertyMode data_store_mode = NORMAL_PROPERTY);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty(
1138 LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001139 MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyElement(
1140 Isolate* isolate, Handle<Object> receiver, uint32_t index,
1141 Handle<Object> value, StrictMode strict_mode);
1142 MUST_USE_RESULT static MaybeHandle<Object> SetDataProperty(
1143 LookupIterator* it, Handle<Object> value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty(
1145 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
1146 StrictMode strict_mode, StoreFromKeyed store_mode);
1147 MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
1148 Handle<Object> object,
1149 Handle<Name> key);
1150 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
1151 Isolate* isolate,
1152 Handle<Object> object,
1153 const char* key);
1154 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
1155 Handle<Object> object,
1156 Handle<Name> key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001157
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor(
1159 Handle<Object> receiver,
1160 Handle<Name> name,
1161 Handle<JSObject> holder,
1162 Handle<Object> structure);
1163 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor(
1164 Handle<Object> receiver, Handle<Name> name, Handle<Object> value,
1165 Handle<JSObject> holder, Handle<Object> structure,
1166 StrictMode strict_mode);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001167
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
1169 Handle<Object> receiver,
1170 Handle<JSReceiver> getter);
1171 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithDefinedSetter(
1172 Handle<Object> receiver,
1173 Handle<JSReceiver> setter,
1174 Handle<Object> value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001175
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001176 MUST_USE_RESULT static inline MaybeHandle<Object> GetElement(
1177 Isolate* isolate,
1178 Handle<Object> object,
1179 uint32_t index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001180
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithReceiver(
1182 Isolate* isolate,
1183 Handle<Object> object,
1184 Handle<Object> receiver,
1185 uint32_t index);
1186
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001187 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithReceiver(
1188 Isolate* isolate, Handle<Object> object, Handle<Object> receiver,
1189 uint32_t index, Handle<Object> value, StrictMode strict_mode);
1190
1191 static inline Handle<Object> GetPrototypeSkipHiddenPrototypes(
1192 Isolate* isolate, Handle<Object> receiver);
1193
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 // Returns the permanent hash code associated with this object. May return
1195 // undefined if not yet created.
1196 Object* GetHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00001197
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001198 // Returns the permanent hash code associated with this object depending on
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199 // the actual object type. May create and store a hash code if needed and none
1200 // exists.
1201 static Handle<Smi> GetOrCreateHash(Isolate* isolate, Handle<Object> object);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001202
1203 // Checks whether this object has the same value as the given one. This
1204 // function is implemented according to ES5, section 9.12 and can be used
1205 // to implement the Harmony "egal" function.
1206 bool SameValue(Object* other);
1207
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001208 // Checks whether this object has the same value as the given one.
1209 // +0 and -0 are treated equal. Everything else is the same as SameValue.
1210 // This function is implemented according to ES6, section 7.2.4 and is used
1211 // by ES6 Map and Set.
1212 bool SameValueZero(Object* other);
1213
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001214 // Tries to convert an object to an array index. Returns true and sets
1215 // the output parameter if it succeeds.
1216 inline bool ToArrayIndex(uint32_t* index);
1217
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 // Returns true if this is a JSValue containing a string and the index is
1219 // < the length of the string. Used to implement [] on strings.
1220 inline bool IsStringObjectWithCharacterAt(uint32_t index);
1221
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001222 DECLARE_VERIFIER(Object)
1223#ifdef VERIFY_HEAP
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 // Verify a pointer is a valid object pointer.
1225 static void VerifyPointer(Object* p);
1226#endif
1227
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001228 inline void VerifyApiCallResultType();
1229
Steve Blocka7e24c12009-10-30 11:49:00 +00001230 // Prints this object without details.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001231 void ShortPrint(FILE* out = stdout);
Steve Blocka7e24c12009-10-30 11:49:00 +00001232
1233 // Prints this object without details to a message accumulator.
1234 void ShortPrint(StringStream* accumulator);
1235
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 void ShortPrint(std::ostream& os); // NOLINT
1237
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238 DECLARE_CAST(Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00001239
1240 // Layout description.
1241 static const int kHeaderSize = 0; // Object does not take up any space.
1242
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243#ifdef OBJECT_PRINT
1244 // For our gdb macros, we should perhaps change these in the future.
1245 void Print();
1246
1247 // Prints this object with details.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001248 void Print(std::ostream& os); // NOLINT
1249#else
1250 void Print() { ShortPrint(); }
1251 void Print(std::ostream& os) { ShortPrint(os); } // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001252#endif
1253
Steve Blocka7e24c12009-10-30 11:49:00 +00001254 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 friend class LookupIterator;
1256 friend class PrototypeIterator;
1257
1258 // Return the map of the root of object's prototype chain.
1259 Map* GetRootMap(Isolate* isolate);
1260
Steve Blocka7e24c12009-10-30 11:49:00 +00001261 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
1262};
1263
1264
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265struct Brief {
1266 explicit Brief(const Object* const v) : value(v) {}
1267 const Object* value;
1268};
1269
1270
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001271std::ostream& operator<<(std::ostream& os, const Brief& v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272
1273
Steve Blocka7e24c12009-10-30 11:49:00 +00001274// Smi represents integer Numbers that can be stored in 31 bits.
1275// Smis are immediate which means they are NOT allocated in the heap.
Steve Blocka7e24c12009-10-30 11:49:00 +00001276// The this pointer has the following format: [31 bit signed int] 0
Steve Block3ce2e202009-11-05 08:53:23 +00001277// For long smis it has the following format:
1278// [32 bit signed int] [31 bits zero padding] 0
1279// Smi stands for small integer.
Steve Blocka7e24c12009-10-30 11:49:00 +00001280class Smi: public Object {
1281 public:
1282 // Returns the integer value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 inline int value() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00001284
1285 // Convert a value to a Smi object.
1286 static inline Smi* FromInt(int value);
1287
1288 static inline Smi* FromIntptr(intptr_t value);
1289
1290 // Returns whether value can be represented in a Smi.
1291 static inline bool IsValid(intptr_t value);
1292
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001293 DECLARE_CAST(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00001294
1295 // Dispatched behavior.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001296 void SmiPrint(std::ostream& os) const; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 DECLARE_VERIFIER(Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00001298
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001299 static const int kMinValue =
1300 (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
Steve Block3ce2e202009-11-05 08:53:23 +00001301 static const int kMaxValue = -(kMinValue + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001302
1303 private:
1304 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
1305};
1306
1307
Steve Blocka7e24c12009-10-30 11:49:00 +00001308// Heap objects typically have a map pointer in their first word. However,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001309// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
Steve Blocka7e24c12009-10-30 11:49:00 +00001310// encoded in the first word. The class MapWord is an abstraction of the
1311// value in a heap object's first word.
1312class MapWord BASE_EMBEDDED {
1313 public:
1314 // Normal state: the map word contains a map pointer.
1315
1316 // Create a map word from a map pointer.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001317 static inline MapWord FromMap(const Map* map);
Steve Blocka7e24c12009-10-30 11:49:00 +00001318
1319 // View this map word as a map pointer.
1320 inline Map* ToMap();
1321
1322
1323 // Scavenge collection: the map word of live objects in the from space
1324 // contains a forwarding address (a heap object pointer in the to space).
1325
1326 // True if this map word is a forwarding address for a scavenge
1327 // collection. Only valid during a scavenge collection (specifically,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001328 // when all map words are heap object pointers, i.e. not during a full GC).
Steve Blocka7e24c12009-10-30 11:49:00 +00001329 inline bool IsForwardingAddress();
1330
1331 // Create a map word from a forwarding address.
1332 static inline MapWord FromForwardingAddress(HeapObject* object);
1333
1334 // View this map word as a forwarding address.
1335 inline HeapObject* ToForwardingAddress();
1336
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001337 static inline MapWord FromRawValue(uintptr_t value) {
1338 return MapWord(value);
1339 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001340
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001341 inline uintptr_t ToRawValue() {
1342 return value_;
1343 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001344
1345 private:
1346 // HeapObject calls the private constructor and directly reads the value.
1347 friend class HeapObject;
1348
1349 explicit MapWord(uintptr_t value) : value_(value) {}
1350
1351 uintptr_t value_;
1352};
1353
1354
1355// HeapObject is the superclass for all classes describing heap allocated
1356// objects.
1357class HeapObject: public Object {
1358 public:
1359 // [map]: Contains a map which contains the object's reflective
1360 // information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 inline Map* map() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 inline void set_map(Map* value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001363 // The no-write-barrier version. This is OK if the object is white and in
1364 // new space, or if the value is an immortal immutable object, like the maps
1365 // of primitive (non-JS) objects like strings, heap numbers etc.
1366 inline void set_map_no_write_barrier(Map* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001367
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 // Get the map using acquire load.
1369 inline Map* synchronized_map();
1370 inline MapWord synchronized_map_word() const;
1371
1372 // Set the map using release store
1373 inline void synchronized_set_map(Map* value);
1374 inline void synchronized_set_map_no_write_barrier(Map* value);
1375 inline void synchronized_set_map_word(MapWord map_word);
1376
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 // During garbage collection, the map word of a heap object does not
1378 // necessarily contain a map pointer.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 inline MapWord map_word() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00001380 inline void set_map_word(MapWord map_word);
1381
Steve Block44f0eee2011-05-26 01:26:41 +01001382 // The Heap the object was allocated in. Used also to access Isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 inline Heap* GetHeap() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001384
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385 // Convenience method to get current isolate.
1386 inline Isolate* GetIsolate() const;
Steve Block44f0eee2011-05-26 01:26:41 +01001387
Steve Blocka7e24c12009-10-30 11:49:00 +00001388 // Converts an address to a HeapObject pointer.
1389 static inline HeapObject* FromAddress(Address address);
1390
1391 // Returns the address of this HeapObject.
1392 inline Address address();
1393
1394 // Iterates over pointers contained in the object (including the Map)
1395 void Iterate(ObjectVisitor* v);
1396
1397 // Iterates over all pointers contained in the object except the
1398 // first map pointer. The object type is given in the first
1399 // parameter. This function does not access the map pointer in the
1400 // object, and so is safe to call while the map pointer is modified.
1401 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
1402
Steve Blocka7e24c12009-10-30 11:49:00 +00001403 // Returns the heap object's size in bytes
1404 inline int Size();
1405
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001406 // Returns true if this heap object may contain raw values, i.e., values that
1407 // look like pointers to heap objects.
1408 inline bool MayContainRawValues();
1409
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 // Given a heap object's map pointer, returns the heap size in bytes
1411 // Useful when the map pointer field is used for other purposes.
1412 // GC internal.
1413 inline int SizeFromMap(Map* map);
1414
Steve Blocka7e24c12009-10-30 11:49:00 +00001415 // Returns the field at offset in obj, as a read/write Object* reference.
1416 // Does no checking, and is safe to use during GC, while maps are invalid.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001417 // Does not invoke write barrier, so should only be assigned to
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 // during marking GC.
1419 static inline Object** RawField(HeapObject* obj, int offset);
1420
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 // Adds the |code| object related to |name| to the code cache of this map. If
1422 // this map is a dictionary map that is shared, the map copied and installed
1423 // onto the object.
1424 static void UpdateMapCodeCache(Handle<HeapObject> object,
1425 Handle<Name> name,
1426 Handle<Code> code);
1427
1428 DECLARE_CAST(HeapObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00001429
Leon Clarke4515c472010-02-03 11:58:03 +00001430 // Return the write barrier mode for this. Callers of this function
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 // must be able to present a reference to an DisallowHeapAllocation
Leon Clarke4515c472010-02-03 11:58:03 +00001432 // object as a sign that they are not going to use this function
1433 // from code that allocates and thus invalidates the returned write
1434 // barrier mode.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001435 inline WriteBarrierMode GetWriteBarrierMode(
1436 const DisallowHeapAllocation& promise);
Steve Blocka7e24c12009-10-30 11:49:00 +00001437
1438 // Dispatched behavior.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439 void HeapObjectShortPrint(std::ostream& os); // NOLINT
Ben Murdochb0fe1622011-05-05 13:52:32 +01001440#ifdef OBJECT_PRINT
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001441 void PrintHeader(std::ostream& os, const char* id); // NOLINT
Ben Murdoch85b71792012-04-11 18:30:58 +01001442#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001443 DECLARE_PRINTER(HeapObject)
1444 DECLARE_VERIFIER(HeapObject)
1445#ifdef VERIFY_HEAP
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001446 inline void VerifyObjectField(int offset);
1447 inline void VerifySmiField(int offset);
1448
Steve Blocka7e24c12009-10-30 11:49:00 +00001449 // Verify a pointer is a valid HeapObject pointer that points to object
1450 // areas in the heap.
1451 static void VerifyHeapPointer(Object* p);
1452#endif
1453
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001454 inline bool NeedsToEnsureDoubleAlignment();
1455
Steve Blocka7e24c12009-10-30 11:49:00 +00001456 // Layout description.
1457 // First field in a heap object is map.
1458 static const int kMapOffset = Object::kHeaderSize;
1459 static const int kHeaderSize = kMapOffset + kPointerSize;
1460
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461 STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001462
1463 protected:
1464 // helpers for calling an ObjectVisitor to iterate over pointers in the
1465 // half-open range [start, end) specified as integer offsets
1466 inline void IteratePointers(ObjectVisitor* v, int start, int end);
1467 // as above, for the single element at "offset"
1468 inline void IteratePointer(ObjectVisitor* v, int offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 // as above, for the next code link of a code object.
1470 inline void IterateNextCodeLink(ObjectVisitor* v, int offset);
Steve Blocka7e24c12009-10-30 11:49:00 +00001471
Steve Blocka7e24c12009-10-30 11:49:00 +00001472 private:
1473 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
1474};
1475
1476
Iain Merrick75681382010-08-19 15:07:18 +01001477// This class describes a body of an object of a fixed size
1478// in which all pointer fields are located in the [start_offset, end_offset)
1479// interval.
1480template<int start_offset, int end_offset, int size>
1481class FixedBodyDescriptor {
1482 public:
1483 static const int kStartOffset = start_offset;
1484 static const int kEndOffset = end_offset;
1485 static const int kSize = size;
1486
1487 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
1488
1489 template<typename StaticVisitor>
1490 static inline void IterateBody(HeapObject* obj) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491 StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
1492 HeapObject::RawField(obj, end_offset));
Iain Merrick75681382010-08-19 15:07:18 +01001493 }
1494};
1495
1496
1497// This class describes a body of an object of a variable size
1498// in which all pointer fields are located in the [start_offset, object_size)
1499// interval.
1500template<int start_offset>
1501class FlexibleBodyDescriptor {
1502 public:
1503 static const int kStartOffset = start_offset;
1504
1505 static inline void IterateBody(HeapObject* obj,
1506 int object_size,
1507 ObjectVisitor* v);
1508
1509 template<typename StaticVisitor>
1510 static inline void IterateBody(HeapObject* obj, int object_size) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511 StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
1512 HeapObject::RawField(obj, object_size));
Iain Merrick75681382010-08-19 15:07:18 +01001513 }
1514};
1515
Iain Merrick75681382010-08-19 15:07:18 +01001516
Steve Blocka7e24c12009-10-30 11:49:00 +00001517// The HeapNumber class describes heap allocated numbers that cannot be
1518// represented in a Smi (small integer)
1519class HeapNumber: public HeapObject {
1520 public:
1521 // [value]: number value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001522 inline double value() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00001523 inline void set_value(double value);
1524
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001525 DECLARE_CAST(HeapNumber)
Steve Blocka7e24c12009-10-30 11:49:00 +00001526
1527 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528 bool HeapNumberBooleanValue();
1529
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001530 void HeapNumberPrint(std::ostream& os); // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 DECLARE_VERIFIER(HeapNumber)
Steve Blocka7e24c12009-10-30 11:49:00 +00001532
Steve Block6ded16b2010-05-10 14:33:55 +01001533 inline int get_exponent();
1534 inline int get_sign();
1535
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 // Layout description.
1537 static const int kValueOffset = HeapObject::kHeaderSize;
1538 // IEEE doubles are two 32 bit words. The first is just mantissa, the second
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001539 // is a mixture of sign, exponent and mantissa. The offsets of two 32 bit
1540 // words within double numbers are endian dependent and they are set
1541 // accordingly.
1542#if defined(V8_TARGET_LITTLE_ENDIAN)
Steve Blocka7e24c12009-10-30 11:49:00 +00001543 static const int kMantissaOffset = kValueOffset;
1544 static const int kExponentOffset = kValueOffset + 4;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001545#elif defined(V8_TARGET_BIG_ENDIAN)
1546 static const int kMantissaOffset = kValueOffset + 4;
1547 static const int kExponentOffset = kValueOffset;
1548#else
1549#error Unknown byte ordering
1550#endif
Ben Murdoch8b112d22011-06-08 16:22:53 +01001551
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 static const int kSize = kValueOffset + kDoubleSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 static const uint32_t kSignMask = 0x80000000u;
1554 static const uint32_t kExponentMask = 0x7ff00000u;
1555 static const uint32_t kMantissaMask = 0xfffffu;
Steve Block6ded16b2010-05-10 14:33:55 +01001556 static const int kMantissaBits = 52;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001557 static const int kExponentBits = 11;
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 static const int kExponentBias = 1023;
1559 static const int kExponentShift = 20;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560 static const int kInfinityOrNanExponent =
1561 (kExponentMask >> kExponentShift) - kExponentBias;
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 static const int kMantissaBitsInTopWord = 20;
1563 static const int kNonMantissaBitsInTopWord = 12;
1564
1565 private:
1566 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
1567};
1568
1569
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001570enum EnsureElementsMode {
1571 DONT_ALLOW_DOUBLE_ELEMENTS,
1572 ALLOW_COPIED_DOUBLE_ELEMENTS,
1573 ALLOW_CONVERTED_DOUBLE_ELEMENTS
1574};
1575
1576
1577// Indicates whether a property should be set or (re)defined. Setting of a
1578// property causes attributes to remain unchanged, writability to be checked
1579// and callbacks to be called. Defining of a property causes attributes to
1580// be updated and callbacks to be overridden.
1581enum SetPropertyMode {
1582 SET_PROPERTY,
1583 DEFINE_PROPERTY
1584};
1585
1586
1587// Indicator for one component of an AccessorPair.
1588enum AccessorComponent {
1589 ACCESSOR_GETTER,
1590 ACCESSOR_SETTER
1591};
1592
1593
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001594// JSReceiver includes types on which properties can be defined, i.e.,
1595// JSObject and JSProxy.
1596class JSReceiver: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00001597 public:
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001598 enum DeleteMode {
1599 NORMAL_DELETION,
1600 STRICT_DELETION,
1601 FORCE_DELETION
1602 };
1603
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001604 DECLARE_CAST(JSReceiver)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001605
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606 MUST_USE_RESULT static MaybeHandle<Object> SetElement(
1607 Handle<JSReceiver> object,
1608 uint32_t index,
1609 Handle<Object> value,
1610 PropertyAttributes attributes,
1611 StrictMode strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001612
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
1614 MUST_USE_RESULT static inline Maybe<bool> HasProperty(
1615 Handle<JSReceiver> object, Handle<Name> name);
1616 MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(Handle<JSReceiver>,
1617 Handle<Name> name);
1618 MUST_USE_RESULT static inline Maybe<bool> HasElement(
1619 Handle<JSReceiver> object, uint32_t index);
1620 MUST_USE_RESULT static inline Maybe<bool> HasOwnElement(
1621 Handle<JSReceiver> object, uint32_t index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001622
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 // Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7.
1624 MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
1625 Handle<JSReceiver> object,
1626 Handle<Name> name,
1627 DeleteMode mode = NORMAL_DELETION);
1628 MUST_USE_RESULT static MaybeHandle<Object> DeleteElement(
1629 Handle<JSReceiver> object,
1630 uint32_t index,
1631 DeleteMode mode = NORMAL_DELETION);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001632
1633 // Tests for the fast common case for property enumeration.
1634 bool IsSimpleEnum();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001635
1636 // Returns the class name ([[Class]] property in the specification).
1637 String* class_name();
1638
1639 // Returns the constructor name (the name (possibly, inferred name) of the
1640 // function that was used to instantiate the object).
1641 String* constructor_name();
1642
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetPropertyAttributes(
1644 Handle<JSReceiver> object, Handle<Name> name);
1645 MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes(
1646 LookupIterator* it);
1647 MUST_USE_RESULT static Maybe<PropertyAttributes> GetOwnPropertyAttributes(
1648 Handle<JSReceiver> object, Handle<Name> name);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001649
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttribute(
1651 Handle<JSReceiver> object, uint32_t index);
1652 MUST_USE_RESULT static inline Maybe<PropertyAttributes>
1653 GetOwnElementAttribute(Handle<JSReceiver> object, uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001654
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001655 // Retrieves a permanent object identity hash code. The undefined value might
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001656 // be returned in case no hash was created yet.
1657 inline Object* GetIdentityHash();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001658
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001659 // Retrieves a permanent object identity hash code. May create and store a
1660 // hash code if needed and none exists.
1661 inline static Handle<Smi> GetOrCreateIdentityHash(
1662 Handle<JSReceiver> object);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001663
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664 enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS };
1665
1666 // Computes the enumerable keys for a JSObject. Used for implementing
1667 // "for (n in object) { }".
1668 MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys(
1669 Handle<JSReceiver> object,
1670 KeyCollectionType type);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001671
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001672 private:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001673 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
1674};
1675
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676// Forward declaration for JSObject::GetOrCreateHiddenPropertiesHashTable.
1677class ObjectHashTable;
1678
1679// Forward declaration for JSObject::Copy.
1680class AllocationSite;
1681
1682
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001683// The JSObject describes real heap allocated JavaScript objects with
1684// properties.
1685// Note that the map of JSObject changes during execution to enable inline
1686// caching.
1687class JSObject: public JSReceiver {
1688 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00001689 // [properties]: Backing storage for properties.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001690 // properties is a FixedArray in the fast case and a Dictionary in the
Steve Blocka7e24c12009-10-30 11:49:00 +00001691 // slow case.
1692 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
1693 inline void initialize_properties();
1694 inline bool HasFastProperties();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 inline NameDictionary* property_dictionary(); // Gets slow properties.
Steve Blocka7e24c12009-10-30 11:49:00 +00001696
1697 // [elements]: The elements (properties with names that are integers).
Iain Merrick75681382010-08-19 15:07:18 +01001698 //
1699 // Elements can be in two general modes: fast and slow. Each mode
1700 // corrensponds to a set of object representations of elements that
1701 // have something in common.
1702 //
1703 // In the fast mode elements is a FixedArray and so each element can
1704 // be quickly accessed. This fact is used in the generated code. The
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001705 // elements array can have one of three maps in this mode:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706 // fixed_array_map, sloppy_arguments_elements_map or
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001707 // fixed_cow_array_map (for copy-on-write arrays). In the latter case
1708 // the elements array may be shared by a few objects and so before
1709 // writing to any element the array must be copied. Use
1710 // EnsureWritableFastElements in this case.
Iain Merrick75681382010-08-19 15:07:18 +01001711 //
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001712 // In the slow mode the elements is either a NumberDictionary, an
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001713 // ExternalArray, or a FixedArray parameter map for a (sloppy)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001714 // arguments object.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001715 DECL_ACCESSORS(elements, FixedArrayBase)
Steve Blocka7e24c12009-10-30 11:49:00 +00001716 inline void initialize_elements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001717 static void ResetElements(Handle<JSObject> object);
1718 static inline void SetMapAndElements(Handle<JSObject> object,
1719 Handle<Map> map,
1720 Handle<FixedArrayBase> elements);
Steve Blocka7e24c12009-10-30 11:49:00 +00001721 inline ElementsKind GetElementsKind();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001722 inline ElementsAccessor* GetElementsAccessor();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001723 // Returns true if an object has elements of FAST_SMI_ELEMENTS ElementsKind.
1724 inline bool HasFastSmiElements();
1725 // Returns true if an object has elements of FAST_ELEMENTS ElementsKind.
1726 inline bool HasFastObjectElements();
1727 // Returns true if an object has elements of FAST_ELEMENTS or
1728 // FAST_SMI_ONLY_ELEMENTS.
1729 inline bool HasFastSmiOrObjectElements();
1730 // Returns true if an object has any of the fast elements kinds.
Steve Blocka7e24c12009-10-30 11:49:00 +00001731 inline bool HasFastElements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001732 // Returns true if an object has elements of FAST_DOUBLE_ELEMENTS
1733 // ElementsKind.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001734 inline bool HasFastDoubleElements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735 // Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS
1736 // ElementsKind.
1737 inline bool HasFastHoleyElements();
1738 inline bool HasSloppyArgumentsElements();
Steve Blocka7e24c12009-10-30 11:49:00 +00001739 inline bool HasDictionaryElements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001740
1741 inline bool HasExternalUint8ClampedElements();
Steve Block3ce2e202009-11-05 08:53:23 +00001742 inline bool HasExternalArrayElements();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001743 inline bool HasExternalInt8Elements();
1744 inline bool HasExternalUint8Elements();
1745 inline bool HasExternalInt16Elements();
1746 inline bool HasExternalUint16Elements();
1747 inline bool HasExternalInt32Elements();
1748 inline bool HasExternalUint32Elements();
1749 inline bool HasExternalFloat32Elements();
1750 inline bool HasExternalFloat64Elements();
1751
1752 inline bool HasFixedTypedArrayElements();
1753
1754 inline bool HasFixedUint8ClampedElements();
1755 inline bool HasFixedArrayElements();
1756 inline bool HasFixedInt8Elements();
1757 inline bool HasFixedUint8Elements();
1758 inline bool HasFixedInt16Elements();
1759 inline bool HasFixedUint16Elements();
1760 inline bool HasFixedInt32Elements();
1761 inline bool HasFixedUint32Elements();
1762 inline bool HasFixedFloat32Elements();
1763 inline bool HasFixedFloat64Elements();
1764
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001765 bool HasFastArgumentsElements();
1766 bool HasDictionaryArgumentsElements();
Ben Murdochc7cc0282012-03-05 14:35:55 +00001767 inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
1768
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001769 // Requires: HasFastElements().
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001770 static Handle<FixedArray> EnsureWritableFastElements(
1771 Handle<JSObject> object);
Steve Blocka7e24c12009-10-30 11:49:00 +00001772
1773 // Collects elements starting at index 0.
1774 // Undefined values are placed after non-undefined values.
1775 // Returns the number of non-undefined values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001776 static Handle<Object> PrepareElementsForSort(Handle<JSObject> object,
1777 uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001778 // As PrepareElementsForSort, but only on objects where elements is
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001779 // a dictionary, and it will stay a dictionary. Collates undefined and
1780 // unexisting elements below limit from position zero of the elements.
1781 static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object,
1782 uint32_t limit);
Steve Blocka7e24c12009-10-30 11:49:00 +00001783
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001784 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor(
1785 LookupIterator* it, Handle<Object> value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001786
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001787 // SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to
1788 // grant an exemption to ExecutableAccessor callbacks in some cases.
1789 enum ExecutableAccessorInfoHandling {
1790 DEFAULT_HANDLING,
1791 DONT_FORCE_FIELD
1792 };
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001793
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001794 MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001795 Handle<JSObject> object,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001796 Handle<Name> key,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001797 Handle<Object> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001798 PropertyAttributes attributes,
1799 ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001800
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001801 static void AddProperty(Handle<JSObject> object, Handle<Name> key,
1802 Handle<Object> value, PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00001803
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 // Extend the receiver with a single fast property appeared first in the
1805 // passed map. This also extends the property backing store if necessary.
1806 static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001808 // Migrates the given object to a map whose field representations are the
1809 // lowest upper bound of all known representations for that field.
1810 static void MigrateInstance(Handle<JSObject> instance);
1811
1812 // Migrates the given object only if the target map is already available,
1813 // or returns false if such a map is not yet available.
1814 static bool TryMigrateInstance(Handle<JSObject> instance);
Steve Blocka7e24c12009-10-30 11:49:00 +00001815
1816 // Sets the property value in a normalized object given (key, value, details).
1817 // Handles the special representation of JS global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001818 static void SetNormalizedProperty(Handle<JSObject> object,
1819 Handle<Name> key,
1820 Handle<Object> value,
1821 PropertyDetails details);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001823 static void OptimizeAsPrototype(Handle<JSObject> object,
1824 PrototypeOptimizationMode mode);
1825 static void ReoptimizeIfPrototype(Handle<JSObject> object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001826 static void RegisterPrototypeUser(Handle<JSObject> prototype,
1827 Handle<HeapObject> user);
1828 static void UnregisterPrototypeUser(Handle<JSObject> prototype,
1829 Handle<HeapObject> user);
Steve Blocka7e24c12009-10-30 11:49:00 +00001830
Steve Blocka7e24c12009-10-30 11:49:00 +00001831 // Retrieve interceptors.
1832 InterceptorInfo* GetNamedInterceptor();
1833 InterceptorInfo* GetIndexedInterceptor();
1834
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001835 // Used from JSReceiver.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001836 MUST_USE_RESULT static Maybe<PropertyAttributes>
1837 GetPropertyAttributesWithInterceptor(Handle<JSObject> holder,
1838 Handle<Object> receiver,
1839 Handle<Name> name);
1840 MUST_USE_RESULT static Maybe<PropertyAttributes>
1841 GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it);
1842 MUST_USE_RESULT static Maybe<PropertyAttributes>
1843 GetElementAttributeWithReceiver(Handle<JSObject> object,
1844 Handle<JSReceiver> receiver,
1845 uint32_t index, bool check_prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00001846
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001847 // Retrieves an AccessorPair property from the given object. Might return
1848 // undefined if the property doesn't exist or is of a different kind.
1849 MUST_USE_RESULT static MaybeHandle<Object> GetAccessor(
1850 Handle<JSObject> object,
1851 Handle<Name> name,
1852 AccessorComponent component);
Steve Blocka7e24c12009-10-30 11:49:00 +00001853
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001854 // Defines an AccessorPair property on the given object.
1855 // TODO(mstarzinger): Rename to SetAccessor().
1856 static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object,
1857 Handle<Name> name,
1858 Handle<Object> getter,
1859 Handle<Object> setter,
1860 PropertyAttributes attributes);
Leon Clarkef7060e22010-06-03 12:02:55 +01001861
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001862 // Defines an AccessorInfo property on the given object.
1863 MUST_USE_RESULT static MaybeHandle<Object> SetAccessor(
1864 Handle<JSObject> object,
1865 Handle<AccessorInfo> info);
1866
1867 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor(
1868 Handle<JSObject> object,
1869 Handle<Object> receiver,
1870 Handle<Name> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00001871
Steve Blockd0582a62009-12-15 09:54:21 +00001872 // Accessors for hidden properties object.
1873 //
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001874 // Hidden properties are not own properties of the object itself.
1875 // Instead they are stored in an auxiliary structure kept as an own
1876 // property with a special name Heap::hidden_string(). But if the
Steve Blockd0582a62009-12-15 09:54:21 +00001877 // receiver is a JSGlobalProxy then the auxiliary object is a property
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001878 // of its prototype, and if it's a detached proxy, then you can't have
1879 // hidden properties.
Steve Blockd0582a62009-12-15 09:54:21 +00001880
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001881 // Sets a hidden property on this object. Returns this object if successful,
1882 // undefined if called on a detached proxy.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001883 static Handle<Object> SetHiddenProperty(Handle<JSObject> object,
1884 Handle<Name> key,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001885 Handle<Object> value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001886 // Gets the value of a hidden property with the given key. Returns the hole
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001887 // if the property doesn't exist (or if called on a detached proxy),
1888 // otherwise returns the value set for the key.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001889 Object* GetHiddenProperty(Handle<Name> key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001890 // Deletes a hidden property. Deleting a non-existing property is
1891 // considered successful.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001892 static void DeleteHiddenProperty(Handle<JSObject> object,
1893 Handle<Name> key);
1894 // Returns true if the object has a property with the hidden string as name.
1895 static bool HasHiddenProperties(Handle<JSObject> object);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001896
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001897 static void SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001898
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001899 static inline void ValidateElements(Handle<JSObject> object);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001900
1901 // Makes sure that this object can contain HeapObject as elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001902 static inline void EnsureCanContainHeapObjectElements(Handle<JSObject> obj);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001903
1904 // Makes sure that this object can contain the specified elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001905 static inline void EnsureCanContainElements(
1906 Handle<JSObject> object,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001907 Object** elements,
1908 uint32_t count,
1909 EnsureElementsMode mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001910 static inline void EnsureCanContainElements(
1911 Handle<JSObject> object,
1912 Handle<FixedArrayBase> elements,
1913 uint32_t length,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001914 EnsureElementsMode mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001915 static void EnsureCanContainElements(
1916 Handle<JSObject> object,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001917 Arguments* arguments,
1918 uint32_t first_arg,
1919 uint32_t arg_count,
1920 EnsureElementsMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001921
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 // Would we convert a fast elements array to dictionary mode given
1923 // an access at key?
1924 bool WouldConvertToSlowElements(Handle<Object> key);
Steve Blocka7e24c12009-10-30 11:49:00 +00001925 // Do we want to keep the elements in fast case when increasing the
1926 // capacity?
1927 bool ShouldConvertToSlowElements(int new_capacity);
1928 // Returns true if the backing storage for the slow-case elements of
1929 // this object takes up nearly as much space as a fast-case backing
1930 // storage would. In that case the JSObject should have fast
1931 // elements.
1932 bool ShouldConvertToFastElements();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001933 // Returns true if the elements of JSObject contains only values that can be
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001934 // represented in a FixedDoubleArray and has at least one value that can only
1935 // be represented as a double and not a Smi.
1936 bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements);
Andrei Popescu402d9372010-02-26 13:31:12 +00001937
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001938 // Computes the new capacity when expanding the elements of a JSObject.
1939 static int NewElementsCapacity(int old_capacity) {
1940 // (old_capacity + 50%) + 16
1941 return old_capacity + (old_capacity >> 1) + 16;
1942 }
1943
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001944 // These methods do not perform access checks!
1945 MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001946 Handle<JSObject> object, uint32_t index);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001947
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 MUST_USE_RESULT static MaybeHandle<Object> SetFastElement(
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001949 Handle<JSObject> object,
1950 uint32_t index,
1951 Handle<Object> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001952 StrictMode strict_mode,
1953 bool check_prototype);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001954
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001955 MUST_USE_RESULT static MaybeHandle<Object> SetOwnElement(
1956 Handle<JSObject> object,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001957 uint32_t index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001958 Handle<Object> value,
1959 StrictMode strict_mode);
1960
1961 // Empty handle is returned if the element cannot be set to the given value.
1962 MUST_USE_RESULT static MaybeHandle<Object> SetElement(
1963 Handle<JSObject> object,
1964 uint32_t index,
1965 Handle<Object> value,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001966 PropertyAttributes attributes,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001967 StrictMode strict_mode,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001968 bool check_prototype = true,
1969 SetPropertyMode set_mode = SET_PROPERTY);
Steve Blocka7e24c12009-10-30 11:49:00 +00001970
1971 // Returns the index'th element.
1972 // The undefined object if index is out of bounds.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001973 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001974 Handle<JSObject> object, Handle<Object> receiver, uint32_t index,
1975 bool check_prototype);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001976
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001977 enum SetFastElementsCapacitySmiMode {
1978 kAllowSmiElements,
1979 kForceSmiElements,
1980 kDontAllowSmiElements
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001981 };
Ben Murdoch592a9fc2012-03-05 11:04:45 +00001982
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001983 // Replace the elements' backing store with fast elements of the given
1984 // capacity. Update the length for JSArrays. Returns the new backing
1985 // store.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001986 static Handle<FixedArray> SetFastElementsCapacityAndLength(
1987 Handle<JSObject> object,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001988 int capacity,
1989 int length,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001990 SetFastElementsCapacitySmiMode smi_mode);
1991 static void SetFastDoubleElementsCapacityAndLength(
1992 Handle<JSObject> object,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001993 int capacity,
1994 int length);
Steve Blocka7e24c12009-10-30 11:49:00 +00001995
1996 // Lookup interceptors are used for handling properties controlled by host
1997 // objects.
1998 inline bool HasNamedInterceptor();
1999 inline bool HasIndexedInterceptor();
2000
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002001 // Computes the enumerable keys from interceptors. Used for debug mirrors and
2002 // by JSReceiver::GetKeys.
2003 MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForNamedInterceptor(
2004 Handle<JSObject> object,
2005 Handle<JSReceiver> receiver);
2006 MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForIndexedInterceptor(
2007 Handle<JSObject> object,
2008 Handle<JSReceiver> receiver);
2009
Steve Blocka7e24c12009-10-30 11:49:00 +00002010 // Support functions for v8 api (needed for correct interceptor behavior).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002011 MUST_USE_RESULT static Maybe<bool> HasRealNamedProperty(
2012 Handle<JSObject> object, Handle<Name> key);
2013 MUST_USE_RESULT static Maybe<bool> HasRealElementProperty(
2014 Handle<JSObject> object, uint32_t index);
2015 MUST_USE_RESULT static Maybe<bool> HasRealNamedCallbackProperty(
2016 Handle<JSObject> object, Handle<Name> key);
Steve Blocka7e24c12009-10-30 11:49:00 +00002017
Steve Blocka7e24c12009-10-30 11:49:00 +00002018 // Get the header size for a JSObject. Used to compute the index of
2019 // internal fields as well as the number of internal fields.
2020 inline int GetHeaderSize();
2021
2022 inline int GetInternalFieldCount();
Steve Block44f0eee2011-05-26 01:26:41 +01002023 inline int GetInternalFieldOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002024 inline Object* GetInternalField(int index);
2025 inline void SetInternalField(int index, Object* value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002026 inline void SetInternalField(int index, Smi* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002027
Steve Blocka7e24c12009-10-30 11:49:00 +00002028 // Returns the number of properties on this object filtering out properties
2029 // with the specified attributes (ignoring interceptors).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002030 int NumberOfOwnProperties(PropertyAttributes filter = NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00002031 // Fill in details for properties into storage starting at the specified
2032 // index.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002033 void GetOwnPropertyNames(
2034 FixedArray* storage, int index, PropertyAttributes filter = NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00002035
2036 // Returns the number of properties on this object filtering out properties
2037 // with the specified attributes (ignoring interceptors).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002038 int NumberOfOwnElements(PropertyAttributes filter);
Steve Blocka7e24c12009-10-30 11:49:00 +00002039 // Returns the number of enumerable elements (ignoring interceptors).
2040 int NumberOfEnumElements();
2041 // Returns the number of elements on this object filtering out elements
2042 // with the specified attributes (ignoring interceptors).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002043 int GetOwnElementKeys(FixedArray* storage, PropertyAttributes filter);
Steve Blocka7e24c12009-10-30 11:49:00 +00002044 // Count and fill in the enumerable elements into storage.
2045 // (storage->length() == NumberOfEnumElements()).
2046 // If storage is NULL, will count the elements without adding
2047 // them to any storage.
2048 // Returns the number of enumerable elements.
2049 int GetEnumElementKeys(FixedArray* storage);
2050
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002051 // Returns a new map with all transitions dropped from the object's current
2052 // map and the ElementsKind set.
2053 static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
2054 ElementsKind to_kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002055 static void TransitionElementsKind(Handle<JSObject> object,
2056 ElementsKind to_kind);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002057
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002058 static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002059
2060 // Convert the object to use the canonical dictionary
2061 // representation. If the object is expected to have additional properties
2062 // added this number can be indicated to have the backing store allocated to
2063 // an initial capacity for holding these properties.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002064 static void NormalizeProperties(Handle<JSObject> object,
2065 PropertyNormalizationMode mode,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002066 int expected_additional_properties,
2067 const char* reason);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002068
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002069 // Convert and update the elements backing store to be a
2070 // SeededNumberDictionary dictionary. Returns the backing after conversion.
2071 static Handle<SeededNumberDictionary> NormalizeElements(
2072 Handle<JSObject> object);
2073
Steve Blocka7e24c12009-10-30 11:49:00 +00002074 // Transform slow named properties to fast variants.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002075 static void MigrateSlowToFast(Handle<JSObject> object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002076 int unused_property_fields, const char* reason);
2077
2078 inline bool IsUnboxedDoubleField(FieldIndex index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002079
2080 // Access fast-case object properties at index.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002081 static Handle<Object> FastPropertyAt(Handle<JSObject> object,
2082 Representation representation,
2083 FieldIndex index);
2084 inline Object* RawFastPropertyAt(FieldIndex index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002085 inline double RawFastDoublePropertyAt(FieldIndex index);
2086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002087 inline void FastPropertyAtPut(FieldIndex index, Object* value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002088 inline void RawFastPropertyAtPut(FieldIndex index, Object* value);
2089 inline void RawFastDoublePropertyAtPut(FieldIndex index, double value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090 void WriteToField(int descriptor, Object* value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002091
2092 // Access to in object properties.
Steve Block44f0eee2011-05-26 01:26:41 +01002093 inline int GetInObjectPropertyOffset(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002094 inline Object* InObjectPropertyAt(int index);
2095 inline Object* InObjectPropertyAtPut(int index,
2096 Object* value,
2097 WriteBarrierMode mode
2098 = UPDATE_WRITE_BARRIER);
2099
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002100 // Set the object's prototype (only JSReceiver and null are allowed values).
2101 MUST_USE_RESULT static MaybeHandle<Object> SetPrototype(
2102 Handle<JSObject> object, Handle<Object> value, bool from_javascript);
2103
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002104 // Initializes the body after properties slot, properties slot is
2105 // initialized by set_properties. Fill the pre-allocated fields with
2106 // pre_allocated_value and the rest with filler_value.
2107 // Note: this call does not update write barrier, the caller is responsible
2108 // to ensure that |filler_value| can be collected without WB here.
2109 inline void InitializeBody(Map* map,
2110 Object* pre_allocated_value,
2111 Object* filler_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00002112
2113 // Check whether this object references another object
2114 bool ReferencesObject(Object* obj);
2115
Steve Block8defd9f2010-07-08 12:39:36 +01002116 // Disalow further properties to be added to the object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002117 MUST_USE_RESULT static MaybeHandle<Object> PreventExtensions(
2118 Handle<JSObject> object);
Steve Block8defd9f2010-07-08 12:39:36 +01002119
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002120 // ES5 Object.seal
2121 MUST_USE_RESULT static MaybeHandle<Object> Seal(Handle<JSObject> object);
2122
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002123 // ES5 Object.freeze
2124 MUST_USE_RESULT static MaybeHandle<Object> Freeze(Handle<JSObject> object);
2125
2126 // Called the first time an object is observed with ES7 Object.observe.
2127 static void SetObserved(Handle<JSObject> object);
2128
2129 // Copy object.
2130 enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };
2131
2132 static Handle<JSObject> Copy(Handle<JSObject> object);
2133 MUST_USE_RESULT static MaybeHandle<JSObject> DeepCopy(
2134 Handle<JSObject> object,
2135 AllocationSiteUsageContext* site_context,
2136 DeepCopyHints hints = kNoHints);
2137 MUST_USE_RESULT static MaybeHandle<JSObject> DeepWalk(
2138 Handle<JSObject> object,
2139 AllocationSiteCreationContext* site_context);
2140
2141 static Handle<Object> GetDataProperty(Handle<JSObject> object,
2142 Handle<Name> key);
2143 static Handle<Object> GetDataProperty(LookupIterator* it);
2144
2145 DECLARE_CAST(JSObject)
Steve Block8defd9f2010-07-08 12:39:36 +01002146
Steve Blocka7e24c12009-10-30 11:49:00 +00002147 // Dispatched behavior.
Steve Blocka7e24c12009-10-30 11:49:00 +00002148 void JSObjectShortPrint(StringStream* accumulator);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002149 DECLARE_PRINTER(JSObject)
2150 DECLARE_VERIFIER(JSObject)
Ben Murdochb0fe1622011-05-05 13:52:32 +01002151#ifdef OBJECT_PRINT
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002152 void PrintProperties(std::ostream& os); // NOLINT
2153 void PrintElements(std::ostream& os); // NOLINT
2154#endif
2155#if defined(DEBUG) || defined(OBJECT_PRINT)
2156 void PrintTransitions(std::ostream& os); // NOLINT
Ben Murdochb0fe1622011-05-05 13:52:32 +01002157#endif
2158
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002159 static void PrintElementsTransition(
2160 FILE* file, Handle<JSObject> object,
2161 ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
2162 ElementsKind to_kind, Handle<FixedArrayBase> to_elements);
2163
2164 void PrintInstanceMigration(FILE* file, Map* original_map, Map* new_map);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002165
Ben Murdochb0fe1622011-05-05 13:52:32 +01002166#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002167 // Structure for collecting spill information about JSObjects.
2168 class SpillInformation {
2169 public:
2170 void Clear();
2171 void Print();
2172 int number_of_objects_;
2173 int number_of_objects_with_fast_properties_;
2174 int number_of_objects_with_fast_elements_;
2175 int number_of_fast_used_fields_;
2176 int number_of_fast_unused_fields_;
2177 int number_of_slow_used_properties_;
2178 int number_of_slow_unused_properties_;
2179 int number_of_fast_used_elements_;
2180 int number_of_fast_unused_elements_;
2181 int number_of_slow_used_elements_;
2182 int number_of_slow_unused_elements_;
2183 };
2184
2185 void IncrementSpillStatistics(SpillInformation* info);
2186#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00002187
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002188#ifdef VERIFY_HEAP
2189 // If a GC was caused while constructing this object, the elements pointer
2190 // may point to a one pointer filler map. The object won't be rooted, but
2191 // our heap verification code could stumble across it.
2192 bool ElementsAreSafeToExamine();
2193#endif
2194
2195 Object* SlowReverseLookup(Object* value);
Steve Block8defd9f2010-07-08 12:39:36 +01002196
Leon Clarkee46be812010-01-19 14:06:41 +00002197 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
2198 // Also maximal value of JSArray's length property.
2199 static const uint32_t kMaxElementCount = 0xffffffffu;
2200
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002201 // Constants for heuristics controlling conversion of fast elements
2202 // to slow elements.
2203
2204 // Maximal gap that can be introduced by adding an element beyond
2205 // the current elements length.
Steve Blocka7e24c12009-10-30 11:49:00 +00002206 static const uint32_t kMaxGap = 1024;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002207
2208 // Maximal length of fast elements array that won't be checked for
2209 // being dense enough on expansion.
2210 static const int kMaxUncheckedFastElementsLength = 5000;
2211
2212 // Same as above but for old arrays. This limit is more strict. We
2213 // don't want to be wasteful with long lived objects.
2214 static const int kMaxUncheckedOldFastElementsLength = 500;
2215
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002216 // Note that Page::kMaxRegularHeapObjectSize puts a limit on
2217 // permissible values (see the DCHECK in heap.cc).
Steve Blocka7e24c12009-10-30 11:49:00 +00002218 static const int kInitialMaxFastElementArray = 100000;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219
2220 // This constant applies only to the initial map of "$Object" aka
2221 // "global.Object" and not to arbitrary other JSObject maps.
2222 static const int kInitialGlobalObjectUnusedPropertiesCount = 4;
2223
Steve Blocka7e24c12009-10-30 11:49:00 +00002224 static const int kMaxInstanceSize = 255 * kPointerSize;
2225 // When extending the backing storage for property values, we increase
2226 // its size by more than the 1 entry necessary, so sequentially adding fields
2227 // to the same object requires fewer allocations and copies.
2228 static const int kFieldsAdded = 3;
2229
2230 // Layout description.
2231 static const int kPropertiesOffset = HeapObject::kHeaderSize;
2232 static const int kElementsOffset = kPropertiesOffset + kPointerSize;
2233 static const int kHeaderSize = kElementsOffset + kPointerSize;
2234
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002235 STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00002236
Iain Merrick75681382010-08-19 15:07:18 +01002237 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
2238 public:
2239 static inline int SizeOf(Map* map, HeapObject* object);
2240 };
2241
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002242 Context* GetCreationContext();
2243
2244 // Enqueue change record for Object.observe. May cause GC.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002245 MUST_USE_RESULT static MaybeHandle<Object> EnqueueChangeRecord(
2246 Handle<JSObject> object, const char* type, Handle<Name> name,
2247 Handle<Object> old_value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248
Steve Blocka7e24c12009-10-30 11:49:00 +00002249 private:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002250 friend class DictionaryElementsAccessor;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002251 friend class JSReceiver;
2252 friend class Object;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002253
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002254 static void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map);
2255 static void MigrateFastToSlow(Handle<JSObject> object,
2256 Handle<Map> new_map,
2257 int expected_additional_properties);
2258
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002259 static void UpdateAllocationSite(Handle<JSObject> object,
2260 ElementsKind to_kind);
2261
2262 // Used from Object::GetProperty().
2263 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck(
2264 LookupIterator* it);
2265
2266 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithCallback(
2267 Handle<JSObject> object,
2268 Handle<Object> receiver,
2269 Handle<Object> structure,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002270 uint32_t index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002271 Handle<Object> holder);
2272
2273 MUST_USE_RESULT static Maybe<PropertyAttributes>
2274 GetElementAttributeWithInterceptor(Handle<JSObject> object,
2275 Handle<JSReceiver> receiver,
2276 uint32_t index, bool continue_search);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002277
2278 // Queries indexed interceptor on an object for property attributes.
2279 //
2280 // We determine property attributes as follows:
2281 // - if interceptor has a query callback, then the property attributes are
2282 // the result of query callback for index.
2283 // - otherwise if interceptor has a getter callback and it returns
2284 // non-empty value on index, then the property attributes is NONE
2285 // (property is present, and it is enumerable, configurable, writable)
2286 // - otherwise there are no property attributes that can be inferred for
2287 // interceptor, and this function returns ABSENT.
2288 MUST_USE_RESULT static Maybe<PropertyAttributes>
2289 GetElementAttributeFromInterceptor(Handle<JSObject> object,
2290 Handle<Object> receiver,
2291 uint32_t index);
2292
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002293 MUST_USE_RESULT static Maybe<PropertyAttributes>
2294 GetElementAttributeWithoutInterceptor(Handle<JSObject> object,
2295 Handle<JSReceiver> receiver,
2296 uint32_t index,
2297 bool continue_search);
2298 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002299 Handle<Object> object, Handle<Object> structure, uint32_t index,
2300 Handle<Object> value, Handle<JSObject> holder, StrictMode strict_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002301 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor(
2302 Handle<JSObject> object,
2303 uint32_t index,
2304 Handle<Object> value,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002305 PropertyAttributes attributes,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002306 StrictMode strict_mode,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002307 bool check_prototype,
2308 SetPropertyMode set_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002309 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithoutInterceptor(
2310 Handle<JSObject> object,
Steve Block9fac8402011-05-12 15:51:54 +01002311 uint32_t index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002312 Handle<Object> value,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002313 PropertyAttributes attributes,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002314 StrictMode strict_mode,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002315 bool check_prototype,
2316 SetPropertyMode set_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002317 MUST_USE_RESULT
2318 static MaybeHandle<Object> SetElementWithCallbackSetterInPrototypes(
2319 Handle<JSObject> object,
2320 uint32_t index,
2321 Handle<Object> value,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002322 bool* found,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002323 StrictMode strict_mode);
2324 MUST_USE_RESULT static MaybeHandle<Object> SetDictionaryElement(
2325 Handle<JSObject> object,
2326 uint32_t index,
2327 Handle<Object> value,
2328 PropertyAttributes attributes,
2329 StrictMode strict_mode,
2330 bool check_prototype,
2331 SetPropertyMode set_mode = SET_PROPERTY);
2332 MUST_USE_RESULT static MaybeHandle<Object> SetFastDoubleElement(
2333 Handle<JSObject> object,
2334 uint32_t index,
2335 Handle<Object> value,
2336 StrictMode strict_mode,
2337 bool check_prototype = true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002338 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithFailedAccessCheck(
2339 Isolate* isolate, Handle<JSObject> object, Handle<Object> receiver,
2340 uint32_t index);
2341 MUST_USE_RESULT static Maybe<PropertyAttributes>
2342 GetElementAttributesWithFailedAccessCheck(Isolate* isolate,
2343 Handle<JSObject> object,
2344 Handle<Object> receiver,
2345 uint32_t index);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002346
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002347 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck(
2348 LookupIterator* it, Handle<Object> value, StrictMode strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002349
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002350 // Add a property to a slow-case object.
2351 static void AddSlowProperty(Handle<JSObject> object,
2352 Handle<Name> name,
2353 Handle<Object> value,
2354 PropertyAttributes attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +00002355
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002356 MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty(
2357 Handle<JSObject> object,
2358 Handle<Name> name,
2359 DeleteMode mode);
2360 MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor(
2361 Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name);
2362
2363 // Deletes the named property in a normalized object.
2364 static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object,
2365 Handle<Name> name,
2366 DeleteMode mode);
2367
2368 MUST_USE_RESULT static MaybeHandle<Object> DeleteElement(
2369 Handle<JSObject> object,
2370 uint32_t index,
2371 DeleteMode mode);
2372 MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithInterceptor(
2373 Handle<JSObject> object,
2374 uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002375
2376 bool ReferencesObjectFromElements(FixedArray* elements,
2377 ElementsKind kind,
2378 Object* object);
Steve Blocka7e24c12009-10-30 11:49:00 +00002379
2380 // Returns true if most of the elements backing storage is used.
2381 bool HasDenseElements();
2382
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002383 // Gets the current elements capacity and the number of used elements.
2384 void GetElementsCapacityAndUsage(int* capacity, int* used);
2385
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002386 static bool CanSetCallback(Handle<JSObject> object, Handle<Name> name);
2387 static void SetElementCallback(Handle<JSObject> object,
2388 uint32_t index,
2389 Handle<Object> structure,
2390 PropertyAttributes attributes);
2391 static void SetPropertyCallback(Handle<JSObject> object,
2392 Handle<Name> name,
2393 Handle<Object> structure,
2394 PropertyAttributes attributes);
2395 static void DefineElementAccessor(Handle<JSObject> object,
2396 uint32_t index,
2397 Handle<Object> getter,
2398 Handle<Object> setter,
2399 PropertyAttributes attributes);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00002400
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002401 // Return the hash table backing store or the inline stored identity hash,
2402 // whatever is found.
2403 MUST_USE_RESULT Object* GetHiddenPropertiesHashTable();
2404
2405 // Return the hash table backing store for hidden properties. If there is no
2406 // backing store, allocate one.
2407 static Handle<ObjectHashTable> GetOrCreateHiddenPropertiesHashtable(
2408 Handle<JSObject> object);
2409
2410 // Set the hidden property backing store to either a hash table or
2411 // the inline-stored identity hash.
2412 static Handle<Object> SetHiddenPropertiesHashTable(
2413 Handle<JSObject> object,
2414 Handle<Object> value);
2415
2416 MUST_USE_RESULT Object* GetIdentityHash();
2417
2418 static Handle<Smi> GetOrCreateIdentityHash(Handle<JSObject> object);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002419
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002420 static Handle<SeededNumberDictionary> GetNormalizedElementDictionary(
2421 Handle<JSObject> object);
2422
2423 // Helper for fast versions of preventExtensions, seal, and freeze.
2424 // attrs is one of NONE, SEALED, or FROZEN (depending on the operation).
2425 template <PropertyAttributes attrs>
2426 MUST_USE_RESULT static MaybeHandle<Object> PreventExtensionsWithTransition(
2427 Handle<JSObject> object);
2428
Steve Blocka7e24c12009-10-30 11:49:00 +00002429 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject);
2430};
2431
2432
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002433// Common superclass for FixedArrays that allow implementations to share
2434// common accessors and some code paths.
2435class FixedArrayBase: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00002436 public:
2437 // [length]: length of the array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 inline int length() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00002439 inline void set_length(int value);
2440
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002441 // Get and set the length using acquire loads and release stores.
2442 inline int synchronized_length() const;
2443 inline void synchronized_set_length(int value);
2444
2445 DECLARE_CAST(FixedArrayBase)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002446
2447 // Layout description.
2448 // Length is smi tagged when it is stored.
2449 static const int kLengthOffset = HeapObject::kHeaderSize;
2450 static const int kHeaderSize = kLengthOffset + kPointerSize;
2451};
2452
2453
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002454class FixedDoubleArray;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002455class IncrementalMarking;
2456
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002457
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002458// FixedArray describes fixed-sized arrays with element type Object*.
2459class FixedArray: public FixedArrayBase {
2460 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00002461 // Setter and getter for elements.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002462 inline Object* get(int index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002463 static inline Handle<Object> get(Handle<FixedArray> array, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002464 // Setter that uses write barrier.
2465 inline void set(int index, Object* value);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002466 inline bool is_the_hole(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00002467
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 // Setter that doesn't need write barrier.
Steve Blocka7e24c12009-10-30 11:49:00 +00002469 inline void set(int index, Smi* value);
2470 // Setter with explicit barrier mode.
2471 inline void set(int index, Object* value, WriteBarrierMode mode);
2472
2473 // Setters for frequently used oddballs located in old space.
2474 inline void set_undefined(int index);
2475 inline void set_null(int index);
2476 inline void set_the_hole(int index);
2477
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002478 inline Object** GetFirstElementAddress();
2479 inline bool ContainsOnlySmisOrHoles();
2480
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002481 // Gives access to raw memory which stores the array's data.
2482 inline Object** data_start();
2483
2484 inline void FillWithHoles(int from, int to);
2485
2486 // Shrink length and insert filler objects.
2487 void Shrink(int length);
2488
2489 // Copy operation.
2490 static Handle<FixedArray> CopySize(Handle<FixedArray> array,
2491 int new_length,
2492 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00002493
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002494 enum KeyFilter { ALL_KEYS, NON_SYMBOL_KEYS };
2495
Steve Blocka7e24c12009-10-30 11:49:00 +00002496 // Add the elements of a JSArray to this FixedArray.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497 MUST_USE_RESULT static MaybeHandle<FixedArray> AddKeysFromArrayLike(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002498 Handle<FixedArray> content, Handle<JSObject> array,
2499 KeyFilter filter = ALL_KEYS);
Steve Blocka7e24c12009-10-30 11:49:00 +00002500
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002501 // Computes the union of keys and return the result.
2502 // Used for implementing "for (n in object) { }"
2503 MUST_USE_RESULT static MaybeHandle<FixedArray> UnionOfKeys(
2504 Handle<FixedArray> first,
2505 Handle<FixedArray> second);
Steve Blocka7e24c12009-10-30 11:49:00 +00002506
2507 // Copy a sub array from the receiver to dest.
2508 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
2509
2510 // Garbage collection support.
2511 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; }
2512
2513 // Code Generation support.
2514 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2515
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002516 // Garbage collection support.
2517 Object** RawFieldOfElementAt(int index) {
2518 return HeapObject::RawField(this, OffsetOfElementAt(index));
2519 }
2520
2521 DECLARE_CAST(FixedArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002522
Leon Clarkee46be812010-01-19 14:06:41 +00002523 // Maximal allowed size, in bytes, of a single FixedArray.
2524 // Prevents overflowing size computations, as well as extreme memory
2525 // consumption.
Ben Murdoch692be652012-01-10 18:47:50 +00002526 static const int kMaxSize = 128 * MB * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00002527 // Maximally allowed length of a FixedArray.
2528 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002529
2530 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002531 DECLARE_PRINTER(FixedArray)
2532 DECLARE_VERIFIER(FixedArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00002533#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +00002534 // Checks if two FixedArrays have identical contents.
2535 bool IsEqualTo(FixedArray* other);
2536#endif
2537
2538 // Swap two elements in a pair of arrays. If this array and the
2539 // numbers array are the same object, the elements are only swapped
2540 // once.
2541 void SwapPairs(FixedArray* numbers, int i, int j);
2542
2543 // Sort prefix of this array and the numbers array as pairs wrt. the
2544 // numbers. If the numbers array and the this array are the same
2545 // object, the prefix of this array is sorted.
2546 void SortPairs(FixedArray* numbers, uint32_t len);
2547
Iain Merrick75681382010-08-19 15:07:18 +01002548 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> {
2549 public:
2550 static inline int SizeOf(Map* map, HeapObject* object) {
2551 return SizeFor(reinterpret_cast<FixedArray*>(object)->length());
2552 }
2553 };
2554
Steve Blocka7e24c12009-10-30 11:49:00 +00002555 protected:
Leon Clarke4515c472010-02-03 11:58:03 +00002556 // Set operation on FixedArray without using write barriers. Can
2557 // only be used for storing old space objects or smis.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002558 static inline void NoWriteBarrierSet(FixedArray* array,
2559 int index,
2560 Object* value);
2561
2562 // Set operation on FixedArray without incremental write barrier. Can
2563 // only be used if the object is guaranteed to be white (whiteness witness
2564 // is present).
2565 static inline void NoIncrementalWriteBarrierSet(FixedArray* array,
2566 int index,
2567 Object* value);
Ben Murdochc7cc0282012-03-05 14:35:55 +00002568
Steve Blocka7e24c12009-10-30 11:49:00 +00002569 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002570 STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
2571
Steve Blocka7e24c12009-10-30 11:49:00 +00002572 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
2573};
2574
2575
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002576// FixedDoubleArray describes fixed-sized arrays with element type double.
2577class FixedDoubleArray: public FixedArrayBase {
2578 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002579 // Setter and getter for elements.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00002580 inline double get_scalar(int index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002581 inline int64_t get_representation(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002582 static inline Handle<Object> get(Handle<FixedDoubleArray> array, int index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002583 inline void set(int index, double value);
2584 inline void set_the_hole(int index);
2585
2586 // Checking for the hole.
2587 inline bool is_the_hole(int index);
2588
2589 // Garbage collection support.
2590 inline static int SizeFor(int length) {
2591 return kHeaderSize + length * kDoubleSize;
2592 }
2593
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002594 // Gives access to raw memory which stores the array's data.
2595 inline double* data_start();
2596
2597 inline void FillWithHoles(int from, int to);
2598
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002599 // Code Generation support.
2600 static int OffsetOfElementAt(int index) { return SizeFor(index); }
2601
2602 inline static bool is_the_hole_nan(double value);
2603 inline static double hole_nan_as_double();
2604 inline static double canonical_not_the_hole_nan_as_double();
2605
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002606 DECLARE_CAST(FixedDoubleArray)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002607
2608 // Maximal allowed size, in bytes, of a single FixedDoubleArray.
2609 // Prevents overflowing size computations, as well as extreme memory
2610 // consumption.
2611 static const int kMaxSize = 512 * MB;
2612 // Maximally allowed length of a FixedArray.
2613 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
2614
2615 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002616 DECLARE_PRINTER(FixedDoubleArray)
2617 DECLARE_VERIFIER(FixedDoubleArray)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002618
2619 private:
2620 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray);
2621};
2622
2623
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002624class WeakFixedArray : public FixedArray {
2625 public:
2626 enum SearchForDuplicates { kAlwaysAdd, kAddIfNotFound };
2627
2628 // If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated.
2629 static Handle<WeakFixedArray> Add(
2630 Handle<Object> maybe_array, Handle<HeapObject> value,
2631 SearchForDuplicates search_for_duplicates = kAlwaysAdd);
2632
2633 void Remove(Handle<HeapObject> value);
2634
2635 inline Object* Get(int index) const;
2636 inline int Length() const;
2637
2638 DECLARE_CAST(WeakFixedArray)
2639
2640 private:
2641 static const int kLastUsedIndexIndex = 0;
2642 static const int kFirstIndex = 1;
2643
2644 static Handle<WeakFixedArray> Allocate(
2645 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from);
2646
2647 static void Set(Handle<WeakFixedArray> array, int index,
2648 Handle<HeapObject> value);
2649 inline void clear(int index);
2650 inline bool IsEmptySlot(int index) const;
2651
2652 inline int last_used_index() const;
2653 inline void set_last_used_index(int index);
2654
2655 // Disallow inherited setters.
2656 void set(int index, Smi* value);
2657 void set(int index, Object* value);
2658 void set(int index, Object* value, WriteBarrierMode mode);
2659 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray);
2660};
2661
2662
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002663// ConstantPoolArray describes a fixed-sized array containing constant pool
2664// entries.
2665//
2666// A ConstantPoolArray can be structured in two different ways depending upon
2667// whether it is extended or small. The is_extended_layout() method can be used
2668// to discover which layout the constant pool has.
2669//
2670// The format of a small constant pool is:
2671// [kSmallLayout1Offset] : Small section layout bitmap 1
2672// [kSmallLayout2Offset] : Small section layout bitmap 2
2673// [first_index(INT64, SMALL_SECTION)] : 64 bit entries
2674// ... : ...
2675// [first_index(CODE_PTR, SMALL_SECTION)] : code pointer entries
2676// ... : ...
2677// [first_index(HEAP_PTR, SMALL_SECTION)] : heap pointer entries
2678// ... : ...
2679// [first_index(INT32, SMALL_SECTION)] : 32 bit entries
2680// ... : ...
2681//
2682// If the constant pool has an extended layout, the extended section constant
2683// pool also contains an extended section, which has the following format at
2684// location get_extended_section_header_offset():
2685// [kExtendedInt64CountOffset] : count of extended 64 bit entries
2686// [kExtendedCodePtrCountOffset] : count of extended code pointers
2687// [kExtendedHeapPtrCountOffset] : count of extended heap pointers
2688// [kExtendedInt32CountOffset] : count of extended 32 bit entries
2689// [first_index(INT64, EXTENDED_SECTION)] : 64 bit entries
2690// ... : ...
2691// [first_index(CODE_PTR, EXTENDED_SECTION)]: code pointer entries
2692// ... : ...
2693// [first_index(HEAP_PTR, EXTENDED_SECTION)]: heap pointer entries
2694// ... : ...
2695// [first_index(INT32, EXTENDED_SECTION)] : 32 bit entries
2696// ... : ...
2697//
2698class ConstantPoolArray: public HeapObject {
2699 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002700 enum WeakObjectState { NO_WEAK_OBJECTS, WEAK_OBJECTS_IN_OPTIMIZED_CODE };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002701
2702 enum Type {
2703 INT64 = 0,
2704 CODE_PTR,
2705 HEAP_PTR,
2706 INT32,
2707 // Number of types stored by the ConstantPoolArrays.
2708 NUMBER_OF_TYPES,
2709 FIRST_TYPE = INT64,
2710 LAST_TYPE = INT32
2711 };
2712
2713 enum LayoutSection {
2714 SMALL_SECTION = 0,
2715 EXTENDED_SECTION,
2716 NUMBER_OF_LAYOUT_SECTIONS
2717 };
2718
2719 class NumberOfEntries BASE_EMBEDDED {
2720 public:
2721 inline NumberOfEntries() {
2722 for (int i = 0; i < NUMBER_OF_TYPES; i++) {
2723 element_counts_[i] = 0;
2724 }
2725 }
2726
2727 inline NumberOfEntries(int int64_count, int code_ptr_count,
2728 int heap_ptr_count, int int32_count) {
2729 element_counts_[INT64] = int64_count;
2730 element_counts_[CODE_PTR] = code_ptr_count;
2731 element_counts_[HEAP_PTR] = heap_ptr_count;
2732 element_counts_[INT32] = int32_count;
2733 }
2734
2735 inline NumberOfEntries(ConstantPoolArray* array, LayoutSection section) {
2736 element_counts_[INT64] = array->number_of_entries(INT64, section);
2737 element_counts_[CODE_PTR] = array->number_of_entries(CODE_PTR, section);
2738 element_counts_[HEAP_PTR] = array->number_of_entries(HEAP_PTR, section);
2739 element_counts_[INT32] = array->number_of_entries(INT32, section);
2740 }
2741
2742 inline void increment(Type type);
2743 inline int equals(const NumberOfEntries& other) const;
2744 inline bool is_empty() const;
2745 inline int count_of(Type type) const;
2746 inline int base_of(Type type) const;
2747 inline int total_count() const;
2748 inline int are_in_range(int min, int max) const;
2749
2750 private:
2751 int element_counts_[NUMBER_OF_TYPES];
2752 };
2753
2754 class Iterator BASE_EMBEDDED {
2755 public:
2756 inline Iterator(ConstantPoolArray* array, Type type)
2757 : array_(array),
2758 type_(type),
2759 final_section_(array->final_section()),
2760 current_section_(SMALL_SECTION),
2761 next_index_(array->first_index(type, SMALL_SECTION)) {
2762 update_section();
2763 }
2764
2765 inline Iterator(ConstantPoolArray* array, Type type, LayoutSection section)
2766 : array_(array),
2767 type_(type),
2768 final_section_(section),
2769 current_section_(section),
2770 next_index_(array->first_index(type, section)) {
2771 update_section();
2772 }
2773
2774 inline int next_index();
2775 inline bool is_finished();
2776
2777 private:
2778 inline void update_section();
2779 ConstantPoolArray* array_;
2780 const Type type_;
2781 const LayoutSection final_section_;
2782
2783 LayoutSection current_section_;
2784 int next_index_;
2785 };
2786
2787 // Getters for the first index, the last index and the count of entries of
2788 // a given type for a given layout section.
2789 inline int first_index(Type type, LayoutSection layout_section);
2790 inline int last_index(Type type, LayoutSection layout_section);
2791 inline int number_of_entries(Type type, LayoutSection layout_section);
2792
2793 // Returns the type of the entry at the given index.
2794 inline Type get_type(int index);
2795 inline bool offset_is_type(int offset, Type type);
2796
2797 // Setter and getter for pool elements.
2798 inline Address get_code_ptr_entry(int index);
2799 inline Object* get_heap_ptr_entry(int index);
2800 inline int64_t get_int64_entry(int index);
2801 inline int32_t get_int32_entry(int index);
2802 inline double get_int64_entry_as_double(int index);
2803
2804 inline void set(int index, Address value);
2805 inline void set(int index, Object* value);
2806 inline void set(int index, int64_t value);
2807 inline void set(int index, double value);
2808 inline void set(int index, int32_t value);
2809
2810 // Setters which take a raw offset rather than an index (for code generation).
2811 inline void set_at_offset(int offset, int32_t value);
2812 inline void set_at_offset(int offset, int64_t value);
2813 inline void set_at_offset(int offset, double value);
2814 inline void set_at_offset(int offset, Address value);
2815 inline void set_at_offset(int offset, Object* value);
2816
2817 // Setter and getter for weak objects state
2818 inline void set_weak_object_state(WeakObjectState state);
2819 inline WeakObjectState get_weak_object_state();
2820
2821 // Returns true if the constant pool has an extended layout, false if it has
2822 // only the small layout.
2823 inline bool is_extended_layout();
2824
2825 // Returns the last LayoutSection in this constant pool array.
2826 inline LayoutSection final_section();
2827
2828 // Set up initial state for a small layout constant pool array.
2829 inline void Init(const NumberOfEntries& small);
2830
2831 // Set up initial state for an extended layout constant pool array.
2832 inline void InitExtended(const NumberOfEntries& small,
2833 const NumberOfEntries& extended);
2834
2835 // Clears the pointer entries with GC safe values.
2836 void ClearPtrEntries(Isolate* isolate);
2837
2838 // returns the total number of entries in the constant pool array.
2839 inline int length();
2840
2841 // Garbage collection support.
2842 inline int size();
2843
2844
2845 inline static int MaxInt64Offset(int number_of_int64) {
2846 return kFirstEntryOffset + (number_of_int64 * kInt64Size);
2847 }
2848
2849 inline static int SizeFor(const NumberOfEntries& small) {
2850 int size = kFirstEntryOffset +
2851 (small.count_of(INT64) * kInt64Size) +
2852 (small.count_of(CODE_PTR) * kPointerSize) +
2853 (small.count_of(HEAP_PTR) * kPointerSize) +
2854 (small.count_of(INT32) * kInt32Size);
2855 return RoundUp(size, kPointerSize);
2856 }
2857
2858 inline static int SizeForExtended(const NumberOfEntries& small,
2859 const NumberOfEntries& extended) {
2860 int size = SizeFor(small);
2861 size = RoundUp(size, kInt64Size); // Align extended header to 64 bits.
2862 size += kExtendedFirstOffset +
2863 (extended.count_of(INT64) * kInt64Size) +
2864 (extended.count_of(CODE_PTR) * kPointerSize) +
2865 (extended.count_of(HEAP_PTR) * kPointerSize) +
2866 (extended.count_of(INT32) * kInt32Size);
2867 return RoundUp(size, kPointerSize);
2868 }
2869
2870 inline static int entry_size(Type type) {
2871 switch (type) {
2872 case INT32:
2873 return kInt32Size;
2874 case INT64:
2875 return kInt64Size;
2876 case CODE_PTR:
2877 case HEAP_PTR:
2878 return kPointerSize;
2879 default:
2880 UNREACHABLE();
2881 return 0;
2882 }
2883 }
2884
2885 // Code Generation support.
2886 inline int OffsetOfElementAt(int index) {
2887 int offset;
2888 LayoutSection section;
2889 if (is_extended_layout() && index >= first_extended_section_index()) {
2890 section = EXTENDED_SECTION;
2891 offset = get_extended_section_header_offset() + kExtendedFirstOffset;
2892 } else {
2893 section = SMALL_SECTION;
2894 offset = kFirstEntryOffset;
2895 }
2896
2897 // Add offsets for the preceding type sections.
2898 DCHECK(index <= last_index(LAST_TYPE, section));
2899 for (Type type = FIRST_TYPE; index > last_index(type, section);
2900 type = next_type(type)) {
2901 offset += entry_size(type) * number_of_entries(type, section);
2902 }
2903
2904 // Add offset for the index in it's type.
2905 Type type = get_type(index);
2906 offset += entry_size(type) * (index - first_index(type, section));
2907 return offset;
2908 }
2909
2910 DECLARE_CAST(ConstantPoolArray)
2911
2912 // Garbage collection support.
2913 Object** RawFieldOfElementAt(int index) {
2914 return HeapObject::RawField(this, OffsetOfElementAt(index));
2915 }
2916
2917 // Small Layout description.
2918 static const int kSmallLayout1Offset = HeapObject::kHeaderSize;
2919 static const int kSmallLayout2Offset = kSmallLayout1Offset + kInt32Size;
2920 static const int kHeaderSize = kSmallLayout2Offset + kInt32Size;
2921 static const int kFirstEntryOffset = ROUND_UP(kHeaderSize, kInt64Size);
2922
2923 static const int kSmallLayoutCountBits = 10;
2924 static const int kMaxSmallEntriesPerType = (1 << kSmallLayoutCountBits) - 1;
2925
2926 // Fields in kSmallLayout1Offset.
2927 class Int64CountField: public BitField<int, 1, kSmallLayoutCountBits> {};
2928 class CodePtrCountField: public BitField<int, 11, kSmallLayoutCountBits> {};
2929 class HeapPtrCountField: public BitField<int, 21, kSmallLayoutCountBits> {};
2930 class IsExtendedField: public BitField<bool, 31, 1> {};
2931
2932 // Fields in kSmallLayout2Offset.
2933 class Int32CountField: public BitField<int, 1, kSmallLayoutCountBits> {};
2934 class TotalCountField: public BitField<int, 11, 12> {};
2935 class WeakObjectStateField: public BitField<WeakObjectState, 23, 2> {};
2936
2937 // Extended layout description, which starts at
2938 // get_extended_section_header_offset().
2939 static const int kExtendedInt64CountOffset = 0;
2940 static const int kExtendedCodePtrCountOffset =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002941 kExtendedInt64CountOffset + kInt32Size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002942 static const int kExtendedHeapPtrCountOffset =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002943 kExtendedCodePtrCountOffset + kInt32Size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002944 static const int kExtendedInt32CountOffset =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002945 kExtendedHeapPtrCountOffset + kInt32Size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002946 static const int kExtendedFirstOffset =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002947 kExtendedInt32CountOffset + kInt32Size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002948
2949 // Dispatched behavior.
2950 void ConstantPoolIterateBody(ObjectVisitor* v);
2951
2952 DECLARE_PRINTER(ConstantPoolArray)
2953 DECLARE_VERIFIER(ConstantPoolArray)
2954
2955 private:
2956 inline int first_extended_section_index();
2957 inline int get_extended_section_header_offset();
2958
2959 inline static Type next_type(Type type) {
2960 DCHECK(type >= FIRST_TYPE && type < NUMBER_OF_TYPES);
2961 int type_int = static_cast<int>(type);
2962 return static_cast<Type>(++type_int);
2963 }
2964
2965 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray);
2966};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002967
2968
Steve Blocka7e24c12009-10-30 11:49:00 +00002969// DescriptorArrays are fixed arrays used to hold instance descriptors.
2970// The format of the these objects is:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002971// [0]: Number of descriptors
2972// [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array:
2973// [0]: pointer to fixed array with enum cache
2974// [1]: either Smi(0) or pointer to fixed array with indices
2975// [2]: first key
2976// [2 + number of descriptors * kDescriptorSize]: start of slack
Steve Blocka7e24c12009-10-30 11:49:00 +00002977class DescriptorArray: public FixedArray {
2978 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00002979 // Returns true for both shared empty_descriptor_array and for smis, which the
2980 // map uses to encode additional bit fields when the descriptor array is not
2981 // yet used.
Steve Blocka7e24c12009-10-30 11:49:00 +00002982 inline bool IsEmpty();
Leon Clarkee46be812010-01-19 14:06:41 +00002983
Steve Blocka7e24c12009-10-30 11:49:00 +00002984 // Returns the number of descriptors in the array.
2985 int number_of_descriptors() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002986 DCHECK(length() >= kFirstIndex || IsEmpty());
Steve Block44f0eee2011-05-26 01:26:41 +01002987 int len = length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002988 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00002989 }
2990
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002991 int number_of_descriptors_storage() {
2992 int len = length();
2993 return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00002994 }
2995
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002996 int NumberOfSlackDescriptors() {
2997 return number_of_descriptors_storage() - number_of_descriptors();
Steve Blocka7e24c12009-10-30 11:49:00 +00002998 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002999
3000 inline void SetNumberOfDescriptors(int number_of_descriptors);
3001 inline int number_of_entries() { return number_of_descriptors(); }
3002
Steve Blocka7e24c12009-10-30 11:49:00 +00003003 bool HasEnumCache() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003004 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi();
Steve Blocka7e24c12009-10-30 11:49:00 +00003005 }
3006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003007 void CopyEnumCacheFrom(DescriptorArray* array) {
3008 set(kEnumCacheIndex, array->get(kEnumCacheIndex));
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 }
3010
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003011 FixedArray* GetEnumCache() {
3012 DCHECK(HasEnumCache());
3013 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
3014 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex));
3015 }
3016
3017 bool HasEnumIndicesCache() {
3018 if (IsEmpty()) return false;
3019 Object* object = get(kEnumCacheIndex);
3020 if (object->IsSmi()) return false;
3021 FixedArray* bridge = FixedArray::cast(object);
3022 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi();
3023 }
3024
3025 FixedArray* GetEnumIndicesCache() {
3026 DCHECK(HasEnumIndicesCache());
3027 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex));
3028 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex));
3029 }
3030
3031 Object** GetEnumCacheSlot() {
3032 DCHECK(HasEnumCache());
3033 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
3034 kEnumCacheOffset);
3035 }
3036
3037 void ClearEnumCache();
Ben Murdoch257744e2011-11-30 15:57:28 +00003038
Steve Blocka7e24c12009-10-30 11:49:00 +00003039 // Initialize or change the enum cache,
3040 // using the supplied storage for the small "bridge".
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003041 void SetEnumCache(FixedArray* bridge_storage,
3042 FixedArray* new_cache,
3043 Object* new_index_cache);
Steve Blocka7e24c12009-10-30 11:49:00 +00003044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003045 bool CanHoldValue(int descriptor, Object* value);
3046
Steve Blocka7e24c12009-10-30 11:49:00 +00003047 // Accessors for fetching instance descriptor at descriptor number.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003048 inline Name* GetKey(int descriptor_number);
3049 inline Object** GetKeySlot(int descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003050 inline Object* GetValue(int descriptor_number);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003051 inline void SetValue(int descriptor_number, Object* value);
3052 inline Object** GetValueSlot(int descriptor_number);
3053 static inline int GetValueOffset(int descriptor_number);
3054 inline Object** GetDescriptorStartSlot(int descriptor_number);
3055 inline Object** GetDescriptorEndSlot(int descriptor_number);
3056 inline PropertyDetails GetDetails(int descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003057 inline PropertyType GetType(int descriptor_number);
3058 inline int GetFieldIndex(int descriptor_number);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003059 inline HeapType* GetFieldType(int descriptor_number);
3060 inline Object* GetConstant(int descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003061 inline Object* GetCallbacksObject(int descriptor_number);
3062 inline AccessorDescriptor* GetCallbacks(int descriptor_number);
Steve Blocka7e24c12009-10-30 11:49:00 +00003063
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003064 inline Name* GetSortedKey(int descriptor_number);
3065 inline int GetSortedKeyIndex(int descriptor_number);
3066 inline void SetSortedKey(int pointer, int descriptor_number);
3067 inline void SetRepresentation(int descriptor_number,
3068 Representation representation);
3069
3070 // Accessor for complete descriptor.
3071 inline void Get(int descriptor_number, Descriptor* desc);
3072 inline void Set(int descriptor_number, Descriptor* desc);
3073 void Replace(int descriptor_number, Descriptor* descriptor);
3074
3075 // Append automatically sets the enumeration index. This should only be used
3076 // to add descriptors in bulk at the end, followed by sorting the descriptor
3077 // array.
3078 inline void Append(Descriptor* desc);
3079
3080 static Handle<DescriptorArray> CopyUpTo(Handle<DescriptorArray> desc,
3081 int enumeration_index,
3082 int slack = 0);
3083
3084 static Handle<DescriptorArray> CopyUpToAddAttributes(
3085 Handle<DescriptorArray> desc,
3086 int enumeration_index,
3087 PropertyAttributes attributes,
3088 int slack = 0);
3089
3090 // Sort the instance descriptors by the hash codes of their keys.
3091 void Sort();
3092
3093 // Search the instance descriptors for given name.
3094 INLINE(int Search(Name* name, int number_of_own_descriptors));
3095
3096 // As the above, but uses DescriptorLookupCache and updates it when
3097 // necessary.
3098 INLINE(int SearchWithCache(Name* name, Map* map));
3099
3100 // Allocates a DescriptorArray, but returns the singleton
3101 // empty descriptor array object if number_of_descriptors is 0.
3102 static Handle<DescriptorArray> Allocate(Isolate* isolate,
3103 int number_of_descriptors,
3104 int slack = 0);
3105
3106 DECLARE_CAST(DescriptorArray)
3107
3108 // Constant for denoting key was not found.
3109 static const int kNotFound = -1;
3110
3111 static const int kDescriptorLengthIndex = 0;
3112 static const int kEnumCacheIndex = 1;
3113 static const int kFirstIndex = 2;
3114
3115 // The length of the "bridge" to the enum cache.
3116 static const int kEnumCacheBridgeLength = 2;
3117 static const int kEnumCacheBridgeCacheIndex = 0;
3118 static const int kEnumCacheBridgeIndicesCacheIndex = 1;
3119
3120 // Layout description.
3121 static const int kDescriptorLengthOffset = FixedArray::kHeaderSize;
3122 static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize;
3123 static const int kFirstOffset = kEnumCacheOffset + kPointerSize;
3124
3125 // Layout description for the bridge array.
3126 static const int kEnumCacheBridgeCacheOffset = FixedArray::kHeaderSize;
3127
3128 // Layout of descriptor.
3129 static const int kDescriptorKey = 0;
3130 static const int kDescriptorDetails = 1;
3131 static const int kDescriptorValue = 2;
3132 static const int kDescriptorSize = 3;
3133
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003134#if defined(DEBUG) || defined(OBJECT_PRINT)
3135 // For our gdb macros, we should perhaps change these in the future.
3136 void Print();
3137
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003138 // Print all the descriptors.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003139 void PrintDescriptors(std::ostream& os); // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003140#endif
3141
3142#ifdef DEBUG
3143 // Is the descriptor array sorted and without duplicates?
3144 bool IsSortedNoDuplicates(int valid_descriptors = -1);
3145
3146 // Is the descriptor array consistent with the back pointers in targets?
3147 bool IsConsistentWithBackPointers(Map* current_map);
3148
3149 // Are two DescriptorArrays equal?
3150 bool IsEqualTo(DescriptorArray* other);
3151#endif
3152
3153 // Returns the fixed array length required to hold number_of_descriptors
3154 // descriptors.
3155 static int LengthFor(int number_of_descriptors) {
3156 return ToKeyIndex(number_of_descriptors);
3157 }
3158
3159 private:
3160 // WhitenessWitness is used to prove that a descriptor array is white
3161 // (unmarked), so incremental write barriers can be skipped because the
3162 // marking invariant cannot be broken and slots pointing into evacuation
3163 // candidates will be discovered when the object is scanned. A witness is
3164 // always stack-allocated right after creating an array. By allocating a
3165 // witness, incremental marking is globally disabled. The witness is then
3166 // passed along wherever needed to statically prove that the array is known to
3167 // be white.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003168 class WhitenessWitness {
3169 public:
3170 inline explicit WhitenessWitness(DescriptorArray* array);
3171 inline ~WhitenessWitness();
3172
3173 private:
3174 IncrementalMarking* marking_;
3175 };
3176
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003177 // An entry in a DescriptorArray, represented as an (array, index) pair.
3178 class Entry {
3179 public:
3180 inline explicit Entry(DescriptorArray* descs, int index) :
3181 descs_(descs), index_(index) { }
3182
3183 inline PropertyType type() { return descs_->GetType(index_); }
3184 inline Object* GetCallbackObject() { return descs_->GetValue(index_); }
3185
3186 private:
3187 DescriptorArray* descs_;
3188 int index_;
3189 };
3190
Steve Blocka7e24c12009-10-30 11:49:00 +00003191 // Conversion from descriptor number to array indices.
3192 static int ToKeyIndex(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003193 return kFirstIndex +
3194 (descriptor_number * kDescriptorSize) +
3195 kDescriptorKey;
Steve Blocka7e24c12009-10-30 11:49:00 +00003196 }
Leon Clarkee46be812010-01-19 14:06:41 +00003197
3198 static int ToDetailsIndex(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003199 return kFirstIndex +
3200 (descriptor_number * kDescriptorSize) +
3201 kDescriptorDetails;
Leon Clarkee46be812010-01-19 14:06:41 +00003202 }
3203
Steve Blocka7e24c12009-10-30 11:49:00 +00003204 static int ToValueIndex(int descriptor_number) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003205 return kFirstIndex +
3206 (descriptor_number * kDescriptorSize) +
3207 kDescriptorValue;
Steve Blocka7e24c12009-10-30 11:49:00 +00003208 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003209
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003210 // Transfer a complete descriptor from the src descriptor array to this
3211 // descriptor array.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003212 void CopyFrom(int index, DescriptorArray* src, const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00003213
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003214 inline void Set(int descriptor_number,
3215 Descriptor* desc,
3216 const WhitenessWitness&);
Steve Blocka7e24c12009-10-30 11:49:00 +00003217
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003218 // Swap first and second descriptor.
3219 inline void SwapSortedKeys(int first, int second);
3220
Steve Blocka7e24c12009-10-30 11:49:00 +00003221 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray);
3222};
3223
3224
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003225enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
3226
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003227template <SearchMode search_mode, typename T>
3228inline int Search(T* array, Name* name, int valid_entries = 0,
3229 int* out_insertion_index = NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003230
3231
Steve Blocka7e24c12009-10-30 11:49:00 +00003232// HashTable is a subclass of FixedArray that implements a hash table
3233// that uses open addressing and quadratic probing.
3234//
3235// In order for the quadratic probing to work, elements that have not
3236// yet been used and elements that have been deleted are
3237// distinguished. Probing continues when deleted elements are
3238// encountered and stops when unused elements are encountered.
3239//
3240// - Elements with key == undefined have not been used yet.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003241// - Elements with key == the_hole have been deleted.
Steve Blocka7e24c12009-10-30 11:49:00 +00003242//
3243// The hash table class is parameterized with a Shape and a Key.
3244// Shape must be a class with the following interface:
3245// class ExampleShape {
3246// public:
3247// // Tells whether key matches other.
3248// static bool IsMatch(Key key, Object* other);
3249// // Returns the hash value for key.
3250// static uint32_t Hash(Key key);
3251// // Returns the hash value for object.
3252// static uint32_t HashForObject(Key key, Object* object);
3253// // Convert key to an object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003254// static inline Handle<Object> AsHandle(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003255// // The prefix size indicates number of elements in the beginning
3256// // of the backing storage.
3257// static const int kPrefixSize = ..;
3258// // The Element size indicates number of elements per entry.
3259// static const int kEntrySize = ..;
3260// };
Steve Block3ce2e202009-11-05 08:53:23 +00003261// The prefix size indicates an amount of memory in the
Steve Blocka7e24c12009-10-30 11:49:00 +00003262// beginning of the backing storage that can be used for non-element
3263// information by subclasses.
3264
Ben Murdochc7cc0282012-03-05 14:35:55 +00003265template<typename Key>
3266class BaseShape {
3267 public:
3268 static const bool UsesSeed = false;
3269 static uint32_t Hash(Key key) { return 0; }
3270 static uint32_t SeededHash(Key key, uint32_t seed) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003271 DCHECK(UsesSeed);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003272 return Hash(key);
3273 }
3274 static uint32_t HashForObject(Key key, Object* object) { return 0; }
3275 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003276 DCHECK(UsesSeed);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003277 return HashForObject(key, object);
3278 }
3279};
3280
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003281template<typename Derived, typename Shape, typename Key>
Steve Blocka7e24c12009-10-30 11:49:00 +00003282class HashTable: public FixedArray {
3283 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00003284 // Wrapper methods
3285 inline uint32_t Hash(Key key) {
3286 if (Shape::UsesSeed) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003287 return Shape::SeededHash(key, GetHeap()->HashSeed());
Ben Murdochc7cc0282012-03-05 14:35:55 +00003288 } else {
3289 return Shape::Hash(key);
3290 }
3291 }
3292
3293 inline uint32_t HashForObject(Key key, Object* object) {
3294 if (Shape::UsesSeed) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003295 return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003296 } else {
3297 return Shape::HashForObject(key, object);
3298 }
3299 }
3300
Steve Block3ce2e202009-11-05 08:53:23 +00003301 // Returns the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00003302 int NumberOfElements() {
3303 return Smi::cast(get(kNumberOfElementsIndex))->value();
3304 }
3305
Leon Clarkee46be812010-01-19 14:06:41 +00003306 // Returns the number of deleted elements in the hash table.
3307 int NumberOfDeletedElements() {
3308 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
3309 }
3310
Steve Block3ce2e202009-11-05 08:53:23 +00003311 // Returns the capacity of the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00003312 int Capacity() {
3313 return Smi::cast(get(kCapacityIndex))->value();
3314 }
3315
3316 // ElementAdded should be called whenever an element is added to a
Steve Block3ce2e202009-11-05 08:53:23 +00003317 // hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00003318 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); }
3319
3320 // ElementRemoved should be called whenever an element is removed from
Steve Block3ce2e202009-11-05 08:53:23 +00003321 // a hash table.
Leon Clarkee46be812010-01-19 14:06:41 +00003322 void ElementRemoved() {
3323 SetNumberOfElements(NumberOfElements() - 1);
3324 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1);
3325 }
3326 void ElementsRemoved(int n) {
3327 SetNumberOfElements(NumberOfElements() - n);
3328 SetNumberOfDeletedElements(NumberOfDeletedElements() + n);
3329 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003330
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003331 // Returns a new HashTable object.
3332 MUST_USE_RESULT static Handle<Derived> New(
3333 Isolate* isolate,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003334 int at_least_space_for,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003335 MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY,
Kristian Monsen80d68ea2010-09-08 11:05:35 +01003336 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003337
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003338 // Computes the required capacity for a table holding the given
3339 // number of elements. May be more than HashTable::kMaxCapacity.
3340 static int ComputeCapacity(int at_least_space_for);
3341
Steve Blocka7e24c12009-10-30 11:49:00 +00003342 // Returns the key at entry.
3343 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
3344
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003345 // Tells whether k is a real key. The hole and undefined are not allowed
Steve Blocka7e24c12009-10-30 11:49:00 +00003346 // as keys and can be used to indicate missing or deleted elements.
3347 bool IsKey(Object* k) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003348 return !k->IsTheHole() && !k->IsUndefined();
Steve Blocka7e24c12009-10-30 11:49:00 +00003349 }
3350
3351 // Garbage collection support.
3352 void IteratePrefix(ObjectVisitor* visitor);
3353 void IterateElements(ObjectVisitor* visitor);
3354
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003355 DECLARE_CAST(HashTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00003356
3357 // Compute the probe offset (quadratic probing).
3358 INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
3359 return (n + n * n) >> 1;
3360 }
3361
3362 static const int kNumberOfElementsIndex = 0;
Leon Clarkee46be812010-01-19 14:06:41 +00003363 static const int kNumberOfDeletedElementsIndex = 1;
3364 static const int kCapacityIndex = 2;
3365 static const int kPrefixStartIndex = 3;
3366 static const int kElementsStartIndex =
Steve Blocka7e24c12009-10-30 11:49:00 +00003367 kPrefixStartIndex + Shape::kPrefixSize;
Leon Clarkee46be812010-01-19 14:06:41 +00003368 static const int kEntrySize = Shape::kEntrySize;
3369 static const int kElementsStartOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00003370 kHeaderSize + kElementsStartIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01003371 static const int kCapacityOffset =
3372 kHeaderSize + kCapacityIndex * kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00003373
3374 // Constant used for denoting a absent entry.
3375 static const int kNotFound = -1;
3376
Leon Clarkee46be812010-01-19 14:06:41 +00003377 // Maximal capacity of HashTable. Based on maximal length of underlying
3378 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex
3379 // cannot overflow.
3380 static const int kMaxCapacity =
3381 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize;
3382
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003383 // Find entry for key otherwise return kNotFound.
Steve Block44f0eee2011-05-26 01:26:41 +01003384 inline int FindEntry(Key key);
3385 int FindEntry(Isolate* isolate, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003386
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003387 // Rehashes the table in-place.
3388 void Rehash(Key key);
3389
Steve Blocka7e24c12009-10-30 11:49:00 +00003390 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003391 friend class ObjectHashTable;
3392
Steve Blocka7e24c12009-10-30 11:49:00 +00003393 // Find the entry at which to insert element with the given key that
3394 // has the given hash value.
3395 uint32_t FindInsertionEntry(uint32_t hash);
3396
3397 // Returns the index for an entry (of the key)
3398 static inline int EntryToIndex(int entry) {
3399 return (entry * kEntrySize) + kElementsStartIndex;
3400 }
3401
Steve Block3ce2e202009-11-05 08:53:23 +00003402 // Update the number of elements in the hash table.
Steve Blocka7e24c12009-10-30 11:49:00 +00003403 void SetNumberOfElements(int nof) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003404 set(kNumberOfElementsIndex, Smi::FromInt(nof));
Steve Blocka7e24c12009-10-30 11:49:00 +00003405 }
3406
Leon Clarkee46be812010-01-19 14:06:41 +00003407 // Update the number of deleted elements in the hash table.
3408 void SetNumberOfDeletedElements(int nod) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003409 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
Leon Clarkee46be812010-01-19 14:06:41 +00003410 }
3411
Steve Blocka7e24c12009-10-30 11:49:00 +00003412 // Sets the capacity of the hash table.
3413 void SetCapacity(int capacity) {
3414 // To scale a computed hash code to fit within the hash table, we
3415 // use bit-wise AND with a mask, so the capacity must be positive
3416 // and non-zero.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003417 DCHECK(capacity > 0);
3418 DCHECK(capacity <= kMaxCapacity);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003419 set(kCapacityIndex, Smi::FromInt(capacity));
Steve Blocka7e24c12009-10-30 11:49:00 +00003420 }
3421
3422
3423 // Returns probe entry.
3424 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003425 DCHECK(base::bits::IsPowerOfTwo32(size));
Steve Blocka7e24c12009-10-30 11:49:00 +00003426 return (hash + GetProbeOffset(number)) & (size - 1);
3427 }
3428
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003429 inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
Leon Clarkee46be812010-01-19 14:06:41 +00003430 return hash & (size - 1);
3431 }
3432
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003433 inline static uint32_t NextProbe(
3434 uint32_t last, uint32_t number, uint32_t size) {
Leon Clarkee46be812010-01-19 14:06:41 +00003435 return (last + number) & (size - 1);
3436 }
3437
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003438 // Attempt to shrink hash table after removal of key.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003439 MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table, Key key);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003440
Steve Blocka7e24c12009-10-30 11:49:00 +00003441 // Ensure enough space for n additional elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003442 MUST_USE_RESULT static Handle<Derived> EnsureCapacity(
3443 Handle<Derived> table,
3444 int n,
3445 Key key,
3446 PretenureFlag pretenure = NOT_TENURED);
3447
3448 private:
3449 // Returns _expected_ if one of entries given by the first _probe_ probes is
3450 // equal to _expected_. Otherwise, returns the entry given by the probe
3451 // number _probe_.
3452 uint32_t EntryForProbe(Key key, Object* k, int probe, uint32_t expected);
3453
3454 void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode);
3455
3456 // Rehashes this hash-table into the new table.
3457 void Rehash(Handle<Derived> new_table, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003458};
3459
3460
Steve Blocka7e24c12009-10-30 11:49:00 +00003461// HashTableKey is an abstract superclass for virtual key behavior.
3462class HashTableKey {
3463 public:
3464 // Returns whether the other object matches this key.
3465 virtual bool IsMatch(Object* other) = 0;
3466 // Returns the hash value for this key.
3467 virtual uint32_t Hash() = 0;
3468 // Returns the hash value for object.
3469 virtual uint32_t HashForObject(Object* key) = 0;
Steve Block3ce2e202009-11-05 08:53:23 +00003470 // Returns the key object for storing into the hash table.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003471 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003472 // Required.
3473 virtual ~HashTableKey() {}
3474};
3475
Ben Murdochc7cc0282012-03-05 14:35:55 +00003476
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003477class StringTableShape : public BaseShape<HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00003478 public:
Steve Block44f0eee2011-05-26 01:26:41 +01003479 static inline bool IsMatch(HashTableKey* key, Object* value) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003480 return key->IsMatch(value);
3481 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003482
Steve Block44f0eee2011-05-26 01:26:41 +01003483 static inline uint32_t Hash(HashTableKey* key) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003484 return key->Hash();
3485 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003486
Steve Block44f0eee2011-05-26 01:26:41 +01003487 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003488 return key->HashForObject(object);
3489 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003490
3491 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003492
3493 static const int kPrefixSize = 0;
3494 static const int kEntrySize = 1;
3495};
3496
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003497class SeqOneByteString;
Ben Murdoch257744e2011-11-30 15:57:28 +00003498
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003499// StringTable.
Steve Blocka7e24c12009-10-30 11:49:00 +00003500//
3501// No special elements in the prefix and the element size is 1
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003502// because only the string itself (the key) needs to be stored.
3503class StringTable: public HashTable<StringTable,
3504 StringTableShape,
3505 HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00003506 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003507 // Find string in the string table. If it is not there yet, it is
3508 // added. The return value is the string found.
3509 static Handle<String> LookupString(Isolate* isolate, Handle<String> key);
3510 static Handle<String> LookupKey(Isolate* isolate, HashTableKey* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003511
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003512 // Tries to internalize given string and returns string handle on success
3513 // or an empty handle otherwise.
3514 MUST_USE_RESULT static MaybeHandle<String> InternalizeStringIfExists(
3515 Isolate* isolate,
3516 Handle<String> string);
Steve Blocka7e24c12009-10-30 11:49:00 +00003517
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003518 // Looks up a string that is equal to the given string and returns
3519 // string handle if it is found, or an empty handle otherwise.
3520 MUST_USE_RESULT static MaybeHandle<String> LookupStringIfExists(
3521 Isolate* isolate,
3522 Handle<String> str);
3523 MUST_USE_RESULT static MaybeHandle<String> LookupTwoCharsStringIfExists(
3524 Isolate* isolate,
3525 uint16_t c1,
3526 uint16_t c2);
3527
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003528 static void EnsureCapacityForDeserialization(Isolate* isolate, int expected);
3529
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003530 DECLARE_CAST(StringTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00003531
3532 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003533 template <bool seq_one_byte>
3534 friend class JsonParser;
Steve Blocka7e24c12009-10-30 11:49:00 +00003535
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003536 DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable);
Steve Blocka7e24c12009-10-30 11:49:00 +00003537};
3538
3539
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003540template <typename Derived, typename Shape, typename Key>
3541class Dictionary: public HashTable<Derived, Shape, Key> {
3542 protected:
3543 typedef HashTable<Derived, Shape, Key> DerivedHashTable;
Steve Blocka7e24c12009-10-30 11:49:00 +00003544
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003545 public:
Steve Blocka7e24c12009-10-30 11:49:00 +00003546 // Returns the value at entry.
3547 Object* ValueAt(int entry) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003548 return this->get(DerivedHashTable::EntryToIndex(entry) + 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00003549 }
3550
3551 // Set the value for entry.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003552 void ValueAtPut(int entry, Object* value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003553 this->set(DerivedHashTable::EntryToIndex(entry) + 1, value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003554 }
3555
3556 // Returns the property details for the property at entry.
3557 PropertyDetails DetailsAt(int entry) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003558 DCHECK(entry >= 0); // Not found is -1, which is not caught by get().
Steve Blocka7e24c12009-10-30 11:49:00 +00003559 return PropertyDetails(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003560 Smi::cast(this->get(DerivedHashTable::EntryToIndex(entry) + 2)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003561 }
3562
3563 // Set the details for entry.
3564 void DetailsAtPut(int entry, PropertyDetails value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003565 this->set(DerivedHashTable::EntryToIndex(entry) + 2, value.AsSmi());
Steve Blocka7e24c12009-10-30 11:49:00 +00003566 }
3567
3568 // Sorting support
3569 void CopyValuesTo(FixedArray* elements);
3570
3571 // Delete a property from the dictionary.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003572 static Handle<Object> DeleteProperty(
3573 Handle<Derived> dictionary,
3574 int entry,
3575 JSObject::DeleteMode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003576
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003577 // Attempt to shrink the dictionary after deletion of key.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003578 MUST_USE_RESULT static inline Handle<Derived> Shrink(
3579 Handle<Derived> dictionary,
3580 Key key) {
3581 return DerivedHashTable::Shrink(dictionary, key);
3582 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003583
Steve Blocka7e24c12009-10-30 11:49:00 +00003584 // Returns the number of elements in the dictionary filtering out properties
3585 // with the specified attributes.
3586 int NumberOfElementsFilterAttributes(PropertyAttributes filter);
3587
3588 // Returns the number of enumerable elements in the dictionary.
3589 int NumberOfEnumElements();
3590
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003591 // Returns true if the dictionary contains any elements that are non-writable,
3592 // non-configurable, non-enumerable, or have getters/setters.
3593 bool HasComplexElements();
3594
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003595 enum SortMode { UNSORTED, SORTED };
Steve Blocka7e24c12009-10-30 11:49:00 +00003596 // Copies keys to preallocated fixed array.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003597 void CopyKeysTo(FixedArray* storage,
3598 PropertyAttributes filter,
3599 SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003600 // Fill in details for properties into storage.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003601 void CopyKeysTo(FixedArray* storage,
3602 int index,
3603 PropertyAttributes filter,
3604 SortMode sort_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +00003605
3606 // Accessors for next enumeration index.
3607 void SetNextEnumerationIndex(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003608 DCHECK(index != 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003609 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00003610 }
3611
3612 int NextEnumerationIndex() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003613 return Smi::cast(this->get(kNextEnumerationIndexIndex))->value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003614 }
3615
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003616 // Creates a new dictionary.
3617 MUST_USE_RESULT static Handle<Derived> New(
3618 Isolate* isolate,
3619 int at_least_space_for,
3620 PretenureFlag pretenure = NOT_TENURED);
Steve Blocka7e24c12009-10-30 11:49:00 +00003621
3622 // Ensure enough space for n additional elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003623 static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003624
Ben Murdochb0fe1622011-05-05 13:52:32 +01003625#ifdef OBJECT_PRINT
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003626 void Print(std::ostream& os); // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +00003627#endif
3628 // Returns the key (slow).
3629 Object* SlowReverseLookup(Object* value);
3630
3631 // Sets the entry to (key, value) pair.
3632 inline void SetEntry(int entry,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003633 Handle<Object> key,
3634 Handle<Object> value);
Ben Murdoch8b112d22011-06-08 16:22:53 +01003635 inline void SetEntry(int entry,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003636 Handle<Object> key,
3637 Handle<Object> value,
Steve Blocka7e24c12009-10-30 11:49:00 +00003638 PropertyDetails details);
3639
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003640 MUST_USE_RESULT static Handle<Derived> Add(
3641 Handle<Derived> dictionary,
3642 Key key,
3643 Handle<Object> value,
3644 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00003645
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003646 // Returns iteration indices array for the |dictionary|.
3647 // Values are direct indices in the |HashTable| array.
3648 static Handle<FixedArray> BuildIterationIndicesArray(
3649 Handle<Derived> dictionary);
3650
Steve Blocka7e24c12009-10-30 11:49:00 +00003651 protected:
3652 // Generic at put operation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003653 MUST_USE_RESULT static Handle<Derived> AtPut(
3654 Handle<Derived> dictionary,
3655 Key key,
3656 Handle<Object> value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003657
3658 // Add entry to dictionary.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003659 static void AddEntry(
3660 Handle<Derived> dictionary,
3661 Key key,
3662 Handle<Object> value,
3663 PropertyDetails details,
3664 uint32_t hash);
Steve Blocka7e24c12009-10-30 11:49:00 +00003665
3666 // Generate new enumeration indices to avoid enumeration index overflow.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003667 // Returns iteration indices array for the |dictionary|.
3668 static Handle<FixedArray> GenerateNewEnumerationIndices(
3669 Handle<Derived> dictionary);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003670 static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00003671 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
3672};
3673
3674
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003675class NameDictionaryShape : public BaseShape<Handle<Name> > {
Steve Blocka7e24c12009-10-30 11:49:00 +00003676 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003677 static inline bool IsMatch(Handle<Name> key, Object* other);
3678 static inline uint32_t Hash(Handle<Name> key);
3679 static inline uint32_t HashForObject(Handle<Name> key, Object* object);
3680 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 static const int kPrefixSize = 2;
3682 static const int kEntrySize = 3;
3683 static const bool kIsEnumerable = true;
3684};
3685
3686
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003687class NameDictionary: public Dictionary<NameDictionary,
3688 NameDictionaryShape,
3689 Handle<Name> > {
3690 typedef Dictionary<
3691 NameDictionary, NameDictionaryShape, Handle<Name> > DerivedDictionary;
3692
Steve Blocka7e24c12009-10-30 11:49:00 +00003693 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003694 DECLARE_CAST(NameDictionary)
Steve Blocka7e24c12009-10-30 11:49:00 +00003695
3696 // Copies enumerable keys to preallocated fixed array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003697 void CopyEnumKeysTo(FixedArray* storage);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003698 inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003699 Handle<NameDictionary> dictionary);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003700
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003701 // Find entry for key, otherwise return kNotFound. Optimized version of
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003702 // HashTable::FindEntry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003703 int FindEntry(Handle<Name> key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003704};
3705
3706
Ben Murdochc7cc0282012-03-05 14:35:55 +00003707class NumberDictionaryShape : public BaseShape<uint32_t> {
Steve Blocka7e24c12009-10-30 11:49:00 +00003708 public:
3709 static inline bool IsMatch(uint32_t key, Object* other);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003710 static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key);
Steve Blocka7e24c12009-10-30 11:49:00 +00003711 static const int kEntrySize = 3;
3712 static const bool kIsEnumerable = false;
3713};
3714
3715
Ben Murdochc7cc0282012-03-05 14:35:55 +00003716class SeededNumberDictionaryShape : public NumberDictionaryShape {
Steve Blocka7e24c12009-10-30 11:49:00 +00003717 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00003718 static const bool UsesSeed = true;
3719 static const int kPrefixSize = 2;
3720
3721 static inline uint32_t SeededHash(uint32_t key, uint32_t seed);
3722 static inline uint32_t SeededHashForObject(uint32_t key,
3723 uint32_t seed,
3724 Object* object);
3725};
3726
3727
3728class UnseededNumberDictionaryShape : public NumberDictionaryShape {
3729 public:
3730 static const int kPrefixSize = 0;
3731
3732 static inline uint32_t Hash(uint32_t key);
3733 static inline uint32_t HashForObject(uint32_t key, Object* object);
3734};
3735
3736
3737class SeededNumberDictionary
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003738 : public Dictionary<SeededNumberDictionary,
3739 SeededNumberDictionaryShape,
3740 uint32_t> {
Ben Murdochc7cc0282012-03-05 14:35:55 +00003741 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003742 DECLARE_CAST(SeededNumberDictionary)
Steve Blocka7e24c12009-10-30 11:49:00 +00003743
3744 // Type specific at put (default NONE attributes is used when adding).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003745 MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut(
3746 Handle<SeededNumberDictionary> dictionary,
3747 uint32_t key,
3748 Handle<Object> value);
3749 MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry(
3750 Handle<SeededNumberDictionary> dictionary,
3751 uint32_t key,
3752 Handle<Object> value,
3753 PropertyDetails details);
Steve Blocka7e24c12009-10-30 11:49:00 +00003754
3755 // Set an existing entry or add a new one if needed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003756 // Return the updated dictionary.
3757 MUST_USE_RESULT static Handle<SeededNumberDictionary> Set(
3758 Handle<SeededNumberDictionary> dictionary,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003759 uint32_t key,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003760 Handle<Object> value,
3761 PropertyDetails details);
3762
Steve Blocka7e24c12009-10-30 11:49:00 +00003763 void UpdateMaxNumberKey(uint32_t key);
3764
3765 // If slow elements are required we will never go back to fast-case
3766 // for the elements kept in this dictionary. We require slow
3767 // elements if an element has been added at an index larger than
3768 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called
3769 // when defining a getter or setter with a number key.
3770 inline bool requires_slow_elements();
3771 inline void set_requires_slow_elements();
3772
3773 // Get the value of the max number key that has been added to this
3774 // dictionary. max_number_key can only be called if
3775 // requires_slow_elements returns false.
3776 inline uint32_t max_number_key();
3777
Steve Blocka7e24c12009-10-30 11:49:00 +00003778 // Bit masks.
3779 static const int kRequiresSlowElementsMask = 1;
3780 static const int kRequiresSlowElementsTagSize = 1;
3781 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1;
3782};
3783
3784
Ben Murdochc7cc0282012-03-05 14:35:55 +00003785class UnseededNumberDictionary
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003786 : public Dictionary<UnseededNumberDictionary,
3787 UnseededNumberDictionaryShape,
3788 uint32_t> {
Ben Murdochc7cc0282012-03-05 14:35:55 +00003789 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003790 DECLARE_CAST(UnseededNumberDictionary)
Ben Murdochc7cc0282012-03-05 14:35:55 +00003791
3792 // Type specific at put (default NONE attributes is used when adding).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003793 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AtNumberPut(
3794 Handle<UnseededNumberDictionary> dictionary,
3795 uint32_t key,
3796 Handle<Object> value);
3797 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AddNumberEntry(
3798 Handle<UnseededNumberDictionary> dictionary,
3799 uint32_t key,
3800 Handle<Object> value);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003801
3802 // Set an existing entry or add a new one if needed.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003803 // Return the updated dictionary.
3804 MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set(
3805 Handle<UnseededNumberDictionary> dictionary,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003806 uint32_t key,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003807 Handle<Object> value);
Ben Murdochc7cc0282012-03-05 14:35:55 +00003808};
3809
3810
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003811class ObjectHashTableShape : public BaseShape<Handle<Object> > {
Ben Murdoch2b4ba112012-01-20 14:57:15 +00003812 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003813 static inline bool IsMatch(Handle<Object> key, Object* other);
3814 static inline uint32_t Hash(Handle<Object> key);
3815 static inline uint32_t HashForObject(Handle<Object> key, Object* object);
3816 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key);
Ben Murdoch592a9fc2012-03-05 11:04:45 +00003817 static const int kPrefixSize = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003818 static const int kEntrySize = 2;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003819};
3820
3821
3822// ObjectHashTable maps keys that are arbitrary objects to object values by
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003823// using the identity hash of the key for hashing purposes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003824class ObjectHashTable: public HashTable<ObjectHashTable,
3825 ObjectHashTableShape,
3826 Handle<Object> > {
3827 typedef HashTable<
3828 ObjectHashTable, ObjectHashTableShape, Handle<Object> > DerivedHashTable;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003829 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003830 DECLARE_CAST(ObjectHashTable)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003831
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003832 // Attempt to shrink hash table after removal of key.
3833 MUST_USE_RESULT static inline Handle<ObjectHashTable> Shrink(
3834 Handle<ObjectHashTable> table,
3835 Handle<Object> key);
3836
3837 // Looks up the value associated with the given key. The hole value is
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003838 // returned in case the key is not present.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003839 Object* Lookup(Handle<Object> key);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003840
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003841 // Adds (or overwrites) the value associated with the given key.
3842 static Handle<ObjectHashTable> Put(Handle<ObjectHashTable> table,
3843 Handle<Object> key,
3844 Handle<Object> value);
3845
3846 // Returns an ObjectHashTable (possibly |table|) where |key| has been removed.
3847 static Handle<ObjectHashTable> Remove(Handle<ObjectHashTable> table,
3848 Handle<Object> key,
3849 bool* was_present);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003850
3851 private:
3852 friend class MarkCompactCollector;
3853
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003854 void AddEntry(int entry, Object* key, Object* value);
3855 void RemoveEntry(int entry);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00003856
3857 // Returns the index to the value of an entry.
3858 static inline int EntryToValueIndex(int entry) {
3859 return EntryToIndex(entry) + 1;
3860 }
3861};
3862
3863
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003864// OrderedHashTable is a HashTable with Object keys that preserves
3865// insertion order. There are Map and Set interfaces (OrderedHashMap
3866// and OrderedHashTable, below). It is meant to be used by JSMap/JSSet.
3867//
3868// Only Object* keys are supported, with Object::SameValueZero() used as the
3869// equality operator and Object::GetHash() for the hash function.
3870//
3871// Based on the "Deterministic Hash Table" as described by Jason Orendorff at
3872// https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables
3873// Originally attributed to Tyler Close.
3874//
3875// Memory layout:
3876// [0]: bucket count
3877// [1]: element count
3878// [2]: deleted element count
3879// [3..(3 + NumberOfBuckets() - 1)]: "hash table", where each item is an
3880// offset into the data table (see below) where the
3881// first item in this bucket is stored.
3882// [3 + NumberOfBuckets()..length]: "data table", an array of length
3883// Capacity() * kEntrySize, where the first entrysize
3884// items are handled by the derived class and the
3885// item at kChainOffset is another entry into the
3886// data table indicating the next entry in this hash
3887// bucket.
3888//
3889// When we transition the table to a new version we obsolete it and reuse parts
3890// of the memory to store information how to transition an iterator to the new
3891// table:
3892//
3893// Memory layout for obsolete table:
3894// [0]: bucket count
3895// [1]: Next newer table
3896// [2]: Number of removed holes or -1 when the table was cleared.
3897// [3..(3 + NumberOfRemovedHoles() - 1)]: The indexes of the removed holes.
3898// [3 + NumberOfRemovedHoles()..length]: Not used
3899//
3900template<class Derived, class Iterator, int entrysize>
3901class OrderedHashTable: public FixedArray {
3902 public:
3903 // Returns an OrderedHashTable with a capacity of at least |capacity|.
3904 static Handle<Derived> Allocate(
3905 Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED);
3906
3907 // Returns an OrderedHashTable (possibly |table|) with enough space
3908 // to add at least one new element.
3909 static Handle<Derived> EnsureGrowable(Handle<Derived> table);
3910
3911 // Returns an OrderedHashTable (possibly |table|) that's shrunken
3912 // if possible.
3913 static Handle<Derived> Shrink(Handle<Derived> table);
3914
3915 // Returns a new empty OrderedHashTable and records the clearing so that
3916 // exisiting iterators can be updated.
3917 static Handle<Derived> Clear(Handle<Derived> table);
3918
3919 // Returns an OrderedHashTable (possibly |table|) where |key| has been
3920 // removed.
3921 static Handle<Derived> Remove(Handle<Derived> table, Handle<Object> key,
3922 bool* was_present);
3923
3924 // Returns kNotFound if the key isn't present.
3925 int FindEntry(Handle<Object> key, int hash);
3926
3927 // Like the above, but doesn't require the caller to provide a hash.
3928 int FindEntry(Handle<Object> key);
3929
3930 int NumberOfElements() {
3931 return Smi::cast(get(kNumberOfElementsIndex))->value();
3932 }
3933
3934 int NumberOfDeletedElements() {
3935 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value();
3936 }
3937
3938 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); }
3939
3940 int NumberOfBuckets() {
3941 return Smi::cast(get(kNumberOfBucketsIndex))->value();
3942 }
3943
3944 // Returns the index into the data table where the new entry
3945 // should be placed. The table is assumed to have enough space
3946 // for a new entry.
3947 int AddEntry(int hash);
3948
3949 // Removes the entry, and puts the_hole in entrysize pointers
3950 // (leaving the hash table chain intact).
3951 void RemoveEntry(int entry);
3952
3953 // Returns an index into |this| for the given entry.
3954 int EntryToIndex(int entry) {
3955 return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize);
3956 }
3957
3958 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); }
3959
3960 bool IsObsolete() {
3961 return !get(kNextTableIndex)->IsSmi();
3962 }
3963
3964 // The next newer table. This is only valid if the table is obsolete.
3965 Derived* NextTable() {
3966 return Derived::cast(get(kNextTableIndex));
3967 }
3968
3969 // When the table is obsolete we store the indexes of the removed holes.
3970 int RemovedIndexAt(int index) {
3971 return Smi::cast(get(kRemovedHolesIndex + index))->value();
3972 }
3973
3974 static const int kNotFound = -1;
3975 static const int kMinCapacity = 4;
3976
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003977 static const int kNumberOfBucketsIndex = 0;
3978 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1;
3979 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
3980 static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1;
3981 static const int kNextTableIndex = kNumberOfElementsIndex;
3982
3983 static const int kNumberOfBucketsOffset =
3984 kHeaderSize + kNumberOfBucketsIndex * kPointerSize;
3985 static const int kNumberOfElementsOffset =
3986 kHeaderSize + kNumberOfElementsIndex * kPointerSize;
3987 static const int kNumberOfDeletedElementsOffset =
3988 kHeaderSize + kNumberOfDeletedElementsIndex * kPointerSize;
3989 static const int kHashTableStartOffset =
3990 kHeaderSize + kHashTableStartIndex * kPointerSize;
3991 static const int kNextTableOffset =
3992 kHeaderSize + kNextTableIndex * kPointerSize;
3993
3994 static const int kEntrySize = entrysize + 1;
3995 static const int kChainOffset = entrysize;
3996
3997 static const int kLoadFactor = 2;
3998
3999 // NumberOfDeletedElements is set to kClearedTableSentinel when
4000 // the table is cleared, which allows iterator transitions to
4001 // optimize that case.
4002 static const int kClearedTableSentinel = -1;
4003
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004004 private:
4005 static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity);
4006
4007 void SetNumberOfBuckets(int num) {
4008 set(kNumberOfBucketsIndex, Smi::FromInt(num));
4009 }
4010
4011 void SetNumberOfElements(int num) {
4012 set(kNumberOfElementsIndex, Smi::FromInt(num));
4013 }
4014
4015 void SetNumberOfDeletedElements(int num) {
4016 set(kNumberOfDeletedElementsIndex, Smi::FromInt(num));
4017 }
4018
4019 int Capacity() {
4020 return NumberOfBuckets() * kLoadFactor;
4021 }
4022
4023 // Returns the next entry for the given entry.
4024 int ChainAt(int entry) {
4025 return Smi::cast(get(EntryToIndex(entry) + kChainOffset))->value();
4026 }
4027
4028 int HashToBucket(int hash) {
4029 return hash & (NumberOfBuckets() - 1);
4030 }
4031
4032 int HashToEntry(int hash) {
4033 int bucket = HashToBucket(hash);
4034 return Smi::cast(get(kHashTableStartIndex + bucket))->value();
4035 }
4036
4037 void SetNextTable(Derived* next_table) {
4038 set(kNextTableIndex, next_table);
4039 }
4040
4041 void SetRemovedIndexAt(int index, int removed_index) {
4042 return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
4043 }
4044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004045 static const int kRemovedHolesIndex = kHashTableStartIndex;
4046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004047 static const int kMaxCapacity =
4048 (FixedArray::kMaxLength - kHashTableStartIndex)
4049 / (1 + (kEntrySize * kLoadFactor));
4050};
4051
4052
4053class JSSetIterator;
4054
4055
4056class OrderedHashSet: public OrderedHashTable<
4057 OrderedHashSet, JSSetIterator, 1> {
4058 public:
4059 DECLARE_CAST(OrderedHashSet)
4060
4061 bool Contains(Handle<Object> key);
4062 static Handle<OrderedHashSet> Add(
4063 Handle<OrderedHashSet> table, Handle<Object> key);
4064};
4065
4066
4067class JSMapIterator;
4068
4069
4070class OrderedHashMap:public OrderedHashTable<
4071 OrderedHashMap, JSMapIterator, 2> {
4072 public:
4073 DECLARE_CAST(OrderedHashMap)
4074
4075 Object* Lookup(Handle<Object> key);
4076 static Handle<OrderedHashMap> Put(
4077 Handle<OrderedHashMap> table,
4078 Handle<Object> key,
4079 Handle<Object> value);
4080
4081 Object* ValueAt(int entry) {
4082 return get(EntryToIndex(entry) + kValueOffset);
4083 }
4084
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004085 static const int kValueOffset = 1;
4086};
4087
4088
4089template <int entrysize>
4090class WeakHashTableShape : public BaseShape<Handle<Object> > {
4091 public:
4092 static inline bool IsMatch(Handle<Object> key, Object* other);
4093 static inline uint32_t Hash(Handle<Object> key);
4094 static inline uint32_t HashForObject(Handle<Object> key, Object* object);
4095 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key);
4096 static const int kPrefixSize = 0;
4097 static const int kEntrySize = entrysize;
4098};
4099
4100
4101// WeakHashTable maps keys that are arbitrary objects to object values.
4102// It is used for the global weak hash table that maps objects
4103// embedded in optimized code to dependent code lists.
4104class WeakHashTable: public HashTable<WeakHashTable,
4105 WeakHashTableShape<2>,
4106 Handle<Object> > {
4107 typedef HashTable<
4108 WeakHashTable, WeakHashTableShape<2>, Handle<Object> > DerivedHashTable;
4109 public:
4110 DECLARE_CAST(WeakHashTable)
4111
4112 // Looks up the value associated with the given key. The hole value is
4113 // returned in case the key is not present.
4114 Object* Lookup(Handle<Object> key);
4115
4116 // Adds (or overwrites) the value associated with the given key. Mapping a
4117 // key to the hole value causes removal of the whole entry.
4118 MUST_USE_RESULT static Handle<WeakHashTable> Put(Handle<WeakHashTable> table,
4119 Handle<Object> key,
4120 Handle<Object> value);
4121
4122 // This function is called when heap verification is turned on.
4123 void Zap(Object* value) {
4124 int capacity = Capacity();
4125 for (int i = 0; i < capacity; i++) {
4126 set(EntryToIndex(i), value);
4127 set(EntryToValueIndex(i), value);
4128 }
4129 }
4130
4131 private:
4132 friend class MarkCompactCollector;
4133
4134 void AddEntry(int entry, Handle<Object> key, Handle<Object> value);
4135
4136 // Returns the index to the value of an entry.
4137 static inline int EntryToValueIndex(int entry) {
4138 return EntryToIndex(entry) + 1;
4139 }
4140};
4141
4142
Steve Block6ded16b2010-05-10 14:33:55 +01004143// JSFunctionResultCache caches results of some JSFunction invocation.
4144// It is a fixed array with fixed structure:
4145// [0]: factory function
4146// [1]: finger index
4147// [2]: current cache size
4148// [3]: dummy field.
4149// The rest of array are key/value pairs.
4150class JSFunctionResultCache: public FixedArray {
4151 public:
4152 static const int kFactoryIndex = 0;
4153 static const int kFingerIndex = kFactoryIndex + 1;
4154 static const int kCacheSizeIndex = kFingerIndex + 1;
4155 static const int kDummyIndex = kCacheSizeIndex + 1;
4156 static const int kEntriesIndex = kDummyIndex + 1;
4157
4158 static const int kEntrySize = 2; // key + value
4159
Kristian Monsen25f61362010-05-21 11:50:48 +01004160 static const int kFactoryOffset = kHeaderSize;
4161 static const int kFingerOffset = kFactoryOffset + kPointerSize;
4162 static const int kCacheSizeOffset = kFingerOffset + kPointerSize;
4163
Steve Block6ded16b2010-05-10 14:33:55 +01004164 inline void MakeZeroSize();
4165 inline void Clear();
4166
Ben Murdochb8e0da22011-05-16 14:20:40 +01004167 inline int size();
4168 inline void set_size(int size);
4169 inline int finger_index();
4170 inline void set_finger_index(int finger_index);
4171
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004172 DECLARE_CAST(JSFunctionResultCache)
Steve Block6ded16b2010-05-10 14:33:55 +01004173
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004174 DECLARE_VERIFIER(JSFunctionResultCache)
Steve Block6ded16b2010-05-10 14:33:55 +01004175};
4176
4177
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004178// ScopeInfo represents information about different scopes of a source
4179// program and the allocation of the scope's variables. Scope information
4180// is stored in a compressed form in ScopeInfo objects and is used
4181// at runtime (stack dumps, deoptimization, etc.).
4182
4183// This object provides quick access to scope info details for runtime
4184// routines.
4185class ScopeInfo : public FixedArray {
4186 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004187 DECLARE_CAST(ScopeInfo)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004188
4189 // Return the type of this scope.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004190 ScopeType scope_type();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004191
4192 // Does this scope call eval?
4193 bool CallsEval();
4194
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004195 // Return the strict mode of this scope.
4196 StrictMode strict_mode();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004197
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004198 // Does this scope make a sloppy eval call?
4199 bool CallsSloppyEval() { return CallsEval() && strict_mode() == SLOPPY; }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004200
4201 // Return the total number of locals allocated on the stack and in the
4202 // context. This includes the parameters that are allocated in the context.
4203 int LocalCount();
4204
4205 // Return the number of stack slots for code. This number consists of two
4206 // parts:
4207 // 1. One stack slot per stack allocated local.
4208 // 2. One stack slot for the function name if it is stack allocated.
4209 int StackSlotCount();
4210
4211 // Return the number of context slots for code if a context is allocated. This
4212 // number consists of three parts:
4213 // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
4214 // 2. One context slot per context allocated local.
4215 // 3. One context slot for the function name if it is context allocated.
4216 // Parameters allocated in the context count as context allocated locals. If
4217 // no contexts are allocated for this scope ContextLength returns 0.
4218 int ContextLength();
4219
4220 // Is this scope the scope of a named function expression?
4221 bool HasFunctionName();
4222
4223 // Return if this has context allocated locals.
4224 bool HasHeapAllocatedLocals();
4225
4226 // Return if contexts are allocated for this scope.
4227 bool HasContext();
4228
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004229 // Return if this is a function scope with "use asm".
4230 bool IsAsmModule() { return AsmModuleField::decode(Flags()); }
4231
4232 // Return if this is a nested function within an asm module scope.
4233 bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); }
4234
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004235 // Return the function_name if present.
4236 String* FunctionName();
4237
4238 // Return the name of the given parameter.
4239 String* ParameterName(int var);
4240
4241 // Return the name of the given local.
4242 String* LocalName(int var);
4243
4244 // Return the name of the given stack local.
4245 String* StackLocalName(int var);
4246
4247 // Return the name of the given context local.
4248 String* ContextLocalName(int var);
4249
4250 // Return the mode of the given context local.
4251 VariableMode ContextLocalMode(int var);
4252
4253 // Return the initialization flag of the given context local.
4254 InitializationFlag ContextLocalInitFlag(int var);
4255
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004256 // Return the initialization flag of the given context local.
4257 MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var);
4258
4259 // Return true if this local was introduced by the compiler, and should not be
4260 // exposed to the user in a debugger.
4261 bool LocalIsSynthetic(int var);
4262
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004263 // Lookup support for serialized scope info. Returns the
4264 // the stack slot index for a given slot name if the slot is
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004265 // present; otherwise returns a value < 0. The name must be an internalized
4266 // string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004267 int StackSlotIndex(String* name);
4268
4269 // Lookup support for serialized scope info. Returns the
4270 // context slot index for a given slot name if the slot is present; otherwise
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004271 // returns a value < 0. The name must be an internalized string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004272 // If the slot is present and mode != NULL, sets *mode to the corresponding
4273 // mode for that variable.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004274 static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name,
4275 VariableMode* mode, InitializationFlag* init_flag,
4276 MaybeAssignedFlag* maybe_assigned_flag);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004277
4278 // Lookup support for serialized scope info. Returns the
4279 // parameter index for a given parameter name if the parameter is present;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004280 // otherwise returns a value < 0. The name must be an internalized string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004281 int ParameterIndex(String* name);
4282
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004283 // Lookup support for serialized scope info. Returns the function context
4284 // slot index if the function name is present and context-allocated (named
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004285 // function expressions, only), otherwise returns a value < 0. The name
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004286 // must be an internalized string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004287 int FunctionContextSlotIndex(String* name, VariableMode* mode);
4288
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004289
4290 // Copies all the context locals into an object used to materialize a scope.
4291 static bool CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
4292 Handle<Context> context,
4293 Handle<JSObject> scope_object);
4294
4295
4296 static Handle<ScopeInfo> Create(Scope* scope, Zone* zone);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004297
4298 // Serializes empty scope info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004299 static ScopeInfo* Empty(Isolate* isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004300
4301#ifdef DEBUG
4302 void Print();
4303#endif
4304
4305 // The layout of the static part of a ScopeInfo is as follows. Each entry is
4306 // numeric and occupies one array slot.
4307 // 1. A set of properties of the scope
4308 // 2. The number of parameters. This only applies to function scopes. For
4309 // non-function scopes this is 0.
4310 // 3. The number of non-parameter variables allocated on the stack.
4311 // 4. The number of non-parameter and parameter variables allocated in the
4312 // context.
4313#define FOR_EACH_NUMERIC_FIELD(V) \
4314 V(Flags) \
4315 V(ParameterCount) \
4316 V(StackLocalCount) \
4317 V(ContextLocalCount)
4318
4319#define FIELD_ACCESSORS(name) \
4320 void Set##name(int value) { \
4321 set(k##name, Smi::FromInt(value)); \
4322 } \
4323 int name() { \
4324 if (length() > 0) { \
4325 return Smi::cast(get(k##name))->value(); \
4326 } else { \
4327 return 0; \
4328 } \
4329 }
4330 FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS)
4331#undef FIELD_ACCESSORS
4332
4333 private:
4334 enum {
4335#define DECL_INDEX(name) k##name,
4336 FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
4337#undef DECL_INDEX
4338#undef FOR_EACH_NUMERIC_FIELD
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004339 kVariablePartIndex
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004340 };
4341
4342 // The layout of the variable part of a ScopeInfo is as follows:
4343 // 1. ParameterEntries:
4344 // This part stores the names of the parameters for function scopes. One
4345 // slot is used per parameter, so in total this part occupies
4346 // ParameterCount() slots in the array. For other scopes than function
4347 // scopes ParameterCount() is 0.
4348 // 2. StackLocalEntries:
4349 // Contains the names of local variables that are allocated on the stack,
4350 // in increasing order of the stack slot index. One slot is used per stack
4351 // local, so in total this part occupies StackLocalCount() slots in the
4352 // array.
4353 // 3. ContextLocalNameEntries:
4354 // Contains the names of local variables and parameters that are allocated
4355 // in the context. They are stored in increasing order of the context slot
4356 // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
4357 // context local, so in total this part occupies ContextLocalCount() slots
4358 // in the array.
4359 // 4. ContextLocalInfoEntries:
4360 // Contains the variable modes and initialization flags corresponding to
4361 // the context locals in ContextLocalNameEntries. One slot is used per
4362 // context local, so in total this part occupies ContextLocalCount()
4363 // slots in the array.
4364 // 5. FunctionNameEntryIndex:
4365 // If the scope belongs to a named function expression this part contains
4366 // information about the function variable. It always occupies two array
4367 // slots: a. The name of the function variable.
4368 // b. The context or stack slot index for the variable.
4369 int ParameterEntriesIndex();
4370 int StackLocalEntriesIndex();
4371 int ContextLocalNameEntriesIndex();
4372 int ContextLocalInfoEntriesIndex();
4373 int FunctionNameEntryIndex();
4374
4375 // Location of the function variable for named function expressions.
4376 enum FunctionVariableInfo {
4377 NONE, // No function name present.
4378 STACK, // Function
4379 CONTEXT,
4380 UNUSED
4381 };
4382
4383 // Properties of scopes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004384 class ScopeTypeField : public BitField<ScopeType, 0, 4> {};
4385 class CallsEvalField : public BitField<bool, 4, 1> {};
4386 class StrictModeField : public BitField<StrictMode, 5, 1> {};
4387 class FunctionVariableField : public BitField<FunctionVariableInfo, 6, 2> {};
4388 class FunctionVariableMode : public BitField<VariableMode, 8, 3> {};
4389 class AsmModuleField : public BitField<bool, 11, 1> {};
4390 class AsmFunctionField : public BitField<bool, 12, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004391
4392 // BitFields representing the encoded information for context locals in the
4393 // ContextLocalInfoEntries part.
4394 class ContextLocalMode: public BitField<VariableMode, 0, 3> {};
4395 class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004396 class ContextLocalMaybeAssignedFlag
4397 : public BitField<MaybeAssignedFlag, 4, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004398};
4399
4400
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004401// The cache for maps used by normalized (dictionary mode) objects.
4402// Such maps do not have property descriptors, so a typical program
4403// needs very limited number of distinct normalized maps.
4404class NormalizedMapCache: public FixedArray {
4405 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004406 static Handle<NormalizedMapCache> New(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004407
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004408 MUST_USE_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map,
4409 PropertyNormalizationMode mode);
4410 void Set(Handle<Map> fast_map, Handle<Map> normalized_map);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004411
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004412 void Clear();
4413
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004414 DECLARE_CAST(NormalizedMapCache)
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004415
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004416 static inline bool IsNormalizedMapCache(const Object* obj);
4417
4418 DECLARE_VERIFIER(NormalizedMapCache)
4419 private:
4420 static const int kEntries = 64;
4421
4422 static inline int GetIndex(Handle<Map> map);
4423
4424 // The following declarations hide base class methods.
4425 Object* get(int index);
4426 void set(int index, Object* value);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01004427};
4428
4429
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004430// ByteArray represents fixed sized byte arrays. Used for the relocation info
4431// that is attached to code objects.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004432class ByteArray: public FixedArrayBase {
Steve Blocka7e24c12009-10-30 11:49:00 +00004433 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004434 inline int Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
4435
Steve Blocka7e24c12009-10-30 11:49:00 +00004436 // Setter and getter.
4437 inline byte get(int index);
4438 inline void set(int index, byte value);
4439
4440 // Treat contents as an int array.
4441 inline int get_int(int index);
4442
4443 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004444 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
Steve Blocka7e24c12009-10-30 11:49:00 +00004445 }
4446 // We use byte arrays for free blocks in the heap. Given a desired size in
4447 // bytes that is a multiple of the word size and big enough to hold a byte
4448 // array, this function returns the number of elements a byte array should
4449 // have.
4450 static int LengthFor(int size_in_bytes) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004451 DCHECK(IsAligned(size_in_bytes, kPointerSize));
4452 DCHECK(size_in_bytes >= kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004453 return size_in_bytes - kHeaderSize;
4454 }
4455
4456 // Returns data start address.
4457 inline Address GetDataStartAddress();
4458
4459 // Returns a pointer to the ByteArray object for a given data start address.
4460 static inline ByteArray* FromDataStartAddress(Address address);
4461
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004462 DECLARE_CAST(ByteArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00004463
4464 // Dispatched behavior.
Iain Merrick75681382010-08-19 15:07:18 +01004465 inline int ByteArraySize() {
4466 return SizeFor(this->length());
4467 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004468 DECLARE_PRINTER(ByteArray)
4469 DECLARE_VERIFIER(ByteArray)
Steve Blocka7e24c12009-10-30 11:49:00 +00004470
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004471 // Layout description.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004472 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00004473
Leon Clarkee46be812010-01-19 14:06:41 +00004474 // Maximal memory consumption for a single ByteArray.
4475 static const int kMaxSize = 512 * MB;
4476 // Maximal length of a single ByteArray.
4477 static const int kMaxLength = kMaxSize - kHeaderSize;
4478
Steve Blocka7e24c12009-10-30 11:49:00 +00004479 private:
4480 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
4481};
4482
4483
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004484// FreeSpace represents fixed sized areas of the heap that are not currently in
4485// use. Used by the heap and GC.
4486class FreeSpace: public HeapObject {
4487 public:
4488 // [size]: size of the free space including the header.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004489 inline int size() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004490 inline void set_size(int value);
4491
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004492 inline int nobarrier_size() const;
4493 inline void nobarrier_set_size(int value);
4494
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004495 inline int Size() { return size(); }
4496
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004497 DECLARE_CAST(FreeSpace)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004498
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004499 // Dispatched behavior.
4500 DECLARE_PRINTER(FreeSpace)
4501 DECLARE_VERIFIER(FreeSpace)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004502
4503 // Layout description.
4504 // Size is smi tagged when it is stored.
4505 static const int kSizeOffset = HeapObject::kHeaderSize;
4506 static const int kHeaderSize = kSizeOffset + kPointerSize;
4507
4508 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
4509
4510 private:
4511 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace);
4512};
4513
4514
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004515// V has parameters (Type, type, TYPE, C type, element_size)
4516#define TYPED_ARRAYS(V) \
4517 V(Uint8, uint8, UINT8, uint8_t, 1) \
4518 V(Int8, int8, INT8, int8_t, 1) \
4519 V(Uint16, uint16, UINT16, uint16_t, 2) \
4520 V(Int16, int16, INT16, int16_t, 2) \
4521 V(Uint32, uint32, UINT32, uint32_t, 4) \
4522 V(Int32, int32, INT32, int32_t, 4) \
4523 V(Float32, float32, FLOAT32, float, 4) \
4524 V(Float64, float64, FLOAT64, double, 8) \
4525 V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1)
4526
4527
4528
Steve Block3ce2e202009-11-05 08:53:23 +00004529// An ExternalArray represents a fixed-size array of primitive values
4530// which live outside the JavaScript heap. Its subclasses are used to
4531// implement the CanvasArray types being defined in the WebGL
4532// specification. As of this writing the first public draft is not yet
4533// available, but Khronos members can access the draft at:
4534// https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html
4535//
4536// The semantics of these arrays differ from CanvasPixelArray.
4537// Out-of-range values passed to the setter are converted via a C
4538// cast, not clamping. Out-of-range indices cause exceptions to be
4539// raised rather than being silently ignored.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004540class ExternalArray: public FixedArrayBase {
Steve Block3ce2e202009-11-05 08:53:23 +00004541 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004542 inline bool is_the_hole(int index) { return false; }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004543
Steve Block3ce2e202009-11-05 08:53:23 +00004544 // [external_pointer]: The pointer to the external memory area backing this
4545 // external array.
4546 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store.
4547
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004548 DECLARE_CAST(ExternalArray)
Steve Block3ce2e202009-11-05 08:53:23 +00004549
4550 // Maximal acceptable length for an external array.
4551 static const int kMaxLength = 0x3fffffff;
4552
4553 // ExternalArray headers are not quadword aligned.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004554 static const int kExternalPointerOffset =
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004555 POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize);
Steve Block3ce2e202009-11-05 08:53:23 +00004556 static const int kHeaderSize = kExternalPointerOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01004557 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
Steve Block3ce2e202009-11-05 08:53:23 +00004558
4559 private:
4560 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray);
4561};
4562
4563
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004564// A ExternalUint8ClampedArray represents a fixed-size byte array with special
Steve Block44f0eee2011-05-26 01:26:41 +01004565// semantics used for implementing the CanvasPixelArray object. Please see the
4566// specification at:
4567
4568// http://www.whatwg.org/specs/web-apps/current-work/
4569// multipage/the-canvas-element.html#canvaspixelarray
4570// In particular, write access clamps the value written to 0 or 255 if the
4571// value written is outside this range.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004572class ExternalUint8ClampedArray: public ExternalArray {
Steve Block44f0eee2011-05-26 01:26:41 +01004573 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004574 inline uint8_t* external_uint8_clamped_pointer();
Steve Block44f0eee2011-05-26 01:26:41 +01004575
4576 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004577 inline uint8_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004578 static inline Handle<Object> get(Handle<ExternalUint8ClampedArray> array,
4579 int index);
Steve Block44f0eee2011-05-26 01:26:41 +01004580 inline void set(int index, uint8_t value);
4581
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004582 // This accessor applies the correct conversion from Smi, HeapNumber
4583 // and undefined and clamps the converted value between 0 and 255.
4584 static Handle<Object> SetValue(Handle<ExternalUint8ClampedArray> array,
4585 uint32_t index,
4586 Handle<Object> value);
Steve Block44f0eee2011-05-26 01:26:41 +01004587
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004588 DECLARE_CAST(ExternalUint8ClampedArray)
Steve Block44f0eee2011-05-26 01:26:41 +01004589
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004590 // Dispatched behavior.
4591 DECLARE_PRINTER(ExternalUint8ClampedArray)
4592 DECLARE_VERIFIER(ExternalUint8ClampedArray)
Steve Block44f0eee2011-05-26 01:26:41 +01004593
4594 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004595 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8ClampedArray);
Steve Block44f0eee2011-05-26 01:26:41 +01004596};
4597
4598
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004599class ExternalInt8Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004600 public:
4601 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004602 inline int8_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004603 static inline Handle<Object> get(Handle<ExternalInt8Array> array, int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004604 inline void set(int index, int8_t value);
4605
4606 // This accessor applies the correct conversion from Smi, HeapNumber
4607 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004608 static Handle<Object> SetValue(Handle<ExternalInt8Array> array,
4609 uint32_t index,
4610 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004611
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004612 DECLARE_CAST(ExternalInt8Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004613
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004614 // Dispatched behavior.
4615 DECLARE_PRINTER(ExternalInt8Array)
4616 DECLARE_VERIFIER(ExternalInt8Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004617
4618 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004619 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt8Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004620};
4621
4622
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004623class ExternalUint8Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004624 public:
4625 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004626 inline uint8_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004627 static inline Handle<Object> get(Handle<ExternalUint8Array> array, int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004628 inline void set(int index, uint8_t value);
4629
4630 // This accessor applies the correct conversion from Smi, HeapNumber
4631 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004632 static Handle<Object> SetValue(Handle<ExternalUint8Array> array,
4633 uint32_t index,
4634 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004635
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004636 DECLARE_CAST(ExternalUint8Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004637
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004638 // Dispatched behavior.
4639 DECLARE_PRINTER(ExternalUint8Array)
4640 DECLARE_VERIFIER(ExternalUint8Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004641
4642 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004643 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004644};
4645
4646
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004647class ExternalInt16Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004648 public:
4649 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004650 inline int16_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004651 static inline Handle<Object> get(Handle<ExternalInt16Array> array, int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004652 inline void set(int index, int16_t value);
4653
4654 // This accessor applies the correct conversion from Smi, HeapNumber
4655 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004656 static Handle<Object> SetValue(Handle<ExternalInt16Array> array,
4657 uint32_t index,
4658 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004659
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004660 DECLARE_CAST(ExternalInt16Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004661
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004662 // Dispatched behavior.
4663 DECLARE_PRINTER(ExternalInt16Array)
4664 DECLARE_VERIFIER(ExternalInt16Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004665
4666 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004667 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt16Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004668};
4669
4670
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004671class ExternalUint16Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004672 public:
4673 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004674 inline uint16_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004675 static inline Handle<Object> get(Handle<ExternalUint16Array> array,
4676 int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004677 inline void set(int index, uint16_t value);
4678
4679 // This accessor applies the correct conversion from Smi, HeapNumber
4680 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004681 static Handle<Object> SetValue(Handle<ExternalUint16Array> array,
4682 uint32_t index,
4683 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004684
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004685 DECLARE_CAST(ExternalUint16Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004686
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004687 // Dispatched behavior.
4688 DECLARE_PRINTER(ExternalUint16Array)
4689 DECLARE_VERIFIER(ExternalUint16Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004690
4691 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004692 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint16Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004693};
4694
4695
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004696class ExternalInt32Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004697 public:
4698 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004699 inline int32_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004700 static inline Handle<Object> get(Handle<ExternalInt32Array> array, int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004701 inline void set(int index, int32_t value);
4702
4703 // This accessor applies the correct conversion from Smi, HeapNumber
4704 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004705 static Handle<Object> SetValue(Handle<ExternalInt32Array> array,
4706 uint32_t index,
4707 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004708
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004709 DECLARE_CAST(ExternalInt32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004710
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004711 // Dispatched behavior.
4712 DECLARE_PRINTER(ExternalInt32Array)
4713 DECLARE_VERIFIER(ExternalInt32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004714
4715 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004716 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt32Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004717};
4718
4719
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004720class ExternalUint32Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004721 public:
4722 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004723 inline uint32_t get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004724 static inline Handle<Object> get(Handle<ExternalUint32Array> array,
4725 int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004726 inline void set(int index, uint32_t value);
4727
4728 // This accessor applies the correct conversion from Smi, HeapNumber
4729 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004730 static Handle<Object> SetValue(Handle<ExternalUint32Array> array,
4731 uint32_t index,
4732 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004733
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004734 DECLARE_CAST(ExternalUint32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004735
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004736 // Dispatched behavior.
4737 DECLARE_PRINTER(ExternalUint32Array)
4738 DECLARE_VERIFIER(ExternalUint32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004739
4740 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004741 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint32Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004742};
4743
4744
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004745class ExternalFloat32Array: public ExternalArray {
Steve Block3ce2e202009-11-05 08:53:23 +00004746 public:
4747 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004748 inline float get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004749 static inline Handle<Object> get(Handle<ExternalFloat32Array> array,
4750 int index);
Steve Block3ce2e202009-11-05 08:53:23 +00004751 inline void set(int index, float value);
4752
4753 // This accessor applies the correct conversion from Smi, HeapNumber
4754 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004755 static Handle<Object> SetValue(Handle<ExternalFloat32Array> array,
4756 uint32_t index,
4757 Handle<Object> value);
Steve Block3ce2e202009-11-05 08:53:23 +00004758
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004759 DECLARE_CAST(ExternalFloat32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004760
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004761 // Dispatched behavior.
4762 DECLARE_PRINTER(ExternalFloat32Array)
4763 DECLARE_VERIFIER(ExternalFloat32Array)
Steve Block3ce2e202009-11-05 08:53:23 +00004764
4765 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004766 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat32Array);
Steve Block3ce2e202009-11-05 08:53:23 +00004767};
4768
4769
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004770class ExternalFloat64Array: public ExternalArray {
Ben Murdoch257744e2011-11-30 15:57:28 +00004771 public:
4772 // Setter and getter.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00004773 inline double get_scalar(int index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004774 static inline Handle<Object> get(Handle<ExternalFloat64Array> array,
4775 int index);
Ben Murdoch257744e2011-11-30 15:57:28 +00004776 inline void set(int index, double value);
4777
4778 // This accessor applies the correct conversion from Smi, HeapNumber
4779 // and undefined.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004780 static Handle<Object> SetValue(Handle<ExternalFloat64Array> array,
4781 uint32_t index,
4782 Handle<Object> value);
Ben Murdoch257744e2011-11-30 15:57:28 +00004783
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004784 DECLARE_CAST(ExternalFloat64Array)
Ben Murdoch257744e2011-11-30 15:57:28 +00004785
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004786 // Dispatched behavior.
4787 DECLARE_PRINTER(ExternalFloat64Array)
4788 DECLARE_VERIFIER(ExternalFloat64Array)
Ben Murdoch257744e2011-11-30 15:57:28 +00004789
4790 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004791 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat64Array);
Ben Murdoch257744e2011-11-30 15:57:28 +00004792};
4793
4794
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004795class FixedTypedArrayBase: public FixedArrayBase {
4796 public:
4797 DECLARE_CAST(FixedTypedArrayBase)
4798
4799 static const int kDataOffset = kHeaderSize;
4800
4801 inline int size();
4802
4803 inline int TypedArraySize(InstanceType type);
4804
4805 // Use with care: returns raw pointer into heap.
4806 inline void* DataPtr();
4807
4808 inline int DataSize();
4809
4810 private:
4811 inline int DataSize(InstanceType type);
4812
4813 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase);
4814};
4815
4816
4817template <class Traits>
4818class FixedTypedArray: public FixedTypedArrayBase {
4819 public:
4820 typedef typename Traits::ElementType ElementType;
4821 static const InstanceType kInstanceType = Traits::kInstanceType;
4822
4823 DECLARE_CAST(FixedTypedArray<Traits>)
4824
4825 static inline int ElementOffset(int index) {
4826 return kDataOffset + index * sizeof(ElementType);
4827 }
4828
4829 static inline int SizeFor(int length) {
4830 return ElementOffset(length);
4831 }
4832
4833 inline ElementType get_scalar(int index);
4834 static inline Handle<Object> get(Handle<FixedTypedArray> array, int index);
4835 inline void set(int index, ElementType value);
4836
4837 static inline ElementType from_int(int value);
4838 static inline ElementType from_double(double value);
4839
4840 // This accessor applies the correct conversion from Smi, HeapNumber
4841 // and undefined.
4842 static Handle<Object> SetValue(Handle<FixedTypedArray<Traits> > array,
4843 uint32_t index,
4844 Handle<Object> value);
4845
4846 DECLARE_PRINTER(FixedTypedArray)
4847 DECLARE_VERIFIER(FixedTypedArray)
4848
4849 private:
4850 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray);
4851};
4852
4853#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType, size) \
4854 class Type##ArrayTraits { \
4855 public: /* NOLINT */ \
4856 typedef elementType ElementType; \
4857 static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
4858 static const char* Designator() { return #type " array"; } \
4859 static inline Handle<Object> ToHandle(Isolate* isolate, \
4860 elementType scalar); \
4861 static inline elementType defaultValue(); \
4862 }; \
4863 \
4864 typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;
4865
4866TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
4867
4868#undef FIXED_TYPED_ARRAY_TRAITS
4869
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004870
Ben Murdochb0fe1622011-05-05 13:52:32 +01004871// DeoptimizationInputData is a fixed array used to hold the deoptimization
4872// data for code generated by the Hydrogen/Lithium compiler. It also
4873// contains information about functions that were inlined. If N different
4874// functions were inlined then first N elements of the literal array will
4875// contain these functions.
4876//
4877// It can be empty.
4878class DeoptimizationInputData: public FixedArray {
4879 public:
4880 // Layout description. Indices in the array.
4881 static const int kTranslationByteArrayIndex = 0;
4882 static const int kInlinedFunctionCountIndex = 1;
4883 static const int kLiteralArrayIndex = 2;
4884 static const int kOsrAstIdIndex = 3;
4885 static const int kOsrPcOffsetIndex = 4;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004886 static const int kOptimizationIdIndex = 5;
4887 static const int kSharedFunctionInfoIndex = 6;
4888 static const int kFirstDeoptEntryIndex = 7;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004889
4890 // Offsets of deopt entry elements relative to the start of the entry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004891 static const int kAstIdRawOffset = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004892 static const int kTranslationIndexOffset = 1;
4893 static const int kArgumentsStackHeightOffset = 2;
Ben Murdoch2b4ba112012-01-20 14:57:15 +00004894 static const int kPcOffset = 3;
4895 static const int kDeoptEntrySize = 4;
Ben Murdochb0fe1622011-05-05 13:52:32 +01004896
4897 // Simple element accessors.
4898#define DEFINE_ELEMENT_ACCESSORS(name, type) \
4899 type* name() { \
4900 return type::cast(get(k##name##Index)); \
4901 } \
4902 void Set##name(type* value) { \
4903 set(k##name##Index, value); \
4904 }
4905
4906 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
4907 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
4908 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
4909 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi)
4910 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004911 DEFINE_ELEMENT_ACCESSORS(OptimizationId, Smi)
4912 DEFINE_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004913
Ben Murdochb0fe1622011-05-05 13:52:32 +01004914#undef DEFINE_ELEMENT_ACCESSORS
4915
4916 // Accessors for elements of the ith deoptimization entry.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004917#define DEFINE_ENTRY_ACCESSORS(name, type) \
4918 type* name(int i) { \
4919 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \
4920 } \
4921 void Set##name(int i, type* value) { \
4922 set(IndexForEntry(i) + k##name##Offset, value); \
Ben Murdochb0fe1622011-05-05 13:52:32 +01004923 }
4924
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004925 DEFINE_ENTRY_ACCESSORS(AstIdRaw, Smi)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004926 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
4927 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
Ben Murdoch2b4ba112012-01-20 14:57:15 +00004928 DEFINE_ENTRY_ACCESSORS(Pc, Smi)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004929
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004930#undef DEFINE_DEOPT_ENTRY_ACCESSORS
4931
4932 BailoutId AstId(int i) {
4933 return BailoutId(AstIdRaw(i)->value());
4934 }
4935
4936 void SetAstId(int i, BailoutId value) {
4937 SetAstIdRaw(i, Smi::FromInt(value.ToInt()));
4938 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004939
4940 int DeoptCount() {
4941 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
4942 }
4943
4944 // Allocates a DeoptimizationInputData.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004945 static Handle<DeoptimizationInputData> New(Isolate* isolate,
4946 int deopt_entry_count,
4947 PretenureFlag pretenure);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004948
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004949 DECLARE_CAST(DeoptimizationInputData)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004950
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004951#ifdef ENABLE_DISASSEMBLER
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004952 void DeoptimizationInputDataPrint(std::ostream& os); // NOLINT
Ben Murdochb0fe1622011-05-05 13:52:32 +01004953#endif
4954
4955 private:
4956 static int IndexForEntry(int i) {
4957 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
4958 }
4959
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004960
4961 static int LengthFor(int entry_count) { return IndexForEntry(entry_count); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01004962};
4963
4964
4965// DeoptimizationOutputData is a fixed array used to hold the deoptimization
4966// data for code generated by the full compiler.
4967// The format of the these objects is
4968// [i * 2]: Ast ID for ith deoptimization.
4969// [i * 2 + 1]: PC and state of ith deoptimization
4970class DeoptimizationOutputData: public FixedArray {
4971 public:
4972 int DeoptPoints() { return length() / 2; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004973
4974 BailoutId AstId(int index) {
4975 return BailoutId(Smi::cast(get(index * 2))->value());
4976 }
4977
4978 void SetAstId(int index, BailoutId id) {
4979 set(index * 2, Smi::FromInt(id.ToInt()));
4980 }
4981
Ben Murdochb0fe1622011-05-05 13:52:32 +01004982 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); }
4983 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); }
4984
4985 static int LengthOfFixedArray(int deopt_points) {
4986 return deopt_points * 2;
4987 }
4988
4989 // Allocates a DeoptimizationOutputData.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004990 static Handle<DeoptimizationOutputData> New(Isolate* isolate,
4991 int number_of_deopt_points,
4992 PretenureFlag pretenure);
Ben Murdochb0fe1622011-05-05 13:52:32 +01004993
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004994 DECLARE_CAST(DeoptimizationOutputData)
Ben Murdochb0fe1622011-05-05 13:52:32 +01004995
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00004996#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004997 void DeoptimizationOutputDataPrint(std::ostream& os); // NOLINT
Ben Murdochb0fe1622011-05-05 13:52:32 +01004998#endif
4999};
5000
5001
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005002// Forward declaration.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005003class Cell;
5004class PropertyCell;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005005class SafepointEntry;
5006class TypeFeedbackInfo;
Ben Murdochb8e0da22011-05-16 14:20:40 +01005007
Steve Blocka7e24c12009-10-30 11:49:00 +00005008// Code describes objects with on-the-fly generated machine code.
5009class Code: public HeapObject {
5010 public:
5011 // Opaque data type for encapsulating code flags like kind, inline
5012 // cache state, and arguments count.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005013 typedef uint32_t Flags;
5014
5015#define NON_IC_KIND_LIST(V) \
5016 V(FUNCTION) \
5017 V(OPTIMIZED_FUNCTION) \
5018 V(STUB) \
5019 V(HANDLER) \
5020 V(BUILTIN) \
5021 V(REGEXP)
5022
5023#define IC_KIND_LIST(V) \
5024 V(LOAD_IC) \
5025 V(KEYED_LOAD_IC) \
5026 V(CALL_IC) \
5027 V(STORE_IC) \
5028 V(KEYED_STORE_IC) \
5029 V(BINARY_OP_IC) \
5030 V(COMPARE_IC) \
5031 V(COMPARE_NIL_IC) \
5032 V(TO_BOOLEAN_IC)
5033
5034#define CODE_KIND_LIST(V) \
5035 NON_IC_KIND_LIST(V) \
5036 IC_KIND_LIST(V)
Steve Blocka7e24c12009-10-30 11:49:00 +00005037
5038 enum Kind {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005039#define DEFINE_CODE_KIND_ENUM(name) name,
5040 CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
5041#undef DEFINE_CODE_KIND_ENUM
5042 NUMBER_OF_KINDS
Steve Blocka7e24c12009-10-30 11:49:00 +00005043 };
5044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005045 // No more than 16 kinds. The value is currently encoded in four bits in
5046 // Flags.
5047 STATIC_ASSERT(NUMBER_OF_KINDS <= 16);
5048
5049 static const char* Kind2String(Kind kind);
5050
5051 // Types of stubs.
5052 enum StubType {
5053 NORMAL,
5054 FAST
Steve Blocka7e24c12009-10-30 11:49:00 +00005055 };
5056
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005057 static const int kPrologueOffsetNotSet = -1;
Ben Murdochb8e0da22011-05-16 14:20:40 +01005058
Steve Blocka7e24c12009-10-30 11:49:00 +00005059#ifdef ENABLE_DISASSEMBLER
5060 // Printing
Steve Blocka7e24c12009-10-30 11:49:00 +00005061 static const char* ICState2String(InlineCacheState state);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005062 static const char* StubType2String(StubType type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005063 static void PrintExtraICState(std::ostream& os, // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005064 Kind kind, ExtraICState extra);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005065 void Disassemble(const char* name, std::ostream& os); // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +00005066#endif // ENABLE_DISASSEMBLER
5067
5068 // [instruction_size]: Size of the native instructions
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005069 inline int instruction_size() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00005070 inline void set_instruction_size(int value);
5071
Leon Clarkeac952652010-07-15 11:15:24 +01005072 // [relocation_info]: Code relocation information
5073 DECL_ACCESSORS(relocation_info, ByteArray)
Ben Murdochb0fe1622011-05-05 13:52:32 +01005074 void InvalidateRelocation();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005075 void InvalidateEmbeddedObjects();
Leon Clarkeac952652010-07-15 11:15:24 +01005076
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005077 // [handler_table]: Fixed array containing offsets of exception handlers.
5078 DECL_ACCESSORS(handler_table, FixedArray)
5079
Ben Murdochb0fe1622011-05-05 13:52:32 +01005080 // [deoptimization_data]: Array containing data for deopt.
5081 DECL_ACCESSORS(deoptimization_data, FixedArray)
5082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005083 // [raw_type_feedback_info]: This field stores various things, depending on
5084 // the kind of the code object.
5085 // FUNCTION => type feedback information.
5086 // STUB and ICs => major/minor key as Smi.
5087 DECL_ACCESSORS(raw_type_feedback_info, Object)
5088 inline Object* type_feedback_info();
5089 inline void set_type_feedback_info(
5090 Object* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5091 inline uint32_t stub_key();
5092 inline void set_stub_key(uint32_t key);
5093
5094 // [next_code_link]: Link for lists of optimized or deoptimized code.
5095 // Note that storage for this field is overlapped with typefeedback_info.
5096 DECL_ACCESSORS(next_code_link, Object)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005097
5098 // [gc_metadata]: Field used to hold GC related metadata. The contents of this
Ben Murdoch257744e2011-11-30 15:57:28 +00005099 // field does not have to be traced during garbage collection since
5100 // it is only used by the garbage collector itself.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005101 DECL_ACCESSORS(gc_metadata, Object)
5102
5103 // [ic_age]: Inline caching age: the value of the Heap::global_ic_age
5104 // at the moment when this object was created.
5105 inline void set_ic_age(int count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005106 inline int ic_age() const;
5107
5108 // [prologue_offset]: Offset of the function prologue, used for aging
5109 // FUNCTIONs and OPTIMIZED_FUNCTIONs.
5110 inline int prologue_offset() const;
5111 inline void set_prologue_offset(int offset);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01005112
Ben Murdochb0fe1622011-05-05 13:52:32 +01005113 // Unchecked accessors to be used during GC.
Leon Clarkeac952652010-07-15 11:15:24 +01005114 inline ByteArray* unchecked_relocation_info();
5115
Steve Blocka7e24c12009-10-30 11:49:00 +00005116 inline int relocation_size();
Steve Blocka7e24c12009-10-30 11:49:00 +00005117
Steve Blocka7e24c12009-10-30 11:49:00 +00005118 // [flags]: Various code flags.
5119 inline Flags flags();
5120 inline void set_flags(Flags flags);
5121
5122 // [flags]: Access to specific code flags.
5123 inline Kind kind();
5124 inline InlineCacheState ic_state(); // Only valid for IC stubs.
Ben Murdochb8e0da22011-05-16 14:20:40 +01005125 inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005126
5127 inline StubType type(); // Only valid for monomorphic IC stubs.
Steve Blocka7e24c12009-10-30 11:49:00 +00005128
5129 // Testers for IC stub kinds.
5130 inline bool is_inline_cache_stub();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005131 inline bool is_debug_stub();
5132 inline bool is_handler() { return kind() == HANDLER; }
Steve Blocka7e24c12009-10-30 11:49:00 +00005133 inline bool is_load_stub() { return kind() == LOAD_IC; }
5134 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; }
5135 inline bool is_store_stub() { return kind() == STORE_IC; }
5136 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; }
5137 inline bool is_call_stub() { return kind() == CALL_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005138 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; }
Ben Murdochb0fe1622011-05-05 13:52:32 +01005139 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005140 inline bool is_compare_nil_ic_stub() { return kind() == COMPARE_NIL_IC; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005141 inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005142 inline bool is_keyed_stub();
5143 inline bool is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005144 inline bool embeds_maps_weakly() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005145 Kind k = kind();
5146 return (k == LOAD_IC || k == STORE_IC || k == KEYED_LOAD_IC ||
5147 k == KEYED_STORE_IC || k == COMPARE_NIL_IC) &&
5148 ic_state() == MONOMORPHIC;
5149 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01005150
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005151 inline bool IsCodeStubOrIC();
5152
5153 inline void set_raw_kind_specific_flags1(int value);
5154 inline void set_raw_kind_specific_flags2(int value);
5155
5156 // [is_crankshafted]: For kind STUB or ICs, tells whether or not a code
5157 // object was generated by either the hydrogen or the TurboFan optimizing
5158 // compiler (but it may not be an optimized function).
5159 inline bool is_crankshafted();
5160 inline bool is_hydrogen_stub(); // Crankshafted, but not a function.
5161 inline void set_is_crankshafted(bool value);
5162
5163 // [is_turbofanned]: For kind STUB or OPTIMIZED_FUNCTION, tells whether the
5164 // code object was generated by the TurboFan optimizing compiler.
5165 inline bool is_turbofanned();
5166 inline void set_is_turbofanned(bool value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005167
Ben Murdochb0fe1622011-05-05 13:52:32 +01005168 // [optimizable]: For FUNCTION kind, tells if it is optimizable.
5169 inline bool optimizable();
5170 inline void set_optimizable(bool value);
5171
5172 // [has_deoptimization_support]: For FUNCTION kind, tells if it has
5173 // deoptimization support.
5174 inline bool has_deoptimization_support();
5175 inline void set_has_deoptimization_support(bool value);
5176
Ben Murdoch589d6972011-11-30 16:04:58 +00005177 // [has_debug_break_slots]: For FUNCTION kind, tells if it has
5178 // been compiled with debug break slots.
5179 inline bool has_debug_break_slots();
5180 inline void set_has_debug_break_slots(bool value);
5181
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005182 // [compiled_with_optimizing]: For FUNCTION kind, tells if it has
5183 // been compiled with IsOptimizing set to true.
5184 inline bool is_compiled_optimizable();
5185 inline void set_compiled_optimizable(bool value);
5186
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005187 // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its
5188 // reloc info includes runtime and external references to support
5189 // serialization/deserialization.
5190 inline bool has_reloc_info_for_serialization();
5191 inline void set_has_reloc_info_for_serialization(bool value);
5192
Ben Murdochb0fe1622011-05-05 13:52:32 +01005193 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
5194 // how long the function has been marked for OSR and therefore which
5195 // level of loop nesting we are willing to do on-stack replacement
5196 // for.
5197 inline void set_allow_osr_at_loop_nesting_level(int level);
5198 inline int allow_osr_at_loop_nesting_level();
5199
Ben Murdoch8f9999f2012-04-23 10:39:17 +01005200 // [profiler_ticks]: For FUNCTION kind, tells for how many profiler ticks
5201 // the code object was seen on the stack with no IC patching going on.
5202 inline int profiler_ticks();
5203 inline void set_profiler_ticks(int ticks);
5204
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005205 // [builtin_index]: For BUILTIN kind, tells which builtin index it has.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005206 // For builtins, tells which builtin index it has.
5207 // Note that builtins can have a code kind other than BUILTIN, which means
5208 // that for arbitrary code objects, this index value may be random garbage.
5209 // To verify in that case, compare the code object to the indexed builtin.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005210 inline int builtin_index();
5211 inline void set_builtin_index(int id);
5212
Ben Murdochb0fe1622011-05-05 13:52:32 +01005213 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots
5214 // reserved in the code prologue.
5215 inline unsigned stack_slots();
5216 inline void set_stack_slots(unsigned slots);
5217
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005218 // [safepoint_table_start]: For kind OPTIMIZED_FUNCTION, the offset in
Ben Murdochb0fe1622011-05-05 13:52:32 +01005219 // the instruction stream where the safepoint table starts.
Steve Block1e0659c2011-05-24 12:43:12 +01005220 inline unsigned safepoint_table_offset();
5221 inline void set_safepoint_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005222
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005223 // [back_edge_table_start]: For kind FUNCTION, the offset in the
5224 // instruction stream where the back edge table starts.
5225 inline unsigned back_edge_table_offset();
5226 inline void set_back_edge_table_offset(unsigned offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005227
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005228 inline bool back_edges_patched_for_osr();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005229
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005230 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
5231 inline byte to_boolean_state();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00005232
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005233 // [has_function_cache]: For kind STUB tells whether there is a function
5234 // cache is passed to the stub.
5235 inline bool has_function_cache();
5236 inline void set_has_function_cache(bool flag);
5237
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005238
5239 // [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether
5240 // the code is going to be deoptimized because of dead embedded maps.
5241 inline bool marked_for_deoptimization();
5242 inline void set_marked_for_deoptimization(bool flag);
5243
5244 // [constant_pool]: The constant pool for this function.
5245 inline ConstantPoolArray* constant_pool();
5246 inline void set_constant_pool(Object* constant_pool);
5247
Ben Murdochb8e0da22011-05-16 14:20:40 +01005248 // Get the safepoint entry for the given pc.
5249 SafepointEntry GetSafepointEntry(Address pc);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005250
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005251 // Find an object in a stub with a specified map
5252 Object* FindNthObject(int n, Map* match_map);
5253
5254 // Find the first allocation site in an IC stub.
5255 AllocationSite* FindFirstAllocationSite();
Ben Murdochb0fe1622011-05-05 13:52:32 +01005256
5257 // Find the first map in an IC stub.
5258 Map* FindFirstMap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005259 void FindAllMaps(MapHandleList* maps);
Steve Blocka7e24c12009-10-30 11:49:00 +00005260
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005261 // Find the first handler in an IC stub.
5262 Code* FindFirstHandler();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005263
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005264 // Find |length| handlers and put them into |code_list|. Returns false if not
5265 // enough handlers can be found.
5266 bool FindHandlers(CodeHandleList* code_list, int length = -1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005267
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005268 // Find the handler for |map|.
5269 MaybeHandle<Code> FindHandlerForMap(Map* map);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005270
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005271 // Find the first name in an IC stub.
5272 Name* FindFirstName();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005273
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005274 class FindAndReplacePattern;
5275 // For each (map-to-find, object-to-replace) pair in the pattern, this
5276 // function replaces the corresponding placeholder in the code with the
5277 // object-to-replace. The function assumes that pairs in the pattern come in
5278 // the same order as the placeholders in the code.
5279 void FindAndReplace(const FindAndReplacePattern& pattern);
5280
5281 // The entire code object including its header is copied verbatim to the
5282 // snapshot so that it can be written in one, fast, memcpy during
5283 // deserialization. The deserializer will overwrite some pointers, rather
5284 // like a runtime linker, but the random allocation addresses used in the
5285 // mksnapshot process would still be present in the unlinked snapshot data,
5286 // which would make snapshot production non-reproducible. This method wipes
5287 // out the to-be-overwritten header data for reproducible snapshots.
5288 inline void WipeOutHeader();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005289
Steve Blocka7e24c12009-10-30 11:49:00 +00005290 // Flags operations.
Ben Murdochb8e0da22011-05-16 14:20:40 +01005291 static inline Flags ComputeFlags(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005292 Kind kind, InlineCacheState ic_state = UNINITIALIZED,
5293 ExtraICState extra_ic_state = kNoExtraICState, StubType type = NORMAL,
5294 CacheHolderFlag holder = kCacheOnReceiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00005295
5296 static inline Flags ComputeMonomorphicFlags(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005297 Kind kind, ExtraICState extra_ic_state = kNoExtraICState,
5298 CacheHolderFlag holder = kCacheOnReceiver, StubType type = NORMAL);
5299
5300 static inline Flags ComputeHandlerFlags(
5301 Kind handler_kind, StubType type = NORMAL,
5302 CacheHolderFlag holder = kCacheOnReceiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00005303
Steve Blocka7e24c12009-10-30 11:49:00 +00005304 static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005305 static inline StubType ExtractTypeFromFlags(Flags flags);
5306 static inline CacheHolderFlag ExtractCacheHolderFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00005307 static inline Kind ExtractKindFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00005308 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
Ben Murdoch589d6972011-11-30 16:04:58 +00005309
Steve Blocka7e24c12009-10-30 11:49:00 +00005310 static inline Flags RemoveTypeFromFlags(Flags flags);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005311 static inline Flags RemoveTypeAndHolderFromFlags(Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00005312
5313 // Convert a target address into a code object.
5314 static inline Code* GetCodeFromTargetAddress(Address address);
5315
Steve Block791712a2010-08-27 10:21:07 +01005316 // Convert an entry address into an object.
5317 static inline Object* GetObjectFromEntryAddress(Address location_of_address);
5318
Steve Blocka7e24c12009-10-30 11:49:00 +00005319 // Returns the address of the first instruction.
5320 inline byte* instruction_start();
5321
Leon Clarkeac952652010-07-15 11:15:24 +01005322 // Returns the address right after the last instruction.
5323 inline byte* instruction_end();
5324
Steve Blocka7e24c12009-10-30 11:49:00 +00005325 // Returns the size of the instructions, padding, and relocation information.
5326 inline int body_size();
5327
5328 // Returns the address of the first relocation info (read backwards!).
5329 inline byte* relocation_start();
5330
5331 // Code entry point.
5332 inline byte* entry();
5333
5334 // Returns true if pc is inside this object's instructions.
5335 inline bool contains(byte* pc);
5336
Steve Blocka7e24c12009-10-30 11:49:00 +00005337 // Relocate the code by delta bytes. Called to signal that this code
5338 // object has been moved by delta bytes.
Steve Blockd0582a62009-12-15 09:54:21 +00005339 void Relocate(intptr_t delta);
Steve Blocka7e24c12009-10-30 11:49:00 +00005340
5341 // Migrate code described by desc.
5342 void CopyFrom(const CodeDesc& desc);
5343
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005344 // Returns the object size for a given body (used for allocation).
5345 static int SizeFor(int body_size) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005346 DCHECK_SIZE_TAG_ALIGNED(body_size);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005347 return RoundUp(kHeaderSize + body_size, kCodeAlignment);
Steve Blocka7e24c12009-10-30 11:49:00 +00005348 }
5349
5350 // Calculate the size of the code object to report for log events. This takes
5351 // the layout of the code object into account.
5352 int ExecutableSize() {
5353 // Check that the assumptions about the layout of the code object holds.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005354 DCHECK_EQ(static_cast<int>(instruction_start() - address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00005355 Code::kHeaderSize);
5356 return instruction_size() + Code::kHeaderSize;
5357 }
5358
5359 // Locating source position.
5360 int SourcePosition(Address pc);
5361 int SourceStatementPosition(Address pc);
5362
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005363 DECLARE_CAST(Code)
Steve Blocka7e24c12009-10-30 11:49:00 +00005364
5365 // Dispatched behavior.
Ben Murdoch3bec4d22010-07-22 14:51:16 +01005366 int CodeSize() { return SizeFor(body_size()); }
Iain Merrick75681382010-08-19 15:07:18 +01005367 inline void CodeIterateBody(ObjectVisitor* v);
5368
5369 template<typename StaticVisitor>
Steve Block44f0eee2011-05-26 01:26:41 +01005370 inline void CodeIterateBody(Heap* heap);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005371
5372 DECLARE_PRINTER(Code)
5373 DECLARE_VERIFIER(Code)
5374
Ben Murdoch8f9999f2012-04-23 10:39:17 +01005375 void ClearInlineCaches();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005376 void ClearInlineCaches(Kind kind);
5377
5378 BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
5379 uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
5380
5381#define DECLARE_CODE_AGE_ENUM(X) k##X##CodeAge,
5382 enum Age {
5383 kNotExecutedCodeAge = -2,
5384 kExecutedOnceCodeAge = -1,
5385 kNoAgeCodeAge = 0,
5386 CODE_AGE_LIST(DECLARE_CODE_AGE_ENUM)
5387 kAfterLastCodeAge,
5388 kFirstCodeAge = kNotExecutedCodeAge,
5389 kLastCodeAge = kAfterLastCodeAge - 1,
5390 kCodeAgeCount = kAfterLastCodeAge - kNotExecutedCodeAge - 1,
5391 kIsOldCodeAge = kSexagenarianCodeAge,
5392 kPreAgedCodeAge = kIsOldCodeAge - 1
5393 };
5394#undef DECLARE_CODE_AGE_ENUM
5395
5396 // Code aging. Indicates how many full GCs this code has survived without
5397 // being entered through the prologue. Used to determine when it is
5398 // relatively safe to flush this code object and replace it with the lazy
5399 // compilation stub.
5400 static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate);
5401 static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005402 void MakeYoung(Isolate* isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005403 void MakeOlder(MarkingParity);
5404 static bool IsYoungSequence(Isolate* isolate, byte* sequence);
5405 bool IsOld();
5406 Age GetAge();
5407 // Gets the raw code age, including psuedo code-age values such as
5408 // kNotExecutedCodeAge and kExecutedOnceCodeAge.
5409 Age GetRawAge();
5410 static inline Code* GetPreAgedCodeAgeStub(Isolate* isolate) {
5411 return GetCodeAgeStub(isolate, kNotExecutedCodeAge, NO_MARKING_PARITY);
5412 }
5413
5414 void PrintDeoptLocation(FILE* out, int bailout_id);
5415 bool CanDeoptAt(Address pc);
5416
5417#ifdef VERIFY_HEAP
5418 void VerifyEmbeddedObjectsDependency();
5419#endif
5420
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005421#ifdef DEBUG
5422 void VerifyEmbeddedObjectsInFullCode();
5423#endif // DEBUG
5424
5425 inline bool CanContainWeakObjects() { return is_optimized_code(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005426
5427 inline bool IsWeakObject(Object* object) {
5428 return (is_optimized_code() && !is_turbofanned() &&
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005429 IsWeakObjectInOptimizedCode(object));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005430 }
5431
5432 static inline bool IsWeakObjectInOptimizedCode(Object* object);
Ben Murdochb0fe1622011-05-05 13:52:32 +01005433
5434 // Max loop nesting marker used to postpose OSR. We don't take loop
5435 // nesting that is deeper than 5 levels into account.
5436 static const int kMaxLoopNestingMarker = 6;
5437
Steve Blocka7e24c12009-10-30 11:49:00 +00005438 // Layout description.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005439 static const int kRelocationInfoOffset = HeapObject::kHeaderSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005440 static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005441 static const int kDeoptimizationDataOffset =
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005442 kHandlerTableOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005443 // For FUNCTION kind, we store the type feedback info here.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005444 static const int kTypeFeedbackInfoOffset =
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01005445 kDeoptimizationDataOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005446 static const int kNextCodeLinkOffset = kTypeFeedbackInfoOffset + kPointerSize;
5447 static const int kGCMetadataOffset = kNextCodeLinkOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005448 static const int kInstructionSizeOffset = kGCMetadataOffset + kPointerSize;
5449 static const int kICAgeOffset = kInstructionSizeOffset + kIntSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005450 static const int kFlagsOffset = kICAgeOffset + kIntSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005451 static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize;
5452 static const int kKindSpecificFlags2Offset =
5453 kKindSpecificFlags1Offset + kIntSize;
5454 // Note: We might be able to squeeze this into the flags above.
5455 static const int kPrologueOffset = kKindSpecificFlags2Offset + kIntSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005456 static const int kConstantPoolOffset = kPrologueOffset + kIntSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005457
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005458 static const int kHeaderPaddingStart = kConstantPoolOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01005459
Steve Blocka7e24c12009-10-30 11:49:00 +00005460 // Add padding to align the instruction start following right after
5461 // the Code object header.
5462 static const int kHeaderSize =
Ben Murdochb0fe1622011-05-05 13:52:32 +01005463 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005464 // Ensure that the slot for the constant pool pointer is aligned.
5465 STATIC_ASSERT((kConstantPoolOffset & kPointerAlignmentMask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00005466
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005467 // Byte offsets within kKindSpecificFlags1Offset.
5468 static const int kOptimizableOffset = kKindSpecificFlags1Offset;
Ben Murdoch589d6972011-11-30 16:04:58 +00005469
5470 static const int kFullCodeFlags = kOptimizableOffset + 1;
5471 class FullCodeFlagsHasDeoptimizationSupportField:
5472 public BitField<bool, 0, 1> {}; // NOLINT
5473 class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005474 class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005475 class FullCodeFlagsHasRelocInfoForSerialization
5476 : public BitField<bool, 3, 1> {};
Ben Murdochb0fe1622011-05-05 13:52:32 +01005477
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005478 static const int kProfilerTicksOffset = kFullCodeFlags + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00005479
Ben Murdoch589d6972011-11-30 16:04:58 +00005480 // Flags layout. BitField<type, shift, size>.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005481 class ICStateField : public BitField<InlineCacheState, 0, 4> {};
5482 class TypeField : public BitField<StubType, 4, 1> {};
5483 class CacheHolderField : public BitField<CacheHolderFlag, 5, 2> {};
5484 class KindField : public BitField<Kind, 7, 4> {};
5485 class ExtraICStateField: public BitField<ExtraICState, 11,
5486 PlatformSmiTagging::kSmiValueSize - 11 + 1> {}; // NOLINT
Steve Blocka7e24c12009-10-30 11:49:00 +00005487
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005488 // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
5489 static const int kStackSlotsFirstBit = 0;
5490 static const int kStackSlotsBitCount = 24;
5491 static const int kHasFunctionCacheBit =
5492 kStackSlotsFirstBit + kStackSlotsBitCount;
5493 static const int kMarkedForDeoptimizationBit = kHasFunctionCacheBit + 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005494 static const int kIsTurbofannedBit = kMarkedForDeoptimizationBit + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005495
5496 STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
5497 STATIC_ASSERT(kIsTurbofannedBit + 1 <= 32);
5498
5499 class StackSlotsField: public BitField<int,
5500 kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
5501 class HasFunctionCacheField : public BitField<bool, kHasFunctionCacheBit, 1> {
5502 }; // NOLINT
5503 class MarkedForDeoptimizationField
5504 : public BitField<bool, kMarkedForDeoptimizationBit, 1> {}; // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005505 class IsTurbofannedField : public BitField<bool, kIsTurbofannedBit, 1> {
5506 }; // NOLINT
5507
5508 // KindSpecificFlags2 layout (ALL)
5509 static const int kIsCrankshaftedBit = 0;
5510 class IsCrankshaftedField: public BitField<bool,
5511 kIsCrankshaftedBit, 1> {}; // NOLINT
5512
5513 // KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION)
5514 static const int kSafepointTableOffsetFirstBit = kIsCrankshaftedBit + 1;
5515 static const int kSafepointTableOffsetBitCount = 24;
5516
5517 STATIC_ASSERT(kSafepointTableOffsetFirstBit +
5518 kSafepointTableOffsetBitCount <= 32);
5519 STATIC_ASSERT(1 + kSafepointTableOffsetBitCount <= 32);
5520
5521 class SafepointTableOffsetField: public BitField<int,
5522 kSafepointTableOffsetFirstBit,
5523 kSafepointTableOffsetBitCount> {}; // NOLINT
5524
5525 // KindSpecificFlags2 layout (FUNCTION)
5526 class BackEdgeTableOffsetField: public BitField<int,
5527 kIsCrankshaftedBit + 1, 27> {}; // NOLINT
5528 class AllowOSRAtLoopNestingLevelField: public BitField<int,
5529 kIsCrankshaftedBit + 1 + 27, 4> {}; // NOLINT
5530 STATIC_ASSERT(AllowOSRAtLoopNestingLevelField::kMax >= kMaxLoopNestingMarker);
5531
5532 static const int kArgumentsBits = 16;
5533 static const int kMaxArguments = (1 << kArgumentsBits) - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00005534
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005535 // This constant should be encodable in an ARM instruction.
Steve Blocka7e24c12009-10-30 11:49:00 +00005536 static const int kFlagsNotUsedInLookup =
Ben Murdoch589d6972011-11-30 16:04:58 +00005537 TypeField::kMask | CacheHolderField::kMask;
Steve Blocka7e24c12009-10-30 11:49:00 +00005538
5539 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005540 friend class RelocIterator;
5541 friend class Deoptimizer; // For FindCodeAgeSequence.
5542
5543 void ClearInlineCaches(Kind* kind);
5544
5545 // Code aging
5546 byte* FindCodeAgeSequence();
5547 static void GetCodeAgeAndParity(Code* code, Age* age,
5548 MarkingParity* parity);
5549 static void GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
5550 MarkingParity* parity);
5551 static Code* GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity);
5552
5553 // Code aging -- platform-specific
5554 static void PatchPlatformCodeAge(Isolate* isolate,
5555 byte* sequence, Age age,
5556 MarkingParity parity);
5557
Steve Blocka7e24c12009-10-30 11:49:00 +00005558 DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
5559};
5560
5561
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005562class CompilationInfo;
5563
5564// This class describes the layout of dependent codes array of a map. The
5565// array is partitioned into several groups of dependent codes. Each group
5566// contains codes with the same dependency on the map. The array has the
5567// following layout for n dependency groups:
5568//
5569// +----+----+-----+----+---------+----------+-----+---------+-----------+
5570// | C1 | C2 | ... | Cn | group 1 | group 2 | ... | group n | undefined |
5571// +----+----+-----+----+---------+----------+-----+---------+-----------+
5572//
5573// The first n elements are Smis, each of them specifies the number of codes
5574// in the corresponding group. The subsequent elements contain grouped code
5575// objects. The suffix of the array can be filled with the undefined value if
5576// the number of codes is less than the length of the array. The order of the
5577// code objects within a group is not preserved.
5578//
5579// All code indexes used in the class are counted starting from the first
5580// code object of the first group. In other words, code index 0 corresponds
5581// to array index n = kCodesStartIndex.
5582
5583class DependentCode: public FixedArray {
5584 public:
5585 enum DependencyGroup {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005586 // Group of code that weakly embed this map and depend on being
5587 // deoptimized when the map is garbage collected.
5588 kWeakCodeGroup,
5589 // Group of code that embed a transition to this map, and depend on being
5590 // deoptimized when the transition is replaced by a new version.
5591 kTransitionGroup,
5592 // Group of code that omit run-time prototype checks for prototypes
5593 // described by this map. The group is deoptimized whenever an object
5594 // described by this map changes shape (and transitions to a new map),
5595 // possibly invalidating the assumptions embedded in the code.
5596 kPrototypeCheckGroup,
5597 // Group of code that depends on elements not being added to objects with
5598 // this map.
5599 kElementsCantBeAddedGroup,
5600 // Group of code that depends on global property values in property cells
5601 // not being changed.
5602 kPropertyCellChangedGroup,
5603 // Group of code that omit run-time type checks for the field(s) introduced
5604 // by this map.
5605 kFieldTypeGroup,
5606 // Group of code that omit run-time type checks for initial maps of
5607 // constructors.
5608 kInitialMapChangedGroup,
5609 // Group of code that depends on tenuring information in AllocationSites
5610 // not being changed.
5611 kAllocationSiteTenuringChangedGroup,
5612 // Group of code that depends on element transition information in
5613 // AllocationSites not being changed.
5614 kAllocationSiteTransitionChangedGroup
5615 };
5616
5617 static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1;
5618
5619 // Array for holding the index of the first code object of each group.
5620 // The last element stores the total number of code objects.
5621 class GroupStartIndexes {
5622 public:
5623 explicit GroupStartIndexes(DependentCode* entries);
5624 void Recompute(DependentCode* entries);
5625 int at(int i) { return start_indexes_[i]; }
5626 int number_of_entries() { return start_indexes_[kGroupCount]; }
5627 private:
5628 int start_indexes_[kGroupCount + 1];
5629 };
5630
5631 bool Contains(DependencyGroup group, Code* code);
5632 static Handle<DependentCode> Insert(Handle<DependentCode> entries,
5633 DependencyGroup group,
5634 Handle<Object> object);
5635 void UpdateToFinishedCode(DependencyGroup group,
5636 CompilationInfo* info,
5637 Code* code);
5638 void RemoveCompilationInfo(DependentCode::DependencyGroup group,
5639 CompilationInfo* info);
5640
5641 void DeoptimizeDependentCodeGroup(Isolate* isolate,
5642 DependentCode::DependencyGroup group);
5643
5644 bool MarkCodeForDeoptimization(Isolate* isolate,
5645 DependentCode::DependencyGroup group);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005646
5647 // The following low-level accessors should only be used by this class
5648 // and the mark compact collector.
5649 inline int number_of_entries(DependencyGroup group);
5650 inline void set_number_of_entries(DependencyGroup group, int value);
5651 inline bool is_code_at(int i);
5652 inline Code* code_at(int i);
5653 inline CompilationInfo* compilation_info_at(int i);
5654 inline void set_object_at(int i, Object* object);
5655 inline Object** slot_at(int i);
5656 inline Object* object_at(int i);
5657 inline void clear_at(int i);
5658 inline void copy(int from, int to);
5659 DECLARE_CAST(DependentCode)
5660
5661 static DependentCode* ForObject(Handle<HeapObject> object,
5662 DependencyGroup group);
5663
5664 static const char* DependencyGroupName(DependencyGroup group);
5665 static void SetMarkedForDeoptimization(Code* code, DependencyGroup group);
5666
5667 private:
5668 // Make a room at the end of the given group by moving out the first
5669 // code objects of the subsequent groups.
5670 inline void ExtendGroup(DependencyGroup group);
5671 static const int kCodesStartIndex = kGroupCount;
5672};
5673
5674
Steve Blocka7e24c12009-10-30 11:49:00 +00005675// All heap objects have a Map that describes their structure.
5676// A Map contains information about:
5677// - Size information about the object
5678// - How to iterate over an object (for garbage collection)
5679class Map: public HeapObject {
5680 public:
5681 // Instance size.
Steve Block791712a2010-08-27 10:21:07 +01005682 // Size in bytes or kVariableSizeSentinel if instances do not have
5683 // a fixed size.
Steve Blocka7e24c12009-10-30 11:49:00 +00005684 inline int instance_size();
5685 inline void set_instance_size(int value);
5686
5687 // Count of properties allocated in the object.
5688 inline int inobject_properties();
5689 inline void set_inobject_properties(int value);
5690
5691 // Count of property fields pre-allocated in the object when first allocated.
5692 inline int pre_allocated_property_fields();
5693 inline void set_pre_allocated_property_fields(int value);
5694
5695 // Instance type.
5696 inline InstanceType instance_type();
5697 inline void set_instance_type(InstanceType value);
5698
5699 // Tells how many unused property fields are available in the
5700 // instance (only used for JSObject in fast mode).
5701 inline int unused_property_fields();
5702 inline void set_unused_property_fields(int value);
5703
5704 // Bit field.
5705 inline byte bit_field();
5706 inline void set_bit_field(byte value);
5707
5708 // Bit field 2.
5709 inline byte bit_field2();
5710 inline void set_bit_field2(byte value);
5711
Ben Murdoch257744e2011-11-30 15:57:28 +00005712 // Bit field 3.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005713 inline uint32_t bit_field3();
5714 inline void set_bit_field3(uint32_t bits);
5715
5716 class EnumLengthBits: public BitField<int,
5717 0, kDescriptorIndexBitCount> {}; // NOLINT
5718 class NumberOfOwnDescriptorsBits: public BitField<int,
5719 kDescriptorIndexBitCount, kDescriptorIndexBitCount> {}; // NOLINT
5720 STATIC_ASSERT(kDescriptorIndexBitCount + kDescriptorIndexBitCount == 20);
5721 class DictionaryMap : public BitField<bool, 20, 1> {};
5722 class OwnsDescriptors : public BitField<bool, 21, 1> {};
5723 class HasInstanceCallHandler : public BitField<bool, 22, 1> {};
5724 class Deprecated : public BitField<bool, 23, 1> {};
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005725 class IsUnstable : public BitField<bool, 24, 1> {};
5726 class IsMigrationTarget : public BitField<bool, 25, 1> {};
5727 // Bits 26 and 27 are free.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005728
5729 // Keep this bit field at the very end for better code in
5730 // Builtins::kJSConstructStubGeneric stub.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005731 // This counter is used for in-object slack tracking and for map aging.
5732 // The in-object slack tracking is considered enabled when the counter is
5733 // in the range [kSlackTrackingCounterStart, kSlackTrackingCounterEnd].
5734 class Counter : public BitField<int, 28, 4> {};
5735 static const int kSlackTrackingCounterStart = 14;
5736 static const int kSlackTrackingCounterEnd = 8;
5737 static const int kRetainingCounterStart = kSlackTrackingCounterEnd - 1;
5738 static const int kRetainingCounterEnd = 0;
Ben Murdoch257744e2011-11-30 15:57:28 +00005739
Steve Blocka7e24c12009-10-30 11:49:00 +00005740 // Tells whether the object in the prototype property will be used
5741 // for instances created from this function. If the prototype
5742 // property is set to a value that is not a JSObject, the prototype
5743 // property will not be used to create instances of the function.
5744 // See ECMA-262, 13.2.2.
5745 inline void set_non_instance_prototype(bool value);
5746 inline bool has_non_instance_prototype();
5747
Steve Block6ded16b2010-05-10 14:33:55 +01005748 // Tells whether function has special prototype property. If not, prototype
5749 // property will not be created when accessed (will return undefined),
5750 // and construction from this function will not be allowed.
5751 inline void set_function_with_prototype(bool value);
5752 inline bool function_with_prototype();
5753
Steve Blocka7e24c12009-10-30 11:49:00 +00005754 // Tells whether the instance with this map should be ignored by the
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005755 // Object.getPrototypeOf() function and the __proto__ accessor.
Steve Blocka7e24c12009-10-30 11:49:00 +00005756 inline void set_is_hidden_prototype() {
5757 set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
5758 }
5759
5760 inline bool is_hidden_prototype() {
5761 return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
5762 }
5763
5764 // Records and queries whether the instance has a named interceptor.
5765 inline void set_has_named_interceptor() {
5766 set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
5767 }
5768
5769 inline bool has_named_interceptor() {
5770 return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
5771 }
5772
5773 // Records and queries whether the instance has an indexed interceptor.
5774 inline void set_has_indexed_interceptor() {
5775 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
5776 }
5777
5778 inline bool has_indexed_interceptor() {
5779 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
5780 }
5781
5782 // Tells whether the instance is undetectable.
5783 // An undetectable object is a special class of JSObject: 'typeof' operator
5784 // returns undefined, ToBoolean returns false. Otherwise it behaves like
5785 // a normal JS object. It is useful for implementing undetectable
5786 // document.all in Firefox & Safari.
5787 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
5788 inline void set_is_undetectable() {
5789 set_bit_field(bit_field() | (1 << kIsUndetectable));
5790 }
5791
5792 inline bool is_undetectable() {
5793 return ((1 << kIsUndetectable) & bit_field()) != 0;
5794 }
5795
Steve Blocka7e24c12009-10-30 11:49:00 +00005796 // Tells whether the instance has a call-as-function handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005797 inline void set_is_observed() {
5798 set_bit_field(bit_field() | (1 << kIsObserved));
Steve Blocka7e24c12009-10-30 11:49:00 +00005799 }
5800
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005801 inline bool is_observed() {
5802 return ((1 << kIsObserved) & bit_field()) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00005803 }
5804
Steve Block8defd9f2010-07-08 12:39:36 +01005805 inline void set_is_extensible(bool value);
5806 inline bool is_extensible();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005807 inline void set_is_prototype_map(bool value);
5808 inline bool is_prototype_map();
Steve Block8defd9f2010-07-08 12:39:36 +01005809
Ben Murdoch589d6972011-11-30 16:04:58 +00005810 inline void set_elements_kind(ElementsKind elements_kind) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005811 DCHECK(static_cast<int>(elements_kind) < kElementsKindCount);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005812 DCHECK(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize));
5813 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind));
5814 DCHECK(this->elements_kind() == elements_kind);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005815 }
5816
Ben Murdoch589d6972011-11-30 16:04:58 +00005817 inline ElementsKind elements_kind() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005818 return Map::ElementsKindBits::decode(bit_field2());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005819 }
5820
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005821 // Tells whether the instance has fast elements that are only Smis.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005822 inline bool has_fast_smi_elements() {
5823 return IsFastSmiElementsKind(elements_kind());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005824 }
5825
Steve Block8defd9f2010-07-08 12:39:36 +01005826 // Tells whether the instance has fast elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005827 inline bool has_fast_object_elements() {
5828 return IsFastObjectElementsKind(elements_kind());
5829 }
5830
5831 inline bool has_fast_smi_or_object_elements() {
5832 return IsFastSmiOrObjectElementsKind(elements_kind());
Leon Clarkee46be812010-01-19 14:06:41 +00005833 }
5834
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005835 inline bool has_fast_double_elements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005836 return IsFastDoubleElementsKind(elements_kind());
Steve Block1e0659c2011-05-24 12:43:12 +01005837 }
5838
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005839 inline bool has_fast_elements() {
5840 return IsFastElementsKind(elements_kind());
5841 }
5842
5843 inline bool has_sloppy_arguments_elements() {
5844 return elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005845 }
5846
Steve Block44f0eee2011-05-26 01:26:41 +01005847 inline bool has_external_array_elements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005848 return IsExternalArrayElementsKind(elements_kind());
5849 }
5850
5851 inline bool has_fixed_typed_array_elements() {
5852 return IsFixedTypedArrayElementsKind(elements_kind());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005853 }
5854
5855 inline bool has_dictionary_elements() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005856 return IsDictionaryElementsKind(elements_kind());
Steve Block1e0659c2011-05-24 12:43:12 +01005857 }
5858
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005859 inline bool has_slow_elements_kind() {
5860 return elements_kind() == DICTIONARY_ELEMENTS
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005861 || elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005862 }
5863
5864 static bool IsValidElementsTransition(ElementsKind from_kind,
5865 ElementsKind to_kind);
5866
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005867 // Returns true if the current map doesn't have DICTIONARY_ELEMENTS but if a
5868 // map with DICTIONARY_ELEMENTS was found in the prototype chain.
5869 bool DictionaryElementsInPrototypeChainOnly();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005870
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005871 inline bool HasTransitionArray() const;
5872 inline bool HasElementsTransition();
5873 inline Map* elements_transition_map();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005874
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005875 inline Map* GetTransition(int transition_index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005876 inline int SearchSpecialTransition(Symbol* name);
5877 inline int SearchTransition(PropertyKind kind, Name* name,
5878 PropertyAttributes attributes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005879 inline FixedArrayBase* GetInitialElements();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005880
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005881 DECL_ACCESSORS(transitions, TransitionArray)
5882
5883 static inline Handle<String> ExpectedTransitionKey(Handle<Map> map);
5884 static inline Handle<Map> ExpectedTransitionTarget(Handle<Map> map);
5885
5886 // Try to follow an existing transition to a field with attributes NONE. The
5887 // return value indicates whether the transition was successful.
5888 static inline Handle<Map> FindTransitionToField(Handle<Map> map,
5889 Handle<Name> key);
5890
5891 Map* FindRootMap();
5892 Map* FindFieldOwner(int descriptor);
5893
5894 inline int GetInObjectPropertyOffset(int index);
5895
5896 int NumberOfFields();
5897
5898 // TODO(ishell): candidate with JSObject::MigrateToMap().
5899 bool InstancesNeedRewriting(Map* target, int target_number_of_fields,
5900 int target_inobject, int target_unused,
5901 int* old_number_of_fields);
5902 // TODO(ishell): moveit!
5903 static Handle<Map> GeneralizeAllFieldRepresentations(Handle<Map> map);
5904 MUST_USE_RESULT static Handle<HeapType> GeneralizeFieldType(
5905 Handle<HeapType> type1,
5906 Handle<HeapType> type2,
5907 Isolate* isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005908 static void GeneralizeFieldType(Handle<Map> map, int modify_index,
5909 Representation new_representation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005910 Handle<HeapType> new_field_type);
5911 static Handle<Map> GeneralizeRepresentation(
5912 Handle<Map> map,
5913 int modify_index,
5914 Representation new_representation,
5915 Handle<HeapType> new_field_type,
5916 StoreMode store_mode);
5917 static Handle<Map> CopyGeneralizeAllRepresentations(
5918 Handle<Map> map,
5919 int modify_index,
5920 StoreMode store_mode,
5921 PropertyAttributes attributes,
5922 const char* reason);
5923 static Handle<Map> CopyGeneralizeAllRepresentations(
5924 Handle<Map> map,
5925 int modify_index,
5926 StoreMode store_mode,
5927 const char* reason);
5928
5929 static Handle<Map> PrepareForDataProperty(Handle<Map> old_map,
5930 int descriptor_number,
5931 Handle<Object> value);
5932
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005933 static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode,
5934 const char* reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005935
5936 // Returns the constructor name (the name (possibly, inferred name) of the
5937 // function that was used to instantiate the object).
5938 String* constructor_name();
5939
5940 // Tells whether the map is used for JSObjects in dictionary mode (ie
5941 // normalized objects, ie objects for which HasFastProperties returns false).
5942 // A map can never be used for both dictionary mode and fast mode JSObjects.
5943 // False by default and for HeapObjects that are not JSObjects.
5944 inline void set_dictionary_map(bool value);
5945 inline bool is_dictionary_map();
Kristian Monsen0d5e1162010-09-30 15:31:59 +01005946
Steve Blocka7e24c12009-10-30 11:49:00 +00005947 // Tells whether the instance needs security checks when accessing its
5948 // properties.
5949 inline void set_is_access_check_needed(bool access_check_needed);
5950 inline bool is_access_check_needed();
5951
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005952 // Returns true if map has a non-empty stub code cache.
5953 inline bool has_code_cache();
5954
Steve Blocka7e24c12009-10-30 11:49:00 +00005955 // [prototype]: implicit prototype object.
5956 DECL_ACCESSORS(prototype, Object)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005957 // TODO(jkummerow): make set_prototype private.
5958 void SetPrototype(Handle<Object> prototype,
5959 PrototypeOptimizationMode proto_mode = FAST_PROTOTYPE);
5960 bool ShouldRegisterAsPrototypeUser(Handle<JSObject> prototype);
5961 bool CanUseOptimizationsBasedOnPrototypeRegistry();
Steve Blocka7e24c12009-10-30 11:49:00 +00005962
5963 // [constructor]: points back to the function responsible for this map.
5964 DECL_ACCESSORS(constructor, Object)
5965
5966 // [instance descriptors]: describes the object.
5967 DECL_ACCESSORS(instance_descriptors, DescriptorArray)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005968
5969 // [layout descriptor]: describes the object layout.
5970 DECL_ACCESSORS(layout_descriptor, LayoutDescriptor)
5971 // |layout descriptor| accessor which can be used from GC.
5972 inline LayoutDescriptor* layout_descriptor_gc_safe();
5973 inline bool HasFastPointerLayout() const;
5974
5975 // |layout descriptor| accessor that is safe to call even when
5976 // FLAG_unbox_double_fields is disabled (in this case Map does not contain
5977 // |layout_descriptor| field at all).
5978 inline LayoutDescriptor* GetLayoutDescriptor();
5979
5980 inline void UpdateDescriptors(DescriptorArray* descriptors,
5981 LayoutDescriptor* layout_descriptor);
5982 inline void InitializeDescriptors(DescriptorArray* descriptors,
5983 LayoutDescriptor* layout_descriptor);
Ben Murdoch257744e2011-11-30 15:57:28 +00005984
Steve Blocka7e24c12009-10-30 11:49:00 +00005985 // [stub cache]: contains stubs compiled for this map.
Steve Block6ded16b2010-05-10 14:33:55 +01005986 DECL_ACCESSORS(code_cache, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00005987
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005988 // [dependent code]: list of optimized codes that weakly embed this map.
5989 DECL_ACCESSORS(dependent_code, DependentCode)
5990
5991 // [back pointer]: points back to the parent map from which a transition
5992 // leads to this map. The field overlaps with prototype transitions and the
5993 // back pointer will be moved into the prototype transitions array if
5994 // required.
5995 inline Object* GetBackPointer();
5996 inline void SetBackPointer(Object* value,
5997 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
5998 inline void init_back_pointer(Object* undefined);
5999
Steve Block053d10c2011-06-13 19:13:29 +01006000 // [prototype transitions]: cache of prototype transitions.
6001 // Prototype transition is a transition that happens
6002 // when we change object's prototype to a new one.
6003 // Cache format:
6004 // 0: finger - index of the first free cell in the cache
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006005 // 1: back pointer that overlaps with prototype transitions field.
6006 // 2 + 2 * i: prototype
6007 // 3 + 2 * i: target map
6008 inline FixedArray* GetPrototypeTransitions();
6009 inline bool HasPrototypeTransitions();
Steve Block053d10c2011-06-13 19:13:29 +01006010
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006011 static const int kProtoTransitionHeaderSize = 1;
6012 static const int kProtoTransitionNumberOfEntriesOffset = 0;
6013 static const int kProtoTransitionElementsPerEntry = 2;
6014 static const int kProtoTransitionPrototypeOffset = 0;
6015 static const int kProtoTransitionMapOffset = 1;
6016
6017 inline int NumberOfProtoTransitions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006018 FixedArray* cache = GetPrototypeTransitions();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006019 if (cache->length() == 0) return 0;
6020 return
6021 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value();
6022 }
6023
6024 inline void SetNumberOfProtoTransitions(int value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006025 FixedArray* cache = GetPrototypeTransitions();
6026 DCHECK(cache->length() != 0);
6027 cache->set(kProtoTransitionNumberOfEntriesOffset, Smi::FromInt(value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006028 }
6029
Ben Murdochb0fe1622011-05-05 13:52:32 +01006030 // Lookup in the map's instance descriptors and fill out the result
6031 // with the given holder if the name is found. The holder may be
6032 // NULL when this function is used from the compiler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006033 inline void LookupDescriptor(JSObject* holder,
6034 Name* name,
6035 LookupResult* result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006036
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006037 inline void LookupTransition(JSObject* holder, Name* name,
6038 PropertyAttributes attributes,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006039 LookupResult* result);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01006040
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006041 inline PropertyDetails GetLastDescriptorDetails();
6042
6043 // The size of transition arrays are limited so they do not end up in large
6044 // object space. Otherwise ClearNonLiveTransitions would leak memory while
6045 // applying in-place right trimming.
6046 inline bool CanHaveMoreTransitions();
6047
6048 int LastAdded() {
6049 int number_of_own_descriptors = NumberOfOwnDescriptors();
6050 DCHECK(number_of_own_descriptors > 0);
6051 return number_of_own_descriptors - 1;
6052 }
6053
6054 int NumberOfOwnDescriptors() {
6055 return NumberOfOwnDescriptorsBits::decode(bit_field3());
6056 }
6057
6058 void SetNumberOfOwnDescriptors(int number) {
6059 DCHECK(number <= instance_descriptors()->number_of_descriptors());
6060 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
6061 }
6062
6063 inline Cell* RetrieveDescriptorsPointer();
6064
6065 int EnumLength() {
6066 return EnumLengthBits::decode(bit_field3());
6067 }
6068
6069 void SetEnumLength(int length) {
6070 if (length != kInvalidEnumCacheSentinel) {
6071 DCHECK(length >= 0);
6072 DCHECK(length == 0 || instance_descriptors()->HasEnumCache());
6073 DCHECK(length <= NumberOfOwnDescriptors());
6074 }
6075 set_bit_field3(EnumLengthBits::update(bit_field3(), length));
6076 }
6077
6078 inline bool owns_descriptors();
6079 inline void set_owns_descriptors(bool owns_descriptors);
6080 inline bool has_instance_call_handler();
6081 inline void set_has_instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006082 inline void mark_unstable();
6083 inline bool is_stable();
6084 inline void set_migration_target(bool value);
6085 inline bool is_migration_target();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006086 inline void set_counter(int value);
6087 inline int counter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006088 inline void deprecate();
6089 inline bool is_deprecated();
6090 inline bool CanBeDeprecated();
6091 // Returns a non-deprecated version of the input. If the input was not
6092 // deprecated, it is directly returned. Otherwise, the non-deprecated version
6093 // is found by re-transitioning from the root of the transition tree using the
6094 // descriptor array of the map. Returns NULL if no updated map is found.
6095 // This method also applies any pending migrations along the prototype chain.
6096 static MaybeHandle<Map> TryUpdate(Handle<Map> map) WARN_UNUSED_RESULT;
6097 // Same as above, but does not touch the prototype chain.
6098 static MaybeHandle<Map> TryUpdateInternal(Handle<Map> map)
6099 WARN_UNUSED_RESULT;
6100
6101 // Returns a non-deprecated version of the input. This method may deprecate
6102 // existing maps along the way if encodings conflict. Not for use while
6103 // gathering type feedback. Use TryUpdate in those cases instead.
6104 static Handle<Map> Update(Handle<Map> map);
6105
6106 static Handle<Map> CopyDropDescriptors(Handle<Map> map);
6107 static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
6108 Descriptor* descriptor,
6109 TransitionFlag flag);
6110
6111 MUST_USE_RESULT static MaybeHandle<Map> CopyWithField(
6112 Handle<Map> map,
6113 Handle<Name> name,
6114 Handle<HeapType> type,
6115 PropertyAttributes attributes,
6116 Representation representation,
6117 TransitionFlag flag);
6118
6119 MUST_USE_RESULT static MaybeHandle<Map> CopyWithConstant(
6120 Handle<Map> map,
6121 Handle<Name> name,
6122 Handle<Object> constant,
6123 PropertyAttributes attributes,
6124 TransitionFlag flag);
6125
6126 // Returns a new map with all transitions dropped from the given map and
6127 // the ElementsKind set.
6128 static Handle<Map> TransitionElementsTo(Handle<Map> map,
6129 ElementsKind to_kind);
6130
6131 static Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind kind);
6132
6133 static Handle<Map> CopyAsElementsKind(Handle<Map> map,
6134 ElementsKind kind,
6135 TransitionFlag flag);
6136
6137 static Handle<Map> CopyForObserved(Handle<Map> map);
6138
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006139 static Handle<Map> CopyForPreventExtensions(Handle<Map> map,
6140 PropertyAttributes attrs_to_add,
6141 Handle<Symbol> transition_marker,
6142 const char* reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006143 // Maximal number of fast properties. Used to restrict the number of map
6144 // transitions to avoid an explosion in the number of maps for objects used as
6145 // dictionaries.
6146 inline bool TooManyFastProperties(StoreFromKeyed store_mode);
6147 static Handle<Map> TransitionToDataProperty(Handle<Map> map,
6148 Handle<Name> name,
6149 Handle<Object> value,
6150 PropertyAttributes attributes,
6151 StoreFromKeyed store_mode);
6152 static Handle<Map> TransitionToAccessorProperty(
6153 Handle<Map> map, Handle<Name> name, AccessorComponent component,
6154 Handle<Object> accessor, PropertyAttributes attributes);
6155 static Handle<Map> ReconfigureDataProperty(Handle<Map> map, int descriptor,
6156 PropertyAttributes attributes);
6157
6158 inline void AppendDescriptor(Descriptor* desc);
Steve Blocka7e24c12009-10-30 11:49:00 +00006159
6160 // Returns a copy of the map, with all transitions dropped from the
6161 // instance descriptors.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006162 static Handle<Map> Copy(Handle<Map> map, const char* reason);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006163 static Handle<Map> Create(Isolate* isolate, int inobject_properties);
Steve Blocka7e24c12009-10-30 11:49:00 +00006164
6165 // Returns the next free property index (only valid for FAST MODE).
6166 int NextFreePropertyIndex();
6167
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006168 // Returns the number of properties described in instance_descriptors
6169 // filtering out properties with the specified attributes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006170 int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS,
6171 PropertyAttributes filter = NONE);
Steve Blocka7e24c12009-10-30 11:49:00 +00006172
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006173 // Returns the number of slots allocated for the initial properties
6174 // backing storage for instances of this map.
6175 int InitialPropertiesLength() {
6176 return pre_allocated_property_fields() + unused_property_fields() -
6177 inobject_properties();
6178 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006179
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006180 DECLARE_CAST(Map)
Steve Blocka7e24c12009-10-30 11:49:00 +00006181
6182 // Code cache operations.
6183
6184 // Clears the code cache.
Steve Block44f0eee2011-05-26 01:26:41 +01006185 inline void ClearCodeCache(Heap* heap);
Steve Blocka7e24c12009-10-30 11:49:00 +00006186
6187 // Update code cache.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006188 static void UpdateCodeCache(Handle<Map> map,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006189 Handle<Name> name,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006190 Handle<Code> code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006191
6192 // Extend the descriptor array of the map with the list of descriptors.
6193 // In case of duplicates, the latest descriptor is used.
6194 static void AppendCallbackDescriptors(Handle<Map> map,
6195 Handle<Object> descriptors);
6196
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006197 static inline int SlackForArraySize(int old_size, int size_limit);
6198
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006199 static void EnsureDescriptorSlack(Handle<Map> map, int slack);
Steve Blocka7e24c12009-10-30 11:49:00 +00006200
6201 // Returns the found code or undefined if absent.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006202 Object* FindInCodeCache(Name* name, Code::Flags flags);
Steve Blocka7e24c12009-10-30 11:49:00 +00006203
6204 // Returns the non-negative index of the code object if it is in the
6205 // cache and -1 otherwise.
Steve Block6ded16b2010-05-10 14:33:55 +01006206 int IndexInCodeCache(Object* name, Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00006207
6208 // Removes a code object from the code cache at the given index.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006209 void RemoveFromCodeCache(Name* name, Code* code, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00006210
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006211 // Set all map transitions from this map to dead maps to null. Also clear
6212 // back pointers in transition targets so that we do not process this map
6213 // again while following back pointers.
6214 void ClearNonLiveTransitions(Heap* heap);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006215
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006216 // Computes a hash value for this map, to be used in HashTables and such.
6217 int Hash();
6218
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006219 // Returns the map that this map transitions to if its elements_kind
6220 // is changed to |elements_kind|, or NULL if no such map is cached yet.
6221 // |safe_to_add_transitions| is set to false if adding transitions is not
6222 // allowed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006223 Map* LookupElementsTransitionMap(ElementsKind elements_kind);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006224
6225 // Returns the transitioned map for this map with the most generic
6226 // elements_kind that's found in |candidates|, or null handle if no match is
6227 // found at all.
6228 Handle<Map> FindTransitionedMap(MapHandleList* candidates);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006229
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006230 bool CanTransition() {
6231 // Only JSObject and subtypes have map transitions and back pointers.
6232 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE);
6233 return instance_type() >= FIRST_JS_OBJECT_TYPE;
6234 }
6235
6236 bool IsJSObjectMap() {
6237 return instance_type() >= FIRST_JS_OBJECT_TYPE;
6238 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006239 bool IsStringMap() { return instance_type() < FIRST_NONSTRING_TYPE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006240 bool IsJSProxyMap() {
6241 InstanceType type = instance_type();
6242 return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
6243 }
6244 bool IsJSGlobalProxyMap() {
6245 return instance_type() == JS_GLOBAL_PROXY_TYPE;
6246 }
6247 bool IsJSGlobalObjectMap() {
6248 return instance_type() == JS_GLOBAL_OBJECT_TYPE;
6249 }
6250 bool IsGlobalObjectMap() {
6251 const InstanceType type = instance_type();
6252 return type == JS_GLOBAL_OBJECT_TYPE || type == JS_BUILTINS_OBJECT_TYPE;
6253 }
6254
6255 inline bool CanOmitMapChecks();
6256
6257 static void AddDependentCompilationInfo(Handle<Map> map,
6258 DependentCode::DependencyGroup group,
6259 CompilationInfo* info);
6260
6261 static void AddDependentCode(Handle<Map> map,
6262 DependentCode::DependencyGroup group,
6263 Handle<Code> code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006264
6265 bool IsMapInArrayPrototypeChain();
Ben Murdoch592a9fc2012-03-05 11:04:45 +00006266
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006267 static Handle<WeakCell> WeakCellForMap(Handle<Map> map);
6268
Steve Blocka7e24c12009-10-30 11:49:00 +00006269 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006270 DECLARE_PRINTER(Map)
6271 DECLARE_VERIFIER(Map)
6272
6273#ifdef VERIFY_HEAP
6274 void DictionaryMapVerify();
6275 void VerifyOmittedMapChecks();
Steve Blocka7e24c12009-10-30 11:49:00 +00006276#endif
6277
Iain Merrick75681382010-08-19 15:07:18 +01006278 inline int visitor_id();
6279 inline void set_visitor_id(int visitor_id);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01006280
Kristian Monsen0d5e1162010-09-30 15:31:59 +01006281 typedef void (*TraverseCallback)(Map* map, void* data);
6282
6283 void TraverseTransitionTree(TraverseCallback callback, void* data);
6284
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006285 // When you set the prototype of an object using the __proto__ accessor you
6286 // need a new map for the object (the prototype is stored in the map). In
6287 // order not to multiply maps unnecessarily we store these as transitions in
6288 // the original map. That way we can transition to the same map if the same
6289 // prototype is set, rather than creating a new map every time. The
6290 // transitions are in the form of a map where the keys are prototype objects
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006291 // and the values are the maps they transition to.
Steve Block053d10c2011-06-13 19:13:29 +01006292 static const int kMaxCachedPrototypeTransitions = 256;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006293 static Handle<Map> TransitionToPrototype(Handle<Map> map,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006294 Handle<Object> prototype,
6295 PrototypeOptimizationMode mode);
Steve Block053d10c2011-06-13 19:13:29 +01006296
Steve Blocka7e24c12009-10-30 11:49:00 +00006297 static const int kMaxPreAllocatedPropertyFields = 255;
6298
6299 // Layout description.
6300 static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
6301 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006302 static const int kBitField3Offset = kInstanceAttributesOffset + kIntSize;
6303 static const int kPrototypeOffset = kBitField3Offset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006304 static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006305 // Storage for the transition array is overloaded to directly contain a back
6306 // pointer if unused. When the map has transitions, the back pointer is
6307 // transferred to the transition array and accessed through an extra
6308 // indirection.
6309 static const int kTransitionsOrBackPointerOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00006310 kConstructorOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006311 static const int kDescriptorsOffset =
6312 kTransitionsOrBackPointerOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006313#if V8_DOUBLE_FIELDS_UNBOXING
6314 static const int kLayoutDecriptorOffset = kDescriptorsOffset + kPointerSize;
6315 static const int kCodeCacheOffset = kLayoutDecriptorOffset + kPointerSize;
6316#else
6317 static const int kLayoutDecriptorOffset = 1; // Must not be ever accessed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006318 static const int kCodeCacheOffset = kDescriptorsOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006319#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006320 static const int kDependentCodeOffset = kCodeCacheOffset + kPointerSize;
6321 static const int kSize = kDependentCodeOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006322
6323 // Layout of pointer fields. Heap iteration code relies on them
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006324 // being continuously allocated.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006325 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006326 static const int kPointerFieldsEndOffset = kSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006327
6328 // Byte offsets within kInstanceSizesOffset.
6329 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
6330 static const int kInObjectPropertiesByte = 1;
6331 static const int kInObjectPropertiesOffset =
6332 kInstanceSizesOffset + kInObjectPropertiesByte;
6333 static const int kPreAllocatedPropertyFieldsByte = 2;
6334 static const int kPreAllocatedPropertyFieldsOffset =
6335 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte;
Iain Merrick9ac36c92010-09-13 15:29:50 +01006336 static const int kVisitorIdByte = 3;
6337 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
Steve Blocka7e24c12009-10-30 11:49:00 +00006338
6339 // Byte offsets within kInstanceAttributesOffset attributes.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006340#if V8_TARGET_LITTLE_ENDIAN
6341 // Order instance type and bit field together such that they can be loaded
6342 // together as a 16-bit word with instance type in the lower 8 bits regardless
6343 // of endianess. Also provide endian-independent offset to that 16-bit word.
Steve Blocka7e24c12009-10-30 11:49:00 +00006344 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006345 static const int kBitFieldOffset = kInstanceAttributesOffset + 1;
6346#else
6347 static const int kBitFieldOffset = kInstanceAttributesOffset + 0;
6348 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 1;
6349#endif
6350 static const int kInstanceTypeAndBitFieldOffset =
6351 kInstanceAttributesOffset + 0;
6352 static const int kBitField2Offset = kInstanceAttributesOffset + 2;
6353 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 3;
Steve Blocka7e24c12009-10-30 11:49:00 +00006354
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006355 STATIC_ASSERT(kInstanceTypeAndBitFieldOffset ==
6356 Internals::kMapInstanceTypeAndBitFieldOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00006357
6358 // Bit positions for bit field.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006359 static const int kHasNonInstancePrototype = 0;
6360 static const int kIsHiddenPrototype = 1;
6361 static const int kHasNamedInterceptor = 2;
6362 static const int kHasIndexedInterceptor = 3;
6363 static const int kIsUndetectable = 4;
6364 static const int kIsObserved = 5;
6365 static const int kIsAccessCheckNeeded = 6;
6366 class FunctionWithPrototype: public BitField<bool, 7, 1> {};
Steve Blocka7e24c12009-10-30 11:49:00 +00006367
6368 // Bit positions for bit field 2
Andrei Popescu31002712010-02-23 13:46:05 +00006369 static const int kIsExtensible = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006370 static const int kStringWrapperSafeForDefaultValueOf = 1;
6371 class IsPrototypeMapBits : public BitField<bool, 2, 1> {};
6372 class ElementsKindBits: public BitField<ElementsKind, 3, 5> {};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006373
6374 // Derived values from bit field 2
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006375 static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006376 (FAST_ELEMENTS + 1) << Map::ElementsKindBits::kShift) - 1;
6377 static const int8_t kMaximumBitField2FastSmiElementValue =
6378 static_cast<int8_t>((FAST_SMI_ELEMENTS + 1) <<
6379 Map::ElementsKindBits::kShift) - 1;
6380 static const int8_t kMaximumBitField2FastHoleyElementValue =
6381 static_cast<int8_t>((FAST_HOLEY_ELEMENTS + 1) <<
6382 Map::ElementsKindBits::kShift) - 1;
6383 static const int8_t kMaximumBitField2FastHoleySmiElementValue =
6384 static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) <<
6385 Map::ElementsKindBits::kShift) - 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00006386
Iain Merrick75681382010-08-19 15:07:18 +01006387 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
6388 kPointerFieldsEndOffset,
6389 kSize> BodyDescriptor;
6390
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006391 // Compares this map to another to see if they describe equivalent objects.
6392 // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if
6393 // it had exactly zero inobject properties.
6394 // The "shared" flags of both this map and |other| are ignored.
6395 bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode);
6396
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006397 // Returns true if given field is unboxed double.
6398 inline bool IsUnboxedDoubleField(FieldIndex index);
6399
6400#if TRACE_MAPS
6401 static void TraceTransition(const char* what, Map* from, Map* to, Name* name);
6402 static void TraceAllTransitions(Map* map);
6403#endif
6404
6405 static inline Handle<Map> CopyInstallDescriptorsForTesting(
6406 Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
6407 Handle<LayoutDescriptor> layout_descriptor);
6408
Steve Blocka7e24c12009-10-30 11:49:00 +00006409 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006410 static void ConnectElementsTransition(Handle<Map> parent, Handle<Map> child);
6411 static void ConnectTransition(Handle<Map> parent, Handle<Map> child,
6412 Handle<Name> name, SimpleTransitionFlag flag);
6413
6414 bool EquivalentToForTransition(Map* other);
6415 static Handle<Map> RawCopy(Handle<Map> map, int instance_size);
6416 static Handle<Map> ShareDescriptor(Handle<Map> map,
6417 Handle<DescriptorArray> descriptors,
6418 Descriptor* descriptor);
6419 static Handle<Map> CopyInstallDescriptors(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006420 Handle<Map> map, int new_descriptor, Handle<DescriptorArray> descriptors,
6421 Handle<LayoutDescriptor> layout_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006422 static Handle<Map> CopyAddDescriptor(Handle<Map> map,
6423 Descriptor* descriptor,
6424 TransitionFlag flag);
6425 static Handle<Map> CopyReplaceDescriptors(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006426 Handle<Map> map, Handle<DescriptorArray> descriptors,
6427 Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
6428 MaybeHandle<Name> maybe_name, const char* reason,
6429 SimpleTransitionFlag simple_flag);
6430
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006431 static Handle<Map> CopyReplaceDescriptor(Handle<Map> map,
6432 Handle<DescriptorArray> descriptors,
6433 Descriptor* descriptor,
6434 int index,
6435 TransitionFlag flag);
6436
6437 static Handle<Map> CopyNormalized(Handle<Map> map,
6438 PropertyNormalizationMode mode);
6439
6440 // Fires when the layout of an object with a leaf map changes.
6441 // This includes adding transitions to the leaf map or changing
6442 // the descriptor array.
6443 inline void NotifyLeafMapLayoutChange();
6444
6445 static Handle<Map> TransitionElementsToSlow(Handle<Map> object,
6446 ElementsKind to_kind);
6447
6448 // Zaps the contents of backing data structures. Note that the
6449 // heap verifier (i.e. VerifyMarkingVisitor) relies on zapping of objects
6450 // holding weak references when incremental marking is used, because it also
6451 // iterates over objects that are otherwise unreachable.
6452 // In general we only want to call these functions in release mode when
6453 // heap verification is turned on.
6454 void ZapPrototypeTransitions();
6455 void ZapTransitions();
6456
6457 void DeprecateTransitionTree();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006458 bool DeprecateTarget(PropertyKind kind, Name* key,
6459 PropertyAttributes attributes,
6460 DescriptorArray* new_descriptors,
6461 LayoutDescriptor* new_layout_descriptor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006462
6463 Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors);
6464
6465 void UpdateFieldType(int descriptor_number, Handle<Name> name,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006466 Representation new_representation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006467 Handle<HeapType> new_type);
6468
6469 void PrintGeneralization(FILE* file,
6470 const char* reason,
6471 int modify_index,
6472 int split,
6473 int descriptors,
6474 bool constant_to_field,
6475 Representation old_representation,
6476 Representation new_representation,
6477 HeapType* old_field_type,
6478 HeapType* new_field_type);
6479
6480 static inline void SetPrototypeTransitions(
6481 Handle<Map> map,
6482 Handle<FixedArray> prototype_transitions);
6483
6484 static Handle<Map> GetPrototypeTransition(Handle<Map> map,
6485 Handle<Object> prototype);
6486 static Handle<Map> PutPrototypeTransition(Handle<Map> map,
6487 Handle<Object> prototype,
6488 Handle<Map> target_map);
6489
6490 static const int kFastPropertiesSoftLimit = 12;
6491 static const int kMaxFastProperties = 128;
6492
Steve Blocka7e24c12009-10-30 11:49:00 +00006493 DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
6494};
6495
6496
6497// An abstract superclass, a marker class really, for simple structure classes.
Ben Murdoch257744e2011-11-30 15:57:28 +00006498// It doesn't carry much functionality but allows struct classes to be
Steve Blocka7e24c12009-10-30 11:49:00 +00006499// identified in the type system.
6500class Struct: public HeapObject {
6501 public:
6502 inline void InitializeBody(int object_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006503 DECLARE_CAST(Struct)
6504};
6505
6506
6507// A simple one-element struct, useful where smis need to be boxed.
6508class Box : public Struct {
6509 public:
6510 // [value]: the boxed contents.
6511 DECL_ACCESSORS(value, Object)
6512
6513 DECLARE_CAST(Box)
6514
6515 // Dispatched behavior.
6516 DECLARE_PRINTER(Box)
6517 DECLARE_VERIFIER(Box)
6518
6519 static const int kValueOffset = HeapObject::kHeaderSize;
6520 static const int kSize = kValueOffset + kPointerSize;
6521
6522 private:
6523 DISALLOW_IMPLICIT_CONSTRUCTORS(Box);
Steve Blocka7e24c12009-10-30 11:49:00 +00006524};
6525
6526
6527// Script describes a script which has been added to the VM.
6528class Script: public Struct {
6529 public:
6530 // Script types.
6531 enum Type {
6532 TYPE_NATIVE = 0,
6533 TYPE_EXTENSION = 1,
6534 TYPE_NORMAL = 2
6535 };
6536
6537 // Script compilation types.
6538 enum CompilationType {
6539 COMPILATION_TYPE_HOST = 0,
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08006540 COMPILATION_TYPE_EVAL = 1
Steve Blocka7e24c12009-10-30 11:49:00 +00006541 };
6542
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006543 // Script compilation state.
6544 enum CompilationState {
6545 COMPILATION_STATE_INITIAL = 0,
6546 COMPILATION_STATE_COMPILED = 1
6547 };
6548
Steve Blocka7e24c12009-10-30 11:49:00 +00006549 // [source]: the script source.
6550 DECL_ACCESSORS(source, Object)
6551
6552 // [name]: the script name.
6553 DECL_ACCESSORS(name, Object)
6554
6555 // [id]: the script id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006556 DECL_ACCESSORS(id, Smi)
Steve Blocka7e24c12009-10-30 11:49:00 +00006557
6558 // [line_offset]: script line offset in resource from where it was extracted.
6559 DECL_ACCESSORS(line_offset, Smi)
6560
6561 // [column_offset]: script column offset in resource from where it was
6562 // extracted.
6563 DECL_ACCESSORS(column_offset, Smi)
6564
Steve Blocka7e24c12009-10-30 11:49:00 +00006565 // [context_data]: context data for the context this script was compiled in.
6566 DECL_ACCESSORS(context_data, Object)
6567
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006568 // [wrapper]: the wrapper cache. This is either undefined or a WeakCell.
6569 DECL_ACCESSORS(wrapper, HeapObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00006570
6571 // [type]: the script type.
6572 DECL_ACCESSORS(type, Smi)
6573
Steve Blockd0582a62009-12-15 09:54:21 +00006574 // [line_ends]: FixedArray of line ends positions.
Steve Blocka7e24c12009-10-30 11:49:00 +00006575 DECL_ACCESSORS(line_ends, Object)
6576
Steve Blockd0582a62009-12-15 09:54:21 +00006577 // [eval_from_shared]: for eval scripts the shared funcion info for the
6578 // function from which eval was called.
6579 DECL_ACCESSORS(eval_from_shared, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00006580
6581 // [eval_from_instructions_offset]: the instruction offset in the code for the
6582 // function from which eval was called where eval was called.
6583 DECL_ACCESSORS(eval_from_instructions_offset, Smi)
6584
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006585 // [flags]: Holds an exciting bitfield.
6586 DECL_ACCESSORS(flags, Smi)
6587
6588 // [source_url]: sourceURL from magic comment
6589 DECL_ACCESSORS(source_url, Object)
6590
6591 // [source_url]: sourceMappingURL magic comment
6592 DECL_ACCESSORS(source_mapping_url, Object)
6593
6594 // [compilation_type]: how the the script was compiled. Encoded in the
6595 // 'flags' field.
6596 inline CompilationType compilation_type();
6597 inline void set_compilation_type(CompilationType type);
6598
6599 // [compilation_state]: determines whether the script has already been
6600 // compiled. Encoded in the 'flags' field.
6601 inline CompilationState compilation_state();
6602 inline void set_compilation_state(CompilationState state);
6603
6604 // [is_shared_cross_origin]: An opaque boolean set by the embedder via
6605 // ScriptOrigin, and used by the embedder to make decisions about the
6606 // script's level of privilege. V8 just passes this through. Encoded in
6607 // the 'flags' field.
6608 DECL_BOOLEAN_ACCESSORS(is_shared_cross_origin)
6609
6610 DECLARE_CAST(Script)
Steve Blocka7e24c12009-10-30 11:49:00 +00006611
Steve Block3ce2e202009-11-05 08:53:23 +00006612 // If script source is an external string, check that the underlying
6613 // resource is accessible. Otherwise, always return true.
6614 inline bool HasValidSource();
6615
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006616 // Convert code position into column number.
6617 static int GetColumnNumber(Handle<Script> script, int code_pos);
6618
6619 // Convert code position into (zero-based) line number.
6620 // The non-handlified version does not allocate, but may be much slower.
6621 static int GetLineNumber(Handle<Script> script, int code_pos);
6622 int GetLineNumber(int code_pos);
6623
6624 static Handle<Object> GetNameOrSourceURL(Handle<Script> script);
6625
6626 // Init line_ends array with code positions of line ends inside script source.
6627 static void InitLineEnds(Handle<Script> script);
6628
6629 // Get the JS object wrapping the given script; create it if none exists.
6630 static Handle<JSObject> GetWrapper(Handle<Script> script);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006631
6632 // Dispatched behavior.
6633 DECLARE_PRINTER(Script)
6634 DECLARE_VERIFIER(Script)
Steve Blocka7e24c12009-10-30 11:49:00 +00006635
6636 static const int kSourceOffset = HeapObject::kHeaderSize;
6637 static const int kNameOffset = kSourceOffset + kPointerSize;
6638 static const int kLineOffsetOffset = kNameOffset + kPointerSize;
6639 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006640 static const int kContextOffset = kColumnOffsetOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006641 static const int kWrapperOffset = kContextOffset + kPointerSize;
6642 static const int kTypeOffset = kWrapperOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006643 static const int kLineEndsOffset = kTypeOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006644 static const int kIdOffset = kLineEndsOffset + kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +00006645 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006646 static const int kEvalFrominstructionsOffsetOffset =
Steve Blockd0582a62009-12-15 09:54:21 +00006647 kEvalFromSharedOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006648 static const int kFlagsOffset =
6649 kEvalFrominstructionsOffsetOffset + kPointerSize;
6650 static const int kSourceUrlOffset = kFlagsOffset + kPointerSize;
6651 static const int kSourceMappingUrlOffset = kSourceUrlOffset + kPointerSize;
6652 static const int kSize = kSourceMappingUrlOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00006653
6654 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006655 int GetLineNumberWithArray(int code_pos);
6656
6657 // Bit positions in the flags field.
6658 static const int kCompilationTypeBit = 0;
6659 static const int kCompilationStateBit = 1;
6660 static const int kIsSharedCrossOriginBit = 2;
6661
Steve Blocka7e24c12009-10-30 11:49:00 +00006662 DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
6663};
6664
6665
Ben Murdochb0fe1622011-05-05 13:52:32 +01006666// List of builtin functions we want to identify to improve code
6667// generation.
6668//
6669// Each entry has a name of a global object property holding an object
6670// optionally followed by ".prototype", a name of a builtin function
6671// on the object (the one the id is set for), and a label.
6672//
6673// Installation of ids for the selected builtin functions is handled
6674// by the bootstrapper.
Ben Murdochb0fe1622011-05-05 13:52:32 +01006675#define FUNCTIONS_WITH_ID_LIST(V) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006676 V(Array.prototype, indexOf, ArrayIndexOf) \
6677 V(Array.prototype, lastIndexOf, ArrayLastIndexOf) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01006678 V(Array.prototype, push, ArrayPush) \
6679 V(Array.prototype, pop, ArrayPop) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006680 V(Array.prototype, shift, ArrayShift) \
Ben Murdoch42effa52011-08-19 16:40:31 +01006681 V(Function.prototype, apply, FunctionApply) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006682 V(Function.prototype, call, FunctionCall) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01006683 V(String.prototype, charCodeAt, StringCharCodeAt) \
6684 V(String.prototype, charAt, StringCharAt) \
6685 V(String, fromCharCode, StringFromCharCode) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006686 V(Math, random, MathRandom) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01006687 V(Math, floor, MathFloor) \
6688 V(Math, round, MathRound) \
6689 V(Math, ceil, MathCeil) \
6690 V(Math, abs, MathAbs) \
6691 V(Math, log, MathLog) \
Ben Murdochb0fe1622011-05-05 13:52:32 +01006692 V(Math, exp, MathExp) \
6693 V(Math, sqrt, MathSqrt) \
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006694 V(Math, pow, MathPow) \
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006695 V(Math, max, MathMax) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006696 V(Math, min, MathMin) \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006697 V(Math, cos, MathCos) \
6698 V(Math, sin, MathSin) \
6699 V(Math, tan, MathTan) \
6700 V(Math, acos, MathAcos) \
6701 V(Math, asin, MathAsin) \
6702 V(Math, atan, MathAtan) \
6703 V(Math, atan2, MathAtan2) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006704 V(Math, imul, MathImul) \
6705 V(Math, clz32, MathClz32) \
6706 V(Math, fround, MathFround)
Ben Murdochb0fe1622011-05-05 13:52:32 +01006707
6708enum BuiltinFunctionId {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006709 kArrayCode,
Ben Murdochb0fe1622011-05-05 13:52:32 +01006710#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
6711 k##name,
6712 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
6713#undef DECLARE_FUNCTION_ID
6714 // Fake id for a special case of Math.pow. Note, it continues the
6715 // list of math functions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006716 kMathPowHalf
Ben Murdochb0fe1622011-05-05 13:52:32 +01006717};
6718
6719
Steve Blocka7e24c12009-10-30 11:49:00 +00006720// SharedFunctionInfo describes the JSFunction information that can be
6721// shared by multiple instances of the function.
6722class SharedFunctionInfo: public HeapObject {
6723 public:
6724 // [name]: Function name.
6725 DECL_ACCESSORS(name, Object)
6726
6727 // [code]: Function code.
6728 DECL_ACCESSORS(code, Code)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006729 inline void ReplaceCode(Code* code);
6730
6731 // [optimized_code_map]: Map from native context to optimized code
6732 // and a shared literals array or Smi(0) if none.
6733 DECL_ACCESSORS(optimized_code_map, Object)
6734
6735 // Returns index i of the entry with the specified context and OSR entry.
6736 // At position i - 1 is the context, position i the code, and i + 1 the
6737 // literals array. Returns -1 when no matching entry is found.
6738 int SearchOptimizedCodeMap(Context* native_context, BailoutId osr_ast_id);
6739
6740 // Installs optimized code from the code map on the given closure. The
6741 // index has to be consistent with a search result as defined above.
6742 FixedArray* GetLiteralsFromOptimizedCodeMap(int index);
6743
6744 Code* GetCodeFromOptimizedCodeMap(int index);
6745
6746 // Clear optimized code map.
6747 void ClearOptimizedCodeMap();
6748
6749 // Removed a specific optimized code object from the optimized code map.
6750 void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason);
6751
6752 void ClearTypeFeedbackInfo();
6753
6754 // Trims the optimized code map after entries have been removed.
6755 void TrimOptimizedCodeMap(int shrink_by);
6756
6757 // Add a new entry to the optimized code map.
6758 static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
6759 Handle<Context> native_context,
6760 Handle<Code> code,
6761 Handle<FixedArray> literals,
6762 BailoutId osr_ast_id);
6763
6764 // Layout description of the optimized code map.
6765 static const int kNextMapIndex = 0;
6766 static const int kEntriesStart = 1;
6767 static const int kContextOffset = 0;
6768 static const int kCachedCodeOffset = 1;
6769 static const int kLiteralsOffset = 2;
6770 static const int kOsrAstIdOffset = 3;
6771 static const int kEntryLength = 4;
6772 static const int kInitialLength = kEntriesStart + kEntryLength;
Steve Blocka7e24c12009-10-30 11:49:00 +00006773
Ben Murdoch3bec4d22010-07-22 14:51:16 +01006774 // [scope_info]: Scope info.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006775 DECL_ACCESSORS(scope_info, ScopeInfo)
Ben Murdoch3bec4d22010-07-22 14:51:16 +01006776
Steve Blocka7e24c12009-10-30 11:49:00 +00006777 // [construct stub]: Code stub for constructing instances of this function.
6778 DECL_ACCESSORS(construct_stub, Code)
6779
6780 // Returns if this function has been compiled to native code yet.
6781 inline bool is_compiled();
6782
6783 // [length]: The function length - usually the number of declared parameters.
6784 // Use up to 2^30 parameters.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006785 inline int length() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006786 inline void set_length(int value);
6787
6788 // [formal parameter count]: The declared number of parameters.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006789 inline int formal_parameter_count() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006790 inline void set_formal_parameter_count(int value);
6791
6792 // Set the formal parameter count so the function code will be
6793 // called without using argument adaptor frames.
6794 inline void DontAdaptArguments();
6795
6796 // [expected_nof_properties]: Expected number of properties for the function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006797 inline int expected_nof_properties() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006798 inline void set_expected_nof_properties(int value);
6799
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006800 // [feedback_vector] - accumulates ast node feedback from full-codegen and
6801 // (increasingly) from crankshafted code where sufficient feedback isn't
6802 // available.
6803 DECL_ACCESSORS(feedback_vector, TypeFeedbackVector)
Kristian Monsen0d5e1162010-09-30 15:31:59 +01006804
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006805#if TRACE_MAPS
6806 // [unique_id] - For --trace-maps purposes, an identifier that's persistent
6807 // even if the GC moves this SharedFunctionInfo.
6808 inline int unique_id() const;
6809 inline void set_unique_id(int value);
6810#endif
6811
Steve Blocka7e24c12009-10-30 11:49:00 +00006812 // [instance class name]: class name for instances.
6813 DECL_ACCESSORS(instance_class_name, Object)
6814
Steve Block6ded16b2010-05-10 14:33:55 +01006815 // [function data]: This field holds some additional data for function.
6816 // Currently it either has FunctionTemplateInfo to make benefit the API
Ben Murdochb0fe1622011-05-05 13:52:32 +01006817 // or Smi identifying a builtin function.
Steve Blocka7e24c12009-10-30 11:49:00 +00006818 // In the long run we don't want all functions to have this field but
6819 // we can fix that when we have a better model for storing hidden data
6820 // on objects.
6821 DECL_ACCESSORS(function_data, Object)
6822
Steve Block6ded16b2010-05-10 14:33:55 +01006823 inline bool IsApiFunction();
6824 inline FunctionTemplateInfo* get_api_func_data();
Ben Murdochb0fe1622011-05-05 13:52:32 +01006825 inline bool HasBuiltinFunctionId();
Ben Murdochb0fe1622011-05-05 13:52:32 +01006826 inline BuiltinFunctionId builtin_function_id();
Steve Block6ded16b2010-05-10 14:33:55 +01006827
Steve Blocka7e24c12009-10-30 11:49:00 +00006828 // [script info]: Script from which the function originates.
6829 DECL_ACCESSORS(script, Object)
6830
Steve Block6ded16b2010-05-10 14:33:55 +01006831 // [num_literals]: Number of literals used by this function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006832 inline int num_literals() const;
Steve Block6ded16b2010-05-10 14:33:55 +01006833 inline void set_num_literals(int value);
6834
Steve Blocka7e24c12009-10-30 11:49:00 +00006835 // [start_position_and_type]: Field used to store both the source code
6836 // position, whether or not the function is a function expression,
6837 // and whether or not the function is a toplevel function. The two
6838 // least significants bit indicates whether the function is an
6839 // expression and the rest contains the source code position.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006840 inline int start_position_and_type() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006841 inline void set_start_position_and_type(int value);
6842
6843 // [debug info]: Debug information.
6844 DECL_ACCESSORS(debug_info, Object)
6845
6846 // [inferred name]: Name inferred from variable or property
6847 // assignment of this function. Used to facilitate debugging and
6848 // profiling of JavaScript code written in OO style, where almost
6849 // all functions are anonymous but are assigned to object
6850 // properties.
6851 DECL_ACCESSORS(inferred_name, String)
6852
Ben Murdochf87a2032010-10-22 12:50:53 +01006853 // The function's name if it is non-empty, otherwise the inferred name.
6854 String* DebugName();
6855
Steve Blocka7e24c12009-10-30 11:49:00 +00006856 // Position of the 'function' token in the script source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006857 inline int function_token_position() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006858 inline void set_function_token_position(int function_token_position);
6859
6860 // Position of this function in the script source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006861 inline int start_position() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006862 inline void set_start_position(int start_position);
6863
6864 // End position of this function in the script source.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006865 inline int end_position() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006866 inline void set_end_position(int end_position);
6867
6868 // Is this function a function expression in the source code.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006869 DECL_BOOLEAN_ACCESSORS(is_expression)
Steve Blocka7e24c12009-10-30 11:49:00 +00006870
6871 // Is this function a top-level function (scripts, evals).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006872 DECL_BOOLEAN_ACCESSORS(is_toplevel)
Steve Blocka7e24c12009-10-30 11:49:00 +00006873
6874 // Bit field containing various information collected by the compiler to
6875 // drive optimization.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006876 inline int compiler_hints() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00006877 inline void set_compiler_hints(int value);
6878
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006879 inline int ast_node_count() const;
Ben Murdoch8f9999f2012-04-23 10:39:17 +01006880 inline void set_ast_node_count(int count);
6881
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006882 inline int profiler_ticks() const;
6883 inline void set_profiler_ticks(int ticks);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006884
Ben Murdoch8f9999f2012-04-23 10:39:17 +01006885 // Inline cache age is used to infer whether the function survived a context
6886 // disposal or not. In the former case we reset the opt_count.
6887 inline int ic_age();
6888 inline void set_ic_age(int age);
Ben Murdochb0fe1622011-05-05 13:52:32 +01006889
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006890 // Indicates if this function can be lazy compiled.
6891 // This is used to determine if we can safely flush code from a function
6892 // when doing GC if we expect that the function will no longer be used.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006893 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01006894
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006895 // Indicates if this function can be lazy compiled without a context.
6896 // This is used to determine if we can force compilation without reaching
6897 // the function through program execution but through other means (e.g. heap
6898 // iteration by the debugger).
6899 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation_without_context)
Iain Merrick75681382010-08-19 15:07:18 +01006900
Ben Murdochb0fe1622011-05-05 13:52:32 +01006901 // Indicates whether optimizations have been disabled for this
6902 // shared function info. If a function is repeatedly optimized or if
6903 // we cannot optimize the function we disable optimization to avoid
6904 // spending time attempting to optimize it again.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006905 DECL_BOOLEAN_ACCESSORS(optimization_disabled)
Ben Murdochb0fe1622011-05-05 13:52:32 +01006906
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006907 // Indicates the language mode.
6908 inline StrictMode strict_mode();
6909 inline void set_strict_mode(StrictMode strict_mode);
Steve Block1e0659c2011-05-24 12:43:12 +01006910
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006911 // False if the function definitely does not allocate an arguments object.
6912 DECL_BOOLEAN_ACCESSORS(uses_arguments)
6913
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006914 // Indicates that this function uses a super property.
6915 // This is needed to set up the [[HomeObject]] on the function instance.
6916 DECL_BOOLEAN_ACCESSORS(uses_super_property)
6917
6918 // Indicates that this function uses the super constructor.
6919 DECL_BOOLEAN_ACCESSORS(uses_super_constructor_call)
6920
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006921 // True if the function has any duplicated parameter names.
6922 DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters)
6923
6924 // Indicates whether the function is a native function.
Ben Murdoch589d6972011-11-30 16:04:58 +00006925 // These needs special treatment in .call and .apply since
Ben Murdoch257744e2011-11-30 15:57:28 +00006926 // null passed as the receiver should not be translated to the
6927 // global object.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006928 DECL_BOOLEAN_ACCESSORS(native)
6929
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006930 // Indicate that this builtin needs to be inlined in crankshaft.
6931 DECL_BOOLEAN_ACCESSORS(inline_builtin)
6932
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00006933 // Indicates that the function was created by the Function function.
6934 // Though it's anonymous, toString should treat it as if it had the name
6935 // "anonymous". We don't set the name itself so that the system does not
6936 // see a binding for it.
6937 DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous)
6938
6939 // Indicates whether the function is a bound function created using
6940 // the bind function.
6941 DECL_BOOLEAN_ACCESSORS(bound)
6942
6943 // Indicates that the function is anonymous (the name field can be set
6944 // through the API, which does not change this flag).
6945 DECL_BOOLEAN_ACCESSORS(is_anonymous)
Ben Murdoch257744e2011-11-30 15:57:28 +00006946
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006947 // Is this a function or top-level/eval code.
6948 DECL_BOOLEAN_ACCESSORS(is_function)
6949
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006950 // Indicates that code for this function cannot be cached.
6951 DECL_BOOLEAN_ACCESSORS(dont_cache)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006952
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006953 // Indicates that code for this function cannot be flushed.
6954 DECL_BOOLEAN_ACCESSORS(dont_flush)
6955
6956 // Indicates that this function is a generator.
6957 DECL_BOOLEAN_ACCESSORS(is_generator)
6958
6959 // Indicates that this function is an arrow function.
6960 DECL_BOOLEAN_ACCESSORS(is_arrow)
6961
6962 // Indicates that this function is a concise method.
6963 DECL_BOOLEAN_ACCESSORS(is_concise_method)
6964
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006965 // Indicates that this function is a default constructor.
6966 DECL_BOOLEAN_ACCESSORS(is_default_constructor)
6967
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006968 // Indicates that this function is an asm function.
6969 DECL_BOOLEAN_ACCESSORS(asm_function)
6970
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006971 // Indicates that the the shared function info is deserialized from cache.
6972 DECL_BOOLEAN_ACCESSORS(deserialized)
6973
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006974 inline FunctionKind kind();
6975 inline void set_kind(FunctionKind kind);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006976
Ben Murdochb0fe1622011-05-05 13:52:32 +01006977 // Indicates whether or not the code in the shared function support
6978 // deoptimization.
6979 inline bool has_deoptimization_support();
6980
6981 // Enable deoptimization support through recompiled code.
6982 void EnableDeoptimizationSupport(Code* recompiled);
6983
Ben Murdoch257744e2011-11-30 15:57:28 +00006984 // Disable (further) attempted optimization of all functions sharing this
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006985 // shared function info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006986 void DisableOptimization(BailoutReason reason);
Ben Murdoch257744e2011-11-30 15:57:28 +00006987
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006988 inline BailoutReason disable_optimization_reason();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006989
6990 // Lookup the bailout ID and DCHECK that it exists in the non-optimized
Ben Murdochb0fe1622011-05-05 13:52:32 +01006991 // code, returns whether it asserted (i.e., always true if assertions are
6992 // disabled).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006993 bool VerifyBailoutId(BailoutId id);
Steve Blocka7e24c12009-10-30 11:49:00 +00006994
6995 // [source code]: Source code for the function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006996 bool HasSourceCode() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01006997 Handle<Object> GetSourceCode();
Steve Blocka7e24c12009-10-30 11:49:00 +00006998
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006999 // Number of times the function was optimized.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007000 inline int opt_count();
7001 inline void set_opt_count(int opt_count);
7002
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007003 // Number of times the function was deoptimized.
7004 inline void set_deopt_count(int value);
7005 inline int deopt_count();
7006 inline void increment_deopt_count();
7007
7008 // Number of time we tried to re-enable optimization after it
7009 // was disabled due to high number of deoptimizations.
7010 inline void set_opt_reenable_tries(int value);
7011 inline int opt_reenable_tries();
7012
7013 inline void TryReenableOptimization();
7014
7015 // Stores deopt_count, opt_reenable_tries and ic_age as bit-fields.
7016 inline void set_counters(int value);
7017 inline int counters() const;
7018
7019 // Stores opt_count and bailout_reason as bit-fields.
7020 inline void set_opt_count_and_bailout_reason(int value);
7021 inline int opt_count_and_bailout_reason() const;
7022
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007023 void set_disable_optimization_reason(BailoutReason reason) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007024 set_opt_count_and_bailout_reason(
7025 DisabledOptimizationReasonBits::update(opt_count_and_bailout_reason(),
7026 reason));
7027 }
7028
7029 // Check whether or not this function is inlineable.
7030 bool IsInlineable();
7031
Ben Murdochb0fe1622011-05-05 13:52:32 +01007032 // Source size of this function.
7033 int SourceSize();
7034
Steve Blocka7e24c12009-10-30 11:49:00 +00007035 // Calculate the instance size.
7036 int CalculateInstanceSize();
7037
7038 // Calculate the number of in-object properties.
7039 int CalculateInObjectProperties();
7040
7041 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007042 DECLARE_PRINTER(SharedFunctionInfo)
7043 DECLARE_VERIFIER(SharedFunctionInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +00007044
Ben Murdoch8f9999f2012-04-23 10:39:17 +01007045 void ResetForNewContext(int new_ic_age);
7046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007047 DECLARE_CAST(SharedFunctionInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +00007048
7049 // Constants.
7050 static const int kDontAdaptArgumentsSentinel = -1;
7051
7052 // Layout description.
Steve Block6ded16b2010-05-10 14:33:55 +01007053 // Pointer fields.
Steve Blocka7e24c12009-10-30 11:49:00 +00007054 static const int kNameOffset = HeapObject::kHeaderSize;
7055 static const int kCodeOffset = kNameOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007056 static const int kOptimizedCodeMapOffset = kCodeOffset + kPointerSize;
7057 static const int kScopeInfoOffset = kOptimizedCodeMapOffset + kPointerSize;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01007058 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01007059 static const int kInstanceClassNameOffset =
7060 kConstructStubOffset + kPointerSize;
7061 static const int kFunctionDataOffset =
7062 kInstanceClassNameOffset + kPointerSize;
7063 static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
7064 static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
7065 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007066 static const int kFeedbackVectorOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01007067 kInferredNameOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007068#if TRACE_MAPS
7069 static const int kUniqueIdOffset = kFeedbackVectorOffset + kPointerSize;
7070 static const int kLastPointerFieldOffset = kUniqueIdOffset;
7071#else
7072 static const int kLastPointerFieldOffset = kFeedbackVectorOffset;
7073#endif
7074
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007075#if V8_HOST_ARCH_32_BIT
7076 // Smi fields.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007077 static const int kLengthOffset = kLastPointerFieldOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007078 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
7079 static const int kExpectedNofPropertiesOffset =
7080 kFormalParameterCountOffset + kPointerSize;
7081 static const int kNumLiteralsOffset =
7082 kExpectedNofPropertiesOffset + kPointerSize;
7083 static const int kStartPositionAndTypeOffset =
7084 kNumLiteralsOffset + kPointerSize;
7085 static const int kEndPositionOffset =
7086 kStartPositionAndTypeOffset + kPointerSize;
7087 static const int kFunctionTokenPositionOffset =
7088 kEndPositionOffset + kPointerSize;
7089 static const int kCompilerHintsOffset =
7090 kFunctionTokenPositionOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007091 static const int kOptCountAndBailoutReasonOffset =
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007092 kCompilerHintsOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007093 static const int kCountersOffset =
7094 kOptCountAndBailoutReasonOffset + kPointerSize;
7095 static const int kAstNodeCountOffset =
7096 kCountersOffset + kPointerSize;
7097 static const int kProfilerTicksOffset =
7098 kAstNodeCountOffset + kPointerSize;
Ben Murdoch8f9999f2012-04-23 10:39:17 +01007099
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007100 // Total size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007101 static const int kSize = kProfilerTicksOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007102#else
7103 // The only reason to use smi fields instead of int fields
Kristian Monsen0d5e1162010-09-30 15:31:59 +01007104 // is to allow iteration without maps decoding during
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007105 // garbage collections.
7106 // To avoid wasting space on 64-bit architectures we use
7107 // the following trick: we group integer fields into pairs
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007108// The least significant integer in each pair is shifted left by 1.
7109// By doing this we guarantee that LSB of each kPointerSize aligned
7110// word is not set and thus this word cannot be treated as pointer
7111// to HeapObject during old space traversal.
7112#if V8_TARGET_LITTLE_ENDIAN
7113 static const int kLengthOffset = kLastPointerFieldOffset + kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007114 static const int kFormalParameterCountOffset =
7115 kLengthOffset + kIntSize;
7116
Steve Blocka7e24c12009-10-30 11:49:00 +00007117 static const int kExpectedNofPropertiesOffset =
7118 kFormalParameterCountOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007119 static const int kNumLiteralsOffset =
7120 kExpectedNofPropertiesOffset + kIntSize;
7121
7122 static const int kEndPositionOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01007123 kNumLiteralsOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007124 static const int kStartPositionAndTypeOffset =
7125 kEndPositionOffset + kIntSize;
7126
7127 static const int kFunctionTokenPositionOffset =
7128 kStartPositionAndTypeOffset + kIntSize;
Steve Block6ded16b2010-05-10 14:33:55 +01007129 static const int kCompilerHintsOffset =
Steve Blocka7e24c12009-10-30 11:49:00 +00007130 kFunctionTokenPositionOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007132 static const int kOptCountAndBailoutReasonOffset =
Steve Block6ded16b2010-05-10 14:33:55 +01007133 kCompilerHintsOffset + kIntSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007134 static const int kCountersOffset =
7135 kOptCountAndBailoutReasonOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007136
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007137 static const int kAstNodeCountOffset =
7138 kCountersOffset + kIntSize;
7139 static const int kProfilerTicksOffset =
7140 kAstNodeCountOffset + kIntSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007141
Steve Block6ded16b2010-05-10 14:33:55 +01007142 // Total size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007143 static const int kSize = kProfilerTicksOffset + kIntSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01007144
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007145#elif V8_TARGET_BIG_ENDIAN
7146 static const int kFormalParameterCountOffset =
7147 kLastPointerFieldOffset + kPointerSize;
7148 static const int kLengthOffset = kFormalParameterCountOffset + kIntSize;
7149
7150 static const int kNumLiteralsOffset = kLengthOffset + kIntSize;
7151 static const int kExpectedNofPropertiesOffset = kNumLiteralsOffset + kIntSize;
7152
7153 static const int kStartPositionAndTypeOffset =
7154 kExpectedNofPropertiesOffset + kIntSize;
7155 static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize;
7156
7157 static const int kCompilerHintsOffset = kEndPositionOffset + kIntSize;
7158 static const int kFunctionTokenPositionOffset =
7159 kCompilerHintsOffset + kIntSize;
7160
7161 static const int kCountersOffset = kFunctionTokenPositionOffset + kIntSize;
7162 static const int kOptCountAndBailoutReasonOffset = kCountersOffset + kIntSize;
7163
7164 static const int kProfilerTicksOffset =
7165 kOptCountAndBailoutReasonOffset + kIntSize;
7166 static const int kAstNodeCountOffset = kProfilerTicksOffset + kIntSize;
7167
7168 // Total size.
7169 static const int kSize = kAstNodeCountOffset + kIntSize;
7170
7171#else
7172#error Unknown byte ordering
7173#endif // Big endian
7174#endif // 64-bit
7175
Kristian Monsen0d5e1162010-09-30 15:31:59 +01007176
Steve Block6ded16b2010-05-10 14:33:55 +01007177 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00007178
Iain Merrick75681382010-08-19 15:07:18 +01007179 typedef FixedBodyDescriptor<kNameOffset,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007180 kLastPointerFieldOffset + kPointerSize,
Iain Merrick75681382010-08-19 15:07:18 +01007181 kSize> BodyDescriptor;
7182
Steve Blocka7e24c12009-10-30 11:49:00 +00007183 // Bit positions in start_position_and_type.
7184 // The source code start position is in the 30 most significant bits of
7185 // the start_position_and_type field.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007186 static const int kIsExpressionBit = 0;
7187 static const int kIsTopLevelBit = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +00007188 static const int kStartPositionShift = 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007189 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00007190
7191 // Bit positions in compiler_hints.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007192 enum CompilerHints {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007193 kAllowLazyCompilation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007194 kAllowLazyCompilationWithoutContext,
7195 kOptimizationDisabled,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007196 kStrictModeFunction,
7197 kUsesArguments,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007198 kUsesSuperProperty,
7199 kUsesSuperConstructorCall,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007200 kHasDuplicateParameters,
7201 kNative,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007202 kInlineBuiltin,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007203 kBoundFunction,
7204 kIsAnonymous,
7205 kNameShouldPrintAsAnonymous,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007206 kIsFunction,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007207 kDontCache,
7208 kDontFlush,
7209 kIsArrow,
7210 kIsGenerator,
7211 kIsConciseMethod,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007212 kIsDefaultConstructor,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007213 kIsAsmFunction,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007214 kDeserialized,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007215 kCompilerHintsCount // Pseudo entry
7216 };
Steve Blocka7e24c12009-10-30 11:49:00 +00007217
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007218 class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 4> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007219
7220 class DeoptCountBits : public BitField<int, 0, 4> {};
7221 class OptReenableTriesBits : public BitField<int, 4, 18> {};
7222 class ICAgeBits : public BitField<int, 22, 8> {};
7223
7224 class OptCountBits : public BitField<int, 0, 22> {};
7225 class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {};
7226
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007227 private:
7228#if V8_HOST_ARCH_32_BIT
7229 // On 32 bit platforms, compiler hints is a smi.
7230 static const int kCompilerHintsSmiTagSize = kSmiTagSize;
7231 static const int kCompilerHintsSize = kPointerSize;
7232#else
7233 // On 64 bit platforms, compiler hints is not a smi, see comment above.
7234 static const int kCompilerHintsSmiTagSize = 0;
7235 static const int kCompilerHintsSize = kIntSize;
7236#endif
7237
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007238 STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <=
7239 SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte);
7240
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007241 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00007242 // Constants for optimizing codegen for strict mode function and
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007243 // native tests.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007244 // Allows to use byte-width instructions.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007245 static const int kStrictModeBitWithinByte =
7246 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
7247
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007248 static const int kNativeBitWithinByte =
7249 (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
Ben Murdoch257744e2011-11-30 15:57:28 +00007250
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007251#if defined(V8_TARGET_LITTLE_ENDIAN)
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007252 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00007253 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007254 static const int kNativeByteOffset = kCompilerHintsOffset +
7255 (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007256#elif defined(V8_TARGET_BIG_ENDIAN)
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007257 static const int kStrictModeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00007258 (kCompilerHintsSize - 1) -
7259 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007260 static const int kNativeByteOffset = kCompilerHintsOffset +
Ben Murdoch257744e2011-11-30 15:57:28 +00007261 (kCompilerHintsSize - 1) -
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007262 ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01007263#else
7264#error Unknown byte ordering
7265#endif
7266
7267 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00007268 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
7269};
7270
7271
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007272// Printing support.
7273struct SourceCodeOf {
7274 explicit SourceCodeOf(SharedFunctionInfo* v, int max = -1)
7275 : value(v), max_length(max) {}
7276 const SharedFunctionInfo* value;
7277 int max_length;
7278};
7279
7280
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007281std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007282
7283
7284class JSGeneratorObject: public JSObject {
7285 public:
7286 // [function]: The function corresponding to this generator object.
7287 DECL_ACCESSORS(function, JSFunction)
7288
7289 // [context]: The context of the suspended computation.
7290 DECL_ACCESSORS(context, Context)
7291
7292 // [receiver]: The receiver of the suspended computation.
7293 DECL_ACCESSORS(receiver, Object)
7294
7295 // [continuation]: Offset into code of continuation.
7296 //
7297 // A positive offset indicates a suspended generator. The special
7298 // kGeneratorExecuting and kGeneratorClosed values indicate that a generator
7299 // cannot be resumed.
7300 inline int continuation() const;
7301 inline void set_continuation(int continuation);
7302 inline bool is_closed();
7303 inline bool is_executing();
7304 inline bool is_suspended();
7305
7306 // [operand_stack]: Saved operand stack.
7307 DECL_ACCESSORS(operand_stack, FixedArray)
7308
7309 // [stack_handler_index]: Index of first stack handler in operand_stack, or -1
7310 // if the captured activation had no stack handler.
7311 inline int stack_handler_index() const;
7312 inline void set_stack_handler_index(int stack_handler_index);
7313
7314 DECLARE_CAST(JSGeneratorObject)
7315
7316 // Dispatched behavior.
7317 DECLARE_PRINTER(JSGeneratorObject)
7318 DECLARE_VERIFIER(JSGeneratorObject)
7319
7320 // Magic sentinel values for the continuation.
7321 static const int kGeneratorExecuting = -1;
7322 static const int kGeneratorClosed = 0;
7323
7324 // Layout description.
7325 static const int kFunctionOffset = JSObject::kHeaderSize;
7326 static const int kContextOffset = kFunctionOffset + kPointerSize;
7327 static const int kReceiverOffset = kContextOffset + kPointerSize;
7328 static const int kContinuationOffset = kReceiverOffset + kPointerSize;
7329 static const int kOperandStackOffset = kContinuationOffset + kPointerSize;
7330 static const int kStackHandlerIndexOffset =
7331 kOperandStackOffset + kPointerSize;
7332 static const int kSize = kStackHandlerIndexOffset + kPointerSize;
7333
7334 // Resume mode, for use by runtime functions.
7335 enum ResumeMode { NEXT, THROW };
7336
7337 // Yielding from a generator returns an object with the following inobject
7338 // properties. See Context::iterator_result_map() for the map.
7339 static const int kResultValuePropertyIndex = 0;
7340 static const int kResultDonePropertyIndex = 1;
7341 static const int kResultPropertyCount = 2;
7342
7343 static const int kResultValuePropertyOffset = JSObject::kHeaderSize;
7344 static const int kResultDonePropertyOffset =
7345 kResultValuePropertyOffset + kPointerSize;
7346 static const int kResultSize = kResultDonePropertyOffset + kPointerSize;
7347
7348 private:
7349 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGeneratorObject);
7350};
7351
7352
7353// Representation for module instance objects.
7354class JSModule: public JSObject {
7355 public:
7356 // [context]: the context holding the module's locals, or undefined if none.
7357 DECL_ACCESSORS(context, Object)
7358
7359 // [scope_info]: Scope info.
7360 DECL_ACCESSORS(scope_info, ScopeInfo)
7361
7362 DECLARE_CAST(JSModule)
7363
7364 // Dispatched behavior.
7365 DECLARE_PRINTER(JSModule)
7366 DECLARE_VERIFIER(JSModule)
7367
7368 // Layout description.
7369 static const int kContextOffset = JSObject::kHeaderSize;
7370 static const int kScopeInfoOffset = kContextOffset + kPointerSize;
7371 static const int kSize = kScopeInfoOffset + kPointerSize;
7372
7373 private:
7374 DISALLOW_IMPLICIT_CONSTRUCTORS(JSModule);
7375};
7376
7377
Steve Blocka7e24c12009-10-30 11:49:00 +00007378// JSFunction describes JavaScript functions.
7379class JSFunction: public JSObject {
7380 public:
7381 // [prototype_or_initial_map]:
7382 DECL_ACCESSORS(prototype_or_initial_map, Object)
7383
Ben Murdoch589d6972011-11-30 16:04:58 +00007384 // [shared]: The information about the function that
Steve Blocka7e24c12009-10-30 11:49:00 +00007385 // can be shared by instances.
7386 DECL_ACCESSORS(shared, SharedFunctionInfo)
7387
7388 // [context]: The context for this function.
7389 inline Context* context();
Steve Blocka7e24c12009-10-30 11:49:00 +00007390 inline void set_context(Object* context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007391 inline JSObject* global_proxy();
Steve Blocka7e24c12009-10-30 11:49:00 +00007392
7393 // [code]: The generated code object for this function. Executed
7394 // when the function is invoked, e.g. foo() or new foo(). See
7395 // [[Call]] and [[Construct]] description in ECMA-262, section
7396 // 8.6.2, page 27.
7397 inline Code* code();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007398 inline void set_code(Code* code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007399 inline void set_code_no_write_barrier(Code* code);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007400 inline void ReplaceCode(Code* code);
Steve Blocka7e24c12009-10-30 11:49:00 +00007401
Steve Blocka7e24c12009-10-30 11:49:00 +00007402 // Tells whether this function is builtin.
7403 inline bool IsBuiltin();
7404
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007405 // Tells whether this function is defined in a native script.
7406 inline bool IsFromNativeScript();
7407
7408 // Tells whether this function is defined in an extension script.
7409 inline bool IsFromExtensionScript();
7410
Ben Murdochb0fe1622011-05-05 13:52:32 +01007411 // Tells whether or not the function needs arguments adaption.
7412 inline bool NeedsArgumentsAdaption();
7413
7414 // Tells whether or not this function has been optimized.
7415 inline bool IsOptimized();
7416
Ben Murdoch8b112d22011-06-08 16:22:53 +01007417 // Tells whether or not this function can be optimized.
7418 inline bool IsOptimizable();
7419
Ben Murdochb0fe1622011-05-05 13:52:32 +01007420 // Mark this function for lazy recompilation. The function will be
7421 // recompiled the next time it is executed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007422 void MarkForOptimization();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007423 void AttemptConcurrentOptimization();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007424
Ben Murdochb0fe1622011-05-05 13:52:32 +01007425 // Tells whether or not the function is already marked for lazy
7426 // recompilation.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007427 inline bool IsMarkedForOptimization();
7428 inline bool IsMarkedForConcurrentOptimization();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007429
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007430 // Tells whether or not the function is on the concurrent recompilation queue.
7431 inline bool IsInOptimizationQueue();
7432
7433 // Inobject slack tracking is the way to reclaim unused inobject space.
7434 //
7435 // The instance size is initially determined by adding some slack to
7436 // expected_nof_properties (to allow for a few extra properties added
7437 // after the constructor). There is no guarantee that the extra space
7438 // will not be wasted.
7439 //
7440 // Here is the algorithm to reclaim the unused inobject space:
7441 // - Detect the first constructor call for this JSFunction.
7442 // When it happens enter the "in progress" state: initialize construction
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007443 // counter in the initial_map.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007444 // - While the tracking is in progress create objects filled with
7445 // one_pointer_filler_map instead of undefined_value. This way they can be
7446 // resized quickly and safely.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007447 // - Once enough objects have been created compute the 'slack'
7448 // (traverse the map transition tree starting from the
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007449 // initial_map and find the lowest value of unused_property_fields).
7450 // - Traverse the transition tree again and decrease the instance size
7451 // of every map. Existing objects will resize automatically (they are
7452 // filled with one_pointer_filler_map). All further allocations will
7453 // use the adjusted instance size.
7454 // - SharedFunctionInfo's expected_nof_properties left unmodified since
7455 // allocations made using different closures could actually create different
7456 // kind of objects (see prototype inheritance pattern).
7457 //
7458 // Important: inobject slack tracking is not attempted during the snapshot
7459 // creation.
7460
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007461 // True if the initial_map is set and the object constructions countdown
7462 // counter is not zero.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007463 static const int kGenerousAllocationCount =
7464 Map::kSlackTrackingCounterStart - Map::kSlackTrackingCounterEnd + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007465 inline bool IsInobjectSlackTrackingInProgress();
7466
7467 // Starts the tracking.
7468 // Initializes object constructions countdown counter in the initial map.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007469 void StartInobjectSlackTracking();
7470
7471 // Completes the tracking.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007472 void CompleteInobjectSlackTracking();
Ben Murdochb0fe1622011-05-05 13:52:32 +01007473
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007474 // [literals_or_bindings]: Fixed array holding either
7475 // the materialized literals or the bindings of a bound function.
Steve Blocka7e24c12009-10-30 11:49:00 +00007476 //
7477 // If the function contains object, regexp or array literals, the
7478 // literals array prefix contains the object, regexp, and array
7479 // function to be used when creating these literals. This is
7480 // necessary so that we do not dynamically lookup the object, regexp
7481 // or array functions. Performing a dynamic lookup, we might end up
7482 // using the functions from a new context that we should not have
7483 // access to.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007484 //
7485 // On bound functions, the array is a (copy-on-write) fixed-array containing
7486 // the function that was bound, bound this-value and any bound
7487 // arguments. Bound functions never contain literals.
7488 DECL_ACCESSORS(literals_or_bindings, FixedArray)
7489
7490 inline FixedArray* literals();
7491 inline void set_literals(FixedArray* literals);
7492
7493 inline FixedArray* function_bindings();
7494 inline void set_function_bindings(FixedArray* bindings);
Steve Blocka7e24c12009-10-30 11:49:00 +00007495
7496 // The initial map for an object created by this constructor.
7497 inline Map* initial_map();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007498 static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
7499 Handle<Object> prototype);
Steve Blocka7e24c12009-10-30 11:49:00 +00007500 inline bool has_initial_map();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007501 static void EnsureHasInitialMap(Handle<JSFunction> function);
Steve Blocka7e24c12009-10-30 11:49:00 +00007502
7503 // Get and set the prototype property on a JSFunction. If the
7504 // function has an initial map the prototype is set on the initial
7505 // map. Otherwise, the prototype is put in the initial map field
7506 // until an initial map is needed.
7507 inline bool has_prototype();
7508 inline bool has_instance_prototype();
7509 inline Object* prototype();
7510 inline Object* instance_prototype();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007511 static void SetPrototype(Handle<JSFunction> function,
7512 Handle<Object> value);
7513 static void SetInstancePrototype(Handle<JSFunction> function,
7514 Handle<Object> value);
7515
7516 // Creates a new closure for the fucntion with the same bindings,
7517 // bound values, and prototype. An equivalent of spec operations
7518 // ``CloneMethod`` and ``CloneBoundFunction``.
7519 static Handle<JSFunction> CloneClosure(Handle<JSFunction> function);
Steve Blocka7e24c12009-10-30 11:49:00 +00007520
Steve Block6ded16b2010-05-10 14:33:55 +01007521 // After prototype is removed, it will not be created when accessed, and
7522 // [[Construct]] from this function will not be allowed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007523 bool RemovePrototype();
Steve Block6ded16b2010-05-10 14:33:55 +01007524 inline bool should_have_prototype();
7525
Steve Blocka7e24c12009-10-30 11:49:00 +00007526 // Accessor for this function's initial map's [[class]]
7527 // property. This is primarily used by ECMA native functions. This
7528 // method sets the class_name field of this function's initial map
7529 // to a given value. It creates an initial map if this function does
7530 // not have one. Note that this method does not copy the initial map
7531 // if it has one already, but simply replaces it with the new value.
7532 // Instances created afterwards will have a map whose [[class]] is
7533 // set to 'value', but there is no guarantees on instances created
7534 // before.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007535 void SetInstanceClassName(String* name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007536
7537 // Returns if this function has been compiled to native code yet.
7538 inline bool is_compiled();
7539
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007540 // [next_function_link]: Links functions into various lists, e.g. the list
7541 // of optimized functions hanging off the native_context. The CodeFlusher
7542 // uses this link to chain together flushing candidates. Treated weakly
7543 // by the garbage collector.
Ben Murdochb0fe1622011-05-05 13:52:32 +01007544 DECL_ACCESSORS(next_function_link, Object)
7545
7546 // Prints the name of the function using PrintF.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007547 void PrintName(FILE* out = stdout);
Ben Murdochb0fe1622011-05-05 13:52:32 +01007548
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007549 DECLARE_CAST(JSFunction)
Steve Blocka7e24c12009-10-30 11:49:00 +00007550
Steve Block791712a2010-08-27 10:21:07 +01007551 // Iterates the objects, including code objects indirectly referenced
7552 // through pointers to the first instruction in the code object.
7553 void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
7554
Steve Blocka7e24c12009-10-30 11:49:00 +00007555 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007556 DECLARE_PRINTER(JSFunction)
7557 DECLARE_VERIFIER(JSFunction)
Steve Blocka7e24c12009-10-30 11:49:00 +00007558
7559 // Returns the number of allocated literals.
7560 inline int NumberOfLiterals();
7561
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007562 // Retrieve the native context from a function's literal array.
7563 static Context* NativeContextFromLiterals(FixedArray* literals);
7564
7565 // Used for flags such as --hydrogen-filter.
7566 bool PassesFilter(const char* raw_filter);
Steve Blocka7e24c12009-10-30 11:49:00 +00007567
Ben Murdochb0fe1622011-05-05 13:52:32 +01007568 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
7569 // kSize) is weak and has special handling during garbage collection.
Steve Block791712a2010-08-27 10:21:07 +01007570 static const int kCodeEntryOffset = JSObject::kHeaderSize;
Iain Merrick75681382010-08-19 15:07:18 +01007571 static const int kPrototypeOrInitialMapOffset =
Steve Block791712a2010-08-27 10:21:07 +01007572 kCodeEntryOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007573 static const int kSharedFunctionInfoOffset =
7574 kPrototypeOrInitialMapOffset + kPointerSize;
7575 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
7576 static const int kLiteralsOffset = kContextOffset + kPointerSize;
Ben Murdochb0fe1622011-05-05 13:52:32 +01007577 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize;
7578 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset;
7579 static const int kSize = kNextFunctionLinkOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007580
7581 // Layout of the literals array.
7582 static const int kLiteralsPrefixSize = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007583 static const int kLiteralNativeContextIndex = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007584
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007585 // Layout of the bound-function binding array.
7586 static const int kBoundFunctionIndex = 0;
7587 static const int kBoundThisIndex = 1;
7588 static const int kBoundArgumentsStartIndex = 2;
7589
Steve Blocka7e24c12009-10-30 11:49:00 +00007590 private:
7591 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
7592};
7593
7594
7595// JSGlobalProxy's prototype must be a JSGlobalObject or null,
7596// and the prototype is hidden. JSGlobalProxy always delegates
7597// property accesses to its prototype if the prototype is not null.
7598//
7599// A JSGlobalProxy can be reinitialized which will preserve its identity.
7600//
7601// Accessing a JSGlobalProxy requires security check.
7602
7603class JSGlobalProxy : public JSObject {
7604 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007605 // [native_context]: the owner native context of this global proxy object.
Steve Blocka7e24c12009-10-30 11:49:00 +00007606 // It is null value if this object is not used by any context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007607 DECL_ACCESSORS(native_context, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00007608
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007609 // [hash]: The hash code property (undefined if not initialized yet).
7610 DECL_ACCESSORS(hash, Object)
7611
7612 DECLARE_CAST(JSGlobalProxy)
7613
7614 inline bool IsDetachedFrom(GlobalObject* global) const;
Steve Blocka7e24c12009-10-30 11:49:00 +00007615
7616 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007617 DECLARE_PRINTER(JSGlobalProxy)
7618 DECLARE_VERIFIER(JSGlobalProxy)
Steve Blocka7e24c12009-10-30 11:49:00 +00007619
7620 // Layout description.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007621 static const int kNativeContextOffset = JSObject::kHeaderSize;
7622 static const int kHashOffset = kNativeContextOffset + kPointerSize;
7623 static const int kSize = kHashOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007624
7625 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00007626 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy);
7627};
7628
7629
7630// Forward declaration.
7631class JSBuiltinsObject;
7632
7633// Common super class for JavaScript global objects and the special
7634// builtins global objects.
7635class GlobalObject: public JSObject {
7636 public:
7637 // [builtins]: the object holding the runtime routines written in JS.
7638 DECL_ACCESSORS(builtins, JSBuiltinsObject)
7639
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007640 // [native context]: the natives corresponding to this global object.
7641 DECL_ACCESSORS(native_context, Context)
7642
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007643 // [global proxy]: the global proxy object of the context
7644 DECL_ACCESSORS(global_proxy, JSObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00007645
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007646 DECLARE_CAST(GlobalObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00007647
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007648 static void InvalidatePropertyCell(Handle<GlobalObject> object,
7649 Handle<Name> name);
7650
Steve Blocka7e24c12009-10-30 11:49:00 +00007651 // Layout description.
7652 static const int kBuiltinsOffset = JSObject::kHeaderSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007653 static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007654 static const int kGlobalProxyOffset = kNativeContextOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007655 static const int kHeaderSize = kGlobalProxyOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00007656
7657 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00007658 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
7659};
7660
7661
7662// JavaScript global object.
7663class JSGlobalObject: public GlobalObject {
7664 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007665 DECLARE_CAST(JSGlobalObject)
7666
7667 // Ensure that the global object has a cell for the given property name.
7668 static Handle<PropertyCell> EnsurePropertyCell(Handle<JSGlobalObject> global,
7669 Handle<Name> name);
7670
7671 inline bool IsDetached();
Steve Blocka7e24c12009-10-30 11:49:00 +00007672
7673 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007674 DECLARE_PRINTER(JSGlobalObject)
7675 DECLARE_VERIFIER(JSGlobalObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00007676
7677 // Layout description.
7678 static const int kSize = GlobalObject::kHeaderSize;
7679
7680 private:
7681 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject);
7682};
7683
7684
7685// Builtins global object which holds the runtime routines written in
7686// JavaScript.
7687class JSBuiltinsObject: public GlobalObject {
7688 public:
7689 // Accessors for the runtime routines written in JavaScript.
7690 inline Object* javascript_builtin(Builtins::JavaScript id);
7691 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value);
7692
Steve Block6ded16b2010-05-10 14:33:55 +01007693 // Accessors for code of the runtime routines written in JavaScript.
7694 inline Code* javascript_builtin_code(Builtins::JavaScript id);
7695 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value);
7696
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007697 DECLARE_CAST(JSBuiltinsObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00007698
7699 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007700 DECLARE_PRINTER(JSBuiltinsObject)
7701 DECLARE_VERIFIER(JSBuiltinsObject)
Steve Blocka7e24c12009-10-30 11:49:00 +00007702
7703 // Layout description. The size of the builtins object includes
Steve Block6ded16b2010-05-10 14:33:55 +01007704 // room for two pointers per runtime routine written in javascript
7705 // (function and code object).
Steve Blocka7e24c12009-10-30 11:49:00 +00007706 static const int kJSBuiltinsCount = Builtins::id_count;
7707 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize;
Steve Block6ded16b2010-05-10 14:33:55 +01007708 static const int kJSBuiltinsCodeOffset =
7709 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00007710 static const int kSize =
Steve Block6ded16b2010-05-10 14:33:55 +01007711 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize);
7712
7713 static int OffsetOfFunctionWithId(Builtins::JavaScript id) {
7714 return kJSBuiltinsOffset + id * kPointerSize;
7715 }
7716
7717 static int OffsetOfCodeWithId(Builtins::JavaScript id) {
7718 return kJSBuiltinsCodeOffset + id * kPointerSize;
7719 }
7720
Steve Blocka7e24c12009-10-30 11:49:00 +00007721 private:
7722 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject);
7723};
7724
7725
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007726// Representation for JS Wrapper objects, String, Number, Boolean, etc.
Steve Blocka7e24c12009-10-30 11:49:00 +00007727class JSValue: public JSObject {
7728 public:
7729 // [value]: the object being wrapped.
7730 DECL_ACCESSORS(value, Object)
7731
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007732 DECLARE_CAST(JSValue)
Steve Blocka7e24c12009-10-30 11:49:00 +00007733
7734 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007735 DECLARE_PRINTER(JSValue)
7736 DECLARE_VERIFIER(JSValue)
Steve Blocka7e24c12009-10-30 11:49:00 +00007737
7738 // Layout description.
7739 static const int kValueOffset = JSObject::kHeaderSize;
7740 static const int kSize = kValueOffset + kPointerSize;
7741
7742 private:
7743 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
7744};
7745
Steve Block1e0659c2011-05-24 12:43:12 +01007746
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007747class DateCache;
7748
7749// Representation for JS date objects.
7750class JSDate: public JSObject {
7751 public:
7752 // If one component is NaN, all of them are, indicating a NaN time value.
7753 // [value]: the time value.
7754 DECL_ACCESSORS(value, Object)
7755 // [year]: caches year. Either undefined, smi, or NaN.
7756 DECL_ACCESSORS(year, Object)
7757 // [month]: caches month. Either undefined, smi, or NaN.
7758 DECL_ACCESSORS(month, Object)
7759 // [day]: caches day. Either undefined, smi, or NaN.
7760 DECL_ACCESSORS(day, Object)
7761 // [weekday]: caches day of week. Either undefined, smi, or NaN.
7762 DECL_ACCESSORS(weekday, Object)
7763 // [hour]: caches hours. Either undefined, smi, or NaN.
7764 DECL_ACCESSORS(hour, Object)
7765 // [min]: caches minutes. Either undefined, smi, or NaN.
7766 DECL_ACCESSORS(min, Object)
7767 // [sec]: caches seconds. Either undefined, smi, or NaN.
7768 DECL_ACCESSORS(sec, Object)
7769 // [cache stamp]: sample of the date cache stamp at the
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007770 // moment when chached fields were cached.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007771 DECL_ACCESSORS(cache_stamp, Object)
7772
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007773 DECLARE_CAST(JSDate)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007774
7775 // Returns the date field with the specified index.
7776 // See FieldIndex for the list of date fields.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007777 static Object* GetField(Object* date, Smi* index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007778
7779 void SetValue(Object* value, bool is_value_nan);
7780
7781
7782 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007783 DECLARE_PRINTER(JSDate)
7784 DECLARE_VERIFIER(JSDate)
7785
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007786 // The order is important. It must be kept in sync with date macros
7787 // in macros.py.
7788 enum FieldIndex {
7789 kDateValue,
7790 kYear,
7791 kMonth,
7792 kDay,
7793 kWeekday,
7794 kHour,
7795 kMinute,
7796 kSecond,
7797 kFirstUncachedField,
7798 kMillisecond = kFirstUncachedField,
7799 kDays,
7800 kTimeInDay,
7801 kFirstUTCField,
7802 kYearUTC = kFirstUTCField,
7803 kMonthUTC,
7804 kDayUTC,
7805 kWeekdayUTC,
7806 kHourUTC,
7807 kMinuteUTC,
7808 kSecondUTC,
7809 kMillisecondUTC,
7810 kDaysUTC,
7811 kTimeInDayUTC,
7812 kTimezoneOffset
7813 };
7814
7815 // Layout description.
7816 static const int kValueOffset = JSObject::kHeaderSize;
7817 static const int kYearOffset = kValueOffset + kPointerSize;
7818 static const int kMonthOffset = kYearOffset + kPointerSize;
7819 static const int kDayOffset = kMonthOffset + kPointerSize;
7820 static const int kWeekdayOffset = kDayOffset + kPointerSize;
7821 static const int kHourOffset = kWeekdayOffset + kPointerSize;
7822 static const int kMinOffset = kHourOffset + kPointerSize;
7823 static const int kSecOffset = kMinOffset + kPointerSize;
7824 static const int kCacheStampOffset = kSecOffset + kPointerSize;
7825 static const int kSize = kCacheStampOffset + kPointerSize;
7826
7827 private:
7828 inline Object* DoGetField(FieldIndex index);
7829
7830 Object* GetUTCField(FieldIndex index, double value, DateCache* date_cache);
7831
7832 // Computes and caches the cacheable fields of the date.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007833 inline void SetCachedFields(int64_t local_time_ms, DateCache* date_cache);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007834
7835
7836 DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate);
7837};
7838
7839
Steve Block1e0659c2011-05-24 12:43:12 +01007840// Representation of message objects used for error reporting through
7841// the API. The messages are formatted in JavaScript so this object is
7842// a real JavaScript object. The information used for formatting the
7843// error messages are not directly accessible from JavaScript to
7844// prevent leaking information to user code called during error
7845// formatting.
7846class JSMessageObject: public JSObject {
7847 public:
7848 // [type]: the type of error message.
7849 DECL_ACCESSORS(type, String)
7850
7851 // [arguments]: the arguments for formatting the error message.
7852 DECL_ACCESSORS(arguments, JSArray)
7853
7854 // [script]: the script from which the error message originated.
7855 DECL_ACCESSORS(script, Object)
7856
Steve Block1e0659c2011-05-24 12:43:12 +01007857 // [stack_frames]: an array of stack frames for this error object.
7858 DECL_ACCESSORS(stack_frames, Object)
7859
7860 // [start_position]: the start position in the script for the error message.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007861 inline int start_position() const;
Steve Block1e0659c2011-05-24 12:43:12 +01007862 inline void set_start_position(int value);
7863
7864 // [end_position]: the end position in the script for the error message.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007865 inline int end_position() const;
Steve Block1e0659c2011-05-24 12:43:12 +01007866 inline void set_end_position(int value);
7867
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007868 DECLARE_CAST(JSMessageObject)
Steve Block1e0659c2011-05-24 12:43:12 +01007869
7870 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007871 DECLARE_PRINTER(JSMessageObject)
7872 DECLARE_VERIFIER(JSMessageObject)
Steve Block1e0659c2011-05-24 12:43:12 +01007873
7874 // Layout description.
7875 static const int kTypeOffset = JSObject::kHeaderSize;
7876 static const int kArgumentsOffset = kTypeOffset + kPointerSize;
7877 static const int kScriptOffset = kArgumentsOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007878 static const int kStackFramesOffset = kScriptOffset + kPointerSize;
Steve Block1e0659c2011-05-24 12:43:12 +01007879 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize;
7880 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
7881 static const int kSize = kEndPositionOffset + kPointerSize;
7882
7883 typedef FixedBodyDescriptor<HeapObject::kMapOffset,
7884 kStackFramesOffset + kPointerSize,
7885 kSize> BodyDescriptor;
7886};
7887
7888
Steve Blocka7e24c12009-10-30 11:49:00 +00007889// Regular expressions
7890// The regular expression holds a single reference to a FixedArray in
7891// the kDataOffset field.
7892// The FixedArray contains the following data:
7893// - tag : type of regexp implementation (not compiled yet, atom or irregexp)
7894// - reference to the original source string
7895// - reference to the original flag string
7896// If it is an atom regexp
7897// - a reference to a literal string to search for
7898// If it is an irregexp regexp:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007899// - a reference to code for Latin1 inputs (bytecode or compiled), or a smi
Ben Murdoch257744e2011-11-30 15:57:28 +00007900// used for tracking the last usage (used for code flushing).
7901// - a reference to code for UC16 inputs (bytecode or compiled), or a smi
7902// used for tracking the last usage (used for code flushing)..
Steve Blocka7e24c12009-10-30 11:49:00 +00007903// - max number of registers used by irregexp implementations.
7904// - number of capture registers (output values) of the regexp.
7905class JSRegExp: public JSObject {
7906 public:
7907 // Meaning of Type:
7908 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet.
7909 // ATOM: A simple string to match against using an indexOf operation.
7910 // IRREGEXP: Compiled with Irregexp.
7911 // IRREGEXP_NATIVE: Compiled to native code with Irregexp.
7912 enum Type { NOT_COMPILED, ATOM, IRREGEXP };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007913 enum Flag {
7914 NONE = 0,
7915 GLOBAL = 1,
7916 IGNORE_CASE = 2,
7917 MULTILINE = 4,
7918 STICKY = 8
7919 };
Steve Blocka7e24c12009-10-30 11:49:00 +00007920
7921 class Flags {
7922 public:
7923 explicit Flags(uint32_t value) : value_(value) { }
7924 bool is_global() { return (value_ & GLOBAL) != 0; }
7925 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
7926 bool is_multiline() { return (value_ & MULTILINE) != 0; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007927 bool is_sticky() { return (value_ & STICKY) != 0; }
Steve Blocka7e24c12009-10-30 11:49:00 +00007928 uint32_t value() { return value_; }
7929 private:
7930 uint32_t value_;
7931 };
7932
7933 DECL_ACCESSORS(data, Object)
7934
7935 inline Type TypeTag();
7936 inline int CaptureCount();
7937 inline Flags GetFlags();
7938 inline String* Pattern();
7939 inline Object* DataAt(int index);
7940 // Set implementation data after the object has been prepared.
7941 inline void SetDataAt(int index, Object* value);
Ben Murdoch257744e2011-11-30 15:57:28 +00007942
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007943 static int code_index(bool is_latin1) {
7944 if (is_latin1) {
7945 return kIrregexpLatin1CodeIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00007946 } else {
7947 return kIrregexpUC16CodeIndex;
7948 }
7949 }
7950
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007951 static int saved_code_index(bool is_latin1) {
7952 if (is_latin1) {
7953 return kIrregexpLatin1CodeSavedIndex;
Ben Murdoch257744e2011-11-30 15:57:28 +00007954 } else {
7955 return kIrregexpUC16CodeSavedIndex;
7956 }
7957 }
7958
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007959 DECLARE_CAST(JSRegExp)
Steve Blocka7e24c12009-10-30 11:49:00 +00007960
7961 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007962 DECLARE_VERIFIER(JSRegExp)
Steve Blocka7e24c12009-10-30 11:49:00 +00007963
7964 static const int kDataOffset = JSObject::kHeaderSize;
7965 static const int kSize = kDataOffset + kPointerSize;
7966
7967 // Indices in the data array.
7968 static const int kTagIndex = 0;
7969 static const int kSourceIndex = kTagIndex + 1;
7970 static const int kFlagsIndex = kSourceIndex + 1;
7971 static const int kDataIndex = kFlagsIndex + 1;
7972 // The data fields are used in different ways depending on the
7973 // value of the tag.
7974 // Atom regexps (literal strings).
7975 static const int kAtomPatternIndex = kDataIndex;
7976
7977 static const int kAtomDataSize = kAtomPatternIndex + 1;
7978
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007979 // Irregexp compiled code or bytecode for Latin1. If compilation
Steve Blocka7e24c12009-10-30 11:49:00 +00007980 // fails, this fields hold an exception object that should be
7981 // thrown if the regexp is used again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007982 static const int kIrregexpLatin1CodeIndex = kDataIndex;
Steve Blocka7e24c12009-10-30 11:49:00 +00007983 // Irregexp compiled code or bytecode for UC16. If compilation
7984 // fails, this fields hold an exception object that should be
7985 // thrown if the regexp is used again.
7986 static const int kIrregexpUC16CodeIndex = kDataIndex + 1;
Ben Murdoch257744e2011-11-30 15:57:28 +00007987
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007988 // Saved instance of Irregexp compiled code or bytecode for Latin1 that
Ben Murdoch257744e2011-11-30 15:57:28 +00007989 // is a potential candidate for flushing.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007990 static const int kIrregexpLatin1CodeSavedIndex = kDataIndex + 2;
Ben Murdoch257744e2011-11-30 15:57:28 +00007991 // Saved instance of Irregexp compiled code or bytecode for UC16 that is
7992 // a potential candidate for flushing.
7993 static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3;
7994
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007995 // Maximal number of registers used by either Latin1 or UC16.
Steve Blocka7e24c12009-10-30 11:49:00 +00007996 // Only used to check that there is enough stack space
Ben Murdoch257744e2011-11-30 15:57:28 +00007997 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4;
Steve Blocka7e24c12009-10-30 11:49:00 +00007998 // Number of captures in the compiled regexp.
Ben Murdoch257744e2011-11-30 15:57:28 +00007999 static const int kIrregexpCaptureCountIndex = kDataIndex + 5;
Steve Blocka7e24c12009-10-30 11:49:00 +00008000
8001 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1;
Leon Clarkee46be812010-01-19 14:06:41 +00008002
8003 // Offsets directly into the data fixed array.
8004 static const int kDataTagOffset =
8005 FixedArray::kHeaderSize + kTagIndex * kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008006 static const int kDataOneByteCodeOffset =
8007 FixedArray::kHeaderSize + kIrregexpLatin1CodeIndex * kPointerSize;
Leon Clarked91b9f72010-01-27 17:25:45 +00008008 static const int kDataUC16CodeOffset =
8009 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize;
Leon Clarkee46be812010-01-19 14:06:41 +00008010 static const int kIrregexpCaptureCountOffset =
8011 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01008012
8013 // In-object fields.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008014 static const int kGlobalFieldIndex = 0;
8015 static const int kIgnoreCaseFieldIndex = 1;
8016 static const int kMultilineFieldIndex = 2;
8017 static const int kLastIndexFieldIndex = 3;
8018 static const int kInObjectFieldCount = 4;
Ben Murdoch257744e2011-11-30 15:57:28 +00008019
8020 // The uninitialized value for a regexp code object.
8021 static const int kUninitializedValue = -1;
8022
8023 // The compilation error value for the regexp code object. The real error
8024 // object is in the saved code field.
8025 static const int kCompilationErrorValue = -2;
8026
8027 // When we store the sweep generation at which we moved the code from the
8028 // code index to the saved code index we mask it of to be in the [0:255]
8029 // range.
8030 static const int kCodeAgeMask = 0xff;
Steve Blocka7e24c12009-10-30 11:49:00 +00008031};
8032
8033
Ben Murdochc7cc0282012-03-05 14:35:55 +00008034class CompilationCacheShape : public BaseShape<HashTableKey*> {
Steve Blocka7e24c12009-10-30 11:49:00 +00008035 public:
8036 static inline bool IsMatch(HashTableKey* key, Object* value) {
8037 return key->IsMatch(value);
8038 }
8039
8040 static inline uint32_t Hash(HashTableKey* key) {
8041 return key->Hash();
8042 }
8043
8044 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
8045 return key->HashForObject(object);
8046 }
8047
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008048 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
Steve Blocka7e24c12009-10-30 11:49:00 +00008049
8050 static const int kPrefixSize = 0;
8051 static const int kEntrySize = 2;
8052};
8053
Steve Block3ce2e202009-11-05 08:53:23 +00008054
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008055// This cache is used in two different variants. For regexp caching, it simply
8056// maps identifying info of the regexp to the cached regexp object. Scripts and
8057// eval code only gets cached after a second probe for the code object. To do
8058// so, on first "put" only a hash identifying the source is entered into the
8059// cache, mapping it to a lifetime count of the hash. On each call to Age all
8060// such lifetimes get reduced, and removed once they reach zero. If a second put
8061// is called while such a hash is live in the cache, the hash gets replaced by
8062// an actual cache entry. Age also removes stale live entries from the cache.
8063// Such entries are identified by SharedFunctionInfos pointing to either the
8064// recompilation stub, or to "old" code. This avoids memory leaks due to
8065// premature caching of scripts and eval strings that are never needed later.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008066class CompilationCacheTable: public HashTable<CompilationCacheTable,
8067 CompilationCacheShape,
Steve Blocka7e24c12009-10-30 11:49:00 +00008068 HashTableKey*> {
8069 public:
8070 // Find cached value for a string key, otherwise return null.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008071 Handle<Object> Lookup(Handle<String> src, Handle<Context> context);
8072 Handle<Object> LookupEval(Handle<String> src,
8073 Handle<SharedFunctionInfo> shared,
8074 StrictMode strict_mode, int scope_position);
8075 Handle<Object> LookupRegExp(Handle<String> source, JSRegExp::Flags flags);
8076 static Handle<CompilationCacheTable> Put(
8077 Handle<CompilationCacheTable> cache, Handle<String> src,
8078 Handle<Context> context, Handle<Object> value);
8079 static Handle<CompilationCacheTable> PutEval(
8080 Handle<CompilationCacheTable> cache, Handle<String> src,
8081 Handle<SharedFunctionInfo> context, Handle<SharedFunctionInfo> value,
8082 int scope_position);
8083 static Handle<CompilationCacheTable> PutRegExp(
8084 Handle<CompilationCacheTable> cache, Handle<String> src,
8085 JSRegExp::Flags flags, Handle<FixedArray> value);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008086 void Remove(Object* value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008087 void Age();
8088 static const int kHashGenerations = 10;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008090 DECLARE_CAST(CompilationCacheTable)
Steve Blocka7e24c12009-10-30 11:49:00 +00008091
8092 private:
8093 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
8094};
8095
8096
Steve Block6ded16b2010-05-10 14:33:55 +01008097class CodeCache: public Struct {
8098 public:
8099 DECL_ACCESSORS(default_cache, FixedArray)
8100 DECL_ACCESSORS(normal_type_cache, Object)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008101 DECL_ACCESSORS(weak_cell_cache, Object)
Steve Block6ded16b2010-05-10 14:33:55 +01008102
8103 // Add the code object to the cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008104 static void Update(
8105 Handle<CodeCache> cache, Handle<Name> name, Handle<Code> code);
Steve Block6ded16b2010-05-10 14:33:55 +01008106
8107 // Lookup code object in the cache. Returns code object if found and undefined
8108 // if not.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008109 Object* Lookup(Name* name, Code::Flags flags);
Steve Block6ded16b2010-05-10 14:33:55 +01008110
8111 // Get the internal index of a code object in the cache. Returns -1 if the
8112 // code object is not in that cache. This index can be used to later call
8113 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and
8114 // RemoveByIndex.
8115 int GetIndex(Object* name, Code* code);
8116
8117 // Remove an object from the cache with the provided internal index.
8118 void RemoveByIndex(Object* name, Code* code, int index);
8119
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008120 DECLARE_CAST(CodeCache)
Steve Block6ded16b2010-05-10 14:33:55 +01008121
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008122 // Dispatched behavior.
8123 DECLARE_PRINTER(CodeCache)
8124 DECLARE_VERIFIER(CodeCache)
Steve Block6ded16b2010-05-10 14:33:55 +01008125
8126 static const int kDefaultCacheOffset = HeapObject::kHeaderSize;
8127 static const int kNormalTypeCacheOffset =
8128 kDefaultCacheOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008129 static const int kWeakCellCacheOffset = kNormalTypeCacheOffset + kPointerSize;
8130 static const int kSize = kWeakCellCacheOffset + kPointerSize;
Steve Block6ded16b2010-05-10 14:33:55 +01008131
8132 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008133 static void UpdateDefaultCache(
8134 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
8135 static void UpdateNormalTypeCache(
8136 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code);
8137 Object* LookupDefaultCache(Name* name, Code::Flags flags);
8138 Object* LookupNormalTypeCache(Name* name, Code::Flags flags);
Steve Block6ded16b2010-05-10 14:33:55 +01008139
8140 // Code cache layout of the default cache. Elements are alternating name and
8141 // code objects for non normal load/store/call IC's.
8142 static const int kCodeCacheEntrySize = 2;
8143 static const int kCodeCacheEntryNameOffset = 0;
8144 static const int kCodeCacheEntryCodeOffset = 1;
8145
8146 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache);
8147};
8148
8149
Ben Murdochc7cc0282012-03-05 14:35:55 +00008150class CodeCacheHashTableShape : public BaseShape<HashTableKey*> {
Steve Block6ded16b2010-05-10 14:33:55 +01008151 public:
8152 static inline bool IsMatch(HashTableKey* key, Object* value) {
8153 return key->IsMatch(value);
8154 }
8155
8156 static inline uint32_t Hash(HashTableKey* key) {
8157 return key->Hash();
8158 }
8159
8160 static inline uint32_t HashForObject(HashTableKey* key, Object* object) {
8161 return key->HashForObject(object);
8162 }
8163
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008164 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key);
Steve Block6ded16b2010-05-10 14:33:55 +01008165
8166 static const int kPrefixSize = 0;
8167 static const int kEntrySize = 2;
8168};
8169
8170
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008171class CodeCacheHashTable: public HashTable<CodeCacheHashTable,
8172 CodeCacheHashTableShape,
Steve Block6ded16b2010-05-10 14:33:55 +01008173 HashTableKey*> {
8174 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008175 Object* Lookup(Name* name, Code::Flags flags);
8176 static Handle<CodeCacheHashTable> Put(
8177 Handle<CodeCacheHashTable> table,
8178 Handle<Name> name,
8179 Handle<Code> code);
Steve Block6ded16b2010-05-10 14:33:55 +01008180
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008181 int GetIndex(Name* name, Code::Flags flags);
Steve Block6ded16b2010-05-10 14:33:55 +01008182 void RemoveByIndex(int index);
8183
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008184 DECLARE_CAST(CodeCacheHashTable)
Steve Block6ded16b2010-05-10 14:33:55 +01008185
8186 // Initial size of the fixed array backing the hash table.
8187 static const int kInitialSize = 64;
8188
8189 private:
8190 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable);
8191};
8192
8193
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008194class PolymorphicCodeCache: public Struct {
8195 public:
8196 DECL_ACCESSORS(cache, Object)
8197
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008198 static void Update(Handle<PolymorphicCodeCache> cache,
8199 MapHandleList* maps,
8200 Code::Flags flags,
8201 Handle<Code> code);
8202
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008203
8204 // Returns an undefined value if the entry is not found.
8205 Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008206
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008207 DECLARE_CAST(PolymorphicCodeCache)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008208
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008209 // Dispatched behavior.
8210 DECLARE_PRINTER(PolymorphicCodeCache)
8211 DECLARE_VERIFIER(PolymorphicCodeCache)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008212
8213 static const int kCacheOffset = HeapObject::kHeaderSize;
8214 static const int kSize = kCacheOffset + kPointerSize;
8215
8216 private:
8217 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache);
8218};
8219
8220
8221class PolymorphicCodeCacheHashTable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008222 : public HashTable<PolymorphicCodeCacheHashTable,
8223 CodeCacheHashTableShape,
8224 HashTableKey*> {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008225 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008226 Object* Lookup(MapHandleList* maps, int code_kind);
8227
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008228 static Handle<PolymorphicCodeCacheHashTable> Put(
8229 Handle<PolymorphicCodeCacheHashTable> hash_table,
8230 MapHandleList* maps,
8231 int code_kind,
8232 Handle<Code> code);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008233
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008234 DECLARE_CAST(PolymorphicCodeCacheHashTable)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008235
8236 static const int kInitialSize = 64;
8237 private:
8238 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable);
8239};
8240
8241
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008242class TypeFeedbackInfo: public Struct {
8243 public:
8244 inline int ic_total_count();
8245 inline void set_ic_total_count(int count);
8246
Ben Murdoch8f9999f2012-04-23 10:39:17 +01008247 inline int ic_with_type_info_count();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008248 inline void change_ic_with_type_info_count(int delta);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008249
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008250 inline int ic_generic_count();
8251 inline void change_ic_generic_count(int delta);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008252
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008253 inline void initialize_storage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008254
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008255 inline void change_own_type_change_checksum();
8256 inline int own_type_change_checksum();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008257
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008258 inline void set_inlined_type_change_checksum(int checksum);
8259 inline bool matches_inlined_type_change_checksum(int checksum);
8260
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008261 DECLARE_CAST(TypeFeedbackInfo)
8262
8263 // Dispatched behavior.
8264 DECLARE_PRINTER(TypeFeedbackInfo)
8265 DECLARE_VERIFIER(TypeFeedbackInfo)
8266
8267 static const int kStorage1Offset = HeapObject::kHeaderSize;
8268 static const int kStorage2Offset = kStorage1Offset + kPointerSize;
8269 static const int kStorage3Offset = kStorage2Offset + kPointerSize;
8270 static const int kSize = kStorage3Offset + kPointerSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008271
8272 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008273 static const int kTypeChangeChecksumBits = 7;
8274
8275 class ICTotalCountField: public BitField<int, 0,
8276 kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
8277 class OwnTypeChangeChecksum: public BitField<int,
8278 kSmiValueSize - kTypeChangeChecksumBits,
8279 kTypeChangeChecksumBits> {}; // NOLINT
8280 class ICsWithTypeInfoCountField: public BitField<int, 0,
8281 kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT
8282 class InlinedTypeChangeChecksum: public BitField<int,
8283 kSmiValueSize - kTypeChangeChecksumBits,
8284 kTypeChangeChecksumBits> {}; // NOLINT
8285
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008286 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackInfo);
8287};
8288
8289
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008290enum AllocationSiteMode {
8291 DONT_TRACK_ALLOCATION_SITE,
8292 TRACK_ALLOCATION_SITE,
8293 LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE
8294};
8295
8296
8297class AllocationSite: public Struct {
8298 public:
8299 static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024;
8300 static const double kPretenureRatio;
8301 static const int kPretenureMinimumCreated = 100;
8302
8303 // Values for pretenure decision field.
8304 enum PretenureDecision {
8305 kUndecided = 0,
8306 kDontTenure = 1,
8307 kMaybeTenure = 2,
8308 kTenure = 3,
8309 kZombie = 4,
8310 kLastPretenureDecisionValue = kZombie
8311 };
8312
8313 const char* PretenureDecisionName(PretenureDecision decision);
8314
8315 DECL_ACCESSORS(transition_info, Object)
8316 // nested_site threads a list of sites that represent nested literals
8317 // walked in a particular order. So [[1, 2], 1, 2] will have one
8318 // nested_site, but [[1, 2], 3, [4]] will have a list of two.
8319 DECL_ACCESSORS(nested_site, Object)
8320 DECL_ACCESSORS(pretenure_data, Smi)
8321 DECL_ACCESSORS(pretenure_create_count, Smi)
8322 DECL_ACCESSORS(dependent_code, DependentCode)
8323 DECL_ACCESSORS(weak_next, Object)
8324
8325 inline void Initialize();
8326
8327 // This method is expensive, it should only be called for reporting.
8328 bool IsNestedSite();
8329
8330 // transition_info bitfields, for constructed array transition info.
8331 class ElementsKindBits: public BitField<ElementsKind, 0, 15> {};
8332 class UnusedBits: public BitField<int, 15, 14> {};
8333 class DoNotInlineBit: public BitField<bool, 29, 1> {};
8334
8335 // Bitfields for pretenure_data
8336 class MementoFoundCountBits: public BitField<int, 0, 26> {};
8337 class PretenureDecisionBits: public BitField<PretenureDecision, 26, 3> {};
8338 class DeoptDependentCodeBit: public BitField<bool, 29, 1> {};
8339 STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue);
8340
8341 // Increments the mementos found counter and returns true when the first
8342 // memento was found for a given allocation site.
8343 inline bool IncrementMementoFoundCount();
8344
8345 inline void IncrementMementoCreateCount();
8346
8347 PretenureFlag GetPretenureMode();
8348
8349 void ResetPretenureDecision();
8350
8351 PretenureDecision pretenure_decision() {
8352 int value = pretenure_data()->value();
8353 return PretenureDecisionBits::decode(value);
8354 }
8355
8356 void set_pretenure_decision(PretenureDecision decision) {
8357 int value = pretenure_data()->value();
8358 set_pretenure_data(
8359 Smi::FromInt(PretenureDecisionBits::update(value, decision)),
8360 SKIP_WRITE_BARRIER);
8361 }
8362
8363 bool deopt_dependent_code() {
8364 int value = pretenure_data()->value();
8365 return DeoptDependentCodeBit::decode(value);
8366 }
8367
8368 void set_deopt_dependent_code(bool deopt) {
8369 int value = pretenure_data()->value();
8370 set_pretenure_data(
8371 Smi::FromInt(DeoptDependentCodeBit::update(value, deopt)),
8372 SKIP_WRITE_BARRIER);
8373 }
8374
8375 int memento_found_count() {
8376 int value = pretenure_data()->value();
8377 return MementoFoundCountBits::decode(value);
8378 }
8379
8380 inline void set_memento_found_count(int count);
8381
8382 int memento_create_count() {
8383 return pretenure_create_count()->value();
8384 }
8385
8386 void set_memento_create_count(int count) {
8387 set_pretenure_create_count(Smi::FromInt(count), SKIP_WRITE_BARRIER);
8388 }
8389
8390 // The pretenuring decision is made during gc, and the zombie state allows
8391 // us to recognize when an allocation site is just being kept alive because
8392 // a later traversal of new space may discover AllocationMementos that point
8393 // to this AllocationSite.
8394 bool IsZombie() {
8395 return pretenure_decision() == kZombie;
8396 }
8397
8398 bool IsMaybeTenure() {
8399 return pretenure_decision() == kMaybeTenure;
8400 }
8401
8402 inline void MarkZombie();
8403
8404 inline bool MakePretenureDecision(PretenureDecision current_decision,
8405 double ratio,
8406 bool maximum_size_scavenge);
8407
8408 inline bool DigestPretenuringFeedback(bool maximum_size_scavenge);
8409
8410 ElementsKind GetElementsKind() {
8411 DCHECK(!SitePointsToLiteral());
8412 int value = Smi::cast(transition_info())->value();
8413 return ElementsKindBits::decode(value);
8414 }
8415
8416 void SetElementsKind(ElementsKind kind) {
8417 int value = Smi::cast(transition_info())->value();
8418 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)),
8419 SKIP_WRITE_BARRIER);
8420 }
8421
8422 bool CanInlineCall() {
8423 int value = Smi::cast(transition_info())->value();
8424 return DoNotInlineBit::decode(value) == 0;
8425 }
8426
8427 void SetDoNotInlineCall() {
8428 int value = Smi::cast(transition_info())->value();
8429 set_transition_info(Smi::FromInt(DoNotInlineBit::update(value, true)),
8430 SKIP_WRITE_BARRIER);
8431 }
8432
8433 bool SitePointsToLiteral() {
8434 // If transition_info is a smi, then it represents an ElementsKind
8435 // for a constructed array. Otherwise, it must be a boilerplate
8436 // for an object or array literal.
8437 return transition_info()->IsJSArray() || transition_info()->IsJSObject();
8438 }
8439
8440 static void DigestTransitionFeedback(Handle<AllocationSite> site,
8441 ElementsKind to_kind);
8442
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008443 static void RegisterForDeoptOnTenureChange(Handle<AllocationSite> site,
8444 CompilationInfo* info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008445
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008446 static void RegisterForDeoptOnTransitionChange(Handle<AllocationSite> site,
8447 CompilationInfo* info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008448
8449 DECLARE_PRINTER(AllocationSite)
8450 DECLARE_VERIFIER(AllocationSite)
8451
8452 DECLARE_CAST(AllocationSite)
8453 static inline AllocationSiteMode GetMode(
8454 ElementsKind boilerplate_elements_kind);
8455 static inline AllocationSiteMode GetMode(ElementsKind from, ElementsKind to);
8456 static inline bool CanTrack(InstanceType type);
8457
8458 static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
8459 static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
8460 static const int kPretenureDataOffset = kNestedSiteOffset + kPointerSize;
8461 static const int kPretenureCreateCountOffset =
8462 kPretenureDataOffset + kPointerSize;
8463 static const int kDependentCodeOffset =
8464 kPretenureCreateCountOffset + kPointerSize;
8465 static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
8466 static const int kSize = kWeakNextOffset + kPointerSize;
8467
8468 // During mark compact we need to take special care for the dependent code
8469 // field.
8470 static const int kPointerFieldsBeginOffset = kTransitionInfoOffset;
8471 static const int kPointerFieldsEndOffset = kDependentCodeOffset;
8472
8473 // For other visitors, use the fixed body descriptor below.
8474 typedef FixedBodyDescriptor<HeapObject::kHeaderSize,
8475 kDependentCodeOffset + kPointerSize,
8476 kSize> BodyDescriptor;
8477
8478 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008479 static void AddDependentCompilationInfo(Handle<AllocationSite> site,
8480 DependentCode::DependencyGroup group,
8481 CompilationInfo* info);
8482
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008483 bool PretenuringDecisionMade() {
8484 return pretenure_decision() != kUndecided;
8485 }
8486
8487 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite);
8488};
8489
8490
8491class AllocationMemento: public Struct {
8492 public:
8493 static const int kAllocationSiteOffset = HeapObject::kHeaderSize;
8494 static const int kSize = kAllocationSiteOffset + kPointerSize;
8495
8496 DECL_ACCESSORS(allocation_site, Object)
8497
8498 bool IsValid() {
8499 return allocation_site()->IsAllocationSite() &&
8500 !AllocationSite::cast(allocation_site())->IsZombie();
8501 }
8502 AllocationSite* GetAllocationSite() {
8503 DCHECK(IsValid());
8504 return AllocationSite::cast(allocation_site());
8505 }
8506
8507 DECLARE_PRINTER(AllocationMemento)
8508 DECLARE_VERIFIER(AllocationMemento)
8509
8510 DECLARE_CAST(AllocationMemento)
8511
8512 private:
8513 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationMemento);
8514};
8515
8516
8517// Representation of a slow alias as part of a sloppy arguments objects.
8518// For fast aliases (if HasSloppyArgumentsElements()):
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008519// - the parameter map contains an index into the context
8520// - all attributes of the element have default values
8521// For slow aliases (if HasDictionaryArgumentsElements()):
8522// - the parameter map contains no fast alias mapping (i.e. the hole)
8523// - this struct (in the slow backing store) contains an index into the context
8524// - all attributes are available as part if the property details
8525class AliasedArgumentsEntry: public Struct {
8526 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008527 inline int aliased_context_slot() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008528 inline void set_aliased_context_slot(int count);
8529
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008530 DECLARE_CAST(AliasedArgumentsEntry)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008531
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008532 // Dispatched behavior.
8533 DECLARE_PRINTER(AliasedArgumentsEntry)
8534 DECLARE_VERIFIER(AliasedArgumentsEntry)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008535
8536 static const int kAliasedContextSlot = HeapObject::kHeaderSize;
8537 static const int kSize = kAliasedContextSlot + kPointerSize;
8538
8539 private:
8540 DISALLOW_IMPLICIT_CONSTRUCTORS(AliasedArgumentsEntry);
8541};
8542
8543
Steve Blocka7e24c12009-10-30 11:49:00 +00008544enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
8545enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
8546
8547
8548class StringHasher {
8549 public:
Ben Murdochc7cc0282012-03-05 14:35:55 +00008550 explicit inline StringHasher(int length, uint32_t seed);
Steve Blocka7e24c12009-10-30 11:49:00 +00008551
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008552 template <typename schar>
8553 static inline uint32_t HashSequentialString(const schar* chars,
8554 int length,
8555 uint32_t seed);
Steve Blocka7e24c12009-10-30 11:49:00 +00008556
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008557 // Reads all the data, even for long strings and computes the utf16 length.
8558 static uint32_t ComputeUtf8Hash(Vector<const char> chars,
8559 uint32_t seed,
8560 int* utf16_length_out);
Steve Blocka7e24c12009-10-30 11:49:00 +00008561
Kristian Monsen80d68ea2010-09-08 11:05:35 +01008562 // Calculated hash value for a string consisting of 1 to
8563 // String::kMaxArrayIndexSize digits with no leading zeros (except "0").
8564 // value is represented decimal value.
Iain Merrick9ac36c92010-09-13 15:29:50 +01008565 static uint32_t MakeArrayIndexHash(uint32_t value, int length);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01008566
Ben Murdochc7cc0282012-03-05 14:35:55 +00008567 // No string is allowed to have a hash of zero. That value is reserved
8568 // for internal properties. If the hash calculation yields zero then we
8569 // use 27 instead.
8570 static const int kZeroHash = 27;
8571
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008572 // Reusable parts of the hashing algorithm.
8573 INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint16_t c));
8574 INLINE(static uint32_t GetHashCore(uint32_t running_hash));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008575 INLINE(static uint32_t ComputeRunningHash(uint32_t running_hash,
8576 const uc16* chars, int length));
8577 INLINE(static uint32_t ComputeRunningHashOneByte(uint32_t running_hash,
8578 const char* chars,
8579 int length));
Steve Blocka7e24c12009-10-30 11:49:00 +00008580
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008581 protected:
8582 // Returns the value to store in the hash field of a string with
8583 // the given length and contents.
8584 uint32_t GetHashField();
8585 // Returns true if the hash of this string can be computed without
8586 // looking at the contents.
8587 inline bool has_trivial_hash();
8588 // Adds a block of characters to the hash.
8589 template<typename Char>
8590 inline void AddCharacters(const Char* chars, int len);
8591
8592 private:
8593 // Add a character to the hash.
8594 inline void AddCharacter(uint16_t c);
8595 // Update index. Returns true if string is still an index.
8596 inline bool UpdateIndex(uint16_t c);
Steve Blocka7e24c12009-10-30 11:49:00 +00008597
8598 int length_;
8599 uint32_t raw_running_hash_;
8600 uint32_t array_index_;
8601 bool is_array_index_;
8602 bool is_first_char_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008603 DISALLOW_COPY_AND_ASSIGN(StringHasher);
Steve Blocka7e24c12009-10-30 11:49:00 +00008604};
8605
8606
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008607class IteratingStringHasher : public StringHasher {
8608 public:
8609 static inline uint32_t Hash(String* string, uint32_t seed);
8610 inline void VisitOneByteString(const uint8_t* chars, int length);
8611 inline void VisitTwoByteString(const uint16_t* chars, int length);
8612
8613 private:
8614 inline IteratingStringHasher(int len, uint32_t seed)
8615 : StringHasher(len, seed) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008616 void VisitConsString(ConsString* cons_string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008617 DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
8618};
Steve Block44f0eee2011-05-26 01:26:41 +01008619
8620
Steve Blocka7e24c12009-10-30 11:49:00 +00008621// The characteristics of a string are stored in its map. Retrieving these
8622// few bits of information is moderately expensive, involving two memory
8623// loads where the second is dependent on the first. To improve efficiency
8624// the shape of the string is given its own class so that it can be retrieved
8625// once and used for several string operations. A StringShape is small enough
8626// to be passed by value and is immutable, but be aware that flattening a
8627// string can potentially alter its shape. Also be aware that a GC caused by
8628// something else can alter the shape of a string due to ConsString
8629// shortcutting. Keeping these restrictions in mind has proven to be error-
8630// prone and so we no longer put StringShapes in variables unless there is a
8631// concrete performance benefit at that particular point in the code.
8632class StringShape BASE_EMBEDDED {
8633 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008634 inline explicit StringShape(const String* s);
Steve Blocka7e24c12009-10-30 11:49:00 +00008635 inline explicit StringShape(Map* s);
8636 inline explicit StringShape(InstanceType t);
8637 inline bool IsSequential();
8638 inline bool IsExternal();
8639 inline bool IsCons();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008640 inline bool IsSliced();
8641 inline bool IsIndirect();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008642 inline bool IsExternalOneByte();
Steve Blocka7e24c12009-10-30 11:49:00 +00008643 inline bool IsExternalTwoByte();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008644 inline bool IsSequentialOneByte();
Steve Blocka7e24c12009-10-30 11:49:00 +00008645 inline bool IsSequentialTwoByte();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008646 inline bool IsInternalized();
Steve Blocka7e24c12009-10-30 11:49:00 +00008647 inline StringRepresentationTag representation_tag();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008648 inline uint32_t encoding_tag();
Steve Blocka7e24c12009-10-30 11:49:00 +00008649 inline uint32_t full_representation_tag();
8650 inline uint32_t size_tag();
8651#ifdef DEBUG
8652 inline uint32_t type() { return type_; }
8653 inline void invalidate() { valid_ = false; }
8654 inline bool valid() { return valid_; }
8655#else
8656 inline void invalidate() { }
8657#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00008658
Steve Blocka7e24c12009-10-30 11:49:00 +00008659 private:
8660 uint32_t type_;
8661#ifdef DEBUG
8662 inline void set_valid() { valid_ = true; }
8663 bool valid_;
8664#else
8665 inline void set_valid() { }
8666#endif
8667};
8668
8669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008670// The Name abstract class captures anything that can be used as a property
8671// name, i.e., strings and symbols. All names store a hash value.
8672class Name: public HeapObject {
8673 public:
8674 // Get and set the hash field of the name.
8675 inline uint32_t hash_field();
8676 inline void set_hash_field(uint32_t value);
8677
8678 // Tells whether the hash code has been computed.
8679 inline bool HasHashCode();
8680
8681 // Returns a hash value used for the property table
8682 inline uint32_t Hash();
8683
8684 // Equality operations.
8685 inline bool Equals(Name* other);
8686 inline static bool Equals(Handle<Name> one, Handle<Name> two);
8687
8688 // Conversion.
8689 inline bool AsArrayIndex(uint32_t* index);
8690
8691 // Whether name can only name own properties.
8692 inline bool IsOwn();
8693
8694 DECLARE_CAST(Name)
8695
8696 DECLARE_PRINTER(Name)
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008697#if TRACE_MAPS
8698 void NameShortPrint();
8699 int NameShortPrint(Vector<char> str);
8700#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008701
8702 // Layout description.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008703 static const int kHashFieldSlot = HeapObject::kHeaderSize;
8704#if V8_TARGET_LITTLE_ENDIAN || !V8_HOST_ARCH_64_BIT
8705 static const int kHashFieldOffset = kHashFieldSlot;
8706#else
8707 static const int kHashFieldOffset = kHashFieldSlot + kIntSize;
8708#endif
8709 static const int kSize = kHashFieldSlot + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008710
8711 // Mask constant for checking if a name has a computed hash code
8712 // and if it is a string that is an array index. The least significant bit
8713 // indicates whether a hash code has been computed. If the hash code has
8714 // been computed the 2nd bit tells whether the string can be used as an
8715 // array index.
8716 static const int kHashNotComputedMask = 1;
8717 static const int kIsNotArrayIndexMask = 1 << 1;
8718 static const int kNofHashBitFields = 2;
8719
8720 // Shift constant retrieving hash code from hash field.
8721 static const int kHashShift = kNofHashBitFields;
8722
8723 // Only these bits are relevant in the hash, since the top two are shifted
8724 // out.
8725 static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift;
8726
8727 // Array index strings this short can keep their index in the hash field.
8728 static const int kMaxCachedArrayIndexLength = 7;
8729
8730 // For strings which are array indexes the hash value has the string length
8731 // mixed into the hash, mainly to avoid a hash value of zero which would be
8732 // the case for the string '0'. 24 bits are used for the array index value.
8733 static const int kArrayIndexValueBits = 24;
8734 static const int kArrayIndexLengthBits =
8735 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
8736
8737 STATIC_ASSERT((kArrayIndexLengthBits > 0));
8738
8739 class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields,
8740 kArrayIndexValueBits> {}; // NOLINT
8741 class ArrayIndexLengthBits : public BitField<unsigned int,
8742 kNofHashBitFields + kArrayIndexValueBits,
8743 kArrayIndexLengthBits> {}; // NOLINT
8744
8745 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
8746 // could use a mask to test if the length of string is less than or equal to
8747 // kMaxCachedArrayIndexLength.
8748 STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
8749
8750 static const unsigned int kContainsCachedArrayIndexMask =
8751 (~static_cast<unsigned>(kMaxCachedArrayIndexLength)
8752 << ArrayIndexLengthBits::kShift) |
8753 kIsNotArrayIndexMask;
8754
8755 // Value of empty hash field indicating that the hash is not computed.
8756 static const int kEmptyHashField =
8757 kIsNotArrayIndexMask | kHashNotComputedMask;
8758
8759 protected:
8760 static inline bool IsHashFieldComputed(uint32_t field);
8761
8762 private:
8763 DISALLOW_IMPLICIT_CONSTRUCTORS(Name);
8764};
8765
8766
8767// ES6 symbols.
8768class Symbol: public Name {
8769 public:
8770 // [name]: the print name of a symbol, or undefined if none.
8771 DECL_ACCESSORS(name, Object)
8772
8773 DECL_ACCESSORS(flags, Smi)
8774
8775 // [is_private]: whether this is a private symbol.
8776 DECL_BOOLEAN_ACCESSORS(is_private)
8777
8778 // [is_own]: whether this is an own symbol, that is, only used to designate
8779 // own properties of objects.
8780 DECL_BOOLEAN_ACCESSORS(is_own)
8781
8782 DECLARE_CAST(Symbol)
8783
8784 // Dispatched behavior.
8785 DECLARE_PRINTER(Symbol)
8786 DECLARE_VERIFIER(Symbol)
8787
8788 // Layout description.
8789 static const int kNameOffset = Name::kSize;
8790 static const int kFlagsOffset = kNameOffset + kPointerSize;
8791 static const int kSize = kFlagsOffset + kPointerSize;
8792
8793 typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor;
8794
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008795 void SymbolShortPrint(std::ostream& os);
8796
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008797 private:
8798 static const int kPrivateBit = 0;
8799 static const int kOwnBit = 1;
8800
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008801 const char* PrivateSymbolToName() const;
8802
8803#if TRACE_MAPS
8804 friend class Name; // For PrivateSymbolToName.
8805#endif
8806
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008807 DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol);
8808};
8809
8810
8811class ConsString;
8812
Steve Blocka7e24c12009-10-30 11:49:00 +00008813// The String abstract class captures JavaScript string values:
8814//
8815// Ecma-262:
8816// 4.3.16 String Value
8817// A string value is a member of the type String and is a finite
8818// ordered sequence of zero or more 16-bit unsigned integer values.
8819//
8820// All string values have a length field.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008821class String: public Name {
Steve Blocka7e24c12009-10-30 11:49:00 +00008822 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008823 enum Encoding { ONE_BYTE_ENCODING, TWO_BYTE_ENCODING };
8824
8825 // Array index strings this short can keep their index in the hash field.
8826 static const int kMaxCachedArrayIndexLength = 7;
8827
8828 // For strings which are array indexes the hash value has the string length
8829 // mixed into the hash, mainly to avoid a hash value of zero which would be
8830 // the case for the string '0'. 24 bits are used for the array index value.
8831 static const int kArrayIndexValueBits = 24;
8832 static const int kArrayIndexLengthBits =
8833 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields;
8834
8835 STATIC_ASSERT((kArrayIndexLengthBits > 0));
8836
8837 class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields,
8838 kArrayIndexValueBits> {}; // NOLINT
8839 class ArrayIndexLengthBits : public BitField<unsigned int,
8840 kNofHashBitFields + kArrayIndexValueBits,
8841 kArrayIndexLengthBits> {}; // NOLINT
8842
8843 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we
8844 // could use a mask to test if the length of string is less than or equal to
8845 // kMaxCachedArrayIndexLength.
8846 STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1));
8847
8848 static const unsigned int kContainsCachedArrayIndexMask =
8849 (~static_cast<unsigned>(kMaxCachedArrayIndexLength)
8850 << ArrayIndexLengthBits::kShift) |
8851 kIsNotArrayIndexMask;
8852
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008853 // Representation of the flat content of a String.
8854 // A non-flat string doesn't have flat content.
8855 // A flat string has content that's encoded as a sequence of either
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008856 // one-byte chars or two-byte UC16.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008857 // Returned by String::GetFlatContent().
8858 class FlatContent {
8859 public:
8860 // Returns true if the string is flat and this structure contains content.
8861 bool IsFlat() { return state_ != NON_FLAT; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008862 // Returns true if the structure contains one-byte content.
8863 bool IsOneByte() { return state_ == ONE_BYTE; }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008864 // Returns true if the structure contains two-byte content.
8865 bool IsTwoByte() { return state_ == TWO_BYTE; }
8866
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008867 // Return the one byte content of the string. Only use if IsOneByte()
8868 // returns true.
8869 Vector<const uint8_t> ToOneByteVector() {
8870 DCHECK_EQ(ONE_BYTE, state_);
8871 return Vector<const uint8_t>(onebyte_start, length_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008872 }
8873 // Return the two-byte content of the string. Only use if IsTwoByte()
8874 // returns true.
8875 Vector<const uc16> ToUC16Vector() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008876 DCHECK_EQ(TWO_BYTE, state_);
8877 return Vector<const uc16>(twobyte_start, length_);
8878 }
8879
8880 uc16 Get(int i) {
8881 DCHECK(i < length_);
8882 DCHECK(state_ != NON_FLAT);
8883 if (state_ == ONE_BYTE) return onebyte_start[i];
8884 return twobyte_start[i];
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008885 }
8886
8887 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008888 enum State { NON_FLAT, ONE_BYTE, TWO_BYTE };
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008889
8890 // Constructors only used by String::GetFlatContent().
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008891 explicit FlatContent(const uint8_t* start, int length)
8892 : onebyte_start(start), length_(length), state_(ONE_BYTE) {}
8893 explicit FlatContent(const uc16* start, int length)
8894 : twobyte_start(start), length_(length), state_(TWO_BYTE) { }
8895 FlatContent() : onebyte_start(NULL), length_(0), state_(NON_FLAT) { }
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008896
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008897 union {
8898 const uint8_t* onebyte_start;
8899 const uc16* twobyte_start;
8900 };
8901 int length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008902 State state_;
8903
8904 friend class String;
8905 };
8906
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008907 template <typename Char>
8908 INLINE(Vector<const Char> GetCharVector());
8909
Steve Blocka7e24c12009-10-30 11:49:00 +00008910 // Get and set the length of the string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008911 inline int length() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00008912 inline void set_length(int value);
8913
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008914 // Get and set the length of the string using acquire loads and release
8915 // stores.
8916 inline int synchronized_length() const;
8917 inline void synchronized_set_length(int value);
Steve Blocka7e24c12009-10-30 11:49:00 +00008918
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008919 // Returns whether this string has only one-byte chars, i.e. all of them can
8920 // be one-byte encoded. This might be the case even if the string is
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008921 // two-byte. Such strings may appear when the embedder prefers
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008922 // two-byte external representations even for one-byte data.
8923 inline bool IsOneByteRepresentation() const;
8924 inline bool IsTwoByteRepresentation() const;
Steve Blocka7e24c12009-10-30 11:49:00 +00008925
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008926 // Cons and slices have an encoding flag that may not represent the actual
8927 // encoding of the underlying string. This is taken into account here.
8928 // Requires: this->IsFlat()
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008929 inline bool IsOneByteRepresentationUnderneath();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008930 inline bool IsTwoByteRepresentationUnderneath();
8931
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01008932 // NOTE: this should be considered only a hint. False negatives are
8933 // possible.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008934 inline bool HasOnlyOneByteChars();
Steve Block6ded16b2010-05-10 14:33:55 +01008935
Steve Blocka7e24c12009-10-30 11:49:00 +00008936 // Get and set individual two byte chars in the string.
8937 inline void Set(int index, uint16_t value);
8938 // Get individual two byte char in the string. Repeated calls
8939 // to this method are not efficient unless the string is flat.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008940 INLINE(uint16_t Get(int index));
Steve Blocka7e24c12009-10-30 11:49:00 +00008941
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008942 // Flattens the string. Checks first inline to see if it is
Leon Clarkef7060e22010-06-03 12:02:55 +01008943 // necessary. Does nothing if the string is not a cons string.
8944 // Flattening allocates a sequential string with the same data as
8945 // the given string and mutates the cons string to a degenerate
8946 // form, where the first component is the new sequential string and
8947 // the second component is the empty string. If allocation fails,
8948 // this function returns a failure. If flattening succeeds, this
8949 // function returns the sequential string that is now the first
8950 // component of the cons string.
8951 //
8952 // Degenerate cons strings are handled specially by the garbage
8953 // collector (see IsShortcutCandidate).
Steve Blocka7e24c12009-10-30 11:49:00 +00008954
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008955 static inline Handle<String> Flatten(Handle<String> string,
8956 PretenureFlag pretenure = NOT_TENURED);
Leon Clarkef7060e22010-06-03 12:02:55 +01008957
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008958 // Tries to return the content of a flat string as a structure holding either
8959 // a flat vector of char or of uc16.
8960 // If the string isn't flat, and therefore doesn't have flat content, the
8961 // returned structure will report so, and can't provide a vector of either
8962 // kind.
8963 FlatContent GetFlatContent();
8964
8965 // Returns the parent of a sliced string or first part of a flat cons string.
8966 // Requires: StringShape(this).IsIndirect() && this->IsFlat()
8967 inline String* GetUnderlying();
Steve Blocka7e24c12009-10-30 11:49:00 +00008968
8969 // Mark the string as an undetectable object. It only applies to
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008970 // one-byte and two-byte string types.
Steve Blocka7e24c12009-10-30 11:49:00 +00008971 bool MarkAsUndetectable();
8972
Steve Blocka7e24c12009-10-30 11:49:00 +00008973 // String equality operations.
8974 inline bool Equals(String* other);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008975 inline static bool Equals(Handle<String> one, Handle<String> two);
8976 bool IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false);
8977 bool IsOneByteEqualTo(Vector<const uint8_t> str);
Steve Block9fac8402011-05-12 15:51:54 +01008978 bool IsTwoByteEqualTo(Vector<const uc16> str);
Steve Blocka7e24c12009-10-30 11:49:00 +00008979
8980 // Return a UTF8 representation of the string. The string is null
8981 // terminated but may optionally contain nulls. Length is returned
8982 // in length_output if length_output is not a null pointer The string
8983 // should be nearly flat, otherwise the performance of this method may
8984 // be very slow (quadratic in the length). Setting robustness_flag to
8985 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
8986 // handles unexpected data without causing assert failures and it does not
8987 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00008988 SmartArrayPointer<char> ToCString(AllowNullsFlag allow_nulls,
8989 RobustnessFlag robustness_flag,
8990 int offset,
8991 int length,
8992 int* length_output = 0);
8993 SmartArrayPointer<char> ToCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00008994 AllowNullsFlag allow_nulls = DISALLOW_NULLS,
8995 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL,
8996 int* length_output = 0);
8997
Steve Blocka7e24c12009-10-30 11:49:00 +00008998 // Return a 16 bit Unicode representation of the string.
8999 // The string should be nearly flat, otherwise the performance of
9000 // of this method may be very bad. Setting robustness_flag to
9001 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it
9002 // handles unexpected data without causing assert failures and it does not
9003 // do any heap allocations. This is useful when printing stack traces.
Ben Murdoch589d6972011-11-30 16:04:58 +00009004 SmartArrayPointer<uc16> ToWideCString(
Steve Blocka7e24c12009-10-30 11:49:00 +00009005 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL);
9006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009007 bool ComputeArrayIndex(uint32_t* index);
Steve Blocka7e24c12009-10-30 11:49:00 +00009008
9009 // Externalization.
9010 bool MakeExternal(v8::String::ExternalStringResource* resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009011 bool MakeExternal(v8::String::ExternalOneByteStringResource* resource);
Steve Blocka7e24c12009-10-30 11:49:00 +00009012
9013 // Conversion.
9014 inline bool AsArrayIndex(uint32_t* index);
9015
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009016 DECLARE_CAST(String)
Steve Blocka7e24c12009-10-30 11:49:00 +00009017
9018 void PrintOn(FILE* out);
9019
9020 // For use during stack traces. Performs rudimentary sanity check.
9021 bool LooksValid();
9022
9023 // Dispatched behavior.
9024 void StringShortPrint(StringStream* accumulator);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009025 void PrintUC16(std::ostream& os, int start = 0, int end = -1); // NOLINT
9026#if defined(DEBUG) || defined(OBJECT_PRINT)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009027 char* ToAsciiArray();
Ben Murdochb0fe1622011-05-05 13:52:32 +01009028#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009029 DECLARE_PRINTER(String)
9030 DECLARE_VERIFIER(String)
9031
Steve Blocka7e24c12009-10-30 11:49:00 +00009032 inline bool IsFlat();
9033
9034 // Layout description.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009035 static const int kLengthOffset = Name::kSize;
9036 static const int kSize = kLengthOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00009037
Steve Blockd0582a62009-12-15 09:54:21 +00009038 // Maximum number of characters to consider when trying to convert a string
9039 // value into an array index.
Steve Blocka7e24c12009-10-30 11:49:00 +00009040 static const int kMaxArrayIndexSize = 10;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009041 STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits));
Steve Blocka7e24c12009-10-30 11:49:00 +00009042
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009043 // Max char codes.
9044 static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
9045 static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009046 static const int kMaxUtf16CodeUnit = 0xffff;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009047 static const uint32_t kMaxUtf16CodeUnitU = kMaxUtf16CodeUnit;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01009048
9049 // Value of hash field containing computed hash equal to zero.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009050 static const int kEmptyStringHash = kIsNotArrayIndexMask;
Steve Blockd0582a62009-12-15 09:54:21 +00009051
9052 // Maximal string length.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009053 static const int kMaxLength = (1 << 28) - 16;
Steve Blockd0582a62009-12-15 09:54:21 +00009054
9055 // Max length for computing hash. For strings longer than this limit the
9056 // string length is used as the hash value.
9057 static const int kMaxHashCalcLength = 16383;
Steve Blocka7e24c12009-10-30 11:49:00 +00009058
9059 // Limit for truncation in short printing.
9060 static const int kMaxShortPrintLength = 1024;
9061
9062 // Support for regular expressions.
Steve Blocka7e24c12009-10-30 11:49:00 +00009063 const uc16* GetTwoByteData(unsigned start);
9064
Steve Blocka7e24c12009-10-30 11:49:00 +00009065 // Helper function for flattening strings.
9066 template <typename sinkchar>
9067 static void WriteToFlat(String* source,
9068 sinkchar* sink,
9069 int from,
9070 int to);
9071
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009072 // The return value may point to the first aligned word containing the first
9073 // non-one-byte character, rather than directly to the non-one-byte character.
9074 // If the return value is >= the passed length, the entire string was
9075 // one-byte.
9076 static inline int NonAsciiStart(const char* chars, int length) {
9077 const char* start = chars;
Steve Block9fac8402011-05-12 15:51:54 +01009078 const char* limit = chars + length;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009079
9080 if (length >= kIntptrSize) {
9081 // Check unaligned bytes.
9082 while (!IsAligned(reinterpret_cast<intptr_t>(chars), sizeof(uintptr_t))) {
9083 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) {
9084 return static_cast<int>(chars - start);
9085 }
9086 ++chars;
Steve Block9fac8402011-05-12 15:51:54 +01009087 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009088 // Check aligned words.
9089 DCHECK(unibrow::Utf8::kMaxOneByteChar == 0x7F);
9090 const uintptr_t non_one_byte_mask = kUintptrAllBitsSet / 0xFF * 0x80;
9091 while (chars + sizeof(uintptr_t) <= limit) {
9092 if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) {
9093 return static_cast<int>(chars - start);
9094 }
9095 chars += sizeof(uintptr_t);
9096 }
Steve Block9fac8402011-05-12 15:51:54 +01009097 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009098 // Check remaining unaligned bytes.
Steve Block9fac8402011-05-12 15:51:54 +01009099 while (chars < limit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009100 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) {
9101 return static_cast<int>(chars - start);
9102 }
Steve Block9fac8402011-05-12 15:51:54 +01009103 ++chars;
9104 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009105
9106 return static_cast<int>(chars - start);
Steve Block9fac8402011-05-12 15:51:54 +01009107 }
9108
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009109 static inline bool IsAscii(const char* chars, int length) {
9110 return NonAsciiStart(chars, length) >= length;
9111 }
9112
9113 static inline bool IsAscii(const uint8_t* chars, int length) {
9114 return
9115 NonAsciiStart(reinterpret_cast<const char*>(chars), length) >= length;
9116 }
9117
9118 static inline int NonOneByteStart(const uc16* chars, int length) {
Steve Block9fac8402011-05-12 15:51:54 +01009119 const uc16* limit = chars + length;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009120 const uc16* start = chars;
Steve Block9fac8402011-05-12 15:51:54 +01009121 while (chars < limit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009122 if (*chars > kMaxOneByteCharCodeU) return static_cast<int>(chars - start);
Steve Block9fac8402011-05-12 15:51:54 +01009123 ++chars;
9124 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009125 return static_cast<int>(chars - start);
Steve Block9fac8402011-05-12 15:51:54 +01009126 }
9127
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009128 static inline bool IsOneByte(const uc16* chars, int length) {
9129 return NonOneByteStart(chars, length) >= length;
9130 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009131
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009132 template<class Visitor>
9133 static inline ConsString* VisitFlat(Visitor* visitor,
9134 String* string,
9135 int offset = 0);
9136
9137 static Handle<FixedArray> CalculateLineEnds(Handle<String> string,
9138 bool include_ending_line);
9139
9140 // Use the hash field to forward to the canonical internalized string
9141 // when deserializing an internalized string.
9142 inline void SetForwardedInternalizedString(String* string);
9143 inline String* GetForwardedInternalizedString();
Steve Blocka7e24c12009-10-30 11:49:00 +00009144
9145 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009146 friend class Name;
9147 friend class StringTableInsertionKey;
Leon Clarkef7060e22010-06-03 12:02:55 +01009148
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009149 static Handle<String> SlowFlatten(Handle<ConsString> cons,
9150 PretenureFlag tenure);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01009151
Steve Blocka7e24c12009-10-30 11:49:00 +00009152 // Slow case of String::Equals. This implementation works on any strings
9153 // but it is most efficient on strings that are almost flat.
9154 bool SlowEquals(String* other);
9155
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009156 static bool SlowEquals(Handle<String> one, Handle<String> two);
9157
Steve Blocka7e24c12009-10-30 11:49:00 +00009158 // Slow case of AsArrayIndex.
9159 bool SlowAsArrayIndex(uint32_t* index);
9160
9161 // Compute and set the hash code.
9162 uint32_t ComputeAndSetHash();
9163
9164 DISALLOW_IMPLICIT_CONSTRUCTORS(String);
9165};
9166
9167
9168// The SeqString abstract class captures sequential string values.
9169class SeqString: public String {
9170 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009171 DECLARE_CAST(SeqString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009172
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009173 // Layout description.
9174 static const int kHeaderSize = String::kSize;
9175
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009176 // Truncate the string in-place if possible and return the result.
9177 // In case of new_length == 0, the empty string is returned without
9178 // truncating the original string.
9179 MUST_USE_RESULT static Handle<String> Truncate(Handle<SeqString> string,
9180 int new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +00009181 private:
9182 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
9183};
9184
9185
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009186// The OneByteString class captures sequential one-byte string objects.
9187// Each character in the OneByteString is an one-byte character.
9188class SeqOneByteString: public SeqString {
Steve Blocka7e24c12009-10-30 11:49:00 +00009189 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009190 static const bool kHasOneByteEncoding = true;
Leon Clarkeac952652010-07-15 11:15:24 +01009191
Steve Blocka7e24c12009-10-30 11:49:00 +00009192 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009193 inline uint16_t SeqOneByteStringGet(int index);
9194 inline void SeqOneByteStringSet(int index, uint16_t value);
Steve Blocka7e24c12009-10-30 11:49:00 +00009195
9196 // Get the address of the characters in this string.
9197 inline Address GetCharsAddress();
9198
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009199 inline uint8_t* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00009200
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009201 DECLARE_CAST(SeqOneByteString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009202
9203 // Garbage collection support. This method is called by the
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009204 // garbage collector to compute the actual size of an OneByteString
Steve Blocka7e24c12009-10-30 11:49:00 +00009205 // instance.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009206 inline int SeqOneByteStringSize(InstanceType instance_type);
Steve Blocka7e24c12009-10-30 11:49:00 +00009207
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009208 // Computes the size for an OneByteString instance of a given length.
Steve Blocka7e24c12009-10-30 11:49:00 +00009209 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01009210 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00009211 }
9212
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009213 // Maximal memory usage for a single sequential one-byte string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009214 static const int kMaxSize = 512 * MB - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009215 STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength);
Steve Blocka7e24c12009-10-30 11:49:00 +00009216
9217 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009218 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqOneByteString);
Steve Blocka7e24c12009-10-30 11:49:00 +00009219};
9220
9221
9222// The TwoByteString class captures sequential unicode string objects.
9223// Each character in the TwoByteString is a two-byte uint16_t.
9224class SeqTwoByteString: public SeqString {
9225 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009226 static const bool kHasOneByteEncoding = false;
Leon Clarkeac952652010-07-15 11:15:24 +01009227
Steve Blocka7e24c12009-10-30 11:49:00 +00009228 // Dispatched behavior.
9229 inline uint16_t SeqTwoByteStringGet(int index);
9230 inline void SeqTwoByteStringSet(int index, uint16_t value);
9231
9232 // Get the address of the characters in this string.
9233 inline Address GetCharsAddress();
9234
9235 inline uc16* GetChars();
9236
9237 // For regexp code.
9238 const uint16_t* SeqTwoByteStringGetData(unsigned start);
9239
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009240 DECLARE_CAST(SeqTwoByteString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009241
9242 // Garbage collection support. This method is called by the
9243 // garbage collector to compute the actual size of a TwoByteString
9244 // instance.
9245 inline int SeqTwoByteStringSize(InstanceType instance_type);
9246
9247 // Computes the size for a TwoByteString instance of a given length.
9248 static int SizeFor(int length) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01009249 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
Steve Blocka7e24c12009-10-30 11:49:00 +00009250 }
9251
Leon Clarkee46be812010-01-19 14:06:41 +00009252 // Maximal memory usage for a single sequential two-byte string.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009253 static const int kMaxSize = 512 * MB - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009254 STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize)/sizeof(uint16_t)) >=
9255 String::kMaxLength);
Steve Blocka7e24c12009-10-30 11:49:00 +00009256
9257 private:
9258 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString);
9259};
9260
9261
9262// The ConsString class describes string values built by using the
9263// addition operator on strings. A ConsString is a pair where the
9264// first and second components are pointers to other string values.
9265// One or both components of a ConsString can be pointers to other
9266// ConsStrings, creating a binary tree of ConsStrings where the leaves
9267// are non-ConsString string values. The string value represented by
9268// a ConsString can be obtained by concatenating the leaf string
9269// values in a left-to-right depth-first traversal of the tree.
9270class ConsString: public String {
9271 public:
9272 // First string of the cons cell.
9273 inline String* first();
9274 // Doesn't check that the result is a string, even in debug mode. This is
9275 // useful during GC where the mark bits confuse the checks.
9276 inline Object* unchecked_first();
9277 inline void set_first(String* first,
9278 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
9279
9280 // Second string of the cons cell.
9281 inline String* second();
9282 // Doesn't check that the result is a string, even in debug mode. This is
9283 // useful during GC where the mark bits confuse the checks.
9284 inline Object* unchecked_second();
9285 inline void set_second(String* second,
9286 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
9287
9288 // Dispatched behavior.
9289 uint16_t ConsStringGet(int index);
9290
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009291 DECLARE_CAST(ConsString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009292
Steve Blocka7e24c12009-10-30 11:49:00 +00009293 // Layout description.
9294 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize);
9295 static const int kSecondOffset = kFirstOffset + kPointerSize;
9296 static const int kSize = kSecondOffset + kPointerSize;
9297
Steve Blocka7e24c12009-10-30 11:49:00 +00009298 // Minimum length for a cons string.
9299 static const int kMinLength = 13;
9300
Iain Merrick75681382010-08-19 15:07:18 +01009301 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize>
9302 BodyDescriptor;
9303
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009304 DECLARE_VERIFIER(ConsString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009305
Steve Blocka7e24c12009-10-30 11:49:00 +00009306 private:
9307 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString);
9308};
9309
9310
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009311// The Sliced String class describes strings that are substrings of another
9312// sequential string. The motivation is to save time and memory when creating
9313// a substring. A Sliced String is described as a pointer to the parent,
9314// the offset from the start of the parent string and the length. Using
9315// a Sliced String therefore requires unpacking of the parent string and
9316// adding the offset to the start address. A substring of a Sliced String
9317// are not nested since the double indirection is simplified when creating
9318// such a substring.
9319// Currently missing features are:
9320// - handling externalized parent strings
9321// - external strings as parent
9322// - truncating sliced string to enable otherwise unneeded parent to be GC'ed.
9323class SlicedString: public String {
9324 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009325 inline String* parent();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009326 inline void set_parent(String* parent,
9327 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
9328 inline int offset() const;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009329 inline void set_offset(int offset);
9330
9331 // Dispatched behavior.
9332 uint16_t SlicedStringGet(int index);
9333
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009334 DECLARE_CAST(SlicedString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009335
9336 // Layout description.
9337 static const int kParentOffset = POINTER_SIZE_ALIGN(String::kSize);
9338 static const int kOffsetOffset = kParentOffset + kPointerSize;
9339 static const int kSize = kOffsetOffset + kPointerSize;
9340
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009341 // Minimum length for a sliced string.
9342 static const int kMinLength = 13;
9343
9344 typedef FixedBodyDescriptor<kParentOffset,
9345 kOffsetOffset + kPointerSize, kSize>
9346 BodyDescriptor;
9347
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009348 DECLARE_VERIFIER(SlicedString)
Ben Murdoch69a99ed2011-11-30 16:03:39 +00009349
9350 private:
9351 DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString);
9352};
9353
9354
Steve Blocka7e24c12009-10-30 11:49:00 +00009355// The ExternalString class describes string values that are backed by
9356// a string resource that lies outside the V8 heap. ExternalStrings
9357// consist of the length field common to all strings, a pointer to the
9358// external resource. It is important to ensure (externally) that the
9359// resource is not deallocated while the ExternalString is live in the
9360// V8 heap.
9361//
9362// The API expects that all ExternalStrings are created through the
9363// API. Therefore, ExternalStrings should not be used internally.
9364class ExternalString: public String {
9365 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009366 DECLARE_CAST(ExternalString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009367
9368 // Layout description.
9369 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009370 static const int kShortSize = kResourceOffset + kPointerSize;
9371 static const int kResourceDataOffset = kResourceOffset + kPointerSize;
9372 static const int kSize = kResourceDataOffset + kPointerSize;
9373
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009374 static const int kMaxShortLength =
9375 (kShortSize - SeqString::kHeaderSize) / kCharSize;
9376
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009377 // Return whether external string is short (data pointer is not cached).
9378 inline bool is_short();
Steve Blocka7e24c12009-10-30 11:49:00 +00009379
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009380 STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +00009381
9382 private:
9383 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString);
9384};
9385
9386
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009387// The ExternalOneByteString class is an external string backed by an
9388// one-byte string.
9389class ExternalOneByteString : public ExternalString {
Steve Blocka7e24c12009-10-30 11:49:00 +00009390 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009391 static const bool kHasOneByteEncoding = true;
Leon Clarkeac952652010-07-15 11:15:24 +01009392
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009393 typedef v8::String::ExternalOneByteStringResource Resource;
Steve Blocka7e24c12009-10-30 11:49:00 +00009394
9395 // The underlying resource.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009396 inline const Resource* resource();
9397 inline void set_resource(const Resource* buffer);
9398
9399 // Update the pointer cache to the external character array.
9400 // The cached pointer is always valid, as the external character array does =
9401 // not move during lifetime. Deserialization is the only exception, after
9402 // which the pointer cache has to be refreshed.
9403 inline void update_data_cache();
9404
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009405 inline const uint8_t* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00009406
9407 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009408 inline uint16_t ExternalOneByteStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00009409
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009410 DECLARE_CAST(ExternalOneByteString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009411
Steve Blockd0582a62009-12-15 09:54:21 +00009412 // Garbage collection support.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009413 inline void ExternalOneByteStringIterateBody(ObjectVisitor* v);
Iain Merrick75681382010-08-19 15:07:18 +01009414
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009415 template <typename StaticVisitor>
9416 inline void ExternalOneByteStringIterateBody();
Steve Blocka7e24c12009-10-30 11:49:00 +00009417
Steve Blocka7e24c12009-10-30 11:49:00 +00009418 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009419 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString);
Steve Blocka7e24c12009-10-30 11:49:00 +00009420};
9421
9422
9423// The ExternalTwoByteString class is an external string backed by a UTF-16
9424// encoded string.
9425class ExternalTwoByteString: public ExternalString {
9426 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009427 static const bool kHasOneByteEncoding = false;
Leon Clarkeac952652010-07-15 11:15:24 +01009428
Steve Blocka7e24c12009-10-30 11:49:00 +00009429 typedef v8::String::ExternalStringResource Resource;
9430
9431 // The underlying string resource.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009432 inline const Resource* resource();
9433 inline void set_resource(const Resource* buffer);
9434
9435 // Update the pointer cache to the external character array.
9436 // The cached pointer is always valid, as the external character array does =
9437 // not move during lifetime. Deserialization is the only exception, after
9438 // which the pointer cache has to be refreshed.
9439 inline void update_data_cache();
9440
9441 inline const uint16_t* GetChars();
Steve Blocka7e24c12009-10-30 11:49:00 +00009442
9443 // Dispatched behavior.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009444 inline uint16_t ExternalTwoByteStringGet(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00009445
9446 // For regexp code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009447 inline const uint16_t* ExternalTwoByteStringGetData(unsigned start);
Steve Blocka7e24c12009-10-30 11:49:00 +00009448
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009449 DECLARE_CAST(ExternalTwoByteString)
Steve Blocka7e24c12009-10-30 11:49:00 +00009450
Steve Blockd0582a62009-12-15 09:54:21 +00009451 // Garbage collection support.
Iain Merrick75681382010-08-19 15:07:18 +01009452 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v);
9453
9454 template<typename StaticVisitor>
9455 inline void ExternalTwoByteStringIterateBody();
9456
Steve Blocka7e24c12009-10-30 11:49:00 +00009457 private:
9458 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString);
9459};
9460
9461
9462// Utility superclass for stack-allocated objects that must be updated
9463// on gc. It provides two ways for the gc to update instances, either
9464// iterating or updating after gc.
9465class Relocatable BASE_EMBEDDED {
9466 public:
Steve Block44f0eee2011-05-26 01:26:41 +01009467 explicit inline Relocatable(Isolate* isolate);
9468 inline virtual ~Relocatable();
Steve Blocka7e24c12009-10-30 11:49:00 +00009469 virtual void IterateInstance(ObjectVisitor* v) { }
9470 virtual void PostGarbageCollection() { }
9471
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009472 static void PostGarbageCollectionProcessing(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009473 static int ArchiveSpacePerThread();
Ben Murdoch257744e2011-11-30 15:57:28 +00009474 static char* ArchiveState(Isolate* isolate, char* to);
9475 static char* RestoreState(Isolate* isolate, char* from);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009476 static void Iterate(Isolate* isolate, ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +00009477 static void Iterate(ObjectVisitor* v, Relocatable* top);
9478 static char* Iterate(ObjectVisitor* v, char* t);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009479
Steve Blocka7e24c12009-10-30 11:49:00 +00009480 private:
Steve Block44f0eee2011-05-26 01:26:41 +01009481 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +00009482 Relocatable* prev_;
9483};
9484
9485
9486// A flat string reader provides random access to the contents of a
9487// string independent of the character width of the string. The handle
9488// must be valid as long as the reader is being used.
9489class FlatStringReader : public Relocatable {
9490 public:
Steve Block44f0eee2011-05-26 01:26:41 +01009491 FlatStringReader(Isolate* isolate, Handle<String> str);
9492 FlatStringReader(Isolate* isolate, Vector<const char> input);
Steve Blocka7e24c12009-10-30 11:49:00 +00009493 void PostGarbageCollection();
9494 inline uc32 Get(int index);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009495 template <typename Char>
9496 inline Char Get(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00009497 int length() { return length_; }
9498 private:
9499 String** str_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009500 bool is_one_byte_;
Steve Blocka7e24c12009-10-30 11:49:00 +00009501 int length_;
9502 const void* start_;
9503};
9504
9505
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009506// This maintains an off-stack representation of the stack frames required
9507// to traverse a ConsString, allowing an entirely iterative and restartable
9508// traversal of the entire string
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009509class ConsStringIterator {
Steve Blocka7e24c12009-10-30 11:49:00 +00009510 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009511 inline ConsStringIterator() {}
9512 inline explicit ConsStringIterator(ConsString* cons_string, int offset = 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009513 Reset(cons_string, offset);
9514 }
9515 inline void Reset(ConsString* cons_string, int offset = 0) {
9516 depth_ = 0;
9517 // Next will always return NULL.
9518 if (cons_string == NULL) return;
9519 Initialize(cons_string, offset);
9520 }
9521 // Returns NULL when complete.
9522 inline String* Next(int* offset_out) {
9523 *offset_out = 0;
9524 if (depth_ == 0) return NULL;
9525 return Continue(offset_out);
9526 }
9527
9528 private:
9529 static const int kStackSize = 32;
9530 // Use a mask instead of doing modulo operations for stack wrapping.
9531 static const int kDepthMask = kStackSize-1;
9532 STATIC_ASSERT(IS_POWER_OF_TWO(kStackSize));
9533 static inline int OffsetForDepth(int depth);
9534
9535 inline void PushLeft(ConsString* string);
9536 inline void PushRight(ConsString* string);
9537 inline void AdjustMaximumDepth();
9538 inline void Pop();
9539 inline bool StackBlown() { return maximum_depth_ - depth_ == kStackSize; }
9540 void Initialize(ConsString* cons_string, int offset);
9541 String* Continue(int* offset_out);
9542 String* NextLeaf(bool* blew_stack);
9543 String* Search(int* offset_out);
9544
9545 // Stack must always contain only frames for which right traversal
9546 // has not yet been performed.
9547 ConsString* frames_[kStackSize];
9548 ConsString* root_;
9549 int depth_;
9550 int maximum_depth_;
9551 int consumed_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009552 DISALLOW_COPY_AND_ASSIGN(ConsStringIterator);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009553};
9554
9555
9556class StringCharacterStream {
9557 public:
9558 inline StringCharacterStream(String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009559 int offset = 0);
9560 inline uint16_t GetNext();
9561 inline bool HasMore();
9562 inline void Reset(String* string, int offset = 0);
9563 inline void VisitOneByteString(const uint8_t* chars, int length);
9564 inline void VisitTwoByteString(const uint16_t* chars, int length);
9565
9566 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009567 ConsStringIterator iter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009568 bool is_one_byte_;
9569 union {
9570 const uint8_t* buffer8_;
9571 const uint16_t* buffer16_;
9572 };
9573 const uint8_t* end_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009574 DISALLOW_COPY_AND_ASSIGN(StringCharacterStream);
Steve Blocka7e24c12009-10-30 11:49:00 +00009575};
9576
9577
9578template <typename T>
9579class VectorIterator {
9580 public:
9581 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { }
9582 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { }
9583 T GetNext() { return data_[index_++]; }
9584 bool has_more() { return index_ < data_.length(); }
9585 private:
9586 Vector<const T> data_;
9587 int index_;
9588};
9589
9590
9591// The Oddball describes objects null, undefined, true, and false.
9592class Oddball: public HeapObject {
9593 public:
9594 // [to_string]: Cached to_string computed at startup.
9595 DECL_ACCESSORS(to_string, String)
9596
9597 // [to_number]: Cached to_number computed at startup.
9598 DECL_ACCESSORS(to_number, Object)
9599
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009600 inline byte kind() const;
Steve Block44f0eee2011-05-26 01:26:41 +01009601 inline void set_kind(byte kind);
9602
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009603 DECLARE_CAST(Oddball)
Steve Blocka7e24c12009-10-30 11:49:00 +00009604
9605 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009606 DECLARE_VERIFIER(Oddball)
Steve Blocka7e24c12009-10-30 11:49:00 +00009607
9608 // Initialize the fields.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009609 static void Initialize(Isolate* isolate,
9610 Handle<Oddball> oddball,
9611 const char* to_string,
9612 Handle<Object> to_number,
9613 byte kind);
Steve Blocka7e24c12009-10-30 11:49:00 +00009614
9615 // Layout description.
9616 static const int kToStringOffset = HeapObject::kHeaderSize;
9617 static const int kToNumberOffset = kToStringOffset + kPointerSize;
Steve Block44f0eee2011-05-26 01:26:41 +01009618 static const int kKindOffset = kToNumberOffset + kPointerSize;
9619 static const int kSize = kKindOffset + kPointerSize;
9620
9621 static const byte kFalse = 0;
9622 static const byte kTrue = 1;
9623 static const byte kNotBooleanMask = ~1;
9624 static const byte kTheHole = 2;
9625 static const byte kNull = 3;
9626 static const byte kArgumentMarker = 4;
9627 static const byte kUndefined = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009628 static const byte kUninitialized = 6;
9629 static const byte kOther = 7;
9630 static const byte kException = 8;
Steve Blocka7e24c12009-10-30 11:49:00 +00009631
Iain Merrick75681382010-08-19 15:07:18 +01009632 typedef FixedBodyDescriptor<kToStringOffset,
9633 kToNumberOffset + kPointerSize,
9634 kSize> BodyDescriptor;
9635
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009636 STATIC_ASSERT(kKindOffset == Internals::kOddballKindOffset);
9637 STATIC_ASSERT(kNull == Internals::kNullOddballKind);
9638 STATIC_ASSERT(kUndefined == Internals::kUndefinedOddballKind);
9639
Steve Blocka7e24c12009-10-30 11:49:00 +00009640 private:
9641 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball);
9642};
9643
9644
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009645class Cell: public HeapObject {
Steve Blocka7e24c12009-10-30 11:49:00 +00009646 public:
9647 // [value]: value of the global property.
9648 DECL_ACCESSORS(value, Object)
9649
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009650 DECLARE_CAST(Cell)
Steve Blocka7e24c12009-10-30 11:49:00 +00009651
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009652 static inline Cell* FromValueAddress(Address value) {
9653 Object* result = FromAddress(value - kValueOffset);
9654 DCHECK(result->IsCell() || result->IsPropertyCell());
9655 return static_cast<Cell*>(result);
Ben Murdochb0fe1622011-05-05 13:52:32 +01009656 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009657
9658 inline Address ValueAddress() {
9659 return address() + kValueOffset;
9660 }
9661
9662 // Dispatched behavior.
9663 DECLARE_PRINTER(Cell)
9664 DECLARE_VERIFIER(Cell)
Steve Blocka7e24c12009-10-30 11:49:00 +00009665
9666 // Layout description.
9667 static const int kValueOffset = HeapObject::kHeaderSize;
9668 static const int kSize = kValueOffset + kPointerSize;
9669
Iain Merrick75681382010-08-19 15:07:18 +01009670 typedef FixedBodyDescriptor<kValueOffset,
9671 kValueOffset + kPointerSize,
9672 kSize> BodyDescriptor;
9673
Steve Blocka7e24c12009-10-30 11:49:00 +00009674 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009675 DISALLOW_IMPLICIT_CONSTRUCTORS(Cell);
9676};
9677
9678
9679class PropertyCell: public Cell {
9680 public:
9681 // [type]: type of the global property.
9682 HeapType* type();
9683 void set_type(HeapType* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
9684
9685 // [dependent_code]: dependent code that depends on the type of the global
9686 // property.
9687 DECL_ACCESSORS(dependent_code, DependentCode)
9688
9689 // Sets the value of the cell and updates the type field to be the union
9690 // of the cell's current type and the value's type. If the change causes
9691 // a change of the type of the cell's contents, code dependent on the cell
9692 // will be deoptimized.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009693 // Usually returns the value that was passed in, but may perform
9694 // non-observable modifications on it, such as internalize strings.
9695 static Handle<Object> SetValueInferType(Handle<PropertyCell> cell,
9696 Handle<Object> value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009697
9698 // Computes the new type of the cell's contents for the given value, but
9699 // without actually modifying the 'type' field.
9700 static Handle<HeapType> UpdatedType(Handle<PropertyCell> cell,
9701 Handle<Object> value);
9702
9703 static void AddDependentCompilationInfo(Handle<PropertyCell> cell,
9704 CompilationInfo* info);
9705
9706 DECLARE_CAST(PropertyCell)
9707
9708 inline Address TypeAddress() {
9709 return address() + kTypeOffset;
9710 }
9711
9712 // Dispatched behavior.
9713 DECLARE_PRINTER(PropertyCell)
9714 DECLARE_VERIFIER(PropertyCell)
9715
9716 // Layout description.
9717 static const int kTypeOffset = kValueOffset + kPointerSize;
9718 static const int kDependentCodeOffset = kTypeOffset + kPointerSize;
9719 static const int kSize = kDependentCodeOffset + kPointerSize;
9720
9721 static const int kPointerFieldsBeginOffset = kValueOffset;
9722 static const int kPointerFieldsEndOffset = kDependentCodeOffset;
9723
9724 typedef FixedBodyDescriptor<kValueOffset,
9725 kSize,
9726 kSize> BodyDescriptor;
9727
9728 private:
9729 DECL_ACCESSORS(type_raw, Object)
9730 DISALLOW_IMPLICIT_CONSTRUCTORS(PropertyCell);
Steve Blocka7e24c12009-10-30 11:49:00 +00009731};
9732
9733
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009734class WeakCell : public HeapObject {
9735 public:
9736 inline Object* value() const;
9737
9738 // This should not be called by anyone except GC.
9739 inline void clear();
9740
9741 // This should not be called by anyone except allocator.
9742 inline void initialize(HeapObject* value);
9743
9744 inline bool cleared() const;
9745
9746 DECL_ACCESSORS(next, Object)
9747
9748 DECLARE_CAST(WeakCell)
9749
9750 DECLARE_PRINTER(WeakCell)
9751 DECLARE_VERIFIER(WeakCell)
9752
9753 // Layout description.
9754 static const int kValueOffset = HeapObject::kHeaderSize;
9755 static const int kNextOffset = kValueOffset + kPointerSize;
9756 static const int kSize = kNextOffset + kPointerSize;
9757
9758 typedef FixedBodyDescriptor<kValueOffset, kSize, kSize> BodyDescriptor;
9759
9760 private:
9761 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakCell);
9762};
9763
9764
Ben Murdoch257744e2011-11-30 15:57:28 +00009765// The JSProxy describes EcmaScript Harmony proxies
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009766class JSProxy: public JSReceiver {
Steve Blocka7e24c12009-10-30 11:49:00 +00009767 public:
Ben Murdoch257744e2011-11-30 15:57:28 +00009768 // [handler]: The handler property.
9769 DECL_ACCESSORS(handler, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +00009770
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009771 // [hash]: The hash code property (undefined if not initialized yet).
9772 DECL_ACCESSORS(hash, Object)
9773
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009774 DECLARE_CAST(JSProxy)
Steve Blocka7e24c12009-10-30 11:49:00 +00009775
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009776 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler(
9777 Handle<JSProxy> proxy,
9778 Handle<Object> receiver,
9779 Handle<Name> name);
9780 MUST_USE_RESULT static inline MaybeHandle<Object> GetElementWithHandler(
9781 Handle<JSProxy> proxy,
9782 Handle<Object> receiver,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009783 uint32_t index);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009784
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009785 // If the handler defines an accessor property with a setter, invoke it.
9786 // If it defines an accessor property without a setter, or a data property
9787 // that is read-only, throw. In all these cases set '*done' to true,
9788 // otherwise set it to false.
9789 MUST_USE_RESULT
9790 static MaybeHandle<Object> SetPropertyViaPrototypesWithHandler(
9791 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
9792 Handle<Object> value, StrictMode strict_mode, bool* done);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009793
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009794 MUST_USE_RESULT static Maybe<PropertyAttributes>
9795 GetPropertyAttributesWithHandler(Handle<JSProxy> proxy,
9796 Handle<Object> receiver,
9797 Handle<Name> name);
9798 MUST_USE_RESULT static Maybe<PropertyAttributes>
9799 GetElementAttributeWithHandler(Handle<JSProxy> proxy,
9800 Handle<JSReceiver> receiver,
9801 uint32_t index);
9802 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler(
9803 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name,
9804 Handle<Object> value, StrictMode strict_mode);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009805
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009806 // Turn the proxy into an (empty) JSObject.
9807 static void Fix(Handle<JSProxy> proxy);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009808
Ben Murdoch589d6972011-11-30 16:04:58 +00009809 // Initializes the body after the handler slot.
9810 inline void InitializeBody(int object_size, Object* value);
9811
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009812 // Invoke a trap by name. If the trap does not exist on this's handler,
9813 // but derived_trap is non-NULL, invoke that instead. May cause GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009814 MUST_USE_RESULT static MaybeHandle<Object> CallTrap(
9815 Handle<JSProxy> proxy,
9816 const char* name,
9817 Handle<Object> derived_trap,
9818 int argc,
9819 Handle<Object> args[]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009820
Steve Blocka7e24c12009-10-30 11:49:00 +00009821 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009822 DECLARE_PRINTER(JSProxy)
9823 DECLARE_VERIFIER(JSProxy)
Ben Murdoch257744e2011-11-30 15:57:28 +00009824
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009825 // Layout description. We add padding so that a proxy has the same
9826 // size as a virgin JSObject. This is essential for becoming a JSObject
9827 // upon freeze.
Ben Murdoch257744e2011-11-30 15:57:28 +00009828 static const int kHandlerOffset = HeapObject::kHeaderSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009829 static const int kHashOffset = kHandlerOffset + kPointerSize;
9830 static const int kPaddingOffset = kHashOffset + kPointerSize;
Ben Murdoch589d6972011-11-30 16:04:58 +00009831 static const int kSize = JSObject::kHeaderSize;
9832 static const int kHeaderSize = kPaddingOffset;
9833 static const int kPaddingSize = kSize - kPaddingOffset;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009834
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009835 STATIC_ASSERT(kPaddingSize >= 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00009836
9837 typedef FixedBodyDescriptor<kHandlerOffset,
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009838 kPaddingOffset,
Ben Murdoch257744e2011-11-30 15:57:28 +00009839 kSize> BodyDescriptor;
9840
9841 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009842 friend class JSReceiver;
9843
9844 MUST_USE_RESULT static inline MaybeHandle<Object> SetElementWithHandler(
9845 Handle<JSProxy> proxy,
9846 Handle<JSReceiver> receiver,
9847 uint32_t index,
9848 Handle<Object> value,
9849 StrictMode strict_mode);
9850
9851 MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler(
9852 Handle<JSProxy> proxy, Handle<Name> name);
9853 MUST_USE_RESULT static inline Maybe<bool> HasElementWithHandler(
9854 Handle<JSProxy> proxy, uint32_t index);
9855
9856 MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler(
9857 Handle<JSProxy> proxy,
9858 Handle<Name> name,
9859 DeleteMode mode);
9860 MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithHandler(
9861 Handle<JSProxy> proxy,
9862 uint32_t index,
9863 DeleteMode mode);
9864
9865 MUST_USE_RESULT Object* GetIdentityHash();
9866
9867 static Handle<Smi> GetOrCreateIdentityHash(Handle<JSProxy> proxy);
9868
Ben Murdoch257744e2011-11-30 15:57:28 +00009869 DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy);
9870};
9871
9872
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009873class JSFunctionProxy: public JSProxy {
9874 public:
Ben Murdoch589d6972011-11-30 16:04:58 +00009875 // [call_trap]: The call trap.
9876 DECL_ACCESSORS(call_trap, Object)
9877
9878 // [construct_trap]: The construct trap.
9879 DECL_ACCESSORS(construct_trap, Object)
9880
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009881 DECLARE_CAST(JSFunctionProxy)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009882
Ben Murdoch589d6972011-11-30 16:04:58 +00009883 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009884 DECLARE_PRINTER(JSFunctionProxy)
9885 DECLARE_VERIFIER(JSFunctionProxy)
Ben Murdoch589d6972011-11-30 16:04:58 +00009886
9887 // Layout description.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009888 static const int kCallTrapOffset = JSProxy::kPaddingOffset;
Ben Murdoch589d6972011-11-30 16:04:58 +00009889 static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize;
9890 static const int kPaddingOffset = kConstructTrapOffset + kPointerSize;
9891 static const int kSize = JSFunction::kSize;
9892 static const int kPaddingSize = kSize - kPaddingOffset;
9893
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009894 STATIC_ASSERT(kPaddingSize >= 0);
Ben Murdoch589d6972011-11-30 16:04:58 +00009895
9896 typedef FixedBodyDescriptor<kHandlerOffset,
9897 kConstructTrapOffset + kPointerSize,
9898 kSize> BodyDescriptor;
9899
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00009900 private:
9901 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy);
9902};
9903
Ben Murdoch257744e2011-11-30 15:57:28 +00009904
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009905class JSCollection : public JSObject {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009906 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009907 // [table]: the backing hash table
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009908 DECL_ACCESSORS(table, Object)
9909
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009910 static const int kTableOffset = JSObject::kHeaderSize;
9911 static const int kSize = kTableOffset + kPointerSize;
9912
9913 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009914 DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollection);
9915};
9916
9917
9918// The JSSet describes EcmaScript Harmony sets
9919class JSSet : public JSCollection {
9920 public:
9921 DECLARE_CAST(JSSet)
9922
9923 // Dispatched behavior.
9924 DECLARE_PRINTER(JSSet)
9925 DECLARE_VERIFIER(JSSet)
9926
9927 private:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009928 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet);
9929};
9930
9931
9932// The JSMap describes EcmaScript Harmony maps
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009933class JSMap : public JSCollection {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009934 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009935 DECLARE_CAST(JSMap)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009936
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009937 // Dispatched behavior.
9938 DECLARE_PRINTER(JSMap)
9939 DECLARE_VERIFIER(JSMap)
Ben Murdoch3ef787d2012-04-12 10:51:47 +01009940
9941 private:
9942 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
9943};
9944
9945
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009946// OrderedHashTableIterator is an iterator that iterates over the keys and
9947// values of an OrderedHashTable.
9948//
9949// The iterator has a reference to the underlying OrderedHashTable data,
9950// [table], as well as the current [index] the iterator is at.
9951//
9952// When the OrderedHashTable is rehashed it adds a reference from the old table
9953// to the new table as well as storing enough data about the changes so that the
9954// iterator [index] can be adjusted accordingly.
9955//
9956// When the [Next] result from the iterator is requested, the iterator checks if
9957// there is a newer table that it needs to transition to.
9958template<class Derived, class TableType>
9959class OrderedHashTableIterator: public JSObject {
9960 public:
9961 // [table]: the backing hash table mapping keys to values.
9962 DECL_ACCESSORS(table, Object)
9963
9964 // [index]: The index into the data table.
9965 DECL_ACCESSORS(index, Object)
9966
9967 // [kind]: The kind of iteration this is. One of the [Kind] enum values.
9968 DECL_ACCESSORS(kind, Object)
9969
9970#ifdef OBJECT_PRINT
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009971 void OrderedHashTableIteratorPrint(std::ostream& os); // NOLINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009972#endif
9973
9974 static const int kTableOffset = JSObject::kHeaderSize;
9975 static const int kIndexOffset = kTableOffset + kPointerSize;
9976 static const int kKindOffset = kIndexOffset + kPointerSize;
9977 static const int kSize = kKindOffset + kPointerSize;
9978
9979 enum Kind {
9980 kKindKeys = 1,
9981 kKindValues = 2,
9982 kKindEntries = 3
9983 };
9984
9985 // Whether the iterator has more elements. This needs to be called before
9986 // calling |CurrentKey| and/or |CurrentValue|.
9987 bool HasMore();
9988
9989 // Move the index forward one.
9990 void MoveNext() {
9991 set_index(Smi::FromInt(Smi::cast(index())->value() + 1));
9992 }
9993
9994 // Populates the array with the next key and value and then moves the iterator
9995 // forward.
9996 // This returns the |kind| or 0 if the iterator is already at the end.
9997 Smi* Next(JSArray* value_array);
9998
9999 // Returns the current key of the iterator. This should only be called when
10000 // |HasMore| returns true.
10001 inline Object* CurrentKey();
10002
10003 private:
10004 // Transitions the iterator to the non obsolete backing store. This is a NOP
10005 // if the [table] is not obsolete.
10006 void Transition();
10007
10008 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator);
10009};
10010
10011
10012class JSSetIterator: public OrderedHashTableIterator<JSSetIterator,
10013 OrderedHashSet> {
10014 public:
10015 // Dispatched behavior.
10016 DECLARE_PRINTER(JSSetIterator)
10017 DECLARE_VERIFIER(JSSetIterator)
10018
10019 DECLARE_CAST(JSSetIterator)
10020
10021 // Called by |Next| to populate the array. This allows the subclasses to
10022 // populate the array differently.
10023 inline void PopulateValueArray(FixedArray* array);
10024
10025 private:
10026 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator);
10027};
10028
10029
10030class JSMapIterator: public OrderedHashTableIterator<JSMapIterator,
10031 OrderedHashMap> {
10032 public:
10033 // Dispatched behavior.
10034 DECLARE_PRINTER(JSMapIterator)
10035 DECLARE_VERIFIER(JSMapIterator)
10036
10037 DECLARE_CAST(JSMapIterator)
10038
10039 // Called by |Next| to populate the array. This allows the subclasses to
10040 // populate the array differently.
10041 inline void PopulateValueArray(FixedArray* array);
10042
10043 private:
10044 // Returns the current value of the iterator. This should only be called when
10045 // |HasMore| returns true.
10046 inline Object* CurrentValue();
10047
10048 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator);
10049};
10050
10051
10052// Base class for both JSWeakMap and JSWeakSet
10053class JSWeakCollection: public JSObject {
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010054 public:
10055 // [table]: the backing hash table mapping keys to values.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010056 DECL_ACCESSORS(table, Object)
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010057
10058 // [next]: linked list of encountered weak maps during GC.
10059 DECL_ACCESSORS(next, Object)
10060
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010061 static const int kTableOffset = JSObject::kHeaderSize;
10062 static const int kNextOffset = kTableOffset + kPointerSize;
10063 static const int kSize = kNextOffset + kPointerSize;
10064
10065 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010066 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
10067};
10068
10069
10070// The JSWeakMap describes EcmaScript Harmony weak maps
10071class JSWeakMap: public JSWeakCollection {
10072 public:
10073 DECLARE_CAST(JSWeakMap)
10074
10075 // Dispatched behavior.
10076 DECLARE_PRINTER(JSWeakMap)
10077 DECLARE_VERIFIER(JSWeakMap)
10078
10079 private:
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010080 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
10081};
10082
10083
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010084// The JSWeakSet describes EcmaScript Harmony weak sets
10085class JSWeakSet: public JSWeakCollection {
10086 public:
10087 DECLARE_CAST(JSWeakSet)
10088
10089 // Dispatched behavior.
10090 DECLARE_PRINTER(JSWeakSet)
10091 DECLARE_VERIFIER(JSWeakSet)
10092
10093 private:
10094 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakSet);
10095};
10096
10097
10098class JSArrayBuffer: public JSObject {
10099 public:
10100 // [backing_store]: backing memory for this array
10101 DECL_ACCESSORS(backing_store, void)
10102
10103 // [byte_length]: length in bytes
10104 DECL_ACCESSORS(byte_length, Object)
10105
10106 // [flags]
10107 DECL_ACCESSORS(flag, Smi)
10108
10109 inline bool is_external();
10110 inline void set_is_external(bool value);
10111
10112 inline bool should_be_freed();
10113 inline void set_should_be_freed(bool value);
10114
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010115 inline bool is_neuterable();
10116 inline void set_is_neuterable(bool value);
10117
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010118 // [weak_next]: linked list of array buffers.
10119 DECL_ACCESSORS(weak_next, Object)
10120
10121 // [weak_first_array]: weak linked list of views.
10122 DECL_ACCESSORS(weak_first_view, Object)
10123
10124 DECLARE_CAST(JSArrayBuffer)
10125
10126 // Neutering. Only neuters the buffer, not associated typed arrays.
10127 void Neuter();
10128
10129 // Dispatched behavior.
10130 DECLARE_PRINTER(JSArrayBuffer)
10131 DECLARE_VERIFIER(JSArrayBuffer)
10132
10133 static const int kBackingStoreOffset = JSObject::kHeaderSize;
10134 static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize;
10135 static const int kFlagOffset = kByteLengthOffset + kPointerSize;
10136 static const int kWeakNextOffset = kFlagOffset + kPointerSize;
10137 static const int kWeakFirstViewOffset = kWeakNextOffset + kPointerSize;
10138 static const int kSize = kWeakFirstViewOffset + kPointerSize;
10139
10140 static const int kSizeWithInternalFields =
10141 kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize;
10142
10143 private:
10144 // Bit position in a flag
10145 static const int kIsExternalBit = 0;
10146 static const int kShouldBeFreed = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010147 static const int kIsNeuterableBit = 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010148
10149 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
10150};
10151
10152
10153class JSArrayBufferView: public JSObject {
10154 public:
10155 // [buffer]: ArrayBuffer that this typed array views.
10156 DECL_ACCESSORS(buffer, Object)
10157
10158 // [byte_length]: offset of typed array in bytes.
10159 DECL_ACCESSORS(byte_offset, Object)
10160
10161 // [byte_length]: length of typed array in bytes.
10162 DECL_ACCESSORS(byte_length, Object)
10163
10164 // [weak_next]: linked list of typed arrays over the same array buffer.
10165 DECL_ACCESSORS(weak_next, Object)
10166
10167 DECLARE_CAST(JSArrayBufferView)
10168
10169 DECLARE_VERIFIER(JSArrayBufferView)
10170
10171 static const int kBufferOffset = JSObject::kHeaderSize;
10172 static const int kByteOffsetOffset = kBufferOffset + kPointerSize;
10173 static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize;
10174 static const int kWeakNextOffset = kByteLengthOffset + kPointerSize;
10175 static const int kViewSize = kWeakNextOffset + kPointerSize;
10176
10177 protected:
10178 void NeuterView();
10179
10180 private:
10181 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBufferView);
10182};
10183
10184
10185class JSTypedArray: public JSArrayBufferView {
10186 public:
10187 // [length]: length of typed array in elements.
10188 DECL_ACCESSORS(length, Object)
10189
10190 // Neutering. Only neuters this typed array.
10191 void Neuter();
10192
10193 DECLARE_CAST(JSTypedArray)
10194
10195 ExternalArrayType type();
10196 size_t element_size();
10197
10198 Handle<JSArrayBuffer> GetBuffer();
10199
10200 // Dispatched behavior.
10201 DECLARE_PRINTER(JSTypedArray)
10202 DECLARE_VERIFIER(JSTypedArray)
10203
10204 static const int kLengthOffset = kViewSize + kPointerSize;
10205 static const int kSize = kLengthOffset + kPointerSize;
10206
10207 static const int kSizeWithInternalFields =
10208 kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
10209
10210 private:
10211 static Handle<JSArrayBuffer> MaterializeArrayBuffer(
10212 Handle<JSTypedArray> typed_array);
10213
10214 DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
10215};
10216
10217
10218class JSDataView: public JSArrayBufferView {
10219 public:
10220 // Only neuters this DataView
10221 void Neuter();
10222
10223 DECLARE_CAST(JSDataView)
10224
10225 // Dispatched behavior.
10226 DECLARE_PRINTER(JSDataView)
10227 DECLARE_VERIFIER(JSDataView)
10228
10229 static const int kSize = kViewSize;
10230
10231 static const int kSizeWithInternalFields =
10232 kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize;
10233
10234 private:
10235 DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView);
10236};
10237
10238
Ben Murdoch257744e2011-11-30 15:57:28 +000010239// Foreign describes objects pointing from JavaScript to C structures.
10240// Since they cannot contain references to JS HeapObjects they can be
10241// placed in old_data_space.
10242class Foreign: public HeapObject {
10243 public:
10244 // [address]: field containing the address.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010245 inline Address foreign_address();
10246 inline void set_foreign_address(Address value);
Ben Murdoch257744e2011-11-30 15:57:28 +000010247
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010248 DECLARE_CAST(Foreign)
Ben Murdoch257744e2011-11-30 15:57:28 +000010249
10250 // Dispatched behavior.
10251 inline void ForeignIterateBody(ObjectVisitor* v);
10252
10253 template<typename StaticVisitor>
10254 inline void ForeignIterateBody();
10255
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010256 // Dispatched behavior.
10257 DECLARE_PRINTER(Foreign)
10258 DECLARE_VERIFIER(Foreign)
Steve Blocka7e24c12009-10-30 11:49:00 +000010259
10260 // Layout description.
10261
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010262 static const int kForeignAddressOffset = HeapObject::kHeaderSize;
10263 static const int kSize = kForeignAddressOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010264
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010265 STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset);
Steve Blocka7e24c12009-10-30 11:49:00 +000010266
10267 private:
Ben Murdoch257744e2011-11-30 15:57:28 +000010268 DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign);
Steve Blocka7e24c12009-10-30 11:49:00 +000010269};
10270
10271
10272// The JSArray describes JavaScript Arrays
10273// Such an array can be in one of two modes:
10274// - fast, backing storage is a FixedArray and length <= elements.length();
10275// Please note: push and pop can be used to grow and shrink the array.
10276// - slow, backing storage is a HashTable with numbers as keys.
10277class JSArray: public JSObject {
10278 public:
10279 // [length]: The length property.
10280 DECL_ACCESSORS(length, Object)
10281
Leon Clarke4515c472010-02-03 11:58:03 +000010282 // Overload the length setter to skip write barrier when the length
10283 // is set to a smi. This matches the set function on FixedArray.
10284 inline void set_length(Smi* length);
10285
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010286 static void JSArrayUpdateLengthFromIndex(Handle<JSArray> array,
10287 uint32_t index,
10288 Handle<Object> value);
10289
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010290 static bool HasReadOnlyLength(Handle<JSArray> array);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010291 static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index);
10292 static MaybeHandle<Object> ReadOnlyLengthError(Handle<JSArray> array);
Steve Blocka7e24c12009-10-30 11:49:00 +000010293
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010294 // TODO(adamk): Remove this method in favor of HasReadOnlyLength().
10295 static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map);
10296
Steve Blocka7e24c12009-10-30 11:49:00 +000010297 // Initialize the array with the given capacity. The function may
10298 // fail due to out-of-memory situations, but only if the requested
10299 // capacity is non-zero.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010300 static void Initialize(Handle<JSArray> array, int capacity, int length = 0);
Steve Blocka7e24c12009-10-30 11:49:00 +000010301
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010302 // Initializes the array to a certain length.
10303 inline bool AllowsSetElementsLength();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010304 // Can cause GC.
10305 MUST_USE_RESULT static MaybeHandle<Object> SetElementsLength(
10306 Handle<JSArray> array,
10307 Handle<Object> length);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010308
Steve Blocka7e24c12009-10-30 11:49:00 +000010309 // Set the content of the array to the content of storage.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010310 static inline void SetContent(Handle<JSArray> array,
10311 Handle<FixedArrayBase> storage);
Steve Blocka7e24c12009-10-30 11:49:00 +000010312
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010313 DECLARE_CAST(JSArray)
Steve Blocka7e24c12009-10-30 11:49:00 +000010314
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010315 // Ensures that the fixed array backing the JSArray has at
Steve Blocka7e24c12009-10-30 11:49:00 +000010316 // least the stated size.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010317 static inline void EnsureSize(Handle<JSArray> array,
10318 int minimum_size_of_backing_fixed_array);
10319
10320 // Expand the fixed array backing of a fast-case JSArray to at least
10321 // the requested size.
10322 static void Expand(Handle<JSArray> array,
10323 int minimum_size_of_backing_fixed_array);
Steve Blocka7e24c12009-10-30 11:49:00 +000010324
10325 // Dispatched behavior.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010326 DECLARE_PRINTER(JSArray)
10327 DECLARE_VERIFIER(JSArray)
Steve Blocka7e24c12009-10-30 11:49:00 +000010328
10329 // Number of element slots to pre-allocate for an empty array.
10330 static const int kPreallocatedArrayElements = 4;
10331
10332 // Layout description.
10333 static const int kLengthOffset = JSObject::kHeaderSize;
10334 static const int kSize = kLengthOffset + kPointerSize;
10335
10336 private:
Steve Blocka7e24c12009-10-30 11:49:00 +000010337 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray);
10338};
10339
10340
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010341Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
10342 Handle<Map> initial_map);
10343
10344
Steve Block6ded16b2010-05-10 14:33:55 +010010345// JSRegExpResult is just a JSArray with a specific initial map.
10346// This initial map adds in-object properties for "index" and "input"
10347// properties, as assigned by RegExp.prototype.exec, which allows
10348// faster creation of RegExp exec results.
10349// This class just holds constants used when creating the result.
10350// After creation the result must be treated as a JSArray in all regards.
10351class JSRegExpResult: public JSArray {
10352 public:
10353 // Offsets of object fields.
10354 static const int kIndexOffset = JSArray::kSize;
10355 static const int kInputOffset = kIndexOffset + kPointerSize;
10356 static const int kSize = kInputOffset + kPointerSize;
10357 // Indices of in-object properties.
10358 static const int kIndexIndex = 0;
10359 static const int kInputIndex = 1;
10360 private:
10361 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult);
10362};
10363
10364
Steve Blocka7e24c12009-10-30 11:49:00 +000010365class AccessorInfo: public Struct {
10366 public:
Steve Blocka7e24c12009-10-30 11:49:00 +000010367 DECL_ACCESSORS(name, Object)
10368 DECL_ACCESSORS(flag, Smi)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010369 DECL_ACCESSORS(expected_receiver_type, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +000010370
10371 inline bool all_can_read();
10372 inline void set_all_can_read(bool value);
10373
10374 inline bool all_can_write();
10375 inline void set_all_can_write(bool value);
10376
Steve Blocka7e24c12009-10-30 11:49:00 +000010377 inline PropertyAttributes property_attributes();
10378 inline void set_property_attributes(PropertyAttributes attributes);
10379
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010380 // Checks whether the given receiver is compatible with this accessor.
10381 static bool IsCompatibleReceiverType(Isolate* isolate,
10382 Handle<AccessorInfo> info,
10383 Handle<HeapType> type);
10384 inline bool IsCompatibleReceiver(Object* receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +000010385
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010386 DECLARE_CAST(AccessorInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010387
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010388 // Dispatched behavior.
10389 DECLARE_VERIFIER(AccessorInfo)
10390
10391 // Append all descriptors to the array that are not already there.
10392 // Return number added.
10393 static int AppendUnique(Handle<Object> descriptors,
10394 Handle<FixedArray> array,
10395 int valid_descriptors);
10396
10397 static const int kNameOffset = HeapObject::kHeaderSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010398 static const int kFlagOffset = kNameOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010399 static const int kExpectedReceiverTypeOffset = kFlagOffset + kPointerSize;
10400 static const int kSize = kExpectedReceiverTypeOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010401
10402 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010403 inline bool HasExpectedReceiverType() {
10404 return expected_receiver_type()->IsFunctionTemplateInfo();
10405 }
Steve Blocka7e24c12009-10-30 11:49:00 +000010406 // Bit positions in flag.
10407 static const int kAllCanReadBit = 0;
10408 static const int kAllCanWriteBit = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010409 class AttributesField: public BitField<PropertyAttributes, 2, 3> {};
Steve Blocka7e24c12009-10-30 11:49:00 +000010410
10411 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
10412};
10413
10414
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010415enum AccessorDescriptorType {
10416 kDescriptorBitmaskCompare,
10417 kDescriptorPointerCompare,
10418 kDescriptorPrimitiveValue,
10419 kDescriptorObjectDereference,
10420 kDescriptorPointerDereference,
10421 kDescriptorPointerShift,
10422 kDescriptorReturnObject
10423};
10424
10425
10426struct BitmaskCompareDescriptor {
10427 uint32_t bitmask;
10428 uint32_t compare_value;
10429 uint8_t size; // Must be in {1,2,4}.
10430};
10431
10432
10433struct PointerCompareDescriptor {
10434 void* compare_value;
10435};
10436
10437
10438struct PrimitiveValueDescriptor {
10439 v8::DeclaredAccessorDescriptorDataType data_type;
10440 uint8_t bool_offset; // Must be in [0,7], used for kDescriptorBoolType.
10441};
10442
10443
10444struct ObjectDerefenceDescriptor {
10445 uint8_t internal_field;
10446};
10447
10448
10449struct PointerShiftDescriptor {
10450 int16_t byte_offset;
10451};
10452
10453
10454struct DeclaredAccessorDescriptorData {
10455 AccessorDescriptorType type;
10456 union {
10457 struct BitmaskCompareDescriptor bitmask_compare_descriptor;
10458 struct PointerCompareDescriptor pointer_compare_descriptor;
10459 struct PrimitiveValueDescriptor primitive_value_descriptor;
10460 struct ObjectDerefenceDescriptor object_dereference_descriptor;
10461 struct PointerShiftDescriptor pointer_shift_descriptor;
10462 };
10463};
10464
10465
10466class DeclaredAccessorDescriptor;
10467
10468
10469class DeclaredAccessorDescriptorIterator {
10470 public:
10471 explicit DeclaredAccessorDescriptorIterator(
10472 DeclaredAccessorDescriptor* descriptor);
10473 const DeclaredAccessorDescriptorData* Next();
10474 bool Complete() const { return length_ == offset_; }
10475 private:
10476 uint8_t* array_;
10477 const int length_;
10478 int offset_;
10479 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptorIterator);
10480};
10481
10482
10483class DeclaredAccessorDescriptor: public Struct {
10484 public:
10485 DECL_ACCESSORS(serialized_data, ByteArray)
10486
10487 DECLARE_CAST(DeclaredAccessorDescriptor)
10488
10489 static Handle<DeclaredAccessorDescriptor> Create(
10490 Isolate* isolate,
10491 const DeclaredAccessorDescriptorData& data,
10492 Handle<DeclaredAccessorDescriptor> previous);
10493
10494 // Dispatched behavior.
10495 DECLARE_PRINTER(DeclaredAccessorDescriptor)
10496 DECLARE_VERIFIER(DeclaredAccessorDescriptor)
10497
10498 static const int kSerializedDataOffset = HeapObject::kHeaderSize;
10499 static const int kSize = kSerializedDataOffset + kPointerSize;
10500
10501 private:
10502 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptor);
10503};
10504
10505
10506class DeclaredAccessorInfo: public AccessorInfo {
10507 public:
10508 DECL_ACCESSORS(descriptor, DeclaredAccessorDescriptor)
10509
10510 DECLARE_CAST(DeclaredAccessorInfo)
10511
10512 // Dispatched behavior.
10513 DECLARE_PRINTER(DeclaredAccessorInfo)
10514 DECLARE_VERIFIER(DeclaredAccessorInfo)
10515
10516 static const int kDescriptorOffset = AccessorInfo::kSize;
10517 static const int kSize = kDescriptorOffset + kPointerSize;
10518
10519 private:
10520 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorInfo);
10521};
10522
10523
10524// An accessor must have a getter, but can have no setter.
10525//
10526// When setting a property, V8 searches accessors in prototypes.
10527// If an accessor was found and it does not have a setter,
10528// the request is ignored.
10529//
10530// If the accessor in the prototype has the READ_ONLY property attribute, then
10531// a new value is added to the derived object when the property is set.
10532// This shadows the accessor in the prototype.
10533class ExecutableAccessorInfo: public AccessorInfo {
10534 public:
10535 DECL_ACCESSORS(getter, Object)
10536 DECL_ACCESSORS(setter, Object)
10537 DECL_ACCESSORS(data, Object)
10538
10539 DECLARE_CAST(ExecutableAccessorInfo)
10540
10541 // Dispatched behavior.
10542 DECLARE_PRINTER(ExecutableAccessorInfo)
10543 DECLARE_VERIFIER(ExecutableAccessorInfo)
10544
10545 static const int kGetterOffset = AccessorInfo::kSize;
10546 static const int kSetterOffset = kGetterOffset + kPointerSize;
10547 static const int kDataOffset = kSetterOffset + kPointerSize;
10548 static const int kSize = kDataOffset + kPointerSize;
10549
10550 inline void clear_setter();
10551
10552 private:
10553 DISALLOW_IMPLICIT_CONSTRUCTORS(ExecutableAccessorInfo);
10554};
10555
10556
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010557// Support for JavaScript accessors: A pair of a getter and a setter. Each
10558// accessor can either be
10559// * a pointer to a JavaScript function or proxy: a real accessor
10560// * undefined: considered an accessor by the spec, too, strangely enough
10561// * the hole: an accessor which has not been set
10562// * a pointer to a map: a transition used to ensure map sharing
10563class AccessorPair: public Struct {
10564 public:
10565 DECL_ACCESSORS(getter, Object)
10566 DECL_ACCESSORS(setter, Object)
10567
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010568 DECLARE_CAST(AccessorPair)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010569
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010570 static Handle<AccessorPair> Copy(Handle<AccessorPair> pair);
10571
10572 Object* get(AccessorComponent component) {
10573 return component == ACCESSOR_GETTER ? getter() : setter();
10574 }
10575
10576 void set(AccessorComponent component, Object* value) {
10577 if (component == ACCESSOR_GETTER) {
10578 set_getter(value);
10579 } else {
10580 set_setter(value);
10581 }
10582 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010583
10584 // Note: Returns undefined instead in case of a hole.
10585 Object* GetComponent(AccessorComponent component);
10586
10587 // Set both components, skipping arguments which are a JavaScript null.
10588 void SetComponents(Object* getter, Object* setter) {
10589 if (!getter->IsNull()) set_getter(getter);
10590 if (!setter->IsNull()) set_setter(setter);
10591 }
10592
10593 bool ContainsAccessor() {
10594 return IsJSAccessor(getter()) || IsJSAccessor(setter());
10595 }
10596
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010597 // Dispatched behavior.
10598 DECLARE_PRINTER(AccessorPair)
10599 DECLARE_VERIFIER(AccessorPair)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010600
10601 static const int kGetterOffset = HeapObject::kHeaderSize;
10602 static const int kSetterOffset = kGetterOffset + kPointerSize;
10603 static const int kSize = kSetterOffset + kPointerSize;
10604
10605 private:
10606 // Strangely enough, in addition to functions and harmony proxies, the spec
10607 // requires us to consider undefined as a kind of accessor, too:
10608 // var obj = {};
10609 // Object.defineProperty(obj, "foo", {get: undefined});
10610 // assertTrue("foo" in obj);
10611 bool IsJSAccessor(Object* obj) {
10612 return obj->IsSpecFunction() || obj->IsUndefined();
10613 }
10614
10615 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair);
10616};
10617
10618
Steve Blocka7e24c12009-10-30 11:49:00 +000010619class AccessCheckInfo: public Struct {
10620 public:
10621 DECL_ACCESSORS(named_callback, Object)
10622 DECL_ACCESSORS(indexed_callback, Object)
10623 DECL_ACCESSORS(data, Object)
10624
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010625 DECLARE_CAST(AccessCheckInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010626
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010627 // Dispatched behavior.
10628 DECLARE_PRINTER(AccessCheckInfo)
10629 DECLARE_VERIFIER(AccessCheckInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010630
10631 static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
10632 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
10633 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize;
10634 static const int kSize = kDataOffset + kPointerSize;
10635
10636 private:
10637 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo);
10638};
10639
10640
10641class InterceptorInfo: public Struct {
10642 public:
10643 DECL_ACCESSORS(getter, Object)
10644 DECL_ACCESSORS(setter, Object)
10645 DECL_ACCESSORS(query, Object)
10646 DECL_ACCESSORS(deleter, Object)
10647 DECL_ACCESSORS(enumerator, Object)
10648 DECL_ACCESSORS(data, Object)
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010649 DECL_BOOLEAN_ACCESSORS(can_intercept_symbols)
10650 DECL_BOOLEAN_ACCESSORS(all_can_read)
10651
10652 inline int flags() const;
10653 inline void set_flags(int flags);
Steve Blocka7e24c12009-10-30 11:49:00 +000010654
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010655 DECLARE_CAST(InterceptorInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010656
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010657 // Dispatched behavior.
10658 DECLARE_PRINTER(InterceptorInfo)
10659 DECLARE_VERIFIER(InterceptorInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010660
10661 static const int kGetterOffset = HeapObject::kHeaderSize;
10662 static const int kSetterOffset = kGetterOffset + kPointerSize;
10663 static const int kQueryOffset = kSetterOffset + kPointerSize;
10664 static const int kDeleterOffset = kQueryOffset + kPointerSize;
10665 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
10666 static const int kDataOffset = kEnumeratorOffset + kPointerSize;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010667 static const int kFlagsOffset = kDataOffset + kPointerSize;
10668 static const int kSize = kFlagsOffset + kPointerSize;
10669
10670 static const int kCanInterceptSymbolsBit = 0;
10671 static const int kAllCanReadBit = 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000010672
10673 private:
10674 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
10675};
10676
10677
10678class CallHandlerInfo: public Struct {
10679 public:
10680 DECL_ACCESSORS(callback, Object)
10681 DECL_ACCESSORS(data, Object)
10682
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010683 DECLARE_CAST(CallHandlerInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010684
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010685 // Dispatched behavior.
10686 DECLARE_PRINTER(CallHandlerInfo)
10687 DECLARE_VERIFIER(CallHandlerInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010688
10689 static const int kCallbackOffset = HeapObject::kHeaderSize;
10690 static const int kDataOffset = kCallbackOffset + kPointerSize;
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080010691 static const int kSize = kDataOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010692
10693 private:
10694 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
10695};
10696
10697
10698class TemplateInfo: public Struct {
10699 public:
10700 DECL_ACCESSORS(tag, Object)
10701 DECL_ACCESSORS(property_list, Object)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010702 DECL_ACCESSORS(property_accessors, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +000010703
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010704 DECLARE_VERIFIER(TemplateInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010705
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010706 static const int kTagOffset = HeapObject::kHeaderSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010707 static const int kPropertyListOffset = kTagOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010708 static const int kPropertyAccessorsOffset =
10709 kPropertyListOffset + kPointerSize;
10710 static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010711
10712 private:
Steve Blocka7e24c12009-10-30 11:49:00 +000010713 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
10714};
10715
10716
10717class FunctionTemplateInfo: public TemplateInfo {
10718 public:
10719 DECL_ACCESSORS(serial_number, Object)
10720 DECL_ACCESSORS(call_code, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +000010721 DECL_ACCESSORS(prototype_template, Object)
10722 DECL_ACCESSORS(parent_template, Object)
10723 DECL_ACCESSORS(named_property_handler, Object)
10724 DECL_ACCESSORS(indexed_property_handler, Object)
10725 DECL_ACCESSORS(instance_template, Object)
10726 DECL_ACCESSORS(class_name, Object)
10727 DECL_ACCESSORS(signature, Object)
10728 DECL_ACCESSORS(instance_call_handler, Object)
10729 DECL_ACCESSORS(access_check_info, Object)
10730 DECL_ACCESSORS(flag, Smi)
10731
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010732 inline int length() const;
10733 inline void set_length(int value);
10734
Steve Blocka7e24c12009-10-30 11:49:00 +000010735 // Following properties use flag bits.
10736 DECL_BOOLEAN_ACCESSORS(hidden_prototype)
10737 DECL_BOOLEAN_ACCESSORS(undetectable)
10738 // If the bit is set, object instances created by this function
10739 // requires access check.
10740 DECL_BOOLEAN_ACCESSORS(needs_access_check)
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010741 DECL_BOOLEAN_ACCESSORS(read_only_prototype)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010742 DECL_BOOLEAN_ACCESSORS(remove_prototype)
10743 DECL_BOOLEAN_ACCESSORS(do_not_cache)
Steve Blocka7e24c12009-10-30 11:49:00 +000010744
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010745 DECLARE_CAST(FunctionTemplateInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010746
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010747 // Dispatched behavior.
10748 DECLARE_PRINTER(FunctionTemplateInfo)
10749 DECLARE_VERIFIER(FunctionTemplateInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010750
10751 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
10752 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010753 static const int kPrototypeTemplateOffset =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010754 kCallCodeOffset + kPointerSize;
Steve Blocka7e24c12009-10-30 11:49:00 +000010755 static const int kParentTemplateOffset =
10756 kPrototypeTemplateOffset + kPointerSize;
10757 static const int kNamedPropertyHandlerOffset =
10758 kParentTemplateOffset + kPointerSize;
10759 static const int kIndexedPropertyHandlerOffset =
10760 kNamedPropertyHandlerOffset + kPointerSize;
10761 static const int kInstanceTemplateOffset =
10762 kIndexedPropertyHandlerOffset + kPointerSize;
10763 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
10764 static const int kSignatureOffset = kClassNameOffset + kPointerSize;
10765 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize;
10766 static const int kAccessCheckInfoOffset =
10767 kInstanceCallHandlerOffset + kPointerSize;
10768 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010769 static const int kLengthOffset = kFlagOffset + kPointerSize;
10770 static const int kSize = kLengthOffset + kPointerSize;
10771
10772 // Returns true if |object| is an instance of this function template.
10773 bool IsTemplateFor(Object* object);
10774 bool IsTemplateFor(Map* map);
Steve Blocka7e24c12009-10-30 11:49:00 +000010775
10776 private:
10777 // Bit position in the flag, from least significant bit position.
10778 static const int kHiddenPrototypeBit = 0;
10779 static const int kUndetectableBit = 1;
10780 static const int kNeedsAccessCheckBit = 2;
Ben Murdoch69a99ed2011-11-30 16:03:39 +000010781 static const int kReadOnlyPrototypeBit = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010782 static const int kRemovePrototypeBit = 4;
10783 static const int kDoNotCacheBit = 5;
Steve Blocka7e24c12009-10-30 11:49:00 +000010784
10785 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
10786};
10787
10788
10789class ObjectTemplateInfo: public TemplateInfo {
10790 public:
10791 DECL_ACCESSORS(constructor, Object)
10792 DECL_ACCESSORS(internal_field_count, Object)
10793
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010794 DECLARE_CAST(ObjectTemplateInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010795
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010796 // Dispatched behavior.
10797 DECLARE_PRINTER(ObjectTemplateInfo)
10798 DECLARE_VERIFIER(ObjectTemplateInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010799
10800 static const int kConstructorOffset = TemplateInfo::kHeaderSize;
10801 static const int kInternalFieldCountOffset =
10802 kConstructorOffset + kPointerSize;
10803 static const int kSize = kInternalFieldCountOffset + kPointerSize;
10804};
10805
10806
10807class SignatureInfo: public Struct {
10808 public:
10809 DECL_ACCESSORS(receiver, Object)
10810 DECL_ACCESSORS(args, Object)
10811
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010812 DECLARE_CAST(SignatureInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010813
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010814 // Dispatched behavior.
10815 DECLARE_PRINTER(SignatureInfo)
10816 DECLARE_VERIFIER(SignatureInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010817
10818 static const int kReceiverOffset = Struct::kHeaderSize;
10819 static const int kArgsOffset = kReceiverOffset + kPointerSize;
10820 static const int kSize = kArgsOffset + kPointerSize;
10821
10822 private:
10823 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo);
10824};
10825
10826
10827class TypeSwitchInfo: public Struct {
10828 public:
10829 DECL_ACCESSORS(types, Object)
10830
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010831 DECLARE_CAST(TypeSwitchInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010832
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010833 // Dispatched behavior.
10834 DECLARE_PRINTER(TypeSwitchInfo)
10835 DECLARE_VERIFIER(TypeSwitchInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010836
10837 static const int kTypesOffset = Struct::kHeaderSize;
10838 static const int kSize = kTypesOffset + kPointerSize;
10839};
10840
10841
Steve Blocka7e24c12009-10-30 11:49:00 +000010842// The DebugInfo class holds additional information for a function being
10843// debugged.
10844class DebugInfo: public Struct {
10845 public:
10846 // The shared function info for the source being debugged.
10847 DECL_ACCESSORS(shared, SharedFunctionInfo)
10848 // Code object for the original code.
10849 DECL_ACCESSORS(original_code, Code)
10850 // Code object for the patched code. This code object is the code object
10851 // currently active for the function.
10852 DECL_ACCESSORS(code, Code)
10853 // Fixed array holding status information for each active break point.
10854 DECL_ACCESSORS(break_points, FixedArray)
10855
10856 // Check if there is a break point at a code position.
10857 bool HasBreakPoint(int code_position);
10858 // Get the break point info object for a code position.
10859 Object* GetBreakPointInfo(int code_position);
10860 // Clear a break point.
10861 static void ClearBreakPoint(Handle<DebugInfo> debug_info,
10862 int code_position,
10863 Handle<Object> break_point_object);
10864 // Set a break point.
10865 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position,
10866 int source_position, int statement_position,
10867 Handle<Object> break_point_object);
10868 // Get the break point objects for a code position.
10869 Object* GetBreakPointObjects(int code_position);
10870 // Find the break point info holding this break point object.
10871 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info,
10872 Handle<Object> break_point_object);
10873 // Get the number of break points for this function.
10874 int GetBreakPointCount();
10875
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010876 DECLARE_CAST(DebugInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010877
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010878 // Dispatched behavior.
10879 DECLARE_PRINTER(DebugInfo)
10880 DECLARE_VERIFIER(DebugInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010881
10882 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize;
10883 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize;
10884 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize;
10885 static const int kActiveBreakPointsCountIndex =
10886 kPatchedCodeIndex + kPointerSize;
10887 static const int kBreakPointsStateIndex =
10888 kActiveBreakPointsCountIndex + kPointerSize;
10889 static const int kSize = kBreakPointsStateIndex + kPointerSize;
10890
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010891 static const int kEstimatedNofBreakPointsInFunction = 16;
10892
Steve Blocka7e24c12009-10-30 11:49:00 +000010893 private:
10894 static const int kNoBreakPointInfo = -1;
10895
10896 // Lookup the index in the break_points array for a code position.
10897 int GetBreakPointInfoIndex(int code_position);
10898
10899 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo);
10900};
10901
10902
10903// The BreakPointInfo class holds information for break points set in a
10904// function. The DebugInfo object holds a BreakPointInfo object for each code
10905// position with one or more break points.
10906class BreakPointInfo: public Struct {
10907 public:
10908 // The position in the code for the break point.
10909 DECL_ACCESSORS(code_position, Smi)
10910 // The position in the source for the break position.
10911 DECL_ACCESSORS(source_position, Smi)
10912 // The position in the source for the last statement before this break
10913 // position.
10914 DECL_ACCESSORS(statement_position, Smi)
10915 // List of related JavaScript break points.
10916 DECL_ACCESSORS(break_point_objects, Object)
10917
10918 // Removes a break point.
10919 static void ClearBreakPoint(Handle<BreakPointInfo> info,
10920 Handle<Object> break_point_object);
10921 // Set a break point.
10922 static void SetBreakPoint(Handle<BreakPointInfo> info,
10923 Handle<Object> break_point_object);
10924 // Check if break point info has this break point object.
10925 static bool HasBreakPointObject(Handle<BreakPointInfo> info,
10926 Handle<Object> break_point_object);
10927 // Get the number of break points for this code position.
10928 int GetBreakPointCount();
10929
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010930 DECLARE_CAST(BreakPointInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010931
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010932 // Dispatched behavior.
10933 DECLARE_PRINTER(BreakPointInfo)
10934 DECLARE_VERIFIER(BreakPointInfo)
Steve Blocka7e24c12009-10-30 11:49:00 +000010935
10936 static const int kCodePositionIndex = Struct::kHeaderSize;
10937 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize;
10938 static const int kStatementPositionIndex =
10939 kSourcePositionIndex + kPointerSize;
10940 static const int kBreakPointObjectsIndex =
10941 kStatementPositionIndex + kPointerSize;
10942 static const int kSize = kBreakPointObjectsIndex + kPointerSize;
10943
10944 private:
10945 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo);
10946};
Steve Blocka7e24c12009-10-30 11:49:00 +000010947
10948
10949#undef DECL_BOOLEAN_ACCESSORS
10950#undef DECL_ACCESSORS
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010951#undef DECLARE_CAST
10952#undef DECLARE_VERIFIER
Steve Blocka7e24c12009-10-30 11:49:00 +000010953
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010954#define VISITOR_SYNCHRONIZATION_TAGS_LIST(V) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010955 V(kStringTable, "string_table", "(Internalized strings)") \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010956 V(kExternalStringsTable, "external_strings_table", "(External strings)") \
10957 V(kStrongRootList, "strong_root_list", "(Strong roots)") \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010958 V(kSmiRootList, "smi_root_list", "(Smi roots)") \
10959 V(kInternalizedString, "internalized_string", "(Internal string)") \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010960 V(kBootstrapper, "bootstrapper", "(Bootstrapper)") \
10961 V(kTop, "top", "(Isolate)") \
10962 V(kRelocatable, "relocatable", "(Relocatable)") \
10963 V(kDebug, "debug", "(Debugger)") \
10964 V(kCompilationCache, "compilationcache", "(Compilation cache)") \
10965 V(kHandleScope, "handlescope", "(Handle scope)") \
10966 V(kBuiltins, "builtins", "(Builtins)") \
10967 V(kGlobalHandles, "globalhandles", "(Global handles)") \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010968 V(kEternalHandles, "eternalhandles", "(Eternal handles)") \
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010969 V(kThreadManager, "threadmanager", "(Thread manager)") \
10970 V(kExtensions, "Extensions", "(Extensions)")
10971
10972class VisitorSynchronization : public AllStatic {
10973 public:
10974#define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item,
10975 enum SyncTag {
10976 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_ENUM)
10977 kNumberOfSyncTags
10978 };
10979#undef DECLARE_ENUM
10980
10981 static const char* const kTags[kNumberOfSyncTags];
10982 static const char* const kTagNames[kNumberOfSyncTags];
10983};
Steve Blocka7e24c12009-10-30 11:49:00 +000010984
10985// Abstract base class for visiting, and optionally modifying, the
10986// pointers contained in Objects. Used in GC and serialization/deserialization.
10987class ObjectVisitor BASE_EMBEDDED {
10988 public:
10989 virtual ~ObjectVisitor() {}
10990
10991 // Visits a contiguous arrays of pointers in the half-open range
10992 // [start, end). Any or all of the values may be modified on return.
10993 virtual void VisitPointers(Object** start, Object** end) = 0;
10994
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010995 // Handy shorthand for visiting a single pointer.
10996 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); }
10997
10998 // Visit weak next_code_link in Code object.
10999 virtual void VisitNextCodeLink(Object** p) { VisitPointers(p, p + 1); }
11000
Steve Blocka7e24c12009-10-30 11:49:00 +000011001 // To allow lazy clearing of inline caches the visitor has
11002 // a rich interface for iterating over Code objects..
11003
11004 // Visits a code target in the instruction stream.
11005 virtual void VisitCodeTarget(RelocInfo* rinfo);
11006
Steve Block791712a2010-08-27 10:21:07 +010011007 // Visits a code entry in a JS function.
11008 virtual void VisitCodeEntry(Address entry_address);
11009
Ben Murdochb0fe1622011-05-05 13:52:32 +010011010 // Visits a global property cell reference in the instruction stream.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011011 virtual void VisitCell(RelocInfo* rinfo);
Ben Murdochb0fe1622011-05-05 13:52:32 +010011012
Steve Blocka7e24c12009-10-30 11:49:00 +000011013 // Visits a runtime entry in the instruction stream.
11014 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}
11015
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011016 // Visits the resource of an one-byte or two-byte string.
11017 virtual void VisitExternalOneByteString(
11018 v8::String::ExternalOneByteStringResource** resource) {}
Steve Blockd0582a62009-12-15 09:54:21 +000011019 virtual void VisitExternalTwoByteString(
11020 v8::String::ExternalStringResource** resource) {}
11021
Steve Blocka7e24c12009-10-30 11:49:00 +000011022 // Visits a debug call target in the instruction stream.
11023 virtual void VisitDebugTarget(RelocInfo* rinfo);
11024
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011025 // Visits the byte sequence in a function's prologue that contains information
11026 // about the code's age.
11027 virtual void VisitCodeAgeSequence(RelocInfo* rinfo);
Steve Blocka7e24c12009-10-30 11:49:00 +000011028
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011029 // Visit pointer embedded into a code object.
11030 virtual void VisitEmbeddedPointer(RelocInfo* rinfo);
11031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011032 // Visits an external reference embedded into a code object.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011033 virtual void VisitExternalReference(RelocInfo* rinfo);
11034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011035 // Visits an external reference. The value may be modified on return.
11036 virtual void VisitExternalReference(Address* p) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000011037
Steve Block44f0eee2011-05-26 01:26:41 +010011038 // Visits a handle that has an embedder-assigned class ID.
11039 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {}
11040
Steve Blocka7e24c12009-10-30 11:49:00 +000011041 // Intended for serialization/deserialization checking: insert, or
11042 // check for the presence of, a tag at this position in the stream.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011043 // Also used for marking up GC roots in heap snapshots.
11044 virtual void Synchronize(VisitorSynchronization::SyncTag tag) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000011045};
11046
11047
Iain Merrick75681382010-08-19 15:07:18 +010011048class StructBodyDescriptor : public
11049 FlexibleBodyDescriptor<HeapObject::kHeaderSize> {
11050 public:
11051 static inline int SizeOf(Map* map, HeapObject* object) {
11052 return map->instance_size();
11053 }
11054};
11055
11056
Steve Blocka7e24c12009-10-30 11:49:00 +000011057// BooleanBit is a helper class for setting and getting a bit in an
11058// integer or Smi.
11059class BooleanBit : public AllStatic {
11060 public:
11061 static inline bool get(Smi* smi, int bit_position) {
11062 return get(smi->value(), bit_position);
11063 }
11064
11065 static inline bool get(int value, int bit_position) {
11066 return (value & (1 << bit_position)) != 0;
11067 }
11068
11069 static inline Smi* set(Smi* smi, int bit_position, bool v) {
11070 return Smi::FromInt(set(smi->value(), bit_position, v));
11071 }
11072
11073 static inline int set(int value, int bit_position, bool v) {
11074 if (v) {
11075 value |= (1 << bit_position);
11076 } else {
11077 value &= ~(1 << bit_position);
11078 }
11079 return value;
11080 }
11081};
11082
11083} } // namespace v8::internal
11084
11085#endif // V8_OBJECTS_H_