1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_OBJECTS_H_ 6 #define V8_OBJECTS_H_ 7 8 #include <iosfwd> 9 #include <memory> 10 11 #include "src/assert-scope.h" 12 #include "src/bailout-reason.h" 13 #include "src/base/bits.h" 14 #include "src/base/flags.h" 15 #include "src/builtins/builtins.h" 16 #include "src/checks.h" 17 #include "src/elements-kind.h" 18 #include "src/field-index.h" 19 #include "src/flags.h" 20 #include "src/list.h" 21 #include "src/messages.h" 22 #include "src/property-details.h" 23 #include "src/unicode-decoder.h" 24 #include "src/unicode.h" 25 #include "src/zone/zone.h" 26 27 #if V8_TARGET_ARCH_ARM 28 #include "src/arm/constants-arm.h" // NOLINT 29 #elif V8_TARGET_ARCH_ARM64 30 #include "src/arm64/constants-arm64.h" // NOLINT 31 #elif V8_TARGET_ARCH_MIPS 32 #include "src/mips/constants-mips.h" // NOLINT 33 #elif V8_TARGET_ARCH_MIPS64 34 #include "src/mips64/constants-mips64.h" // NOLINT 35 #elif V8_TARGET_ARCH_PPC 36 #include "src/ppc/constants-ppc.h" // NOLINT 37 #elif V8_TARGET_ARCH_S390 38 #include "src/s390/constants-s390.h" // NOLINT 39 #endif 40 41 // Has to be the last include (doesn't have include guards): 42 #include "src/objects/object-macros.h" 43 44 // 45 // Most object types in the V8 JavaScript are described in this file. 46 // 47 // Inheritance hierarchy: 48 // - Object 49 // - Smi (immediate small integer) 50 // - HeapObject (superclass for everything allocated in the heap) 51 // - JSReceiver (suitable for property access) 52 // - JSObject 53 // - JSArray 54 // - JSArrayBuffer 55 // - JSArrayBufferView 56 // - JSTypedArray 57 // - JSDataView 58 // - JSBoundFunction 59 // - JSCollection 60 // - JSSet 61 // - JSMap 62 // - JSStringIterator 63 // - JSSetIterator 64 // - JSMapIterator 65 // - JSWeakCollection 66 // - JSWeakMap 67 // - JSWeakSet 68 // - JSRegExp 69 // - JSFunction 70 // - JSGeneratorObject 71 // - JSGlobalObject 72 // - JSGlobalProxy 73 // - JSValue 74 // - JSDate 75 // - JSMessageObject 76 // - JSModuleNamespace 77 // - JSProxy 78 // - FixedArrayBase 79 // - ByteArray 80 // - BytecodeArray 81 // - FixedArray 82 // - DescriptorArray 83 // - FrameArray 84 // - HashTable 85 // - Dictionary 86 // - StringTable 87 // - StringSet 88 // - CompilationCacheTable 89 // - CodeCacheHashTable 90 // - MapCache 91 // - OrderedHashTable 92 // - OrderedHashSet 93 // - OrderedHashMap 94 // - Context 95 // - FeedbackMetadata 96 // - FeedbackVector 97 // - TemplateList 98 // - TransitionArray 99 // - ScopeInfo 100 // - ModuleInfo 101 // - ScriptContextTable 102 // - WeakFixedArray 103 // - FixedDoubleArray 104 // - Name 105 // - String 106 // - SeqString 107 // - SeqOneByteString 108 // - SeqTwoByteString 109 // - SlicedString 110 // - ConsString 111 // - ThinString 112 // - ExternalString 113 // - ExternalOneByteString 114 // - ExternalTwoByteString 115 // - InternalizedString 116 // - SeqInternalizedString 117 // - SeqOneByteInternalizedString 118 // - SeqTwoByteInternalizedString 119 // - ConsInternalizedString 120 // - ExternalInternalizedString 121 // - ExternalOneByteInternalizedString 122 // - ExternalTwoByteInternalizedString 123 // - Symbol 124 // - HeapNumber 125 // - Cell 126 // - PropertyCell 127 // - Code 128 // - AbstractCode, a wrapper around Code or BytecodeArray 129 // - Map 130 // - Oddball 131 // - Foreign 132 // - SharedFunctionInfo 133 // - Struct 134 // - AccessorInfo 135 // - PromiseResolveThenableJobInfo 136 // - PromiseReactionJobInfo 137 // - AccessorPair 138 // - AccessCheckInfo 139 // - InterceptorInfo 140 // - CallHandlerInfo 141 // - TemplateInfo 142 // - FunctionTemplateInfo 143 // - ObjectTemplateInfo 144 // - Script 145 // - DebugInfo 146 // - BreakPointInfo 147 // - CodeCache 148 // - PrototypeInfo 149 // - Module 150 // - ModuleInfoEntry 151 // - WeakCell 152 // 153 // Formats of Object*: 154 // Smi: [31 bit signed int] 0 155 // HeapObject: [32 bit direct pointer] (4 byte aligned) | 01 156 157 namespace v8 { 158 namespace internal { 159 160 struct InliningPosition; 161 162 enum KeyedAccessStoreMode { 163 STANDARD_STORE, 164 STORE_TRANSITION_TO_OBJECT, 165 STORE_TRANSITION_TO_DOUBLE, 166 STORE_AND_GROW_NO_TRANSITION, 167 STORE_AND_GROW_TRANSITION_TO_OBJECT, 168 STORE_AND_GROW_TRANSITION_TO_DOUBLE, 169 STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS, 170 STORE_NO_TRANSITION_HANDLE_COW 171 }; 172 173 enum MutableMode { 174 MUTABLE, 175 IMMUTABLE 176 }; 177 178 179 static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) { 180 return store_mode == STORE_TRANSITION_TO_OBJECT || 181 store_mode == STORE_TRANSITION_TO_DOUBLE || 182 store_mode == STORE_AND_GROW_TRANSITION_TO_OBJECT || 183 store_mode == STORE_AND_GROW_TRANSITION_TO_DOUBLE; 184 } 185 186 187 static inline KeyedAccessStoreMode GetNonTransitioningStoreMode( 188 KeyedAccessStoreMode store_mode) { 189 if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 190 return store_mode; 191 } 192 if (store_mode >= STORE_AND_GROW_NO_TRANSITION) { 193 return STORE_AND_GROW_NO_TRANSITION; 194 } 195 return STANDARD_STORE; 196 } 197 198 199 static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) { 200 return store_mode >= STORE_AND_GROW_NO_TRANSITION && 201 store_mode <= STORE_AND_GROW_TRANSITION_TO_DOUBLE; 202 } 203 204 205 enum IcCheckType { ELEMENT, PROPERTY }; 206 207 208 // SKIP_WRITE_BARRIER skips the write barrier. 209 // UPDATE_WEAK_WRITE_BARRIER skips the marking part of the write barrier and 210 // only performs the generational part. 211 // UPDATE_WRITE_BARRIER is doing the full barrier, marking and generational. 212 enum WriteBarrierMode { 213 SKIP_WRITE_BARRIER, 214 UPDATE_WEAK_WRITE_BARRIER, 215 UPDATE_WRITE_BARRIER 216 }; 217 218 219 // PropertyNormalizationMode is used to specify whether to keep 220 // inobject properties when normalizing properties of a JSObject. 221 enum PropertyNormalizationMode { 222 CLEAR_INOBJECT_PROPERTIES, 223 KEEP_INOBJECT_PROPERTIES 224 }; 225 226 227 // Indicates how aggressively the prototype should be optimized. FAST_PROTOTYPE 228 // will give the fastest result by tailoring the map to the prototype, but that 229 // will cause polymorphism with other objects. REGULAR_PROTOTYPE is to be used 230 // (at least for now) when dynamically modifying the prototype chain of an 231 // object using __proto__ or Object.setPrototypeOf. 232 enum PrototypeOptimizationMode { REGULAR_PROTOTYPE, FAST_PROTOTYPE }; 233 234 235 // Indicates whether transitions can be added to a source map or not. 236 enum TransitionFlag { 237 INSERT_TRANSITION, 238 OMIT_TRANSITION 239 }; 240 241 242 // Indicates whether the transition is simple: the target map of the transition 243 // either extends the current map with a new property, or it modifies the 244 // property that was added last to the current map. 245 enum SimpleTransitionFlag { 246 SIMPLE_PROPERTY_TRANSITION, 247 PROPERTY_TRANSITION, 248 SPECIAL_TRANSITION 249 }; 250 251 252 // Indicates whether we are only interested in the descriptors of a particular 253 // map, or in all descriptors in the descriptor array. 254 enum DescriptorFlag { 255 ALL_DESCRIPTORS, 256 OWN_DESCRIPTORS 257 }; 258 259 // ICs store extra state in a Code object. The default extra state is 260 // kNoExtraICState. 261 typedef int ExtraICState; 262 static const ExtraICState kNoExtraICState = 0; 263 264 // Instance size sentinel for objects of variable size. 265 const int kVariableSizeSentinel = 0; 266 267 // We may store the unsigned bit field as signed Smi value and do not 268 // use the sign bit. 269 const int kStubMajorKeyBits = 8; 270 const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; 271 272 // All Maps have a field instance_type containing a InstanceType. 273 // It describes the type of the instances. 274 // 275 // As an example, a JavaScript object is a heap object and its map 276 // instance_type is JS_OBJECT_TYPE. 277 // 278 // The names of the string instance types are intended to systematically 279 // mirror their encoding in the instance_type field of the map. The default 280 // encoding is considered TWO_BYTE. It is not mentioned in the name. ONE_BYTE 281 // encoding is mentioned explicitly in the name. Likewise, the default 282 // representation is considered sequential. It is not mentioned in the 283 // name. The other representations (e.g. CONS, EXTERNAL) are explicitly 284 // mentioned. Finally, the string is either a STRING_TYPE (if it is a normal 285 // string) or a INTERNALIZED_STRING_TYPE (if it is a internalized string). 286 // 287 // NOTE: The following things are some that depend on the string types having 288 // instance_types that are less than those of all other types: 289 // HeapObject::Size, HeapObject::IterateBody, the typeof operator, and 290 // Object::IsString. 291 // 292 // NOTE: Everything following JS_VALUE_TYPE is considered a 293 // JSObject for GC purposes. The first four entries here have typeof 294 // 'object', whereas JS_FUNCTION_TYPE has typeof 'function'. 295 #define INSTANCE_TYPE_LIST(V) \ 296 V(INTERNALIZED_STRING_TYPE) \ 297 V(EXTERNAL_INTERNALIZED_STRING_TYPE) \ 298 V(ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 299 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 300 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 301 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \ 302 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 303 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 304 V(STRING_TYPE) \ 305 V(CONS_STRING_TYPE) \ 306 V(EXTERNAL_STRING_TYPE) \ 307 V(SLICED_STRING_TYPE) \ 308 V(THIN_STRING_TYPE) \ 309 V(ONE_BYTE_STRING_TYPE) \ 310 V(CONS_ONE_BYTE_STRING_TYPE) \ 311 V(EXTERNAL_ONE_BYTE_STRING_TYPE) \ 312 V(SLICED_ONE_BYTE_STRING_TYPE) \ 313 V(THIN_ONE_BYTE_STRING_TYPE) \ 314 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 315 V(SHORT_EXTERNAL_STRING_TYPE) \ 316 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE) \ 317 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 318 \ 319 V(SYMBOL_TYPE) \ 320 V(HEAP_NUMBER_TYPE) \ 321 V(ODDBALL_TYPE) \ 322 \ 323 V(MAP_TYPE) \ 324 V(CODE_TYPE) \ 325 V(MUTABLE_HEAP_NUMBER_TYPE) \ 326 V(FOREIGN_TYPE) \ 327 V(BYTE_ARRAY_TYPE) \ 328 V(BYTECODE_ARRAY_TYPE) \ 329 V(FREE_SPACE_TYPE) \ 330 \ 331 V(FIXED_INT8_ARRAY_TYPE) \ 332 V(FIXED_UINT8_ARRAY_TYPE) \ 333 V(FIXED_INT16_ARRAY_TYPE) \ 334 V(FIXED_UINT16_ARRAY_TYPE) \ 335 V(FIXED_INT32_ARRAY_TYPE) \ 336 V(FIXED_UINT32_ARRAY_TYPE) \ 337 V(FIXED_FLOAT32_ARRAY_TYPE) \ 338 V(FIXED_FLOAT64_ARRAY_TYPE) \ 339 V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \ 340 \ 341 V(FIXED_DOUBLE_ARRAY_TYPE) \ 342 V(FILLER_TYPE) \ 343 \ 344 V(ACCESSOR_INFO_TYPE) \ 345 V(ACCESSOR_PAIR_TYPE) \ 346 V(ACCESS_CHECK_INFO_TYPE) \ 347 V(INTERCEPTOR_INFO_TYPE) \ 348 V(CALL_HANDLER_INFO_TYPE) \ 349 V(FUNCTION_TEMPLATE_INFO_TYPE) \ 350 V(OBJECT_TEMPLATE_INFO_TYPE) \ 351 V(ALLOCATION_SITE_TYPE) \ 352 V(ALLOCATION_MEMENTO_TYPE) \ 353 V(SCRIPT_TYPE) \ 354 V(TYPE_FEEDBACK_INFO_TYPE) \ 355 V(ALIASED_ARGUMENTS_ENTRY_TYPE) \ 356 V(PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE) \ 357 V(PROMISE_REACTION_JOB_INFO_TYPE) \ 358 V(DEBUG_INFO_TYPE) \ 359 V(BREAK_POINT_INFO_TYPE) \ 360 V(PROTOTYPE_INFO_TYPE) \ 361 V(TUPLE2_TYPE) \ 362 V(TUPLE3_TYPE) \ 363 V(CONTEXT_EXTENSION_TYPE) \ 364 V(CONSTANT_ELEMENTS_PAIR_TYPE) \ 365 V(MODULE_TYPE) \ 366 V(MODULE_INFO_ENTRY_TYPE) \ 367 V(FIXED_ARRAY_TYPE) \ 368 V(TRANSITION_ARRAY_TYPE) \ 369 V(SHARED_FUNCTION_INFO_TYPE) \ 370 V(CELL_TYPE) \ 371 V(WEAK_CELL_TYPE) \ 372 V(PROPERTY_CELL_TYPE) \ 373 \ 374 V(JS_PROXY_TYPE) \ 375 V(JS_GLOBAL_OBJECT_TYPE) \ 376 V(JS_GLOBAL_PROXY_TYPE) \ 377 V(JS_SPECIAL_API_OBJECT_TYPE) \ 378 V(JS_VALUE_TYPE) \ 379 V(JS_MESSAGE_OBJECT_TYPE) \ 380 V(JS_DATE_TYPE) \ 381 V(JS_API_OBJECT_TYPE) \ 382 V(JS_OBJECT_TYPE) \ 383 V(JS_ARGUMENTS_TYPE) \ 384 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \ 385 V(JS_GENERATOR_OBJECT_TYPE) \ 386 V(JS_MODULE_NAMESPACE_TYPE) \ 387 V(JS_ARRAY_TYPE) \ 388 V(JS_ARRAY_BUFFER_TYPE) \ 389 V(JS_TYPED_ARRAY_TYPE) \ 390 V(JS_DATA_VIEW_TYPE) \ 391 V(JS_SET_TYPE) \ 392 V(JS_MAP_TYPE) \ 393 V(JS_SET_ITERATOR_TYPE) \ 394 V(JS_MAP_ITERATOR_TYPE) \ 395 V(JS_WEAK_MAP_TYPE) \ 396 V(JS_WEAK_SET_TYPE) \ 397 V(JS_PROMISE_CAPABILITY_TYPE) \ 398 V(JS_PROMISE_TYPE) \ 399 V(JS_REGEXP_TYPE) \ 400 V(JS_ERROR_TYPE) \ 401 V(JS_ASYNC_FROM_SYNC_ITERATOR_TYPE) \ 402 V(JS_STRING_ITERATOR_TYPE) \ 403 \ 404 V(JS_TYPED_ARRAY_KEY_ITERATOR_TYPE) \ 405 V(JS_FAST_ARRAY_KEY_ITERATOR_TYPE) \ 406 V(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE) \ 407 \ 408 V(JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 409 V(JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 410 V(JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 411 V(JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 412 V(JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 413 V(JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 414 V(JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 415 V(JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 416 V(JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 417 \ 418 V(JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 419 V(JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 420 V(JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 421 V(JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 422 V(JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 423 V(JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 424 V(JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE) \ 425 \ 426 V(JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE) \ 427 V(JS_INT8_ARRAY_VALUE_ITERATOR_TYPE) \ 428 V(JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE) \ 429 V(JS_INT16_ARRAY_VALUE_ITERATOR_TYPE) \ 430 V(JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE) \ 431 V(JS_INT32_ARRAY_VALUE_ITERATOR_TYPE) \ 432 V(JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE) \ 433 V(JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE) \ 434 V(JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE) \ 435 \ 436 V(JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE) \ 437 V(JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE) \ 438 V(JS_FAST_ARRAY_VALUE_ITERATOR_TYPE) \ 439 V(JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE) \ 440 V(JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE) \ 441 V(JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE) \ 442 V(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) \ 443 \ 444 V(JS_BOUND_FUNCTION_TYPE) \ 445 V(JS_FUNCTION_TYPE) 446 447 // Since string types are not consecutive, this macro is used to 448 // iterate over them. 449 #define STRING_TYPE_LIST(V) \ 450 V(STRING_TYPE, kVariableSizeSentinel, string, String) \ 451 V(ONE_BYTE_STRING_TYPE, kVariableSizeSentinel, one_byte_string, \ 452 OneByteString) \ 453 V(CONS_STRING_TYPE, ConsString::kSize, cons_string, ConsString) \ 454 V(CONS_ONE_BYTE_STRING_TYPE, ConsString::kSize, cons_one_byte_string, \ 455 ConsOneByteString) \ 456 V(SLICED_STRING_TYPE, SlicedString::kSize, sliced_string, SlicedString) \ 457 V(SLICED_ONE_BYTE_STRING_TYPE, SlicedString::kSize, sliced_one_byte_string, \ 458 SlicedOneByteString) \ 459 V(EXTERNAL_STRING_TYPE, ExternalTwoByteString::kSize, external_string, \ 460 ExternalString) \ 461 V(EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kSize, \ 462 external_one_byte_string, ExternalOneByteString) \ 463 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, ExternalTwoByteString::kSize, \ 464 external_string_with_one_byte_data, ExternalStringWithOneByteData) \ 465 V(SHORT_EXTERNAL_STRING_TYPE, ExternalTwoByteString::kShortSize, \ 466 short_external_string, ShortExternalString) \ 467 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kShortSize, \ 468 short_external_one_byte_string, ShortExternalOneByteString) \ 469 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 470 ExternalTwoByteString::kShortSize, \ 471 short_external_string_with_one_byte_data, \ 472 ShortExternalStringWithOneByteData) \ 473 \ 474 V(INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, internalized_string, \ 475 InternalizedString) \ 476 V(ONE_BYTE_INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, \ 477 one_byte_internalized_string, OneByteInternalizedString) \ 478 V(EXTERNAL_INTERNALIZED_STRING_TYPE, ExternalTwoByteString::kSize, \ 479 external_internalized_string, ExternalInternalizedString) \ 480 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, ExternalOneByteString::kSize, \ 481 external_one_byte_internalized_string, ExternalOneByteInternalizedString) \ 482 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 483 ExternalTwoByteString::kSize, \ 484 external_internalized_string_with_one_byte_data, \ 485 ExternalInternalizedStringWithOneByteData) \ 486 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE, \ 487 ExternalTwoByteString::kShortSize, short_external_internalized_string, \ 488 ShortExternalInternalizedString) \ 489 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, \ 490 ExternalOneByteString::kShortSize, \ 491 short_external_one_byte_internalized_string, \ 492 ShortExternalOneByteInternalizedString) \ 493 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 494 ExternalTwoByteString::kShortSize, \ 495 short_external_internalized_string_with_one_byte_data, \ 496 ShortExternalInternalizedStringWithOneByteData) \ 497 V(THIN_STRING_TYPE, ThinString::kSize, thin_string, ThinString) \ 498 V(THIN_ONE_BYTE_STRING_TYPE, ThinString::kSize, thin_one_byte_string, \ 499 ThinOneByteString) 500 501 // A struct is a simple object a set of object-valued fields. Including an 502 // object type in this causes the compiler to generate most of the boilerplate 503 // code for the class including allocation and garbage collection routines, 504 // casts and predicates. All you need to define is the class, methods and 505 // object verification routines. Easy, no? 506 // 507 // Note that for subtle reasons related to the ordering or numerical values of 508 // type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST 509 // manually. 510 #define STRUCT_LIST(V) \ 511 V(ACCESSOR_INFO, AccessorInfo, accessor_info) \ 512 V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \ 513 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \ 514 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \ 515 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \ 516 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \ 517 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \ 518 V(ALLOCATION_SITE, AllocationSite, allocation_site) \ 519 V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \ 520 V(SCRIPT, Script, script) \ 521 V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \ 522 V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry) \ 523 V(PROMISE_RESOLVE_THENABLE_JOB_INFO, PromiseResolveThenableJobInfo, \ 524 promise_resolve_thenable_job_info) \ 525 V(PROMISE_REACTION_JOB_INFO, PromiseReactionJobInfo, \ 526 promise_reaction_job_info) \ 527 V(DEBUG_INFO, DebugInfo, debug_info) \ 528 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info) \ 529 V(PROTOTYPE_INFO, PrototypeInfo, prototype_info) \ 530 V(TUPLE2, Tuple2, tuple2) \ 531 V(TUPLE3, Tuple3, tuple3) \ 532 V(CONTEXT_EXTENSION, ContextExtension, context_extension) \ 533 V(CONSTANT_ELEMENTS_PAIR, ConstantElementsPair, constant_elements_pair) \ 534 V(MODULE, Module, module) \ 535 V(MODULE_INFO_ENTRY, ModuleInfoEntry, module_info_entry) 536 537 // We use the full 8 bits of the instance_type field to encode heap object 538 // instance types. The high-order bit (bit 7) is set if the object is not a 539 // string, and cleared if it is a string. 540 const uint32_t kIsNotStringMask = 0x80; 541 const uint32_t kStringTag = 0x0; 542 const uint32_t kNotStringTag = 0x80; 543 544 // Bit 6 indicates that the object is an internalized string (if set) or not. 545 // Bit 7 has to be clear as well. 546 const uint32_t kIsNotInternalizedMask = 0x40; 547 const uint32_t kNotInternalizedTag = 0x40; 548 const uint32_t kInternalizedTag = 0x0; 549 550 // If bit 7 is clear then bit 3 indicates whether the string consists of 551 // two-byte characters or one-byte characters. 552 const uint32_t kStringEncodingMask = 0x8; 553 const uint32_t kTwoByteStringTag = 0x0; 554 const uint32_t kOneByteStringTag = 0x8; 555 556 // If bit 7 is clear, the low-order 3 bits indicate the representation 557 // of the string. 558 const uint32_t kStringRepresentationMask = 0x07; 559 enum StringRepresentationTag { 560 kSeqStringTag = 0x0, 561 kConsStringTag = 0x1, 562 kExternalStringTag = 0x2, 563 kSlicedStringTag = 0x3, 564 kThinStringTag = 0x5 565 }; 566 const uint32_t kIsIndirectStringMask = 0x1; 567 const uint32_t kIsIndirectStringTag = 0x1; 568 STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0); // NOLINT 569 STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0); // NOLINT 570 STATIC_ASSERT((kConsStringTag & 571 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT 572 STATIC_ASSERT((kSlicedStringTag & 573 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT 574 STATIC_ASSERT((kThinStringTag & kIsIndirectStringMask) == kIsIndirectStringTag); 575 576 // If bit 7 is clear, then bit 4 indicates whether this two-byte 577 // string actually contains one byte data. 578 const uint32_t kOneByteDataHintMask = 0x10; 579 const uint32_t kOneByteDataHintTag = 0x10; 580 581 // If bit 7 is clear and string representation indicates an external string, 582 // then bit 5 indicates whether the data pointer is cached. 583 const uint32_t kShortExternalStringMask = 0x20; 584 const uint32_t kShortExternalStringTag = 0x20; 585 586 // A ConsString with an empty string as the right side is a candidate 587 // for being shortcut by the garbage collector. We don't allocate any 588 // non-flat internalized strings, so we do not shortcut them thereby 589 // avoiding turning internalized strings into strings. The bit-masks 590 // below contain the internalized bit as additional safety. 591 // See heap.cc, mark-compact.cc and objects-visiting.cc. 592 const uint32_t kShortcutTypeMask = 593 kIsNotStringMask | 594 kIsNotInternalizedMask | 595 kStringRepresentationMask; 596 const uint32_t kShortcutTypeTag = kConsStringTag | kNotInternalizedTag; 597 598 static inline bool IsShortcutCandidate(int type) { 599 return ((type & kShortcutTypeMask) == kShortcutTypeTag); 600 } 601 602 enum InstanceType { 603 // String types. 604 INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kSeqStringTag | 605 kInternalizedTag, // FIRST_PRIMITIVE_TYPE 606 ONE_BYTE_INTERNALIZED_STRING_TYPE = 607 kOneByteStringTag | kSeqStringTag | kInternalizedTag, 608 EXTERNAL_INTERNALIZED_STRING_TYPE = 609 kTwoByteStringTag | kExternalStringTag | kInternalizedTag, 610 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE = 611 kOneByteStringTag | kExternalStringTag | kInternalizedTag, 612 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE = 613 EXTERNAL_INTERNALIZED_STRING_TYPE | kOneByteDataHintTag | 614 kInternalizedTag, 615 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE = EXTERNAL_INTERNALIZED_STRING_TYPE | 616 kShortExternalStringTag | 617 kInternalizedTag, 618 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE = 619 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kShortExternalStringTag | 620 kInternalizedTag, 621 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE = 622 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 623 kShortExternalStringTag | kInternalizedTag, 624 STRING_TYPE = INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 625 ONE_BYTE_STRING_TYPE = 626 ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 627 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag | kNotInternalizedTag, 628 CONS_ONE_BYTE_STRING_TYPE = 629 kOneByteStringTag | kConsStringTag | kNotInternalizedTag, 630 SLICED_STRING_TYPE = 631 kTwoByteStringTag | kSlicedStringTag | kNotInternalizedTag, 632 SLICED_ONE_BYTE_STRING_TYPE = 633 kOneByteStringTag | kSlicedStringTag | kNotInternalizedTag, 634 EXTERNAL_STRING_TYPE = 635 EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 636 EXTERNAL_ONE_BYTE_STRING_TYPE = 637 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 638 EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE = 639 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 640 kNotInternalizedTag, 641 SHORT_EXTERNAL_STRING_TYPE = 642 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 643 SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE = 644 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 645 SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE = 646 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 647 kNotInternalizedTag, 648 THIN_STRING_TYPE = kTwoByteStringTag | kThinStringTag | kNotInternalizedTag, 649 THIN_ONE_BYTE_STRING_TYPE = 650 kOneByteStringTag | kThinStringTag | kNotInternalizedTag, 651 652 // Non-string names 653 SYMBOL_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE 654 655 // Other primitives (cannot contain non-map-word pointers to heap objects). 656 HEAP_NUMBER_TYPE, 657 ODDBALL_TYPE, // LAST_PRIMITIVE_TYPE 658 659 // Objects allocated in their own spaces (never in new space). 660 MAP_TYPE, 661 CODE_TYPE, 662 663 // "Data", objects that cannot contain non-map-word pointers to heap 664 // objects. 665 MUTABLE_HEAP_NUMBER_TYPE, 666 FOREIGN_TYPE, 667 BYTE_ARRAY_TYPE, 668 BYTECODE_ARRAY_TYPE, 669 FREE_SPACE_TYPE, 670 FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE 671 FIXED_UINT8_ARRAY_TYPE, 672 FIXED_INT16_ARRAY_TYPE, 673 FIXED_UINT16_ARRAY_TYPE, 674 FIXED_INT32_ARRAY_TYPE, 675 FIXED_UINT32_ARRAY_TYPE, 676 FIXED_FLOAT32_ARRAY_TYPE, 677 FIXED_FLOAT64_ARRAY_TYPE, 678 FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE 679 FIXED_DOUBLE_ARRAY_TYPE, 680 FILLER_TYPE, // LAST_DATA_TYPE 681 682 // Structs. 683 ACCESSOR_INFO_TYPE, 684 ACCESSOR_PAIR_TYPE, 685 ACCESS_CHECK_INFO_TYPE, 686 INTERCEPTOR_INFO_TYPE, 687 CALL_HANDLER_INFO_TYPE, 688 FUNCTION_TEMPLATE_INFO_TYPE, 689 OBJECT_TEMPLATE_INFO_TYPE, 690 ALLOCATION_SITE_TYPE, 691 ALLOCATION_MEMENTO_TYPE, 692 SCRIPT_TYPE, 693 TYPE_FEEDBACK_INFO_TYPE, 694 ALIASED_ARGUMENTS_ENTRY_TYPE, 695 PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE, 696 PROMISE_REACTION_JOB_INFO_TYPE, 697 DEBUG_INFO_TYPE, 698 BREAK_POINT_INFO_TYPE, 699 PROTOTYPE_INFO_TYPE, 700 TUPLE2_TYPE, 701 TUPLE3_TYPE, 702 CONTEXT_EXTENSION_TYPE, 703 CONSTANT_ELEMENTS_PAIR_TYPE, 704 MODULE_TYPE, 705 MODULE_INFO_ENTRY_TYPE, 706 FIXED_ARRAY_TYPE, 707 TRANSITION_ARRAY_TYPE, 708 SHARED_FUNCTION_INFO_TYPE, 709 CELL_TYPE, 710 WEAK_CELL_TYPE, 711 PROPERTY_CELL_TYPE, 712 713 // All the following types are subtypes of JSReceiver, which corresponds to 714 // objects in the JS sense. The first and the last type in this range are 715 // the two forms of function. This organization enables using the same 716 // compares for checking the JS_RECEIVER and the NONCALLABLE_JS_OBJECT range. 717 JS_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE 718 JS_GLOBAL_OBJECT_TYPE, // FIRST_JS_OBJECT_TYPE 719 JS_GLOBAL_PROXY_TYPE, 720 // Like JS_API_OBJECT_TYPE, but requires access checks and/or has 721 // interceptors. 722 JS_SPECIAL_API_OBJECT_TYPE, // LAST_SPECIAL_RECEIVER_TYPE 723 JS_VALUE_TYPE, // LAST_CUSTOM_ELEMENTS_RECEIVER 724 JS_MESSAGE_OBJECT_TYPE, 725 JS_DATE_TYPE, 726 // Like JS_OBJECT_TYPE, but created from API function. 727 JS_API_OBJECT_TYPE, 728 JS_OBJECT_TYPE, 729 JS_ARGUMENTS_TYPE, 730 JS_CONTEXT_EXTENSION_OBJECT_TYPE, 731 JS_GENERATOR_OBJECT_TYPE, 732 JS_MODULE_NAMESPACE_TYPE, 733 JS_ARRAY_TYPE, 734 JS_ARRAY_BUFFER_TYPE, 735 JS_TYPED_ARRAY_TYPE, 736 JS_DATA_VIEW_TYPE, 737 JS_SET_TYPE, 738 JS_MAP_TYPE, 739 JS_SET_ITERATOR_TYPE, 740 JS_MAP_ITERATOR_TYPE, 741 JS_WEAK_MAP_TYPE, 742 JS_WEAK_SET_TYPE, 743 JS_PROMISE_CAPABILITY_TYPE, 744 JS_PROMISE_TYPE, 745 JS_REGEXP_TYPE, 746 JS_ERROR_TYPE, 747 JS_ASYNC_FROM_SYNC_ITERATOR_TYPE, 748 JS_STRING_ITERATOR_TYPE, 749 750 JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, 751 JS_FAST_ARRAY_KEY_ITERATOR_TYPE, 752 JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE, 753 754 JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, 755 JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, 756 JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, 757 JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE, 758 JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, 759 JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, 760 JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE, 761 JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE, 762 JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE, 763 764 JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, 765 JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE, 766 JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE, 767 JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE, 768 JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, 769 JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE, 770 JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE, 771 772 JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE, 773 JS_INT8_ARRAY_VALUE_ITERATOR_TYPE, 774 JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE, 775 JS_INT16_ARRAY_VALUE_ITERATOR_TYPE, 776 JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE, 777 JS_INT32_ARRAY_VALUE_ITERATOR_TYPE, 778 JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE, 779 JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE, 780 JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE, 781 782 JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE, 783 JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE, 784 JS_FAST_ARRAY_VALUE_ITERATOR_TYPE, 785 JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE, 786 JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, 787 JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE, 788 JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE, 789 790 JS_BOUND_FUNCTION_TYPE, 791 JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE 792 793 // Pseudo-types 794 FIRST_TYPE = 0x0, 795 LAST_TYPE = JS_FUNCTION_TYPE, 796 FIRST_NAME_TYPE = FIRST_TYPE, 797 LAST_NAME_TYPE = SYMBOL_TYPE, 798 FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE, 799 LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE, 800 FIRST_NONSTRING_TYPE = SYMBOL_TYPE, 801 FIRST_PRIMITIVE_TYPE = FIRST_NAME_TYPE, 802 LAST_PRIMITIVE_TYPE = ODDBALL_TYPE, 803 FIRST_FUNCTION_TYPE = JS_BOUND_FUNCTION_TYPE, 804 LAST_FUNCTION_TYPE = JS_FUNCTION_TYPE, 805 // Boundaries for testing for a fixed typed array. 806 FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE, 807 LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE, 808 // Boundary for promotion to old space. 809 LAST_DATA_TYPE = FILLER_TYPE, 810 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy). 811 // Note that there is no range for JSObject or JSProxy, since their subtypes 812 // are not continuous in this enum! The enum ranges instead reflect the 813 // external class names, where proxies are treated as either ordinary objects, 814 // or functions. 815 FIRST_JS_RECEIVER_TYPE = JS_PROXY_TYPE, 816 LAST_JS_RECEIVER_TYPE = LAST_TYPE, 817 // Boundaries for testing the types represented as JSObject 818 FIRST_JS_OBJECT_TYPE = JS_GLOBAL_OBJECT_TYPE, 819 LAST_JS_OBJECT_TYPE = LAST_TYPE, 820 // Boundary for testing JSReceivers that need special property lookup handling 821 LAST_SPECIAL_RECEIVER_TYPE = JS_SPECIAL_API_OBJECT_TYPE, 822 // Boundary case for testing JSReceivers that may have elements while having 823 // an empty fixed array as elements backing store. This is true for string 824 // wrappers. 825 LAST_CUSTOM_ELEMENTS_RECEIVER = JS_VALUE_TYPE, 826 827 FIRST_ARRAY_KEY_ITERATOR_TYPE = JS_TYPED_ARRAY_KEY_ITERATOR_TYPE, 828 LAST_ARRAY_KEY_ITERATOR_TYPE = JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE, 829 830 FIRST_ARRAY_KEY_VALUE_ITERATOR_TYPE = JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE, 831 LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE = JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE, 832 833 FIRST_ARRAY_VALUE_ITERATOR_TYPE = JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE, 834 LAST_ARRAY_VALUE_ITERATOR_TYPE = JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE, 835 836 FIRST_ARRAY_ITERATOR_TYPE = FIRST_ARRAY_KEY_ITERATOR_TYPE, 837 LAST_ARRAY_ITERATOR_TYPE = LAST_ARRAY_VALUE_ITERATOR_TYPE, 838 }; 839 840 STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType); 841 STATIC_ASSERT(JS_API_OBJECT_TYPE == Internals::kJSApiObjectType); 842 STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType); 843 STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType); 844 STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType); 845 846 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 847 InstanceType instance_type); 848 849 #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \ 850 V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \ 851 V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \ 852 V(CODE_STUBS_TABLE_SUB_TYPE) \ 853 V(COMPILATION_CACHE_TABLE_SUB_TYPE) \ 854 V(CONTEXT_SUB_TYPE) \ 855 V(COPY_ON_WRITE_SUB_TYPE) \ 856 V(DEOPTIMIZATION_DATA_SUB_TYPE) \ 857 V(DESCRIPTOR_ARRAY_SUB_TYPE) \ 858 V(EMBEDDED_OBJECT_SUB_TYPE) \ 859 V(ENUM_CACHE_SUB_TYPE) \ 860 V(ENUM_INDICES_CACHE_SUB_TYPE) \ 861 V(DEPENDENT_CODE_SUB_TYPE) \ 862 V(DICTIONARY_ELEMENTS_SUB_TYPE) \ 863 V(DICTIONARY_PROPERTIES_SUB_TYPE) \ 864 V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \ 865 V(FAST_ELEMENTS_SUB_TYPE) \ 866 V(FAST_PROPERTIES_SUB_TYPE) \ 867 V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \ 868 V(HANDLER_TABLE_SUB_TYPE) \ 869 V(JS_COLLECTION_SUB_TYPE) \ 870 V(JS_WEAK_COLLECTION_SUB_TYPE) \ 871 V(MAP_CODE_CACHE_SUB_TYPE) \ 872 V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \ 873 V(NUMBER_STRING_CACHE_SUB_TYPE) \ 874 V(OBJECT_TO_CODE_SUB_TYPE) \ 875 V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \ 876 V(OPTIMIZED_CODE_MAP_SUB_TYPE) \ 877 V(PROTOTYPE_USERS_SUB_TYPE) \ 878 V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \ 879 V(RETAINED_MAPS_SUB_TYPE) \ 880 V(SCOPE_INFO_SUB_TYPE) \ 881 V(SCRIPT_LIST_SUB_TYPE) \ 882 V(SERIALIZED_TEMPLATES_SUB_TYPE) \ 883 V(SHARED_FUNCTION_INFOS_SUB_TYPE) \ 884 V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \ 885 V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \ 886 V(STRING_SPLIT_CACHE_SUB_TYPE) \ 887 V(STRING_TABLE_SUB_TYPE) \ 888 V(TEMPLATE_INFO_SUB_TYPE) \ 889 V(FEEDBACK_VECTOR_SUB_TYPE) \ 890 V(FEEDBACK_METADATA_SUB_TYPE) \ 891 V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE) 892 893 enum FixedArraySubInstanceType { 894 #define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name, 895 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE) 896 #undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE 897 LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE 898 }; 899 900 901 // TODO(bmeurer): Remove this in favor of the ComparisonResult below. 902 enum CompareResult { 903 LESS = -1, 904 EQUAL = 0, 905 GREATER = 1, 906 907 NOT_EQUAL = GREATER 908 }; 909 910 911 // Result of an abstract relational comparison of x and y, implemented according 912 // to ES6 section 7.2.11 Abstract Relational Comparison. 913 enum class ComparisonResult { 914 kLessThan, // x < y 915 kEqual, // x = y 916 kGreaterThan, // x > y 917 kUndefined // at least one of x or y was undefined or NaN 918 }; 919 920 921 class AbstractCode; 922 class AccessorPair; 923 class AllocationSite; 924 class AllocationSiteCreationContext; 925 class AllocationSiteUsageContext; 926 class Cell; 927 class ConsString; 928 class ElementsAccessor; 929 class FindAndReplacePattern; 930 class FixedArrayBase; 931 class FunctionLiteral; 932 class JSGlobalObject; 933 class KeyAccumulator; 934 class LayoutDescriptor; 935 class LookupIterator; 936 class FieldType; 937 class Module; 938 class ModuleDescriptor; 939 class ModuleInfoEntry; 940 class ModuleInfo; 941 class ObjectHashTable; 942 class ObjectVisitor; 943 class PropertyCell; 944 class PropertyDescriptor; 945 class SafepointEntry; 946 class SharedFunctionInfo; 947 class StringStream; 948 class TypeFeedbackInfo; 949 class FeedbackMetadata; 950 class FeedbackVector; 951 class WeakCell; 952 class TransitionArray; 953 class TemplateList; 954 955 // A template-ized version of the IsXXX functions. 956 template <class C> inline bool Is(Object* obj); 957 958 #ifdef OBJECT_PRINT 959 #define DECLARE_PRINTER(Name) void Name##Print(std::ostream& os); // NOLINT 960 #else 961 #define DECLARE_PRINTER(Name) 962 #endif 963 964 #define OBJECT_TYPE_LIST(V) \ 965 V(Smi) \ 966 V(LayoutDescriptor) \ 967 V(HeapObject) \ 968 V(Primitive) \ 969 V(Number) 970 971 #define HEAP_OBJECT_TYPE_LIST(V) \ 972 V(HeapNumber) \ 973 V(MutableHeapNumber) \ 974 V(Name) \ 975 V(UniqueName) \ 976 V(String) \ 977 V(SeqString) \ 978 V(ExternalString) \ 979 V(ConsString) \ 980 V(SlicedString) \ 981 V(ExternalTwoByteString) \ 982 V(ExternalOneByteString) \ 983 V(SeqTwoByteString) \ 984 V(SeqOneByteString) \ 985 V(InternalizedString) \ 986 V(ThinString) \ 987 V(Symbol) \ 988 \ 989 V(FixedTypedArrayBase) \ 990 V(FixedUint8Array) \ 991 V(FixedInt8Array) \ 992 V(FixedUint16Array) \ 993 V(FixedInt16Array) \ 994 V(FixedUint32Array) \ 995 V(FixedInt32Array) \ 996 V(FixedFloat32Array) \ 997 V(FixedFloat64Array) \ 998 V(FixedUint8ClampedArray) \ 999 V(ByteArray) \ 1000 V(BytecodeArray) \ 1001 V(FreeSpace) \ 1002 V(JSReceiver) \ 1003 V(JSObject) \ 1004 V(JSArgumentsObject) \ 1005 V(JSContextExtensionObject) \ 1006 V(JSGeneratorObject) \ 1007 V(JSModuleNamespace) \ 1008 V(Map) \ 1009 V(DescriptorArray) \ 1010 V(FrameArray) \ 1011 V(TransitionArray) \ 1012 V(FeedbackMetadata) \ 1013 V(FeedbackVector) \ 1014 V(DeoptimizationInputData) \ 1015 V(DeoptimizationOutputData) \ 1016 V(DependentCode) \ 1017 V(HandlerTable) \ 1018 V(FixedArray) \ 1019 V(BoilerplateDescription) \ 1020 V(FixedDoubleArray) \ 1021 V(WeakFixedArray) \ 1022 V(ArrayList) \ 1023 V(RegExpMatchInfo) \ 1024 V(Context) \ 1025 V(ScriptContextTable) \ 1026 V(NativeContext) \ 1027 V(ScopeInfo) \ 1028 V(ModuleInfo) \ 1029 V(JSBoundFunction) \ 1030 V(JSFunction) \ 1031 V(Code) \ 1032 V(AbstractCode) \ 1033 V(Oddball) \ 1034 V(SharedFunctionInfo) \ 1035 V(JSValue) \ 1036 V(JSDate) \ 1037 V(JSMessageObject) \ 1038 V(StringWrapper) \ 1039 V(Foreign) \ 1040 V(Boolean) \ 1041 V(JSArray) \ 1042 V(JSArrayBuffer) \ 1043 V(JSArrayBufferView) \ 1044 V(JSAsyncFromSyncIterator) \ 1045 V(JSCollection) \ 1046 V(JSTypedArray) \ 1047 V(JSArrayIterator) \ 1048 V(JSDataView) \ 1049 V(JSProxy) \ 1050 V(JSError) \ 1051 V(JSPromiseCapability) \ 1052 V(JSPromise) \ 1053 V(JSStringIterator) \ 1054 V(JSSet) \ 1055 V(JSMap) \ 1056 V(JSSetIterator) \ 1057 V(JSMapIterator) \ 1058 V(JSWeakCollection) \ 1059 V(JSWeakMap) \ 1060 V(JSWeakSet) \ 1061 V(JSRegExp) \ 1062 V(HashTable) \ 1063 V(Dictionary) \ 1064 V(UnseededNumberDictionary) \ 1065 V(StringTable) \ 1066 V(StringSet) \ 1067 V(NormalizedMapCache) \ 1068 V(CompilationCacheTable) \ 1069 V(CodeCacheHashTable) \ 1070 V(MapCache) \ 1071 V(JSGlobalObject) \ 1072 V(JSGlobalProxy) \ 1073 V(Undetectable) \ 1074 V(AccessCheckNeeded) \ 1075 V(Callable) \ 1076 V(Function) \ 1077 V(Constructor) \ 1078 V(TemplateInfo) \ 1079 V(Filler) \ 1080 V(FixedArrayBase) \ 1081 V(External) \ 1082 V(Struct) \ 1083 V(Cell) \ 1084 V(TemplateList) \ 1085 V(PropertyCell) \ 1086 V(WeakCell) \ 1087 V(ObjectHashTable) \ 1088 V(ObjectHashSet) \ 1089 V(WeakHashTable) \ 1090 V(OrderedHashTable) 1091 1092 #define ODDBALL_LIST(V) \ 1093 V(Undefined, undefined_value) \ 1094 V(Null, null_value) \ 1095 V(TheHole, the_hole_value) \ 1096 V(Exception, exception) \ 1097 V(Uninitialized, uninitialized_value) \ 1098 V(True, true_value) \ 1099 V(False, false_value) \ 1100 V(ArgumentsMarker, arguments_marker) \ 1101 V(OptimizedOut, optimized_out) \ 1102 V(StaleRegister, stale_register) 1103 1104 // The element types selection for CreateListFromArrayLike. 1105 enum class ElementTypes { kAll, kStringAndSymbol }; 1106 1107 // Object is the abstract superclass for all classes in the 1108 // object hierarchy. 1109 // Object does not use any virtual functions to avoid the 1110 // allocation of the C++ vtable. 1111 // Since both Smi and HeapObject are subclasses of Object no 1112 // data members can be present in Object. 1113 class Object { 1114 public: 1115 // Type testing. 1116 bool IsObject() const { return true; } 1117 1118 #define IS_TYPE_FUNCTION_DECL(Type) INLINE(bool Is##Type() const); 1119 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) 1120 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) 1121 #undef IS_TYPE_FUNCTION_DECL 1122 1123 #define IS_TYPE_FUNCTION_DECL(Type, Value) \ 1124 INLINE(bool Is##Type(Isolate* isolate) const); 1125 ODDBALL_LIST(IS_TYPE_FUNCTION_DECL) 1126 #undef IS_TYPE_FUNCTION_DECL 1127 1128 INLINE(bool IsNullOrUndefined(Isolate* isolate) const); 1129 1130 // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas 1131 // a keyed store is of the form a[expression] = foo. 1132 enum StoreFromKeyed { 1133 MAY_BE_STORE_FROM_KEYED, 1134 CERTAINLY_NOT_STORE_FROM_KEYED 1135 }; 1136 1137 enum ShouldThrow { THROW_ON_ERROR, DONT_THROW }; 1138 1139 #define RETURN_FAILURE(isolate, should_throw, call) \ 1140 do { \ 1141 if ((should_throw) == DONT_THROW) { \ 1142 return Just(false); \ 1143 } else { \ 1144 isolate->Throw(*isolate->factory()->call); \ 1145 return Nothing<bool>(); \ 1146 } \ 1147 } while (false) 1148 1149 #define MAYBE_RETURN(call, value) \ 1150 do { \ 1151 if ((call).IsNothing()) return value; \ 1152 } while (false) 1153 1154 #define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>()) 1155 1156 #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \ 1157 INLINE(bool Is##Name() const); 1158 STRUCT_LIST(DECLARE_STRUCT_PREDICATE) 1159 #undef DECLARE_STRUCT_PREDICATE 1160 1161 // ES6, section 7.2.2 IsArray. NOT to be confused with %_IsArray. 1162 MUST_USE_RESULT static Maybe<bool> IsArray(Handle<Object> object); 1163 1164 INLINE(bool IsNameDictionary() const); 1165 INLINE(bool IsGlobalDictionary() const); 1166 INLINE(bool IsSeededNumberDictionary() const); 1167 INLINE(bool IsOrderedHashSet() const); 1168 INLINE(bool IsOrderedHashMap() const); 1169 1170 // Extract the number. 1171 inline double Number() const; 1172 INLINE(bool IsNaN() const); 1173 INLINE(bool IsMinusZero() const); 1174 bool ToInt32(int32_t* value); 1175 inline bool ToUint32(uint32_t* value); 1176 1177 inline Representation OptimalRepresentation(); 1178 1179 inline ElementsKind OptimalElementsKind(); 1180 1181 inline bool FitsRepresentation(Representation representation); 1182 1183 // Checks whether two valid primitive encodings of a property name resolve to 1184 // the same logical property. E.g., the smi 1, the string "1" and the double 1185 // 1 all refer to the same property, so this helper will return true. 1186 inline bool KeyEquals(Object* other); 1187 1188 inline bool FilterKey(PropertyFilter filter); 1189 1190 Handle<FieldType> OptimalType(Isolate* isolate, 1191 Representation representation); 1192 1193 inline static Handle<Object> NewStorageFor(Isolate* isolate, 1194 Handle<Object> object, 1195 Representation representation); 1196 1197 inline static Handle<Object> WrapForRead(Isolate* isolate, 1198 Handle<Object> object, 1199 Representation representation); 1200 1201 // Returns true if the object is of the correct type to be used as a 1202 // implementation of a JSObject's elements. 1203 inline bool HasValidElements(); 1204 1205 inline bool HasSpecificClassOf(String* name); 1206 1207 bool BooleanValue(); // ECMA-262 9.2. 1208 1209 // ES6 section 7.2.11 Abstract Relational Comparison 1210 MUST_USE_RESULT static Maybe<ComparisonResult> Compare(Handle<Object> x, 1211 Handle<Object> y); 1212 1213 // ES6 section 7.2.12 Abstract Equality Comparison 1214 MUST_USE_RESULT static Maybe<bool> Equals(Handle<Object> x, Handle<Object> y); 1215 1216 // ES6 section 7.2.13 Strict Equality Comparison 1217 bool StrictEquals(Object* that); 1218 1219 // Convert to a JSObject if needed. 1220 // native_context is used when creating wrapper object. 1221 MUST_USE_RESULT static inline MaybeHandle<JSReceiver> ToObject( 1222 Isolate* isolate, Handle<Object> object); 1223 MUST_USE_RESULT static MaybeHandle<JSReceiver> ToObject( 1224 Isolate* isolate, Handle<Object> object, Handle<Context> context); 1225 1226 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee. 1227 MUST_USE_RESULT static MaybeHandle<JSReceiver> ConvertReceiver( 1228 Isolate* isolate, Handle<Object> object); 1229 1230 // ES6 section 7.1.14 ToPropertyKey 1231 MUST_USE_RESULT static inline MaybeHandle<Name> ToName(Isolate* isolate, 1232 Handle<Object> input); 1233 1234 // ES6 section 7.1.1 ToPrimitive 1235 MUST_USE_RESULT static inline MaybeHandle<Object> ToPrimitive( 1236 Handle<Object> input, ToPrimitiveHint hint = ToPrimitiveHint::kDefault); 1237 1238 // ES6 section 7.1.3 ToNumber 1239 MUST_USE_RESULT static inline MaybeHandle<Object> ToNumber( 1240 Handle<Object> input); 1241 1242 // ES6 section 7.1.4 ToInteger 1243 MUST_USE_RESULT static inline MaybeHandle<Object> ToInteger( 1244 Isolate* isolate, Handle<Object> input); 1245 1246 // ES6 section 7.1.5 ToInt32 1247 MUST_USE_RESULT static inline MaybeHandle<Object> ToInt32( 1248 Isolate* isolate, Handle<Object> input); 1249 1250 // ES6 section 7.1.6 ToUint32 1251 MUST_USE_RESULT inline static MaybeHandle<Object> ToUint32( 1252 Isolate* isolate, Handle<Object> input); 1253 1254 // ES6 section 7.1.12 ToString 1255 MUST_USE_RESULT static inline MaybeHandle<String> ToString( 1256 Isolate* isolate, Handle<Object> input); 1257 1258 static Handle<String> NoSideEffectsToString(Isolate* isolate, 1259 Handle<Object> input); 1260 1261 // ES6 section 7.1.14 ToPropertyKey 1262 MUST_USE_RESULT static inline MaybeHandle<Object> ToPropertyKey( 1263 Isolate* isolate, Handle<Object> value); 1264 1265 // ES6 section 7.1.15 ToLength 1266 MUST_USE_RESULT static inline MaybeHandle<Object> ToLength( 1267 Isolate* isolate, Handle<Object> input); 1268 1269 // ES6 section 7.1.17 ToIndex 1270 MUST_USE_RESULT static inline MaybeHandle<Object> ToIndex( 1271 Isolate* isolate, Handle<Object> input, 1272 MessageTemplate::Template error_index); 1273 1274 // ES6 section 7.3.9 GetMethod 1275 MUST_USE_RESULT static MaybeHandle<Object> GetMethod( 1276 Handle<JSReceiver> receiver, Handle<Name> name); 1277 1278 // ES6 section 7.3.17 CreateListFromArrayLike 1279 MUST_USE_RESULT static MaybeHandle<FixedArray> CreateListFromArrayLike( 1280 Isolate* isolate, Handle<Object> object, ElementTypes element_types); 1281 1282 // Get length property and apply ToLength. 1283 MUST_USE_RESULT static MaybeHandle<Object> GetLengthFromArrayLike( 1284 Isolate* isolate, Handle<Object> object); 1285 1286 // ES6 section 12.5.6 The typeof Operator 1287 static Handle<String> TypeOf(Isolate* isolate, Handle<Object> object); 1288 1289 // ES6 section 12.6 Multiplicative Operators 1290 MUST_USE_RESULT static MaybeHandle<Object> Multiply(Isolate* isolate, 1291 Handle<Object> lhs, 1292 Handle<Object> rhs); 1293 MUST_USE_RESULT static MaybeHandle<Object> Divide(Isolate* isolate, 1294 Handle<Object> lhs, 1295 Handle<Object> rhs); 1296 MUST_USE_RESULT static MaybeHandle<Object> Modulus(Isolate* isolate, 1297 Handle<Object> lhs, 1298 Handle<Object> rhs); 1299 1300 // ES6 section 12.7 Additive Operators 1301 MUST_USE_RESULT static MaybeHandle<Object> Add(Isolate* isolate, 1302 Handle<Object> lhs, 1303 Handle<Object> rhs); 1304 MUST_USE_RESULT static MaybeHandle<Object> Subtract(Isolate* isolate, 1305 Handle<Object> lhs, 1306 Handle<Object> rhs); 1307 1308 // ES6 section 12.8 Bitwise Shift Operators 1309 MUST_USE_RESULT static MaybeHandle<Object> ShiftLeft(Isolate* isolate, 1310 Handle<Object> lhs, 1311 Handle<Object> rhs); 1312 MUST_USE_RESULT static MaybeHandle<Object> ShiftRight(Isolate* isolate, 1313 Handle<Object> lhs, 1314 Handle<Object> rhs); 1315 MUST_USE_RESULT static MaybeHandle<Object> ShiftRightLogical( 1316 Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs); 1317 1318 // ES6 section 12.9 Relational Operators 1319 MUST_USE_RESULT static inline Maybe<bool> GreaterThan(Handle<Object> x, 1320 Handle<Object> y); 1321 MUST_USE_RESULT static inline Maybe<bool> GreaterThanOrEqual( 1322 Handle<Object> x, Handle<Object> y); 1323 MUST_USE_RESULT static inline Maybe<bool> LessThan(Handle<Object> x, 1324 Handle<Object> y); 1325 MUST_USE_RESULT static inline Maybe<bool> LessThanOrEqual(Handle<Object> x, 1326 Handle<Object> y); 1327 1328 // ES6 section 12.11 Binary Bitwise Operators 1329 MUST_USE_RESULT static MaybeHandle<Object> BitwiseAnd(Isolate* isolate, 1330 Handle<Object> lhs, 1331 Handle<Object> rhs); 1332 MUST_USE_RESULT static MaybeHandle<Object> BitwiseOr(Isolate* isolate, 1333 Handle<Object> lhs, 1334 Handle<Object> rhs); 1335 MUST_USE_RESULT static MaybeHandle<Object> BitwiseXor(Isolate* isolate, 1336 Handle<Object> lhs, 1337 Handle<Object> rhs); 1338 1339 // ES6 section 7.3.19 OrdinaryHasInstance (C, O). 1340 MUST_USE_RESULT static MaybeHandle<Object> OrdinaryHasInstance( 1341 Isolate* isolate, Handle<Object> callable, Handle<Object> object); 1342 1343 // ES6 section 12.10.4 Runtime Semantics: InstanceofOperator(O, C) 1344 MUST_USE_RESULT static MaybeHandle<Object> InstanceOf( 1345 Isolate* isolate, Handle<Object> object, Handle<Object> callable); 1346 1347 V8_EXPORT_PRIVATE MUST_USE_RESULT static MaybeHandle<Object> GetProperty( 1348 LookupIterator* it); 1349 1350 // ES6 [[Set]] (when passed DONT_THROW) 1351 // Invariants for this and related functions (unless stated otherwise): 1352 // 1) When the result is Nothing, an exception is pending. 1353 // 2) When passed THROW_ON_ERROR, the result is never Just(false). 1354 // In some cases, an exception is thrown regardless of the ShouldThrow 1355 // argument. These cases are either in accordance with the spec or not 1356 // covered by it (eg., concerning API callbacks). 1357 MUST_USE_RESULT static Maybe<bool> SetProperty(LookupIterator* it, 1358 Handle<Object> value, 1359 LanguageMode language_mode, 1360 StoreFromKeyed store_mode); 1361 MUST_USE_RESULT static MaybeHandle<Object> SetProperty( 1362 Handle<Object> object, Handle<Name> name, Handle<Object> value, 1363 LanguageMode language_mode, 1364 StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); 1365 MUST_USE_RESULT static inline MaybeHandle<Object> SetPropertyOrElement( 1366 Handle<Object> object, Handle<Name> name, Handle<Object> value, 1367 LanguageMode language_mode, 1368 StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); 1369 1370 MUST_USE_RESULT static Maybe<bool> SetSuperProperty( 1371 LookupIterator* it, Handle<Object> value, LanguageMode language_mode, 1372 StoreFromKeyed store_mode); 1373 1374 MUST_USE_RESULT static Maybe<bool> CannotCreateProperty( 1375 Isolate* isolate, Handle<Object> receiver, Handle<Object> name, 1376 Handle<Object> value, ShouldThrow should_throw); 1377 MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty( 1378 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); 1379 MUST_USE_RESULT static Maybe<bool> WriteToReadOnlyProperty( 1380 Isolate* isolate, Handle<Object> receiver, Handle<Object> name, 1381 Handle<Object> value, ShouldThrow should_throw); 1382 MUST_USE_RESULT static Maybe<bool> RedefineIncompatibleProperty( 1383 Isolate* isolate, Handle<Object> name, Handle<Object> value, 1384 ShouldThrow should_throw); 1385 MUST_USE_RESULT static Maybe<bool> SetDataProperty(LookupIterator* it, 1386 Handle<Object> value); 1387 MUST_USE_RESULT static Maybe<bool> AddDataProperty( 1388 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 1389 ShouldThrow should_throw, StoreFromKeyed store_mode); 1390 MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( 1391 Handle<Object> object, Handle<Name> name); 1392 MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( 1393 Handle<Object> receiver, Handle<Name> name, Handle<JSReceiver> holder); 1394 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( 1395 Handle<Object> object, Handle<Name> name); 1396 1397 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor( 1398 LookupIterator* it); 1399 MUST_USE_RESULT static Maybe<bool> SetPropertyWithAccessor( 1400 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); 1401 1402 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter( 1403 Handle<Object> receiver, 1404 Handle<JSReceiver> getter); 1405 MUST_USE_RESULT static Maybe<bool> SetPropertyWithDefinedSetter( 1406 Handle<Object> receiver, Handle<JSReceiver> setter, Handle<Object> value, 1407 ShouldThrow should_throw); 1408 1409 MUST_USE_RESULT static inline MaybeHandle<Object> GetElement( 1410 Isolate* isolate, Handle<Object> object, uint32_t index); 1411 1412 MUST_USE_RESULT static inline MaybeHandle<Object> SetElement( 1413 Isolate* isolate, Handle<Object> object, uint32_t index, 1414 Handle<Object> value, LanguageMode language_mode); 1415 1416 // Returns the permanent hash code associated with this object. May return 1417 // undefined if not yet created. 1418 Object* GetHash(); 1419 1420 // Returns the permanent hash code associated with this object depending on 1421 // the actual object type. May create and store a hash code if needed and none 1422 // exists. 1423 static Smi* GetOrCreateHash(Isolate* isolate, Handle<Object> object); 1424 1425 // Checks whether this object has the same value as the given one. This 1426 // function is implemented according to ES5, section 9.12 and can be used 1427 // to implement the Harmony "egal" function. 1428 V8_EXPORT_PRIVATE bool SameValue(Object* other); 1429 1430 // Checks whether this object has the same value as the given one. 1431 // +0 and -0 are treated equal. Everything else is the same as SameValue. 1432 // This function is implemented according to ES6, section 7.2.4 and is used 1433 // by ES6 Map and Set. 1434 bool SameValueZero(Object* other); 1435 1436 // ES6 section 9.4.2.3 ArraySpeciesCreate (part of it) 1437 MUST_USE_RESULT static MaybeHandle<Object> ArraySpeciesConstructor( 1438 Isolate* isolate, Handle<Object> original_array); 1439 1440 // Tries to convert an object to an array length. Returns true and sets the 1441 // output parameter if it succeeds. 1442 inline bool ToArrayLength(uint32_t* index); 1443 1444 // Tries to convert an object to an array index. Returns true and sets the 1445 // output parameter if it succeeds. Equivalent to ToArrayLength, but does not 1446 // allow kMaxUInt32. 1447 inline bool ToArrayIndex(uint32_t* index); 1448 1449 // Returns true if the result of iterating over the object is the same 1450 // (including observable effects) as simply accessing the properties between 0 1451 // and length. 1452 bool IterationHasObservableEffects(); 1453 1454 DECLARE_VERIFIER(Object) 1455 #ifdef VERIFY_HEAP 1456 // Verify a pointer is a valid object pointer. 1457 static void VerifyPointer(Object* p); 1458 #endif 1459 1460 inline void VerifyApiCallResultType(); 1461 1462 // Prints this object without details. 1463 void ShortPrint(FILE* out = stdout); 1464 1465 // Prints this object without details to a message accumulator. 1466 void ShortPrint(StringStream* accumulator); 1467 1468 void ShortPrint(std::ostream& os); // NOLINT 1469 1470 DECLARE_CAST(Object) 1471 1472 // Layout description. 1473 static const int kHeaderSize = 0; // Object does not take up any space. 1474 1475 #ifdef OBJECT_PRINT 1476 // For our gdb macros, we should perhaps change these in the future. 1477 void Print(); 1478 1479 // Prints this object with details. 1480 void Print(std::ostream& os); // NOLINT 1481 #else 1482 void Print() { ShortPrint(); } 1483 void Print(std::ostream& os) { ShortPrint(os); } // NOLINT 1484 #endif 1485 1486 private: 1487 friend class LookupIterator; 1488 friend class StringStream; 1489 1490 // Return the map of the root of object's prototype chain. 1491 Map* GetPrototypeChainRootMap(Isolate* isolate); 1492 1493 // Helper for SetProperty and SetSuperProperty. 1494 // Return value is only meaningful if [found] is set to true on return. 1495 MUST_USE_RESULT static Maybe<bool> SetPropertyInternal( 1496 LookupIterator* it, Handle<Object> value, LanguageMode language_mode, 1497 StoreFromKeyed store_mode, bool* found); 1498 1499 MUST_USE_RESULT static MaybeHandle<Name> ConvertToName(Isolate* isolate, 1500 Handle<Object> input); 1501 MUST_USE_RESULT static MaybeHandle<Object> ConvertToPropertyKey( 1502 Isolate* isolate, Handle<Object> value); 1503 MUST_USE_RESULT static MaybeHandle<String> ConvertToString( 1504 Isolate* isolate, Handle<Object> input); 1505 MUST_USE_RESULT static MaybeHandle<Object> ConvertToNumber( 1506 Isolate* isolate, Handle<Object> input); 1507 MUST_USE_RESULT static MaybeHandle<Object> ConvertToInteger( 1508 Isolate* isolate, Handle<Object> input); 1509 MUST_USE_RESULT static MaybeHandle<Object> ConvertToInt32( 1510 Isolate* isolate, Handle<Object> input); 1511 MUST_USE_RESULT static MaybeHandle<Object> ConvertToUint32( 1512 Isolate* isolate, Handle<Object> input); 1513 MUST_USE_RESULT static MaybeHandle<Object> ConvertToLength( 1514 Isolate* isolate, Handle<Object> input); 1515 MUST_USE_RESULT static MaybeHandle<Object> ConvertToIndex( 1516 Isolate* isolate, Handle<Object> input, 1517 MessageTemplate::Template error_index); 1518 1519 DISALLOW_IMPLICIT_CONSTRUCTORS(Object); 1520 }; 1521 1522 1523 // In objects.h to be usable without objects-inl.h inclusion. 1524 bool Object::IsSmi() const { return HAS_SMI_TAG(this); } 1525 bool Object::IsHeapObject() const { return Internals::HasHeapObjectTag(this); } 1526 1527 1528 struct Brief { 1529 explicit Brief(const Object* const v) : value(v) {} 1530 const Object* value; 1531 }; 1532 1533 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const Brief& v); 1534 1535 // Smi represents integer Numbers that can be stored in 31 bits. 1536 // Smis are immediate which means they are NOT allocated in the heap. 1537 // The this pointer has the following format: [31 bit signed int] 0 1538 // For long smis it has the following format: 1539 // [32 bit signed int] [31 bits zero padding] 0 1540 // Smi stands for small integer. 1541 class Smi: public Object { 1542 public: 1543 // Returns the integer value. 1544 inline int value() const { return Internals::SmiValue(this); } 1545 inline Smi* ToUint32Smi() { 1546 if (value() <= 0) return Smi::kZero; 1547 return Smi::FromInt(static_cast<uint32_t>(value())); 1548 } 1549 1550 // Convert a value to a Smi object. 1551 static inline Smi* FromInt(int value) { 1552 DCHECK(Smi::IsValid(value)); 1553 return reinterpret_cast<Smi*>(Internals::IntToSmi(value)); 1554 } 1555 1556 static inline Smi* FromIntptr(intptr_t value) { 1557 DCHECK(Smi::IsValid(value)); 1558 int smi_shift_bits = kSmiTagSize + kSmiShiftSize; 1559 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag); 1560 } 1561 1562 // Returns whether value can be represented in a Smi. 1563 static inline bool IsValid(intptr_t value) { 1564 bool result = Internals::IsValidSmi(value); 1565 DCHECK_EQ(result, value >= kMinValue && value <= kMaxValue); 1566 return result; 1567 } 1568 1569 DECLARE_CAST(Smi) 1570 1571 // Dispatched behavior. 1572 V8_EXPORT_PRIVATE void SmiPrint(std::ostream& os) const; // NOLINT 1573 DECLARE_VERIFIER(Smi) 1574 1575 static constexpr Smi* const kZero = nullptr; 1576 static const int kMinValue = 1577 (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1); 1578 static const int kMaxValue = -(kMinValue + 1); 1579 1580 private: 1581 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi); 1582 }; 1583 1584 1585 // Heap objects typically have a map pointer in their first word. However, 1586 // during GC other data (e.g. mark bits, forwarding addresses) is sometimes 1587 // encoded in the first word. The class MapWord is an abstraction of the 1588 // value in a heap object's first word. 1589 class MapWord BASE_EMBEDDED { 1590 public: 1591 // Normal state: the map word contains a map pointer. 1592 1593 // Create a map word from a map pointer. 1594 static inline MapWord FromMap(const Map* map); 1595 1596 // View this map word as a map pointer. 1597 inline Map* ToMap(); 1598 1599 1600 // Scavenge collection: the map word of live objects in the from space 1601 // contains a forwarding address (a heap object pointer in the to space). 1602 1603 // True if this map word is a forwarding address for a scavenge 1604 // collection. Only valid during a scavenge collection (specifically, 1605 // when all map words are heap object pointers, i.e. not during a full GC). 1606 inline bool IsForwardingAddress() const; 1607 1608 // Create a map word from a forwarding address. 1609 static inline MapWord FromForwardingAddress(HeapObject* object); 1610 1611 // View this map word as a forwarding address. 1612 inline HeapObject* ToForwardingAddress(); 1613 1614 static inline MapWord FromRawValue(uintptr_t value) { 1615 return MapWord(value); 1616 } 1617 1618 inline uintptr_t ToRawValue() { 1619 return value_; 1620 } 1621 1622 private: 1623 // HeapObject calls the private constructor and directly reads the value. 1624 friend class HeapObject; 1625 1626 explicit MapWord(uintptr_t value) : value_(value) {} 1627 1628 uintptr_t value_; 1629 }; 1630 1631 1632 // HeapObject is the superclass for all classes describing heap allocated 1633 // objects. 1634 class HeapObject: public Object { 1635 public: 1636 // [map]: Contains a map which contains the object's reflective 1637 // information. 1638 inline Map* map() const; 1639 inline void set_map(Map* value); 1640 // The no-write-barrier version. This is OK if the object is white and in 1641 // new space, or if the value is an immortal immutable object, like the maps 1642 // of primitive (non-JS) objects like strings, heap numbers etc. 1643 inline void set_map_no_write_barrier(Map* value); 1644 1645 // Get the map using acquire load. 1646 inline Map* synchronized_map(); 1647 inline MapWord synchronized_map_word() const; 1648 1649 // Set the map using release store 1650 inline void synchronized_set_map(Map* value); 1651 inline void synchronized_set_map_no_write_barrier(Map* value); 1652 inline void synchronized_set_map_word(MapWord map_word); 1653 1654 // During garbage collection, the map word of a heap object does not 1655 // necessarily contain a map pointer. 1656 inline MapWord map_word() const; 1657 inline void set_map_word(MapWord map_word); 1658 1659 // The Heap the object was allocated in. Used also to access Isolate. 1660 inline Heap* GetHeap() const; 1661 1662 // Convenience method to get current isolate. 1663 inline Isolate* GetIsolate() const; 1664 1665 #define IS_TYPE_FUNCTION_DECL(Type) INLINE(bool Is##Type() const); 1666 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) 1667 #undef IS_TYPE_FUNCTION_DECL 1668 1669 #define IS_TYPE_FUNCTION_DECL(Type, Value) \ 1670 INLINE(bool Is##Type(Isolate* isolate) const); 1671 ODDBALL_LIST(IS_TYPE_FUNCTION_DECL) 1672 #undef IS_TYPE_FUNCTION_DECL 1673 1674 INLINE(bool IsNullOrUndefined(Isolate* isolate) const); 1675 1676 #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \ 1677 INLINE(bool Is##Name() const); 1678 STRUCT_LIST(DECLARE_STRUCT_PREDICATE) 1679 #undef DECLARE_STRUCT_PREDICATE 1680 1681 // Converts an address to a HeapObject pointer. 1682 static inline HeapObject* FromAddress(Address address) { 1683 DCHECK_TAG_ALIGNED(address); 1684 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag); 1685 } 1686 1687 // Returns the address of this HeapObject. 1688 inline Address address() { 1689 return reinterpret_cast<Address>(this) - kHeapObjectTag; 1690 } 1691 1692 // Iterates over pointers contained in the object (including the Map). 1693 // If it's not performance critical iteration use the non-templatized 1694 // version. 1695 void Iterate(ObjectVisitor* v); 1696 1697 template <typename ObjectVisitor> 1698 inline void IterateFast(ObjectVisitor* v); 1699 1700 // Iterates over all pointers contained in the object except the 1701 // first map pointer. The object type is given in the first 1702 // parameter. This function does not access the map pointer in the 1703 // object, and so is safe to call while the map pointer is modified. 1704 // If it's not performance critical iteration use the non-templatized 1705 // version. 1706 void IterateBody(ObjectVisitor* v); 1707 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v); 1708 1709 template <typename ObjectVisitor> 1710 inline void IterateBodyFast(ObjectVisitor* v); 1711 1712 template <typename ObjectVisitor> 1713 inline void IterateBodyFast(InstanceType type, int object_size, 1714 ObjectVisitor* v); 1715 1716 // Returns true if the object contains a tagged value at given offset. 1717 // It is used for invalid slots filtering. If the offset points outside 1718 // of the object or to the map word, the result is UNDEFINED (!!!). 1719 bool IsValidSlot(int offset); 1720 1721 // Returns the heap object's size in bytes 1722 inline int Size(); 1723 1724 // Given a heap object's map pointer, returns the heap size in bytes 1725 // Useful when the map pointer field is used for other purposes. 1726 // GC internal. 1727 inline int SizeFromMap(Map* map); 1728 1729 // Returns the field at offset in obj, as a read/write Object* reference. 1730 // Does no checking, and is safe to use during GC, while maps are invalid. 1731 // Does not invoke write barrier, so should only be assigned to 1732 // during marking GC. 1733 static inline Object** RawField(HeapObject* obj, int offset); 1734 1735 // Adds the |code| object related to |name| to the code cache of this map. If 1736 // this map is a dictionary map that is shared, the map copied and installed 1737 // onto the object. 1738 static void UpdateMapCodeCache(Handle<HeapObject> object, 1739 Handle<Name> name, 1740 Handle<Code> code); 1741 1742 DECLARE_CAST(HeapObject) 1743 1744 // Return the write barrier mode for this. Callers of this function 1745 // must be able to present a reference to an DisallowHeapAllocation 1746 // object as a sign that they are not going to use this function 1747 // from code that allocates and thus invalidates the returned write 1748 // barrier mode. 1749 inline WriteBarrierMode GetWriteBarrierMode( 1750 const DisallowHeapAllocation& promise); 1751 1752 // Dispatched behavior. 1753 void HeapObjectShortPrint(std::ostream& os); // NOLINT 1754 #ifdef OBJECT_PRINT 1755 void PrintHeader(std::ostream& os, const char* id); // NOLINT 1756 #endif 1757 DECLARE_PRINTER(HeapObject) 1758 DECLARE_VERIFIER(HeapObject) 1759 #ifdef VERIFY_HEAP 1760 inline void VerifyObjectField(int offset); 1761 inline void VerifySmiField(int offset); 1762 1763 // Verify a pointer is a valid HeapObject pointer that points to object 1764 // areas in the heap. 1765 static void VerifyHeapPointer(Object* p); 1766 #endif 1767 1768 inline AllocationAlignment RequiredAlignment(); 1769 1770 // Layout description. 1771 // First field in a heap object is map. 1772 static const int kMapOffset = Object::kHeaderSize; 1773 static const int kHeaderSize = kMapOffset + kPointerSize; 1774 1775 STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset); 1776 1777 private: 1778 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject); 1779 }; 1780 1781 1782 template <int start_offset, int end_offset, int size> 1783 class FixedBodyDescriptor; 1784 1785 1786 template <int start_offset> 1787 class FlexibleBodyDescriptor; 1788 1789 1790 // The HeapNumber class describes heap allocated numbers that cannot be 1791 // represented in a Smi (small integer) 1792 class HeapNumber: public HeapObject { 1793 public: 1794 // [value]: number value. 1795 inline double value() const; 1796 inline void set_value(double value); 1797 1798 inline uint64_t value_as_bits() const; 1799 inline void set_value_as_bits(uint64_t bits); 1800 1801 DECLARE_CAST(HeapNumber) 1802 1803 // Dispatched behavior. 1804 bool HeapNumberBooleanValue(); 1805 1806 V8_EXPORT_PRIVATE void HeapNumberPrint(std::ostream& os); // NOLINT 1807 DECLARE_VERIFIER(HeapNumber) 1808 1809 inline int get_exponent(); 1810 inline int get_sign(); 1811 1812 // Layout description. 1813 static const int kValueOffset = HeapObject::kHeaderSize; 1814 // IEEE doubles are two 32 bit words. The first is just mantissa, the second 1815 // is a mixture of sign, exponent and mantissa. The offsets of two 32 bit 1816 // words within double numbers are endian dependent and they are set 1817 // accordingly. 1818 #if defined(V8_TARGET_LITTLE_ENDIAN) 1819 static const int kMantissaOffset = kValueOffset; 1820 static const int kExponentOffset = kValueOffset + 4; 1821 #elif defined(V8_TARGET_BIG_ENDIAN) 1822 static const int kMantissaOffset = kValueOffset + 4; 1823 static const int kExponentOffset = kValueOffset; 1824 #else 1825 #error Unknown byte ordering 1826 #endif 1827 1828 static const int kSize = kValueOffset + kDoubleSize; 1829 static const uint32_t kSignMask = 0x80000000u; 1830 static const uint32_t kExponentMask = 0x7ff00000u; 1831 static const uint32_t kMantissaMask = 0xfffffu; 1832 static const int kMantissaBits = 52; 1833 static const int kExponentBits = 11; 1834 static const int kExponentBias = 1023; 1835 static const int kExponentShift = 20; 1836 static const int kInfinityOrNanExponent = 1837 (kExponentMask >> kExponentShift) - kExponentBias; 1838 static const int kMantissaBitsInTopWord = 20; 1839 static const int kNonMantissaBitsInTopWord = 12; 1840 1841 private: 1842 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber); 1843 }; 1844 1845 enum EnsureElementsMode { 1846 DONT_ALLOW_DOUBLE_ELEMENTS, 1847 ALLOW_COPIED_DOUBLE_ELEMENTS, 1848 ALLOW_CONVERTED_DOUBLE_ELEMENTS 1849 }; 1850 1851 1852 // Indicator for one component of an AccessorPair. 1853 enum AccessorComponent { 1854 ACCESSOR_GETTER, 1855 ACCESSOR_SETTER 1856 }; 1857 1858 enum class GetKeysConversion { kKeepNumbers, kConvertToString }; 1859 1860 enum class KeyCollectionMode { 1861 kOwnOnly = static_cast<int>(v8::KeyCollectionMode::kOwnOnly), 1862 kIncludePrototypes = 1863 static_cast<int>(v8::KeyCollectionMode::kIncludePrototypes) 1864 }; 1865 1866 enum class AllocationSiteUpdateMode { kUpdate, kCheckOnly }; 1867 1868 // JSReceiver includes types on which properties can be defined, i.e., 1869 // JSObject and JSProxy. 1870 class JSReceiver: public HeapObject { 1871 public: 1872 // [properties]: Backing storage for properties. 1873 // properties is a FixedArray in the fast case and a Dictionary in the 1874 // slow case. 1875 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties. 1876 inline void initialize_properties(); 1877 inline bool HasFastProperties(); 1878 // Gets slow properties for non-global objects. 1879 inline NameDictionary* property_dictionary(); 1880 1881 // Deletes an existing named property in a normalized object. 1882 static void DeleteNormalizedProperty(Handle<JSReceiver> object, 1883 Handle<Name> name, int entry); 1884 1885 DECLARE_CAST(JSReceiver) 1886 1887 // ES6 section 7.1.1 ToPrimitive 1888 MUST_USE_RESULT static MaybeHandle<Object> ToPrimitive( 1889 Handle<JSReceiver> receiver, 1890 ToPrimitiveHint hint = ToPrimitiveHint::kDefault); 1891 1892 // ES6 section 7.1.1.1 OrdinaryToPrimitive 1893 MUST_USE_RESULT static MaybeHandle<Object> OrdinaryToPrimitive( 1894 Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint); 1895 1896 static MaybeHandle<Context> GetFunctionRealm(Handle<JSReceiver> receiver); 1897 1898 // Get the first non-hidden prototype. 1899 static inline MaybeHandle<Object> GetPrototype(Isolate* isolate, 1900 Handle<JSReceiver> receiver); 1901 1902 MUST_USE_RESULT static Maybe<bool> HasInPrototypeChain( 1903 Isolate* isolate, Handle<JSReceiver> object, Handle<Object> proto); 1904 1905 // Reads all enumerable own properties of source and adds them to 1906 // target, using either Set or CreateDataProperty depending on the 1907 // use_set argument. This only copies values not present in the 1908 // maybe_excluded_properties list. 1909 MUST_USE_RESULT static Maybe<bool> SetOrCopyDataProperties( 1910 Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source, 1911 const ScopedVector<Handle<Object>>* excluded_properties = nullptr, 1912 bool use_set = true); 1913 1914 // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6. 1915 MUST_USE_RESULT static Maybe<bool> HasProperty(LookupIterator* it); 1916 MUST_USE_RESULT static inline Maybe<bool> HasProperty( 1917 Handle<JSReceiver> object, Handle<Name> name); 1918 MUST_USE_RESULT static inline Maybe<bool> HasElement( 1919 Handle<JSReceiver> object, uint32_t index); 1920 1921 MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty( 1922 Handle<JSReceiver> object, Handle<Name> name); 1923 MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty( 1924 Handle<JSReceiver> object, uint32_t index); 1925 1926 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( 1927 Isolate* isolate, Handle<JSReceiver> receiver, const char* key); 1928 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( 1929 Handle<JSReceiver> receiver, Handle<Name> name); 1930 MUST_USE_RESULT static inline MaybeHandle<Object> GetElement( 1931 Isolate* isolate, Handle<JSReceiver> receiver, uint32_t index); 1932 1933 // Implementation of ES6 [[Delete]] 1934 MUST_USE_RESULT static Maybe<bool> DeletePropertyOrElement( 1935 Handle<JSReceiver> object, Handle<Name> name, 1936 LanguageMode language_mode = SLOPPY); 1937 MUST_USE_RESULT static Maybe<bool> DeleteProperty( 1938 Handle<JSReceiver> object, Handle<Name> name, 1939 LanguageMode language_mode = SLOPPY); 1940 MUST_USE_RESULT static Maybe<bool> DeleteProperty(LookupIterator* it, 1941 LanguageMode language_mode); 1942 MUST_USE_RESULT static Maybe<bool> DeleteElement( 1943 Handle<JSReceiver> object, uint32_t index, 1944 LanguageMode language_mode = SLOPPY); 1945 1946 MUST_USE_RESULT static Object* DefineProperty(Isolate* isolate, 1947 Handle<Object> object, 1948 Handle<Object> name, 1949 Handle<Object> attributes); 1950 MUST_USE_RESULT static MaybeHandle<Object> DefineProperties( 1951 Isolate* isolate, Handle<Object> object, Handle<Object> properties); 1952 1953 // "virtual" dispatcher to the correct [[DefineOwnProperty]] implementation. 1954 MUST_USE_RESULT static Maybe<bool> DefineOwnProperty( 1955 Isolate* isolate, Handle<JSReceiver> object, Handle<Object> key, 1956 PropertyDescriptor* desc, ShouldThrow should_throw); 1957 1958 // ES6 7.3.4 (when passed DONT_THROW) 1959 MUST_USE_RESULT static Maybe<bool> CreateDataProperty( 1960 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); 1961 1962 // ES6 9.1.6.1 1963 MUST_USE_RESULT static Maybe<bool> OrdinaryDefineOwnProperty( 1964 Isolate* isolate, Handle<JSObject> object, Handle<Object> key, 1965 PropertyDescriptor* desc, ShouldThrow should_throw); 1966 MUST_USE_RESULT static Maybe<bool> OrdinaryDefineOwnProperty( 1967 LookupIterator* it, PropertyDescriptor* desc, ShouldThrow should_throw); 1968 // ES6 9.1.6.2 1969 MUST_USE_RESULT static Maybe<bool> IsCompatiblePropertyDescriptor( 1970 Isolate* isolate, bool extensible, PropertyDescriptor* desc, 1971 PropertyDescriptor* current, Handle<Name> property_name, 1972 ShouldThrow should_throw); 1973 // ES6 9.1.6.3 1974 // |it| can be NULL in cases where the ES spec passes |undefined| as the 1975 // receiver. Exactly one of |it| and |property_name| must be provided. 1976 MUST_USE_RESULT static Maybe<bool> ValidateAndApplyPropertyDescriptor( 1977 Isolate* isolate, LookupIterator* it, bool extensible, 1978 PropertyDescriptor* desc, PropertyDescriptor* current, 1979 ShouldThrow should_throw, Handle<Name> property_name = Handle<Name>()); 1980 1981 V8_EXPORT_PRIVATE MUST_USE_RESULT static Maybe<bool> GetOwnPropertyDescriptor( 1982 Isolate* isolate, Handle<JSReceiver> object, Handle<Object> key, 1983 PropertyDescriptor* desc); 1984 MUST_USE_RESULT static Maybe<bool> GetOwnPropertyDescriptor( 1985 LookupIterator* it, PropertyDescriptor* desc); 1986 1987 typedef PropertyAttributes IntegrityLevel; 1988 1989 // ES6 7.3.14 (when passed DONT_THROW) 1990 // 'level' must be SEALED or FROZEN. 1991 MUST_USE_RESULT static Maybe<bool> SetIntegrityLevel( 1992 Handle<JSReceiver> object, IntegrityLevel lvl, ShouldThrow should_throw); 1993 1994 // ES6 7.3.15 1995 // 'level' must be SEALED or FROZEN. 1996 MUST_USE_RESULT static Maybe<bool> TestIntegrityLevel( 1997 Handle<JSReceiver> object, IntegrityLevel lvl); 1998 1999 // ES6 [[PreventExtensions]] (when passed DONT_THROW) 2000 MUST_USE_RESULT static Maybe<bool> PreventExtensions( 2001 Handle<JSReceiver> object, ShouldThrow should_throw); 2002 2003 MUST_USE_RESULT static Maybe<bool> IsExtensible(Handle<JSReceiver> object); 2004 2005 // Returns the class name ([[Class]] property in the specification). 2006 String* class_name(); 2007 2008 // Returns the constructor name (the name (possibly, inferred name) of the 2009 // function that was used to instantiate the object). 2010 static Handle<String> GetConstructorName(Handle<JSReceiver> receiver); 2011 2012 Handle<Context> GetCreationContext(); 2013 2014 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetPropertyAttributes( 2015 Handle<JSReceiver> object, Handle<Name> name); 2016 MUST_USE_RESULT static inline Maybe<PropertyAttributes> 2017 GetOwnPropertyAttributes(Handle<JSReceiver> object, Handle<Name> name); 2018 MUST_USE_RESULT static inline Maybe<PropertyAttributes> 2019 GetOwnPropertyAttributes(Handle<JSReceiver> object, uint32_t index); 2020 2021 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttributes( 2022 Handle<JSReceiver> object, uint32_t index); 2023 MUST_USE_RESULT static inline Maybe<PropertyAttributes> 2024 GetOwnElementAttributes(Handle<JSReceiver> object, uint32_t index); 2025 2026 MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes( 2027 LookupIterator* it); 2028 2029 // Set the object's prototype (only JSReceiver and null are allowed values). 2030 MUST_USE_RESULT static Maybe<bool> SetPrototype(Handle<JSReceiver> object, 2031 Handle<Object> value, 2032 bool from_javascript, 2033 ShouldThrow should_throw); 2034 2035 inline static Handle<Object> GetDataProperty(Handle<JSReceiver> object, 2036 Handle<Name> name); 2037 static Handle<Object> GetDataProperty(LookupIterator* it); 2038 2039 2040 // Retrieves a permanent object identity hash code. The undefined value might 2041 // be returned in case no hash was created yet. 2042 static inline Object* GetIdentityHash(Isolate* isolate, 2043 Handle<JSReceiver> object); 2044 2045 // Retrieves a permanent object identity hash code. May create and store a 2046 // hash code if needed and none exists. 2047 inline static Smi* GetOrCreateIdentityHash(Isolate* isolate, 2048 Handle<JSReceiver> object); 2049 2050 // ES6 [[OwnPropertyKeys]] (modulo return type) 2051 MUST_USE_RESULT static inline MaybeHandle<FixedArray> OwnPropertyKeys( 2052 Handle<JSReceiver> object); 2053 2054 MUST_USE_RESULT static MaybeHandle<FixedArray> GetOwnValues( 2055 Handle<JSReceiver> object, PropertyFilter filter); 2056 2057 MUST_USE_RESULT static MaybeHandle<FixedArray> GetOwnEntries( 2058 Handle<JSReceiver> object, PropertyFilter filter); 2059 2060 // Layout description. 2061 static const int kPropertiesOffset = HeapObject::kHeaderSize; 2062 static const int kHeaderSize = HeapObject::kHeaderSize + kPointerSize; 2063 2064 bool HasProxyInPrototype(Isolate* isolate); 2065 2066 private: 2067 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); 2068 }; 2069 2070 2071 // The JSObject describes real heap allocated JavaScript objects with 2072 // properties. 2073 // Note that the map of JSObject changes during execution to enable inline 2074 // caching. 2075 class JSObject: public JSReceiver { 2076 public: 2077 static MUST_USE_RESULT MaybeHandle<JSObject> New( 2078 Handle<JSFunction> constructor, Handle<JSReceiver> new_target, 2079 Handle<AllocationSite> site = Handle<AllocationSite>::null()); 2080 2081 // Gets global object properties. 2082 inline GlobalDictionary* global_dictionary(); 2083 2084 static MaybeHandle<Context> GetFunctionRealm(Handle<JSObject> object); 2085 2086 // [elements]: The elements (properties with names that are integers). 2087 // 2088 // Elements can be in two general modes: fast and slow. Each mode 2089 // corresponds to a set of object representations of elements that 2090 // have something in common. 2091 // 2092 // In the fast mode elements is a FixedArray and so each element can 2093 // be quickly accessed. This fact is used in the generated code. The 2094 // elements array can have one of three maps in this mode: 2095 // fixed_array_map, sloppy_arguments_elements_map or 2096 // fixed_cow_array_map (for copy-on-write arrays). In the latter case 2097 // the elements array may be shared by a few objects and so before 2098 // writing to any element the array must be copied. Use 2099 // EnsureWritableFastElements in this case. 2100 // 2101 // In the slow mode the elements is either a NumberDictionary, a 2102 // FixedArray parameter map for a (sloppy) arguments object. 2103 DECL_ACCESSORS(elements, FixedArrayBase) 2104 inline void initialize_elements(); 2105 static void ResetElements(Handle<JSObject> object); 2106 static inline void SetMapAndElements(Handle<JSObject> object, 2107 Handle<Map> map, 2108 Handle<FixedArrayBase> elements); 2109 inline ElementsKind GetElementsKind(); 2110 ElementsAccessor* GetElementsAccessor(); 2111 // Returns true if an object has elements of FAST_SMI_ELEMENTS ElementsKind. 2112 inline bool HasFastSmiElements(); 2113 // Returns true if an object has elements of FAST_ELEMENTS ElementsKind. 2114 inline bool HasFastObjectElements(); 2115 // Returns true if an object has elements of FAST_ELEMENTS or 2116 // FAST_SMI_ONLY_ELEMENTS. 2117 inline bool HasFastSmiOrObjectElements(); 2118 // Returns true if an object has any of the fast elements kinds. 2119 inline bool HasFastElements(); 2120 // Returns true if an object has elements of FAST_DOUBLE_ELEMENTS 2121 // ElementsKind. 2122 inline bool HasFastDoubleElements(); 2123 // Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS 2124 // ElementsKind. 2125 inline bool HasFastHoleyElements(); 2126 inline bool HasSloppyArgumentsElements(); 2127 inline bool HasStringWrapperElements(); 2128 inline bool HasDictionaryElements(); 2129 2130 inline bool HasFixedTypedArrayElements(); 2131 2132 inline bool HasFixedUint8ClampedElements(); 2133 inline bool HasFixedArrayElements(); 2134 inline bool HasFixedInt8Elements(); 2135 inline bool HasFixedUint8Elements(); 2136 inline bool HasFixedInt16Elements(); 2137 inline bool HasFixedUint16Elements(); 2138 inline bool HasFixedInt32Elements(); 2139 inline bool HasFixedUint32Elements(); 2140 inline bool HasFixedFloat32Elements(); 2141 inline bool HasFixedFloat64Elements(); 2142 2143 inline bool HasFastArgumentsElements(); 2144 inline bool HasSlowArgumentsElements(); 2145 inline bool HasFastStringWrapperElements(); 2146 inline bool HasSlowStringWrapperElements(); 2147 bool HasEnumerableElements(); 2148 2149 inline SeededNumberDictionary* element_dictionary(); // Gets slow elements. 2150 2151 // Requires: HasFastElements(). 2152 static void EnsureWritableFastElements(Handle<JSObject> object); 2153 2154 // Collects elements starting at index 0. 2155 // Undefined values are placed after non-undefined values. 2156 // Returns the number of non-undefined values. 2157 static Handle<Object> PrepareElementsForSort(Handle<JSObject> object, 2158 uint32_t limit); 2159 // As PrepareElementsForSort, but only on objects where elements is 2160 // a dictionary, and it will stay a dictionary. Collates undefined and 2161 // unexisting elements below limit from position zero of the elements. 2162 static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object, 2163 uint32_t limit); 2164 2165 MUST_USE_RESULT static Maybe<bool> SetPropertyWithInterceptor( 2166 LookupIterator* it, ShouldThrow should_throw, Handle<Object> value); 2167 2168 // The API currently still wants DefineOwnPropertyIgnoreAttributes to convert 2169 // AccessorInfo objects to data fields. We allow FORCE_FIELD as an exception 2170 // to the default behavior that calls the setter. 2171 enum AccessorInfoHandling { FORCE_FIELD, DONT_FORCE_FIELD }; 2172 2173 MUST_USE_RESULT static MaybeHandle<Object> DefineOwnPropertyIgnoreAttributes( 2174 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 2175 AccessorInfoHandling handling = DONT_FORCE_FIELD); 2176 2177 MUST_USE_RESULT static Maybe<bool> DefineOwnPropertyIgnoreAttributes( 2178 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 2179 ShouldThrow should_throw, 2180 AccessorInfoHandling handling = DONT_FORCE_FIELD); 2181 2182 MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes( 2183 Handle<JSObject> object, Handle<Name> name, Handle<Object> value, 2184 PropertyAttributes attributes); 2185 2186 MUST_USE_RESULT static MaybeHandle<Object> SetOwnElementIgnoreAttributes( 2187 Handle<JSObject> object, uint32_t index, Handle<Object> value, 2188 PropertyAttributes attributes); 2189 2190 // Equivalent to one of the above depending on whether |name| can be converted 2191 // to an array index. 2192 MUST_USE_RESULT static MaybeHandle<Object> 2193 DefinePropertyOrElementIgnoreAttributes(Handle<JSObject> object, 2194 Handle<Name> name, 2195 Handle<Object> value, 2196 PropertyAttributes attributes = NONE); 2197 2198 // Adds or reconfigures a property to attributes NONE. It will fail when it 2199 // cannot. 2200 MUST_USE_RESULT static Maybe<bool> CreateDataProperty( 2201 LookupIterator* it, Handle<Object> value, 2202 ShouldThrow should_throw = DONT_THROW); 2203 2204 static void AddProperty(Handle<JSObject> object, Handle<Name> name, 2205 Handle<Object> value, PropertyAttributes attributes); 2206 2207 MUST_USE_RESULT static Maybe<bool> AddDataElement( 2208 Handle<JSObject> receiver, uint32_t index, Handle<Object> value, 2209 PropertyAttributes attributes, ShouldThrow should_throw); 2210 MUST_USE_RESULT static MaybeHandle<Object> AddDataElement( 2211 Handle<JSObject> receiver, uint32_t index, Handle<Object> value, 2212 PropertyAttributes attributes); 2213 2214 // Extend the receiver with a single fast property appeared first in the 2215 // passed map. This also extends the property backing store if necessary. 2216 static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map); 2217 2218 // Migrates the given object to a map whose field representations are the 2219 // lowest upper bound of all known representations for that field. 2220 static void MigrateInstance(Handle<JSObject> instance); 2221 2222 // Migrates the given object only if the target map is already available, 2223 // or returns false if such a map is not yet available. 2224 static bool TryMigrateInstance(Handle<JSObject> instance); 2225 2226 // Sets the property value in a normalized object given (key, value, details). 2227 // Handles the special representation of JS global objects. 2228 static void SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name, 2229 Handle<Object> value, 2230 PropertyDetails details); 2231 static void SetDictionaryElement(Handle<JSObject> object, uint32_t index, 2232 Handle<Object> value, 2233 PropertyAttributes attributes); 2234 static void SetDictionaryArgumentsElement(Handle<JSObject> object, 2235 uint32_t index, 2236 Handle<Object> value, 2237 PropertyAttributes attributes); 2238 2239 static void OptimizeAsPrototype(Handle<JSObject> object, 2240 PrototypeOptimizationMode mode); 2241 static void ReoptimizeIfPrototype(Handle<JSObject> object); 2242 static void MakePrototypesFast(Handle<Object> receiver, 2243 WhereToStart where_to_start, Isolate* isolate); 2244 static void LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate); 2245 static void UpdatePrototypeUserRegistration(Handle<Map> old_map, 2246 Handle<Map> new_map, 2247 Isolate* isolate); 2248 static bool UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate); 2249 static void InvalidatePrototypeChains(Map* map); 2250 2251 // Updates prototype chain tracking information when an object changes its 2252 // map from |old_map| to |new_map|. 2253 static void NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map, 2254 Isolate* isolate); 2255 2256 // Utility used by many Array builtins and runtime functions 2257 static inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object); 2258 2259 // Alternative implementation of WeakFixedArray::NullCallback. 2260 class PrototypeRegistryCompactionCallback { 2261 public: 2262 static void Callback(Object* value, int old_index, int new_index); 2263 }; 2264 2265 // Retrieve interceptors. 2266 inline InterceptorInfo* GetNamedInterceptor(); 2267 inline InterceptorInfo* GetIndexedInterceptor(); 2268 2269 // Used from JSReceiver. 2270 MUST_USE_RESULT static Maybe<PropertyAttributes> 2271 GetPropertyAttributesWithInterceptor(LookupIterator* it); 2272 MUST_USE_RESULT static Maybe<PropertyAttributes> 2273 GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it); 2274 2275 // Defines an AccessorPair property on the given object. 2276 // TODO(mstarzinger): Rename to SetAccessor(). 2277 static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object, 2278 Handle<Name> name, 2279 Handle<Object> getter, 2280 Handle<Object> setter, 2281 PropertyAttributes attributes); 2282 static MaybeHandle<Object> DefineAccessor(LookupIterator* it, 2283 Handle<Object> getter, 2284 Handle<Object> setter, 2285 PropertyAttributes attributes); 2286 2287 // Defines an AccessorInfo property on the given object. 2288 MUST_USE_RESULT static MaybeHandle<Object> SetAccessor( 2289 Handle<JSObject> object, 2290 Handle<AccessorInfo> info); 2291 2292 // The result must be checked first for exceptions. If there's no exception, 2293 // the output parameter |done| indicates whether the interceptor has a result 2294 // or not. 2295 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor( 2296 LookupIterator* it, bool* done); 2297 2298 static void ValidateElements(Handle<JSObject> object); 2299 2300 // Makes sure that this object can contain HeapObject as elements. 2301 static inline void EnsureCanContainHeapObjectElements(Handle<JSObject> obj); 2302 2303 // Makes sure that this object can contain the specified elements. 2304 static inline void EnsureCanContainElements( 2305 Handle<JSObject> object, 2306 Object** elements, 2307 uint32_t count, 2308 EnsureElementsMode mode); 2309 static inline void EnsureCanContainElements( 2310 Handle<JSObject> object, 2311 Handle<FixedArrayBase> elements, 2312 uint32_t length, 2313 EnsureElementsMode mode); 2314 static void EnsureCanContainElements( 2315 Handle<JSObject> object, 2316 Arguments* arguments, 2317 uint32_t first_arg, 2318 uint32_t arg_count, 2319 EnsureElementsMode mode); 2320 2321 // Would we convert a fast elements array to dictionary mode given 2322 // an access at key? 2323 bool WouldConvertToSlowElements(uint32_t index); 2324 2325 // Computes the new capacity when expanding the elements of a JSObject. 2326 static uint32_t NewElementsCapacity(uint32_t old_capacity) { 2327 // (old_capacity + 50%) + 16 2328 return old_capacity + (old_capacity >> 1) + 16; 2329 } 2330 2331 // These methods do not perform access checks! 2332 template <AllocationSiteUpdateMode update_or_check = 2333 AllocationSiteUpdateMode::kUpdate> 2334 static bool UpdateAllocationSite(Handle<JSObject> object, 2335 ElementsKind to_kind); 2336 2337 // Lookup interceptors are used for handling properties controlled by host 2338 // objects. 2339 inline bool HasNamedInterceptor(); 2340 inline bool HasIndexedInterceptor(); 2341 2342 // Support functions for v8 api (needed for correct interceptor behavior). 2343 MUST_USE_RESULT static Maybe<bool> HasRealNamedProperty( 2344 Handle<JSObject> object, Handle<Name> name); 2345 MUST_USE_RESULT static Maybe<bool> HasRealElementProperty( 2346 Handle<JSObject> object, uint32_t index); 2347 MUST_USE_RESULT static Maybe<bool> HasRealNamedCallbackProperty( 2348 Handle<JSObject> object, Handle<Name> name); 2349 2350 // Get the header size for a JSObject. Used to compute the index of 2351 // internal fields as well as the number of internal fields. 2352 static inline int GetHeaderSize(InstanceType instance_type); 2353 inline int GetHeaderSize(); 2354 2355 static inline int GetInternalFieldCount(Map* map); 2356 inline int GetInternalFieldCount(); 2357 inline int GetInternalFieldOffset(int index); 2358 inline Object* GetInternalField(int index); 2359 inline void SetInternalField(int index, Object* value); 2360 inline void SetInternalField(int index, Smi* value); 2361 bool WasConstructedFromApiFunction(); 2362 2363 // Returns a new map with all transitions dropped from the object's current 2364 // map and the ElementsKind set. 2365 static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object, 2366 ElementsKind to_kind); 2367 static void TransitionElementsKind(Handle<JSObject> object, 2368 ElementsKind to_kind); 2369 2370 // Always use this to migrate an object to a new map. 2371 // |expected_additional_properties| is only used for fast-to-slow transitions 2372 // and ignored otherwise. 2373 static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, 2374 int expected_additional_properties = 0); 2375 2376 // Forces a prototype without any of the checks that the regular SetPrototype 2377 // would do. 2378 static void ForceSetPrototype(Handle<JSObject> object, Handle<Object> proto); 2379 2380 // Convert the object to use the canonical dictionary 2381 // representation. If the object is expected to have additional properties 2382 // added this number can be indicated to have the backing store allocated to 2383 // an initial capacity for holding these properties. 2384 static void NormalizeProperties(Handle<JSObject> object, 2385 PropertyNormalizationMode mode, 2386 int expected_additional_properties, 2387 const char* reason); 2388 2389 // Convert and update the elements backing store to be a 2390 // SeededNumberDictionary dictionary. Returns the backing after conversion. 2391 static Handle<SeededNumberDictionary> NormalizeElements( 2392 Handle<JSObject> object); 2393 2394 void RequireSlowElements(SeededNumberDictionary* dictionary); 2395 2396 // Transform slow named properties to fast variants. 2397 static void MigrateSlowToFast(Handle<JSObject> object, 2398 int unused_property_fields, const char* reason); 2399 2400 inline bool IsUnboxedDoubleField(FieldIndex index); 2401 2402 // Access fast-case object properties at index. 2403 static Handle<Object> FastPropertyAt(Handle<JSObject> object, 2404 Representation representation, 2405 FieldIndex index); 2406 inline Object* RawFastPropertyAt(FieldIndex index); 2407 inline double RawFastDoublePropertyAt(FieldIndex index); 2408 inline uint64_t RawFastDoublePropertyAsBitsAt(FieldIndex index); 2409 2410 inline void FastPropertyAtPut(FieldIndex index, Object* value); 2411 inline void RawFastPropertyAtPut(FieldIndex index, Object* value); 2412 inline void RawFastDoublePropertyAsBitsAtPut(FieldIndex index, uint64_t bits); 2413 inline void WriteToField(int descriptor, PropertyDetails details, 2414 Object* value); 2415 2416 // Access to in object properties. 2417 inline int GetInObjectPropertyOffset(int index); 2418 inline Object* InObjectPropertyAt(int index); 2419 inline Object* InObjectPropertyAtPut(int index, 2420 Object* value, 2421 WriteBarrierMode mode 2422 = UPDATE_WRITE_BARRIER); 2423 2424 // Set the object's prototype (only JSReceiver and null are allowed values). 2425 MUST_USE_RESULT static Maybe<bool> SetPrototype(Handle<JSObject> object, 2426 Handle<Object> value, 2427 bool from_javascript, 2428 ShouldThrow should_throw); 2429 2430 // Makes the object prototype immutable 2431 // Never called from JavaScript 2432 static void SetImmutableProto(Handle<JSObject> object); 2433 2434 // Initializes the body starting at |start_offset|. It is responsibility of 2435 // the caller to initialize object header. Fill the pre-allocated fields with 2436 // pre_allocated_value and the rest with filler_value. 2437 // Note: this call does not update write barrier, the caller is responsible 2438 // to ensure that |filler_value| can be collected without WB here. 2439 inline void InitializeBody(Map* map, int start_offset, 2440 Object* pre_allocated_value, Object* filler_value); 2441 2442 // Check whether this object references another object 2443 bool ReferencesObject(Object* obj); 2444 2445 MUST_USE_RESULT static Maybe<bool> PreventExtensions( 2446 Handle<JSObject> object, ShouldThrow should_throw); 2447 2448 static bool IsExtensible(Handle<JSObject> object); 2449 2450 // Copy object. 2451 enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 }; 2452 2453 MUST_USE_RESULT static MaybeHandle<JSObject> DeepCopy( 2454 Handle<JSObject> object, 2455 AllocationSiteUsageContext* site_context, 2456 DeepCopyHints hints = kNoHints); 2457 MUST_USE_RESULT static MaybeHandle<JSObject> DeepWalk( 2458 Handle<JSObject> object, 2459 AllocationSiteCreationContext* site_context); 2460 2461 DECLARE_CAST(JSObject) 2462 2463 // Dispatched behavior. 2464 void JSObjectShortPrint(StringStream* accumulator); 2465 DECLARE_PRINTER(JSObject) 2466 DECLARE_VERIFIER(JSObject) 2467 #ifdef OBJECT_PRINT 2468 bool PrintProperties(std::ostream& os); // NOLINT 2469 bool PrintElements(std::ostream& os); // NOLINT 2470 #endif 2471 #if defined(DEBUG) || defined(OBJECT_PRINT) 2472 void PrintTransitions(std::ostream& os); // NOLINT 2473 #endif 2474 2475 static void PrintElementsTransition( 2476 FILE* file, Handle<JSObject> object, 2477 ElementsKind from_kind, Handle<FixedArrayBase> from_elements, 2478 ElementsKind to_kind, Handle<FixedArrayBase> to_elements); 2479 2480 void PrintInstanceMigration(FILE* file, Map* original_map, Map* new_map); 2481 2482 #ifdef DEBUG 2483 // Structure for collecting spill information about JSObjects. 2484 class SpillInformation { 2485 public: 2486 void Clear(); 2487 void Print(); 2488 int number_of_objects_; 2489 int number_of_objects_with_fast_properties_; 2490 int number_of_objects_with_fast_elements_; 2491 int number_of_fast_used_fields_; 2492 int number_of_fast_unused_fields_; 2493 int number_of_slow_used_properties_; 2494 int number_of_slow_unused_properties_; 2495 int number_of_fast_used_elements_; 2496 int number_of_fast_unused_elements_; 2497 int number_of_slow_used_elements_; 2498 int number_of_slow_unused_elements_; 2499 }; 2500 2501 void IncrementSpillStatistics(SpillInformation* info); 2502 #endif 2503 2504 #ifdef VERIFY_HEAP 2505 // If a GC was caused while constructing this object, the elements pointer 2506 // may point to a one pointer filler map. The object won't be rooted, but 2507 // our heap verification code could stumble across it. 2508 bool ElementsAreSafeToExamine(); 2509 #endif 2510 2511 Object* SlowReverseLookup(Object* value); 2512 2513 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1). 2514 // Also maximal value of JSArray's length property. 2515 static const uint32_t kMaxElementCount = 0xffffffffu; 2516 2517 // Constants for heuristics controlling conversion of fast elements 2518 // to slow elements. 2519 2520 // Maximal gap that can be introduced by adding an element beyond 2521 // the current elements length. 2522 static const uint32_t kMaxGap = 1024; 2523 2524 // Maximal length of fast elements array that won't be checked for 2525 // being dense enough on expansion. 2526 static const int kMaxUncheckedFastElementsLength = 5000; 2527 2528 // Same as above but for old arrays. This limit is more strict. We 2529 // don't want to be wasteful with long lived objects. 2530 static const int kMaxUncheckedOldFastElementsLength = 500; 2531 2532 // This constant applies only to the initial map of "global.Object" and 2533 // not to arbitrary other JSObject maps. 2534 static const int kInitialGlobalObjectUnusedPropertiesCount = 4; 2535 2536 static const int kMaxInstanceSize = 255 * kPointerSize; 2537 // When extending the backing storage for property values, we increase 2538 // its size by more than the 1 entry necessary, so sequentially adding fields 2539 // to the same object requires fewer allocations and copies. 2540 static const int kFieldsAdded = 3; 2541 2542 // Layout description. 2543 static const int kElementsOffset = JSReceiver::kHeaderSize; 2544 static const int kHeaderSize = kElementsOffset + kPointerSize; 2545 2546 STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize); 2547 2548 typedef FlexibleBodyDescriptor<JSReceiver::kPropertiesOffset> BodyDescriptor; 2549 2550 // Gets the number of currently used elements. 2551 int GetFastElementsUsage(); 2552 2553 static bool AllCanRead(LookupIterator* it); 2554 static bool AllCanWrite(LookupIterator* it); 2555 2556 private: 2557 friend class JSReceiver; 2558 friend class Object; 2559 2560 // Used from Object::GetProperty(). 2561 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck( 2562 LookupIterator* it); 2563 2564 MUST_USE_RESULT static Maybe<bool> SetPropertyWithFailedAccessCheck( 2565 LookupIterator* it, Handle<Object> value, ShouldThrow should_throw); 2566 2567 MUST_USE_RESULT static Maybe<bool> DeletePropertyWithInterceptor( 2568 LookupIterator* it, ShouldThrow should_throw); 2569 2570 bool ReferencesObjectFromElements(FixedArray* elements, 2571 ElementsKind kind, 2572 Object* object); 2573 2574 static Object* GetIdentityHash(Isolate* isolate, Handle<JSObject> object); 2575 2576 static Smi* GetOrCreateIdentityHash(Isolate* isolate, 2577 Handle<JSObject> object); 2578 2579 // Helper for fast versions of preventExtensions, seal, and freeze. 2580 // attrs is one of NONE, SEALED, or FROZEN (depending on the operation). 2581 template <PropertyAttributes attrs> 2582 MUST_USE_RESULT static Maybe<bool> PreventExtensionsWithTransition( 2583 Handle<JSObject> object, ShouldThrow should_throw); 2584 2585 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject); 2586 }; 2587 2588 2589 // JSAccessorPropertyDescriptor is just a JSObject with a specific initial 2590 // map. This initial map adds in-object properties for "get", "set", 2591 // "enumerable" and "configurable" properties, as assigned by the 2592 // FromPropertyDescriptor function for regular accessor properties. 2593 class JSAccessorPropertyDescriptor: public JSObject { 2594 public: 2595 // Offsets of object fields. 2596 static const int kGetOffset = JSObject::kHeaderSize; 2597 static const int kSetOffset = kGetOffset + kPointerSize; 2598 static const int kEnumerableOffset = kSetOffset + kPointerSize; 2599 static const int kConfigurableOffset = kEnumerableOffset + kPointerSize; 2600 static const int kSize = kConfigurableOffset + kPointerSize; 2601 // Indices of in-object properties. 2602 static const int kGetIndex = 0; 2603 static const int kSetIndex = 1; 2604 static const int kEnumerableIndex = 2; 2605 static const int kConfigurableIndex = 3; 2606 2607 private: 2608 DISALLOW_IMPLICIT_CONSTRUCTORS(JSAccessorPropertyDescriptor); 2609 }; 2610 2611 2612 // JSDataPropertyDescriptor is just a JSObject with a specific initial map. 2613 // This initial map adds in-object properties for "value", "writable", 2614 // "enumerable" and "configurable" properties, as assigned by the 2615 // FromPropertyDescriptor function for regular data properties. 2616 class JSDataPropertyDescriptor: public JSObject { 2617 public: 2618 // Offsets of object fields. 2619 static const int kValueOffset = JSObject::kHeaderSize; 2620 static const int kWritableOffset = kValueOffset + kPointerSize; 2621 static const int kEnumerableOffset = kWritableOffset + kPointerSize; 2622 static const int kConfigurableOffset = kEnumerableOffset + kPointerSize; 2623 static const int kSize = kConfigurableOffset + kPointerSize; 2624 // Indices of in-object properties. 2625 static const int kValueIndex = 0; 2626 static const int kWritableIndex = 1; 2627 static const int kEnumerableIndex = 2; 2628 static const int kConfigurableIndex = 3; 2629 2630 private: 2631 DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataPropertyDescriptor); 2632 }; 2633 2634 2635 // JSIteratorResult is just a JSObject with a specific initial map. 2636 // This initial map adds in-object properties for "done" and "value", 2637 // as specified by ES6 section 25.1.1.3 The IteratorResult Interface 2638 class JSIteratorResult: public JSObject { 2639 public: 2640 DECL_ACCESSORS(value, Object) 2641 2642 DECL_ACCESSORS(done, Object) 2643 2644 // Offsets of object fields. 2645 static const int kValueOffset = JSObject::kHeaderSize; 2646 static const int kDoneOffset = kValueOffset + kPointerSize; 2647 static const int kSize = kDoneOffset + kPointerSize; 2648 // Indices of in-object properties. 2649 static const int kValueIndex = 0; 2650 static const int kDoneIndex = 1; 2651 2652 private: 2653 DISALLOW_IMPLICIT_CONSTRUCTORS(JSIteratorResult); 2654 }; 2655 2656 2657 // Common superclass for JSSloppyArgumentsObject and JSStrictArgumentsObject. 2658 class JSArgumentsObject: public JSObject { 2659 public: 2660 // Offsets of object fields. 2661 static const int kLengthOffset = JSObject::kHeaderSize; 2662 static const int kHeaderSize = kLengthOffset + kPointerSize; 2663 // Indices of in-object properties. 2664 static const int kLengthIndex = 0; 2665 2666 private: 2667 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArgumentsObject); 2668 }; 2669 2670 2671 // JSSloppyArgumentsObject is just a JSObject with specific initial map. 2672 // This initial map adds in-object properties for "length" and "callee". 2673 class JSSloppyArgumentsObject: public JSArgumentsObject { 2674 public: 2675 // Offsets of object fields. 2676 static const int kCalleeOffset = JSArgumentsObject::kHeaderSize; 2677 static const int kSize = kCalleeOffset + kPointerSize; 2678 // Indices of in-object properties. 2679 static const int kCalleeIndex = 1; 2680 2681 private: 2682 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSloppyArgumentsObject); 2683 }; 2684 2685 2686 // JSStrictArgumentsObject is just a JSObject with specific initial map. 2687 // This initial map adds an in-object property for "length". 2688 class JSStrictArgumentsObject: public JSArgumentsObject { 2689 public: 2690 // Offsets of object fields. 2691 static const int kSize = JSArgumentsObject::kHeaderSize; 2692 2693 private: 2694 DISALLOW_IMPLICIT_CONSTRUCTORS(JSStrictArgumentsObject); 2695 }; 2696 2697 2698 // Common superclass for FixedArrays that allow implementations to share 2699 // common accessors and some code paths. 2700 class FixedArrayBase: public HeapObject { 2701 public: 2702 // [length]: length of the array. 2703 inline int length() const; 2704 inline void set_length(int value); 2705 2706 // Get and set the length using acquire loads and release stores. 2707 inline int synchronized_length() const; 2708 inline void synchronized_set_length(int value); 2709 2710 DECLARE_CAST(FixedArrayBase) 2711 2712 static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind); 2713 2714 // Layout description. 2715 // Length is smi tagged when it is stored. 2716 static const int kLengthOffset = HeapObject::kHeaderSize; 2717 static const int kHeaderSize = kLengthOffset + kPointerSize; 2718 }; 2719 2720 2721 class FixedDoubleArray; 2722 class IncrementalMarking; 2723 2724 2725 // FixedArray describes fixed-sized arrays with element type Object*. 2726 class FixedArray: public FixedArrayBase { 2727 public: 2728 // Setter and getter for elements. 2729 inline Object* get(int index) const; 2730 static inline Handle<Object> get(FixedArray* array, int index, 2731 Isolate* isolate); 2732 template <class T> 2733 MaybeHandle<T> GetValue(Isolate* isolate, int index) const; 2734 2735 template <class T> 2736 Handle<T> GetValueChecked(Isolate* isolate, int index) const; 2737 2738 // Return a grown copy if the index is bigger than the array's length. 2739 static Handle<FixedArray> SetAndGrow(Handle<FixedArray> array, int index, 2740 Handle<Object> value); 2741 2742 // Setter that uses write barrier. 2743 inline void set(int index, Object* value); 2744 inline bool is_the_hole(Isolate* isolate, int index); 2745 2746 // Setter that doesn't need write barrier. 2747 inline void set(int index, Smi* value); 2748 // Setter with explicit barrier mode. 2749 inline void set(int index, Object* value, WriteBarrierMode mode); 2750 2751 // Setters for frequently used oddballs located in old space. 2752 inline void set_undefined(int index); 2753 inline void set_undefined(Isolate* isolate, int index); 2754 inline void set_null(int index); 2755 inline void set_null(Isolate* isolate, int index); 2756 inline void set_the_hole(int index); 2757 inline void set_the_hole(Isolate* isolate, int index); 2758 2759 inline Object** GetFirstElementAddress(); 2760 inline bool ContainsOnlySmisOrHoles(); 2761 2762 // Gives access to raw memory which stores the array's data. 2763 inline Object** data_start(); 2764 2765 inline void FillWithHoles(int from, int to); 2766 2767 // Shrink length and insert filler objects. 2768 void Shrink(int length); 2769 2770 // Copy a sub array from the receiver to dest. 2771 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); 2772 2773 // Garbage collection support. 2774 static constexpr int SizeFor(int length) { 2775 return kHeaderSize + length * kPointerSize; 2776 } 2777 2778 // Code Generation support. 2779 static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); } 2780 2781 // Garbage collection support. 2782 inline Object** RawFieldOfElementAt(int index); 2783 2784 DECLARE_CAST(FixedArray) 2785 2786 // Maximal allowed size, in bytes, of a single FixedArray. 2787 // Prevents overflowing size computations, as well as extreme memory 2788 // consumption. 2789 static const int kMaxSize = 128 * MB * kPointerSize; 2790 // Maximally allowed length of a FixedArray. 2791 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize; 2792 2793 // Dispatched behavior. 2794 DECLARE_PRINTER(FixedArray) 2795 DECLARE_VERIFIER(FixedArray) 2796 #ifdef DEBUG 2797 // Checks if two FixedArrays have identical contents. 2798 bool IsEqualTo(FixedArray* other); 2799 #endif 2800 2801 typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor; 2802 2803 protected: 2804 // Set operation on FixedArray without using write barriers. Can 2805 // only be used for storing old space objects or smis. 2806 static inline void NoWriteBarrierSet(FixedArray* array, 2807 int index, 2808 Object* value); 2809 2810 private: 2811 STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize); 2812 2813 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray); 2814 }; 2815 2816 // FixedDoubleArray describes fixed-sized arrays with element type double. 2817 class FixedDoubleArray: public FixedArrayBase { 2818 public: 2819 // Setter and getter for elements. 2820 inline double get_scalar(int index); 2821 inline uint64_t get_representation(int index); 2822 static inline Handle<Object> get(FixedDoubleArray* array, int index, 2823 Isolate* isolate); 2824 inline void set(int index, double value); 2825 inline void set_the_hole(Isolate* isolate, int index); 2826 inline void set_the_hole(int index); 2827 2828 // Checking for the hole. 2829 inline bool is_the_hole(Isolate* isolate, int index); 2830 inline bool is_the_hole(int index); 2831 2832 // Garbage collection support. 2833 inline static int SizeFor(int length) { 2834 return kHeaderSize + length * kDoubleSize; 2835 } 2836 2837 // Gives access to raw memory which stores the array's data. 2838 inline double* data_start(); 2839 2840 inline void FillWithHoles(int from, int to); 2841 2842 // Code Generation support. 2843 static int OffsetOfElementAt(int index) { return SizeFor(index); } 2844 2845 DECLARE_CAST(FixedDoubleArray) 2846 2847 // Maximal allowed size, in bytes, of a single FixedDoubleArray. 2848 // Prevents overflowing size computations, as well as extreme memory 2849 // consumption. 2850 static const int kMaxSize = 512 * MB; 2851 // Maximally allowed length of a FixedArray. 2852 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize; 2853 2854 // Dispatched behavior. 2855 DECLARE_PRINTER(FixedDoubleArray) 2856 DECLARE_VERIFIER(FixedDoubleArray) 2857 2858 private: 2859 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray); 2860 }; 2861 2862 2863 class WeakFixedArray : public FixedArray { 2864 public: 2865 // If |maybe_array| is not a WeakFixedArray, a fresh one will be allocated. 2866 // This function does not check if the value exists already, callers must 2867 // ensure this themselves if necessary. 2868 static Handle<WeakFixedArray> Add(Handle<Object> maybe_array, 2869 Handle<HeapObject> value, 2870 int* assigned_index = NULL); 2871 2872 // Returns true if an entry was found and removed. 2873 bool Remove(Handle<HeapObject> value); 2874 2875 class NullCallback { 2876 public: 2877 static void Callback(Object* value, int old_index, int new_index) {} 2878 }; 2879 2880 template <class CompactionCallback> 2881 void Compact(); 2882 2883 inline Object* Get(int index) const; 2884 inline void Clear(int index); 2885 inline int Length() const; 2886 2887 inline bool IsEmptySlot(int index) const; 2888 static Object* Empty() { return Smi::kZero; } 2889 2890 class Iterator { 2891 public: 2892 explicit Iterator(Object* maybe_array) : list_(NULL) { Reset(maybe_array); } 2893 void Reset(Object* maybe_array); 2894 2895 template <class T> 2896 inline T* Next(); 2897 2898 private: 2899 int index_; 2900 WeakFixedArray* list_; 2901 #ifdef DEBUG 2902 int last_used_index_; 2903 DisallowHeapAllocation no_gc_; 2904 #endif // DEBUG 2905 DISALLOW_COPY_AND_ASSIGN(Iterator); 2906 }; 2907 2908 DECLARE_CAST(WeakFixedArray) 2909 2910 private: 2911 static const int kLastUsedIndexIndex = 0; 2912 static const int kFirstIndex = 1; 2913 2914 static Handle<WeakFixedArray> Allocate( 2915 Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from); 2916 2917 static void Set(Handle<WeakFixedArray> array, int index, 2918 Handle<HeapObject> value); 2919 inline void clear(int index); 2920 2921 inline int last_used_index() const; 2922 inline void set_last_used_index(int index); 2923 2924 // Disallow inherited setters. 2925 void set(int index, Smi* value); 2926 void set(int index, Object* value); 2927 void set(int index, Object* value, WriteBarrierMode mode); 2928 DISALLOW_IMPLICIT_CONSTRUCTORS(WeakFixedArray); 2929 }; 2930 2931 // Generic array grows dynamically with O(1) amortized insertion. 2932 class ArrayList : public FixedArray { 2933 public: 2934 enum AddMode { 2935 kNone, 2936 // Use this if GC can delete elements from the array. 2937 kReloadLengthAfterAllocation, 2938 }; 2939 static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj, 2940 AddMode mode = kNone); 2941 static Handle<ArrayList> Add(Handle<ArrayList> array, Handle<Object> obj1, 2942 Handle<Object> obj2, AddMode = kNone); 2943 static Handle<ArrayList> New(Isolate* isolate, int size); 2944 inline int Length(); 2945 inline void SetLength(int length); 2946 inline Object* Get(int index); 2947 inline Object** Slot(int index); 2948 inline void Set(int index, Object* obj, 2949 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 2950 inline void Clear(int index, Object* undefined); 2951 bool IsFull(); 2952 DECLARE_CAST(ArrayList) 2953 2954 private: 2955 static Handle<ArrayList> EnsureSpace(Handle<ArrayList> array, int length); 2956 static const int kLengthIndex = 0; 2957 static const int kFirstIndex = 1; 2958 DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayList); 2959 }; 2960 2961 #define FRAME_ARRAY_FIELD_LIST(V) \ 2962 V(WasmInstance, Object) \ 2963 V(WasmFunctionIndex, Smi) \ 2964 V(Receiver, Object) \ 2965 V(Function, JSFunction) \ 2966 V(Code, AbstractCode) \ 2967 V(Offset, Smi) \ 2968 V(Flags, Smi) 2969 2970 // Container object for data collected during simple stack trace captures. 2971 class FrameArray : public FixedArray { 2972 public: 2973 #define DECLARE_FRAME_ARRAY_ACCESSORS(name, type) \ 2974 inline type* name(int frame_ix) const; \ 2975 inline void Set##name(int frame_ix, type* value); 2976 FRAME_ARRAY_FIELD_LIST(DECLARE_FRAME_ARRAY_ACCESSORS) 2977 #undef DECLARE_FRAME_ARRAY_ACCESSORS 2978 2979 inline bool IsWasmFrame(int frame_ix) const; 2980 inline bool IsAsmJsWasmFrame(int frame_ix) const; 2981 inline int FrameCount() const; 2982 2983 void ShrinkToFit(); 2984 2985 // Flags. 2986 static const int kIsWasmFrame = 1 << 0; 2987 static const int kIsAsmJsWasmFrame = 1 << 1; 2988 static const int kIsStrict = 1 << 2; 2989 static const int kForceConstructor = 1 << 3; 2990 static const int kAsmJsAtNumberConversion = 1 << 4; 2991 2992 static Handle<FrameArray> AppendJSFrame(Handle<FrameArray> in, 2993 Handle<Object> receiver, 2994 Handle<JSFunction> function, 2995 Handle<AbstractCode> code, int offset, 2996 int flags); 2997 static Handle<FrameArray> AppendWasmFrame(Handle<FrameArray> in, 2998 Handle<Object> wasm_instance, 2999 int wasm_function_index, 3000 Handle<AbstractCode> code, 3001 int offset, int flags); 3002 3003 DECLARE_CAST(FrameArray) 3004 3005 private: 3006 // The underlying fixed array embodies a captured stack trace. Frame i 3007 // occupies indices 3008 // 3009 // kFirstIndex + 1 + [i * kElementsPerFrame, (i + 1) * kElementsPerFrame[, 3010 // 3011 // with internal offsets as below: 3012 3013 static const int kWasmInstanceOffset = 0; 3014 static const int kWasmFunctionIndexOffset = 1; 3015 3016 static const int kReceiverOffset = 0; 3017 static const int kFunctionOffset = 1; 3018 3019 static const int kCodeOffset = 2; 3020 static const int kOffsetOffset = 3; 3021 3022 static const int kFlagsOffset = 4; 3023 3024 static const int kElementsPerFrame = 5; 3025 3026 // Array layout indices. 3027 3028 static const int kFrameCountIndex = 0; 3029 static const int kFirstIndex = 1; 3030 3031 static int LengthFor(int frame_count) { 3032 return kFirstIndex + frame_count * kElementsPerFrame; 3033 } 3034 3035 static Handle<FrameArray> EnsureSpace(Handle<FrameArray> array, int length); 3036 3037 friend class Factory; 3038 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameArray); 3039 }; 3040 3041 // DescriptorArrays are fixed arrays used to hold instance descriptors. 3042 // The format of the these objects is: 3043 // [0]: Number of descriptors 3044 // [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array: 3045 // [0]: pointer to fixed array with enum cache 3046 // [1]: either Smi(0) or pointer to fixed array with indices 3047 // [2]: first key 3048 // [2 + number of descriptors * kEntrySize]: start of slack 3049 class DescriptorArray: public FixedArray { 3050 public: 3051 // Returns true for both shared empty_descriptor_array and for smis, which the 3052 // map uses to encode additional bit fields when the descriptor array is not 3053 // yet used. 3054 inline bool IsEmpty(); 3055 3056 // Returns the number of descriptors in the array. 3057 inline int number_of_descriptors(); 3058 3059 inline int number_of_descriptors_storage(); 3060 3061 inline int NumberOfSlackDescriptors(); 3062 3063 inline void SetNumberOfDescriptors(int number_of_descriptors); 3064 inline int number_of_entries(); 3065 3066 inline bool HasEnumCache(); 3067 3068 inline void CopyEnumCacheFrom(DescriptorArray* array); 3069 3070 inline FixedArray* GetEnumCache(); 3071 3072 inline bool HasEnumIndicesCache(); 3073 3074 inline FixedArray* GetEnumIndicesCache(); 3075 3076 inline Object** GetEnumCacheSlot(); 3077 3078 void ClearEnumCache(); 3079 3080 // Initialize or change the enum cache, 3081 // using the supplied storage for the small "bridge". 3082 static void SetEnumCache(Handle<DescriptorArray> descriptors, 3083 Isolate* isolate, Handle<FixedArray> new_cache, 3084 Handle<FixedArray> new_index_cache); 3085 3086 // Accessors for fetching instance descriptor at descriptor number. 3087 inline Name* GetKey(int descriptor_number); 3088 inline Object** GetKeySlot(int descriptor_number); 3089 inline Object* GetValue(int descriptor_number); 3090 inline void SetValue(int descriptor_number, Object* value); 3091 inline Object** GetValueSlot(int descriptor_number); 3092 static inline int GetValueOffset(int descriptor_number); 3093 inline Object** GetDescriptorStartSlot(int descriptor_number); 3094 inline Object** GetDescriptorEndSlot(int descriptor_number); 3095 inline PropertyDetails GetDetails(int descriptor_number); 3096 inline int GetFieldIndex(int descriptor_number); 3097 inline FieldType* GetFieldType(int descriptor_number); 3098 3099 inline Name* GetSortedKey(int descriptor_number); 3100 inline int GetSortedKeyIndex(int descriptor_number); 3101 inline void SetSortedKey(int pointer, int descriptor_number); 3102 3103 // Accessor for complete descriptor. 3104 inline void Get(int descriptor_number, Descriptor* desc); 3105 inline void Set(int descriptor_number, Descriptor* desc); 3106 inline void Set(int descriptor_number, Name* key, Object* value, 3107 PropertyDetails details); 3108 void Replace(int descriptor_number, Descriptor* descriptor); 3109 3110 // Generalizes constness, representation and field type of all field 3111 // descriptors. 3112 void GeneralizeAllFields(); 3113 3114 // Append automatically sets the enumeration index. This should only be used 3115 // to add descriptors in bulk at the end, followed by sorting the descriptor 3116 // array. 3117 inline void Append(Descriptor* desc); 3118 3119 static Handle<DescriptorArray> CopyUpTo(Handle<DescriptorArray> desc, 3120 int enumeration_index, 3121 int slack = 0); 3122 3123 static Handle<DescriptorArray> CopyUpToAddAttributes( 3124 Handle<DescriptorArray> desc, 3125 int enumeration_index, 3126 PropertyAttributes attributes, 3127 int slack = 0); 3128 3129 // Sort the instance descriptors by the hash codes of their keys. 3130 void Sort(); 3131 3132 // Search the instance descriptors for given name. 3133 INLINE(int Search(Name* name, int number_of_own_descriptors)); 3134 3135 // As the above, but uses DescriptorLookupCache and updates it when 3136 // necessary. 3137 INLINE(int SearchWithCache(Isolate* isolate, Name* name, Map* map)); 3138 3139 bool IsEqualUpTo(DescriptorArray* desc, int nof_descriptors); 3140 3141 // Allocates a DescriptorArray, but returns the singleton 3142 // empty descriptor array object if number_of_descriptors is 0. 3143 static Handle<DescriptorArray> Allocate( 3144 Isolate* isolate, int number_of_descriptors, int slack, 3145 PretenureFlag pretenure = NOT_TENURED); 3146 3147 DECLARE_CAST(DescriptorArray) 3148 3149 // Constant for denoting key was not found. 3150 static const int kNotFound = -1; 3151 3152 static const int kDescriptorLengthIndex = 0; 3153 static const int kEnumCacheIndex = 1; 3154 static const int kFirstIndex = 2; 3155 3156 // The length of the "bridge" to the enum cache. 3157 static const int kEnumCacheBridgeLength = 2; 3158 static const int kEnumCacheBridgeCacheIndex = 0; 3159 static const int kEnumCacheBridgeIndicesCacheIndex = 1; 3160 3161 // Layout description. 3162 static const int kDescriptorLengthOffset = FixedArray::kHeaderSize; 3163 static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize; 3164 static const int kFirstOffset = kEnumCacheOffset + kPointerSize; 3165 3166 // Layout description for the bridge array. 3167 static const int kEnumCacheBridgeCacheOffset = FixedArray::kHeaderSize; 3168 3169 // Layout of descriptor. 3170 // Naming is consistent with Dictionary classes for easy templating. 3171 static const int kEntryKeyIndex = 0; 3172 static const int kEntryDetailsIndex = 1; 3173 static const int kEntryValueIndex = 2; 3174 static const int kEntrySize = 3; 3175 3176 #if defined(DEBUG) || defined(OBJECT_PRINT) 3177 // For our gdb macros, we should perhaps change these in the future. 3178 void Print(); 3179 3180 // Print all the descriptors. 3181 void PrintDescriptors(std::ostream& os); // NOLINT 3182 3183 void PrintDescriptorDetails(std::ostream& os, int descriptor, 3184 PropertyDetails::PrintMode mode); 3185 #endif 3186 3187 #ifdef DEBUG 3188 // Is the descriptor array sorted and without duplicates? 3189 bool IsSortedNoDuplicates(int valid_descriptors = -1); 3190 3191 // Is the descriptor array consistent with the back pointers in targets? 3192 bool IsConsistentWithBackPointers(Map* current_map); 3193 3194 // Are two DescriptorArrays equal? 3195 bool IsEqualTo(DescriptorArray* other); 3196 #endif 3197 3198 // Returns the fixed array length required to hold number_of_descriptors 3199 // descriptors. 3200 static int LengthFor(int number_of_descriptors) { 3201 return ToKeyIndex(number_of_descriptors); 3202 } 3203 3204 static int ToDetailsIndex(int descriptor_number) { 3205 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryDetailsIndex; 3206 } 3207 3208 // Conversion from descriptor number to array indices. 3209 static int ToKeyIndex(int descriptor_number) { 3210 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryKeyIndex; 3211 } 3212 3213 static int ToValueIndex(int descriptor_number) { 3214 return kFirstIndex + (descriptor_number * kEntrySize) + kEntryValueIndex; 3215 } 3216 3217 private: 3218 // Transfer a complete descriptor from the src descriptor array to this 3219 // descriptor array. 3220 void CopyFrom(int index, DescriptorArray* src); 3221 3222 // Swap first and second descriptor. 3223 inline void SwapSortedKeys(int first, int second); 3224 3225 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); 3226 }; 3227 3228 3229 enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; 3230 3231 template <SearchMode search_mode, typename T> 3232 inline int Search(T* array, Name* name, int valid_entries = 0, 3233 int* out_insertion_index = NULL); 3234 3235 3236 // HashTable is a subclass of FixedArray that implements a hash table 3237 // that uses open addressing and quadratic probing. 3238 // 3239 // In order for the quadratic probing to work, elements that have not 3240 // yet been used and elements that have been deleted are 3241 // distinguished. Probing continues when deleted elements are 3242 // encountered and stops when unused elements are encountered. 3243 // 3244 // - Elements with key == undefined have not been used yet. 3245 // - Elements with key == the_hole have been deleted. 3246 // 3247 // The hash table class is parameterized with a Shape and a Key. 3248 // Shape must be a class with the following interface: 3249 // class ExampleShape { 3250 // public: 3251 // // Tells whether key matches other. 3252 // static bool IsMatch(Key key, Object* other); 3253 // // Returns the hash value for key. 3254 // static uint32_t Hash(Key key); 3255 // // Returns the hash value for object. 3256 // static uint32_t HashForObject(Key key, Object* object); 3257 // // Convert key to an object. 3258 // static inline Handle<Object> AsHandle(Isolate* isolate, Key key); 3259 // // The prefix size indicates number of elements in the beginning 3260 // // of the backing storage. 3261 // static const int kPrefixSize = ..; 3262 // // The Element size indicates number of elements per entry. 3263 // static const int kEntrySize = ..; 3264 // }; 3265 // The prefix size indicates an amount of memory in the 3266 // beginning of the backing storage that can be used for non-element 3267 // information by subclasses. 3268 3269 template<typename Key> 3270 class BaseShape { 3271 public: 3272 static const bool UsesSeed = false; 3273 static uint32_t Hash(Key key) { return 0; } 3274 static uint32_t SeededHash(Key key, uint32_t seed) { 3275 DCHECK(UsesSeed); 3276 return Hash(key); 3277 } 3278 static uint32_t HashForObject(Key key, Object* object) { return 0; } 3279 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) { 3280 DCHECK(UsesSeed); 3281 return HashForObject(key, object); 3282 } 3283 static inline Map* GetMap(Isolate* isolate); 3284 }; 3285 3286 3287 class HashTableBase : public FixedArray { 3288 public: 3289 // Returns the number of elements in the hash table. 3290 inline int NumberOfElements(); 3291 3292 // Returns the number of deleted elements in the hash table. 3293 inline int NumberOfDeletedElements(); 3294 3295 // Returns the capacity of the hash table. 3296 inline int Capacity(); 3297 3298 // ElementAdded should be called whenever an element is added to a 3299 // hash table. 3300 inline void ElementAdded(); 3301 3302 // ElementRemoved should be called whenever an element is removed from 3303 // a hash table. 3304 inline void ElementRemoved(); 3305 inline void ElementsRemoved(int n); 3306 3307 // Computes the required capacity for a table holding the given 3308 // number of elements. May be more than HashTable::kMaxCapacity. 3309 static inline int ComputeCapacity(int at_least_space_for); 3310 3311 // Tells whether k is a real key. The hole and undefined are not allowed 3312 // as keys and can be used to indicate missing or deleted elements. 3313 inline bool IsKey(Object* k); 3314 inline bool IsKey(Isolate* isolate, Object* k); 3315 3316 // Compute the probe offset (quadratic probing). 3317 INLINE(static uint32_t GetProbeOffset(uint32_t n)) { 3318 return (n + n * n) >> 1; 3319 } 3320 3321 static const int kNumberOfElementsIndex = 0; 3322 static const int kNumberOfDeletedElementsIndex = 1; 3323 static const int kCapacityIndex = 2; 3324 static const int kPrefixStartIndex = 3; 3325 3326 // Constant used for denoting a absent entry. 3327 static const int kNotFound = -1; 3328 3329 // Minimum capacity for newly created hash tables. 3330 static const int kMinCapacity = 4; 3331 3332 protected: 3333 // Update the number of elements in the hash table. 3334 inline void SetNumberOfElements(int nof); 3335 3336 // Update the number of deleted elements in the hash table. 3337 inline void SetNumberOfDeletedElements(int nod); 3338 3339 // Returns probe entry. 3340 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) { 3341 DCHECK(base::bits::IsPowerOfTwo32(size)); 3342 return (hash + GetProbeOffset(number)) & (size - 1); 3343 } 3344 3345 inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) { 3346 return hash & (size - 1); 3347 } 3348 3349 inline static uint32_t NextProbe( 3350 uint32_t last, uint32_t number, uint32_t size) { 3351 return (last + number) & (size - 1); 3352 } 3353 }; 3354 3355 3356 template <typename Derived, typename Shape, typename Key> 3357 class HashTable : public HashTableBase { 3358 public: 3359 typedef Shape ShapeT; 3360 3361 // Wrapper methods 3362 inline uint32_t Hash(Key key) { 3363 if (Shape::UsesSeed) { 3364 return Shape::SeededHash(key, GetHeap()->HashSeed()); 3365 } else { 3366 return Shape::Hash(key); 3367 } 3368 } 3369 3370 inline uint32_t HashForObject(Key key, Object* object) { 3371 if (Shape::UsesSeed) { 3372 return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object); 3373 } else { 3374 return Shape::HashForObject(key, object); 3375 } 3376 } 3377 3378 // Returns a new HashTable object. 3379 MUST_USE_RESULT static Handle<Derived> New( 3380 Isolate* isolate, int at_least_space_for, 3381 MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY, 3382 PretenureFlag pretenure = NOT_TENURED); 3383 3384 DECLARE_CAST(HashTable) 3385 3386 // Garbage collection support. 3387 void IteratePrefix(ObjectVisitor* visitor); 3388 void IterateElements(ObjectVisitor* visitor); 3389 3390 // Find entry for key otherwise return kNotFound. 3391 inline int FindEntry(Key key); 3392 inline int FindEntry(Isolate* isolate, Key key, int32_t hash); 3393 int FindEntry(Isolate* isolate, Key key); 3394 inline bool Has(Isolate* isolate, Key key); 3395 inline bool Has(Key key); 3396 3397 // Rehashes the table in-place. 3398 void Rehash(Key key); 3399 3400 // Returns the key at entry. 3401 Object* KeyAt(int entry) { return get(EntryToIndex(entry) + kEntryKeyIndex); } 3402 3403 static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize; 3404 static const int kEntrySize = Shape::kEntrySize; 3405 STATIC_ASSERT(kEntrySize > 0); 3406 static const int kEntryKeyIndex = 0; 3407 static const int kElementsStartOffset = 3408 kHeaderSize + kElementsStartIndex * kPointerSize; 3409 // Maximal capacity of HashTable. Based on maximal length of underlying 3410 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex 3411 // cannot overflow. 3412 static const int kMaxCapacity = 3413 (FixedArray::kMaxLength - kElementsStartIndex) / kEntrySize; 3414 3415 // Returns the index for an entry (of the key) 3416 static inline int EntryToIndex(int entry) { 3417 return (entry * kEntrySize) + kElementsStartIndex; 3418 } 3419 3420 protected: 3421 friend class ObjectHashTable; 3422 3423 MUST_USE_RESULT static Handle<Derived> New(Isolate* isolate, int capacity, 3424 PretenureFlag pretenure); 3425 3426 // Find the entry at which to insert element with the given key that 3427 // has the given hash value. 3428 uint32_t FindInsertionEntry(uint32_t hash); 3429 3430 // Attempt to shrink hash table after removal of key. 3431 MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table, Key key); 3432 3433 // Ensure enough space for n additional elements. 3434 MUST_USE_RESULT static Handle<Derived> EnsureCapacity( 3435 Handle<Derived> table, 3436 int n, 3437 Key key, 3438 PretenureFlag pretenure = NOT_TENURED); 3439 3440 // Returns true if this table has sufficient capacity for adding n elements. 3441 bool HasSufficientCapacityToAdd(int number_of_additional_elements); 3442 3443 // Sets the capacity of the hash table. 3444 void SetCapacity(int capacity) { 3445 // To scale a computed hash code to fit within the hash table, we 3446 // use bit-wise AND with a mask, so the capacity must be positive 3447 // and non-zero. 3448 DCHECK(capacity > 0); 3449 DCHECK(capacity <= kMaxCapacity); 3450 set(kCapacityIndex, Smi::FromInt(capacity)); 3451 } 3452 3453 private: 3454 // Returns _expected_ if one of entries given by the first _probe_ probes is 3455 // equal to _expected_. Otherwise, returns the entry given by the probe 3456 // number _probe_. 3457 uint32_t EntryForProbe(Key key, Object* k, int probe, uint32_t expected); 3458 3459 void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode); 3460 3461 // Rehashes this hash-table into the new table. 3462 void Rehash(Handle<Derived> new_table, Key key); 3463 }; 3464 3465 3466 // HashTableKey is an abstract superclass for virtual key behavior. 3467 class HashTableKey { 3468 public: 3469 // Returns whether the other object matches this key. 3470 virtual bool IsMatch(Object* other) = 0; 3471 // Returns the hash value for this key. 3472 virtual uint32_t Hash() = 0; 3473 // Returns the hash value for object. 3474 virtual uint32_t HashForObject(Object* key) = 0; 3475 // Returns the key object for storing into the hash table. 3476 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) = 0; 3477 // Required. 3478 virtual ~HashTableKey() {} 3479 }; 3480 3481 3482 class StringTableShape : public BaseShape<HashTableKey*> { 3483 public: 3484 static inline bool IsMatch(HashTableKey* key, Object* value) { 3485 return key->IsMatch(value); 3486 } 3487 3488 static inline uint32_t Hash(HashTableKey* key) { 3489 return key->Hash(); 3490 } 3491 3492 static inline uint32_t HashForObject(HashTableKey* key, Object* object) { 3493 return key->HashForObject(object); 3494 } 3495 3496 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); 3497 3498 static const int kPrefixSize = 0; 3499 static const int kEntrySize = 1; 3500 }; 3501 3502 class SeqOneByteString; 3503 3504 // StringTable. 3505 // 3506 // No special elements in the prefix and the element size is 1 3507 // because only the string itself (the key) needs to be stored. 3508 class StringTable: public HashTable<StringTable, 3509 StringTableShape, 3510 HashTableKey*> { 3511 public: 3512 // Find string in the string table. If it is not there yet, it is 3513 // added. The return value is the string found. 3514 V8_EXPORT_PRIVATE static Handle<String> LookupString(Isolate* isolate, 3515 Handle<String> key); 3516 static Handle<String> LookupKey(Isolate* isolate, HashTableKey* key); 3517 static String* LookupKeyIfExists(Isolate* isolate, HashTableKey* key); 3518 3519 // Tries to internalize given string and returns string handle on success 3520 // or an empty handle otherwise. 3521 MUST_USE_RESULT static MaybeHandle<String> InternalizeStringIfExists( 3522 Isolate* isolate, 3523 Handle<String> string); 3524 3525 // Looks up a string that is equal to the given string and returns 3526 // string handle if it is found, or an empty handle otherwise. 3527 MUST_USE_RESULT static MaybeHandle<String> LookupStringIfExists( 3528 Isolate* isolate, 3529 Handle<String> str); 3530 MUST_USE_RESULT static MaybeHandle<String> LookupTwoCharsStringIfExists( 3531 Isolate* isolate, 3532 uint16_t c1, 3533 uint16_t c2); 3534 3535 static void EnsureCapacityForDeserialization(Isolate* isolate, int expected); 3536 3537 DECLARE_CAST(StringTable) 3538 3539 private: 3540 template <bool seq_one_byte> 3541 friend class JsonParser; 3542 3543 DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable); 3544 }; 3545 3546 class StringSetShape : public BaseShape<String*> { 3547 public: 3548 static inline bool IsMatch(String* key, Object* value); 3549 static inline uint32_t Hash(String* key); 3550 static inline uint32_t HashForObject(String* key, Object* object); 3551 3552 static const int kPrefixSize = 0; 3553 static const int kEntrySize = 1; 3554 }; 3555 3556 class StringSet : public HashTable<StringSet, StringSetShape, String*> { 3557 public: 3558 static Handle<StringSet> New(Isolate* isolate); 3559 static Handle<StringSet> Add(Handle<StringSet> blacklist, 3560 Handle<String> name); 3561 bool Has(Handle<String> name); 3562 3563 DECLARE_CAST(StringSet) 3564 }; 3565 3566 template <typename Derived, typename Shape, typename Key> 3567 class Dictionary: public HashTable<Derived, Shape, Key> { 3568 typedef HashTable<Derived, Shape, Key> DerivedHashTable; 3569 3570 public: 3571 // Returns the value at entry. 3572 Object* ValueAt(int entry) { 3573 return this->get(Derived::EntryToIndex(entry) + 1); 3574 } 3575 3576 // Set the value for entry. 3577 void ValueAtPut(int entry, Object* value) { 3578 this->set(Derived::EntryToIndex(entry) + 1, value); 3579 } 3580 3581 // Returns the property details for the property at entry. 3582 PropertyDetails DetailsAt(int entry) { 3583 return Shape::DetailsAt(static_cast<Derived*>(this), entry); 3584 } 3585 3586 // Set the details for entry. 3587 void DetailsAtPut(int entry, PropertyDetails value) { 3588 Shape::DetailsAtPut(static_cast<Derived*>(this), entry, value); 3589 } 3590 3591 // Returns true if property at given entry is deleted. 3592 bool IsDeleted(int entry) { 3593 return Shape::IsDeleted(static_cast<Derived*>(this), entry); 3594 } 3595 3596 // Delete a property from the dictionary. 3597 static Handle<Object> DeleteProperty(Handle<Derived> dictionary, int entry); 3598 3599 // Attempt to shrink the dictionary after deletion of key. 3600 MUST_USE_RESULT static inline Handle<Derived> Shrink( 3601 Handle<Derived> dictionary, 3602 Key key) { 3603 return DerivedHashTable::Shrink(dictionary, key); 3604 } 3605 3606 // Sorting support 3607 // TODO(dcarney): templatize or move to SeededNumberDictionary 3608 void CopyValuesTo(FixedArray* elements); 3609 3610 // Returns the number of elements in the dictionary filtering out properties 3611 // with the specified attributes. 3612 int NumberOfElementsFilterAttributes(PropertyFilter filter); 3613 3614 // Returns the number of enumerable elements in the dictionary. 3615 int NumberOfEnumElements() { 3616 return NumberOfElementsFilterAttributes(ENUMERABLE_STRINGS); 3617 } 3618 3619 enum SortMode { UNSORTED, SORTED }; 3620 3621 // Return the key indices sorted by its enumeration index. 3622 static Handle<FixedArray> IterationIndices( 3623 Handle<Dictionary<Derived, Shape, Key>> dictionary); 3624 3625 // Collect the keys into the given KeyAccumulator, in ascending chronological 3626 // order of property creation. 3627 static void CollectKeysTo(Handle<Dictionary<Derived, Shape, Key>> dictionary, 3628 KeyAccumulator* keys); 3629 3630 // Copies enumerable keys to preallocated fixed array. 3631 static void CopyEnumKeysTo(Handle<Dictionary<Derived, Shape, Key>> dictionary, 3632 Handle<FixedArray> storage, KeyCollectionMode mode, 3633 KeyAccumulator* accumulator); 3634 3635 // Accessors for next enumeration index. 3636 void SetNextEnumerationIndex(int index) { 3637 DCHECK(index != 0); 3638 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index)); 3639 } 3640 3641 int NextEnumerationIndex() { 3642 return Smi::cast(this->get(kNextEnumerationIndexIndex))->value(); 3643 } 3644 3645 // Creates a new dictionary. 3646 MUST_USE_RESULT static Handle<Derived> New( 3647 Isolate* isolate, int at_least_space_for, 3648 PretenureFlag pretenure = NOT_TENURED, 3649 MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY); 3650 3651 // Creates an dictionary with minimal possible capacity. 3652 MUST_USE_RESULT static Handle<Derived> NewEmpty( 3653 Isolate* isolate, PretenureFlag pretenure = NOT_TENURED); 3654 3655 // Ensures that a new dictionary is created when the capacity is checked. 3656 void SetRequiresCopyOnCapacityChange(); 3657 3658 // Ensure enough space for n additional elements. 3659 static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key); 3660 3661 #ifdef OBJECT_PRINT 3662 // For our gdb macros, we should perhaps change these in the future. 3663 void Print(); 3664 3665 void Print(std::ostream& os); // NOLINT 3666 #endif 3667 // Returns the key (slow). 3668 Object* SlowReverseLookup(Object* value); 3669 3670 // Sets the entry to (key, value) pair. 3671 inline void SetEntry(int entry, 3672 Handle<Object> key, 3673 Handle<Object> value); 3674 inline void SetEntry(int entry, 3675 Handle<Object> key, 3676 Handle<Object> value, 3677 PropertyDetails details); 3678 3679 MUST_USE_RESULT static Handle<Derived> Add(Handle<Derived> dictionary, 3680 Key key, Handle<Object> value, 3681 PropertyDetails details, 3682 int* entry_out = nullptr); 3683 3684 static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex; 3685 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; 3686 3687 static const bool kIsEnumerable = Shape::kIsEnumerable; 3688 3689 protected: 3690 // Generic at put operation. 3691 MUST_USE_RESULT static Handle<Derived> AtPut( 3692 Handle<Derived> dictionary, 3693 Key key, 3694 Handle<Object> value); 3695 // Add entry to dictionary. Returns entry value. 3696 static int AddEntry(Handle<Derived> dictionary, Key key, Handle<Object> value, 3697 PropertyDetails details, uint32_t hash); 3698 // Generate new enumeration indices to avoid enumeration index overflow. 3699 // Returns iteration indices array for the |dictionary|. 3700 static Handle<FixedArray> GenerateNewEnumerationIndices( 3701 Handle<Derived> dictionary); 3702 }; 3703 3704 3705 template <typename Derived, typename Shape> 3706 class NameDictionaryBase : public Dictionary<Derived, Shape, Handle<Name> > { 3707 typedef Dictionary<Derived, Shape, Handle<Name> > DerivedDictionary; 3708 3709 public: 3710 // Find entry for key, otherwise return kNotFound. Optimized version of 3711 // HashTable::FindEntry. 3712 int FindEntry(Handle<Name> key); 3713 }; 3714 3715 3716 template <typename Key> 3717 class BaseDictionaryShape : public BaseShape<Key> { 3718 public: 3719 template <typename Dictionary> 3720 static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) { 3721 STATIC_ASSERT(Dictionary::kEntrySize == 3); 3722 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 3723 return PropertyDetails(Smi::cast(dict->get( 3724 Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex))); 3725 } 3726 3727 template <typename Dictionary> 3728 static inline void DetailsAtPut(Dictionary* dict, int entry, 3729 PropertyDetails value) { 3730 STATIC_ASSERT(Dictionary::kEntrySize == 3); 3731 dict->set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex, 3732 value.AsSmi()); 3733 } 3734 3735 template <typename Dictionary> 3736 static bool IsDeleted(Dictionary* dict, int entry) { 3737 return false; 3738 } 3739 3740 template <typename Dictionary> 3741 static inline void SetEntry(Dictionary* dict, int entry, Handle<Object> key, 3742 Handle<Object> value, PropertyDetails details); 3743 }; 3744 3745 3746 class NameDictionaryShape : public BaseDictionaryShape<Handle<Name> > { 3747 public: 3748 static inline bool IsMatch(Handle<Name> key, Object* other); 3749 static inline uint32_t Hash(Handle<Name> key); 3750 static inline uint32_t HashForObject(Handle<Name> key, Object* object); 3751 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key); 3752 static const int kPrefixSize = 2; 3753 static const int kEntrySize = 3; 3754 static const int kEntryValueIndex = 1; 3755 static const int kEntryDetailsIndex = 2; 3756 static const bool kIsEnumerable = true; 3757 }; 3758 3759 3760 class NameDictionary 3761 : public NameDictionaryBase<NameDictionary, NameDictionaryShape> { 3762 typedef NameDictionaryBase<NameDictionary, NameDictionaryShape> 3763 DerivedDictionary; 3764 3765 public: 3766 DECLARE_CAST(NameDictionary) 3767 3768 inline static Handle<FixedArray> DoGenerateNewEnumerationIndices( 3769 Handle<NameDictionary> dictionary); 3770 3771 static const int kEntryValueIndex = 1; 3772 static const int kEntryDetailsIndex = 2; 3773 static const int kInitialCapacity = 2; 3774 }; 3775 3776 3777 class GlobalDictionaryShape : public NameDictionaryShape { 3778 public: 3779 static const int kEntrySize = 2; // Overrides NameDictionaryShape::kEntrySize 3780 3781 template <typename Dictionary> 3782 static inline PropertyDetails DetailsAt(Dictionary* dict, int entry); 3783 3784 template <typename Dictionary> 3785 static inline void DetailsAtPut(Dictionary* dict, int entry, 3786 PropertyDetails value); 3787 3788 template <typename Dictionary> 3789 static bool IsDeleted(Dictionary* dict, int entry); 3790 3791 template <typename Dictionary> 3792 static inline void SetEntry(Dictionary* dict, int entry, Handle<Object> key, 3793 Handle<Object> value, PropertyDetails details); 3794 }; 3795 3796 3797 class GlobalDictionary 3798 : public NameDictionaryBase<GlobalDictionary, GlobalDictionaryShape> { 3799 public: 3800 DECLARE_CAST(GlobalDictionary) 3801 3802 static const int kEntryValueIndex = 1; 3803 }; 3804 3805 3806 class NumberDictionaryShape : public BaseDictionaryShape<uint32_t> { 3807 public: 3808 static inline bool IsMatch(uint32_t key, Object* other); 3809 static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key); 3810 static const bool kIsEnumerable = false; 3811 }; 3812 3813 3814 class SeededNumberDictionaryShape : public NumberDictionaryShape { 3815 public: 3816 static const bool UsesSeed = true; 3817 static const int kPrefixSize = 2; 3818 static const int kEntrySize = 3; 3819 3820 static inline uint32_t SeededHash(uint32_t key, uint32_t seed); 3821 static inline uint32_t SeededHashForObject(uint32_t key, 3822 uint32_t seed, 3823 Object* object); 3824 }; 3825 3826 3827 class UnseededNumberDictionaryShape : public NumberDictionaryShape { 3828 public: 3829 static const int kPrefixSize = 0; 3830 static const int kEntrySize = 2; 3831 3832 static inline uint32_t Hash(uint32_t key); 3833 static inline uint32_t HashForObject(uint32_t key, Object* object); 3834 3835 template <typename Dictionary> 3836 static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) { 3837 UNREACHABLE(); 3838 return PropertyDetails::Empty(); 3839 } 3840 3841 template <typename Dictionary> 3842 static inline void DetailsAtPut(Dictionary* dict, int entry, 3843 PropertyDetails value) { 3844 UNREACHABLE(); 3845 } 3846 3847 static inline Map* GetMap(Isolate* isolate); 3848 }; 3849 3850 3851 class SeededNumberDictionary 3852 : public Dictionary<SeededNumberDictionary, 3853 SeededNumberDictionaryShape, 3854 uint32_t> { 3855 public: 3856 DECLARE_CAST(SeededNumberDictionary) 3857 3858 // Type specific at put (default NONE attributes is used when adding). 3859 MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut( 3860 Handle<SeededNumberDictionary> dictionary, uint32_t key, 3861 Handle<Object> value, Handle<JSObject> dictionary_holder); 3862 MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry( 3863 Handle<SeededNumberDictionary> dictionary, uint32_t key, 3864 Handle<Object> value, PropertyDetails details, 3865 Handle<JSObject> dictionary_holder); 3866 3867 // Set an existing entry or add a new one if needed. 3868 // Return the updated dictionary. 3869 MUST_USE_RESULT static Handle<SeededNumberDictionary> Set( 3870 Handle<SeededNumberDictionary> dictionary, uint32_t key, 3871 Handle<Object> value, PropertyDetails details, 3872 Handle<JSObject> dictionary_holder); 3873 3874 void UpdateMaxNumberKey(uint32_t key, Handle<JSObject> dictionary_holder); 3875 3876 // Returns true if the dictionary contains any elements that are non-writable, 3877 // non-configurable, non-enumerable, or have getters/setters. 3878 bool HasComplexElements(); 3879 3880 // If slow elements are required we will never go back to fast-case 3881 // for the elements kept in this dictionary. We require slow 3882 // elements if an element has been added at an index larger than 3883 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called 3884 // when defining a getter or setter with a number key. 3885 inline bool requires_slow_elements(); 3886 inline void set_requires_slow_elements(); 3887 3888 // Get the value of the max number key that has been added to this 3889 // dictionary. max_number_key can only be called if 3890 // requires_slow_elements returns false. 3891 inline uint32_t max_number_key(); 3892 3893 static const int kEntryValueIndex = 1; 3894 static const int kEntryDetailsIndex = 2; 3895 3896 // Bit masks. 3897 static const int kRequiresSlowElementsMask = 1; 3898 static const int kRequiresSlowElementsTagSize = 1; 3899 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1; 3900 }; 3901 3902 3903 class UnseededNumberDictionary 3904 : public Dictionary<UnseededNumberDictionary, 3905 UnseededNumberDictionaryShape, 3906 uint32_t> { 3907 public: 3908 DECLARE_CAST(UnseededNumberDictionary) 3909 3910 // Type specific at put (default NONE attributes is used when adding). 3911 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AtNumberPut( 3912 Handle<UnseededNumberDictionary> dictionary, 3913 uint32_t key, 3914 Handle<Object> value); 3915 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AddNumberEntry( 3916 Handle<UnseededNumberDictionary> dictionary, 3917 uint32_t key, 3918 Handle<Object> value); 3919 static Handle<UnseededNumberDictionary> DeleteKey( 3920 Handle<UnseededNumberDictionary> dictionary, uint32_t key); 3921 3922 // Set an existing entry or add a new one if needed. 3923 // Return the updated dictionary. 3924 MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set( 3925 Handle<UnseededNumberDictionary> dictionary, 3926 uint32_t key, 3927 Handle<Object> value); 3928 3929 static const int kEntryValueIndex = 1; 3930 static const int kEntryDetailsIndex = 2; 3931 }; 3932 3933 3934 class ObjectHashTableShape : public BaseShape<Handle<Object> > { 3935 public: 3936 static inline bool IsMatch(Handle<Object> key, Object* other); 3937 static inline uint32_t Hash(Handle<Object> key); 3938 static inline uint32_t HashForObject(Handle<Object> key, Object* object); 3939 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key); 3940 static const int kPrefixSize = 0; 3941 static const int kEntrySize = 2; 3942 }; 3943 3944 3945 // ObjectHashTable maps keys that are arbitrary objects to object values by 3946 // using the identity hash of the key for hashing purposes. 3947 class ObjectHashTable: public HashTable<ObjectHashTable, 3948 ObjectHashTableShape, 3949 Handle<Object> > { 3950 typedef HashTable< 3951 ObjectHashTable, ObjectHashTableShape, Handle<Object> > DerivedHashTable; 3952 public: 3953 DECLARE_CAST(ObjectHashTable) 3954 3955 // Attempt to shrink hash table after removal of key. 3956 MUST_USE_RESULT static inline Handle<ObjectHashTable> Shrink( 3957 Handle<ObjectHashTable> table, 3958 Handle<Object> key); 3959 3960 // Looks up the value associated with the given key. The hole value is 3961 // returned in case the key is not present. 3962 Object* Lookup(Handle<Object> key); 3963 Object* Lookup(Handle<Object> key, int32_t hash); 3964 Object* Lookup(Isolate* isolate, Handle<Object> key, int32_t hash); 3965 3966 // Returns the value at entry. 3967 Object* ValueAt(int entry); 3968 3969 // Adds (or overwrites) the value associated with the given key. 3970 static Handle<ObjectHashTable> Put(Handle<ObjectHashTable> table, 3971 Handle<Object> key, 3972 Handle<Object> value); 3973 static Handle<ObjectHashTable> Put(Handle<ObjectHashTable> table, 3974 Handle<Object> key, Handle<Object> value, 3975 int32_t hash); 3976 3977 // Returns an ObjectHashTable (possibly |table|) where |key| has been removed. 3978 static Handle<ObjectHashTable> Remove(Handle<ObjectHashTable> table, 3979 Handle<Object> key, 3980 bool* was_present); 3981 static Handle<ObjectHashTable> Remove(Handle<ObjectHashTable> table, 3982 Handle<Object> key, bool* was_present, 3983 int32_t hash); 3984 3985 protected: 3986 friend class MarkCompactCollector; 3987 3988 void AddEntry(int entry, Object* key, Object* value); 3989 void RemoveEntry(int entry); 3990 3991 // Returns the index to the value of an entry. 3992 static inline int EntryToValueIndex(int entry) { 3993 return EntryToIndex(entry) + 1; 3994 } 3995 }; 3996 3997 class ObjectHashSetShape : public ObjectHashTableShape { 3998 public: 3999 static const int kPrefixSize = 0; 4000 static const int kEntrySize = 1; 4001 }; 4002 4003 class ObjectHashSet 4004 : public HashTable<ObjectHashSet, ObjectHashSetShape, Handle<Object>> { 4005 public: 4006 static Handle<ObjectHashSet> Add(Handle<ObjectHashSet> set, 4007 Handle<Object> key); 4008 4009 inline bool Has(Isolate* isolate, Handle<Object> key, int32_t hash); 4010 inline bool Has(Isolate* isolate, Handle<Object> key); 4011 4012 DECLARE_CAST(ObjectHashSet) 4013 }; 4014 4015 // OrderedHashTable is a HashTable with Object keys that preserves 4016 // insertion order. There are Map and Set interfaces (OrderedHashMap 4017 // and OrderedHashTable, below). It is meant to be used by JSMap/JSSet. 4018 // 4019 // Only Object* keys are supported, with Object::SameValueZero() used as the 4020 // equality operator and Object::GetHash() for the hash function. 4021 // 4022 // Based on the "Deterministic Hash Table" as described by Jason Orendorff at 4023 // https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables 4024 // Originally attributed to Tyler Close. 4025 // 4026 // Memory layout: 4027 // [0]: bucket count 4028 // [1]: element count 4029 // [2]: deleted element count 4030 // [3..(3 + NumberOfBuckets() - 1)]: "hash table", where each item is an 4031 // offset into the data table (see below) where the 4032 // first item in this bucket is stored. 4033 // [3 + NumberOfBuckets()..length]: "data table", an array of length 4034 // Capacity() * kEntrySize, where the first entrysize 4035 // items are handled by the derived class and the 4036 // item at kChainOffset is another entry into the 4037 // data table indicating the next entry in this hash 4038 // bucket. 4039 // 4040 // When we transition the table to a new version we obsolete it and reuse parts 4041 // of the memory to store information how to transition an iterator to the new 4042 // table: 4043 // 4044 // Memory layout for obsolete table: 4045 // [0]: bucket count 4046 // [1]: Next newer table 4047 // [2]: Number of removed holes or -1 when the table was cleared. 4048 // [3..(3 + NumberOfRemovedHoles() - 1)]: The indexes of the removed holes. 4049 // [3 + NumberOfRemovedHoles()..length]: Not used 4050 // 4051 template<class Derived, class Iterator, int entrysize> 4052 class OrderedHashTable: public FixedArray { 4053 public: 4054 // Returns an OrderedHashTable with a capacity of at least |capacity|. 4055 static Handle<Derived> Allocate( 4056 Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED); 4057 4058 // Returns an OrderedHashTable (possibly |table|) with enough space 4059 // to add at least one new element. 4060 static Handle<Derived> EnsureGrowable(Handle<Derived> table); 4061 4062 // Returns an OrderedHashTable (possibly |table|) that's shrunken 4063 // if possible. 4064 static Handle<Derived> Shrink(Handle<Derived> table); 4065 4066 // Returns a new empty OrderedHashTable and records the clearing so that 4067 // existing iterators can be updated. 4068 static Handle<Derived> Clear(Handle<Derived> table); 4069 4070 // Returns a true if the OrderedHashTable contains the key 4071 static bool HasKey(Handle<Derived> table, Handle<Object> key); 4072 4073 int NumberOfElements() { 4074 return Smi::cast(get(kNumberOfElementsIndex))->value(); 4075 } 4076 4077 int NumberOfDeletedElements() { 4078 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 4079 } 4080 4081 // Returns the number of contiguous entries in the data table, starting at 0, 4082 // that either are real entries or have been deleted. 4083 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); } 4084 4085 int NumberOfBuckets() { 4086 return Smi::cast(get(kNumberOfBucketsIndex))->value(); 4087 } 4088 4089 // Returns an index into |this| for the given entry. 4090 int EntryToIndex(int entry) { 4091 return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize); 4092 } 4093 4094 int HashToBucket(int hash) { return hash & (NumberOfBuckets() - 1); } 4095 4096 int HashToEntry(int hash) { 4097 int bucket = HashToBucket(hash); 4098 Object* entry = this->get(kHashTableStartIndex + bucket); 4099 return Smi::cast(entry)->value(); 4100 } 4101 4102 int KeyToFirstEntry(Isolate* isolate, Object* key) { 4103 Object* hash = key->GetHash(); 4104 // If the object does not have an identity hash, it was never used as a key 4105 if (hash->IsUndefined(isolate)) return kNotFound; 4106 return HashToEntry(Smi::cast(hash)->value()); 4107 } 4108 4109 int NextChainEntry(int entry) { 4110 Object* next_entry = get(EntryToIndex(entry) + kChainOffset); 4111 return Smi::cast(next_entry)->value(); 4112 } 4113 4114 // use KeyAt(i)->IsTheHole(isolate) to determine if this is a deleted entry. 4115 Object* KeyAt(int entry) { 4116 DCHECK_LT(entry, this->UsedCapacity()); 4117 return get(EntryToIndex(entry)); 4118 } 4119 4120 bool IsObsolete() { 4121 return !get(kNextTableIndex)->IsSmi(); 4122 } 4123 4124 // The next newer table. This is only valid if the table is obsolete. 4125 Derived* NextTable() { 4126 return Derived::cast(get(kNextTableIndex)); 4127 } 4128 4129 // When the table is obsolete we store the indexes of the removed holes. 4130 int RemovedIndexAt(int index) { 4131 return Smi::cast(get(kRemovedHolesIndex + index))->value(); 4132 } 4133 4134 static const int kNotFound = -1; 4135 static const int kMinCapacity = 4; 4136 4137 static const int kNumberOfElementsIndex = 0; 4138 // The next table is stored at the same index as the nof elements. 4139 static const int kNextTableIndex = kNumberOfElementsIndex; 4140 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; 4141 static const int kNumberOfBucketsIndex = kNumberOfDeletedElementsIndex + 1; 4142 static const int kHashTableStartIndex = kNumberOfBucketsIndex + 1; 4143 4144 static constexpr const int kNumberOfElementsOffset = 4145 FixedArray::OffsetOfElementAt(kNumberOfElementsIndex); 4146 static constexpr const int kNextTableOffset = 4147 FixedArray::OffsetOfElementAt(kNextTableIndex); 4148 static constexpr const int kNumberOfDeletedElementsOffset = 4149 FixedArray::OffsetOfElementAt(kNumberOfDeletedElementsIndex); 4150 static constexpr const int kNumberOfBucketsOffset = 4151 FixedArray::OffsetOfElementAt(kNumberOfBucketsIndex); 4152 static constexpr const int kHashTableStartOffset = 4153 FixedArray::OffsetOfElementAt(kHashTableStartIndex); 4154 4155 static const int kEntrySize = entrysize + 1; 4156 static const int kChainOffset = entrysize; 4157 4158 static const int kLoadFactor = 2; 4159 4160 // NumberOfDeletedElements is set to kClearedTableSentinel when 4161 // the table is cleared, which allows iterator transitions to 4162 // optimize that case. 4163 static const int kClearedTableSentinel = -1; 4164 4165 protected: 4166 static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity); 4167 4168 void SetNumberOfBuckets(int num) { 4169 set(kNumberOfBucketsIndex, Smi::FromInt(num)); 4170 } 4171 4172 void SetNumberOfElements(int num) { 4173 set(kNumberOfElementsIndex, Smi::FromInt(num)); 4174 } 4175 4176 void SetNumberOfDeletedElements(int num) { 4177 set(kNumberOfDeletedElementsIndex, Smi::FromInt(num)); 4178 } 4179 4180 // Returns the number elements that can fit into the allocated buffer. 4181 int Capacity() { 4182 return NumberOfBuckets() * kLoadFactor; 4183 } 4184 4185 void SetNextTable(Derived* next_table) { 4186 set(kNextTableIndex, next_table); 4187 } 4188 4189 void SetRemovedIndexAt(int index, int removed_index) { 4190 return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index)); 4191 } 4192 4193 static const int kRemovedHolesIndex = kHashTableStartIndex; 4194 4195 static const int kMaxCapacity = 4196 (FixedArray::kMaxLength - kHashTableStartIndex) 4197 / (1 + (kEntrySize * kLoadFactor)); 4198 }; 4199 4200 4201 class JSSetIterator; 4202 4203 4204 class OrderedHashSet: public OrderedHashTable< 4205 OrderedHashSet, JSSetIterator, 1> { 4206 public: 4207 DECLARE_CAST(OrderedHashSet) 4208 4209 static Handle<OrderedHashSet> Add(Handle<OrderedHashSet> table, 4210 Handle<Object> value); 4211 static Handle<FixedArray> ConvertToKeysArray(Handle<OrderedHashSet> table, 4212 GetKeysConversion convert); 4213 }; 4214 4215 4216 class JSMapIterator; 4217 4218 4219 class OrderedHashMap 4220 : public OrderedHashTable<OrderedHashMap, JSMapIterator, 2> { 4221 public: 4222 DECLARE_CAST(OrderedHashMap) 4223 4224 inline Object* ValueAt(int entry); 4225 4226 static const int kValueOffset = 1; 4227 }; 4228 4229 4230 template <int entrysize> 4231 class WeakHashTableShape : public BaseShape<Handle<Object> > { 4232 public: 4233 static inline bool IsMatch(Handle<Object> key, Object* other); 4234 static inline uint32_t Hash(Handle<Object> key); 4235 static inline uint32_t HashForObject(Handle<Object> key, Object* object); 4236 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key); 4237 static const int kPrefixSize = 0; 4238 static const int kEntrySize = entrysize; 4239 }; 4240 4241 4242 // WeakHashTable maps keys that are arbitrary heap objects to heap object 4243 // values. The table wraps the keys in weak cells and store values directly. 4244 // Thus it references keys weakly and values strongly. 4245 class WeakHashTable: public HashTable<WeakHashTable, 4246 WeakHashTableShape<2>, 4247 Handle<Object> > { 4248 typedef HashTable< 4249 WeakHashTable, WeakHashTableShape<2>, Handle<Object> > DerivedHashTable; 4250 public: 4251 DECLARE_CAST(WeakHashTable) 4252 4253 // Looks up the value associated with the given key. The hole value is 4254 // returned in case the key is not present. 4255 Object* Lookup(Handle<HeapObject> key); 4256 4257 // Adds (or overwrites) the value associated with the given key. Mapping a 4258 // key to the hole value causes removal of the whole entry. 4259 MUST_USE_RESULT static Handle<WeakHashTable> Put(Handle<WeakHashTable> table, 4260 Handle<HeapObject> key, 4261 Handle<HeapObject> value); 4262 4263 static Handle<FixedArray> GetValues(Handle<WeakHashTable> table); 4264 4265 private: 4266 friend class MarkCompactCollector; 4267 4268 void AddEntry(int entry, Handle<WeakCell> key, Handle<HeapObject> value); 4269 4270 // Returns the index to the value of an entry. 4271 static inline int EntryToValueIndex(int entry) { 4272 return EntryToIndex(entry) + 1; 4273 } 4274 }; 4275 4276 4277 // The cache for maps used by normalized (dictionary mode) objects. 4278 // Such maps do not have property descriptors, so a typical program 4279 // needs very limited number of distinct normalized maps. 4280 class NormalizedMapCache: public FixedArray { 4281 public: 4282 static Handle<NormalizedMapCache> New(Isolate* isolate); 4283 4284 MUST_USE_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map, 4285 PropertyNormalizationMode mode); 4286 void Set(Handle<Map> fast_map, Handle<Map> normalized_map); 4287 4288 void Clear(); 4289 4290 DECLARE_CAST(NormalizedMapCache) 4291 4292 static inline bool IsNormalizedMapCache(const HeapObject* obj); 4293 4294 DECLARE_VERIFIER(NormalizedMapCache) 4295 private: 4296 static const int kEntries = 64; 4297 4298 static inline int GetIndex(Handle<Map> map); 4299 4300 // The following declarations hide base class methods. 4301 Object* get(int index); 4302 void set(int index, Object* value); 4303 }; 4304 4305 // HandlerTable is a fixed array containing entries for exception handlers in 4306 // the code object it is associated with. The tables comes in two flavors: 4307 // 1) Based on ranges: Used for unoptimized code. Contains one entry per 4308 // exception handler and a range representing the try-block covered by that 4309 // handler. Layout looks as follows: 4310 // [ range-start , range-end , handler-offset , handler-data ] 4311 // 2) Based on return addresses: Used for turbofanned code. Contains one entry 4312 // per call-site that could throw an exception. Layout looks as follows: 4313 // [ return-address-offset , handler-offset ] 4314 class HandlerTable : public FixedArray { 4315 public: 4316 // Conservative prediction whether a given handler will locally catch an 4317 // exception or cause a re-throw to outside the code boundary. Since this is 4318 // undecidable it is merely an approximation (e.g. useful for debugger). 4319 enum CatchPrediction { 4320 UNCAUGHT, // The handler will (likely) rethrow the exception. 4321 CAUGHT, // The exception will be caught by the handler. 4322 PROMISE, // The exception will be caught and cause a promise rejection. 4323 DESUGARING, // The exception will be caught, but both the exception and the 4324 // catching are part of a desugaring and should therefore not 4325 // be visible to the user (we won't notify the debugger of such 4326 // exceptions). 4327 ASYNC_AWAIT, // The exception will be caught and cause a promise rejection 4328 // in the desugaring of an async function, so special 4329 // async/await handling in the debugger can take place. 4330 }; 4331 4332 // Getters for handler table based on ranges. 4333 inline int GetRangeStart(int index) const; 4334 inline int GetRangeEnd(int index) const; 4335 inline int GetRangeHandler(int index) const; 4336 inline int GetRangeData(int index) const; 4337 4338 // Setters for handler table based on ranges. 4339 inline void SetRangeStart(int index, int value); 4340 inline void SetRangeEnd(int index, int value); 4341 inline void SetRangeHandler(int index, int offset, CatchPrediction pred); 4342 inline void SetRangeData(int index, int value); 4343 4344 // Setters for handler table based on return addresses. 4345 inline void SetReturnOffset(int index, int value); 4346 inline void SetReturnHandler(int index, int offset); 4347 4348 // Lookup handler in a table based on ranges. The {pc_offset} is an offset to 4349 // the start of the potentially throwing instruction (using return addresses 4350 // for this value would be invalid). 4351 int LookupRange(int pc_offset, int* data, CatchPrediction* prediction); 4352 4353 // Lookup handler in a table based on return addresses. 4354 int LookupReturn(int pc_offset); 4355 4356 // Returns the number of entries in the table. 4357 inline int NumberOfRangeEntries() const; 4358 4359 // Returns the required length of the underlying fixed array. 4360 static int LengthForRange(int entries) { return entries * kRangeEntrySize; } 4361 static int LengthForReturn(int entries) { return entries * kReturnEntrySize; } 4362 4363 DECLARE_CAST(HandlerTable) 4364 4365 #ifdef ENABLE_DISASSEMBLER 4366 void HandlerTableRangePrint(std::ostream& os); // NOLINT 4367 void HandlerTableReturnPrint(std::ostream& os); // NOLINT 4368 #endif 4369 4370 private: 4371 // Layout description for handler table based on ranges. 4372 static const int kRangeStartIndex = 0; 4373 static const int kRangeEndIndex = 1; 4374 static const int kRangeHandlerIndex = 2; 4375 static const int kRangeDataIndex = 3; 4376 static const int kRangeEntrySize = 4; 4377 4378 // Layout description for handler table based on return addresses. 4379 static const int kReturnOffsetIndex = 0; 4380 static const int kReturnHandlerIndex = 1; 4381 static const int kReturnEntrySize = 2; 4382 4383 // Encoding of the {handler} field. 4384 class HandlerPredictionField : public BitField<CatchPrediction, 0, 3> {}; 4385 class HandlerOffsetField : public BitField<int, 3, 29> {}; 4386 }; 4387 4388 // ByteArray represents fixed sized byte arrays. Used for the relocation info 4389 // that is attached to code objects. 4390 class ByteArray: public FixedArrayBase { 4391 public: 4392 inline int Size(); 4393 4394 // Setter and getter. 4395 inline byte get(int index); 4396 inline void set(int index, byte value); 4397 4398 // Copy in / copy out whole byte slices. 4399 inline void copy_out(int index, byte* buffer, int length); 4400 inline void copy_in(int index, const byte* buffer, int length); 4401 4402 // Treat contents as an int array. 4403 inline int get_int(int index); 4404 inline void set_int(int index, int value); 4405 4406 static int SizeFor(int length) { 4407 return OBJECT_POINTER_ALIGN(kHeaderSize + length); 4408 } 4409 // We use byte arrays for free blocks in the heap. Given a desired size in 4410 // bytes that is a multiple of the word size and big enough to hold a byte 4411 // array, this function returns the number of elements a byte array should 4412 // have. 4413 static int LengthFor(int size_in_bytes) { 4414 DCHECK(IsAligned(size_in_bytes, kPointerSize)); 4415 DCHECK(size_in_bytes >= kHeaderSize); 4416 return size_in_bytes - kHeaderSize; 4417 } 4418 4419 // Returns data start address. 4420 inline Address GetDataStartAddress(); 4421 4422 // Returns a pointer to the ByteArray object for a given data start address. 4423 static inline ByteArray* FromDataStartAddress(Address address); 4424 4425 DECLARE_CAST(ByteArray) 4426 4427 // Dispatched behavior. 4428 inline int ByteArraySize(); 4429 DECLARE_PRINTER(ByteArray) 4430 DECLARE_VERIFIER(ByteArray) 4431 4432 // Layout description. 4433 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize); 4434 4435 // Maximal memory consumption for a single ByteArray. 4436 static const int kMaxSize = 512 * MB; 4437 // Maximal length of a single ByteArray. 4438 static const int kMaxLength = kMaxSize - kHeaderSize; 4439 4440 private: 4441 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray); 4442 }; 4443 4444 // Wrapper class for ByteArray which can store arbitrary C++ classes, as long 4445 // as they can be copied with memcpy. 4446 template <class T> 4447 class PodArray : public ByteArray { 4448 public: 4449 static Handle<PodArray<T>> New(Isolate* isolate, int length, 4450 PretenureFlag pretenure = NOT_TENURED); 4451 void copy_out(int index, T* result) { 4452 ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result), 4453 sizeof(T)); 4454 } 4455 T get(int index) { 4456 T result; 4457 copy_out(index, &result); 4458 return result; 4459 } 4460 void set(int index, const T& value) { 4461 copy_in(index * sizeof(T), reinterpret_cast<const byte*>(&value), 4462 sizeof(T)); 4463 } 4464 int length() { return ByteArray::length() / sizeof(T); } 4465 DECLARE_CAST(PodArray<T>) 4466 4467 private: 4468 DISALLOW_IMPLICIT_CONSTRUCTORS(PodArray<T>); 4469 }; 4470 4471 // BytecodeArray represents a sequence of interpreter bytecodes. 4472 class BytecodeArray : public FixedArrayBase { 4473 public: 4474 #define DECLARE_BYTECODE_AGE_ENUM(X) k##X##BytecodeAge, 4475 enum Age { 4476 kNoAgeBytecodeAge = 0, 4477 CODE_AGE_LIST(DECLARE_BYTECODE_AGE_ENUM) kAfterLastBytecodeAge, 4478 kFirstBytecodeAge = kNoAgeBytecodeAge, 4479 kLastBytecodeAge = kAfterLastBytecodeAge - 1, 4480 kBytecodeAgeCount = kAfterLastBytecodeAge - kFirstBytecodeAge - 1, 4481 kIsOldBytecodeAge = kSexagenarianBytecodeAge 4482 }; 4483 #undef DECLARE_BYTECODE_AGE_ENUM 4484 4485 static int SizeFor(int length) { 4486 return OBJECT_POINTER_ALIGN(kHeaderSize + length); 4487 } 4488 4489 // Setter and getter 4490 inline byte get(int index); 4491 inline void set(int index, byte value); 4492 4493 // Returns data start address. 4494 inline Address GetFirstBytecodeAddress(); 4495 4496 // Accessors for frame size. 4497 inline int frame_size() const; 4498 inline void set_frame_size(int frame_size); 4499 4500 // Accessor for register count (derived from frame_size). 4501 inline int register_count() const; 4502 4503 // Accessors for parameter count (including implicit 'this' receiver). 4504 inline int parameter_count() const; 4505 inline void set_parameter_count(int number_of_parameters); 4506 4507 // Accessors for profiling count. 4508 inline int interrupt_budget() const; 4509 inline void set_interrupt_budget(int interrupt_budget); 4510 4511 // Accessors for OSR loop nesting level. 4512 inline int osr_loop_nesting_level() const; 4513 inline void set_osr_loop_nesting_level(int depth); 4514 4515 // Accessors for bytecode's code age. 4516 inline Age bytecode_age() const; 4517 inline void set_bytecode_age(Age age); 4518 4519 // Accessors for the constant pool. 4520 DECL_ACCESSORS(constant_pool, FixedArray) 4521 4522 // Accessors for handler table containing offsets of exception handlers. 4523 DECL_ACCESSORS(handler_table, FixedArray) 4524 4525 // Accessors for source position table containing mappings between byte code 4526 // offset and source position. 4527 DECL_ACCESSORS(source_position_table, ByteArray) 4528 4529 DECLARE_CAST(BytecodeArray) 4530 4531 // Dispatched behavior. 4532 inline int BytecodeArraySize(); 4533 4534 inline int instruction_size(); 4535 4536 // Returns the size of bytecode and its metadata. This includes the size of 4537 // bytecode, constant pool, source position table, and handler table. 4538 inline int SizeIncludingMetadata(); 4539 4540 int SourcePosition(int offset); 4541 int SourceStatementPosition(int offset); 4542 4543 DECLARE_PRINTER(BytecodeArray) 4544 DECLARE_VERIFIER(BytecodeArray) 4545 4546 void Disassemble(std::ostream& os); 4547 4548 void CopyBytecodesTo(BytecodeArray* to); 4549 4550 // Bytecode aging 4551 bool IsOld() const; 4552 void MakeOlder(); 4553 4554 // Layout description. 4555 static const int kConstantPoolOffset = FixedArrayBase::kHeaderSize; 4556 static const int kHandlerTableOffset = kConstantPoolOffset + kPointerSize; 4557 static const int kSourcePositionTableOffset = 4558 kHandlerTableOffset + kPointerSize; 4559 static const int kFrameSizeOffset = kSourcePositionTableOffset + kPointerSize; 4560 static const int kParameterSizeOffset = kFrameSizeOffset + kIntSize; 4561 static const int kInterruptBudgetOffset = kParameterSizeOffset + kIntSize; 4562 static const int kOSRNestingLevelOffset = kInterruptBudgetOffset + kIntSize; 4563 static const int kBytecodeAgeOffset = kOSRNestingLevelOffset + kCharSize; 4564 static const int kHeaderSize = kBytecodeAgeOffset + kCharSize; 4565 4566 // Maximal memory consumption for a single BytecodeArray. 4567 static const int kMaxSize = 512 * MB; 4568 // Maximal length of a single BytecodeArray. 4569 static const int kMaxLength = kMaxSize - kHeaderSize; 4570 4571 static const int kPointerFieldsBeginOffset = kConstantPoolOffset; 4572 static const int kPointerFieldsEndOffset = kFrameSizeOffset; 4573 4574 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset, 4575 kPointerFieldsEndOffset, kHeaderSize> 4576 MarkingBodyDescriptor; 4577 4578 class BodyDescriptor; 4579 4580 private: 4581 DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArray); 4582 }; 4583 4584 4585 // FreeSpace are fixed-size free memory blocks used by the heap and GC. 4586 // They look like heap objects (are heap object tagged and have a map) so that 4587 // the heap remains iterable. They have a size and a next pointer. 4588 // The next pointer is the raw address of the next FreeSpace object (or NULL) 4589 // in the free list. 4590 class FreeSpace: public HeapObject { 4591 public: 4592 // [size]: size of the free space including the header. 4593 inline int size() const; 4594 inline void set_size(int value); 4595 4596 inline int nobarrier_size() const; 4597 inline void nobarrier_set_size(int value); 4598 4599 inline int Size(); 4600 4601 // Accessors for the next field. 4602 inline FreeSpace* next(); 4603 inline void set_next(FreeSpace* next); 4604 4605 inline static FreeSpace* cast(HeapObject* obj); 4606 4607 // Dispatched behavior. 4608 DECLARE_PRINTER(FreeSpace) 4609 DECLARE_VERIFIER(FreeSpace) 4610 4611 // Layout description. 4612 // Size is smi tagged when it is stored. 4613 static const int kSizeOffset = HeapObject::kHeaderSize; 4614 static const int kNextOffset = POINTER_SIZE_ALIGN(kSizeOffset + kPointerSize); 4615 static const int kSize = kNextOffset + kPointerSize; 4616 4617 private: 4618 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace); 4619 }; 4620 4621 4622 // V has parameters (Type, type, TYPE, C type, element_size) 4623 #define TYPED_ARRAYS(V) \ 4624 V(Uint8, uint8, UINT8, uint8_t, 1) \ 4625 V(Int8, int8, INT8, int8_t, 1) \ 4626 V(Uint16, uint16, UINT16, uint16_t, 2) \ 4627 V(Int16, int16, INT16, int16_t, 2) \ 4628 V(Uint32, uint32, UINT32, uint32_t, 4) \ 4629 V(Int32, int32, INT32, int32_t, 4) \ 4630 V(Float32, float32, FLOAT32, float, 4) \ 4631 V(Float64, float64, FLOAT64, double, 8) \ 4632 V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1) 4633 4634 4635 class FixedTypedArrayBase: public FixedArrayBase { 4636 public: 4637 // [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr. 4638 DECL_ACCESSORS(base_pointer, Object) 4639 4640 // [external_pointer]: Contains the offset between base_pointer and the start 4641 // of the data. If the base_pointer is a nullptr, the external_pointer 4642 // therefore points to the actual backing store. 4643 DECL_ACCESSORS(external_pointer, void) 4644 4645 // Dispatched behavior. 4646 DECLARE_CAST(FixedTypedArrayBase) 4647 4648 static const int kBasePointerOffset = FixedArrayBase::kHeaderSize; 4649 static const int kExternalPointerOffset = kBasePointerOffset + kPointerSize; 4650 static const int kHeaderSize = 4651 DOUBLE_POINTER_ALIGN(kExternalPointerOffset + kPointerSize); 4652 4653 static const int kDataOffset = kHeaderSize; 4654 4655 class BodyDescriptor; 4656 4657 inline int size(); 4658 4659 static inline int TypedArraySize(InstanceType type, int length); 4660 inline int TypedArraySize(InstanceType type); 4661 4662 // Use with care: returns raw pointer into heap. 4663 inline void* DataPtr(); 4664 4665 inline int DataSize(); 4666 4667 private: 4668 static inline int ElementSize(InstanceType type); 4669 4670 inline int DataSize(InstanceType type); 4671 4672 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase); 4673 }; 4674 4675 4676 template <class Traits> 4677 class FixedTypedArray: public FixedTypedArrayBase { 4678 public: 4679 typedef typename Traits::ElementType ElementType; 4680 static const InstanceType kInstanceType = Traits::kInstanceType; 4681 4682 DECLARE_CAST(FixedTypedArray<Traits>) 4683 4684 inline ElementType get_scalar(int index); 4685 static inline Handle<Object> get(FixedTypedArray* array, int index); 4686 inline void set(int index, ElementType value); 4687 4688 static inline ElementType from_int(int value); 4689 static inline ElementType from_double(double value); 4690 4691 // This accessor applies the correct conversion from Smi, HeapNumber 4692 // and undefined. 4693 inline void SetValue(uint32_t index, Object* value); 4694 4695 DECLARE_PRINTER(FixedTypedArray) 4696 DECLARE_VERIFIER(FixedTypedArray) 4697 4698 private: 4699 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray); 4700 }; 4701 4702 #define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType, size) \ 4703 class Type##ArrayTraits { \ 4704 public: /* NOLINT */ \ 4705 typedef elementType ElementType; \ 4706 static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \ 4707 static const char* Designator() { return #type " array"; } \ 4708 static inline Handle<Object> ToHandle(Isolate* isolate, \ 4709 elementType scalar); \ 4710 static inline elementType defaultValue(); \ 4711 }; \ 4712 \ 4713 typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array; 4714 4715 TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS) 4716 4717 #undef FIXED_TYPED_ARRAY_TRAITS 4718 4719 // DeoptimizationInputData is a fixed array used to hold the deoptimization 4720 // data for code generated by the Hydrogen/Lithium compiler. It also 4721 // contains information about functions that were inlined. If N different 4722 // functions were inlined then first N elements of the literal array will 4723 // contain these functions. 4724 // 4725 // It can be empty. 4726 class DeoptimizationInputData: public FixedArray { 4727 public: 4728 // Layout description. Indices in the array. 4729 static const int kTranslationByteArrayIndex = 0; 4730 static const int kInlinedFunctionCountIndex = 1; 4731 static const int kLiteralArrayIndex = 2; 4732 static const int kOsrAstIdIndex = 3; 4733 static const int kOsrPcOffsetIndex = 4; 4734 static const int kOptimizationIdIndex = 5; 4735 static const int kSharedFunctionInfoIndex = 6; 4736 static const int kWeakCellCacheIndex = 7; 4737 static const int kInliningPositionsIndex = 8; 4738 static const int kFirstDeoptEntryIndex = 9; 4739 4740 // Offsets of deopt entry elements relative to the start of the entry. 4741 static const int kAstIdRawOffset = 0; 4742 static const int kTranslationIndexOffset = 1; 4743 static const int kArgumentsStackHeightOffset = 2; 4744 static const int kPcOffset = 3; 4745 static const int kDeoptEntrySize = 4; 4746 4747 // Simple element accessors. 4748 #define DECLARE_ELEMENT_ACCESSORS(name, type) \ 4749 inline type* name(); \ 4750 inline void Set##name(type* value); 4751 4752 DECLARE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray) 4753 DECLARE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) 4754 DECLARE_ELEMENT_ACCESSORS(LiteralArray, FixedArray) 4755 DECLARE_ELEMENT_ACCESSORS(OsrAstId, Smi) 4756 DECLARE_ELEMENT_ACCESSORS(OsrPcOffset, Smi) 4757 DECLARE_ELEMENT_ACCESSORS(OptimizationId, Smi) 4758 DECLARE_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) 4759 DECLARE_ELEMENT_ACCESSORS(WeakCellCache, Object) 4760 DECLARE_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>) 4761 4762 #undef DECLARE_ELEMENT_ACCESSORS 4763 4764 // Accessors for elements of the ith deoptimization entry. 4765 #define DECLARE_ENTRY_ACCESSORS(name, type) \ 4766 inline type* name(int i); \ 4767 inline void Set##name(int i, type* value); 4768 4769 DECLARE_ENTRY_ACCESSORS(AstIdRaw, Smi) 4770 DECLARE_ENTRY_ACCESSORS(TranslationIndex, Smi) 4771 DECLARE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi) 4772 DECLARE_ENTRY_ACCESSORS(Pc, Smi) 4773 4774 #undef DECLARE_ENTRY_ACCESSORS 4775 4776 inline BailoutId AstId(int i); 4777 4778 inline void SetAstId(int i, BailoutId value); 4779 4780 inline int DeoptCount(); 4781 4782 static const int kNotInlinedIndex = -1; 4783 4784 // Returns the inlined function at the given position in LiteralArray, or the 4785 // outer function if index == kNotInlinedIndex. 4786 class SharedFunctionInfo* GetInlinedFunction(int index); 4787 4788 // Allocates a DeoptimizationInputData. 4789 static Handle<DeoptimizationInputData> New(Isolate* isolate, 4790 int deopt_entry_count, 4791 PretenureFlag pretenure); 4792 4793 DECLARE_CAST(DeoptimizationInputData) 4794 4795 #ifdef ENABLE_DISASSEMBLER 4796 void DeoptimizationInputDataPrint(std::ostream& os); // NOLINT 4797 #endif 4798 4799 private: 4800 static int IndexForEntry(int i) { 4801 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize); 4802 } 4803 4804 4805 static int LengthFor(int entry_count) { return IndexForEntry(entry_count); } 4806 }; 4807 4808 // DeoptimizationOutputData is a fixed array used to hold the deoptimization 4809 // data for code generated by the full compiler. 4810 // The format of the these objects is 4811 // [i * 2]: Ast ID for ith deoptimization. 4812 // [i * 2 + 1]: PC and state of ith deoptimization 4813 class DeoptimizationOutputData: public FixedArray { 4814 public: 4815 inline int DeoptPoints(); 4816 4817 inline BailoutId AstId(int index); 4818 4819 inline void SetAstId(int index, BailoutId id); 4820 4821 inline Smi* PcAndState(int index); 4822 inline void SetPcAndState(int index, Smi* offset); 4823 4824 static int LengthOfFixedArray(int deopt_points) { 4825 return deopt_points * 2; 4826 } 4827 4828 // Allocates a DeoptimizationOutputData. 4829 static Handle<DeoptimizationOutputData> New(Isolate* isolate, 4830 int number_of_deopt_points, 4831 PretenureFlag pretenure); 4832 4833 DECLARE_CAST(DeoptimizationOutputData) 4834 4835 #ifdef ENABLE_DISASSEMBLER 4836 void DeoptimizationOutputDataPrint(std::ostream& os); // NOLINT 4837 #endif 4838 }; 4839 4840 class TemplateList : public FixedArray { 4841 public: 4842 static Handle<TemplateList> New(Isolate* isolate, int size); 4843 inline int length() const; 4844 inline Object* get(int index) const; 4845 inline void set(int index, Object* value); 4846 static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list, 4847 Handle<Object> value); 4848 DECLARE_CAST(TemplateList) 4849 private: 4850 static const int kLengthIndex = 0; 4851 static const int kFirstElementIndex = kLengthIndex + 1; 4852 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateList); 4853 }; 4854 4855 // Code describes objects with on-the-fly generated machine code. 4856 class Code: public HeapObject { 4857 public: 4858 // Opaque data type for encapsulating code flags like kind, inline 4859 // cache state, and arguments count. 4860 typedef uint32_t Flags; 4861 4862 #define NON_IC_KIND_LIST(V) \ 4863 V(FUNCTION) \ 4864 V(OPTIMIZED_FUNCTION) \ 4865 V(BYTECODE_HANDLER) \ 4866 V(STUB) \ 4867 V(HANDLER) \ 4868 V(BUILTIN) \ 4869 V(REGEXP) \ 4870 V(WASM_FUNCTION) \ 4871 V(WASM_TO_JS_FUNCTION) \ 4872 V(JS_TO_WASM_FUNCTION) \ 4873 V(WASM_INTERPRETER_ENTRY) 4874 4875 #define IC_KIND_LIST(V) \ 4876 V(LOAD_IC) \ 4877 V(LOAD_GLOBAL_IC) \ 4878 V(KEYED_LOAD_IC) \ 4879 V(STORE_IC) \ 4880 V(KEYED_STORE_IC) \ 4881 V(BINARY_OP_IC) \ 4882 V(COMPARE_IC) \ 4883 V(TO_BOOLEAN_IC) 4884 4885 #define CODE_KIND_LIST(V) \ 4886 NON_IC_KIND_LIST(V) \ 4887 IC_KIND_LIST(V) 4888 4889 enum Kind { 4890 #define DEFINE_CODE_KIND_ENUM(name) name, 4891 CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM) 4892 #undef DEFINE_CODE_KIND_ENUM 4893 NUMBER_OF_KINDS 4894 }; 4895 4896 static const char* Kind2String(Kind kind); 4897 4898 static const int kPrologueOffsetNotSet = -1; 4899 4900 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 4901 // Printing 4902 static const char* ICState2String(InlineCacheState state); 4903 static void PrintExtraICState(std::ostream& os, // NOLINT 4904 Kind kind, ExtraICState extra); 4905 #endif // defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 4906 4907 #ifdef ENABLE_DISASSEMBLER 4908 void Disassemble(const char* name, std::ostream& os); // NOLINT 4909 #endif // ENABLE_DISASSEMBLER 4910 4911 // [instruction_size]: Size of the native instructions 4912 inline int instruction_size() const; 4913 inline void set_instruction_size(int value); 4914 4915 // [relocation_info]: Code relocation information 4916 DECL_ACCESSORS(relocation_info, ByteArray) 4917 void InvalidateRelocation(); 4918 void InvalidateEmbeddedObjects(); 4919 4920 // [handler_table]: Fixed array containing offsets of exception handlers. 4921 DECL_ACCESSORS(handler_table, FixedArray) 4922 4923 // [deoptimization_data]: Array containing data for deopt. 4924 DECL_ACCESSORS(deoptimization_data, FixedArray) 4925 4926 // [source_position_table]: ByteArray for the source positions table. 4927 DECL_ACCESSORS(source_position_table, ByteArray) 4928 4929 // [raw_type_feedback_info]: This field stores various things, depending on 4930 // the kind of the code object. 4931 // FUNCTION => type feedback information. 4932 // STUB and ICs => major/minor key as Smi. 4933 DECL_ACCESSORS(raw_type_feedback_info, Object) 4934 inline Object* type_feedback_info(); 4935 inline void set_type_feedback_info( 4936 Object* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 4937 inline uint32_t stub_key(); 4938 inline void set_stub_key(uint32_t key); 4939 4940 // [next_code_link]: Link for lists of optimized or deoptimized code. 4941 // Note that storage for this field is overlapped with typefeedback_info. 4942 DECL_ACCESSORS(next_code_link, Object) 4943 4944 // [gc_metadata]: Field used to hold GC related metadata. The contents of this 4945 // field does not have to be traced during garbage collection since 4946 // it is only used by the garbage collector itself. 4947 DECL_ACCESSORS(gc_metadata, Object) 4948 4949 // [ic_age]: Inline caching age: the value of the Heap::global_ic_age 4950 // at the moment when this object was created. 4951 inline void set_ic_age(int count); 4952 inline int ic_age() const; 4953 4954 // [prologue_offset]: Offset of the function prologue, used for aging 4955 // FUNCTIONs and OPTIMIZED_FUNCTIONs. 4956 inline int prologue_offset() const; 4957 inline void set_prologue_offset(int offset); 4958 4959 // [constant_pool offset]: Offset of the constant pool. 4960 // Valid for FLAG_enable_embedded_constant_pool only 4961 inline int constant_pool_offset() const; 4962 inline void set_constant_pool_offset(int offset); 4963 4964 // Unchecked accessors to be used during GC. 4965 inline ByteArray* unchecked_relocation_info(); 4966 4967 inline int relocation_size(); 4968 4969 // [flags]: Various code flags. 4970 inline Flags flags(); 4971 inline void set_flags(Flags flags); 4972 4973 // [flags]: Access to specific code flags. 4974 inline Kind kind(); 4975 inline ExtraICState extra_ic_state(); // Only valid for IC stubs. 4976 4977 // Testers for IC stub kinds. 4978 inline bool is_inline_cache_stub(); 4979 inline bool is_debug_stub(); 4980 inline bool is_handler(); 4981 inline bool is_stub(); 4982 inline bool is_binary_op_stub(); 4983 inline bool is_compare_ic_stub(); 4984 inline bool is_to_boolean_ic_stub(); 4985 inline bool is_optimized_code(); 4986 inline bool is_wasm_code(); 4987 4988 inline bool IsCodeStubOrIC(); 4989 4990 inline void set_raw_kind_specific_flags1(int value); 4991 inline void set_raw_kind_specific_flags2(int value); 4992 4993 // Testers for interpreter builtins. 4994 inline bool is_interpreter_trampoline_builtin(); 4995 4996 // [is_crankshafted]: For kind STUB or ICs, tells whether or not a code 4997 // object was generated by either the hydrogen or the TurboFan optimizing 4998 // compiler (but it may not be an optimized function). 4999 inline bool is_crankshafted(); 5000 inline bool is_hydrogen_stub(); // Crankshafted, but not a function. 5001 inline void set_is_crankshafted(bool value); 5002 5003 // [is_turbofanned]: For kind STUB or OPTIMIZED_FUNCTION, tells whether the 5004 // code object was generated by the TurboFan optimizing compiler. 5005 inline bool is_turbofanned(); 5006 inline void set_is_turbofanned(bool value); 5007 5008 // [can_have_weak_objects]: For kind OPTIMIZED_FUNCTION, tells whether the 5009 // embedded objects in code should be treated weakly. 5010 inline bool can_have_weak_objects(); 5011 inline void set_can_have_weak_objects(bool value); 5012 5013 // [is_construct_stub]: For kind BUILTIN, tells whether the code object 5014 // represents a hand-written construct stub 5015 // (e.g., NumberConstructor_ConstructStub). 5016 inline bool is_construct_stub(); 5017 inline void set_is_construct_stub(bool value); 5018 5019 // [has_deoptimization_support]: For FUNCTION kind, tells if it has 5020 // deoptimization support. 5021 inline bool has_deoptimization_support(); 5022 inline void set_has_deoptimization_support(bool value); 5023 5024 // [has_debug_break_slots]: For FUNCTION kind, tells if it has 5025 // been compiled with debug break slots. 5026 inline bool has_debug_break_slots(); 5027 inline void set_has_debug_break_slots(bool value); 5028 5029 // [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its 5030 // reloc info includes runtime and external references to support 5031 // serialization/deserialization. 5032 inline bool has_reloc_info_for_serialization(); 5033 inline void set_has_reloc_info_for_serialization(bool value); 5034 5035 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for 5036 // how long the function has been marked for OSR and therefore which 5037 // level of loop nesting we are willing to do on-stack replacement 5038 // for. 5039 inline void set_allow_osr_at_loop_nesting_level(int level); 5040 inline int allow_osr_at_loop_nesting_level(); 5041 5042 // [profiler_ticks]: For FUNCTION kind, tells for how many profiler ticks 5043 // the code object was seen on the stack with no IC patching going on. 5044 inline int profiler_ticks(); 5045 inline void set_profiler_ticks(int ticks); 5046 5047 // [builtin_index]: For builtins, tells which builtin index the code object 5048 // has. Note that builtins can have a code kind other than BUILTIN. The 5049 // builtin index is a non-negative integer for builtins, and -1 otherwise. 5050 inline int builtin_index(); 5051 inline void set_builtin_index(int id); 5052 5053 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots 5054 // reserved in the code prologue. 5055 inline unsigned stack_slots(); 5056 inline void set_stack_slots(unsigned slots); 5057 5058 // [safepoint_table_start]: For kind OPTIMIZED_FUNCTION, the offset in 5059 // the instruction stream where the safepoint table starts. 5060 inline unsigned safepoint_table_offset(); 5061 inline void set_safepoint_table_offset(unsigned offset); 5062 5063 // [back_edge_table_start]: For kind FUNCTION, the offset in the 5064 // instruction stream where the back edge table starts. 5065 inline unsigned back_edge_table_offset(); 5066 inline void set_back_edge_table_offset(unsigned offset); 5067 5068 inline bool back_edges_patched_for_osr(); 5069 5070 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in. 5071 inline uint16_t to_boolean_state(); 5072 5073 // [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether 5074 // the code is going to be deoptimized because of dead embedded maps. 5075 inline bool marked_for_deoptimization(); 5076 inline void set_marked_for_deoptimization(bool flag); 5077 5078 // [is_promise_rejection]: For kind BUILTIN tells whether the exception 5079 // thrown by the code will lead to promise rejection. 5080 inline bool is_promise_rejection(); 5081 inline void set_is_promise_rejection(bool flag); 5082 5083 // [is_exception_caught]: For kind BUILTIN tells whether the exception 5084 // thrown by the code will be caught internally. 5085 inline bool is_exception_caught(); 5086 inline void set_is_exception_caught(bool flag); 5087 5088 // [constant_pool]: The constant pool for this function. 5089 inline Address constant_pool(); 5090 5091 // Get the safepoint entry for the given pc. 5092 SafepointEntry GetSafepointEntry(Address pc); 5093 5094 // Find an object in a stub with a specified map 5095 Object* FindNthObject(int n, Map* match_map); 5096 5097 // Find the first allocation site in an IC stub. 5098 AllocationSite* FindFirstAllocationSite(); 5099 5100 // Find the first map in an IC stub. 5101 Map* FindFirstMap(); 5102 5103 // For each (map-to-find, object-to-replace) pair in the pattern, this 5104 // function replaces the corresponding placeholder in the code with the 5105 // object-to-replace. The function assumes that pairs in the pattern come in 5106 // the same order as the placeholders in the code. 5107 // If the placeholder is a weak cell, then the value of weak cell is matched 5108 // against the map-to-find. 5109 void FindAndReplace(const FindAndReplacePattern& pattern); 5110 5111 // The entire code object including its header is copied verbatim to the 5112 // snapshot so that it can be written in one, fast, memcpy during 5113 // deserialization. The deserializer will overwrite some pointers, rather 5114 // like a runtime linker, but the random allocation addresses used in the 5115 // mksnapshot process would still be present in the unlinked snapshot data, 5116 // which would make snapshot production non-reproducible. This method wipes 5117 // out the to-be-overwritten header data for reproducible snapshots. 5118 inline void WipeOutHeader(); 5119 5120 // Flags operations. 5121 static inline Flags ComputeFlags( 5122 Kind kind, ExtraICState extra_ic_state = kNoExtraICState, 5123 CacheHolderFlag holder = kCacheOnReceiver); 5124 5125 static inline Flags ComputeHandlerFlags( 5126 Kind handler_kind, CacheHolderFlag holder = kCacheOnReceiver); 5127 5128 static inline CacheHolderFlag ExtractCacheHolderFromFlags(Flags flags); 5129 static inline Kind ExtractKindFromFlags(Flags flags); 5130 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags); 5131 5132 static inline Flags RemoveHolderFromFlags(Flags flags); 5133 5134 // Convert a target address into a code object. 5135 static inline Code* GetCodeFromTargetAddress(Address address); 5136 5137 // Convert an entry address into an object. 5138 static inline Object* GetObjectFromEntryAddress(Address location_of_address); 5139 5140 // Returns the address of the first instruction. 5141 inline byte* instruction_start(); 5142 5143 // Returns the address right after the last instruction. 5144 inline byte* instruction_end(); 5145 5146 // Returns the size of the instructions, padding, relocation and unwinding 5147 // information. 5148 inline int body_size(); 5149 5150 // Returns the size of code and its metadata. This includes the size of code 5151 // relocation information, deoptimization data and handler table. 5152 inline int SizeIncludingMetadata(); 5153 5154 // Returns the address of the first relocation info (read backwards!). 5155 inline byte* relocation_start(); 5156 5157 // [has_unwinding_info]: Whether this code object has unwinding information. 5158 // If it doesn't, unwinding_information_start() will point to invalid data. 5159 // 5160 // The body of all code objects has the following layout. 5161 // 5162 // +--------------------------+ <-- instruction_start() 5163 // | instructions | 5164 // | ... | 5165 // +--------------------------+ 5166 // | relocation info | 5167 // | ... | 5168 // +--------------------------+ <-- instruction_end() 5169 // 5170 // If has_unwinding_info() is false, instruction_end() points to the first 5171 // memory location after the end of the code object. Otherwise, the body 5172 // continues as follows: 5173 // 5174 // +--------------------------+ 5175 // | padding to the next | 5176 // | 8-byte aligned address | 5177 // +--------------------------+ <-- instruction_end() 5178 // | [unwinding_info_size] | 5179 // | as uint64_t | 5180 // +--------------------------+ <-- unwinding_info_start() 5181 // | unwinding info | 5182 // | ... | 5183 // +--------------------------+ <-- unwinding_info_end() 5184 // 5185 // and unwinding_info_end() points to the first memory location after the end 5186 // of the code object. 5187 // 5188 DECL_BOOLEAN_ACCESSORS(has_unwinding_info) 5189 5190 // [unwinding_info_size]: Size of the unwinding information. 5191 inline int unwinding_info_size() const; 5192 inline void set_unwinding_info_size(int value); 5193 5194 // Returns the address of the unwinding information, if any. 5195 inline byte* unwinding_info_start(); 5196 5197 // Returns the address right after the end of the unwinding information. 5198 inline byte* unwinding_info_end(); 5199 5200 // Code entry point. 5201 inline byte* entry(); 5202 5203 // Returns true if pc is inside this object's instructions. 5204 inline bool contains(byte* pc); 5205 5206 // Relocate the code by delta bytes. Called to signal that this code 5207 // object has been moved by delta bytes. 5208 void Relocate(intptr_t delta); 5209 5210 // Migrate code described by desc. 5211 void CopyFrom(const CodeDesc& desc); 5212 5213 // Returns the object size for a given body (used for allocation). 5214 static int SizeFor(int body_size) { 5215 DCHECK_SIZE_TAG_ALIGNED(body_size); 5216 return RoundUp(kHeaderSize + body_size, kCodeAlignment); 5217 } 5218 5219 // Calculate the size of the code object to report for log events. This takes 5220 // the layout of the code object into account. 5221 inline int ExecutableSize(); 5222 5223 DECLARE_CAST(Code) 5224 5225 // Dispatched behavior. 5226 inline int CodeSize(); 5227 5228 DECLARE_PRINTER(Code) 5229 DECLARE_VERIFIER(Code) 5230 5231 void ClearInlineCaches(); 5232 5233 BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset); 5234 uint32_t TranslateAstIdToPcOffset(BailoutId ast_id); 5235 5236 #define DECLARE_CODE_AGE_ENUM(X) k##X##CodeAge, 5237 enum Age { 5238 kToBeExecutedOnceCodeAge = -3, 5239 kNotExecutedCodeAge = -2, 5240 kExecutedOnceCodeAge = -1, 5241 kNoAgeCodeAge = 0, 5242 CODE_AGE_LIST(DECLARE_CODE_AGE_ENUM) 5243 kAfterLastCodeAge, 5244 kFirstCodeAge = kToBeExecutedOnceCodeAge, 5245 kLastCodeAge = kAfterLastCodeAge - 1, 5246 kCodeAgeCount = kAfterLastCodeAge - kFirstCodeAge - 1, 5247 kIsOldCodeAge = kSexagenarianCodeAge, 5248 kPreAgedCodeAge = kIsOldCodeAge - 1 5249 }; 5250 #undef DECLARE_CODE_AGE_ENUM 5251 5252 // Code aging. Indicates how many full GCs this code has survived without 5253 // being entered through the prologue. Used to determine when it is 5254 // relatively safe to flush this code object and replace it with the lazy 5255 // compilation stub. 5256 static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate); 5257 static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate); 5258 void MakeYoung(Isolate* isolate); 5259 void PreAge(Isolate* isolate); 5260 void MarkToBeExecutedOnce(Isolate* isolate); 5261 void MakeOlder(); 5262 static bool IsYoungSequence(Isolate* isolate, byte* sequence); 5263 bool IsOld(); 5264 Age GetAge(); 5265 static inline Code* GetPreAgedCodeAgeStub(Isolate* isolate) { 5266 return GetCodeAgeStub(isolate, kNotExecutedCodeAge); 5267 } 5268 5269 void PrintDeoptLocation(FILE* out, Address pc); 5270 bool CanDeoptAt(Address pc); 5271 5272 #ifdef VERIFY_HEAP 5273 void VerifyEmbeddedObjectsDependency(); 5274 #endif 5275 5276 #ifdef DEBUG 5277 enum VerifyMode { kNoContextSpecificPointers, kNoContextRetainingPointers }; 5278 void VerifyEmbeddedObjects(VerifyMode mode = kNoContextRetainingPointers); 5279 static void VerifyRecompiledCode(Code* old_code, Code* new_code); 5280 #endif // DEBUG 5281 5282 inline bool CanContainWeakObjects(); 5283 5284 inline bool IsWeakObject(Object* object); 5285 5286 static inline bool IsWeakObjectInOptimizedCode(Object* object); 5287 5288 static Handle<WeakCell> WeakCellFor(Handle<Code> code); 5289 WeakCell* CachedWeakCell(); 5290 5291 static const int kConstantPoolSize = 5292 FLAG_enable_embedded_constant_pool ? kIntSize : 0; 5293 5294 // Layout description. 5295 static const int kRelocationInfoOffset = HeapObject::kHeaderSize; 5296 static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize; 5297 static const int kDeoptimizationDataOffset = 5298 kHandlerTableOffset + kPointerSize; 5299 static const int kSourcePositionTableOffset = 5300 kDeoptimizationDataOffset + kPointerSize; 5301 // For FUNCTION kind, we store the type feedback info here. 5302 static const int kTypeFeedbackInfoOffset = 5303 kSourcePositionTableOffset + kPointerSize; 5304 static const int kNextCodeLinkOffset = kTypeFeedbackInfoOffset + kPointerSize; 5305 static const int kGCMetadataOffset = kNextCodeLinkOffset + kPointerSize; 5306 static const int kInstructionSizeOffset = kGCMetadataOffset + kPointerSize; 5307 static const int kICAgeOffset = kInstructionSizeOffset + kIntSize; 5308 static const int kFlagsOffset = kICAgeOffset + kIntSize; 5309 static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize; 5310 static const int kKindSpecificFlags2Offset = 5311 kKindSpecificFlags1Offset + kIntSize; 5312 // Note: We might be able to squeeze this into the flags above. 5313 static const int kPrologueOffset = kKindSpecificFlags2Offset + kIntSize; 5314 static const int kConstantPoolOffset = kPrologueOffset + kIntSize; 5315 static const int kBuiltinIndexOffset = 5316 kConstantPoolOffset + kConstantPoolSize; 5317 static const int kHeaderPaddingStart = kBuiltinIndexOffset + kIntSize; 5318 5319 enum TrapFields { kTrapCodeOffset, kTrapLandingOffset, kTrapDataSize }; 5320 5321 5322 // Add padding to align the instruction start following right after 5323 // the Code object header. 5324 static const int kHeaderSize = 5325 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask; 5326 5327 inline int GetUnwindingInfoSizeOffset() const; 5328 5329 class BodyDescriptor; 5330 5331 // Byte offsets within kKindSpecificFlags1Offset. 5332 static const int kFullCodeFlags = kKindSpecificFlags1Offset; 5333 class FullCodeFlagsHasDeoptimizationSupportField: 5334 public BitField<bool, 0, 1> {}; // NOLINT 5335 class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {}; 5336 class FullCodeFlagsHasRelocInfoForSerialization 5337 : public BitField<bool, 2, 1> {}; 5338 // Bit 3 in this bitfield is unused. 5339 class ProfilerTicksField : public BitField<int, 4, 28> {}; 5340 5341 // Flags layout. BitField<type, shift, size>. 5342 class HasUnwindingInfoField : public BitField<bool, 0, 1> {}; 5343 class CacheHolderField 5344 : public BitField<CacheHolderFlag, HasUnwindingInfoField::kNext, 2> {}; 5345 class KindField : public BitField<Kind, CacheHolderField::kNext, 5> {}; 5346 STATIC_ASSERT(NUMBER_OF_KINDS <= KindField::kMax); 5347 class ExtraICStateField 5348 : public BitField<ExtraICState, KindField::kNext, 5349 PlatformSmiTagging::kSmiValueSize - KindField::kNext> { 5350 }; 5351 5352 // KindSpecificFlags1 layout (STUB, BUILTIN and OPTIMIZED_FUNCTION) 5353 static const int kStackSlotsFirstBit = 0; 5354 static const int kStackSlotsBitCount = 24; 5355 static const int kMarkedForDeoptimizationBit = 5356 kStackSlotsFirstBit + kStackSlotsBitCount; 5357 static const int kIsTurbofannedBit = kMarkedForDeoptimizationBit + 1; 5358 static const int kCanHaveWeakObjects = kIsTurbofannedBit + 1; 5359 // Could be moved to overlap previous bits when we need more space. 5360 static const int kIsConstructStub = kCanHaveWeakObjects + 1; 5361 static const int kIsPromiseRejection = kIsConstructStub + 1; 5362 static const int kIsExceptionCaught = kIsPromiseRejection + 1; 5363 5364 STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32); 5365 STATIC_ASSERT(kIsExceptionCaught + 1 <= 32); 5366 5367 class StackSlotsField: public BitField<int, 5368 kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT 5369 class MarkedForDeoptimizationField 5370 : public BitField<bool, kMarkedForDeoptimizationBit, 1> {}; // NOLINT 5371 class IsTurbofannedField : public BitField<bool, kIsTurbofannedBit, 1> { 5372 }; // NOLINT 5373 class CanHaveWeakObjectsField 5374 : public BitField<bool, kCanHaveWeakObjects, 1> {}; // NOLINT 5375 class IsConstructStubField : public BitField<bool, kIsConstructStub, 1> { 5376 }; // NOLINT 5377 class IsPromiseRejectionField 5378 : public BitField<bool, kIsPromiseRejection, 1> {}; // NOLINT 5379 class IsExceptionCaughtField : public BitField<bool, kIsExceptionCaught, 1> { 5380 }; // NOLINT 5381 5382 // KindSpecificFlags2 layout (ALL) 5383 static const int kIsCrankshaftedBit = 0; 5384 class IsCrankshaftedField: public BitField<bool, 5385 kIsCrankshaftedBit, 1> {}; // NOLINT 5386 5387 // KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION) 5388 static const int kSafepointTableOffsetFirstBit = kIsCrankshaftedBit + 1; 5389 static const int kSafepointTableOffsetBitCount = 30; 5390 5391 STATIC_ASSERT(kSafepointTableOffsetFirstBit + 5392 kSafepointTableOffsetBitCount <= 32); 5393 STATIC_ASSERT(1 + kSafepointTableOffsetBitCount <= 32); 5394 5395 class SafepointTableOffsetField: public BitField<int, 5396 kSafepointTableOffsetFirstBit, 5397 kSafepointTableOffsetBitCount> {}; // NOLINT 5398 5399 // KindSpecificFlags2 layout (FUNCTION) 5400 class BackEdgeTableOffsetField: public BitField<int, 5401 kIsCrankshaftedBit + 1, 27> {}; // NOLINT 5402 class AllowOSRAtLoopNestingLevelField: public BitField<int, 5403 kIsCrankshaftedBit + 1 + 27, 4> {}; // NOLINT 5404 5405 static const int kArgumentsBits = 16; 5406 static const int kMaxArguments = (1 << kArgumentsBits) - 1; 5407 5408 // This constant should be encodable in an ARM instruction. 5409 static const int kFlagsNotUsedInLookup = CacheHolderField::kMask; 5410 5411 private: 5412 friend class RelocIterator; 5413 friend class Deoptimizer; // For FindCodeAgeSequence. 5414 5415 // Code aging 5416 byte* FindCodeAgeSequence(); 5417 static Age GetCodeAge(Isolate* isolate, byte* sequence); 5418 static Age GetAgeOfCodeAgeStub(Code* code); 5419 static Code* GetCodeAgeStub(Isolate* isolate, Age age); 5420 5421 // Code aging -- platform-specific 5422 static void PatchPlatformCodeAge(Isolate* isolate, byte* sequence, Age age); 5423 5424 DISALLOW_IMPLICIT_CONSTRUCTORS(Code); 5425 }; 5426 5427 class AbstractCode : public HeapObject { 5428 public: 5429 // All code kinds and INTERPRETED_FUNCTION. 5430 enum Kind { 5431 #define DEFINE_CODE_KIND_ENUM(name) name, 5432 CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM) 5433 #undef DEFINE_CODE_KIND_ENUM 5434 INTERPRETED_FUNCTION, 5435 NUMBER_OF_KINDS 5436 }; 5437 5438 static const char* Kind2String(Kind kind); 5439 5440 int SourcePosition(int offset); 5441 int SourceStatementPosition(int offset); 5442 5443 // Returns the address of the first instruction. 5444 inline Address instruction_start(); 5445 5446 // Returns the address right after the last instruction. 5447 inline Address instruction_end(); 5448 5449 // Returns the size of the code instructions. 5450 inline int instruction_size(); 5451 5452 // Return the source position table. 5453 inline ByteArray* source_position_table(); 5454 5455 // Set the source position table. 5456 inline void set_source_position_table(ByteArray* source_position_table); 5457 5458 // Returns the size of instructions and the metadata. 5459 inline int SizeIncludingMetadata(); 5460 5461 // Returns true if pc is inside this object's instructions. 5462 inline bool contains(byte* pc); 5463 5464 // Returns the AbstractCode::Kind of the code. 5465 inline Kind kind(); 5466 5467 // Calculate the size of the code object to report for log events. This takes 5468 // the layout of the code object into account. 5469 inline int ExecutableSize(); 5470 5471 DECLARE_CAST(AbstractCode) 5472 inline Code* GetCode(); 5473 inline BytecodeArray* GetBytecodeArray(); 5474 5475 // Max loop nesting marker used to postpose OSR. We don't take loop 5476 // nesting that is deeper than 5 levels into account. 5477 static const int kMaxLoopNestingMarker = 6; 5478 STATIC_ASSERT(Code::AllowOSRAtLoopNestingLevelField::kMax >= 5479 kMaxLoopNestingMarker); 5480 }; 5481 5482 // Dependent code is a singly linked list of fixed arrays. Each array contains 5483 // code objects in weak cells for one dependent group. The suffix of the array 5484 // can be filled with the undefined value if the number of codes is less than 5485 // the length of the array. 5486 // 5487 // +------+-----------------+--------+--------+-----+--------+-----------+-----+ 5488 // | next | count & group 1 | code 1 | code 2 | ... | code n | undefined | ... | 5489 // +------+-----------------+--------+--------+-----+--------+-----------+-----+ 5490 // | 5491 // V 5492 // +------+-----------------+--------+--------+-----+--------+-----------+-----+ 5493 // | next | count & group 2 | code 1 | code 2 | ... | code m | undefined | ... | 5494 // +------+-----------------+--------+--------+-----+--------+-----------+-----+ 5495 // | 5496 // V 5497 // empty_fixed_array() 5498 // 5499 // The list of fixed arrays is ordered by dependency groups. 5500 5501 class DependentCode: public FixedArray { 5502 public: 5503 enum DependencyGroup { 5504 // Group of code that weakly embed this map and depend on being 5505 // deoptimized when the map is garbage collected. 5506 kWeakCodeGroup, 5507 // Group of code that embed a transition to this map, and depend on being 5508 // deoptimized when the transition is replaced by a new version. 5509 kTransitionGroup, 5510 // Group of code that omit run-time prototype checks for prototypes 5511 // described by this map. The group is deoptimized whenever an object 5512 // described by this map changes shape (and transitions to a new map), 5513 // possibly invalidating the assumptions embedded in the code. 5514 kPrototypeCheckGroup, 5515 // Group of code that depends on global property values in property cells 5516 // not being changed. 5517 kPropertyCellChangedGroup, 5518 // Group of code that omit run-time checks for field(s) introduced by 5519 // this map, i.e. for the field type. 5520 kFieldOwnerGroup, 5521 // Group of code that omit run-time type checks for initial maps of 5522 // constructors. 5523 kInitialMapChangedGroup, 5524 // Group of code that depends on tenuring information in AllocationSites 5525 // not being changed. 5526 kAllocationSiteTenuringChangedGroup, 5527 // Group of code that depends on element transition information in 5528 // AllocationSites not being changed. 5529 kAllocationSiteTransitionChangedGroup 5530 }; 5531 5532 static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1; 5533 static const int kNextLinkIndex = 0; 5534 static const int kFlagsIndex = 1; 5535 static const int kCodesStartIndex = 2; 5536 5537 bool Contains(DependencyGroup group, WeakCell* code_cell); 5538 bool IsEmpty(DependencyGroup group); 5539 5540 static Handle<DependentCode> InsertCompilationDependencies( 5541 Handle<DependentCode> entries, DependencyGroup group, 5542 Handle<Foreign> info); 5543 5544 static Handle<DependentCode> InsertWeakCode(Handle<DependentCode> entries, 5545 DependencyGroup group, 5546 Handle<WeakCell> code_cell); 5547 5548 void UpdateToFinishedCode(DependencyGroup group, Foreign* info, 5549 WeakCell* code_cell); 5550 5551 void RemoveCompilationDependencies(DependentCode::DependencyGroup group, 5552 Foreign* info); 5553 5554 void DeoptimizeDependentCodeGroup(Isolate* isolate, 5555 DependentCode::DependencyGroup group); 5556 5557 bool MarkCodeForDeoptimization(Isolate* isolate, 5558 DependentCode::DependencyGroup group); 5559 5560 // The following low-level accessors should only be used by this class 5561 // and the mark compact collector. 5562 inline DependentCode* next_link(); 5563 inline void set_next_link(DependentCode* next); 5564 inline int count(); 5565 inline void set_count(int value); 5566 inline DependencyGroup group(); 5567 inline void set_group(DependencyGroup group); 5568 inline Object* object_at(int i); 5569 inline void set_object_at(int i, Object* object); 5570 inline void clear_at(int i); 5571 inline void copy(int from, int to); 5572 DECLARE_CAST(DependentCode) 5573 5574 static const char* DependencyGroupName(DependencyGroup group); 5575 static void SetMarkedForDeoptimization(Code* code, DependencyGroup group); 5576 5577 private: 5578 static Handle<DependentCode> Insert(Handle<DependentCode> entries, 5579 DependencyGroup group, 5580 Handle<Object> object); 5581 static Handle<DependentCode> New(DependencyGroup group, Handle<Object> object, 5582 Handle<DependentCode> next); 5583 static Handle<DependentCode> EnsureSpace(Handle<DependentCode> entries); 5584 // Compact by removing cleared weak cells and return true if there was 5585 // any cleared weak cell. 5586 bool Compact(); 5587 static int Grow(int number_of_entries) { 5588 if (number_of_entries < 5) return number_of_entries + 1; 5589 return number_of_entries * 5 / 4; 5590 } 5591 inline int flags(); 5592 inline void set_flags(int flags); 5593 class GroupField : public BitField<int, 0, 3> {}; 5594 class CountField : public BitField<int, 3, 27> {}; 5595 STATIC_ASSERT(kGroupCount <= GroupField::kMax + 1); 5596 }; 5597 5598 5599 class PrototypeInfo; 5600 5601 5602 // All heap objects have a Map that describes their structure. 5603 // A Map contains information about: 5604 // - Size information about the object 5605 // - How to iterate over an object (for garbage collection) 5606 class Map: public HeapObject { 5607 public: 5608 // Instance size. 5609 // Size in bytes or kVariableSizeSentinel if instances do not have 5610 // a fixed size. 5611 inline int instance_size(); 5612 inline void set_instance_size(int value); 5613 5614 // Only to clear an unused byte, remove once byte is used. 5615 inline void clear_unused(); 5616 5617 // [inobject_properties_or_constructor_function_index]: Provides access 5618 // to the inobject properties in case of JSObject maps, or the constructor 5619 // function index in case of primitive maps. 5620 inline int inobject_properties_or_constructor_function_index(); 5621 inline void set_inobject_properties_or_constructor_function_index(int value); 5622 // Count of properties allocated in the object (JSObject only). 5623 inline int GetInObjectProperties(); 5624 inline void SetInObjectProperties(int value); 5625 // Index of the constructor function in the native context (primitives only), 5626 // or the special sentinel value to indicate that there is no object wrapper 5627 // for the primitive (i.e. in case of null or undefined). 5628 static const int kNoConstructorFunctionIndex = 0; 5629 inline int GetConstructorFunctionIndex(); 5630 inline void SetConstructorFunctionIndex(int value); 5631 static MaybeHandle<JSFunction> GetConstructorFunction( 5632 Handle<Map> map, Handle<Context> native_context); 5633 5634 // Retrieve interceptors. 5635 inline InterceptorInfo* GetNamedInterceptor(); 5636 inline InterceptorInfo* GetIndexedInterceptor(); 5637 5638 // Instance type. 5639 inline InstanceType instance_type(); 5640 inline void set_instance_type(InstanceType value); 5641 5642 // Tells how many unused property fields are available in the 5643 // instance (only used for JSObject in fast mode). 5644 inline int unused_property_fields(); 5645 inline void set_unused_property_fields(int value); 5646 5647 // Bit field. 5648 inline byte bit_field() const; 5649 inline void set_bit_field(byte value); 5650 5651 // Bit field 2. 5652 inline byte bit_field2() const; 5653 inline void set_bit_field2(byte value); 5654 5655 // Bit field 3. 5656 inline uint32_t bit_field3() const; 5657 inline void set_bit_field3(uint32_t bits); 5658 5659 class EnumLengthBits: public BitField<int, 5660 0, kDescriptorIndexBitCount> {}; // NOLINT 5661 class NumberOfOwnDescriptorsBits: public BitField<int, 5662 kDescriptorIndexBitCount, kDescriptorIndexBitCount> {}; // NOLINT 5663 STATIC_ASSERT(kDescriptorIndexBitCount + kDescriptorIndexBitCount == 20); 5664 class DictionaryMap : public BitField<bool, 20, 1> {}; 5665 class OwnsDescriptors : public BitField<bool, 21, 1> {}; 5666 class HasHiddenPrototype : public BitField<bool, 22, 1> {}; 5667 class Deprecated : public BitField<bool, 23, 1> {}; 5668 class IsUnstable : public BitField<bool, 24, 1> {}; 5669 class IsMigrationTarget : public BitField<bool, 25, 1> {}; 5670 class ImmutablePrototype : public BitField<bool, 26, 1> {}; 5671 class NewTargetIsBase : public BitField<bool, 27, 1> {}; 5672 // Bit 28 is free. 5673 5674 // Keep this bit field at the very end for better code in 5675 // Builtins::kJSConstructStubGeneric stub. 5676 // This counter is used for in-object slack tracking. 5677 // The in-object slack tracking is considered enabled when the counter is 5678 // non zero. The counter only has a valid count for initial maps. For 5679 // transitioned maps only kNoSlackTracking has a meaning, namely that inobject 5680 // slack tracking already finished for the transition tree. Any other value 5681 // indicates that either inobject slack tracking is still in progress, or that 5682 // the map isn't part of the transition tree anymore. 5683 class ConstructionCounter : public BitField<int, 29, 3> {}; 5684 static const int kSlackTrackingCounterStart = 7; 5685 static const int kSlackTrackingCounterEnd = 1; 5686 static const int kNoSlackTracking = 0; 5687 STATIC_ASSERT(kSlackTrackingCounterStart <= ConstructionCounter::kMax); 5688 5689 5690 // Inobject slack tracking is the way to reclaim unused inobject space. 5691 // 5692 // The instance size is initially determined by adding some slack to 5693 // expected_nof_properties (to allow for a few extra properties added 5694 // after the constructor). There is no guarantee that the extra space 5695 // will not be wasted. 5696 // 5697 // Here is the algorithm to reclaim the unused inobject space: 5698 // - Detect the first constructor call for this JSFunction. 5699 // When it happens enter the "in progress" state: initialize construction 5700 // counter in the initial_map. 5701 // - While the tracking is in progress initialize unused properties of a new 5702 // object with one_pointer_filler_map instead of undefined_value (the "used" 5703 // part is initialized with undefined_value as usual). This way they can 5704 // be resized quickly and safely. 5705 // - Once enough objects have been created compute the 'slack' 5706 // (traverse the map transition tree starting from the 5707 // initial_map and find the lowest value of unused_property_fields). 5708 // - Traverse the transition tree again and decrease the instance size 5709 // of every map. Existing objects will resize automatically (they are 5710 // filled with one_pointer_filler_map). All further allocations will 5711 // use the adjusted instance size. 5712 // - SharedFunctionInfo's expected_nof_properties left unmodified since 5713 // allocations made using different closures could actually create different 5714 // kind of objects (see prototype inheritance pattern). 5715 // 5716 // Important: inobject slack tracking is not attempted during the snapshot 5717 // creation. 5718 5719 static const int kGenerousAllocationCount = 5720 kSlackTrackingCounterStart - kSlackTrackingCounterEnd + 1; 5721 5722 // Starts the tracking by initializing object constructions countdown counter. 5723 void StartInobjectSlackTracking(); 5724 5725 // True if the object constructions countdown counter is a range 5726 // [kSlackTrackingCounterEnd, kSlackTrackingCounterStart]. 5727 inline bool IsInobjectSlackTrackingInProgress(); 5728 5729 // Does the tracking step. 5730 inline void InobjectSlackTrackingStep(); 5731 5732 // Completes inobject slack tracking for the transition tree starting at this 5733 // initial map. 5734 void CompleteInobjectSlackTracking(); 5735 5736 // Tells whether the object in the prototype property will be used 5737 // for instances created from this function. If the prototype 5738 // property is set to a value that is not a JSObject, the prototype 5739 // property will not be used to create instances of the function. 5740 // See ECMA-262, 13.2.2. 5741 inline void set_non_instance_prototype(bool value); 5742 inline bool has_non_instance_prototype(); 5743 5744 // Tells whether the instance has a [[Construct]] internal method. 5745 // This property is implemented according to ES6, section 7.2.4. 5746 inline void set_is_constructor(bool value); 5747 inline bool is_constructor() const; 5748 5749 // Tells whether the instance with this map has a hidden prototype. 5750 inline void set_has_hidden_prototype(bool value); 5751 inline bool has_hidden_prototype() const; 5752 5753 // Records and queries whether the instance has a named interceptor. 5754 inline void set_has_named_interceptor(); 5755 inline bool has_named_interceptor(); 5756 5757 // Records and queries whether the instance has an indexed interceptor. 5758 inline void set_has_indexed_interceptor(); 5759 inline bool has_indexed_interceptor(); 5760 5761 // Tells whether the instance is undetectable. 5762 // An undetectable object is a special class of JSObject: 'typeof' operator 5763 // returns undefined, ToBoolean returns false. Otherwise it behaves like 5764 // a normal JS object. It is useful for implementing undetectable 5765 // document.all in Firefox & Safari. 5766 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549. 5767 inline void set_is_undetectable(); 5768 inline bool is_undetectable(); 5769 5770 // Tells whether the instance has a [[Call]] internal method. 5771 // This property is implemented according to ES6, section 7.2.3. 5772 inline void set_is_callable(); 5773 inline bool is_callable() const; 5774 5775 inline void set_new_target_is_base(bool value); 5776 inline bool new_target_is_base(); 5777 inline void set_is_extensible(bool value); 5778 inline bool is_extensible(); 5779 inline void set_is_prototype_map(bool value); 5780 inline bool is_prototype_map() const; 5781 5782 inline void set_elements_kind(ElementsKind elements_kind); 5783 inline ElementsKind elements_kind(); 5784 5785 // Tells whether the instance has fast elements that are only Smis. 5786 inline bool has_fast_smi_elements(); 5787 5788 // Tells whether the instance has fast elements. 5789 inline bool has_fast_object_elements(); 5790 inline bool has_fast_smi_or_object_elements(); 5791 inline bool has_fast_double_elements(); 5792 inline bool has_fast_elements(); 5793 inline bool has_sloppy_arguments_elements(); 5794 inline bool has_fast_sloppy_arguments_elements(); 5795 inline bool has_fast_string_wrapper_elements(); 5796 inline bool has_fixed_typed_array_elements(); 5797 inline bool has_dictionary_elements(); 5798 5799 static bool IsValidElementsTransition(ElementsKind from_kind, 5800 ElementsKind to_kind); 5801 5802 // Returns true if the current map doesn't have DICTIONARY_ELEMENTS but if a 5803 // map with DICTIONARY_ELEMENTS was found in the prototype chain. 5804 bool DictionaryElementsInPrototypeChainOnly(); 5805 5806 inline Map* ElementsTransitionMap(); 5807 5808 inline FixedArrayBase* GetInitialElements(); 5809 5810 // [raw_transitions]: Provides access to the transitions storage field. 5811 // Don't call set_raw_transitions() directly to overwrite transitions, use 5812 // the TransitionArray::ReplaceTransitions() wrapper instead! 5813 DECL_ACCESSORS(raw_transitions, Object) 5814 // [prototype_info]: Per-prototype metadata. Aliased with transitions 5815 // (which prototype maps don't have). 5816 DECL_ACCESSORS(prototype_info, Object) 5817 // PrototypeInfo is created lazily using this helper (which installs it on 5818 // the given prototype's map). 5819 static Handle<PrototypeInfo> GetOrCreatePrototypeInfo( 5820 Handle<JSObject> prototype, Isolate* isolate); 5821 static Handle<PrototypeInfo> GetOrCreatePrototypeInfo( 5822 Handle<Map> prototype_map, Isolate* isolate); 5823 inline bool should_be_fast_prototype_map() const; 5824 static void SetShouldBeFastPrototypeMap(Handle<Map> map, bool value, 5825 Isolate* isolate);