blob: bbdefc14a5942122092dd2f82345b4b4d73a2bb6 [file] [log] [blame]
// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_OBJECTS_H_
#define V8_OBJECTS_H_
#include "allocation.h"
#include "assert-scope.h"
#include "builtins.h"
#include "elements-kind.h"
#include "flags.h"
#include "list.h"
#include "property-details.h"
#include "smart-pointers.h"
#include "unicode-inl.h"
#if V8_TARGET_ARCH_ARM
#include "arm/constants-arm.h"
#elif V8_TARGET_ARCH_MIPS
#include "mips/constants-mips.h"
#endif
#include "v8checks.h"
#include "zone.h"
//
// Most object types in the V8 JavaScript are described in this file.
//
// Inheritance hierarchy:
// - MaybeObject (an object or a failure)
// - Failure (immediate for marking failed operation)
// - Object
// - Smi (immediate small integer)
// - HeapObject (superclass for everything allocated in the heap)
// - JSReceiver (suitable for property access)
// - JSObject
// - JSArray
// - JSArrayBuffer
// - JSArrayBufferView
// - JSTypedArray
// - JSDataView
// - JSSet
// - JSMap
// - JSWeakCollection
// - JSWeakMap
// - JSWeakSet
// - JSRegExp
// - JSFunction
// - JSGeneratorObject
// - JSModule
// - GlobalObject
// - JSGlobalObject
// - JSBuiltinsObject
// - JSGlobalProxy
// - JSValue
// - JSDate
// - JSMessageObject
// - JSProxy
// - JSFunctionProxy
// - FixedArrayBase
// - ByteArray
// - FixedArray
// - DescriptorArray
// - HashTable
// - Dictionary
// - StringTable
// - CompilationCacheTable
// - CodeCacheHashTable
// - MapCache
// - Context
// - JSFunctionResultCache
// - ScopeInfo
// - TransitionArray
// - FixedDoubleArray
// - ExternalArray
// - ExternalPixelArray
// - ExternalByteArray
// - ExternalUnsignedByteArray
// - ExternalShortArray
// - ExternalUnsignedShortArray
// - ExternalIntArray
// - ExternalUnsignedIntArray
// - ExternalFloatArray
// - Name
// - String
// - SeqString
// - SeqOneByteString
// - SeqTwoByteString
// - SlicedString
// - ConsString
// - ExternalString
// - ExternalAsciiString
// - ExternalTwoByteString
// - InternalizedString
// - SeqInternalizedString
// - SeqOneByteInternalizedString
// - SeqTwoByteInternalizedString
// - ConsInternalizedString
// - ExternalInternalizedString
// - ExternalAsciiInternalizedString
// - ExternalTwoByteInternalizedString
// - Symbol
// - HeapNumber
// - Cell
// - PropertyCell
// - Code
// - Map
// - Oddball
// - Foreign
// - SharedFunctionInfo
// - Struct
// - Box
// - DeclaredAccessorDescriptor
// - AccessorInfo
// - DeclaredAccessorInfo
// - ExecutableAccessorInfo
// - AccessorPair
// - AccessCheckInfo
// - InterceptorInfo
// - CallHandlerInfo
// - TemplateInfo
// - FunctionTemplateInfo
// - ObjectTemplateInfo
// - Script
// - SignatureInfo
// - TypeSwitchInfo
// - DebugInfo
// - BreakPointInfo
// - CodeCache
//
// Formats of Object*:
// Smi: [31 bit signed int] 0
// HeapObject: [32 bit direct pointer] (4 byte aligned) | 01
// Failure: [30 bit signed int] 11
namespace v8 {
namespace internal {
enum KeyedAccessStoreMode {
STANDARD_STORE,
STORE_TRANSITION_SMI_TO_OBJECT,
STORE_TRANSITION_SMI_TO_DOUBLE,
STORE_TRANSITION_DOUBLE_TO_OBJECT,
STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
STORE_AND_GROW_NO_TRANSITION,
STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
STORE_NO_TRANSITION_HANDLE_COW
};
enum ContextualMode {
NOT_CONTEXTUAL,
CONTEXTUAL
};
static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
STANDARD_STORE;
STATIC_ASSERT(STANDARD_STORE == 0);
STATIC_ASSERT(kGrowICDelta ==
STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
STORE_TRANSITION_SMI_TO_OBJECT);
STATIC_ASSERT(kGrowICDelta ==
STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
STORE_TRANSITION_SMI_TO_DOUBLE);
STATIC_ASSERT(kGrowICDelta ==
STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
STORE_TRANSITION_DOUBLE_TO_OBJECT);
static inline KeyedAccessStoreMode GetGrowStoreMode(
KeyedAccessStoreMode store_mode) {
if (store_mode < STORE_AND_GROW_NO_TRANSITION) {
store_mode = static_cast<KeyedAccessStoreMode>(
static_cast<int>(store_mode) + kGrowICDelta);
}
return store_mode;
}
static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) {
return store_mode > STANDARD_STORE &&
store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT &&
store_mode != STORE_AND_GROW_NO_TRANSITION;
}
static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
KeyedAccessStoreMode store_mode) {
if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
return store_mode;
}
if (store_mode >= STORE_AND_GROW_NO_TRANSITION) {
return STORE_AND_GROW_NO_TRANSITION;
}
return STANDARD_STORE;
}
static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
return store_mode >= STORE_AND_GROW_NO_TRANSITION &&
store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
}
// Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
// Indicates whether a value can be loaded as a constant.
enum StoreMode {
ALLOW_AS_CONSTANT,
FORCE_FIELD
};
// PropertyNormalizationMode is used to specify whether to keep
// inobject properties when normalizing properties of a JSObject.
enum PropertyNormalizationMode {
CLEAR_INOBJECT_PROPERTIES,
KEEP_INOBJECT_PROPERTIES
};
// NormalizedMapSharingMode is used to specify whether a map may be shared
// by different objects with normalized properties.
enum NormalizedMapSharingMode {
UNIQUE_NORMALIZED_MAP,
SHARED_NORMALIZED_MAP
};
// Indicates whether transitions can be added to a source map or not.
enum TransitionFlag {
INSERT_TRANSITION,
OMIT_TRANSITION
};
enum DebugExtraICState {
DEBUG_BREAK,
DEBUG_PREPARE_STEP_IN
};
// Indicates whether the transition is simple: the target map of the transition
// either extends the current map with a new property, or it modifies the
// property that was added last to the current map.
enum SimpleTransitionFlag {
SIMPLE_TRANSITION,
FULL_TRANSITION
};
// Indicates whether we are only interested in the descriptors of a particular
// map, or in all descriptors in the descriptor array.
enum DescriptorFlag {
ALL_DESCRIPTORS,
OWN_DESCRIPTORS
};
// The GC maintains a bit of information, the MarkingParity, which toggles
// from odd to even and back every time marking is completed. Incremental
// marking can visit an object twice during a marking phase, so algorithms that
// that piggy-back on marking can use the parity to ensure that they only
// perform an operation on an object once per marking phase: they record the
// MarkingParity when they visit an object, and only re-visit the object when it
// is marked again and the MarkingParity changes.
enum MarkingParity {
NO_MARKING_PARITY,
ODD_MARKING_PARITY,
EVEN_MARKING_PARITY
};
// ICs store extra state in a Code object. The default extra state is
// kNoExtraICState.
typedef int ExtraICState;
static const ExtraICState kNoExtraICState = 0;
// Instance size sentinel for objects of variable size.
const int kVariableSizeSentinel = 0;
const int kStubMajorKeyBits = 6;
const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
// All Maps have a field instance_type containing a InstanceType.
// It describes the type of the instances.
//
// As an example, a JavaScript object is a heap object and its map
// instance_type is JS_OBJECT_TYPE.
//
// The names of the string instance types are intended to systematically
// mirror their encoding in the instance_type field of the map. The default
// encoding is considered TWO_BYTE. It is not mentioned in the name. ASCII
// encoding is mentioned explicitly in the name. Likewise, the default
// representation is considered sequential. It is not mentioned in the
// name. The other representations (e.g. CONS, EXTERNAL) are explicitly
// mentioned. Finally, the string is either a STRING_TYPE (if it is a normal
// string) or a INTERNALIZED_STRING_TYPE (if it is a internalized string).
//
// NOTE: The following things are some that depend on the string types having
// instance_types that are less than those of all other types:
// HeapObject::Size, HeapObject::IterateBody, the typeof operator, and
// Object::IsString.
//
// NOTE: Everything following JS_VALUE_TYPE is considered a
// JSObject for GC purposes. The first four entries here have typeof
// 'object', whereas JS_FUNCTION_TYPE has typeof 'function'.
#define INSTANCE_TYPE_LIST(V) \
V(STRING_TYPE) \
V(ASCII_STRING_TYPE) \
V(CONS_STRING_TYPE) \
V(CONS_ASCII_STRING_TYPE) \
V(SLICED_STRING_TYPE) \
V(SLICED_ASCII_STRING_TYPE) \
V(EXTERNAL_STRING_TYPE) \
V(EXTERNAL_ASCII_STRING_TYPE) \
V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(SHORT_EXTERNAL_STRING_TYPE) \
V(SHORT_EXTERNAL_ASCII_STRING_TYPE) \
V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \
\
V(INTERNALIZED_STRING_TYPE) \
V(ASCII_INTERNALIZED_STRING_TYPE) \
V(CONS_INTERNALIZED_STRING_TYPE) \
V(CONS_ASCII_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE) \
V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \
\
V(SYMBOL_TYPE) \
\
V(MAP_TYPE) \
V(CODE_TYPE) \
V(ODDBALL_TYPE) \
V(CELL_TYPE) \
V(PROPERTY_CELL_TYPE) \
\
V(HEAP_NUMBER_TYPE) \
V(FOREIGN_TYPE) \
V(BYTE_ARRAY_TYPE) \
V(FREE_SPACE_TYPE) \
/* Note: the order of these external array */ \
/* types is relied upon in */ \
/* Object::IsExternalArray(). */ \
V(EXTERNAL_BYTE_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) \
V(EXTERNAL_SHORT_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) \
V(EXTERNAL_INT_ARRAY_TYPE) \
V(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) \
V(EXTERNAL_FLOAT_ARRAY_TYPE) \
V(EXTERNAL_DOUBLE_ARRAY_TYPE) \
V(EXTERNAL_PIXEL_ARRAY_TYPE) \
V(FILLER_TYPE) \
\
V(DECLARED_ACCESSOR_DESCRIPTOR_TYPE) \
V(DECLARED_ACCESSOR_INFO_TYPE) \
V(EXECUTABLE_ACCESSOR_INFO_TYPE) \
V(ACCESSOR_PAIR_TYPE) \
V(ACCESS_CHECK_INFO_TYPE) \
V(INTERCEPTOR_INFO_TYPE) \
V(CALL_HANDLER_INFO_TYPE) \
V(FUNCTION_TEMPLATE_INFO_TYPE) \
V(OBJECT_TEMPLATE_INFO_TYPE) \
V(SIGNATURE_INFO_TYPE) \
V(TYPE_SWITCH_INFO_TYPE) \
V(ALLOCATION_MEMENTO_TYPE) \
V(ALLOCATION_SITE_TYPE) \
V(SCRIPT_TYPE) \
V(CODE_CACHE_TYPE) \
V(POLYMORPHIC_CODE_CACHE_TYPE) \
V(TYPE_FEEDBACK_INFO_TYPE) \
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
V(BOX_TYPE) \
\
V(FIXED_ARRAY_TYPE) \
V(FIXED_DOUBLE_ARRAY_TYPE) \
V(CONSTANT_POOL_ARRAY_TYPE) \
V(SHARED_FUNCTION_INFO_TYPE) \
\
V(JS_MESSAGE_OBJECT_TYPE) \
\
V(JS_VALUE_TYPE) \
V(JS_DATE_TYPE) \
V(JS_OBJECT_TYPE) \
V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
V(JS_GENERATOR_OBJECT_TYPE) \
V(JS_MODULE_TYPE) \
V(JS_GLOBAL_OBJECT_TYPE) \
V(JS_BUILTINS_OBJECT_TYPE) \
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_ARRAY_TYPE) \
V(JS_ARRAY_BUFFER_TYPE) \
V(JS_TYPED_ARRAY_TYPE) \
V(JS_DATA_VIEW_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_SET_TYPE) \
V(JS_MAP_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_WEAK_SET_TYPE) \
V(JS_REGEXP_TYPE) \
\
V(JS_FUNCTION_TYPE) \
V(JS_FUNCTION_PROXY_TYPE) \
V(DEBUG_INFO_TYPE) \
V(BREAK_POINT_INFO_TYPE)
// Since string types are not consecutive, this macro is used to
// iterate over them.
#define STRING_TYPE_LIST(V) \
V(STRING_TYPE, \
kVariableSizeSentinel, \
string, \
String) \
V(ASCII_STRING_TYPE, \
kVariableSizeSentinel, \
ascii_string, \
AsciiString) \
V(CONS_STRING_TYPE, \
ConsString::kSize, \
cons_string, \
ConsString) \
V(CONS_ASCII_STRING_TYPE, \
ConsString::kSize, \
cons_ascii_string, \
ConsAsciiString) \
V(SLICED_STRING_TYPE, \
SlicedString::kSize, \
sliced_string, \
SlicedString) \
V(SLICED_ASCII_STRING_TYPE, \
SlicedString::kSize, \
sliced_ascii_string, \
SlicedAsciiString) \
V(EXTERNAL_STRING_TYPE, \
ExternalTwoByteString::kSize, \
external_string, \
ExternalString) \
V(EXTERNAL_ASCII_STRING_TYPE, \
ExternalAsciiString::kSize, \
external_ascii_string, \
ExternalAsciiString) \
V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, \
ExternalTwoByteString::kSize, \
external_string_with_one_bytei_data, \
ExternalStringWithOneByteData) \
V(SHORT_EXTERNAL_STRING_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_string, \
ShortExternalString) \
V(SHORT_EXTERNAL_ASCII_STRING_TYPE, \
ExternalAsciiString::kShortSize, \
short_external_ascii_string, \
ShortExternalAsciiString) \
V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_string_with_one_byte_data, \
ShortExternalStringWithOneByteData) \
\
V(INTERNALIZED_STRING_TYPE, \
kVariableSizeSentinel, \
internalized_string, \
InternalizedString) \
V(ASCII_INTERNALIZED_STRING_TYPE, \
kVariableSizeSentinel, \
ascii_internalized_string, \
AsciiInternalizedString) \
V(CONS_INTERNALIZED_STRING_TYPE, \
ConsString::kSize, \
cons_internalized_string, \
ConsInternalizedString) \
V(CONS_ASCII_INTERNALIZED_STRING_TYPE, \
ConsString::kSize, \
cons_ascii_internalized_string, \
ConsAsciiInternalizedString) \
V(EXTERNAL_INTERNALIZED_STRING_TYPE, \
ExternalTwoByteString::kSize, \
external_internalized_string, \
ExternalInternalizedString) \
V(EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE, \
ExternalAsciiString::kSize, \
external_ascii_internalized_string, \
ExternalAsciiInternalizedString) \
V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \
ExternalTwoByteString::kSize, \
external_internalized_string_with_one_byte_data, \
ExternalInternalizedStringWithOneByteData) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_internalized_string, \
ShortExternalInternalizedString) \
V(SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE, \
ExternalAsciiString::kShortSize, \
short_external_ascii_internalized_string, \
ShortExternalAsciiInternalizedString) \
V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \
ExternalTwoByteString::kShortSize, \
short_external_internalized_string_with_one_byte_data, \
ShortExternalInternalizedStringWithOneByteData) \
// A struct is a simple object a set of object-valued fields. Including an
// object type in this causes the compiler to generate most of the boilerplate
// code for the class including allocation and garbage collection routines,
// casts and predicates. All you need to define is the class, methods and
// object verification routines. Easy, no?
//
// Note that for subtle reasons related to the ordering or numerical values of
// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
// manually.
#define STRUCT_LIST_ALL(V) \
V(BOX, Box, box) \
V(DECLARED_ACCESSOR_DESCRIPTOR, \
DeclaredAccessorDescriptor, \
declared_accessor_descriptor) \
V(DECLARED_ACCESSOR_INFO, DeclaredAccessorInfo, declared_accessor_info) \
V(EXECUTABLE_ACCESSOR_INFO, ExecutableAccessorInfo, executable_accessor_info)\
V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \
V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \
V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \
V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \
V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
V(SIGNATURE_INFO, SignatureInfo, signature_info) \
V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
V(SCRIPT, Script, script) \
V(ALLOCATION_SITE, AllocationSite, allocation_site) \
V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \
V(CODE_CACHE, CodeCache, code_cache) \
V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache) \
V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \
V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry)
#ifdef ENABLE_DEBUGGER_SUPPORT
#define STRUCT_LIST_DEBUGGER(V) \
V(DEBUG_INFO, DebugInfo, debug_info) \
V(BREAK_POINT_INFO, BreakPointInfo, break_point_info)
#else
#define STRUCT_LIST_DEBUGGER(V)
#endif
#define STRUCT_LIST(V) \
STRUCT_LIST_ALL(V) \
STRUCT_LIST_DEBUGGER(V)
// We use the full 8 bits of the instance_type field to encode heap object
// instance types. The high-order bit (bit 7) is set if the object is not a
// string, and cleared if it is a string.
const uint32_t kIsNotStringMask = 0x80;
const uint32_t kStringTag = 0x0;
const uint32_t kNotStringTag = 0x80;
// Bit 6 indicates that the object is an internalized string (if set) or not.
// Bit 7 has to be clear as well.
const uint32_t kIsNotInternalizedMask = 0x40;
const uint32_t kNotInternalizedTag = 0x40;
const uint32_t kInternalizedTag = 0x0;
// If bit 7 is clear then bit 2 indicates whether the string consists of
// two-byte characters or one-byte characters.
const uint32_t kStringEncodingMask = 0x4;
const uint32_t kTwoByteStringTag = 0x0;
const uint32_t kOneByteStringTag = 0x4;
// If bit 7 is clear, the low-order 2 bits indicate the representation
// of the string.
const uint32_t kStringRepresentationMask = 0x03;
enum StringRepresentationTag {
kSeqStringTag = 0x0,
kConsStringTag = 0x1,
kExternalStringTag = 0x2,
kSlicedStringTag = 0x3
};
const uint32_t kIsIndirectStringMask = 0x1;
const uint32_t kIsIndirectStringTag = 0x1;
STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0);
STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0);
STATIC_ASSERT(
(kConsStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
STATIC_ASSERT(
(kSlicedStringTag & kIsIndirectStringMask) == kIsIndirectStringTag);
// Use this mask to distinguish between cons and slice only after making
// sure that the string is one of the two (an indirect string).
const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag;
STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask) && kSlicedNotConsMask != 0);
// If bit 7 is clear, then bit 3 indicates whether this two-byte
// string actually contains one byte data.
const uint32_t kOneByteDataHintMask = 0x08;
const uint32_t kOneByteDataHintTag = 0x08;
// If bit 7 is clear and string representation indicates an external string,
// then bit 4 indicates whether the data pointer is cached.
const uint32_t kShortExternalStringMask = 0x10;
const uint32_t kShortExternalStringTag = 0x10;
// A ConsString with an empty string as the right side is a candidate
// for being shortcut by the garbage collector unless it is internalized.
// It's not common to have non-flat internalized strings, so we do not
// shortcut them thereby avoiding turning internalized strings into strings.
// See heap.cc and mark-compact.cc.
const uint32_t kShortcutTypeMask =
kIsNotStringMask |
kIsNotInternalizedMask |
kStringRepresentationMask;
const uint32_t kShortcutTypeTag = kConsStringTag | kNotInternalizedTag;
enum InstanceType {
// String types.
INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kSeqStringTag
| kInternalizedTag,
ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag | kSeqStringTag
| kInternalizedTag,
CONS_INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kConsStringTag
| kInternalizedTag,
CONS_ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag | kConsStringTag
| kInternalizedTag,
EXTERNAL_INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kExternalStringTag
| kInternalizedTag,
EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag
| kExternalStringTag | kInternalizedTag,
EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
EXTERNAL_INTERNALIZED_STRING_TYPE | kOneByteDataHintTag
| kInternalizedTag,
SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE =
EXTERNAL_INTERNALIZED_STRING_TYPE | kShortExternalStringTag
| kInternalizedTag,
SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE =
EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kShortExternalStringTag
| kInternalizedTag,
SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
| kShortExternalStringTag | kInternalizedTag,
STRING_TYPE = INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
ASCII_STRING_TYPE = ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
CONS_STRING_TYPE = CONS_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
CONS_ASCII_STRING_TYPE =
CONS_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
SLICED_STRING_TYPE =
kTwoByteStringTag | kSlicedStringTag | kNotInternalizedTag,
SLICED_ASCII_STRING_TYPE =
kOneByteStringTag | kSlicedStringTag | kNotInternalizedTag,
EXTERNAL_STRING_TYPE =
EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
EXTERNAL_ASCII_STRING_TYPE =
EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
| kNotInternalizedTag,
SHORT_EXTERNAL_STRING_TYPE =
SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
SHORT_EXTERNAL_ASCII_STRING_TYPE =
SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
| kNotInternalizedTag,
// Non-string names
SYMBOL_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE
// Objects allocated in their own spaces (never in new space).
MAP_TYPE,
CODE_TYPE,
ODDBALL_TYPE,
CELL_TYPE,
PROPERTY_CELL_TYPE,
// "Data", objects that cannot contain non-map-word pointers to heap
// objects.
HEAP_NUMBER_TYPE,
FOREIGN_TYPE,
BYTE_ARRAY_TYPE,
FREE_SPACE_TYPE,
EXTERNAL_BYTE_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE
EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE,
EXTERNAL_SHORT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE,
EXTERNAL_INT_ARRAY_TYPE,
EXTERNAL_UNSIGNED_INT_ARRAY_TYPE,
EXTERNAL_FLOAT_ARRAY_TYPE,
EXTERNAL_DOUBLE_ARRAY_TYPE,
EXTERNAL_PIXEL_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE
FIXED_DOUBLE_ARRAY_TYPE,
CONSTANT_POOL_ARRAY_TYPE,
FILLER_TYPE, // LAST_DATA_TYPE
// Structs.
DECLARED_ACCESSOR_DESCRIPTOR_TYPE,
DECLARED_ACCESSOR_INFO_TYPE,
EXECUTABLE_ACCESSOR_INFO_TYPE,
ACCESSOR_PAIR_TYPE,
ACCESS_CHECK_INFO_TYPE,
INTERCEPTOR_INFO_TYPE,
CALL_HANDLER_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
OBJECT_TEMPLATE_INFO_TYPE,
SIGNATURE_INFO_TYPE,
TYPE_SWITCH_INFO_TYPE,
ALLOCATION_SITE_TYPE,
ALLOCATION_MEMENTO_TYPE,
SCRIPT_TYPE,
CODE_CACHE_TYPE,
POLYMORPHIC_CODE_CACHE_TYPE,
TYPE_FEEDBACK_INFO_TYPE,
ALIASED_ARGUMENTS_ENTRY_TYPE,
BOX_TYPE,
// The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
// is defined. However as include/v8.h contain some of the instance type
// constants always having them avoids them getting different numbers
// depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
DEBUG_INFO_TYPE,
BREAK_POINT_INFO_TYPE,
FIXED_ARRAY_TYPE,
SHARED_FUNCTION_INFO_TYPE,
JS_MESSAGE_OBJECT_TYPE,
// All the following types are subtypes of JSReceiver, which corresponds to
// objects in the JS sense. The first and the last type in this range are
// the two forms of function. This organization enables using the same
// compares for checking the JS_RECEIVER/SPEC_OBJECT range and the
// NONCALLABLE_JS_OBJECT range.
JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE
JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE
JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE
JS_DATE_TYPE,
JS_OBJECT_TYPE,
JS_CONTEXT_EXTENSION_OBJECT_TYPE,
JS_GENERATOR_OBJECT_TYPE,
JS_MODULE_TYPE,
JS_GLOBAL_OBJECT_TYPE,
JS_BUILTINS_OBJECT_TYPE,
JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE,
JS_ARRAY_BUFFER_TYPE,
JS_TYPED_ARRAY_TYPE,
JS_DATA_VIEW_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
JS_WEAK_MAP_TYPE,
JS_WEAK_SET_TYPE,
JS_REGEXP_TYPE,
JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
// Pseudo-types
FIRST_TYPE = 0x0,
LAST_TYPE = JS_FUNCTION_TYPE,
FIRST_NAME_TYPE = FIRST_TYPE,
LAST_NAME_TYPE = SYMBOL_TYPE,
FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
// Boundaries for testing for an external array.
FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_BYTE_ARRAY_TYPE,
LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_PIXEL_ARRAY_TYPE,
// Boundary for promotion to old data space/old pointer space.
LAST_DATA_TYPE = FILLER_TYPE,
// Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy).
// Note that there is no range for JSObject or JSProxy, since their subtypes
// are not continuous in this enum! The enum ranges instead reflect the
// external class names, where proxies are treated as either ordinary objects,
// or functions.
FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE,
LAST_JS_RECEIVER_TYPE = LAST_TYPE,
// Boundaries for testing the types represented as JSObject
FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE,
LAST_JS_OBJECT_TYPE = LAST_TYPE,
// Boundaries for testing the types represented as JSProxy
FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE,
LAST_JS_PROXY_TYPE = JS_PROXY_TYPE,
// Boundaries for testing whether the type is a JavaScript object.
FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE,
LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE,
// Boundaries for testing the types for which typeof is "object".
FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE,
LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE,
// Note that the types for which typeof is "function" are not continuous.
// Define this so that we can put assertions on discrete checks.
NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2
};
const int kExternalArrayTypeCount =
LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1;
STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
STATIC_CHECK(ODDBALL_TYPE == Internals::kOddballType);
STATIC_CHECK(FOREIGN_TYPE == Internals::kForeignType);
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(FAST_ELEMENTS_SUB_TYPE) \
V(DICTIONARY_ELEMENTS_SUB_TYPE) \
V(FAST_PROPERTIES_SUB_TYPE) \
V(DICTIONARY_PROPERTIES_SUB_TYPE) \
V(MAP_CODE_CACHE_SUB_TYPE) \
V(SCOPE_INFO_SUB_TYPE) \
V(STRING_TABLE_SUB_TYPE) \
V(DESCRIPTOR_ARRAY_SUB_TYPE) \
V(TRANSITION_ARRAY_SUB_TYPE)
enum FixedArraySubInstanceType {
#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
LAST_FIXED_ARRAY_SUB_TYPE = TRANSITION_ARRAY_SUB_TYPE
};
enum CompareResult {
LESS = -1,
EQUAL = 0,
GREATER = 1,
NOT_EQUAL = GREATER
};
#define DECL_BOOLEAN_ACCESSORS(name) \
inline bool name(); \
inline void set_##name(bool value); \
#define DECL_ACCESSORS(name, type) \
inline type* name(); \
inline void set_##name(type* value, \
WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
class AccessorPair;
class AllocationSite;
class AllocationSiteCreationContext;
class AllocationSiteUsageContext;
class DictionaryElementsAccessor;
class ElementsAccessor;
class Failure;
class FixedArrayBase;
class ObjectVisitor;
class StringStream;
class Type;
// A template-ized version of the IsXXX functions.
template <class C> inline bool Is(Object* obj);
#ifdef VERIFY_HEAP
#define DECLARE_VERIFIER(Name) void Name##Verify();
#else
#define DECLARE_VERIFIER(Name)
#endif
#ifdef OBJECT_PRINT
#define DECLARE_PRINTER(Name) void Name##Print(FILE* out = stdout);
#else
#define DECLARE_PRINTER(Name)
#endif
class MaybeObject BASE_EMBEDDED {
public:
inline bool IsFailure();
inline bool IsRetryAfterGC();
inline bool IsOutOfMemory();
inline bool IsException();
INLINE(bool IsTheHole());
INLINE(bool IsUninitialized());
inline bool ToObject(Object** obj) {
if (IsFailure()) return false;
*obj = reinterpret_cast<Object*>(this);
return true;
}
inline Failure* ToFailureUnchecked() {
ASSERT(IsFailure());
return reinterpret_cast<Failure*>(this);
}
inline Object* ToObjectUnchecked() {
// TODO(jkummerow): Turn this back into an ASSERT when we can be certain
// that it never fires in Release mode in the wild.
CHECK(!IsFailure());
return reinterpret_cast<Object*>(this);
}
inline Object* ToObjectChecked() {
CHECK(!IsFailure());
return reinterpret_cast<Object*>(this);
}
template<typename T>
inline bool To(T** obj) {
if (IsFailure()) return false;
*obj = T::cast(reinterpret_cast<Object*>(this));
return true;
}
template<typename T>
inline bool ToHandle(Handle<T>* obj, Isolate* isolate) {
if (IsFailure()) return false;
*obj = handle(T::cast(reinterpret_cast<Object*>(this)), isolate);
return true;
}
#ifdef OBJECT_PRINT
// Prints this object with details.
void Print();
void Print(FILE* out);
void PrintLn();
void PrintLn(FILE* out);
#endif
#ifdef VERIFY_HEAP
// Verifies the object.
void Verify();
#endif
};
#define OBJECT_TYPE_LIST(V) \
V(Smi) \
V(HeapObject) \
V(Number) \
#define HEAP_OBJECT_TYPE_LIST(V) \
V(HeapNumber) \
V(Name) \
V(UniqueName) \
V(String) \
V(SeqString) \
V(ExternalString) \
V(ConsString) \
V(SlicedString) \
V(ExternalTwoByteString) \
V(ExternalAsciiString) \
V(SeqTwoByteString) \
V(SeqOneByteString) \
V(InternalizedString) \
V(Symbol) \
\
V(ExternalArray) \
V(ExternalByteArray) \
V(ExternalUnsignedByteArray) \
V(ExternalShortArray) \
V(ExternalUnsignedShortArray) \
V(ExternalIntArray) \
V(ExternalUnsignedIntArray) \
V(ExternalFloatArray) \
V(ExternalDoubleArray) \
V(ExternalPixelArray) \
V(ByteArray) \
V(FreeSpace) \
V(JSReceiver) \
V(JSObject) \
V(JSContextExtensionObject) \
V(JSGeneratorObject) \
V(JSModule) \
V(Map) \
V(DescriptorArray) \
V(TransitionArray) \
V(DeoptimizationInputData) \
V(DeoptimizationOutputData) \
V(DependentCode) \
V(TypeFeedbackCells) \
V(FixedArray) \
V(FixedDoubleArray) \
V(ConstantPoolArray) \
V(Context) \
V(NativeContext) \
V(ScopeInfo) \
V(JSFunction) \
V(Code) \
V(Oddball) \
V(SharedFunctionInfo) \
V(JSValue) \
V(JSDate) \
V(JSMessageObject) \
V(StringWrapper) \
V(Foreign) \
V(Boolean) \
V(JSArray) \
V(JSArrayBuffer) \
V(JSArrayBufferView) \
V(JSTypedArray) \
V(JSDataView) \
V(JSProxy) \
V(JSFunctionProxy) \
V(JSSet) \
V(JSMap) \
V(JSWeakCollection) \
V(JSWeakMap) \
V(JSWeakSet) \
V(JSRegExp) \
V(HashTable) \
V(Dictionary) \
V(StringTable) \
V(JSFunctionResultCache) \
V(NormalizedMapCache) \
V(CompilationCacheTable) \
V(CodeCacheHashTable) \
V(PolymorphicCodeCacheHashTable) \
V(MapCache) \
V(Primitive) \
V(GlobalObject) \
V(JSGlobalObject) \
V(JSBuiltinsObject) \
V(JSGlobalProxy) \
V(UndetectableObject) \
V(AccessCheckNeeded) \
V(Cell) \
V(PropertyCell) \
V(ObjectHashTable) \
V(WeakHashTable)
#define ERROR_MESSAGES_LIST(V) \
V(kNoReason, "no reason") \
\
V(k32BitValueInRegisterIsNotZeroExtended, \
"32 bit value in register is not zero-extended") \
V(kAlignmentMarkerExpected, "alignment marker expected") \
V(kAllocationIsNotDoubleAligned, "Allocation is not double aligned") \
V(kAPICallReturnedInvalidObject, "API call returned invalid object") \
V(kArgumentsObjectValueInATestContext, \
"arguments object value in a test context") \
V(kArrayBoilerplateCreationFailed, "array boilerplate creation failed") \
V(kArrayIndexConstantValueTooBig, "array index constant value too big") \
V(kAssignmentToArguments, "assignment to arguments") \
V(kAssignmentToLetVariableBeforeInitialization, \
"assignment to let variable before initialization") \
V(kAssignmentToLOOKUPVariable, "assignment to LOOKUP variable") \
V(kAssignmentToParameterFunctionUsesArgumentsObject, \
"assignment to parameter, function uses arguments object") \
V(kAssignmentToParameterInArgumentsObject, \
"assignment to parameter in arguments object") \
V(kAttemptToUseUndefinedCache, "Attempt to use undefined cache") \
V(kBadValueContextForArgumentsObjectValue, \
"bad value context for arguments object value") \
V(kBadValueContextForArgumentsValue, \
"bad value context for arguments value") \
V(kBailedOutDueToDependencyChange, "bailed out due to dependency change") \
V(kBailoutWasNotPrepared, "bailout was not prepared") \
V(kBinaryStubGenerateFloatingPointCode, \
"BinaryStub_GenerateFloatingPointCode") \
V(kBothRegistersWereSmisInSelectNonSmi, \
"Both registers were smis in SelectNonSmi") \
V(kCallToAJavaScriptRuntimeFunction, \
"call to a JavaScript runtime function") \
V(kCannotTranslatePositionInChangedArea, \
"Cannot translate position in changed area") \
V(kCodeGenerationFailed, "code generation failed") \
V(kCodeObjectNotProperlyPatched, "code object not properly patched") \
V(kCompoundAssignmentToLookupSlot, "compound assignment to lookup slot") \
V(kContextAllocatedArguments, "context-allocated arguments") \
V(kDebuggerIsActive, "debugger is active") \
V(kDebuggerStatement, "DebuggerStatement") \
V(kDeclarationInCatchContext, "Declaration in catch context") \
V(kDeclarationInWithContext, "Declaration in with context") \
V(kDefaultNaNModeNotSet, "Default NaN mode not set") \
V(kDeleteWithGlobalVariable, "delete with global variable") \
V(kDeleteWithNonGlobalVariable, "delete with non-global variable") \
V(kDestinationOfCopyNotAligned, "Destination of copy not aligned") \
V(kDontDeleteCellsCannotContainTheHole, \
"DontDelete cells can't contain the hole") \
V(kDoPushArgumentNotImplementedForDoubleType, \
"DoPushArgument not implemented for double type") \
V(kEmitLoadRegisterUnsupportedDoubleImmediate, \
"EmitLoadRegister: Unsupported double immediate") \
V(kEval, "eval") \
V(kExpected0AsASmiSentinel, "Expected 0 as a Smi sentinel") \
V(kExpectedAlignmentMarker, "expected alignment marker") \
V(kExpectedAllocationSiteInCell, \
"Expected AllocationSite in property cell") \
V(kExpectedPropertyCellInRegisterA2, \
"Expected property cell in register a2") \
V(kExpectedPropertyCellInRegisterEbx, \
"Expected property cell in register ebx") \
V(kExpectedPropertyCellInRegisterRbx, \
"Expected property cell in register rbx") \
V(kExpectingAlignmentForCopyBytes, \
"Expecting alignment for CopyBytes") \
V(kExportDeclaration, "Export declaration") \
V(kExternalStringExpectedButNotFound, \
"external string expected, but not found") \
V(kFailedBailedOutLastTime, "failed/bailed out last time") \
V(kForInStatementIsNotFastCase, "ForInStatement is not fast case") \
V(kForInStatementOptimizationIsDisabled, \
"ForInStatement optimization is disabled") \
V(kForInStatementWithNonLocalEachVariable, \
"ForInStatement with non-local each variable") \
V(kForOfStatement, "ForOfStatement") \
V(kFrameIsExpectedToBeAligned, "frame is expected to be aligned") \
V(kFunctionCallsEval, "function calls eval") \
V(kFunctionIsAGenerator, "function is a generator") \
V(kFunctionWithIllegalRedeclaration, "function with illegal redeclaration") \
V(kGeneratedCodeIsTooLarge, "Generated code is too large") \
V(kGeneratorFailedToResume, "Generator failed to resume") \
V(kGenerator, "generator") \
V(kGlobalFunctionsMustHaveInitialMap, \
"Global functions must have initial map") \
V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered") \
V(kImportDeclaration, "Import declaration") \
V(kImproperObjectOnPrototypeChainForStore, \
"improper object on prototype chain for store") \
V(kIndexIsNegative, "Index is negative") \
V(kIndexIsTooLarge, "Index is too large") \
V(kInlinedRuntimeFunctionClassOf, "inlined runtime function: ClassOf") \
V(kInlinedRuntimeFunctionFastAsciiArrayJoin, \
"inlined runtime function: FastAsciiArrayJoin") \
V(kInlinedRuntimeFunctionGeneratorNext, \
"inlined runtime function: GeneratorNext") \
V(kInlinedRuntimeFunctionGeneratorThrow, \
"inlined runtime function: GeneratorThrow") \
V(kInlinedRuntimeFunctionGetFromCache, \
"inlined runtime function: GetFromCache") \
V(kInlinedRuntimeFunctionIsNonNegativeSmi, \
"inlined runtime function: IsNonNegativeSmi") \
V(kInlinedRuntimeFunctionIsRegExpEquivalent, \
"inlined runtime function: IsRegExpEquivalent") \
V(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf, \
"inlined runtime function: IsStringWrapperSafeForDefaultValueOf") \
V(kInliningBailedOut, "inlining bailed out") \
V(kInputGPRIsExpectedToHaveUpper32Cleared, \
"input GPR is expected to have upper32 cleared") \
V(kInstanceofStubUnexpectedCallSiteCacheCheck, \
"InstanceofStub unexpected call site cache (check)") \
V(kInstanceofStubUnexpectedCallSiteCacheCmp1, \
"InstanceofStub unexpected call site cache (cmp 1)") \
V(kInstanceofStubUnexpectedCallSiteCacheCmp2, \
"InstanceofStub unexpected call site cache (cmp 2)") \
V(kInstanceofStubUnexpectedCallSiteCacheMov, \
"InstanceofStub unexpected call site cache (mov)") \
V(kInteger32ToSmiFieldWritingToNonSmiLocation, \
"Integer32ToSmiField writing to non-smi location") \
V(kInvalidCaptureReferenced, "Invalid capture referenced") \
V(kInvalidElementsKindForInternalArrayOrInternalPackedArray, \
"Invalid ElementsKind for InternalArray or InternalPackedArray") \
V(kInvalidHandleScopeLevel, "Invalid HandleScope level") \
V(kInvalidLeftHandSideInAssignment, "invalid left-hand side in assignment") \
V(kInvalidLhsInCompoundAssignment, "invalid lhs in compound assignment") \
V(kInvalidLhsInCountOperation, "invalid lhs in count operation") \
V(kInvalidMinLength, "Invalid min_length") \
V(kJSGlobalObjectNativeContextShouldBeANativeContext, \
"JSGlobalObject::native_context should be a native context") \
V(kJSGlobalProxyContextShouldNotBeNull, \
"JSGlobalProxy::context() should not be null") \
V(kJSObjectWithFastElementsMapHasSlowElements, \
"JSObject with fast elements map has slow elements") \
V(kLetBindingReInitialization, "Let binding re-initialization") \
V(kLiveBytesCountOverflowChunkSize, "Live Bytes Count overflow chunk size") \
V(kLiveEditFrameDroppingIsNotSupportedOnArm, \
"LiveEdit frame dropping is not supported on arm") \
V(kLiveEditFrameDroppingIsNotSupportedOnMips, \
"LiveEdit frame dropping is not supported on mips") \
V(kLiveEdit, "LiveEdit") \
V(kLookupVariableInCountOperation, \
"lookup variable in count operation") \
V(kMapIsNoLongerInEax, "Map is no longer in eax") \
V(kModuleDeclaration, "Module declaration") \
V(kModuleLiteral, "Module literal") \
V(kModulePath, "Module path") \
V(kModuleStatement, "Module statement") \
V(kModuleVariable, "Module variable") \
V(kModuleUrl, "Module url") \
V(kNativeFunctionLiteral, "Native function literal") \
V(kNoCasesLeft, "no cases left") \
V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \
"No empty arrays here in EmitFastAsciiArrayJoin") \
V(kNonInitializerAssignmentToConst, \
"non-initializer assignment to const") \
V(kNonSmiIndex, "Non-smi index") \
V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \
V(kNonSmiValue, "Non-smi value") \
V(kNonObject, "Non-object value") \
V(kNotEnoughVirtualRegistersForValues, \
"not enough virtual registers for values") \
V(kNotEnoughSpillSlotsForOsr, \
"not enough spill slots for OSR") \
V(kNotEnoughVirtualRegistersRegalloc, \
"not enough virtual registers (regalloc)") \
V(kObjectFoundInSmiOnlyArray, "object found in smi-only array") \
V(kObjectLiteralWithComplexProperty, \
"Object literal with complex property") \
V(kOddballInStringTableIsNotUndefinedOrTheHole, \
"oddball in string table is not undefined or the hole") \
V(kOperandIsASmiAndNotAName, "Operand is a smi and not a name") \
V(kOperandIsASmiAndNotAString, "Operand is a smi and not a string") \
V(kOperandIsASmi, "Operand is a smi") \
V(kOperandIsNotAName, "Operand is not a name") \
V(kOperandIsNotANumber, "Operand is not a number") \
V(kOperandIsNotASmi, "Operand is not a smi") \
V(kOperandIsNotAString, "Operand is not a string") \
V(kOperandIsNotSmi, "Operand is not smi") \
V(kOperandNotANumber, "Operand not a number") \
V(kOptimizedTooManyTimes, "optimized too many times") \
V(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister, \
"Out of virtual registers while trying to allocate temp register") \
V(kParseScopeError, "parse/scope error") \
V(kPossibleDirectCallToEval, "possible direct call to eval") \
V(kPropertyAllocationCountFailed, "Property allocation count failed") \
V(kReceivedInvalidReturnAddress, "Received invalid return address") \
V(kReferenceToAVariableWhichRequiresDynamicLookup, \
"reference to a variable which requires dynamic lookup") \
V(kReferenceToGlobalLexicalVariable, \
"reference to global lexical variable") \
V(kReferenceToUninitializedVariable, "reference to uninitialized variable") \
V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \
V(kRegisterWasClobbered, "register was clobbered") \
V(kScopedBlock, "ScopedBlock") \
V(kSmiAdditionOverflow, "Smi addition overflow") \
V(kSmiSubtractionOverflow, "Smi subtraction overflow") \
V(kStackFrameTypesMustMatch, "stack frame types must match") \
V(kSwitchStatementMixedOrNonLiteralSwitchLabels, \
"SwitchStatement: mixed or non-literal switch labels") \
V(kSwitchStatementTooManyClauses, "SwitchStatement: too many clauses") \
V(kTheInstructionShouldBeALui, "The instruction should be a lui") \
V(kTheInstructionShouldBeAnOri, "The instruction should be an ori") \
V(kTheInstructionToPatchShouldBeALoadFromPc, \
"The instruction to patch should be a load from pc") \
V(kTheInstructionToPatchShouldBeALui, \
"The instruction to patch should be a lui") \
V(kTheInstructionToPatchShouldBeAnOri, \
"The instruction to patch should be an ori") \
V(kTooManyParametersLocals, "too many parameters/locals") \
V(kTooManyParameters, "too many parameters") \
V(kTooManySpillSlotsNeededForOSR, "Too many spill slots needed for OSR") \
V(kToOperandIsDoubleRegisterUnimplemented, \
"ToOperand IsDoubleRegister unimplemented") \
V(kToOperandUnsupportedDoubleImmediate, \
"ToOperand Unsupported double immediate") \
V(kTryCatchStatement, "TryCatchStatement") \
V(kTryFinallyStatement, "TryFinallyStatement") \
V(kUnableToEncodeValueAsSmi, "Unable to encode value as smi") \
V(kUnalignedAllocationInNewSpace, "Unaligned allocation in new space") \
V(kUndefinedValueNotLoaded, "Undefined value not loaded") \
V(kUndoAllocationOfNonAllocatedMemory, \
"Undo allocation of non allocated memory") \
V(kUnexpectedAllocationTop, "Unexpected allocation top") \
V(kUnexpectedElementsKindInArrayConstructor, \
"Unexpected ElementsKind in array constructor") \
V(kUnexpectedFallthroughFromCharCodeAtSlowCase, \
"Unexpected fallthrough from CharCodeAt slow case") \
V(kUnexpectedFallthroughFromCharFromCodeSlowCase, \
"Unexpected fallthrough from CharFromCode slow case") \
V(kUnexpectedFallThroughFromStringComparison, \
"Unexpected fall-through from string comparison") \
V(kUnexpectedFallThroughInBinaryStubGenerateFloatingPointCode, \
"Unexpected fall-through in BinaryStub_GenerateFloatingPointCode") \
V(kUnexpectedFallthroughToCharCodeAtSlowCase, \
"Unexpected fallthrough to CharCodeAt slow case") \
V(kUnexpectedFallthroughToCharFromCodeSlowCase, \
"Unexpected fallthrough to CharFromCode slow case") \
V(kUnexpectedFPUStackDepthAfterInstruction, \
"Unexpected FPU stack depth after instruction") \
V(kUnexpectedInitialMapForArrayFunction1, \
"Unexpected initial map for Array function (1)") \
V(kUnexpectedInitialMapForArrayFunction2, \
"Unexpected initial map for Array function (2)") \
V(kUnexpectedInitialMapForArrayFunction, \
"Unexpected initial map for Array function") \
V(kUnexpectedInitialMapForInternalArrayFunction, \
"Unexpected initial map for InternalArray function") \
V(kUnexpectedLevelAfterReturnFromApiCall, \
"Unexpected level after return from api call") \
V(kUnexpectedNumberOfPreAllocatedPropertyFields, \
"Unexpected number of pre-allocated property fields") \
V(kUnexpectedStringFunction, "Unexpected String function") \
V(kUnexpectedStringType, "Unexpected string type") \
V(kUnexpectedStringWrapperInstanceSize, \
"Unexpected string wrapper instance size") \
V(kUnexpectedTypeForRegExpDataFixedArrayExpected, \
"Unexpected type for RegExp data, FixedArray expected") \
V(kUnexpectedUnusedPropertiesOfStringWrapper, \
"Unexpected unused properties of string wrapper") \
V(kUninitializedKSmiConstantRegister, "Uninitialized kSmiConstantRegister") \
V(kUnknown, "unknown") \
V(kUnsupportedConstCompoundAssignment, \
"unsupported const compound assignment") \
V(kUnsupportedCountOperationWithConst, \
"unsupported count operation with const") \
V(kUnsupportedDoubleImmediate, "unsupported double immediate") \
V(kUnsupportedLetCompoundAssignment, "unsupported let compound assignment") \
V(kUnsupportedLookupSlotInDeclaration, \
"unsupported lookup slot in declaration") \
V(kUnsupportedNonPrimitiveCompare, "Unsupported non-primitive compare") \
V(kUnsupportedPhiUseOfArguments, "Unsupported phi use of arguments") \
V(kUnsupportedPhiUseOfConstVariable, \
"Unsupported phi use of const variable") \
V(kUnsupportedTaggedImmediate, "unsupported tagged immediate") \
V(kVariableResolvedToWithContext, "Variable resolved to with context") \
V(kWeShouldNotHaveAnEmptyLexicalContext, \
"we should not have an empty lexical context") \
V(kWithStatement, "WithStatement") \
V(kWrongAddressOrValuePassedToRecordWrite, \
"Wrong address or value passed to RecordWrite") \
V(kYield, "Yield")
#define ERROR_MESSAGES_CONSTANTS(C, T) C,
enum BailoutReason {
ERROR_MESSAGES_LIST(ERROR_MESSAGES_CONSTANTS)
kLastErrorMessage
};
#undef ERROR_MESSAGES_CONSTANTS
const char* GetBailoutReason(BailoutReason reason);
// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
// Since Smi and Failure are subclasses of Object no
// data members can be present in Object.
class Object : public MaybeObject {
public:
// Type testing.
bool IsObject() { return true; }
#define IS_TYPE_FUNCTION_DECL(type_) inline bool Is##type_();
OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
inline bool IsFixedArrayBase();
inline bool IsExternal();
inline bool IsAccessorInfo();
inline bool IsStruct();
#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
#undef DECLARE_STRUCT_PREDICATE
INLINE(bool IsSpecObject());
INLINE(bool IsSpecFunction());
bool IsCallable();
// Oddball testing.
INLINE(bool IsUndefined());
INLINE(bool IsNull());
INLINE(bool IsTheHole()); // Shadows MaybeObject's implementation.
INLINE(bool IsUninitialized());
INLINE(bool IsTrue());
INLINE(bool IsFalse());
inline bool IsArgumentsMarker();
inline bool NonFailureIsHeapObject();
// Filler objects (fillers and free space objects).
inline bool IsFiller();
// Extract the number.
inline double Number();
inline bool IsNaN();
bool ToInt32(int32_t* value);
bool ToUint32(uint32_t* value);
// Indicates whether OptimalRepresentation can do its work, or whether it
// always has to return Representation::Tagged().
enum ValueType {
OPTIMAL_REPRESENTATION,
FORCE_TAGGED
};
inline Representation OptimalRepresentation(
ValueType type = OPTIMAL_REPRESENTATION) {
if (!FLAG_track_fields) return Representation::Tagged();
if (type == FORCE_TAGGED) return Representation::Tagged();
if (IsSmi()) {
return Representation::Smi();
} else if (FLAG_track_double_fields && IsHeapNumber()) {
return Representation::Double();
} else if (FLAG_track_computed_fields && IsUninitialized()) {
return Representation::None();
} else if (FLAG_track_heap_object_fields) {
ASSERT(IsHeapObject());
return Representation::HeapObject();
} else {
return Representation::Tagged();
}
}
inline bool FitsRepresentation(Representation representation) {
if (FLAG_track_fields && representation.IsNone()) {
return false;
} else if (FLAG_track_fields && representation.IsSmi()) {
return IsSmi();
} else if (FLAG_track_double_fields && representation.IsDouble()) {
return IsNumber();
} else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
return IsHeapObject();
}
return true;
}
inline MaybeObject* AllocateNewStorageFor(Heap* heap,
Representation representation);
// Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements.
inline bool HasValidElements();
inline bool HasSpecificClassOf(String* name);
MUST_USE_RESULT MaybeObject* ToObject(Isolate* isolate); // ECMA-262 9.9.
bool BooleanValue(); // ECMA-262 9.2.
// Convert to a JSObject if needed.
// native_context is used when creating wrapper object.
MUST_USE_RESULT MaybeObject* ToObject(Context* native_context);
// Converts this to a Smi if possible.
// Failure is returned otherwise.
MUST_USE_RESULT inline MaybeObject* ToSmi();
void Lookup(Name* name, LookupResult* result);
// Property access.
MUST_USE_RESULT inline MaybeObject* GetProperty(Name* key);
MUST_USE_RESULT inline MaybeObject* GetProperty(
Name* key,
PropertyAttributes* attributes);
// TODO(yangguo): this should eventually replace the non-handlified version.
static Handle<Object> GetPropertyWithReceiver(Handle<Object> object,
Handle<Object> receiver,
Handle<Name> name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
Object* receiver,
Name* key,
PropertyAttributes* attributes);
static Handle<Object> GetProperty(Handle<Object> object,
Handle<Name> key);
static Handle<Object> GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
Handle<Name> key,
PropertyAttributes* attributes);
MUST_USE_RESULT static MaybeObject* GetPropertyOrFail(
Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
Handle<Name> key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
LookupResult* result,
Name* key,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
JSReceiver* getter);
static Handle<Object> GetElement(Isolate* isolate,
Handle<Object> object,
uint32_t index);
MUST_USE_RESULT inline MaybeObject* GetElement(Isolate* isolate,
uint32_t index);
// For use when we know that no exception can be thrown.
inline Object* GetElementNoExceptionThrown(Isolate* isolate, uint32_t index);
MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Isolate* isolate,
Object* receiver,
uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype(Isolate* isolate);
Map* GetMarkerMap(Isolate* isolate);
// Returns the permanent hash code associated with this object. May return
// undefined if not yet created.
Object* GetHash();
// Returns the permanent hash code associated with this object depending on
// the actual object type. May create and store a hash code if needed and none
// exists.
// TODO(rafaelw): Remove isolate parameter when objects.cc is fully
// handlified.
static Handle<Object> GetOrCreateHash(Handle<Object> object,
Isolate* isolate);
// Checks whether this object has the same value as the given one. This
// function is implemented according to ES5, section 9.12 and can be used
// to implement the Harmony "egal" function.
bool SameValue(Object* other);
// Tries to convert an object to an array index. Returns true and sets
// the output parameter if it succeeds.
inline bool ToArrayIndex(uint32_t* index);
// Returns true if this is a JSValue containing a string and the index is
// < the length of the string. Used to implement [] on strings.
inline bool IsStringObjectWithCharacterAt(uint32_t index);
#ifdef VERIFY_HEAP
// Verify a pointer is a valid object pointer.
static void VerifyPointer(Object* p);
#endif
inline void VerifyApiCallResultType();
// Prints this object without details.
void ShortPrint(FILE* out = stdout);
// Prints this object without details to a message accumulator.
void ShortPrint(StringStream* accumulator);
// Casting: This cast is only needed to satisfy macros in objects-inl.h.
static Object* cast(Object* value) { return value; }
// Layout description.
static const int kHeaderSize = 0; // Object does not take up any space.
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};
// Smi represents integer Numbers that can be stored in 31 bits.
// Smis are immediate which means they are NOT allocated in the heap.
// The this pointer has the following format: [31 bit signed int] 0
// For long smis it has the following format:
// [32 bit signed int] [31 bits zero padding] 0
// Smi stands for small integer.
class Smi: public Object {
public:
// Returns the integer value.
inline int value();
// Convert a value to a Smi object.
static inline Smi* FromInt(int value);
static inline Smi* FromIntptr(intptr_t value);
// Returns whether value can be represented in a Smi.
static inline bool IsValid(intptr_t value);
// Casting.
static inline Smi* cast(Object* object);
// Dispatched behavior.
void SmiPrint(FILE* out = stdout);
void SmiPrint(StringStream* accumulator);
DECLARE_VERIFIER(Smi)
static const int kMinValue =
(static_cast<unsigned int>(-1)) << (kSmiValueSize - 1);
static const int kMaxValue = -(kMinValue + 1);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
};
// Failure is used for reporting out of memory situations and
// propagating exceptions through the runtime system. Failure objects
// are transient and cannot occur as part of the object graph.
//
// Failures are a single word, encoded as follows:
// +-------------------------+---+--+--+
// |.........unused..........|sss|tt|11|
// +-------------------------+---+--+--+
// 7 6 4 32 10
//
//
// The low two bits, 0-1, are the failure tag, 11. The next two bits,
// 2-3, are a failure type tag 'tt' with possible values:
// 00 RETRY_AFTER_GC
// 01 EXCEPTION
// 10 INTERNAL_ERROR
// 11 OUT_OF_MEMORY_EXCEPTION
//
// The next three bits, 4-6, are an allocation space tag 'sss'. The
// allocation space tag is 000 for all failure types except
// RETRY_AFTER_GC. For RETRY_AFTER_GC, the possible values are the
// allocation spaces (the encoding is found in globals.h).
// Failure type tag info.
const int kFailureTypeTagSize = 2;
const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
class Failure: public MaybeObject {
public:
// RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
enum Type {
RETRY_AFTER_GC = 0,
EXCEPTION = 1, // Returning this marker tells the real exception
// is in Isolate::pending_exception.
INTERNAL_ERROR = 2,
OUT_OF_MEMORY_EXCEPTION = 3
};
inline Type type() const;
// Returns the space that needs to be collected for RetryAfterGC failures.
inline AllocationSpace allocation_space() const;
inline bool IsInternalError() const;
inline bool IsOutOfMemoryException() const;
static inline Failure* RetryAfterGC(AllocationSpace space);
static inline Failure* RetryAfterGC(); // NEW_SPACE
static inline Failure* Exception();
static inline Failure* InternalError();
// TODO(jkummerow): The value is temporary instrumentation. Remove it
// when it has served its purpose.
static inline Failure* OutOfMemoryException(intptr_t value);
// Casting.
static inline Failure* cast(MaybeObject* object);
// Dispatched behavior.
void FailurePrint(FILE* out = stdout);
void FailurePrint(StringStream* accumulator);
DECLARE_VERIFIER(Failure)
private:
inline intptr_t value() const;
static inline Failure* Construct(Type type, intptr_t value = 0);
DISALLOW_IMPLICIT_CONSTRUCTORS(Failure);
};
// Heap objects typically have a map pointer in their first word. However,
// during GC other data (e.g. mark bits, forwarding addresses) is sometimes
// encoded in the first word. The class MapWord is an abstraction of the
// value in a heap object's first word.
class MapWord BASE_EMBEDDED {
public:
// Normal state: the map word contains a map pointer.
// Create a map word from a map pointer.
static inline MapWord FromMap(Map* map);
// View this map word as a map pointer.
inline Map* ToMap();
// Scavenge collection: the map word of live objects in the from space
// contains a forwarding address (a heap object pointer in the to space).
// True if this map word is a forwarding address for a scavenge
// collection. Only valid during a scavenge collection (specifically,
// when all map words are heap object pointers, i.e. not during a full GC).
inline bool IsForwardingAddress();
// Create a map word from a forwarding address.
static inline MapWord FromForwardingAddress(HeapObject* object);
// View this map word as a forwarding address.
inline HeapObject* ToForwardingAddress();
static inline MapWord FromRawValue(uintptr_t value) {
return MapWord(value);
}
inline uintptr_t ToRawValue() {
return value_;
}
private:
// HeapObject calls the private constructor and directly reads the value.
friend class HeapObject;
explicit MapWord(uintptr_t value) : value_(value) {}
uintptr_t value_;
};
// HeapObject is the superclass for all classes describing heap allocated
// objects.
class HeapObject: public Object {
public:
// [map]: Contains a map which contains the object's reflective
// information.
inline Map* map();
inline void set_map(Map* value);
// The no-write-barrier version. This is OK if the object is white and in
// new space, or if the value is an immortal immutable object, like the maps
// of primitive (non-JS) objects like strings, heap numbers etc.
inline void set_map_no_write_barrier(Map* value);
// During garbage collection, the map word of a heap object does not
// necessarily contain a map pointer.
inline MapWord map_word();
inline void set_map_word(MapWord map_word);
// The Heap the object was allocated in. Used also to access Isolate.
inline Heap* GetHeap();
// Convenience method to get current isolate.
inline Isolate* GetIsolate();
// Converts an address to a HeapObject pointer.
static inline HeapObject* FromAddress(Address address);
// Returns the address of this HeapObject.
inline Address address();
// Iterates over pointers contained in the object (including the Map)
void Iterate(ObjectVisitor* v);
// Iterates over all pointers contained in the object except the
// first map pointer. The object type is given in the first
// parameter. This function does not access the map pointer in the
// object, and so is safe to call while the map pointer is modified.
void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);
// Returns the heap object's size in bytes
inline int Size();
// Given a heap object's map pointer, returns the heap size in bytes
// Useful when the map pointer field is used for other purposes.
// GC internal.
inline int SizeFromMap(Map* map);
// Returns the field at offset in obj, as a read/write Object* reference.
// Does no checking, and is safe to use during GC, while maps are invalid.
// Does not invoke write barrier, so should only be assigned to
// during marking GC.
static inline Object** RawField(HeapObject* obj, int offset);
// Adds the |code| object related to |name| to the code cache of this map. If
// this map is a dictionary map that is shared, the map copied and installed
// onto the object.
static void UpdateMapCodeCache(Handle<HeapObject> object,
Handle<Name> name,
Handle<Code> code);
// Casting.
static inline HeapObject* cast(Object* obj);
// Return the write barrier mode for this. Callers of this function
// must be able to present a reference to an DisallowHeapAllocation
// object as a sign that they are not going to use this function
// from code that allocates and thus invalidates the returned write
// barrier mode.
inline WriteBarrierMode GetWriteBarrierMode(
const DisallowHeapAllocation& promise);
// Dispatched behavior.
void HeapObjectShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
void PrintHeader(FILE* out, const char* id);
#endif
DECLARE_PRINTER(HeapObject)
DECLARE_VERIFIER(HeapObject)
#ifdef VERIFY_HEAP
inline void VerifyObjectField(int offset);
inline void VerifySmiField(int offset);
// Verify a pointer is a valid HeapObject pointer that points to object
// areas in the heap.
static void VerifyHeapPointer(Object* p);
#endif
// Layout description.
// First field in a heap object is map.
static const int kMapOffset = Object::kHeaderSize;
static const int kHeaderSize = kMapOffset + kPointerSize;
STATIC_CHECK(kMapOffset == Internals::kHeapObjectMapOffset);
protected:
// helpers for calling an ObjectVisitor to iterate over pointers in the
// half-open range [start, end) specified as integer offsets
inline void IteratePointers(ObjectVisitor* v, int start, int end);
// as above, for the single element at "offset"
inline void IteratePointer(ObjectVisitor* v, int offset);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
};
// This class describes a body of an object of a fixed size
// in which all pointer fields are located in the [start_offset, end_offset)
// interval.
template<int start_offset, int end_offset, int size>
class FixedBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static const int kEndOffset = end_offset;
static const int kSize = size;
static inline void IterateBody(HeapObject* obj, ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj) {
StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
HeapObject::RawField(obj, end_offset));
}
};
// This class describes a body of an object of a variable size
// in which all pointer fields are located in the [start_offset, object_size)
// interval.
template<int start_offset>
class FlexibleBodyDescriptor {
public:
static const int kStartOffset = start_offset;
static inline void IterateBody(HeapObject* obj,
int object_size,
ObjectVisitor* v);
template<typename StaticVisitor>
static inline void IterateBody(HeapObject* obj, int object_size) {
StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset),
HeapObject::RawField(obj, object_size));
}
};
// The HeapNumber class describes heap allocated numbers that cannot be
// represented in a Smi (small integer)
class HeapNumber: public HeapObject {
public:
// [value]: number value.
inline double value();
inline void set_value(double value);
// Casting.
static inline HeapNumber* cast(Object* obj);
// Dispatched behavior.
bool HeapNumberBooleanValue();
void HeapNumberPrint(FILE* out = stdout);
void HeapNumberPrint(StringStream* accumulator);
DECLARE_VERIFIER(HeapNumber)
inline int get_exponent();
inline int get_sign();
// Layout description.
static const int kValueOffset = HeapObject::kHeaderSize;
// IEEE doubles are two 32 bit words. The first is just mantissa, the second
// is a mixture of sign, exponent and mantissa. Our current platforms are all
// little endian apart from non-EABI arm which is little endian with big
// endian floating point word ordering!
static const int kMantissaOffset = kValueOffset;
static const int kExponentOffset = kValueOffset + 4;
static const int kSize = kValueOffset + kDoubleSize;
static const uint32_t kSignMask = 0x80000000u;
static const uint32_t kExponentMask = 0x7ff00000u;
static const uint32_t kMantissaMask = 0xfffffu;
static const int kMantissaBits = 52;
static const int kExponentBits = 11;
static const int kExponentBias = 1023;
static const int kExponentShift = 20;
static const int kInfinityOrNanExponent =
(kExponentMask >> kExponentShift) - kExponentBias;
static const int kMantissaBitsInTopWord = 20;
static const int kNonMantissaBitsInTopWord = 12;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);
};
enum EnsureElementsMode {
DONT_ALLOW_DOUBLE_ELEMENTS,
ALLOW_COPIED_DOUBLE_ELEMENTS,
ALLOW_CONVERTED_DOUBLE_ELEMENTS
};
// Indicates whether a property should be set or (re)defined. Setting of a
// property causes attributes to remain unchanged, writability to be checked
// and callbacks to be called. Defining of a property causes attributes to
// be updated and callbacks to be overridden.
enum SetPropertyMode {
SET_PROPERTY,
DEFINE_PROPERTY
};
// Indicator for one component of an AccessorPair.
enum AccessorComponent {
ACCESSOR_GETTER,
ACCESSOR_SETTER
};
// JSReceiver includes types on which properties can be defined, i.e.,
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
public:
enum DeleteMode {
NORMAL_DELETION,
STRICT_DELETION,
FORCE_DELETION
};
// A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
// a keyed store is of the form a[expression] = foo.
enum StoreFromKeyed {
MAY_BE_STORE_FROM_KEYED,
CERTAINLY_NOT_STORE_FROM_KEYED
};
// Internal properties (e.g. the hidden properties dictionary) might
// be added even though the receiver is non-extensible.
enum ExtensibilityCheck {
PERFORM_EXTENSIBILITY_CHECK,
OMIT_EXTENSIBILITY_CHECK
};
// Casting.
static inline JSReceiver* cast(Object* obj);
// Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5.
static Handle<Object> SetProperty(Handle<JSReceiver> object,
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode =
MAY_BE_STORE_FROM_KEYED);
static Handle<Object> SetElement(Handle<JSReceiver> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
static inline bool HasProperty(Handle<JSReceiver> object, Handle<Name> name);
static inline bool HasLocalProperty(Handle<JSReceiver>, Handle<Name> name);
static inline bool HasElement(Handle<JSReceiver> object, uint32_t index);
static inline bool HasLocalElement(Handle<JSReceiver> object, uint32_t index);
// Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7.
static Handle<Object> DeleteProperty(Handle<JSReceiver> object,
Handle<Name> name,
DeleteMode mode = NORMAL_DELETION);
static Handle<Object> DeleteElement(Handle<JSReceiver> object,
uint32_t index,
DeleteMode mode = NORMAL_DELETION);
// Tests for the fast common case for property enumeration.
bool IsSimpleEnum();
// Returns the class name ([[Class]] property in the specification).
String* class_name();
// Returns the constructor name (the name (possibly, inferred name) of the
// function that was used to instantiate the object).
String* constructor_name();
inline PropertyAttributes GetPropertyAttribute(Name* name);
PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
Name* name);
PropertyAttributes GetLocalPropertyAttribute(Name* name);
inline PropertyAttributes GetElementAttribute(uint32_t index);
inline PropertyAttributes GetLocalElementAttribute(uint32_t index);
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
// Return the constructor function (may be Heap::null_value()).
inline Object* GetConstructor();
// Retrieves a permanent object identity hash code. The undefined value might
// be returned in case no hash was created yet.
inline Object* GetIdentityHash();
// Retrieves a permanent object identity hash code. May create and store a
// hash code if needed and none exists.
inline static Handle<Object> GetOrCreateIdentityHash(
Handle<JSReceiver> object);
// Lookup a property. If found, the result is valid and has
// detailed information.
void LocalLookup(Name* name, LookupResult* result,
bool search_hidden_prototypes = false);
void Lookup(Name* name, LookupResult* result);
protected:
Smi* GenerateIdentityHash();
static Handle<Object> SetPropertyWithDefinedSetter(Handle<JSReceiver> object,
Handle<JSReceiver> setter,
Handle<Object> value);
private:
PropertyAttributes GetPropertyAttributeForResult(JSReceiver* receiver,
LookupResult* result,
Name* name,
bool continue_search);
static Handle<Object> SetProperty(Handle<JSReceiver> receiver,
LookupResult* result,
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_from_keyed);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
};
// Forward declaration for JSObject::GetOrCreateHiddenPropertiesHashTable.
class ObjectHashTable;
// The JSObject describes real heap allocated JavaScript objects with
// properties.
// Note that the map of JSObject changes during execution to enable inline
// caching.
class JSObject: public JSReceiver {
public:
// [properties]: Backing storage for properties.
// properties is a FixedArray in the fast case and a Dictionary in the
// slow case.
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
inline void initialize_properties();
inline bool HasFastProperties();
inline NameDictionary* property_dictionary(); // Gets slow properties.
// [elements]: The elements (properties with names that are integers).
//
// Elements can be in two general modes: fast and slow. Each mode
// corrensponds to a set of object representations of elements that
// have something in common.
//
// In the fast mode elements is a FixedArray and so each element can
// be quickly accessed. This fact is used in the generated code. The
// elements array can have one of three maps in this mode:
// fixed_array_map, non_strict_arguments_elements_map or
// fixed_cow_array_map (for copy-on-write arrays). In the latter case
// the elements array may be shared by a few objects and so before
// writing to any element the array must be copied. Use
// EnsureWritableFastElements in this case.
//
// In the slow mode the elements is either a NumberDictionary, an
// ExternalArray, or a FixedArray parameter map for a (non-strict)
// arguments object.
DECL_ACCESSORS(elements, FixedArrayBase)
inline void initialize_elements();
MUST_USE_RESULT inline MaybeObject* ResetElements();
inline ElementsKind GetElementsKind();
inline ElementsAccessor* GetElementsAccessor();
// Returns true if an object has elements of FAST_SMI_ELEMENTS ElementsKind.
inline bool HasFastSmiElements();
// Returns true if an object has elements of FAST_ELEMENTS ElementsKind.
inline bool HasFastObjectElements();
// Returns true if an object has elements of FAST_ELEMENTS or
// FAST_SMI_ONLY_ELEMENTS.
inline bool HasFastSmiOrObjectElements();
// Returns true if an object has any of the fast elements kinds.
inline bool HasFastElements();
// Returns true if an object has elements of FAST_DOUBLE_ELEMENTS
// ElementsKind.
inline bool HasFastDoubleElements();
// Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS
// ElementsKind.
inline bool HasFastHoleyElements();
inline bool HasNonStrictArgumentsElements();
inline bool HasDictionaryElements();
inline bool HasExternalPixelElements();
inline bool HasExternalArrayElements();
inline bool HasExternalByteElements();
inline bool HasExternalUnsignedByteElements();
inline bool HasExternalShortElements();
inline bool HasExternalUnsignedShortElements();
inline bool HasExternalIntElements();
inline bool HasExternalUnsignedIntElements();
inline bool HasExternalFloatElements();
inline bool HasExternalDoubleElements();
bool HasFastArgumentsElements();
bool HasDictionaryArgumentsElements();
inline SeededNumberDictionary* element_dictionary(); // Gets slow elements.
inline bool ShouldTrackAllocationInfo();
inline void set_map_and_elements(
Map* map,
FixedArrayBase* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Requires: HasFastElements().
static Handle<FixedArray> EnsureWritableFastElements(
Handle<JSObject> object);
MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
// Collects elements starting at index 0.
// Undefined values are placed after non-undefined values.
// Returns the number of non-undefined values.
static Handle<Object> PrepareElementsForSort(Handle<JSObject> object,
uint32_t limit);
// As PrepareElementsForSort, but only on objects where elements is
// a dictionary, and it will stay a dictionary.
static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object,
uint32_t limit);
MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
static Handle<Object> GetPropertyWithCallback(Handle<JSObject> object,
Handle<Object> receiver,
Handle<Object> structure,
Handle<Name> name);
static Handle<Object> SetPropertyWithCallback(
Handle<JSObject> object,
Handle<Object> structure,
Handle<Name> name,
Handle<Object> value,
Handle<JSObject> holder,
StrictModeFlag strict_mode);
static Handle<Object> SetPropertyWithInterceptor(
Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
static Handle<Object> SetPropertyForResult(
Handle<JSObject> object,
LookupResult* result,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
static Handle<Object> SetLocalPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
ValueType value_type = OPTIMAL_REPRESENTATION,
StoreMode mode = ALLOW_AS_CONSTANT,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK);
static inline Handle<String> ExpectedTransitionKey(Handle<Map> map);
static inline Handle<Map> ExpectedTransitionTarget(Handle<Map> map);
// Try to follow an existing transition to a field with attributes NONE. The
// return value indicates whether the transition was successful.
static inline Handle<Map> FindTransitionToField(Handle<Map> map,
Handle<Name> key);
// Extend the receiver with a single fast property appeared first in the
// passed map. This also extends the property backing store if necessary.
static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
// Migrates the given object to a map whose field representations are the
// lowest upper bound of all known representations for that field.
static void MigrateInstance(Handle<JSObject> instance);
// Migrates the given object only if the target map is already available,
// or returns an empty handle if such a map is not yet available.
static Handle<Object> TryMigrateInstance(Handle<JSObject> instance);
// Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
Object* GetNormalizedProperty(LookupResult* result);
// Sets the property value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
static void SetNormalizedProperty(Handle<JSObject> object,
LookupResult* result,
Handle<Object> value);
// Sets the property value in a normalized object given (key, value, details).
// Handles the special representation of JS global objects.
static void SetNormalizedProperty(Handle<JSObject> object,
Handle<Name> key,
Handle<Object> value,
PropertyDetails details);
static void OptimizeAsPrototype(Handle<JSObject> object);
// Retrieve interceptors.
InterceptorInfo* GetNamedInterceptor();
InterceptorInfo* GetIndexedInterceptor();
// Used from JSReceiver.
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
Name* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
Name* name,
bool continue_search);
PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
Object* receiver,
LookupResult* result,
Name* name,
bool continue_search);
PropertyAttributes GetElementAttributeWithReceiver(JSReceiver* receiver,
uint32_t index,
bool continue_search);
// Retrieves an AccessorPair property from the given object. Might return
// undefined if the property doesn't exist or is of a different kind.
static Handle<Object> GetAccessor(Handle<JSObject> object,
Handle<Name> name,
AccessorComponent component);
// Defines an AccessorPair property on the given object.
// TODO(mstarzinger): Rename to SetAccessor() and return empty handle on
// exception instead of letting callers check for scheduled exception.
static void DefineAccessor(Handle<JSObject> object,
Handle<Name> name,
Handle<Object> getter,
Handle<Object> setter,
PropertyAttributes attributes,
v8::AccessControl access_control = v8::DEFAULT);
// Defines an AccessorInfo property on the given object.
static Handle<Object> SetAccessor(Handle<JSObject> object,
Handle<AccessorInfo> info);
static Handle<Object> GetPropertyWithInterceptor(
Handle<JSObject> object,
Handle<Object> receiver,
Handle<Name> name,
PropertyAttributes* attributes);
static Handle<Object> GetPropertyPostInterceptor(
Handle<JSObject> object,
Handle<Object> receiver,
Handle<Name> name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
Object* receiver,
Name* name,
PropertyAttributes* attributes);
// Returns true if this is an instance of an api function and has
// been modified since it was created. May give false positives.
bool IsDirty();
// If the receiver is a JSGlobalProxy this method will return its prototype,
// otherwise the result is the receiver itself.
inline Object* BypassGlobalProxy();
// Accessors for hidden properties object.
//
// Hidden properties are not local properties of the object itself.
// Instead they are stored in an auxiliary structure kept as a local
// property with a special name Heap::hidden_string(). But if the
// receiver is a JSGlobalProxy then the auxiliary object is a property
// of its prototype, and if it's a detached proxy, then you can't have
// hidden properties.
// Sets a hidden property on this object. Returns this object if successful,
// undefined if called on a detached proxy.
static Handle<Object> SetHiddenProperty(Handle<JSObject> object,
Handle<Name> key,
Handle<Object> value);
// Gets the value of a hidden property with the given key. Returns the hole
// if the property doesn't exist (or if called on a detached proxy),
// otherwise returns the value set for the key.
Object* GetHiddenProperty(Name* key);
// Deletes a hidden property. Deleting a non-existing property is
// considered successful.
static void DeleteHiddenProperty(Handle<JSObject> object,
Handle<Name> key);
// Returns true if the object has a property with the hidden string as name.
bool HasHiddenProperties();
static void SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash);
inline void ValidateElements();
// Makes sure that this object can contain HeapObject as elements.
static inline void EnsureCanContainHeapObjectElements(Handle<JSObject> obj);
// Makes sure that this object can contain the specified elements.
MUST_USE_RESULT inline MaybeObject* EnsureCanContainElements(
Object** elements,
uint32_t count,
EnsureElementsMode mode);
MUST_USE_RESULT inline MaybeObject* EnsureCanContainElements(
FixedArrayBase* elements,
uint32_t length,
EnsureElementsMode mode);
MUST_USE_RESULT MaybeObject* EnsureCanContainElements(
Arguments* arguments,
uint32_t first_arg,
uint32_t arg_count,
EnsureElementsMode mode);
// Do we want to keep the elements in fast case when increasing the
// capacity?
bool ShouldConvertToSlowElements(int new_capacity);
// Returns true if the backing storage for the slow-case elements of
// this object takes up nearly as much space as a fast-case backing
// storage would. In that case the JSObject should have fast
// elements.
bool ShouldConvertToFastElements();
// Returns true if the elements of JSObject contains only values that can be
// represented in a FixedDoubleArray and has at least one value that can only
// be represented as a double and not a Smi.
bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements);
// Computes the new capacity when expanding the elements of a JSObject.
static int NewElementsCapacity(int old_capacity) {
// (old_capacity + 50%) + 16
return old_capacity + (old_capacity >> 1) + 16;
}
// These methods do not perform access checks!
AccessorPair* GetLocalPropertyAccessorPair(Name* name);
AccessorPair* GetLocalElementAccessorPair(uint32_t index);
static Handle<Object> SetFastElement(Handle<JSObject> object, uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode,
bool check_prototype);
static Handle<Object> SetOwnElement(Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode);
// Empty handle is returned if the element cannot be set to the given value.
static Handle<Object> SetElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype = true,
SetPropertyMode set_mode = SET_PROPERTY);
// Returns the index'th element.
// The undefined object if index is out of bounds.
MUST_USE_RESULT MaybeObject* GetElementWithInterceptor(Object* receiver,
uint32_t index);
enum SetFastElementsCapacitySmiMode {
kAllowSmiElements,
kForceSmiElements,
kDontAllowSmiElements
};
static Handle<FixedArray> SetFastElementsCapacityAndLength(
Handle<JSObject> object,
int capacity,
int length,
SetFastElementsCapacitySmiMode smi_mode);
// Replace the elements' backing store with fast elements of the given
// capacity. Update the length for JSArrays. Returns the new backing
// store.
MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(
int capacity,
int length,
SetFastElementsCapacitySmiMode smi_mode);
static void SetFastDoubleElementsCapacityAndLength(
Handle<JSObject> object,
int capacity,
int length);
MUST_USE_RESULT MaybeObject* SetFastDoubleElementsCapacityAndLength(
int capacity,
int length);
// Lookup interceptors are used for handling properties controlled by host
// objects.
inline bool HasNamedInterceptor();
inline bool HasIndexedInterceptor();
// Support functions for v8 api (needed for correct interceptor behavior).
static bool HasRealNamedProperty(Handle<JSObject> object,
Handle<Name> key);
static bool HasRealElementProperty(Handle<JSObject> object, uint32_t index);
static bool HasRealNamedCallbackProperty(Handle<JSObject> object,
Handle<Name> key);
// Get the header size for a JSObject. Used to compute the index of
// internal fields as well as the number of internal fields.
inline int GetHeaderSize();
inline int GetInternalFieldCount();
inline int GetInternalFieldOffset(int index);
inline Object* GetInternalField(int index);
inline void SetInternalField(int index, Object* value);
inline void SetInternalField(int index, Smi* value);
// The following lookup functions skip interceptors.
void LocalLookupRealNamedProperty(Name* name, LookupResult* result);
void LookupRealNamedProperty(Name* name, LookupResult* result);
void LookupRealNamedPropertyInPrototypes(Name* name, LookupResult* result);
void LookupCallbackProperty(Name* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
int NumberOfLocalProperties(PropertyAttributes filter = NONE);
// Fill in details for properties into storage starting at the specified
// index.
void GetLocalPropertyNames(
FixedArray* storage, int index, PropertyAttributes filter = NONE);
// Returns the number of properties on this object filtering out properties
// with the specified attributes (ignoring interceptors).
int NumberOfLocalElements(PropertyAttributes filter);
// Returns the number of enumerable elements (ignoring interceptors).
int NumberOfEnumElements();
// Returns the number of elements on this object filtering out elements
// with the specified attributes (ignoring interceptors).
int GetLocalElementKeys(FixedArray* storage, PropertyAttributes filter);
// Count and fill in the enumerable elements into storage.
// (storage->length() == NumberOfEnumElements()).
// If storage is NULL, will count the elements without adding
// them to any storage.
// Returns the number of enumerable elements.
int GetEnumElementKeys(FixedArray* storage);
// Returns a new map with all transitions dropped from the object's current
// map and the ElementsKind set.
static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
ElementsKind to_kind);
inline MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
Isolate* isolate,
ElementsKind elements_kind);
MUST_USE_RESULT MaybeObject* GetElementsTransitionMapSlow(
ElementsKind elements_kind);
static void TransitionElementsKind(Handle<JSObject> object,
ElementsKind to_kind);
MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
// TODO(mstarzinger): Both public because of ConvertAnsSetLocalProperty().
static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
static void GeneralizeFieldRepresentation(Handle<JSObject> object,
int modify_index,
Representation new_representation,
StoreMode store_mode);
// Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
// added this number can be indicated to have the backing store allocated to
// an initial capacity for holding these properties.
static void NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode,
int expected_additional_properties);
// Convert and update the elements backing store to be a
// SeededNumberDictionary dictionary. Returns the backing after conversion.
static Handle<SeededNumberDictionary> NormalizeElements(
Handle<JSObject> object);
MUST_USE_RESULT MaybeObject* NormalizeElements();
// Transform slow named properties to fast variants.
static void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields);
// Access fast-case object properties at index.
MUST_USE_RESULT inline MaybeObject* FastPropertyAt(
Representation representation,
int index);
inline Object* RawFastPropertyAt(int index);
inline void FastPropertyAtPut(int index, Object* value);
// Access to in object properties.
inline int GetInObjectPropertyOffset(int index);
inline Object* InObjectPropertyAt(int index);
inline Object* InObjectPropertyAtPut(int index,
Object* value,
WriteBarrierMode mode
= UPDATE_WRITE_BARRIER);
// Set the object's prototype (only JSReceiver and null are allowed values).
static Handle<Object> SetPrototype(Handle<JSObject> object,
Handle<Object> value,
bool skip_hidden_prototypes = false);
// Initializes the body after properties slot, properties slot is
// initialized by set_properties. Fill the pre-allocated fields with
// pre_allocated_value and the rest with filler_value.
// Note: this call does not update write barrier, the caller is responsible
// to ensure that |filler_value| can be collected without WB here.
inline void InitializeBody(Map* map,
Object* pre_allocated_value,
Object* filler_value);
// Check whether this object references another object
bool ReferencesObject(Object* obj);
// Disalow further properties to be added to the object.
static Handle<Object> PreventExtensions(Handle<JSObject> object);
// ES5 Object.freeze
static Handle<Object> Freeze(Handle<JSObject> object);
// Called the first time an object is observed with ES7 Object.observe.
static void SetObserved(Handle<JSObject> object);
// Copy object.
enum DeepCopyHints {
kNoHints = 0,
kObjectIsShallowArray = 1
};
static Handle<JSObject> Copy(Handle<JSObject> object);
static Handle<JSObject> DeepCopy(Handle<JSObject> object,
AllocationSiteUsageContext* site_context,
DeepCopyHints hints = kNoHints);
static Handle<JSObject> DeepWalk(Handle<JSObject> object,
AllocationSiteCreationContext* site_context);
// Casting.
static inline JSObject* cast(Object* obj);
// Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator);
DECLARE_PRINTER(JSObject)
DECLARE_VERIFIER(JSObject)
#ifdef OBJECT_PRINT
void PrintProperties(FILE* out = stdout);
void PrintElements(FILE* out = stdout);
void PrintTransitions(FILE* out = stdout);
#endif
void PrintElementsTransition(
FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
ElementsKind to_kind, FixedArrayBase* to_elements);
void PrintInstanceMigration(FILE* file, Map* original_map, Map* new_map);
#ifdef DEBUG
// Structure for collecting spill information about JSObjects.
class SpillInformation {
public:
void Clear();
void Print();
int number_of_objects_;
int number_of_objects_with_fast_properties_;
int number_of_objects_with_fast_elements_;
int number_of_fast_used_fields_;
int number_of_fast_unused_fields_;
int number_of_slow_used_properties_;
int number_of_slow_unused_properties_;
int number_of_fast_used_elements_;
int number_of_fast_unused_elements_;
int number_of_slow_used_elements_;
int number_of_slow_unused_elements_;
};
void IncrementSpillStatistics(SpillInformation* info);
#endif
#ifdef VERIFY_HEAP
// If a GC was caused while constructing this object, the elements pointer
// may point to a one pointer filler map. The object won't be rooted, but
// our heap verification code could stumble across it.
bool ElementsAreSafeToExamine();
#endif
Object* SlowReverseLookup(Object* value);
// Maximal number of fast properties for the JSObject. Used to
// restrict the number of map transitions to avoid an explosion in
// the number of maps for objects used as dictionaries.
inline bool TooManyFastProperties(
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
// Also maximal value of JSArray's length property.
static const uint32_t kMaxElementCount = 0xffffffffu;
// Constants for heuristics controlling conversion of fast elements
// to slow elements.
// Maximal gap that can be introduced by adding an element beyond
// the current elements length.
static const uint32_t kMaxGap = 1024;
// Maximal length of fast elements array that won't be checked for
// being dense enough on expansion.
static const int kMaxUncheckedFastElementsLength = 5000;
// Same as above but for old arrays. This limit is more strict. We
// don't want to be wasteful with long lived objects.
static const int kMaxUncheckedOldFastElementsLength = 500;
// Note that Heap::MaxRegularSpaceAllocationSize() puts a limit on
// permissible values (see the ASSERT in heap.cc).
static const int kInitialMaxFastElementArray = 100000;
static const int kFastPropertiesSoftLimit = 12;
static const int kMaxFastProperties = 64;
static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields
// to the same object requires fewer allocations and copies.
static const int kFieldsAdded = 3;
// Layout description.
static const int kPropertiesOffset = HeapObject::kHeaderSize;
static const int kElementsOffset = kPropertiesOffset + kPointerSize;
static const int kHeaderSize = kElementsOffset + kPointerSize;
STATIC_CHECK(kHeaderSize == Internals::kJSObjectHeaderSize);
class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> {
public:
static inline int SizeOf(Map* map, HeapObject* object);
};
// Enqueue change record for Object.observe. May cause GC.
static void EnqueueChangeRecord(Handle<JSObject> object,
const char* type,
Handle<Name> name,
Handle<Object> old_value);
private:
friend class DictionaryElementsAccessor;
friend class JSReceiver;
friend class Object;
static void UpdateAllocationSite(Handle<JSObject> object,
ElementsKind to_kind);
MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind);
// Used from Object::GetProperty().
static Handle<Object> GetPropertyWithFailedAccessCheck(
Handle<JSObject> object,
Handle<Object> receiver,
LookupResult* result,
Handle<Name> name,
PropertyAttributes* attributes);
MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
Object* structure,
uint32_t index,
Object* holder);
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithInterceptor(
JSReceiver* receiver,
uint32_t index,
bool continue_search);
MUST_USE_RESULT PropertyAttributes GetElementAttributeWithoutInterceptor(
JSReceiver* receiver,
uint32_t index,
bool continue_search);
static Handle<Object> SetElementWithCallback(
Handle<JSObject> object,
Handle<Object> structure,
uint32_t index,
Handle<Object> value,
Handle<JSObject> holder,
StrictModeFlag strict_mode);
static Handle<Object> SetElementWithInterceptor(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
static Handle<Object> SetElementWithoutInterceptor(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
static Handle<Object> SetElementWithCallbackSetterInPrototypes(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
bool* found,
StrictModeFlag strict_mode);
static Handle<Object> SetDictionaryElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool check_prototype,
SetPropertyMode set_mode = SET_PROPERTY);
static Handle<Object> SetFastDoubleElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
StrictModeFlag strict_mode,
bool check_prototype = true);
// Searches the prototype chain for property 'name'. If it is found and
// has a setter, invoke it and set '*done' to true. If it is found and is
// read-only, reject and set '*done' to true. Otherwise, set '*done' to
// false. Can throw and return an empty handle with '*done==true'.
static Handle<Object> SetPropertyViaPrototypes(
Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
bool* done);
static