1 // Copyright 2012 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 "src/allocation.h" 9 #include "src/assert-scope.h" 10 #include "src/bailout-reason.h" 11 #include "src/base/bits.h" 12 #include "src/builtins.h" 13 #include "src/checks.h" 14 #include "src/elements-kind.h" 15 #include "src/field-index.h" 16 #include "src/flags.h" 17 #include "src/list.h" 18 #include "src/property-details.h" 19 #include "src/smart-pointers.h" 20 #include "src/unicode-inl.h" 21 #include "src/zone.h" 22 23 #if V8_TARGET_ARCH_ARM 24 #include "src/arm/constants-arm.h" // NOLINT 25 #elif V8_TARGET_ARCH_ARM64 26 #include "src/arm64/constants-arm64.h" // NOLINT 27 #elif V8_TARGET_ARCH_MIPS 28 #include "src/mips/constants-mips.h" // NOLINT 29 #elif V8_TARGET_ARCH_MIPS64 30 #include "src/mips64/constants-mips64.h" // NOLINT 31 #endif 32 33 34 // 35 // Most object types in the V8 JavaScript are described in this file. 36 // 37 // Inheritance hierarchy: 38 // - Object 39 // - Smi (immediate small integer) 40 // - HeapObject (superclass for everything allocated in the heap) 41 // - JSReceiver (suitable for property access) 42 // - JSObject 43 // - JSArray 44 // - JSArrayBuffer 45 // - JSArrayBufferView 46 // - JSTypedArray 47 // - JSDataView 48 // - JSCollection 49 // - JSSet 50 // - JSMap 51 // - JSSetIterator 52 // - JSMapIterator 53 // - JSWeakCollection 54 // - JSWeakMap 55 // - JSWeakSet 56 // - JSRegExp 57 // - JSFunction 58 // - JSGeneratorObject 59 // - JSModule 60 // - GlobalObject 61 // - JSGlobalObject 62 // - JSBuiltinsObject 63 // - JSGlobalProxy 64 // - JSValue 65 // - JSDate 66 // - JSMessageObject 67 // - JSProxy 68 // - JSFunctionProxy 69 // - FixedArrayBase 70 // - ByteArray 71 // - FixedArray 72 // - DescriptorArray 73 // - HashTable 74 // - Dictionary 75 // - StringTable 76 // - CompilationCacheTable 77 // - CodeCacheHashTable 78 // - MapCache 79 // - OrderedHashTable 80 // - OrderedHashSet 81 // - OrderedHashMap 82 // - Context 83 // - TypeFeedbackVector 84 // - JSFunctionResultCache 85 // - ScopeInfo 86 // - TransitionArray 87 // - FixedDoubleArray 88 // - ExternalArray 89 // - ExternalUint8ClampedArray 90 // - ExternalInt8Array 91 // - ExternalUint8Array 92 // - ExternalInt16Array 93 // - ExternalUint16Array 94 // - ExternalInt32Array 95 // - ExternalUint32Array 96 // - ExternalFloat32Array 97 // - Name 98 // - String 99 // - SeqString 100 // - SeqOneByteString 101 // - SeqTwoByteString 102 // - SlicedString 103 // - ConsString 104 // - ExternalString 105 // - ExternalOneByteString 106 // - ExternalTwoByteString 107 // - InternalizedString 108 // - SeqInternalizedString 109 // - SeqOneByteInternalizedString 110 // - SeqTwoByteInternalizedString 111 // - ConsInternalizedString 112 // - ExternalInternalizedString 113 // - ExternalOneByteInternalizedString 114 // - ExternalTwoByteInternalizedString 115 // - Symbol 116 // - HeapNumber 117 // - Cell 118 // - PropertyCell 119 // - Code 120 // - Map 121 // - Oddball 122 // - Foreign 123 // - SharedFunctionInfo 124 // - Struct 125 // - Box 126 // - DeclaredAccessorDescriptor 127 // - AccessorInfo 128 // - DeclaredAccessorInfo 129 // - ExecutableAccessorInfo 130 // - AccessorPair 131 // - AccessCheckInfo 132 // - InterceptorInfo 133 // - CallHandlerInfo 134 // - TemplateInfo 135 // - FunctionTemplateInfo 136 // - ObjectTemplateInfo 137 // - Script 138 // - SignatureInfo 139 // - TypeSwitchInfo 140 // - DebugInfo 141 // - BreakPointInfo 142 // - CodeCache 143 // 144 // Formats of Object*: 145 // Smi: [31 bit signed int] 0 146 // HeapObject: [32 bit direct pointer] (4 byte aligned) | 01 147 148 namespace v8 { 149 namespace internal { 150 151 class OStream; 152 153 enum KeyedAccessStoreMode { 154 STANDARD_STORE, 155 STORE_TRANSITION_SMI_TO_OBJECT, 156 STORE_TRANSITION_SMI_TO_DOUBLE, 157 STORE_TRANSITION_DOUBLE_TO_OBJECT, 158 STORE_TRANSITION_HOLEY_SMI_TO_OBJECT, 159 STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE, 160 STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT, 161 STORE_AND_GROW_NO_TRANSITION, 162 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT, 163 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE, 164 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT, 165 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT, 166 STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE, 167 STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT, 168 STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS, 169 STORE_NO_TRANSITION_HANDLE_COW 170 }; 171 172 173 enum ContextualMode { 174 NOT_CONTEXTUAL, 175 CONTEXTUAL 176 }; 177 178 179 enum MutableMode { 180 MUTABLE, 181 IMMUTABLE 182 }; 183 184 185 static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION - 186 STANDARD_STORE; 187 STATIC_ASSERT(STANDARD_STORE == 0); 188 STATIC_ASSERT(kGrowICDelta == 189 STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT - 190 STORE_TRANSITION_SMI_TO_OBJECT); 191 STATIC_ASSERT(kGrowICDelta == 192 STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE - 193 STORE_TRANSITION_SMI_TO_DOUBLE); 194 STATIC_ASSERT(kGrowICDelta == 195 STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT - 196 STORE_TRANSITION_DOUBLE_TO_OBJECT); 197 198 199 static inline KeyedAccessStoreMode GetGrowStoreMode( 200 KeyedAccessStoreMode store_mode) { 201 if (store_mode < STORE_AND_GROW_NO_TRANSITION) { 202 store_mode = static_cast<KeyedAccessStoreMode>( 203 static_cast<int>(store_mode) + kGrowICDelta); 204 } 205 return store_mode; 206 } 207 208 209 static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) { 210 return store_mode > STANDARD_STORE && 211 store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT && 212 store_mode != STORE_AND_GROW_NO_TRANSITION; 213 } 214 215 216 static inline KeyedAccessStoreMode GetNonTransitioningStoreMode( 217 KeyedAccessStoreMode store_mode) { 218 if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 219 return store_mode; 220 } 221 if (store_mode >= STORE_AND_GROW_NO_TRANSITION) { 222 return STORE_AND_GROW_NO_TRANSITION; 223 } 224 return STANDARD_STORE; 225 } 226 227 228 static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) { 229 return store_mode >= STORE_AND_GROW_NO_TRANSITION && 230 store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT; 231 } 232 233 234 // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER. 235 enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER }; 236 237 238 // Indicates whether a value can be loaded as a constant. 239 enum StoreMode { 240 ALLOW_AS_CONSTANT, 241 FORCE_FIELD 242 }; 243 244 245 // PropertyNormalizationMode is used to specify whether to keep 246 // inobject properties when normalizing properties of a JSObject. 247 enum PropertyNormalizationMode { 248 CLEAR_INOBJECT_PROPERTIES, 249 KEEP_INOBJECT_PROPERTIES 250 }; 251 252 253 // Indicates how aggressively the prototype should be optimized. FAST_PROTOTYPE 254 // will give the fastest result by tailoring the map to the prototype, but that 255 // will cause polymorphism with other objects. REGULAR_PROTOTYPE is to be used 256 // (at least for now) when dynamically modifying the prototype chain of an 257 // object using __proto__ or Object.setPrototypeOf. 258 enum PrototypeOptimizationMode { REGULAR_PROTOTYPE, FAST_PROTOTYPE }; 259 260 261 // Indicates whether transitions can be added to a source map or not. 262 enum TransitionFlag { 263 INSERT_TRANSITION, 264 OMIT_TRANSITION 265 }; 266 267 268 enum DebugExtraICState { 269 DEBUG_BREAK, 270 DEBUG_PREPARE_STEP_IN 271 }; 272 273 274 // Indicates whether the transition is simple: the target map of the transition 275 // either extends the current map with a new property, or it modifies the 276 // property that was added last to the current map. 277 enum SimpleTransitionFlag { 278 SIMPLE_TRANSITION, 279 FULL_TRANSITION 280 }; 281 282 283 // Indicates whether we are only interested in the descriptors of a particular 284 // map, or in all descriptors in the descriptor array. 285 enum DescriptorFlag { 286 ALL_DESCRIPTORS, 287 OWN_DESCRIPTORS 288 }; 289 290 // The GC maintains a bit of information, the MarkingParity, which toggles 291 // from odd to even and back every time marking is completed. Incremental 292 // marking can visit an object twice during a marking phase, so algorithms that 293 // that piggy-back on marking can use the parity to ensure that they only 294 // perform an operation on an object once per marking phase: they record the 295 // MarkingParity when they visit an object, and only re-visit the object when it 296 // is marked again and the MarkingParity changes. 297 enum MarkingParity { 298 NO_MARKING_PARITY, 299 ODD_MARKING_PARITY, 300 EVEN_MARKING_PARITY 301 }; 302 303 // ICs store extra state in a Code object. The default extra state is 304 // kNoExtraICState. 305 typedef int ExtraICState; 306 static const ExtraICState kNoExtraICState = 0; 307 308 // Instance size sentinel for objects of variable size. 309 const int kVariableSizeSentinel = 0; 310 311 // We may store the unsigned bit field as signed Smi value and do not 312 // use the sign bit. 313 const int kStubMajorKeyBits = 7; 314 const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; 315 316 // All Maps have a field instance_type containing a InstanceType. 317 // It describes the type of the instances. 318 // 319 // As an example, a JavaScript object is a heap object and its map 320 // instance_type is JS_OBJECT_TYPE. 321 // 322 // The names of the string instance types are intended to systematically 323 // mirror their encoding in the instance_type field of the map. The default 324 // encoding is considered TWO_BYTE. It is not mentioned in the name. ONE_BYTE 325 // encoding is mentioned explicitly in the name. Likewise, the default 326 // representation is considered sequential. It is not mentioned in the 327 // name. The other representations (e.g. CONS, EXTERNAL) are explicitly 328 // mentioned. Finally, the string is either a STRING_TYPE (if it is a normal 329 // string) or a INTERNALIZED_STRING_TYPE (if it is a internalized string). 330 // 331 // NOTE: The following things are some that depend on the string types having 332 // instance_types that are less than those of all other types: 333 // HeapObject::Size, HeapObject::IterateBody, the typeof operator, and 334 // Object::IsString. 335 // 336 // NOTE: Everything following JS_VALUE_TYPE is considered a 337 // JSObject for GC purposes. The first four entries here have typeof 338 // 'object', whereas JS_FUNCTION_TYPE has typeof 'function'. 339 #define INSTANCE_TYPE_LIST(V) \ 340 V(STRING_TYPE) \ 341 V(ONE_BYTE_STRING_TYPE) \ 342 V(CONS_STRING_TYPE) \ 343 V(CONS_ONE_BYTE_STRING_TYPE) \ 344 V(SLICED_STRING_TYPE) \ 345 V(SLICED_ONE_BYTE_STRING_TYPE) \ 346 V(EXTERNAL_STRING_TYPE) \ 347 V(EXTERNAL_ONE_BYTE_STRING_TYPE) \ 348 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 349 V(SHORT_EXTERNAL_STRING_TYPE) \ 350 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE) \ 351 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 352 \ 353 V(INTERNALIZED_STRING_TYPE) \ 354 V(ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 355 V(EXTERNAL_INTERNALIZED_STRING_TYPE) \ 356 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 357 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 358 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE) \ 359 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE) \ 360 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE) \ 361 \ 362 V(SYMBOL_TYPE) \ 363 \ 364 V(MAP_TYPE) \ 365 V(CODE_TYPE) \ 366 V(ODDBALL_TYPE) \ 367 V(CELL_TYPE) \ 368 V(PROPERTY_CELL_TYPE) \ 369 \ 370 V(HEAP_NUMBER_TYPE) \ 371 V(MUTABLE_HEAP_NUMBER_TYPE) \ 372 V(FOREIGN_TYPE) \ 373 V(BYTE_ARRAY_TYPE) \ 374 V(FREE_SPACE_TYPE) \ 375 /* Note: the order of these external array */ \ 376 /* types is relied upon in */ \ 377 /* Object::IsExternalArray(). */ \ 378 V(EXTERNAL_INT8_ARRAY_TYPE) \ 379 V(EXTERNAL_UINT8_ARRAY_TYPE) \ 380 V(EXTERNAL_INT16_ARRAY_TYPE) \ 381 V(EXTERNAL_UINT16_ARRAY_TYPE) \ 382 V(EXTERNAL_INT32_ARRAY_TYPE) \ 383 V(EXTERNAL_UINT32_ARRAY_TYPE) \ 384 V(EXTERNAL_FLOAT32_ARRAY_TYPE) \ 385 V(EXTERNAL_FLOAT64_ARRAY_TYPE) \ 386 V(EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE) \ 387 \ 388 V(FIXED_INT8_ARRAY_TYPE) \ 389 V(FIXED_UINT8_ARRAY_TYPE) \ 390 V(FIXED_INT16_ARRAY_TYPE) \ 391 V(FIXED_UINT16_ARRAY_TYPE) \ 392 V(FIXED_INT32_ARRAY_TYPE) \ 393 V(FIXED_UINT32_ARRAY_TYPE) \ 394 V(FIXED_FLOAT32_ARRAY_TYPE) \ 395 V(FIXED_FLOAT64_ARRAY_TYPE) \ 396 V(FIXED_UINT8_CLAMPED_ARRAY_TYPE) \ 397 \ 398 V(FILLER_TYPE) \ 399 \ 400 V(DECLARED_ACCESSOR_DESCRIPTOR_TYPE) \ 401 V(DECLARED_ACCESSOR_INFO_TYPE) \ 402 V(EXECUTABLE_ACCESSOR_INFO_TYPE) \ 403 V(ACCESSOR_PAIR_TYPE) \ 404 V(ACCESS_CHECK_INFO_TYPE) \ 405 V(INTERCEPTOR_INFO_TYPE) \ 406 V(CALL_HANDLER_INFO_TYPE) \ 407 V(FUNCTION_TEMPLATE_INFO_TYPE) \ 408 V(OBJECT_TEMPLATE_INFO_TYPE) \ 409 V(SIGNATURE_INFO_TYPE) \ 410 V(TYPE_SWITCH_INFO_TYPE) \ 411 V(ALLOCATION_MEMENTO_TYPE) \ 412 V(ALLOCATION_SITE_TYPE) \ 413 V(SCRIPT_TYPE) \ 414 V(CODE_CACHE_TYPE) \ 415 V(POLYMORPHIC_CODE_CACHE_TYPE) \ 416 V(TYPE_FEEDBACK_INFO_TYPE) \ 417 V(ALIASED_ARGUMENTS_ENTRY_TYPE) \ 418 V(BOX_TYPE) \ 419 \ 420 V(FIXED_ARRAY_TYPE) \ 421 V(FIXED_DOUBLE_ARRAY_TYPE) \ 422 V(CONSTANT_POOL_ARRAY_TYPE) \ 423 V(SHARED_FUNCTION_INFO_TYPE) \ 424 \ 425 V(JS_MESSAGE_OBJECT_TYPE) \ 426 \ 427 V(JS_VALUE_TYPE) \ 428 V(JS_DATE_TYPE) \ 429 V(JS_OBJECT_TYPE) \ 430 V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \ 431 V(JS_GENERATOR_OBJECT_TYPE) \ 432 V(JS_MODULE_TYPE) \ 433 V(JS_GLOBAL_OBJECT_TYPE) \ 434 V(JS_BUILTINS_OBJECT_TYPE) \ 435 V(JS_GLOBAL_PROXY_TYPE) \ 436 V(JS_ARRAY_TYPE) \ 437 V(JS_ARRAY_BUFFER_TYPE) \ 438 V(JS_TYPED_ARRAY_TYPE) \ 439 V(JS_DATA_VIEW_TYPE) \ 440 V(JS_PROXY_TYPE) \ 441 V(JS_SET_TYPE) \ 442 V(JS_MAP_TYPE) \ 443 V(JS_SET_ITERATOR_TYPE) \ 444 V(JS_MAP_ITERATOR_TYPE) \ 445 V(JS_WEAK_MAP_TYPE) \ 446 V(JS_WEAK_SET_TYPE) \ 447 V(JS_REGEXP_TYPE) \ 448 \ 449 V(JS_FUNCTION_TYPE) \ 450 V(JS_FUNCTION_PROXY_TYPE) \ 451 V(DEBUG_INFO_TYPE) \ 452 V(BREAK_POINT_INFO_TYPE) 453 454 455 // Since string types are not consecutive, this macro is used to 456 // iterate over them. 457 #define STRING_TYPE_LIST(V) \ 458 V(STRING_TYPE, kVariableSizeSentinel, string, String) \ 459 V(ONE_BYTE_STRING_TYPE, kVariableSizeSentinel, one_byte_string, \ 460 OneByteString) \ 461 V(CONS_STRING_TYPE, ConsString::kSize, cons_string, ConsString) \ 462 V(CONS_ONE_BYTE_STRING_TYPE, ConsString::kSize, cons_one_byte_string, \ 463 ConsOneByteString) \ 464 V(SLICED_STRING_TYPE, SlicedString::kSize, sliced_string, SlicedString) \ 465 V(SLICED_ONE_BYTE_STRING_TYPE, SlicedString::kSize, sliced_one_byte_string, \ 466 SlicedOneByteString) \ 467 V(EXTERNAL_STRING_TYPE, ExternalTwoByteString::kSize, external_string, \ 468 ExternalString) \ 469 V(EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kSize, \ 470 external_one_byte_string, ExternalOneByteString) \ 471 V(EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, ExternalTwoByteString::kSize, \ 472 external_string_with_one_byte_data, ExternalStringWithOneByteData) \ 473 V(SHORT_EXTERNAL_STRING_TYPE, ExternalTwoByteString::kShortSize, \ 474 short_external_string, ShortExternalString) \ 475 V(SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE, ExternalOneByteString::kShortSize, \ 476 short_external_one_byte_string, ShortExternalOneByteString) \ 477 V(SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 478 ExternalTwoByteString::kShortSize, \ 479 short_external_string_with_one_byte_data, \ 480 ShortExternalStringWithOneByteData) \ 481 \ 482 V(INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, internalized_string, \ 483 InternalizedString) \ 484 V(ONE_BYTE_INTERNALIZED_STRING_TYPE, kVariableSizeSentinel, \ 485 one_byte_internalized_string, OneByteInternalizedString) \ 486 V(EXTERNAL_INTERNALIZED_STRING_TYPE, ExternalTwoByteString::kSize, \ 487 external_internalized_string, ExternalInternalizedString) \ 488 V(EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, ExternalOneByteString::kSize, \ 489 external_one_byte_internalized_string, ExternalOneByteInternalizedString) \ 490 V(EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 491 ExternalTwoByteString::kSize, \ 492 external_internalized_string_with_one_byte_data, \ 493 ExternalInternalizedStringWithOneByteData) \ 494 V(SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE, \ 495 ExternalTwoByteString::kShortSize, short_external_internalized_string, \ 496 ShortExternalInternalizedString) \ 497 V(SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE, \ 498 ExternalOneByteString::kShortSize, \ 499 short_external_one_byte_internalized_string, \ 500 ShortExternalOneByteInternalizedString) \ 501 V(SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE, \ 502 ExternalTwoByteString::kShortSize, \ 503 short_external_internalized_string_with_one_byte_data, \ 504 ShortExternalInternalizedStringWithOneByteData) 505 506 // A struct is a simple object a set of object-valued fields. Including an 507 // object type in this causes the compiler to generate most of the boilerplate 508 // code for the class including allocation and garbage collection routines, 509 // casts and predicates. All you need to define is the class, methods and 510 // object verification routines. Easy, no? 511 // 512 // Note that for subtle reasons related to the ordering or numerical values of 513 // type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST 514 // manually. 515 #define STRUCT_LIST(V) \ 516 V(BOX, Box, box) \ 517 V(DECLARED_ACCESSOR_DESCRIPTOR, \ 518 DeclaredAccessorDescriptor, \ 519 declared_accessor_descriptor) \ 520 V(DECLARED_ACCESSOR_INFO, DeclaredAccessorInfo, declared_accessor_info) \ 521 V(EXECUTABLE_ACCESSOR_INFO, ExecutableAccessorInfo, executable_accessor_info)\ 522 V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \ 523 V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \ 524 V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \ 525 V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \ 526 V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \ 527 V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \ 528 V(SIGNATURE_INFO, SignatureInfo, signature_info) \ 529 V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \ 530 V(SCRIPT, Script, script) \ 531 V(ALLOCATION_SITE, AllocationSite, allocation_site) \ 532 V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \ 533 V(CODE_CACHE, CodeCache, code_cache) \ 534 V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache) \ 535 V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \ 536 V(ALIASED_ARGUMENTS_ENTRY, AliasedArgumentsEntry, aliased_arguments_entry) \ 537 V(DEBUG_INFO, DebugInfo, debug_info) \ 538 V(BREAK_POINT_INFO, BreakPointInfo, break_point_info) 539 540 // We use the full 8 bits of the instance_type field to encode heap object 541 // instance types. The high-order bit (bit 7) is set if the object is not a 542 // string, and cleared if it is a string. 543 const uint32_t kIsNotStringMask = 0x80; 544 const uint32_t kStringTag = 0x0; 545 const uint32_t kNotStringTag = 0x80; 546 547 // Bit 6 indicates that the object is an internalized string (if set) or not. 548 // Bit 7 has to be clear as well. 549 const uint32_t kIsNotInternalizedMask = 0x40; 550 const uint32_t kNotInternalizedTag = 0x40; 551 const uint32_t kInternalizedTag = 0x0; 552 553 // If bit 7 is clear then bit 2 indicates whether the string consists of 554 // two-byte characters or one-byte characters. 555 const uint32_t kStringEncodingMask = 0x4; 556 const uint32_t kTwoByteStringTag = 0x0; 557 const uint32_t kOneByteStringTag = 0x4; 558 559 // If bit 7 is clear, the low-order 2 bits indicate the representation 560 // of the string. 561 const uint32_t kStringRepresentationMask = 0x03; 562 enum StringRepresentationTag { 563 kSeqStringTag = 0x0, 564 kConsStringTag = 0x1, 565 kExternalStringTag = 0x2, 566 kSlicedStringTag = 0x3 567 }; 568 const uint32_t kIsIndirectStringMask = 0x1; 569 const uint32_t kIsIndirectStringTag = 0x1; 570 STATIC_ASSERT((kSeqStringTag & kIsIndirectStringMask) == 0); // NOLINT 571 STATIC_ASSERT((kExternalStringTag & kIsIndirectStringMask) == 0); // NOLINT 572 STATIC_ASSERT((kConsStringTag & 573 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT 574 STATIC_ASSERT((kSlicedStringTag & 575 kIsIndirectStringMask) == kIsIndirectStringTag); // NOLINT 576 577 // Use this mask to distinguish between cons and slice only after making 578 // sure that the string is one of the two (an indirect string). 579 const uint32_t kSlicedNotConsMask = kSlicedStringTag & ~kConsStringTag; 580 STATIC_ASSERT(IS_POWER_OF_TWO(kSlicedNotConsMask)); 581 582 // If bit 7 is clear, then bit 3 indicates whether this two-byte 583 // string actually contains one byte data. 584 const uint32_t kOneByteDataHintMask = 0x08; 585 const uint32_t kOneByteDataHintTag = 0x08; 586 587 // If bit 7 is clear and string representation indicates an external string, 588 // then bit 4 indicates whether the data pointer is cached. 589 const uint32_t kShortExternalStringMask = 0x10; 590 const uint32_t kShortExternalStringTag = 0x10; 591 592 593 // A ConsString with an empty string as the right side is a candidate 594 // for being shortcut by the garbage collector. We don't allocate any 595 // non-flat internalized strings, so we do not shortcut them thereby 596 // avoiding turning internalized strings into strings. The bit-masks 597 // below contain the internalized bit as additional safety. 598 // See heap.cc, mark-compact.cc and objects-visiting.cc. 599 const uint32_t kShortcutTypeMask = 600 kIsNotStringMask | 601 kIsNotInternalizedMask | 602 kStringRepresentationMask; 603 const uint32_t kShortcutTypeTag = kConsStringTag | kNotInternalizedTag; 604 605 static inline bool IsShortcutCandidate(int type) { 606 return ((type & kShortcutTypeMask) == kShortcutTypeTag); 607 } 608 609 610 enum InstanceType { 611 // String types. 612 INTERNALIZED_STRING_TYPE = 613 kTwoByteStringTag | kSeqStringTag | kInternalizedTag, 614 ONE_BYTE_INTERNALIZED_STRING_TYPE = 615 kOneByteStringTag | kSeqStringTag | kInternalizedTag, 616 EXTERNAL_INTERNALIZED_STRING_TYPE = 617 kTwoByteStringTag | kExternalStringTag | kInternalizedTag, 618 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE = 619 kOneByteStringTag | kExternalStringTag | kInternalizedTag, 620 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE = 621 EXTERNAL_INTERNALIZED_STRING_TYPE | kOneByteDataHintTag | 622 kInternalizedTag, 623 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE = EXTERNAL_INTERNALIZED_STRING_TYPE | 624 kShortExternalStringTag | 625 kInternalizedTag, 626 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE = 627 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kShortExternalStringTag | 628 kInternalizedTag, 629 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE = 630 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 631 kShortExternalStringTag | kInternalizedTag, 632 STRING_TYPE = INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 633 ONE_BYTE_STRING_TYPE = 634 ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 635 CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag | kNotInternalizedTag, 636 CONS_ONE_BYTE_STRING_TYPE = 637 kOneByteStringTag | kConsStringTag | kNotInternalizedTag, 638 SLICED_STRING_TYPE = 639 kTwoByteStringTag | kSlicedStringTag | kNotInternalizedTag, 640 SLICED_ONE_BYTE_STRING_TYPE = 641 kOneByteStringTag | kSlicedStringTag | kNotInternalizedTag, 642 EXTERNAL_STRING_TYPE = 643 EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 644 EXTERNAL_ONE_BYTE_STRING_TYPE = 645 EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 646 EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE = 647 EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 648 kNotInternalizedTag, 649 SHORT_EXTERNAL_STRING_TYPE = 650 SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 651 SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE = 652 SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE | kNotInternalizedTag, 653 SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE = 654 SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE | 655 kNotInternalizedTag, 656 657 // Non-string names 658 SYMBOL_TYPE = kNotStringTag, // FIRST_NONSTRING_TYPE, LAST_NAME_TYPE 659 660 // Objects allocated in their own spaces (never in new space). 661 MAP_TYPE, 662 CODE_TYPE, 663 ODDBALL_TYPE, 664 CELL_TYPE, 665 PROPERTY_CELL_TYPE, 666 667 // "Data", objects that cannot contain non-map-word pointers to heap 668 // objects. 669 HEAP_NUMBER_TYPE, 670 MUTABLE_HEAP_NUMBER_TYPE, 671 FOREIGN_TYPE, 672 BYTE_ARRAY_TYPE, 673 FREE_SPACE_TYPE, 674 EXTERNAL_INT8_ARRAY_TYPE, // FIRST_EXTERNAL_ARRAY_TYPE 675 EXTERNAL_UINT8_ARRAY_TYPE, 676 EXTERNAL_INT16_ARRAY_TYPE, 677 EXTERNAL_UINT16_ARRAY_TYPE, 678 EXTERNAL_INT32_ARRAY_TYPE, 679 EXTERNAL_UINT32_ARRAY_TYPE, 680 EXTERNAL_FLOAT32_ARRAY_TYPE, 681 EXTERNAL_FLOAT64_ARRAY_TYPE, 682 EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE, // LAST_EXTERNAL_ARRAY_TYPE 683 FIXED_INT8_ARRAY_TYPE, // FIRST_FIXED_TYPED_ARRAY_TYPE 684 FIXED_UINT8_ARRAY_TYPE, 685 FIXED_INT16_ARRAY_TYPE, 686 FIXED_UINT16_ARRAY_TYPE, 687 FIXED_INT32_ARRAY_TYPE, 688 FIXED_UINT32_ARRAY_TYPE, 689 FIXED_FLOAT32_ARRAY_TYPE, 690 FIXED_FLOAT64_ARRAY_TYPE, 691 FIXED_UINT8_CLAMPED_ARRAY_TYPE, // LAST_FIXED_TYPED_ARRAY_TYPE 692 FIXED_DOUBLE_ARRAY_TYPE, 693 FILLER_TYPE, // LAST_DATA_TYPE 694 695 // Structs. 696 DECLARED_ACCESSOR_DESCRIPTOR_TYPE, 697 DECLARED_ACCESSOR_INFO_TYPE, 698 EXECUTABLE_ACCESSOR_INFO_TYPE, 699 ACCESSOR_PAIR_TYPE, 700 ACCESS_CHECK_INFO_TYPE, 701 INTERCEPTOR_INFO_TYPE, 702 CALL_HANDLER_INFO_TYPE, 703 FUNCTION_TEMPLATE_INFO_TYPE, 704 OBJECT_TEMPLATE_INFO_TYPE, 705 SIGNATURE_INFO_TYPE, 706 TYPE_SWITCH_INFO_TYPE, 707 ALLOCATION_SITE_TYPE, 708 ALLOCATION_MEMENTO_TYPE, 709 SCRIPT_TYPE, 710 CODE_CACHE_TYPE, 711 POLYMORPHIC_CODE_CACHE_TYPE, 712 TYPE_FEEDBACK_INFO_TYPE, 713 ALIASED_ARGUMENTS_ENTRY_TYPE, 714 BOX_TYPE, 715 DEBUG_INFO_TYPE, 716 BREAK_POINT_INFO_TYPE, 717 FIXED_ARRAY_TYPE, 718 CONSTANT_POOL_ARRAY_TYPE, 719 SHARED_FUNCTION_INFO_TYPE, 720 721 // All the following types are subtypes of JSReceiver, which corresponds to 722 // objects in the JS sense. The first and the last type in this range are 723 // the two forms of function. This organization enables using the same 724 // compares for checking the JS_RECEIVER/SPEC_OBJECT range and the 725 // NONCALLABLE_JS_OBJECT range. 726 JS_FUNCTION_PROXY_TYPE, // FIRST_JS_RECEIVER_TYPE, FIRST_JS_PROXY_TYPE 727 JS_PROXY_TYPE, // LAST_JS_PROXY_TYPE 728 JS_VALUE_TYPE, // FIRST_JS_OBJECT_TYPE 729 JS_MESSAGE_OBJECT_TYPE, 730 JS_DATE_TYPE, 731 JS_OBJECT_TYPE, 732 JS_CONTEXT_EXTENSION_OBJECT_TYPE, 733 JS_GENERATOR_OBJECT_TYPE, 734 JS_MODULE_TYPE, 735 JS_GLOBAL_OBJECT_TYPE, 736 JS_BUILTINS_OBJECT_TYPE, 737 JS_GLOBAL_PROXY_TYPE, 738 JS_ARRAY_TYPE, 739 JS_ARRAY_BUFFER_TYPE, 740 JS_TYPED_ARRAY_TYPE, 741 JS_DATA_VIEW_TYPE, 742 JS_SET_TYPE, 743 JS_MAP_TYPE, 744 JS_SET_ITERATOR_TYPE, 745 JS_MAP_ITERATOR_TYPE, 746 JS_WEAK_MAP_TYPE, 747 JS_WEAK_SET_TYPE, 748 JS_REGEXP_TYPE, 749 JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE 750 751 // Pseudo-types 752 FIRST_TYPE = 0x0, 753 LAST_TYPE = JS_FUNCTION_TYPE, 754 FIRST_NAME_TYPE = FIRST_TYPE, 755 LAST_NAME_TYPE = SYMBOL_TYPE, 756 FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE, 757 LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE, 758 FIRST_NONSTRING_TYPE = SYMBOL_TYPE, 759 // Boundaries for testing for an external array. 760 FIRST_EXTERNAL_ARRAY_TYPE = EXTERNAL_INT8_ARRAY_TYPE, 761 LAST_EXTERNAL_ARRAY_TYPE = EXTERNAL_UINT8_CLAMPED_ARRAY_TYPE, 762 // Boundaries for testing for a fixed typed array. 763 FIRST_FIXED_TYPED_ARRAY_TYPE = FIXED_INT8_ARRAY_TYPE, 764 LAST_FIXED_TYPED_ARRAY_TYPE = FIXED_UINT8_CLAMPED_ARRAY_TYPE, 765 // Boundary for promotion to old data space/old pointer space. 766 LAST_DATA_TYPE = FILLER_TYPE, 767 // Boundary for objects represented as JSReceiver (i.e. JSObject or JSProxy). 768 // Note that there is no range for JSObject or JSProxy, since their subtypes 769 // are not continuous in this enum! The enum ranges instead reflect the 770 // external class names, where proxies are treated as either ordinary objects, 771 // or functions. 772 FIRST_JS_RECEIVER_TYPE = JS_FUNCTION_PROXY_TYPE, 773 LAST_JS_RECEIVER_TYPE = LAST_TYPE, 774 // Boundaries for testing the types represented as JSObject 775 FIRST_JS_OBJECT_TYPE = JS_VALUE_TYPE, 776 LAST_JS_OBJECT_TYPE = LAST_TYPE, 777 // Boundaries for testing the types represented as JSProxy 778 FIRST_JS_PROXY_TYPE = JS_FUNCTION_PROXY_TYPE, 779 LAST_JS_PROXY_TYPE = JS_PROXY_TYPE, 780 // Boundaries for testing whether the type is a JavaScript object. 781 FIRST_SPEC_OBJECT_TYPE = FIRST_JS_RECEIVER_TYPE, 782 LAST_SPEC_OBJECT_TYPE = LAST_JS_RECEIVER_TYPE, 783 // Boundaries for testing the types for which typeof is "object". 784 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_PROXY_TYPE, 785 LAST_NONCALLABLE_SPEC_OBJECT_TYPE = JS_REGEXP_TYPE, 786 // Note that the types for which typeof is "function" are not continuous. 787 // Define this so that we can put assertions on discrete checks. 788 NUM_OF_CALLABLE_SPEC_OBJECT_TYPES = 2 789 }; 790 791 const int kExternalArrayTypeCount = 792 LAST_EXTERNAL_ARRAY_TYPE - FIRST_EXTERNAL_ARRAY_TYPE + 1; 793 794 STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType); 795 STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType); 796 STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType); 797 STATIC_ASSERT(FOREIGN_TYPE == Internals::kForeignType); 798 799 800 #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \ 801 V(FAST_ELEMENTS_SUB_TYPE) \ 802 V(DICTIONARY_ELEMENTS_SUB_TYPE) \ 803 V(FAST_PROPERTIES_SUB_TYPE) \ 804 V(DICTIONARY_PROPERTIES_SUB_TYPE) \ 805 V(MAP_CODE_CACHE_SUB_TYPE) \ 806 V(SCOPE_INFO_SUB_TYPE) \ 807 V(STRING_TABLE_SUB_TYPE) \ 808 V(DESCRIPTOR_ARRAY_SUB_TYPE) \ 809 V(TRANSITION_ARRAY_SUB_TYPE) 810 811 enum FixedArraySubInstanceType { 812 #define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name, 813 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE) 814 #undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE 815 LAST_FIXED_ARRAY_SUB_TYPE = TRANSITION_ARRAY_SUB_TYPE 816 }; 817 818 819 enum CompareResult { 820 LESS = -1, 821 EQUAL = 0, 822 GREATER = 1, 823 824 NOT_EQUAL = GREATER 825 }; 826 827 828 #define DECL_BOOLEAN_ACCESSORS(name) \ 829 inline bool name() const; \ 830 inline void set_##name(bool value); \ 831 832 833 #define DECL_ACCESSORS(name, type) \ 834 inline type* name() const; \ 835 inline void set_##name(type* value, \ 836 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \ 837 838 839 #define DECLARE_CAST(type) \ 840 INLINE(static type* cast(Object* object)); \ 841 INLINE(static const type* cast(const Object* object)); 842 843 844 class AccessorPair; 845 class AllocationSite; 846 class AllocationSiteCreationContext; 847 class AllocationSiteUsageContext; 848 class DictionaryElementsAccessor; 849 class ElementsAccessor; 850 class FixedArrayBase; 851 class GlobalObject; 852 class ObjectVisitor; 853 class LookupIterator; 854 class StringStream; 855 class TypeFeedbackVector; 856 // We cannot just say "class HeapType;" if it is created from a template... =8-? 857 template<class> class TypeImpl; 858 struct HeapTypeConfig; 859 typedef TypeImpl<HeapTypeConfig> HeapType; 860 861 862 // A template-ized version of the IsXXX functions. 863 template <class C> inline bool Is(Object* obj); 864 865 #ifdef VERIFY_HEAP 866 #define DECLARE_VERIFIER(Name) void Name##Verify(); 867 #else 868 #define DECLARE_VERIFIER(Name) 869 #endif 870 871 #ifdef OBJECT_PRINT 872 #define DECLARE_PRINTER(Name) void Name##Print(OStream& os); // NOLINT 873 #else 874 #define DECLARE_PRINTER(Name) 875 #endif 876 877 878 #define OBJECT_TYPE_LIST(V) \ 879 V(Smi) \ 880 V(HeapObject) \ 881 V(Number) 882 883 #define HEAP_OBJECT_TYPE_LIST(V) \ 884 V(HeapNumber) \ 885 V(MutableHeapNumber) \ 886 V(Name) \ 887 V(UniqueName) \ 888 V(String) \ 889 V(SeqString) \ 890 V(ExternalString) \ 891 V(ConsString) \ 892 V(SlicedString) \ 893 V(ExternalTwoByteString) \ 894 V(ExternalOneByteString) \ 895 V(SeqTwoByteString) \ 896 V(SeqOneByteString) \ 897 V(InternalizedString) \ 898 V(Symbol) \ 899 \ 900 V(ExternalArray) \ 901 V(ExternalInt8Array) \ 902 V(ExternalUint8Array) \ 903 V(ExternalInt16Array) \ 904 V(ExternalUint16Array) \ 905 V(ExternalInt32Array) \ 906 V(ExternalUint32Array) \ 907 V(ExternalFloat32Array) \ 908 V(ExternalFloat64Array) \ 909 V(ExternalUint8ClampedArray) \ 910 V(FixedTypedArrayBase) \ 911 V(FixedUint8Array) \ 912 V(FixedInt8Array) \ 913 V(FixedUint16Array) \ 914 V(FixedInt16Array) \ 915 V(FixedUint32Array) \ 916 V(FixedInt32Array) \ 917 V(FixedFloat32Array) \ 918 V(FixedFloat64Array) \ 919 V(FixedUint8ClampedArray) \ 920 V(ByteArray) \ 921 V(FreeSpace) \ 922 V(JSReceiver) \ 923 V(JSObject) \ 924 V(JSContextExtensionObject) \ 925 V(JSGeneratorObject) \ 926 V(JSModule) \ 927 V(Map) \ 928 V(DescriptorArray) \ 929 V(TransitionArray) \ 930 V(TypeFeedbackVector) \ 931 V(DeoptimizationInputData) \ 932 V(DeoptimizationOutputData) \ 933 V(DependentCode) \ 934 V(FixedArray) \ 935 V(FixedDoubleArray) \ 936 V(ConstantPoolArray) \ 937 V(Context) \ 938 V(NativeContext) \ 939 V(ScopeInfo) \ 940 V(JSFunction) \ 941 V(Code) \ 942 V(Oddball) \ 943 V(SharedFunctionInfo) \ 944 V(JSValue) \ 945 V(JSDate) \ 946 V(JSMessageObject) \ 947 V(StringWrapper) \ 948 V(Foreign) \ 949 V(Boolean) \ 950 V(JSArray) \ 951 V(JSArrayBuffer) \ 952 V(JSArrayBufferView) \ 953 V(JSTypedArray) \ 954 V(JSDataView) \ 955 V(JSProxy) \ 956 V(JSFunctionProxy) \ 957 V(JSSet) \ 958 V(JSMap) \ 959 V(JSSetIterator) \ 960 V(JSMapIterator) \ 961 V(JSWeakCollection) \ 962 V(JSWeakMap) \ 963 V(JSWeakSet) \ 964 V(JSRegExp) \ 965 V(HashTable) \ 966 V(Dictionary) \ 967 V(StringTable) \ 968 V(JSFunctionResultCache) \ 969 V(NormalizedMapCache) \ 970 V(CompilationCacheTable) \ 971 V(CodeCacheHashTable) \ 972 V(PolymorphicCodeCacheHashTable) \ 973 V(MapCache) \ 974 V(Primitive) \ 975 V(GlobalObject) \ 976 V(JSGlobalObject) \ 977 V(JSBuiltinsObject) \ 978 V(JSGlobalProxy) \ 979 V(UndetectableObject) \ 980 V(AccessCheckNeeded) \ 981 V(Cell) \ 982 V(PropertyCell) \ 983 V(ObjectHashTable) \ 984 V(WeakHashTable) \ 985 V(OrderedHashTable) 986 987 // Object is the abstract superclass for all classes in the 988 // object hierarchy. 989 // Object does not use any virtual functions to avoid the 990 // allocation of the C++ vtable. 991 // Since both Smi and HeapObject are subclasses of Object no 992 // data members can be present in Object. 993 class Object { 994 public: 995 // Type testing. 996 bool IsObject() const { return true; } 997 998 #define IS_TYPE_FUNCTION_DECL(type_) INLINE(bool Is##type_() const); 999 OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) 1000 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL) 1001 #undef IS_TYPE_FUNCTION_DECL 1002 1003 // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas 1004 // a keyed store is of the form a[expression] = foo. 1005 enum StoreFromKeyed { 1006 MAY_BE_STORE_FROM_KEYED, 1007 CERTAINLY_NOT_STORE_FROM_KEYED 1008 }; 1009 1010 INLINE(bool IsFixedArrayBase() const); 1011 INLINE(bool IsExternal() const); 1012 INLINE(bool IsAccessorInfo() const); 1013 1014 INLINE(bool IsStruct() const); 1015 #define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \ 1016 INLINE(bool Is##Name() const); 1017 STRUCT_LIST(DECLARE_STRUCT_PREDICATE) 1018 #undef DECLARE_STRUCT_PREDICATE 1019 1020 INLINE(bool IsSpecObject()) const; 1021 INLINE(bool IsSpecFunction()) const; 1022 INLINE(bool IsTemplateInfo()) const; 1023 INLINE(bool IsNameDictionary() const); 1024 INLINE(bool IsSeededNumberDictionary() const); 1025 INLINE(bool IsUnseededNumberDictionary() const); 1026 INLINE(bool IsOrderedHashSet() const); 1027 INLINE(bool IsOrderedHashMap() const); 1028 bool IsCallable() const; 1029 1030 // Oddball testing. 1031 INLINE(bool IsUndefined() const); 1032 INLINE(bool IsNull() const); 1033 INLINE(bool IsTheHole() const); 1034 INLINE(bool IsException() const); 1035 INLINE(bool IsUninitialized() const); 1036 INLINE(bool IsTrue() const); 1037 INLINE(bool IsFalse() const); 1038 INLINE(bool IsArgumentsMarker() const); 1039 1040 // Filler objects (fillers and free space objects). 1041 INLINE(bool IsFiller() const); 1042 1043 // Extract the number. 1044 inline double Number(); 1045 INLINE(bool IsNaN() const); 1046 INLINE(bool IsMinusZero() const); 1047 bool ToInt32(int32_t* value); 1048 bool ToUint32(uint32_t* value); 1049 1050 inline Representation OptimalRepresentation() { 1051 if (!FLAG_track_fields) return Representation::Tagged(); 1052 if (IsSmi()) { 1053 return Representation::Smi(); 1054 } else if (FLAG_track_double_fields && IsHeapNumber()) { 1055 return Representation::Double(); 1056 } else if (FLAG_track_computed_fields && IsUninitialized()) { 1057 return Representation::None(); 1058 } else if (FLAG_track_heap_object_fields) { 1059 DCHECK(IsHeapObject()); 1060 return Representation::HeapObject(); 1061 } else { 1062 return Representation::Tagged(); 1063 } 1064 } 1065 1066 inline bool FitsRepresentation(Representation representation) { 1067 if (FLAG_track_fields && representation.IsNone()) { 1068 return false; 1069 } else if (FLAG_track_fields && representation.IsSmi()) { 1070 return IsSmi(); 1071 } else if (FLAG_track_double_fields && representation.IsDouble()) { 1072 return IsMutableHeapNumber() || IsNumber(); 1073 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 1074 return IsHeapObject(); 1075 } 1076 return true; 1077 } 1078 1079 Handle<HeapType> OptimalType(Isolate* isolate, Representation representation); 1080 1081 inline static Handle<Object> NewStorageFor(Isolate* isolate, 1082 Handle<Object> object, 1083 Representation representation); 1084 1085 inline static Handle<Object> WrapForRead(Isolate* isolate, 1086 Handle<Object> object, 1087 Representation representation); 1088 1089 // Returns true if the object is of the correct type to be used as a 1090 // implementation of a JSObject's elements. 1091 inline bool HasValidElements(); 1092 1093 inline bool HasSpecificClassOf(String* name); 1094 1095 bool BooleanValue(); // ECMA-262 9.2. 1096 1097 // Convert to a JSObject if needed. 1098 // native_context is used when creating wrapper object. 1099 static inline MaybeHandle<JSReceiver> ToObject(Isolate* isolate, 1100 Handle<Object> object); 1101 static MaybeHandle<JSReceiver> ToObject(Isolate* isolate, 1102 Handle<Object> object, 1103 Handle<Context> context); 1104 1105 // Converts this to a Smi if possible. 1106 static MUST_USE_RESULT inline MaybeHandle<Smi> ToSmi(Isolate* isolate, 1107 Handle<Object> object); 1108 1109 MUST_USE_RESULT static MaybeHandle<Object> GetProperty(LookupIterator* it); 1110 1111 // Implementation of [[Put]], ECMA-262 5th edition, section 8.12.5. 1112 MUST_USE_RESULT static MaybeHandle<Object> SetProperty( 1113 Handle<Object> object, Handle<Name> key, Handle<Object> value, 1114 StrictMode strict_mode, 1115 StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED); 1116 1117 MUST_USE_RESULT static MaybeHandle<Object> SetProperty( 1118 LookupIterator* it, Handle<Object> value, StrictMode strict_mode, 1119 StoreFromKeyed store_mode); 1120 MUST_USE_RESULT static MaybeHandle<Object> WriteToReadOnlyProperty( 1121 LookupIterator* it, Handle<Object> value, StrictMode strict_mode); 1122 static Handle<Object> SetDataProperty(LookupIterator* it, 1123 Handle<Object> value); 1124 MUST_USE_RESULT static MaybeHandle<Object> AddDataProperty( 1125 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 1126 StrictMode strict_mode, StoreFromKeyed store_mode); 1127 MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement( 1128 Handle<Object> object, 1129 Handle<Name> key); 1130 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( 1131 Isolate* isolate, 1132 Handle<Object> object, 1133 const char* key); 1134 MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty( 1135 Handle<Object> object, 1136 Handle<Name> key); 1137 1138 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithAccessor( 1139 Handle<Object> receiver, 1140 Handle<Name> name, 1141 Handle<JSObject> holder, 1142 Handle<Object> structure); 1143 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithAccessor( 1144 Handle<Object> receiver, Handle<Name> name, Handle<Object> value, 1145 Handle<JSObject> holder, Handle<Object> structure, 1146 StrictMode strict_mode); 1147 1148 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter( 1149 Handle<Object> receiver, 1150 Handle<JSReceiver> getter); 1151 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithDefinedSetter( 1152 Handle<Object> receiver, 1153 Handle<JSReceiver> setter, 1154 Handle<Object> value); 1155 1156 MUST_USE_RESULT static inline MaybeHandle<Object> GetElement( 1157 Isolate* isolate, 1158 Handle<Object> object, 1159 uint32_t index); 1160 1161 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithReceiver( 1162 Isolate* isolate, 1163 Handle<Object> object, 1164 Handle<Object> receiver, 1165 uint32_t index); 1166 1167 // Returns the permanent hash code associated with this object. May return 1168 // undefined if not yet created. 1169 Object* GetHash(); 1170 1171 // Returns the permanent hash code associated with this object depending on 1172 // the actual object type. May create and store a hash code if needed and none 1173 // exists. 1174 static Handle<Smi> GetOrCreateHash(Isolate* isolate, Handle<Object> object); 1175 1176 // Checks whether this object has the same value as the given one. This 1177 // function is implemented according to ES5, section 9.12 and can be used 1178 // to implement the Harmony "egal" function. 1179 bool SameValue(Object* other); 1180 1181 // Checks whether this object has the same value as the given one. 1182 // +0 and -0 are treated equal. Everything else is the same as SameValue. 1183 // This function is implemented according to ES6, section 7.2.4 and is used 1184 // by ES6 Map and Set. 1185 bool SameValueZero(Object* other); 1186 1187 // Tries to convert an object to an array index. Returns true and sets 1188 // the output parameter if it succeeds. 1189 inline bool ToArrayIndex(uint32_t* index); 1190 1191 // Returns true if this is a JSValue containing a string and the index is 1192 // < the length of the string. Used to implement [] on strings. 1193 inline bool IsStringObjectWithCharacterAt(uint32_t index); 1194 1195 DECLARE_VERIFIER(Object) 1196 #ifdef VERIFY_HEAP 1197 // Verify a pointer is a valid object pointer. 1198 static void VerifyPointer(Object* p); 1199 #endif 1200 1201 inline void VerifyApiCallResultType(); 1202 1203 // Prints this object without details. 1204 void ShortPrint(FILE* out = stdout); 1205 1206 // Prints this object without details to a message accumulator. 1207 void ShortPrint(StringStream* accumulator); 1208 1209 DECLARE_CAST(Object) 1210 1211 // Layout description. 1212 static const int kHeaderSize = 0; // Object does not take up any space. 1213 1214 #ifdef OBJECT_PRINT 1215 // For our gdb macros, we should perhaps change these in the future. 1216 void Print(); 1217 1218 // Prints this object with details. 1219 void Print(OStream& os); // NOLINT 1220 #endif 1221 1222 private: 1223 friend class LookupIterator; 1224 friend class PrototypeIterator; 1225 1226 // Return the map of the root of object's prototype chain. 1227 Map* GetRootMap(Isolate* isolate); 1228 1229 DISALLOW_IMPLICIT_CONSTRUCTORS(Object); 1230 }; 1231 1232 1233 struct Brief { 1234 explicit Brief(const Object* const v) : value(v) {} 1235 const Object* value; 1236 }; 1237 1238 1239 OStream& operator<<(OStream& os, const Brief& v); 1240 1241 1242 // Smi represents integer Numbers that can be stored in 31 bits. 1243 // Smis are immediate which means they are NOT allocated in the heap. 1244 // The this pointer has the following format: [31 bit signed int] 0 1245 // For long smis it has the following format: 1246 // [32 bit signed int] [31 bits zero padding] 0 1247 // Smi stands for small integer. 1248 class Smi: public Object { 1249 public: 1250 // Returns the integer value. 1251 inline int value() const; 1252 1253 // Convert a value to a Smi object. 1254 static inline Smi* FromInt(int value); 1255 1256 static inline Smi* FromIntptr(intptr_t value); 1257 1258 // Returns whether value can be represented in a Smi. 1259 static inline bool IsValid(intptr_t value); 1260 1261 DECLARE_CAST(Smi) 1262 1263 // Dispatched behavior. 1264 void SmiPrint(OStream& os) const; // NOLINT 1265 DECLARE_VERIFIER(Smi) 1266 1267 static const int kMinValue = 1268 (static_cast<unsigned int>(-1)) << (kSmiValueSize - 1); 1269 static const int kMaxValue = -(kMinValue + 1); 1270 1271 private: 1272 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi); 1273 }; 1274 1275 1276 // Heap objects typically have a map pointer in their first word. However, 1277 // during GC other data (e.g. mark bits, forwarding addresses) is sometimes 1278 // encoded in the first word. The class MapWord is an abstraction of the 1279 // value in a heap object's first word. 1280 class MapWord BASE_EMBEDDED { 1281 public: 1282 // Normal state: the map word contains a map pointer. 1283 1284 // Create a map word from a map pointer. 1285 static inline MapWord FromMap(const Map* map); 1286 1287 // View this map word as a map pointer. 1288 inline Map* ToMap(); 1289 1290 1291 // Scavenge collection: the map word of live objects in the from space 1292 // contains a forwarding address (a heap object pointer in the to space). 1293 1294 // True if this map word is a forwarding address for a scavenge 1295 // collection. Only valid during a scavenge collection (specifically, 1296 // when all map words are heap object pointers, i.e. not during a full GC). 1297 inline bool IsForwardingAddress(); 1298 1299 // Create a map word from a forwarding address. 1300 static inline MapWord FromForwardingAddress(HeapObject* object); 1301 1302 // View this map word as a forwarding address. 1303 inline HeapObject* ToForwardingAddress(); 1304 1305 static inline MapWord FromRawValue(uintptr_t value) { 1306 return MapWord(value); 1307 } 1308 1309 inline uintptr_t ToRawValue() { 1310 return value_; 1311 } 1312 1313 private: 1314 // HeapObject calls the private constructor and directly reads the value. 1315 friend class HeapObject; 1316 1317 explicit MapWord(uintptr_t value) : value_(value) {} 1318 1319 uintptr_t value_; 1320 }; 1321 1322 1323 // HeapObject is the superclass for all classes describing heap allocated 1324 // objects. 1325 class HeapObject: public Object { 1326 public: 1327 // [map]: Contains a map which contains the object's reflective 1328 // information. 1329 inline Map* map() const; 1330 inline void set_map(Map* value); 1331 // The no-write-barrier version. This is OK if the object is white and in 1332 // new space, or if the value is an immortal immutable object, like the maps 1333 // of primitive (non-JS) objects like strings, heap numbers etc. 1334 inline void set_map_no_write_barrier(Map* value); 1335 1336 // Get the map using acquire load. 1337 inline Map* synchronized_map(); 1338 inline MapWord synchronized_map_word() const; 1339 1340 // Set the map using release store 1341 inline void synchronized_set_map(Map* value); 1342 inline void synchronized_set_map_no_write_barrier(Map* value); 1343 inline void synchronized_set_map_word(MapWord map_word); 1344 1345 // During garbage collection, the map word of a heap object does not 1346 // necessarily contain a map pointer. 1347 inline MapWord map_word() const; 1348 inline void set_map_word(MapWord map_word); 1349 1350 // The Heap the object was allocated in. Used also to access Isolate. 1351 inline Heap* GetHeap() const; 1352 1353 // Convenience method to get current isolate. 1354 inline Isolate* GetIsolate() const; 1355 1356 // Converts an address to a HeapObject pointer. 1357 static inline HeapObject* FromAddress(Address address); 1358 1359 // Returns the address of this HeapObject. 1360 inline Address address(); 1361 1362 // Iterates over pointers contained in the object (including the Map) 1363 void Iterate(ObjectVisitor* v); 1364 1365 // Iterates over all pointers contained in the object except the 1366 // first map pointer. The object type is given in the first 1367 // parameter. This function does not access the map pointer in the 1368 // object, and so is safe to call while the map pointer is modified. 1369 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v); 1370 1371 // Returns the heap object's size in bytes 1372 inline int Size(); 1373 1374 // Returns true if this heap object may contain raw values, i.e., values that 1375 // look like pointers to heap objects. 1376 inline bool MayContainRawValues(); 1377 1378 // Given a heap object's map pointer, returns the heap size in bytes 1379 // Useful when the map pointer field is used for other purposes. 1380 // GC internal. 1381 inline int SizeFromMap(Map* map); 1382 1383 // Returns the field at offset in obj, as a read/write Object* reference. 1384 // Does no checking, and is safe to use during GC, while maps are invalid. 1385 // Does not invoke write barrier, so should only be assigned to 1386 // during marking GC. 1387 static inline Object** RawField(HeapObject* obj, int offset); 1388 1389 // Adds the |code| object related to |name| to the code cache of this map. If 1390 // this map is a dictionary map that is shared, the map copied and installed 1391 // onto the object. 1392 static void UpdateMapCodeCache(Handle<HeapObject> object, 1393 Handle<Name> name, 1394 Handle<Code> code); 1395 1396 DECLARE_CAST(HeapObject) 1397 1398 // Return the write barrier mode for this. Callers of this function 1399 // must be able to present a reference to an DisallowHeapAllocation 1400 // object as a sign that they are not going to use this function 1401 // from code that allocates and thus invalidates the returned write 1402 // barrier mode. 1403 inline WriteBarrierMode GetWriteBarrierMode( 1404 const DisallowHeapAllocation& promise); 1405 1406 // Dispatched behavior. 1407 void HeapObjectShortPrint(OStream& os); // NOLINT 1408 #ifdef OBJECT_PRINT 1409 void PrintHeader(OStream& os, const char* id); // NOLINT 1410 #endif 1411 DECLARE_PRINTER(HeapObject) 1412 DECLARE_VERIFIER(HeapObject) 1413 #ifdef VERIFY_HEAP 1414 inline void VerifyObjectField(int offset); 1415 inline void VerifySmiField(int offset); 1416 1417 // Verify a pointer is a valid HeapObject pointer that points to object 1418 // areas in the heap. 1419 static void VerifyHeapPointer(Object* p); 1420 #endif 1421 1422 // Layout description. 1423 // First field in a heap object is map. 1424 static const int kMapOffset = Object::kHeaderSize; 1425 static const int kHeaderSize = kMapOffset + kPointerSize; 1426 1427 STATIC_ASSERT(kMapOffset == Internals::kHeapObjectMapOffset); 1428 1429 protected: 1430 // helpers for calling an ObjectVisitor to iterate over pointers in the 1431 // half-open range [start, end) specified as integer offsets 1432 inline void IteratePointers(ObjectVisitor* v, int start, int end); 1433 // as above, for the single element at "offset" 1434 inline void IteratePointer(ObjectVisitor* v, int offset); 1435 // as above, for the next code link of a code object. 1436 inline void IterateNextCodeLink(ObjectVisitor* v, int offset); 1437 1438 private: 1439 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject); 1440 }; 1441 1442 1443 // This class describes a body of an object of a fixed size 1444 // in which all pointer fields are located in the [start_offset, end_offset) 1445 // interval. 1446 template<int start_offset, int end_offset, int size> 1447 class FixedBodyDescriptor { 1448 public: 1449 static const int kStartOffset = start_offset; 1450 static const int kEndOffset = end_offset; 1451 static const int kSize = size; 1452 1453 static inline void IterateBody(HeapObject* obj, ObjectVisitor* v); 1454 1455 template<typename StaticVisitor> 1456 static inline void IterateBody(HeapObject* obj) { 1457 StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset), 1458 HeapObject::RawField(obj, end_offset)); 1459 } 1460 }; 1461 1462 1463 // This class describes a body of an object of a variable size 1464 // in which all pointer fields are located in the [start_offset, object_size) 1465 // interval. 1466 template<int start_offset> 1467 class FlexibleBodyDescriptor { 1468 public: 1469 static const int kStartOffset = start_offset; 1470 1471 static inline void IterateBody(HeapObject* obj, 1472 int object_size, 1473 ObjectVisitor* v); 1474 1475 template<typename StaticVisitor> 1476 static inline void IterateBody(HeapObject* obj, int object_size) { 1477 StaticVisitor::VisitPointers(HeapObject::RawField(obj, start_offset), 1478 HeapObject::RawField(obj, object_size)); 1479 } 1480 }; 1481 1482 1483 // The HeapNumber class describes heap allocated numbers that cannot be 1484 // represented in a Smi (small integer) 1485 class HeapNumber: public HeapObject { 1486 public: 1487 // [value]: number value. 1488 inline double value() const; 1489 inline void set_value(double value); 1490 1491 DECLARE_CAST(HeapNumber) 1492 1493 // Dispatched behavior. 1494 bool HeapNumberBooleanValue(); 1495 1496 void HeapNumberPrint(OStream& os); // NOLINT 1497 DECLARE_VERIFIER(HeapNumber) 1498 1499 inline int get_exponent(); 1500 inline int get_sign(); 1501 1502 // Layout description. 1503 static const int kValueOffset = HeapObject::kHeaderSize; 1504 // IEEE doubles are two 32 bit words. The first is just mantissa, the second 1505 // is a mixture of sign, exponent and mantissa. The offsets of two 32 bit 1506 // words within double numbers are endian dependent and they are set 1507 // accordingly. 1508 #if defined(V8_TARGET_LITTLE_ENDIAN) 1509 static const int kMantissaOffset = kValueOffset; 1510 static const int kExponentOffset = kValueOffset + 4; 1511 #elif defined(V8_TARGET_BIG_ENDIAN) 1512 static const int kMantissaOffset = kValueOffset + 4; 1513 static const int kExponentOffset = kValueOffset; 1514 #else 1515 #error Unknown byte ordering 1516 #endif 1517 1518 static const int kSize = kValueOffset + kDoubleSize; 1519 static const uint32_t kSignMask = 0x80000000u; 1520 static const uint32_t kExponentMask = 0x7ff00000u; 1521 static const uint32_t kMantissaMask = 0xfffffu; 1522 static const int kMantissaBits = 52; 1523 static const int kExponentBits = 11; 1524 static const int kExponentBias = 1023; 1525 static const int kExponentShift = 20; 1526 static const int kInfinityOrNanExponent = 1527 (kExponentMask >> kExponentShift) - kExponentBias; 1528 static const int kMantissaBitsInTopWord = 20; 1529 static const int kNonMantissaBitsInTopWord = 12; 1530 1531 private: 1532 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber); 1533 }; 1534 1535 1536 enum EnsureElementsMode { 1537 DONT_ALLOW_DOUBLE_ELEMENTS, 1538 ALLOW_COPIED_DOUBLE_ELEMENTS, 1539 ALLOW_CONVERTED_DOUBLE_ELEMENTS 1540 }; 1541 1542 1543 // Indicates whether a property should be set or (re)defined. Setting of a 1544 // property causes attributes to remain unchanged, writability to be checked 1545 // and callbacks to be called. Defining of a property causes attributes to 1546 // be updated and callbacks to be overridden. 1547 enum SetPropertyMode { 1548 SET_PROPERTY, 1549 DEFINE_PROPERTY 1550 }; 1551 1552 1553 // Indicator for one component of an AccessorPair. 1554 enum AccessorComponent { 1555 ACCESSOR_GETTER, 1556 ACCESSOR_SETTER 1557 }; 1558 1559 1560 // JSReceiver includes types on which properties can be defined, i.e., 1561 // JSObject and JSProxy. 1562 class JSReceiver: public HeapObject { 1563 public: 1564 enum DeleteMode { 1565 NORMAL_DELETION, 1566 STRICT_DELETION, 1567 FORCE_DELETION 1568 }; 1569 1570 DECLARE_CAST(JSReceiver) 1571 1572 MUST_USE_RESULT static MaybeHandle<Object> SetElement( 1573 Handle<JSReceiver> object, 1574 uint32_t index, 1575 Handle<Object> value, 1576 PropertyAttributes attributes, 1577 StrictMode strict_mode); 1578 1579 // Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6. 1580 MUST_USE_RESULT static inline Maybe<bool> HasProperty( 1581 Handle<JSReceiver> object, Handle<Name> name); 1582 MUST_USE_RESULT static inline Maybe<bool> HasOwnProperty(Handle<JSReceiver>, 1583 Handle<Name> name); 1584 MUST_USE_RESULT static inline Maybe<bool> HasElement( 1585 Handle<JSReceiver> object, uint32_t index); 1586 MUST_USE_RESULT static inline Maybe<bool> HasOwnElement( 1587 Handle<JSReceiver> object, uint32_t index); 1588 1589 // Implementation of [[Delete]], ECMA-262 5th edition, section 8.12.7. 1590 MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty( 1591 Handle<JSReceiver> object, 1592 Handle<Name> name, 1593 DeleteMode mode = NORMAL_DELETION); 1594 MUST_USE_RESULT static MaybeHandle<Object> DeleteElement( 1595 Handle<JSReceiver> object, 1596 uint32_t index, 1597 DeleteMode mode = NORMAL_DELETION); 1598 1599 // Tests for the fast common case for property enumeration. 1600 bool IsSimpleEnum(); 1601 1602 // Returns the class name ([[Class]] property in the specification). 1603 String* class_name(); 1604 1605 // Returns the constructor name (the name (possibly, inferred name) of the 1606 // function that was used to instantiate the object). 1607 String* constructor_name(); 1608 1609 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetPropertyAttributes( 1610 Handle<JSReceiver> object, Handle<Name> name); 1611 MUST_USE_RESULT static Maybe<PropertyAttributes> GetPropertyAttributes( 1612 LookupIterator* it); 1613 MUST_USE_RESULT static Maybe<PropertyAttributes> GetOwnPropertyAttributes( 1614 Handle<JSReceiver> object, Handle<Name> name); 1615 1616 MUST_USE_RESULT static inline Maybe<PropertyAttributes> GetElementAttribute( 1617 Handle<JSReceiver> object, uint32_t index); 1618 MUST_USE_RESULT static inline Maybe<PropertyAttributes> 1619 GetOwnElementAttribute(Handle<JSReceiver> object, uint32_t index); 1620 1621 // Return the constructor function (may be Heap::null_value()). 1622 inline Object* GetConstructor(); 1623 1624 // Retrieves a permanent object identity hash code. The undefined value might 1625 // be returned in case no hash was created yet. 1626 inline Object* GetIdentityHash(); 1627 1628 // Retrieves a permanent object identity hash code. May create and store a 1629 // hash code if needed and none exists. 1630 inline static Handle<Smi> GetOrCreateIdentityHash( 1631 Handle<JSReceiver> object); 1632 1633 enum KeyCollectionType { OWN_ONLY, INCLUDE_PROTOS }; 1634 1635 // Computes the enumerable keys for a JSObject. Used for implementing 1636 // "for (n in object) { }". 1637 MUST_USE_RESULT static MaybeHandle<FixedArray> GetKeys( 1638 Handle<JSReceiver> object, 1639 KeyCollectionType type); 1640 1641 private: 1642 DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver); 1643 }; 1644 1645 // Forward declaration for JSObject::GetOrCreateHiddenPropertiesHashTable. 1646 class ObjectHashTable; 1647 1648 // Forward declaration for JSObject::Copy. 1649 class AllocationSite; 1650 1651 1652 // The JSObject describes real heap allocated JavaScript objects with 1653 // properties. 1654 // Note that the map of JSObject changes during execution to enable inline 1655 // caching. 1656 class JSObject: public JSReceiver { 1657 public: 1658 // [properties]: Backing storage for properties. 1659 // properties is a FixedArray in the fast case and a Dictionary in the 1660 // slow case. 1661 DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties. 1662 inline void initialize_properties(); 1663 inline bool HasFastProperties(); 1664 inline NameDictionary* property_dictionary(); // Gets slow properties. 1665 1666 // [elements]: The elements (properties with names that are integers). 1667 // 1668 // Elements can be in two general modes: fast and slow. Each mode 1669 // corrensponds to a set of object representations of elements that 1670 // have something in common. 1671 // 1672 // In the fast mode elements is a FixedArray and so each element can 1673 // be quickly accessed. This fact is used in the generated code. The 1674 // elements array can have one of three maps in this mode: 1675 // fixed_array_map, sloppy_arguments_elements_map or 1676 // fixed_cow_array_map (for copy-on-write arrays). In the latter case 1677 // the elements array may be shared by a few objects and so before 1678 // writing to any element the array must be copied. Use 1679 // EnsureWritableFastElements in this case. 1680 // 1681 // In the slow mode the elements is either a NumberDictionary, an 1682 // ExternalArray, or a FixedArray parameter map for a (sloppy) 1683 // arguments object. 1684 DECL_ACCESSORS(elements, FixedArrayBase) 1685 inline void initialize_elements(); 1686 static void ResetElements(Handle<JSObject> object); 1687 static inline void SetMapAndElements(Handle<JSObject> object, 1688 Handle<Map> map, 1689 Handle<FixedArrayBase> elements); 1690 inline ElementsKind GetElementsKind(); 1691 inline ElementsAccessor* GetElementsAccessor(); 1692 // Returns true if an object has elements of FAST_SMI_ELEMENTS ElementsKind. 1693 inline bool HasFastSmiElements(); 1694 // Returns true if an object has elements of FAST_ELEMENTS ElementsKind. 1695 inline bool HasFastObjectElements(); 1696 // Returns true if an object has elements of FAST_ELEMENTS or 1697 // FAST_SMI_ONLY_ELEMENTS. 1698 inline bool HasFastSmiOrObjectElements(); 1699 // Returns true if an object has any of the fast elements kinds. 1700 inline bool HasFastElements(); 1701 // Returns true if an object has elements of FAST_DOUBLE_ELEMENTS 1702 // ElementsKind. 1703 inline bool HasFastDoubleElements(); 1704 // Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS 1705 // ElementsKind. 1706 inline bool HasFastHoleyElements(); 1707 inline bool HasSloppyArgumentsElements(); 1708 inline bool HasDictionaryElements(); 1709 1710 inline bool HasExternalUint8ClampedElements(); 1711 inline bool HasExternalArrayElements(); 1712 inline bool HasExternalInt8Elements(); 1713 inline bool HasExternalUint8Elements(); 1714 inline bool HasExternalInt16Elements(); 1715 inline bool HasExternalUint16Elements(); 1716 inline bool HasExternalInt32Elements(); 1717 inline bool HasExternalUint32Elements(); 1718 inline bool HasExternalFloat32Elements(); 1719 inline bool HasExternalFloat64Elements(); 1720 1721 inline bool HasFixedTypedArrayElements(); 1722 1723 inline bool HasFixedUint8ClampedElements(); 1724 inline bool HasFixedArrayElements(); 1725 inline bool HasFixedInt8Elements(); 1726 inline bool HasFixedUint8Elements(); 1727 inline bool HasFixedInt16Elements(); 1728 inline bool HasFixedUint16Elements(); 1729 inline bool HasFixedInt32Elements(); 1730 inline bool HasFixedUint32Elements(); 1731 inline bool HasFixedFloat32Elements(); 1732 inline bool HasFixedFloat64Elements(); 1733 1734 bool HasFastArgumentsElements(); 1735 bool HasDictionaryArgumentsElements(); 1736 inline SeededNumberDictionary* element_dictionary(); // Gets slow elements. 1737 1738 // Requires: HasFastElements(). 1739 static Handle<FixedArray> EnsureWritableFastElements( 1740 Handle<JSObject> object); 1741 1742 // Collects elements starting at index 0. 1743 // Undefined values are placed after non-undefined values. 1744 // Returns the number of non-undefined values. 1745 static Handle<Object> PrepareElementsForSort(Handle<JSObject> object, 1746 uint32_t limit); 1747 // As PrepareElementsForSort, but only on objects where elements is 1748 // a dictionary, and it will stay a dictionary. Collates undefined and 1749 // unexisting elements below limit from position zero of the elements. 1750 static Handle<Object> PrepareSlowElementsForSort(Handle<JSObject> object, 1751 uint32_t limit); 1752 1753 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithInterceptor( 1754 LookupIterator* it, Handle<Object> value); 1755 1756 // SetLocalPropertyIgnoreAttributes converts callbacks to fields. We need to 1757 // grant an exemption to ExecutableAccessor callbacks in some cases. 1758 enum ExecutableAccessorInfoHandling { 1759 DEFAULT_HANDLING, 1760 DONT_FORCE_FIELD 1761 }; 1762 1763 MUST_USE_RESULT static MaybeHandle<Object> SetOwnPropertyIgnoreAttributes( 1764 Handle<JSObject> object, 1765 Handle<Name> key, 1766 Handle<Object> value, 1767 PropertyAttributes attributes, 1768 ExecutableAccessorInfoHandling handling = DEFAULT_HANDLING); 1769 1770 static void AddProperty(Handle<JSObject> object, Handle<Name> key, 1771 Handle<Object> value, PropertyAttributes attributes); 1772 1773 // Extend the receiver with a single fast property appeared first in the 1774 // passed map. This also extends the property backing store if necessary. 1775 static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map); 1776 1777 // Migrates the given object to a map whose field representations are the 1778 // lowest upper bound of all known representations for that field. 1779 static void MigrateInstance(Handle<JSObject> instance); 1780 1781 // Migrates the given object only if the target map is already available, 1782 // or returns false if such a map is not yet available. 1783 static bool TryMigrateInstance(Handle<JSObject> instance); 1784 1785 // Sets the property value in a normalized object given (key, value, details). 1786 // Handles the special representation of JS global objects. 1787 static void SetNormalizedProperty(Handle<JSObject> object, 1788 Handle<Name> key, 1789 Handle<Object> value, 1790 PropertyDetails details); 1791 1792 static void OptimizeAsPrototype(Handle<JSObject> object, 1793 PrototypeOptimizationMode mode); 1794 static void ReoptimizeIfPrototype(Handle<JSObject> object); 1795 1796 // Retrieve interceptors. 1797 InterceptorInfo* GetNamedInterceptor(); 1798 InterceptorInfo* GetIndexedInterceptor(); 1799 1800 // Used from JSReceiver. 1801 MUST_USE_RESULT static Maybe<PropertyAttributes> 1802 GetPropertyAttributesWithInterceptor(Handle<JSObject> holder, 1803 Handle<Object> receiver, 1804 Handle<Name> name); 1805 MUST_USE_RESULT static Maybe<PropertyAttributes> 1806 GetPropertyAttributesWithFailedAccessCheck(LookupIterator* it); 1807 MUST_USE_RESULT static Maybe<PropertyAttributes> 1808 GetElementAttributeWithReceiver(Handle<JSObject> object, 1809 Handle<JSReceiver> receiver, 1810 uint32_t index, bool check_prototype); 1811 1812 // Retrieves an AccessorPair property from the given object. Might return 1813 // undefined if the property doesn't exist or is of a different kind. 1814 MUST_USE_RESULT static MaybeHandle<Object> GetAccessor( 1815 Handle<JSObject> object, 1816 Handle<Name> name, 1817 AccessorComponent component); 1818 1819 // Defines an AccessorPair property on the given object. 1820 // TODO(mstarzinger): Rename to SetAccessor(). 1821 static MaybeHandle<Object> DefineAccessor(Handle<JSObject> object, 1822 Handle<Name> name, 1823 Handle<Object> getter, 1824 Handle<Object> setter, 1825 PropertyAttributes attributes); 1826 1827 // Defines an AccessorInfo property on the given object. 1828 MUST_USE_RESULT static MaybeHandle<Object> SetAccessor( 1829 Handle<JSObject> object, 1830 Handle<AccessorInfo> info); 1831 1832 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithInterceptor( 1833 Handle<JSObject> object, 1834 Handle<Object> receiver, 1835 Handle<Name> name); 1836 1837 // Returns true if this is an instance of an api function and has 1838 // been modified since it was created. May give false positives. 1839 bool IsDirty(); 1840 1841 // Accessors for hidden properties object. 1842 // 1843 // Hidden properties are not own properties of the object itself. 1844 // Instead they are stored in an auxiliary structure kept as an own 1845 // property with a special name Heap::hidden_string(). But if the 1846 // receiver is a JSGlobalProxy then the auxiliary object is a property 1847 // of its prototype, and if it's a detached proxy, then you can't have 1848 // hidden properties. 1849 1850 // Sets a hidden property on this object. Returns this object if successful, 1851 // undefined if called on a detached proxy. 1852 static Handle<Object> SetHiddenProperty(Handle<JSObject> object, 1853 Handle<Name> key, 1854 Handle<Object> value); 1855 // Gets the value of a hidden property with the given key. Returns the hole 1856 // if the property doesn't exist (or if called on a detached proxy), 1857 // otherwise returns the value set for the key. 1858 Object* GetHiddenProperty(Handle<Name> key); 1859 // Deletes a hidden property. Deleting a non-existing property is 1860 // considered successful. 1861 static void DeleteHiddenProperty(Handle<JSObject> object, 1862 Handle<Name> key); 1863 // Returns true if the object has a property with the hidden string as name. 1864 static bool HasHiddenProperties(Handle<JSObject> object); 1865 1866 static void SetIdentityHash(Handle<JSObject> object, Handle<Smi> hash); 1867 1868 static inline void ValidateElements(Handle<JSObject> object); 1869 1870 // Makes sure that this object can contain HeapObject as elements. 1871 static inline void EnsureCanContainHeapObjectElements(Handle<JSObject> obj); 1872 1873 // Makes sure that this object can contain the specified elements. 1874 static inline void EnsureCanContainElements( 1875 Handle<JSObject> object, 1876 Object** elements, 1877 uint32_t count, 1878 EnsureElementsMode mode); 1879 static inline void EnsureCanContainElements( 1880 Handle<JSObject> object, 1881 Handle<FixedArrayBase> elements, 1882 uint32_t length, 1883 EnsureElementsMode mode); 1884 static void EnsureCanContainElements( 1885 Handle<JSObject> object, 1886 Arguments* arguments, 1887 uint32_t first_arg, 1888 uint32_t arg_count, 1889 EnsureElementsMode mode); 1890 1891 // Would we convert a fast elements array to dictionary mode given 1892 // an access at key? 1893 bool WouldConvertToSlowElements(Handle<Object> key); 1894 // Do we want to keep the elements in fast case when increasing the 1895 // capacity? 1896 bool ShouldConvertToSlowElements(int new_capacity); 1897 // Returns true if the backing storage for the slow-case elements of 1898 // this object takes up nearly as much space as a fast-case backing 1899 // storage would. In that case the JSObject should have fast 1900 // elements. 1901 bool ShouldConvertToFastElements(); 1902 // Returns true if the elements of JSObject contains only values that can be 1903 // represented in a FixedDoubleArray and has at least one value that can only 1904 // be represented as a double and not a Smi. 1905 bool ShouldConvertToFastDoubleElements(bool* has_smi_only_elements); 1906 1907 // Computes the new capacity when expanding the elements of a JSObject. 1908 static int NewElementsCapacity(int old_capacity) { 1909 // (old_capacity + 50%) + 16 1910 return old_capacity + (old_capacity >> 1) + 16; 1911 } 1912 1913 // These methods do not perform access checks! 1914 MUST_USE_RESULT static MaybeHandle<AccessorPair> GetOwnElementAccessorPair( 1915 Handle<JSObject> object, 1916 uint32_t index); 1917 1918 MUST_USE_RESULT static MaybeHandle<Object> SetFastElement( 1919 Handle<JSObject> object, 1920 uint32_t index, 1921 Handle<Object> value, 1922 StrictMode strict_mode, 1923 bool check_prototype); 1924 1925 MUST_USE_RESULT static MaybeHandle<Object> SetOwnElement( 1926 Handle<JSObject> object, 1927 uint32_t index, 1928 Handle<Object> value, 1929 StrictMode strict_mode); 1930 1931 // Empty handle is returned if the element cannot be set to the given value. 1932 MUST_USE_RESULT static MaybeHandle<Object> SetElement( 1933 Handle<JSObject> object, 1934 uint32_t index, 1935 Handle<Object> value, 1936 PropertyAttributes attributes, 1937 StrictMode strict_mode, 1938 bool check_prototype = true, 1939 SetPropertyMode set_mode = SET_PROPERTY); 1940 1941 // Returns the index'th element. 1942 // The undefined object if index is out of bounds. 1943 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithInterceptor( 1944 Handle<JSObject> object, 1945 Handle<Object> receiver, 1946 uint32_t index); 1947 1948 enum SetFastElementsCapacitySmiMode { 1949 kAllowSmiElements, 1950 kForceSmiElements, 1951 kDontAllowSmiElements 1952 }; 1953 1954 // Replace the elements' backing store with fast elements of the given 1955 // capacity. Update the length for JSArrays. Returns the new backing 1956 // store. 1957 static Handle<FixedArray> SetFastElementsCapacityAndLength( 1958 Handle<JSObject> object, 1959 int capacity, 1960 int length, 1961 SetFastElementsCapacitySmiMode smi_mode); 1962 static void SetFastDoubleElementsCapacityAndLength( 1963 Handle<JSObject> object, 1964 int capacity, 1965 int length); 1966 1967 // Lookup interceptors are used for handling properties controlled by host 1968 // objects. 1969 inline bool HasNamedInterceptor(); 1970 inline bool HasIndexedInterceptor(); 1971 1972 // Computes the enumerable keys from interceptors. Used for debug mirrors and 1973 // by JSReceiver::GetKeys. 1974 MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForNamedInterceptor( 1975 Handle<JSObject> object, 1976 Handle<JSReceiver> receiver); 1977 MUST_USE_RESULT static MaybeHandle<JSObject> GetKeysForIndexedInterceptor( 1978 Handle<JSObject> object, 1979 Handle<JSReceiver> receiver); 1980 1981 // Support functions for v8 api (needed for correct interceptor behavior). 1982 MUST_USE_RESULT static Maybe<bool> HasRealNamedProperty( 1983 Handle<JSObject> object, Handle<Name> key); 1984 MUST_USE_RESULT static Maybe<bool> HasRealElementProperty( 1985 Handle<JSObject> object, uint32_t index); 1986 MUST_USE_RESULT static Maybe<bool> HasRealNamedCallbackProperty( 1987 Handle<JSObject> object, Handle<Name> key); 1988 1989 // Get the header size for a JSObject. Used to compute the index of 1990 // internal fields as well as the number of internal fields. 1991 inline int GetHeaderSize(); 1992 1993 inline int GetInternalFieldCount(); 1994 inline int GetInternalFieldOffset(int index); 1995 inline Object* GetInternalField(int index); 1996 inline void SetInternalField(int index, Object* value); 1997 inline void SetInternalField(int index, Smi* value); 1998 1999 // Returns the number of properties on this object filtering out properties 2000 // with the specified attributes (ignoring interceptors). 2001 int NumberOfOwnProperties(PropertyAttributes filter = NONE); 2002 // Fill in details for properties into storage starting at the specified 2003 // index. 2004 void GetOwnPropertyNames( 2005 FixedArray* storage, int index, PropertyAttributes filter = NONE); 2006 2007 // Returns the number of properties on this object filtering out properties 2008 // with the specified attributes (ignoring interceptors). 2009 int NumberOfOwnElements(PropertyAttributes filter); 2010 // Returns the number of enumerable elements (ignoring interceptors). 2011 int NumberOfEnumElements(); 2012 // Returns the number of elements on this object filtering out elements 2013 // with the specified attributes (ignoring interceptors). 2014 int GetOwnElementKeys(FixedArray* storage, PropertyAttributes filter); 2015 // Count and fill in the enumerable elements into storage. 2016 // (storage->length() == NumberOfEnumElements()). 2017 // If storage is NULL, will count the elements without adding 2018 // them to any storage. 2019 // Returns the number of enumerable elements. 2020 int GetEnumElementKeys(FixedArray* storage); 2021 2022 // Returns a new map with all transitions dropped from the object's current 2023 // map and the ElementsKind set. 2024 static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object, 2025 ElementsKind to_kind); 2026 static void TransitionElementsKind(Handle<JSObject> object, 2027 ElementsKind to_kind); 2028 2029 static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map); 2030 2031 // Convert the object to use the canonical dictionary 2032 // representation. If the object is expected to have additional properties 2033 // added this number can be indicated to have the backing store allocated to 2034 // an initial capacity for holding these properties. 2035 static void NormalizeProperties(Handle<JSObject> object, 2036 PropertyNormalizationMode mode, 2037 int expected_additional_properties); 2038 2039 // Convert and update the elements backing store to be a 2040 // SeededNumberDictionary dictionary. Returns the backing after conversion. 2041 static Handle<SeededNumberDictionary> NormalizeElements( 2042 Handle<JSObject> object); 2043 2044 // Transform slow named properties to fast variants. 2045 static void MigrateSlowToFast(Handle<JSObject> object, 2046 int unused_property_fields); 2047 2048 // Access fast-case object properties at index. 2049 static Handle<Object> FastPropertyAt(Handle<JSObject> object, 2050 Representation representation, 2051 FieldIndex index); 2052 inline Object* RawFastPropertyAt(FieldIndex index); 2053 inline void FastPropertyAtPut(FieldIndex index, Object* value); 2054 void WriteToField(int descriptor, Object* value); 2055 2056 // Access to in object properties. 2057 inline int GetInObjectPropertyOffset(int index); 2058 inline Object* InObjectPropertyAt(int index); 2059 inline Object* InObjectPropertyAtPut(int index, 2060 Object* value, 2061 WriteBarrierMode mode 2062 = UPDATE_WRITE_BARRIER); 2063 2064 // Set the object's prototype (only JSReceiver and null are allowed values). 2065 MUST_USE_RESULT static MaybeHandle<Object> SetPrototype( 2066 Handle<JSObject> object, Handle<Object> value, bool from_javascript); 2067 2068 // Initializes the body after properties slot, properties slot is 2069 // initialized by set_properties. Fill the pre-allocated fields with 2070 // pre_allocated_value and the rest with filler_value. 2071 // Note: this call does not update write barrier, the caller is responsible 2072 // to ensure that |filler_value| can be collected without WB here. 2073 inline void InitializeBody(Map* map, 2074 Object* pre_allocated_value, 2075 Object* filler_value); 2076 2077 // Check whether this object references another object 2078 bool ReferencesObject(Object* obj); 2079 2080 // Disalow further properties to be added to the object. 2081 MUST_USE_RESULT static MaybeHandle<Object> PreventExtensions( 2082 Handle<JSObject> object); 2083 2084 // ES5 Object.freeze 2085 MUST_USE_RESULT static MaybeHandle<Object> Freeze(Handle<JSObject> object); 2086 2087 // Called the first time an object is observed with ES7 Object.observe. 2088 static void SetObserved(Handle<JSObject> object); 2089 2090 // Copy object. 2091 enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 }; 2092 2093 static Handle<JSObject> Copy(Handle<JSObject> object); 2094 MUST_USE_RESULT static MaybeHandle<JSObject> DeepCopy( 2095 Handle<JSObject> object, 2096 AllocationSiteUsageContext* site_context, 2097 DeepCopyHints hints = kNoHints); 2098 MUST_USE_RESULT static MaybeHandle<JSObject> DeepWalk( 2099 Handle<JSObject> object, 2100 AllocationSiteCreationContext* site_context); 2101 2102 static Handle<Object> GetDataProperty(Handle<JSObject> object, 2103 Handle<Name> key); 2104 static Handle<Object> GetDataProperty(LookupIterator* it); 2105 2106 DECLARE_CAST(JSObject) 2107 2108 // Dispatched behavior. 2109 void JSObjectShortPrint(StringStream* accumulator); 2110 DECLARE_PRINTER(JSObject) 2111 DECLARE_VERIFIER(JSObject) 2112 #ifdef OBJECT_PRINT 2113 void PrintProperties(OStream& os); // NOLINT 2114 void PrintElements(OStream& os); // NOLINT 2115 void PrintTransitions(OStream& os); // NOLINT 2116 #endif 2117 2118 static void PrintElementsTransition( 2119 FILE* file, Handle<JSObject> object, 2120 ElementsKind from_kind, Handle<FixedArrayBase> from_elements, 2121 ElementsKind to_kind, Handle<FixedArrayBase> to_elements); 2122 2123 void PrintInstanceMigration(FILE* file, Map* original_map, Map* new_map); 2124 2125 #ifdef DEBUG 2126 // Structure for collecting spill information about JSObjects. 2127 class SpillInformation { 2128 public: 2129 void Clear(); 2130 void Print(); 2131 int number_of_objects_; 2132 int number_of_objects_with_fast_properties_; 2133 int number_of_objects_with_fast_elements_; 2134 int number_of_fast_used_fields_; 2135 int number_of_fast_unused_fields_; 2136 int number_of_slow_used_properties_; 2137 int number_of_slow_unused_properties_; 2138 int number_of_fast_used_elements_; 2139 int number_of_fast_unused_elements_; 2140 int number_of_slow_used_elements_; 2141 int number_of_slow_unused_elements_; 2142 }; 2143 2144 void IncrementSpillStatistics(SpillInformation* info); 2145 #endif 2146 2147 #ifdef VERIFY_HEAP 2148 // If a GC was caused while constructing this object, the elements pointer 2149 // may point to a one pointer filler map. The object won't be rooted, but 2150 // our heap verification code could stumble across it. 2151 bool ElementsAreSafeToExamine(); 2152 #endif 2153 2154 Object* SlowReverseLookup(Object* value); 2155 2156 // Maximal number of elements (numbered 0 .. kMaxElementCount - 1). 2157 // Also maximal value of JSArray's length property. 2158 static const uint32_t kMaxElementCount = 0xffffffffu; 2159 2160 // Constants for heuristics controlling conversion of fast elements 2161 // to slow elements. 2162 2163 // Maximal gap that can be introduced by adding an element beyond 2164 // the current elements length. 2165 static const uint32_t kMaxGap = 1024; 2166 2167 // Maximal length of fast elements array that won't be checked for 2168 // being dense enough on expansion. 2169 static const int kMaxUncheckedFastElementsLength = 5000; 2170 2171 // Same as above but for old arrays. This limit is more strict. We 2172 // don't want to be wasteful with long lived objects. 2173 static const int kMaxUncheckedOldFastElementsLength = 500; 2174 2175 // Note that Page::kMaxRegularHeapObjectSize puts a limit on 2176 // permissible values (see the DCHECK in heap.cc). 2177 static const int kInitialMaxFastElementArray = 100000; 2178 2179 // This constant applies only to the initial map of "$Object" aka 2180 // "global.Object" and not to arbitrary other JSObject maps. 2181 static const int kInitialGlobalObjectUnusedPropertiesCount = 4; 2182 2183 static const int kMaxInstanceSize = 255 * kPointerSize; 2184 // When extending the backing storage for property values, we increase 2185 // its size by more than the 1 entry necessary, so sequentially adding fields 2186 // to the same object requires fewer allocations and copies. 2187 static const int kFieldsAdded = 3; 2188 2189 // Layout description. 2190 static const int kPropertiesOffset = HeapObject::kHeaderSize; 2191 static const int kElementsOffset = kPropertiesOffset + kPointerSize; 2192 static const int kHeaderSize = kElementsOffset + kPointerSize; 2193 2194 STATIC_ASSERT(kHeaderSize == Internals::kJSObjectHeaderSize); 2195 2196 class BodyDescriptor : public FlexibleBodyDescriptor<kPropertiesOffset> { 2197 public: 2198 static inline int SizeOf(Map* map, HeapObject* object); 2199 }; 2200 2201 Context* GetCreationContext(); 2202 2203 // Enqueue change record for Object.observe. May cause GC. 2204 static void EnqueueChangeRecord(Handle<JSObject> object, 2205 const char* type, 2206 Handle<Name> name, 2207 Handle<Object> old_value); 2208 2209 static void MigrateToNewProperty(Handle<JSObject> object, 2210 Handle<Map> transition, 2211 Handle<Object> value); 2212 2213 private: 2214 friend class DictionaryElementsAccessor; 2215 friend class JSReceiver; 2216 friend class Object; 2217 2218 static void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map); 2219 static void MigrateFastToSlow(Handle<JSObject> object, 2220 Handle<Map> new_map, 2221 int expected_additional_properties); 2222 2223 static void GeneralizeFieldRepresentation(Handle<JSObject> object, 2224 int modify_index, 2225 Representation new_representation, 2226 Handle<HeapType> new_field_type); 2227 2228 static void UpdateAllocationSite(Handle<JSObject> object, 2229 ElementsKind to_kind); 2230 2231 // Used from Object::GetProperty(). 2232 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithFailedAccessCheck( 2233 LookupIterator* it); 2234 2235 MUST_USE_RESULT static MaybeHandle<Object> GetElementWithCallback( 2236 Handle<JSObject> object, 2237 Handle<Object> receiver, 2238 Handle<Object> structure, 2239 uint32_t index, 2240 Handle<Object> holder); 2241 2242 MUST_USE_RESULT static Maybe<PropertyAttributes> 2243 GetElementAttributeWithInterceptor(Handle<JSObject> object, 2244 Handle<JSReceiver> receiver, 2245 uint32_t index, bool continue_search); 2246 MUST_USE_RESULT static Maybe<PropertyAttributes> 2247 GetElementAttributeWithoutInterceptor(Handle<JSObject> object, 2248 Handle<JSReceiver> receiver, 2249 uint32_t index, 2250 bool continue_search); 2251 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback( 2252 Handle<JSObject> object, 2253 Handle<Object> structure, 2254 uint32_t index, 2255 Handle<Object> value, 2256 Handle<JSObject> holder, 2257 StrictMode strict_mode); 2258 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithInterceptor( 2259 Handle<JSObject> object, 2260 uint32_t index, 2261 Handle<Object> value, 2262 PropertyAttributes attributes, 2263 StrictMode strict_mode, 2264 bool check_prototype, 2265 SetPropertyMode set_mode); 2266 MUST_USE_RESULT static MaybeHandle<Object> SetElementWithoutInterceptor( 2267 Handle<JSObject> object, 2268 uint32_t index, 2269 Handle<Object> value, 2270 PropertyAttributes attributes, 2271 StrictMode strict_mode, 2272 bool check_prototype, 2273 SetPropertyMode set_mode); 2274 MUST_USE_RESULT 2275 static MaybeHandle<Object> SetElementWithCallbackSetterInPrototypes( 2276 Handle<JSObject> object, 2277 uint32_t index, 2278 Handle<Object> value, 2279 bool* found, 2280 StrictMode strict_mode); 2281 MUST_USE_RESULT static MaybeHandle<Object> SetDictionaryElement( 2282 Handle<JSObject> object, 2283 uint32_t index, 2284 Handle<Object> value, 2285 PropertyAttributes attributes, 2286 StrictMode strict_mode, 2287 bool check_prototype, 2288 SetPropertyMode set_mode = SET_PROPERTY); 2289 MUST_USE_RESULT static MaybeHandle<Object> SetFastDoubleElement( 2290 Handle<JSObject> object, 2291 uint32_t index, 2292 Handle<Object> value, 2293 StrictMode strict_mode, 2294 bool check_prototype = true); 2295 2296 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithFailedAccessCheck( 2297 LookupIterator* it, Handle<Object> value, StrictMode strict_mode); 2298 2299 // Add a property to a slow-case object. 2300 static void AddSlowProperty(Handle<JSObject> object, 2301 Handle<Name> name, 2302 Handle<Object> value, 2303 PropertyAttributes attributes); 2304 2305 MUST_USE_RESULT static MaybeHandle<Object> DeleteProperty( 2306 Handle<JSObject> object, 2307 Handle<Name> name, 2308 DeleteMode mode); 2309 MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithInterceptor( 2310 Handle<JSObject> holder, Handle<JSObject> receiver, Handle<Name> name); 2311 2312 // Deletes the named property in a normalized object. 2313 static Handle<Object> DeleteNormalizedProperty(Handle<JSObject> object, 2314 Handle<Name> name, 2315 DeleteMode mode); 2316 2317 MUST_USE_RESULT static MaybeHandle<Object> DeleteElement( 2318 Handle<JSObject> object, 2319 uint32_t index, 2320 DeleteMode mode); 2321 MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithInterceptor( 2322 Handle<JSObject> object, 2323 uint32_t index); 2324 2325 bool ReferencesObjectFromElements(FixedArray* elements, 2326 ElementsKind kind, 2327 Object* object); 2328 2329 // Returns true if most of the elements backing storage is used. 2330 bool HasDenseElements(); 2331 2332 // Gets the current elements capacity and the number of used elements. 2333 void GetElementsCapacityAndUsage(int* capacity, int* used); 2334 2335 static bool CanSetCallback(Handle<JSObject> object, Handle<Name> name); 2336 static void SetElementCallback(Handle<JSObject> object, 2337 uint32_t index, 2338 Handle<Object> structure, 2339 PropertyAttributes attributes); 2340 static void SetPropertyCallback(Handle<JSObject> object, 2341 Handle<Name> name, 2342 Handle<Object> structure, 2343 PropertyAttributes attributes); 2344 static void DefineElementAccessor(Handle<JSObject> object, 2345 uint32_t index, 2346 Handle<Object> getter, 2347 Handle<Object> setter, 2348 PropertyAttributes attributes); 2349 2350 // Return the hash table backing store or the inline stored identity hash, 2351 // whatever is found. 2352 MUST_USE_RESULT Object* GetHiddenPropertiesHashTable(); 2353 2354 // Return the hash table backing store for hidden properties. If there is no 2355 // backing store, allocate one. 2356 static Handle<ObjectHashTable> GetOrCreateHiddenPropertiesHashtable( 2357 Handle<JSObject> object); 2358 2359 // Set the hidden property backing store to either a hash table or 2360 // the inline-stored identity hash. 2361 static Handle<Object> SetHiddenPropertiesHashTable( 2362 Handle<JSObject> object, 2363 Handle<Object> value); 2364 2365 MUST_USE_RESULT Object* GetIdentityHash(); 2366 2367 static Handle<Smi> GetOrCreateIdentityHash(Handle<JSObject> object); 2368 2369 DISALLOW_IMPLICIT_CONSTRUCTORS(JSObject); 2370 }; 2371 2372 2373 // Common superclass for FixedArrays that allow implementations to share 2374 // common accessors and some code paths. 2375 class FixedArrayBase: public HeapObject { 2376 public: 2377 // [length]: length of the array. 2378 inline int length() const; 2379 inline void set_length(int value); 2380 2381 // Get and set the length using acquire loads and release stores. 2382 inline int synchronized_length() const; 2383 inline void synchronized_set_length(int value); 2384 2385 DECLARE_CAST(FixedArrayBase) 2386 2387 // Layout description. 2388 // Length is smi tagged when it is stored. 2389 static const int kLengthOffset = HeapObject::kHeaderSize; 2390 static const int kHeaderSize = kLengthOffset + kPointerSize; 2391 }; 2392 2393 2394 class FixedDoubleArray; 2395 class IncrementalMarking; 2396 2397 2398 // FixedArray describes fixed-sized arrays with element type Object*. 2399 class FixedArray: public FixedArrayBase { 2400 public: 2401 // Setter and getter for elements. 2402 inline Object* get(int index); 2403 static inline Handle<Object> get(Handle<FixedArray> array, int index); 2404 // Setter that uses write barrier. 2405 inline void set(int index, Object* value); 2406 inline bool is_the_hole(int index); 2407 2408 // Setter that doesn't need write barrier. 2409 inline void set(int index, Smi* value); 2410 // Setter with explicit barrier mode. 2411 inline void set(int index, Object* value, WriteBarrierMode mode); 2412 2413 // Setters for frequently used oddballs located in old space. 2414 inline void set_undefined(int index); 2415 inline void set_null(int index); 2416 inline void set_the_hole(int index); 2417 2418 inline Object** GetFirstElementAddress(); 2419 inline bool ContainsOnlySmisOrHoles(); 2420 2421 // Gives access to raw memory which stores the array's data. 2422 inline Object** data_start(); 2423 2424 inline void FillWithHoles(int from, int to); 2425 2426 // Shrink length and insert filler objects. 2427 void Shrink(int length); 2428 2429 // Copy operation. 2430 static Handle<FixedArray> CopySize(Handle<FixedArray> array, 2431 int new_length, 2432 PretenureFlag pretenure = NOT_TENURED); 2433 2434 // Add the elements of a JSArray to this FixedArray. 2435 MUST_USE_RESULT static MaybeHandle<FixedArray> AddKeysFromArrayLike( 2436 Handle<FixedArray> content, 2437 Handle<JSObject> array); 2438 2439 // Computes the union of keys and return the result. 2440 // Used for implementing "for (n in object) { }" 2441 MUST_USE_RESULT static MaybeHandle<FixedArray> UnionOfKeys( 2442 Handle<FixedArray> first, 2443 Handle<FixedArray> second); 2444 2445 // Copy a sub array from the receiver to dest. 2446 void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); 2447 2448 // Garbage collection support. 2449 static int SizeFor(int length) { return kHeaderSize + length * kPointerSize; } 2450 2451 // Code Generation support. 2452 static int OffsetOfElementAt(int index) { return SizeFor(index); } 2453 2454 // Garbage collection support. 2455 Object** RawFieldOfElementAt(int index) { 2456 return HeapObject::RawField(this, OffsetOfElementAt(index)); 2457 } 2458 2459 DECLARE_CAST(FixedArray) 2460 2461 // Maximal allowed size, in bytes, of a single FixedArray. 2462 // Prevents overflowing size computations, as well as extreme memory 2463 // consumption. 2464 static const int kMaxSize = 128 * MB * kPointerSize; 2465 // Maximally allowed length of a FixedArray. 2466 static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize; 2467 2468 // Dispatched behavior. 2469 DECLARE_PRINTER(FixedArray) 2470 DECLARE_VERIFIER(FixedArray) 2471 #ifdef DEBUG 2472 // Checks if two FixedArrays have identical contents. 2473 bool IsEqualTo(FixedArray* other); 2474 #endif 2475 2476 // Swap two elements in a pair of arrays. If this array and the 2477 // numbers array are the same object, the elements are only swapped 2478 // once. 2479 void SwapPairs(FixedArray* numbers, int i, int j); 2480 2481 // Sort prefix of this array and the numbers array as pairs wrt. the 2482 // numbers. If the numbers array and the this array are the same 2483 // object, the prefix of this array is sorted. 2484 void SortPairs(FixedArray* numbers, uint32_t len); 2485 2486 class BodyDescriptor : public FlexibleBodyDescriptor<kHeaderSize> { 2487 public: 2488 static inline int SizeOf(Map* map, HeapObject* object) { 2489 return SizeFor(reinterpret_cast<FixedArray*>(object)->length()); 2490 } 2491 }; 2492 2493 protected: 2494 // Set operation on FixedArray without using write barriers. Can 2495 // only be used for storing old space objects or smis. 2496 static inline void NoWriteBarrierSet(FixedArray* array, 2497 int index, 2498 Object* value); 2499 2500 // Set operation on FixedArray without incremental write barrier. Can 2501 // only be used if the object is guaranteed to be white (whiteness witness 2502 // is present). 2503 static inline void NoIncrementalWriteBarrierSet(FixedArray* array, 2504 int index, 2505 Object* value); 2506 2507 private: 2508 STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize); 2509 2510 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray); 2511 }; 2512 2513 2514 // FixedDoubleArray describes fixed-sized arrays with element type double. 2515 class FixedDoubleArray: public FixedArrayBase { 2516 public: 2517 // Setter and getter for elements. 2518 inline double get_scalar(int index); 2519 inline int64_t get_representation(int index); 2520 static inline Handle<Object> get(Handle<FixedDoubleArray> array, int index); 2521 inline void set(int index, double value); 2522 inline void set_the_hole(int index); 2523 2524 // Checking for the hole. 2525 inline bool is_the_hole(int index); 2526 2527 // Garbage collection support. 2528 inline static int SizeFor(int length) { 2529 return kHeaderSize + length * kDoubleSize; 2530 } 2531 2532 // Gives access to raw memory which stores the array's data. 2533 inline double* data_start(); 2534 2535 inline void FillWithHoles(int from, int to); 2536 2537 // Code Generation support. 2538 static int OffsetOfElementAt(int index) { return SizeFor(index); } 2539 2540 inline static bool is_the_hole_nan(double value); 2541 inline static double hole_nan_as_double(); 2542 inline static double canonical_not_the_hole_nan_as_double(); 2543 2544 DECLARE_CAST(FixedDoubleArray) 2545 2546 // Maximal allowed size, in bytes, of a single FixedDoubleArray. 2547 // Prevents overflowing size computations, as well as extreme memory 2548 // consumption. 2549 static const int kMaxSize = 512 * MB; 2550 // Maximally allowed length of a FixedArray. 2551 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize; 2552 2553 // Dispatched behavior. 2554 DECLARE_PRINTER(FixedDoubleArray) 2555 DECLARE_VERIFIER(FixedDoubleArray) 2556 2557 private: 2558 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedDoubleArray); 2559 }; 2560 2561 2562 // ConstantPoolArray describes a fixed-sized array containing constant pool 2563 // entries. 2564 // 2565 // A ConstantPoolArray can be structured in two different ways depending upon 2566 // whether it is extended or small. The is_extended_layout() method can be used 2567 // to discover which layout the constant pool has. 2568 // 2569 // The format of a small constant pool is: 2570 // [kSmallLayout1Offset] : Small section layout bitmap 1 2571 // [kSmallLayout2Offset] : Small section layout bitmap 2 2572 // [first_index(INT64, SMALL_SECTION)] : 64 bit entries 2573 // ... : ... 2574 // [first_index(CODE_PTR, SMALL_SECTION)] : code pointer entries 2575 // ... : ... 2576 // [first_index(HEAP_PTR, SMALL_SECTION)] : heap pointer entries 2577 // ... : ... 2578 // [first_index(INT32, SMALL_SECTION)] : 32 bit entries 2579 // ... : ... 2580 // 2581 // If the constant pool has an extended layout, the extended section constant 2582 // pool also contains an extended section, which has the following format at 2583 // location get_extended_section_header_offset(): 2584 // [kExtendedInt64CountOffset] : count of extended 64 bit entries 2585 // [kExtendedCodePtrCountOffset] : count of extended code pointers 2586 // [kExtendedHeapPtrCountOffset] : count of extended heap pointers 2587 // [kExtendedInt32CountOffset] : count of extended 32 bit entries 2588 // [first_index(INT64, EXTENDED_SECTION)] : 64 bit entries 2589 // ... : ... 2590 // [first_index(CODE_PTR, EXTENDED_SECTION)]: code pointer entries 2591 // ... : ... 2592 // [first_index(HEAP_PTR, EXTENDED_SECTION)]: heap pointer entries 2593 // ... : ... 2594 // [first_index(INT32, EXTENDED_SECTION)] : 32 bit entries 2595 // ... : ... 2596 // 2597 class ConstantPoolArray: public HeapObject { 2598 public: 2599 enum WeakObjectState { 2600 NO_WEAK_OBJECTS, 2601 WEAK_OBJECTS_IN_OPTIMIZED_CODE, 2602 WEAK_OBJECTS_IN_IC 2603 }; 2604 2605 enum Type { 2606 INT64 = 0, 2607 CODE_PTR, 2608 HEAP_PTR, 2609 INT32, 2610 // Number of types stored by the ConstantPoolArrays. 2611 NUMBER_OF_TYPES, 2612 FIRST_TYPE = INT64, 2613 LAST_TYPE = INT32 2614 }; 2615 2616 enum LayoutSection { 2617 SMALL_SECTION = 0, 2618 EXTENDED_SECTION, 2619 NUMBER_OF_LAYOUT_SECTIONS 2620 }; 2621 2622 class NumberOfEntries BASE_EMBEDDED { 2623 public: 2624 inline NumberOfEntries() { 2625 for (int i = 0; i < NUMBER_OF_TYPES; i++) { 2626 element_counts_[i] = 0; 2627 } 2628 } 2629 2630 inline NumberOfEntries(int int64_count, int code_ptr_count, 2631 int heap_ptr_count, int int32_count) { 2632 element_counts_[INT64] = int64_count; 2633 element_counts_[CODE_PTR] = code_ptr_count; 2634 element_counts_[HEAP_PTR] = heap_ptr_count; 2635 element_counts_[INT32] = int32_count; 2636 } 2637 2638 inline NumberOfEntries(ConstantPoolArray* array, LayoutSection section) { 2639 element_counts_[INT64] = array->number_of_entries(INT64, section); 2640 element_counts_[CODE_PTR] = array->number_of_entries(CODE_PTR, section); 2641 element_counts_[HEAP_PTR] = array->number_of_entries(HEAP_PTR, section); 2642 element_counts_[INT32] = array->number_of_entries(INT32, section); 2643 } 2644 2645 inline void increment(Type type); 2646 inline int equals(const NumberOfEntries& other) const; 2647 inline bool is_empty() const; 2648 inline int count_of(Type type) const; 2649 inline int base_of(Type type) const; 2650 inline int total_count() const; 2651 inline int are_in_range(int min, int max) const; 2652 2653 private: 2654 int element_counts_[NUMBER_OF_TYPES]; 2655 }; 2656 2657 class Iterator BASE_EMBEDDED { 2658 public: 2659 inline Iterator(ConstantPoolArray* array, Type type) 2660 : array_(array), 2661 type_(type), 2662 final_section_(array->final_section()), 2663 current_section_(SMALL_SECTION), 2664 next_index_(array->first_index(type, SMALL_SECTION)) { 2665 update_section(); 2666 } 2667 2668 inline Iterator(ConstantPoolArray* array, Type type, LayoutSection section) 2669 : array_(array), 2670 type_(type), 2671 final_section_(section), 2672 current_section_(section), 2673 next_index_(array->first_index(type, section)) { 2674 update_section(); 2675 } 2676 2677 inline int next_index(); 2678 inline bool is_finished(); 2679 2680 private: 2681 inline void update_section(); 2682 ConstantPoolArray* array_; 2683 const Type type_; 2684 const LayoutSection final_section_; 2685 2686 LayoutSection current_section_; 2687 int next_index_; 2688 }; 2689 2690 // Getters for the first index, the last index and the count of entries of 2691 // a given type for a given layout section. 2692 inline int first_index(Type type, LayoutSection layout_section); 2693 inline int last_index(Type type, LayoutSection layout_section); 2694 inline int number_of_entries(Type type, LayoutSection layout_section); 2695 2696 // Returns the type of the entry at the given index. 2697 inline Type get_type(int index); 2698 inline bool offset_is_type(int offset, Type type); 2699 2700 // Setter and getter for pool elements. 2701 inline Address get_code_ptr_entry(int index); 2702 inline Object* get_heap_ptr_entry(int index); 2703 inline int64_t get_int64_entry(int index); 2704 inline int32_t get_int32_entry(int index); 2705 inline double get_int64_entry_as_double(int index); 2706 2707 inline void set(int index, Address value); 2708 inline void set(int index, Object* value); 2709 inline void set(int index, int64_t value); 2710 inline void set(int index, double value); 2711 inline void set(int index, int32_t value); 2712 2713 // Setters which take a raw offset rather than an index (for code generation). 2714 inline void set_at_offset(int offset, int32_t value); 2715 inline void set_at_offset(int offset, int64_t value); 2716 inline void set_at_offset(int offset, double value); 2717 inline void set_at_offset(int offset, Address value); 2718 inline void set_at_offset(int offset, Object* value); 2719 2720 // Setter and getter for weak objects state 2721 inline void set_weak_object_state(WeakObjectState state); 2722 inline WeakObjectState get_weak_object_state(); 2723 2724 // Returns true if the constant pool has an extended layout, false if it has 2725 // only the small layout. 2726 inline bool is_extended_layout(); 2727 2728 // Returns the last LayoutSection in this constant pool array. 2729 inline LayoutSection final_section(); 2730 2731 // Set up initial state for a small layout constant pool array. 2732 inline void Init(const NumberOfEntries& small); 2733 2734 // Set up initial state for an extended layout constant pool array. 2735 inline void InitExtended(const NumberOfEntries& small, 2736 const NumberOfEntries& extended); 2737 2738 // Clears the pointer entries with GC safe values. 2739 void ClearPtrEntries(Isolate* isolate); 2740 2741 // returns the total number of entries in the constant pool array. 2742 inline int length(); 2743 2744 // Garbage collection support. 2745 inline int size(); 2746 2747 2748 inline static int MaxInt64Offset(int number_of_int64) { 2749 return kFirstEntryOffset + (number_of_int64 * kInt64Size); 2750 } 2751 2752 inline static int SizeFor(const NumberOfEntries& small) { 2753 int size = kFirstEntryOffset + 2754 (small.count_of(INT64) * kInt64Size) + 2755 (small.count_of(CODE_PTR) * kPointerSize) + 2756 (small.count_of(HEAP_PTR) * kPointerSize) + 2757 (small.count_of(INT32) * kInt32Size); 2758 return RoundUp(size, kPointerSize); 2759 } 2760 2761 inline static int SizeForExtended(const NumberOfEntries& small, 2762 const NumberOfEntries& extended) { 2763 int size = SizeFor(small); 2764 size = RoundUp(size, kInt64Size); // Align extended header to 64 bits. 2765 size += kExtendedFirstOffset + 2766 (extended.count_of(INT64) * kInt64Size) + 2767 (extended.count_of(CODE_PTR) * kPointerSize) + 2768 (extended.count_of(HEAP_PTR) * kPointerSize) + 2769 (extended.count_of(INT32) * kInt32Size); 2770 return RoundUp(size, kPointerSize); 2771 } 2772 2773 inline static int entry_size(Type type) { 2774 switch (type) { 2775 case INT32: 2776 return kInt32Size; 2777 case INT64: 2778 return kInt64Size; 2779 case CODE_PTR: 2780 case HEAP_PTR: 2781 return kPointerSize; 2782 default: 2783 UNREACHABLE(); 2784 return 0; 2785 } 2786 } 2787 2788 // Code Generation support. 2789 inline int OffsetOfElementAt(int index) { 2790 int offset; 2791 LayoutSection section; 2792 if (is_extended_layout() && index >= first_extended_section_index()) { 2793 section = EXTENDED_SECTION; 2794 offset = get_extended_section_header_offset() + kExtendedFirstOffset; 2795 } else { 2796 section = SMALL_SECTION; 2797 offset = kFirstEntryOffset; 2798 } 2799 2800 // Add offsets for the preceding type sections. 2801 DCHECK(index <= last_index(LAST_TYPE, section)); 2802 for (Type type = FIRST_TYPE; index > last_index(type, section); 2803 type = next_type(type)) { 2804 offset += entry_size(type) * number_of_entries(type, section); 2805 } 2806 2807 // Add offset for the index in it's type. 2808 Type type = get_type(index); 2809 offset += entry_size(type) * (index - first_index(type, section)); 2810 return offset; 2811 } 2812 2813 DECLARE_CAST(ConstantPoolArray) 2814 2815 // Garbage collection support. 2816 Object** RawFieldOfElementAt(int index) { 2817 return HeapObject::RawField(this, OffsetOfElementAt(index)); 2818 } 2819 2820 // Small Layout description. 2821 static const int kSmallLayout1Offset = HeapObject::kHeaderSize; 2822 static const int kSmallLayout2Offset = kSmallLayout1Offset + kInt32Size; 2823 static const int kHeaderSize = kSmallLayout2Offset + kInt32Size; 2824 static const int kFirstEntryOffset = ROUND_UP(kHeaderSize, kInt64Size); 2825 2826 static const int kSmallLayoutCountBits = 10; 2827 static const int kMaxSmallEntriesPerType = (1 << kSmallLayoutCountBits) - 1; 2828 2829 // Fields in kSmallLayout1Offset. 2830 class Int64CountField: public BitField<int, 1, kSmallLayoutCountBits> {}; 2831 class CodePtrCountField: public BitField<int, 11, kSmallLayoutCountBits> {}; 2832 class HeapPtrCountField: public BitField<int, 21, kSmallLayoutCountBits> {}; 2833 class IsExtendedField: public BitField<bool, 31, 1> {}; 2834 2835 // Fields in kSmallLayout2Offset. 2836 class Int32CountField: public BitField<int, 1, kSmallLayoutCountBits> {}; 2837 class TotalCountField: public BitField<int, 11, 12> {}; 2838 class WeakObjectStateField: public BitField<WeakObjectState, 23, 2> {}; 2839 2840 // Extended layout description, which starts at 2841 // get_extended_section_header_offset(). 2842 static const int kExtendedInt64CountOffset = 0; 2843 static const int kExtendedCodePtrCountOffset = 2844 kExtendedInt64CountOffset + kPointerSize; 2845 static const int kExtendedHeapPtrCountOffset = 2846 kExtendedCodePtrCountOffset + kPointerSize; 2847 static const int kExtendedInt32CountOffset = 2848 kExtendedHeapPtrCountOffset + kPointerSize; 2849 static const int kExtendedFirstOffset = 2850 kExtendedInt32CountOffset + kPointerSize; 2851 2852 // Dispatched behavior. 2853 void ConstantPoolIterateBody(ObjectVisitor* v); 2854 2855 DECLARE_PRINTER(ConstantPoolArray) 2856 DECLARE_VERIFIER(ConstantPoolArray) 2857 2858 private: 2859 inline int first_extended_section_index(); 2860 inline int get_extended_section_header_offset(); 2861 2862 inline static Type next_type(Type type) { 2863 DCHECK(type >= FIRST_TYPE && type < NUMBER_OF_TYPES); 2864 int type_int = static_cast<int>(type); 2865 return static_cast<Type>(++type_int); 2866 } 2867 2868 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolArray); 2869 }; 2870 2871 2872 // DescriptorArrays are fixed arrays used to hold instance descriptors. 2873 // The format of the these objects is: 2874 // [0]: Number of descriptors 2875 // [1]: Either Smi(0) if uninitialized, or a pointer to small fixed array: 2876 // [0]: pointer to fixed array with enum cache 2877 // [1]: either Smi(0) or pointer to fixed array with indices 2878 // [2]: first key 2879 // [2 + number of descriptors * kDescriptorSize]: start of slack 2880 class DescriptorArray: public FixedArray { 2881 public: 2882 // Returns true for both shared empty_descriptor_array and for smis, which the 2883 // map uses to encode additional bit fields when the descriptor array is not 2884 // yet used. 2885 inline bool IsEmpty(); 2886 2887 // Returns the number of descriptors in the array. 2888 int number_of_descriptors() { 2889 DCHECK(length() >= kFirstIndex || IsEmpty()); 2890 int len = length(); 2891 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value(); 2892 } 2893 2894 int number_of_descriptors_storage() { 2895 int len = length(); 2896 return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize; 2897 } 2898 2899 int NumberOfSlackDescriptors() { 2900 return number_of_descriptors_storage() - number_of_descriptors(); 2901 } 2902 2903 inline void SetNumberOfDescriptors(int number_of_descriptors); 2904 inline int number_of_entries() { return number_of_descriptors(); } 2905 2906 bool HasEnumCache() { 2907 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi(); 2908 } 2909 2910 void CopyEnumCacheFrom(DescriptorArray* array) { 2911 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); 2912 } 2913 2914 FixedArray* GetEnumCache() { 2915 DCHECK(HasEnumCache()); 2916 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2917 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex)); 2918 } 2919 2920 bool HasEnumIndicesCache() { 2921 if (IsEmpty()) return false; 2922 Object* object = get(kEnumCacheIndex); 2923 if (object->IsSmi()) return false; 2924 FixedArray* bridge = FixedArray::cast(object); 2925 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi(); 2926 } 2927 2928 FixedArray* GetEnumIndicesCache() { 2929 DCHECK(HasEnumIndicesCache()); 2930 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2931 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); 2932 } 2933 2934 Object** GetEnumCacheSlot() { 2935 DCHECK(HasEnumCache()); 2936 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), 2937 kEnumCacheOffset); 2938 } 2939 2940 void ClearEnumCache(); 2941 2942 // Initialize or change the enum cache, 2943 // using the supplied storage for the small "bridge". 2944 void SetEnumCache(FixedArray* bridge_storage, 2945 FixedArray* new_cache, 2946 Object* new_index_cache); 2947 2948 bool CanHoldValue(int descriptor, Object* value); 2949 2950 // Accessors for fetching instance descriptor at descriptor number. 2951 inline Name* GetKey(int descriptor_number); 2952 inline Object** GetKeySlot(int descriptor_number); 2953 inline Object* GetValue(int descriptor_number); 2954 inline void SetValue(int descriptor_number, Object* value); 2955 inline Object** GetValueSlot(int descriptor_number); 2956 static inline int GetValueOffset(int descriptor_number); 2957 inline Object** GetDescriptorStartSlot(int descriptor_number); 2958 inline Object** GetDescriptorEndSlot(int descriptor_number); 2959 inline PropertyDetails GetDetails(int descriptor_number); 2960 inline PropertyType GetType(int descriptor_number); 2961 inline int GetFieldIndex(int descriptor_number); 2962 inline HeapType* GetFieldType(int descriptor_number); 2963 inline Object* GetConstant(int descriptor_number); 2964 inline Object* GetCallbacksObject(int descriptor_number); 2965 inline AccessorDescriptor* GetCallbacks(int descriptor_number); 2966 2967 inline Name* GetSortedKey(int descriptor_number); 2968 inline int GetSortedKeyIndex(int descriptor_number); 2969 inline void SetSortedKey(int pointer, int descriptor_number); 2970 inline void SetRepresentation(int descriptor_number, 2971 Representation representation); 2972 2973 // Accessor for complete descriptor. 2974 inline void Get(int descriptor_number, Descriptor* desc); 2975 inline void Set(int descriptor_number, Descriptor* desc); 2976 void Replace(int descriptor_number, Descriptor* descriptor); 2977 2978 // Append automatically sets the enumeration index. This should only be used 2979 // to add descriptors in bulk at the end, followed by sorting the descriptor 2980 // array. 2981 inline void Append(Descriptor* desc); 2982 2983 static Handle<DescriptorArray> CopyUpTo(Handle<DescriptorArray> desc, 2984 int enumeration_index, 2985 int slack = 0); 2986 2987 static Handle<DescriptorArray> CopyUpToAddAttributes( 2988 Handle<DescriptorArray> desc, 2989 int enumeration_index, 2990 PropertyAttributes attributes, 2991 int slack = 0); 2992 2993 // Sort the instance descriptors by the hash codes of their keys. 2994 void Sort(); 2995 2996 // Search the instance descriptors for given name. 2997 INLINE(int Search(Name* name, int number_of_own_descriptors)); 2998 2999 // As the above, but uses DescriptorLookupCache and updates it when 3000 // necessary. 3001 INLINE(int SearchWithCache(Name* name, Map* map)); 3002 3003 // Allocates a DescriptorArray, but returns the singleton 3004 // empty descriptor array object if number_of_descriptors is 0. 3005 static Handle<DescriptorArray> Allocate(Isolate* isolate, 3006 int number_of_descriptors, 3007 int slack = 0); 3008 3009 DECLARE_CAST(DescriptorArray) 3010 3011 // Constant for denoting key was not found. 3012 static const int kNotFound = -1; 3013 3014 static const int kDescriptorLengthIndex = 0; 3015 static const int kEnumCacheIndex = 1; 3016 static const int kFirstIndex = 2; 3017 3018 // The length of the "bridge" to the enum cache. 3019 static const int kEnumCacheBridgeLength = 2; 3020 static const int kEnumCacheBridgeCacheIndex = 0; 3021 static const int kEnumCacheBridgeIndicesCacheIndex = 1; 3022 3023 // Layout description. 3024 static const int kDescriptorLengthOffset = FixedArray::kHeaderSize; 3025 static const int kEnumCacheOffset = kDescriptorLengthOffset + kPointerSize; 3026 static const int kFirstOffset = kEnumCacheOffset + kPointerSize; 3027 3028 // Layout description for the bridge array. 3029 static const int kEnumCacheBridgeCacheOffset = FixedArray::kHeaderSize; 3030 3031 // Layout of descriptor. 3032 static const int kDescriptorKey = 0; 3033 static const int kDescriptorDetails = 1; 3034 static const int kDescriptorValue = 2; 3035 static const int kDescriptorSize = 3; 3036 3037 #ifdef OBJECT_PRINT 3038 // Print all the descriptors. 3039 void PrintDescriptors(OStream& os); // NOLINT 3040 #endif 3041 3042 #ifdef DEBUG 3043 // Is the descriptor array sorted and without duplicates? 3044 bool IsSortedNoDuplicates(int valid_descriptors = -1); 3045 3046 // Is the descriptor array consistent with the back pointers in targets? 3047 bool IsConsistentWithBackPointers(Map* current_map); 3048 3049 // Are two DescriptorArrays equal? 3050 bool IsEqualTo(DescriptorArray* other); 3051 #endif 3052 3053 // Returns the fixed array length required to hold number_of_descriptors 3054 // descriptors. 3055 static int LengthFor(int number_of_descriptors) { 3056 return ToKeyIndex(number_of_descriptors); 3057 } 3058 3059 private: 3060 // WhitenessWitness is used to prove that a descriptor array is white 3061 // (unmarked), so incremental write barriers can be skipped because the 3062 // marking invariant cannot be broken and slots pointing into evacuation 3063 // candidates will be discovered when the object is scanned. A witness is 3064 // always stack-allocated right after creating an array. By allocating a 3065 // witness, incremental marking is globally disabled. The witness is then 3066 // passed along wherever needed to statically prove that the array is known to 3067 // be white. 3068 class WhitenessWitness { 3069 public: 3070 inline explicit WhitenessWitness(DescriptorArray* array); 3071 inline ~WhitenessWitness(); 3072 3073 private: 3074 IncrementalMarking* marking_; 3075 }; 3076 3077 // An entry in a DescriptorArray, represented as an (array, index) pair. 3078 class Entry { 3079 public: 3080 inline explicit Entry(DescriptorArray* descs, int index) : 3081 descs_(descs), index_(index) { } 3082 3083 inline PropertyType type() { return descs_->GetType(index_); } 3084 inline Object* GetCallbackObject() { return descs_->GetValue(index_); } 3085 3086 private: 3087 DescriptorArray* descs_; 3088 int index_; 3089 }; 3090 3091 // Conversion from descriptor number to array indices. 3092 static int ToKeyIndex(int descriptor_number) { 3093 return kFirstIndex + 3094 (descriptor_number * kDescriptorSize) + 3095 kDescriptorKey; 3096 } 3097 3098 static int ToDetailsIndex(int descriptor_number) { 3099 return kFirstIndex + 3100 (descriptor_number * kDescriptorSize) + 3101 kDescriptorDetails; 3102 } 3103 3104 static int ToValueIndex(int descriptor_number) { 3105 return kFirstIndex + 3106 (descriptor_number * kDescriptorSize) + 3107 kDescriptorValue; 3108 } 3109 3110 // Transfer a complete descriptor from the src descriptor array to this 3111 // descriptor array. 3112 void CopyFrom(int index, 3113 DescriptorArray* src, 3114 const WhitenessWitness&); 3115 3116 inline void Set(int descriptor_number, 3117 Descriptor* desc, 3118 const WhitenessWitness&); 3119 3120 // Swap first and second descriptor. 3121 inline void SwapSortedKeys(int first, int second); 3122 3123 DISALLOW_IMPLICIT_CONSTRUCTORS(DescriptorArray); 3124 }; 3125 3126 3127 enum SearchMode { ALL_ENTRIES, VALID_ENTRIES }; 3128 3129 template<SearchMode search_mode, typename T> 3130 inline int LinearSearch(T* array, Name* name, int len, int valid_entries); 3131 3132 3133 template<SearchMode search_mode, typename T> 3134 inline int Search(T* array, Name* name, int valid_entries = 0); 3135 3136 3137 // HashTable is a subclass of FixedArray that implements a hash table 3138 // that uses open addressing and quadratic probing. 3139 // 3140 // In order for the quadratic probing to work, elements that have not 3141 // yet been used and elements that have been deleted are 3142 // distinguished. Probing continues when deleted elements are 3143 // encountered and stops when unused elements are encountered. 3144 // 3145 // - Elements with key == undefined have not been used yet. 3146 // - Elements with key == the_hole have been deleted. 3147 // 3148 // The hash table class is parameterized with a Shape and a Key. 3149 // Shape must be a class with the following interface: 3150 // class ExampleShape { 3151 // public: 3152 // // Tells whether key matches other. 3153 // static bool IsMatch(Key key, Object* other); 3154 // // Returns the hash value for key. 3155 // static uint32_t Hash(Key key); 3156 // // Returns the hash value for object. 3157 // static uint32_t HashForObject(Key key, Object* object); 3158 // // Convert key to an object. 3159 // static inline Handle<Object> AsHandle(Isolate* isolate, Key key); 3160 // // The prefix size indicates number of elements in the beginning 3161 // // of the backing storage. 3162 // static const int kPrefixSize = ..; 3163 // // The Element size indicates number of elements per entry. 3164 // static const int kEntrySize = ..; 3165 // }; 3166 // The prefix size indicates an amount of memory in the 3167 // beginning of the backing storage that can be used for non-element 3168 // information by subclasses. 3169 3170 template<typename Key> 3171 class BaseShape { 3172 public: 3173 static const bool UsesSeed = false; 3174 static uint32_t Hash(Key key) { return 0; } 3175 static uint32_t SeededHash(Key key, uint32_t seed) { 3176 DCHECK(UsesSeed); 3177 return Hash(key); 3178 } 3179 static uint32_t HashForObject(Key key, Object* object) { return 0; } 3180 static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) { 3181 DCHECK(UsesSeed); 3182 return HashForObject(key, object); 3183 } 3184 }; 3185 3186 template<typename Derived, typename Shape, typename Key> 3187 class HashTable: public FixedArray { 3188 public: 3189 // Wrapper methods 3190 inline uint32_t Hash(Key key) { 3191 if (Shape::UsesSeed) { 3192 return Shape::SeededHash(key, GetHeap()->HashSeed()); 3193 } else { 3194 return Shape::Hash(key); 3195 } 3196 } 3197 3198 inline uint32_t HashForObject(Key key, Object* object) { 3199 if (Shape::UsesSeed) { 3200 return Shape::SeededHashForObject(key, GetHeap()->HashSeed(), object); 3201 } else { 3202 return Shape::HashForObject(key, object); 3203 } 3204 } 3205 3206 // Returns the number of elements in the hash table. 3207 int NumberOfElements() { 3208 return Smi::cast(get(kNumberOfElementsIndex))->value(); 3209 } 3210 3211 // Returns the number of deleted elements in the hash table. 3212 int NumberOfDeletedElements() { 3213 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 3214 } 3215 3216 // Returns the capacity of the hash table. 3217 int Capacity() { 3218 return Smi::cast(get(kCapacityIndex))->value(); 3219 } 3220 3221 // ElementAdded should be called whenever an element is added to a 3222 // hash table. 3223 void ElementAdded() { SetNumberOfElements(NumberOfElements() + 1); } 3224 3225 // ElementRemoved should be called whenever an element is removed from 3226 // a hash table. 3227 void ElementRemoved() { 3228 SetNumberOfElements(NumberOfElements() - 1); 3229 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); 3230 } 3231 void ElementsRemoved(int n) { 3232 SetNumberOfElements(NumberOfElements() - n); 3233 SetNumberOfDeletedElements(NumberOfDeletedElements() + n); 3234 } 3235 3236 // Returns a new HashTable object. 3237 MUST_USE_RESULT static Handle<Derived> New( 3238 Isolate* isolate, 3239 int at_least_space_for, 3240 MinimumCapacity capacity_option = USE_DEFAULT_MINIMUM_CAPACITY, 3241 PretenureFlag pretenure = NOT_TENURED); 3242 3243 // Computes the required capacity for a table holding the given 3244 // number of elements. May be more than HashTable::kMaxCapacity. 3245 static int ComputeCapacity(int at_least_space_for); 3246 3247 // Returns the key at entry. 3248 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } 3249 3250 // Tells whether k is a real key. The hole and undefined are not allowed 3251 // as keys and can be used to indicate missing or deleted elements. 3252 bool IsKey(Object* k) { 3253 return !k->IsTheHole() && !k->IsUndefined(); 3254 } 3255 3256 // Garbage collection support. 3257 void IteratePrefix(ObjectVisitor* visitor); 3258 void IterateElements(ObjectVisitor* visitor); 3259 3260 DECLARE_CAST(HashTable) 3261 3262 // Compute the probe offset (quadratic probing). 3263 INLINE(static uint32_t GetProbeOffset(uint32_t n)) { 3264 return (n + n * n) >> 1; 3265 } 3266 3267 static const int kNumberOfElementsIndex = 0; 3268 static const int kNumberOfDeletedElementsIndex = 1; 3269 static const int kCapacityIndex = 2; 3270 static const int kPrefixStartIndex = 3; 3271 static const int kElementsStartIndex = 3272 kPrefixStartIndex + Shape::kPrefixSize; 3273 static const int kEntrySize = Shape::kEntrySize; 3274 static const int kElementsStartOffset = 3275 kHeaderSize + kElementsStartIndex * kPointerSize; 3276 static const int kCapacityOffset = 3277 kHeaderSize + kCapacityIndex * kPointerSize; 3278 3279 // Constant used for denoting a absent entry. 3280 static const int kNotFound = -1; 3281 3282 // Maximal capacity of HashTable. Based on maximal length of underlying 3283 // FixedArray. Staying below kMaxCapacity also ensures that EntryToIndex 3284 // cannot overflow. 3285 static const int kMaxCapacity = 3286 (FixedArray::kMaxLength - kElementsStartOffset) / kEntrySize; 3287 3288 // Find entry for key otherwise return kNotFound. 3289 inline int FindEntry(Key key); 3290 int FindEntry(Isolate* isolate, Key key); 3291 3292 // Rehashes the table in-place. 3293 void Rehash(Key key); 3294 3295 protected: 3296 friend class ObjectHashTable; 3297 3298 // Find the entry at which to insert element with the given key that 3299 // has the given hash value. 3300 uint32_t FindInsertionEntry(uint32_t hash); 3301 3302 // Returns the index for an entry (of the key) 3303 static inline int EntryToIndex(int entry) { 3304 return (entry * kEntrySize) + kElementsStartIndex; 3305 } 3306 3307 // Update the number of elements in the hash table. 3308 void SetNumberOfElements(int nof) { 3309 set(kNumberOfElementsIndex, Smi::FromInt(nof)); 3310 } 3311 3312 // Update the number of deleted elements in the hash table. 3313 void SetNumberOfDeletedElements(int nod) { 3314 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); 3315 } 3316 3317 // Sets the capacity of the hash table. 3318 void SetCapacity(int capacity) { 3319 // To scale a computed hash code to fit within the hash table, we 3320 // use bit-wise AND with a mask, so the capacity must be positive 3321 // and non-zero. 3322 DCHECK(capacity > 0); 3323 DCHECK(capacity <= kMaxCapacity); 3324 set(kCapacityIndex, Smi::FromInt(capacity)); 3325 } 3326 3327 3328 // Returns probe entry. 3329 static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) { 3330 DCHECK(base::bits::IsPowerOfTwo32(size)); 3331 return (hash + GetProbeOffset(number)) & (size - 1); 3332 } 3333 3334 inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) { 3335 return hash & (size - 1); 3336 } 3337 3338 inline static uint32_t NextProbe( 3339 uint32_t last, uint32_t number, uint32_t size) { 3340 return (last + number) & (size - 1); 3341 } 3342 3343 // Attempt to shrink hash table after removal of key. 3344 MUST_USE_RESULT static Handle<Derived> Shrink(Handle<Derived> table, Key key); 3345 3346 // Ensure enough space for n additional elements. 3347 MUST_USE_RESULT static Handle<Derived> EnsureCapacity( 3348 Handle<Derived> table, 3349 int n, 3350 Key key, 3351 PretenureFlag pretenure = NOT_TENURED); 3352 3353 private: 3354 // Returns _expected_ if one of entries given by the first _probe_ probes is 3355 // equal to _expected_. Otherwise, returns the entry given by the probe 3356 // number _probe_. 3357 uint32_t EntryForProbe(Key key, Object* k, int probe, uint32_t expected); 3358 3359 void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode); 3360 3361 // Rehashes this hash-table into the new table. 3362 void Rehash(Handle<Derived> new_table, Key key); 3363 }; 3364 3365 3366 // HashTableKey is an abstract superclass for virtual key behavior. 3367 class HashTableKey { 3368 public: 3369 // Returns whether the other object matches this key. 3370 virtual bool IsMatch(Object* other) = 0; 3371 // Returns the hash value for this key. 3372 virtual uint32_t Hash() = 0; 3373 // Returns the hash value for object. 3374 virtual uint32_t HashForObject(Object* key) = 0; 3375 // Returns the key object for storing into the hash table. 3376 MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate) = 0; 3377 // Required. 3378 virtual ~HashTableKey() {} 3379 }; 3380 3381 3382 class StringTableShape : public BaseShape<HashTableKey*> { 3383 public: 3384 static inline bool IsMatch(HashTableKey* key, Object* value) { 3385 return key->IsMatch(value); 3386 } 3387 3388 static inline uint32_t Hash(HashTableKey* key) { 3389 return key->Hash(); 3390 } 3391 3392 static inline uint32_t HashForObject(HashTableKey* key, Object* object) { 3393 return key->HashForObject(object); 3394 } 3395 3396 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); 3397 3398 static const int kPrefixSize = 0; 3399 static const int kEntrySize = 1; 3400 }; 3401 3402 class SeqOneByteString; 3403 3404 // StringTable. 3405 // 3406 // No special elements in the prefix and the element size is 1 3407 // because only the string itself (the key) needs to be stored. 3408 class StringTable: public HashTable<StringTable, 3409 StringTableShape, 3410 HashTableKey*> { 3411 public: 3412 // Find string in the string table. If it is not there yet, it is 3413 // added. The return value is the string found. 3414 static Handle<String> LookupString(Isolate* isolate, Handle<String> key); 3415 static Handle<String> LookupKey(Isolate* isolate, HashTableKey* key); 3416 3417 // Tries to internalize given string and returns string handle on success 3418 // or an empty handle otherwise. 3419 MUST_USE_RESULT static MaybeHandle<String> InternalizeStringIfExists( 3420 Isolate* isolate, 3421 Handle<String> string); 3422 3423 // Looks up a string that is equal to the given string and returns 3424 // string handle if it is found, or an empty handle otherwise. 3425 MUST_USE_RESULT static MaybeHandle<String> LookupStringIfExists( 3426 Isolate* isolate, 3427 Handle<String> str); 3428 MUST_USE_RESULT static MaybeHandle<String> LookupTwoCharsStringIfExists( 3429 Isolate* isolate, 3430 uint16_t c1, 3431 uint16_t c2); 3432 3433 DECLARE_CAST(StringTable) 3434 3435 private: 3436 template <bool seq_one_byte> 3437 friend class JsonParser; 3438 3439 DISALLOW_IMPLICIT_CONSTRUCTORS(StringTable); 3440 }; 3441 3442 3443 class MapCacheShape : public BaseShape<HashTableKey*> { 3444 public: 3445 static inline bool IsMatch(HashTableKey* key, Object* value) { 3446 return key->IsMatch(value); 3447 } 3448 3449 static inline uint32_t Hash(HashTableKey* key) { 3450 return key->Hash(); 3451 } 3452 3453 static inline uint32_t HashForObject(HashTableKey* key, Object* object) { 3454 return key->HashForObject(object); 3455 } 3456 3457 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); 3458 3459 static const int kPrefixSize = 0; 3460 static const int kEntrySize = 2; 3461 }; 3462 3463 3464 // MapCache. 3465 // 3466 // Maps keys that are a fixed array of unique names to a map. 3467 // Used for canonicalize maps for object literals. 3468 class MapCache: public HashTable<MapCache, MapCacheShape, HashTableKey*> { 3469 public: 3470 // Find cached value for a name key, otherwise return null. 3471 Object* Lookup(FixedArray* key); 3472 static Handle<MapCache> Put( 3473 Handle<MapCache> map_cache, Handle<FixedArray> key, Handle<Map> value); 3474 DECLARE_CAST(MapCache) 3475 3476 private: 3477 DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache); 3478 }; 3479 3480 3481 template <typename Derived, typename Shape, typename Key> 3482 class Dictionary: public HashTable<Derived, Shape, Key> { 3483 protected: 3484 typedef HashTable<Derived, Shape, Key> DerivedHashTable; 3485 3486 public: 3487 // Returns the value at entry. 3488 Object* ValueAt(int entry) { 3489 return this->get(DerivedHashTable::EntryToIndex(entry) + 1); 3490 } 3491 3492 // Set the value for entry. 3493 void ValueAtPut(int entry, Object* value) { 3494 this->set(DerivedHashTable::EntryToIndex(entry) + 1, value); 3495 } 3496 3497 // Returns the property details for the property at entry. 3498 PropertyDetails DetailsAt(int entry) { 3499 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 3500 return PropertyDetails( 3501 Smi::cast(this->get(DerivedHashTable::EntryToIndex(entry) + 2))); 3502 } 3503 3504 // Set the details for entry. 3505 void DetailsAtPut(int entry, PropertyDetails value) { 3506 this->set(DerivedHashTable::EntryToIndex(entry) + 2, value.AsSmi()); 3507 } 3508 3509 // Sorting support 3510 void CopyValuesTo(FixedArray* elements); 3511 3512 // Delete a property from the dictionary. 3513 static Handle<Object> DeleteProperty( 3514 Handle<Derived> dictionary, 3515 int entry, 3516 JSObject::DeleteMode mode); 3517 3518 // Attempt to shrink the dictionary after deletion of key. 3519 MUST_USE_RESULT static inline Handle<Derived> Shrink( 3520 Handle<Derived> dictionary, 3521 Key key) { 3522 return DerivedHashTable::Shrink(dictionary, key); 3523 } 3524 3525 // Returns the number of elements in the dictionary filtering out properties 3526 // with the specified attributes. 3527 int NumberOfElementsFilterAttributes(PropertyAttributes filter); 3528 3529 // Returns the number of enumerable elements in the dictionary. 3530 int NumberOfEnumElements(); 3531 3532 enum SortMode { UNSORTED, SORTED }; 3533 // Copies keys to preallocated fixed array. 3534 void CopyKeysTo(FixedArray* storage, 3535 PropertyAttributes filter, 3536 SortMode sort_mode); 3537 // Fill in details for properties into storage. 3538 void CopyKeysTo(FixedArray* storage, 3539 int index, 3540 PropertyAttributes filter, 3541 SortMode sort_mode); 3542 3543 // Accessors for next enumeration index. 3544 void SetNextEnumerationIndex(int index) { 3545 DCHECK(index != 0); 3546 this->set(kNextEnumerationIndexIndex, Smi::FromInt(index)); 3547 } 3548 3549 int NextEnumerationIndex() { 3550 return Smi::cast(this->get(kNextEnumerationIndexIndex))->value(); 3551 } 3552 3553 // Creates a new dictionary. 3554 MUST_USE_RESULT static Handle<Derived> New( 3555 Isolate* isolate, 3556 int at_least_space_for, 3557 PretenureFlag pretenure = NOT_TENURED); 3558 3559 // Ensure enough space for n additional elements. 3560 static Handle<Derived> EnsureCapacity(Handle<Derived> obj, int n, Key key); 3561 3562 #ifdef OBJECT_PRINT 3563 void Print(OStream& os); // NOLINT 3564 #endif 3565 // Returns the key (slow). 3566 Object* SlowReverseLookup(Object* value); 3567 3568 // Sets the entry to (key, value) pair. 3569 inline void SetEntry(int entry, 3570 Handle<Object> key, 3571 Handle<Object> value); 3572 inline void SetEntry(int entry, 3573 Handle<Object> key, 3574 Handle<Object> value, 3575 PropertyDetails details); 3576 3577 MUST_USE_RESULT static Handle<Derived> Add( 3578 Handle<Derived> dictionary, 3579 Key key, 3580 Handle<Object> value, 3581 PropertyDetails details); 3582 3583 protected: 3584 // Generic at put operation. 3585 MUST_USE_RESULT static Handle<Derived> AtPut( 3586 Handle<Derived> dictionary, 3587 Key key, 3588 Handle<Object> value); 3589 3590 // Add entry to dictionary. 3591 static void AddEntry( 3592 Handle<Derived> dictionary, 3593 Key key, 3594 Handle<Object> value, 3595 PropertyDetails details, 3596 uint32_t hash); 3597 3598 // Generate new enumeration indices to avoid enumeration index overflow. 3599 static void GenerateNewEnumerationIndices(Handle<Derived> dictionary); 3600 static const int kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex; 3601 static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; 3602 }; 3603 3604 3605 class NameDictionaryShape : public BaseShape<Handle<Name> > { 3606 public: 3607 static inline bool IsMatch(Handle<Name> key, Object* other); 3608 static inline uint32_t Hash(Handle<Name> key); 3609 static inline uint32_t HashForObject(Handle<Name> key, Object* object); 3610 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key); 3611 static const int kPrefixSize = 2; 3612 static const int kEntrySize = 3; 3613 static const bool kIsEnumerable = true; 3614 }; 3615 3616 3617 class NameDictionary: public Dictionary<NameDictionary, 3618 NameDictionaryShape, 3619 Handle<Name> > { 3620 typedef Dictionary< 3621 NameDictionary, NameDictionaryShape, Handle<Name> > DerivedDictionary; 3622 3623 public: 3624 DECLARE_CAST(NameDictionary) 3625 3626 // Copies enumerable keys to preallocated fixed array. 3627 void CopyEnumKeysTo(FixedArray* storage); 3628 inline static void DoGenerateNewEnumerationIndices( 3629 Handle<NameDictionary> dictionary); 3630 3631 // Find entry for key, otherwise return kNotFound. Optimized version of 3632 // HashTable::FindEntry. 3633 int FindEntry(Handle<Name> key); 3634 }; 3635 3636 3637 class NumberDictionaryShape : public BaseShape<uint32_t> { 3638 public: 3639 static inline bool IsMatch(uint32_t key, Object* other); 3640 static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key); 3641 static const int kEntrySize = 3; 3642 static const bool kIsEnumerable = false; 3643 }; 3644 3645 3646 class SeededNumberDictionaryShape : public NumberDictionaryShape { 3647 public: 3648 static const bool UsesSeed = true; 3649 static const int kPrefixSize = 2; 3650 3651 static inline uint32_t SeededHash(uint32_t key, uint32_t seed); 3652 static inline uint32_t SeededHashForObject(uint32_t key, 3653 uint32_t seed, 3654 Object* object); 3655 }; 3656 3657 3658 class UnseededNumberDictionaryShape : public NumberDictionaryShape { 3659 public: 3660 static const int kPrefixSize = 0; 3661 3662 static inline uint32_t Hash(uint32_t key); 3663 static inline uint32_t HashForObject(uint32_t key, Object* object); 3664 }; 3665 3666 3667 class SeededNumberDictionary 3668 : public Dictionary<SeededNumberDictionary, 3669 SeededNumberDictionaryShape, 3670 uint32_t> { 3671 public: 3672 DECLARE_CAST(SeededNumberDictionary) 3673 3674 // Type specific at put (default NONE attributes is used when adding). 3675 MUST_USE_RESULT static Handle<SeededNumberDictionary> AtNumberPut( 3676 Handle<SeededNumberDictionary> dictionary, 3677 uint32_t key, 3678 Handle<Object> value); 3679 MUST_USE_RESULT static Handle<SeededNumberDictionary> AddNumberEntry( 3680 Handle<SeededNumberDictionary> dictionary, 3681 uint32_t key, 3682 Handle<Object> value, 3683 PropertyDetails details); 3684 3685 // Set an existing entry or add a new one if needed. 3686 // Return the updated dictionary. 3687 MUST_USE_RESULT static Handle<SeededNumberDictionary> Set( 3688 Handle<SeededNumberDictionary> dictionary, 3689 uint32_t key, 3690 Handle<Object> value, 3691 PropertyDetails details); 3692 3693 void UpdateMaxNumberKey(uint32_t key); 3694 3695 // If slow elements are required we will never go back to fast-case 3696 // for the elements kept in this dictionary. We require slow 3697 // elements if an element has been added at an index larger than 3698 // kRequiresSlowElementsLimit or set_requires_slow_elements() has been called 3699 // when defining a getter or setter with a number key. 3700 inline bool requires_slow_elements(); 3701 inline void set_requires_slow_elements(); 3702 3703 // Get the value of the max number key that has been added to this 3704 // dictionary. max_number_key can only be called if 3705 // requires_slow_elements returns false. 3706 inline uint32_t max_number_key(); 3707 3708 // Bit masks. 3709 static const int kRequiresSlowElementsMask = 1; 3710 static const int kRequiresSlowElementsTagSize = 1; 3711 static const uint32_t kRequiresSlowElementsLimit = (1 << 29) - 1; 3712 }; 3713 3714 3715 class UnseededNumberDictionary 3716 : public Dictionary<UnseededNumberDictionary, 3717 UnseededNumberDictionaryShape, 3718 uint32_t> { 3719 public: 3720 DECLARE_CAST(UnseededNumberDictionary) 3721 3722 // Type specific at put (default NONE attributes is used when adding). 3723 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AtNumberPut( 3724 Handle<UnseededNumberDictionary> dictionary, 3725 uint32_t key, 3726 Handle<Object> value); 3727 MUST_USE_RESULT static Handle<UnseededNumberDictionary> AddNumberEntry( 3728 Handle<UnseededNumberDictionary> dictionary, 3729 uint32_t key, 3730 Handle<Object> value); 3731 3732 // Set an existing entry or add a new one if needed. 3733 // Return the updated dictionary. 3734 MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set( 3735 Handle<UnseededNumberDictionary> dictionary, 3736 uint32_t key, 3737 Handle<Object> value); 3738 }; 3739 3740 3741 class ObjectHashTableShape : public BaseShape<Handle<Object> > { 3742 public: 3743 static inline bool IsMatch(Handle<Object> key, Object* other); 3744 static inline uint32_t Hash(Handle<Object> key); 3745 static inline uint32_t HashForObject(Handle<Object> key, Object* object); 3746 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key); 3747 static const int kPrefixSize = 0; 3748 static const int kEntrySize = 2; 3749 }; 3750 3751 3752 // ObjectHashTable maps keys that are arbitrary objects to object values by 3753 // using the identity hash of the key for hashing purposes. 3754 class ObjectHashTable: public HashTable<ObjectHashTable, 3755 ObjectHashTableShape, 3756 Handle<Object> > { 3757 typedef HashTable< 3758 ObjectHashTable, ObjectHashTableShape, Handle<Object> > DerivedHashTable; 3759 public: 3760 DECLARE_CAST(ObjectHashTable) 3761 3762 // Attempt to shrink hash table after removal of key. 3763 MUST_USE_RESULT static inline Handle<ObjectHashTable> Shrink( 3764 Handle<ObjectHashTable> table, 3765 Handle<Object> key); 3766 3767 // Looks up the value associated with the given key. The hole value is 3768 // returned in case the key is not present. 3769 Object* Lookup(Handle<Object> key); 3770 3771 // Adds (or overwrites) the value associated with the given key. 3772 static Handle<ObjectHashTable> Put(Handle<ObjectHashTable> table, 3773 Handle<Object> key, 3774 Handle<Object> value); 3775 3776 // Returns an ObjectHashTable (possibly |table|) where |key| has been removed. 3777 static Handle<ObjectHashTable> Remove(Handle<ObjectHashTable> table, 3778 Handle<Object> key, 3779 bool* was_present); 3780 3781 private: 3782 friend class MarkCompactCollector; 3783 3784 void AddEntry(int entry, Object* key, Object* value); 3785 void RemoveEntry(int entry); 3786 3787 // Returns the index to the value of an entry. 3788 static inline int EntryToValueIndex(int entry) { 3789 return EntryToIndex(entry) + 1; 3790 } 3791 }; 3792 3793 3794 // OrderedHashTable is a HashTable with Object keys that preserves 3795 // insertion order. There are Map and Set interfaces (OrderedHashMap 3796 // and OrderedHashTable, below). It is meant to be used by JSMap/JSSet. 3797 // 3798 // Only Object* keys are supported, with Object::SameValueZero() used as the 3799 // equality operator and Object::GetHash() for the hash function. 3800 // 3801 // Based on the "Deterministic Hash Table" as described by Jason Orendorff at 3802 // https://wiki.mozilla.org/User:Jorend/Deterministic_hash_tables 3803 // Originally attributed to Tyler Close. 3804 // 3805 // Memory layout: 3806 // [0]: bucket count 3807 // [1]: element count 3808 // [2]: deleted element count 3809 // [3..(3 + NumberOfBuckets() - 1)]: "hash table", where each item is an 3810 // offset into the data table (see below) where the 3811 // first item in this bucket is stored. 3812 // [3 + NumberOfBuckets()..length]: "data table", an array of length 3813 // Capacity() * kEntrySize, where the first entrysize 3814 // items are handled by the derived class and the 3815 // item at kChainOffset is another entry into the 3816 // data table indicating the next entry in this hash 3817 // bucket. 3818 // 3819 // When we transition the table to a new version we obsolete it and reuse parts 3820 // of the memory to store information how to transition an iterator to the new 3821 // table: 3822 // 3823 // Memory layout for obsolete table: 3824 // [0]: bucket count 3825 // [1]: Next newer table 3826 // [2]: Number of removed holes or -1 when the table was cleared. 3827 // [3..(3 + NumberOfRemovedHoles() - 1)]: The indexes of the removed holes. 3828 // [3 + NumberOfRemovedHoles()..length]: Not used 3829 // 3830 template<class Derived, class Iterator, int entrysize> 3831 class OrderedHashTable: public FixedArray { 3832 public: 3833 // Returns an OrderedHashTable with a capacity of at least |capacity|. 3834 static Handle<Derived> Allocate( 3835 Isolate* isolate, int capacity, PretenureFlag pretenure = NOT_TENURED); 3836 3837 // Returns an OrderedHashTable (possibly |table|) with enough space 3838 // to add at least one new element. 3839 static Handle<Derived> EnsureGrowable(Handle<Derived> table); 3840 3841 // Returns an OrderedHashTable (possibly |table|) that's shrunken 3842 // if possible. 3843 static Handle<Derived> Shrink(Handle<Derived> table); 3844 3845 // Returns a new empty OrderedHashTable and records the clearing so that 3846 // exisiting iterators can be updated. 3847 static Handle<Derived> Clear(Handle<Derived> table); 3848 3849 // Returns an OrderedHashTable (possibly |table|) where |key| has been 3850 // removed. 3851 static Handle<Derived> Remove(Handle<Derived> table, Handle<Object> key, 3852 bool* was_present); 3853 3854 // Returns kNotFound if the key isn't present. 3855 int FindEntry(Handle<Object> key, int hash); 3856 3857 // Like the above, but doesn't require the caller to provide a hash. 3858 int FindEntry(Handle<Object> key); 3859 3860 int NumberOfElements() { 3861 return Smi::cast(get(kNumberOfElementsIndex))->value(); 3862 } 3863 3864 int NumberOfDeletedElements() { 3865 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 3866 } 3867 3868 int UsedCapacity() { return NumberOfElements() + NumberOfDeletedElements(); } 3869 3870 int NumberOfBuckets() { 3871 return Smi::cast(get(kNumberOfBucketsIndex))->value(); 3872 } 3873 3874 // Returns the index into the data table where the new entry 3875 // should be placed. The table is assumed to have enough space 3876 // for a new entry. 3877 int AddEntry(int hash); 3878 3879 // Removes the entry, and puts the_hole in entrysize pointers 3880 // (leaving the hash table chain intact). 3881 void RemoveEntry(int entry); 3882 3883 // Returns an index into |this| for the given entry. 3884 int EntryToIndex(int entry) { 3885 return kHashTableStartIndex + NumberOfBuckets() + (entry * kEntrySize); 3886 } 3887 3888 Object* KeyAt(int entry) { return get(EntryToIndex(entry)); } 3889 3890 bool IsObsolete() { 3891 return !get(kNextTableIndex)->IsSmi(); 3892 } 3893 3894 // The next newer table. This is only valid if the table is obsolete. 3895 Derived* NextTable() { 3896 return Derived::cast(get(kNextTableIndex)); 3897 } 3898 3899 // When the table is obsolete we store the indexes of the removed holes. 3900 int RemovedIndexAt(int index) { 3901 return Smi::cast(get(kRemovedHolesIndex + index))->value(); 3902 } 3903 3904 static const int kNotFound = -1; 3905 static const int kMinCapacity = 4; 3906 3907 private: 3908 static Handle<Derived> Rehash(Handle<Derived> table, int new_capacity); 3909 3910 void SetNumberOfBuckets(int num) { 3911 set(kNumberOfBucketsIndex, Smi::FromInt(num)); 3912 } 3913 3914 void SetNumberOfElements(int num) { 3915 set(kNumberOfElementsIndex, Smi::FromInt(num)); 3916 } 3917 3918 void SetNumberOfDeletedElements(int num) { 3919 set(kNumberOfDeletedElementsIndex, Smi::FromInt(num)); 3920 } 3921 3922 int Capacity() { 3923 return NumberOfBuckets() * kLoadFactor; 3924 } 3925 3926 // Returns the next entry for the given entry. 3927 int ChainAt(int entry) { 3928 return Smi::cast(get(EntryToIndex(entry) + kChainOffset))->value(); 3929 } 3930 3931 int HashToBucket(int hash) { 3932 return hash & (NumberOfBuckets() - 1); 3933 } 3934 3935 int HashToEntry(int hash) { 3936 int bucket = HashToBucket(hash); 3937 return Smi::cast(get(kHashTableStartIndex + bucket))->value(); 3938 } 3939 3940 void SetNextTable(Derived* next_table) { 3941 set(kNextTableIndex, next_table); 3942 } 3943 3944 void SetRemovedIndexAt(int index, int removed_index) { 3945 return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index)); 3946 } 3947 3948 static const int kNumberOfBucketsIndex = 0; 3949 static const int kNumberOfElementsIndex = kNumberOfBucketsIndex + 1; 3950 static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1; 3951 static const int kHashTableStartIndex = kNumberOfDeletedElementsIndex + 1; 3952 3953 static const int kNextTableIndex = kNumberOfElementsIndex; 3954 static const int kRemovedHolesIndex = kHashTableStartIndex; 3955 3956 static const int kEntrySize = entrysize + 1; 3957 static const int kChainOffset = entrysize; 3958 3959 static const int kLoadFactor = 2; 3960 static const int kMaxCapacity = 3961 (FixedArray::kMaxLength - kHashTableStartIndex) 3962 / (1 + (kEntrySize * kLoadFactor)); 3963 }; 3964 3965 3966 class JSSetIterator; 3967 3968 3969 class OrderedHashSet: public OrderedHashTable< 3970 OrderedHashSet, JSSetIterator, 1> { 3971 public: 3972 DECLARE_CAST(OrderedHashSet) 3973 3974 bool Contains(Handle<Object> key); 3975 static Handle<OrderedHashSet> Add( 3976 Handle<OrderedHashSet> table, Handle<Object> key); 3977 }; 3978 3979 3980 class JSMapIterator; 3981 3982 3983 class OrderedHashMap:public OrderedHashTable< 3984 OrderedHashMap, JSMapIterator, 2> { 3985 public: 3986 DECLARE_CAST(OrderedHashMap) 3987 3988 Object* Lookup(Handle<Object> key); 3989 static Handle<OrderedHashMap> Put( 3990 Handle<OrderedHashMap> table, 3991 Handle<Object> key, 3992 Handle<Object> value); 3993 3994 Object* ValueAt(int entry) { 3995 return get(EntryToIndex(entry) + kValueOffset); 3996 } 3997 3998 private: 3999 static const int kValueOffset = 1; 4000 }; 4001 4002 4003 template <int entrysize> 4004 class WeakHashTableShape : public BaseShape<Handle<Object> > { 4005 public: 4006 static inline bool IsMatch(Handle<Object> key, Object* other); 4007 static inline uint32_t Hash(Handle<Object> key); 4008 static inline uint32_t HashForObject(Handle<Object> key, Object* object); 4009 static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Object> key); 4010 static const int kPrefixSize = 0; 4011 static const int kEntrySize = entrysize; 4012 }; 4013 4014 4015 // WeakHashTable maps keys that are arbitrary objects to object values. 4016 // It is used for the global weak hash table that maps objects 4017 // embedded in optimized code to dependent code lists. 4018 class WeakHashTable: public HashTable<WeakHashTable, 4019 WeakHashTableShape<2>, 4020 Handle<Object> > { 4021 typedef HashTable< 4022 WeakHashTable, WeakHashTableShape<2>, Handle<Object> > DerivedHashTable; 4023 public: 4024 DECLARE_CAST(WeakHashTable) 4025 4026 // Looks up the value associated with the given key. The hole value is 4027 // returned in case the key is not present. 4028 Object* Lookup(Handle<Object> key); 4029 4030 // Adds (or overwrites) the value associated with the given key. Mapping a 4031 // key to the hole value causes removal of the whole entry. 4032 MUST_USE_RESULT static Handle<WeakHashTable> Put(Handle<WeakHashTable> table, 4033 Handle<Object> key, 4034 Handle<Object> value); 4035 4036 // This function is called when heap verification is turned on. 4037 void Zap(Object* value) { 4038 int capacity = Capacity(); 4039 for (int i = 0; i < capacity; i++) { 4040 set(EntryToIndex(i), value); 4041 set(EntryToValueIndex(i), value); 4042 } 4043 } 4044 4045 private: 4046 friend class MarkCompactCollector; 4047 4048 void AddEntry(int entry, Handle<Object> key, Handle<Object> value); 4049 4050 // Returns the index to the value of an entry. 4051 static inline int EntryToValueIndex(int entry) { 4052 return EntryToIndex(entry) + 1; 4053 } 4054 }; 4055 4056 4057 // JSFunctionResultCache caches results of some JSFunction invocation. 4058 // It is a fixed array with fixed structure: 4059 // [0]: factory function 4060 // [1]: finger index 4061 // [2]: current cache size 4062 // [3]: dummy field. 4063 // The rest of array are key/value pairs. 4064 class JSFunctionResultCache: public FixedArray { 4065 public: 4066 static const int kFactoryIndex = 0; 4067 static const int kFingerIndex = kFactoryIndex + 1; 4068 static const int kCacheSizeIndex = kFingerIndex + 1; 4069 static const int kDummyIndex = kCacheSizeIndex + 1; 4070 static const int kEntriesIndex = kDummyIndex + 1; 4071 4072 static const int kEntrySize = 2; // key + value 4073 4074 static const int kFactoryOffset = kHeaderSize; 4075 static const int kFingerOffset = kFactoryOffset + kPointerSize; 4076 static const int kCacheSizeOffset = kFingerOffset + kPointerSize; 4077 4078 inline void MakeZeroSize(); 4079 inline void Clear(); 4080 4081 inline int size(); 4082 inline void set_size(int size); 4083 inline int finger_index(); 4084 inline void set_finger_index(int finger_index); 4085 4086 DECLARE_CAST(JSFunctionResultCache) 4087 4088 DECLARE_VERIFIER(JSFunctionResultCache) 4089 }; 4090 4091 4092 // ScopeInfo represents information about different scopes of a source 4093 // program and the allocation of the scope's variables. Scope information 4094 // is stored in a compressed form in ScopeInfo objects and is used 4095 // at runtime (stack dumps, deoptimization, etc.). 4096 4097 // This object provides quick access to scope info details for runtime 4098 // routines. 4099 class ScopeInfo : public FixedArray { 4100 public: 4101 DECLARE_CAST(ScopeInfo) 4102 4103 // Return the type of this scope. 4104 ScopeType scope_type(); 4105 4106 // Does this scope call eval? 4107 bool CallsEval(); 4108 4109 // Return the strict mode of this scope. 4110 StrictMode strict_mode(); 4111 4112 // Does this scope make a sloppy eval call? 4113 bool CallsSloppyEval() { return CallsEval() && strict_mode() == SLOPPY; } 4114 4115 // Return the total number of locals allocated on the stack and in the 4116 // context. This includes the parameters that are allocated in the context. 4117 int LocalCount(); 4118 4119 // Return the number of stack slots for code. This number consists of two 4120 // parts: 4121 // 1. One stack slot per stack allocated local. 4122 // 2. One stack slot for the function name if it is stack allocated. 4123 int StackSlotCount(); 4124 4125 // Return the number of context slots for code if a context is allocated. This 4126 // number consists of three parts: 4127 // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS 4128 // 2. One context slot per context allocated local. 4129 // 3. One context slot for the function name if it is context allocated. 4130 // Parameters allocated in the context count as context allocated locals. If 4131 // no contexts are allocated for this scope ContextLength returns 0. 4132 int ContextLength(); 4133 4134 // Is this scope the scope of a named function expression? 4135 bool HasFunctionName(); 4136 4137 // Return if this has context allocated locals. 4138 bool HasHeapAllocatedLocals(); 4139 4140 // Return if contexts are allocated for this scope. 4141 bool HasContext(); 4142 4143 // Return if this is a function scope with "use asm". 4144 bool IsAsmModule() { return AsmModuleField::decode(Flags()); } 4145 4146 // Return if this is a nested function within an asm module scope. 4147 bool IsAsmFunction() { return AsmFunctionField::decode(Flags()); } 4148 4149 // Return the function_name if present. 4150 String* FunctionName(); 4151 4152 // Return the name of the given parameter. 4153 String* ParameterName(int var); 4154 4155 // Return the name of the given local. 4156 String* LocalName(int var); 4157 4158 // Return the name of the given stack local. 4159 String* StackLocalName(int var); 4160 4161 // Return the name of the given context local. 4162 String* ContextLocalName(int var); 4163 4164 // Return the mode of the given context local. 4165 VariableMode ContextLocalMode(int var); 4166 4167 // Return the initialization flag of the given context local. 4168 InitializationFlag ContextLocalInitFlag(int var); 4169 4170 // Return the initialization flag of the given context local. 4171 MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var); 4172 4173 // Return true if this local was introduced by the compiler, and should not be 4174 // exposed to the user in a debugger. 4175 bool LocalIsSynthetic(int var); 4176 4177 // Lookup support for serialized scope info. Returns the 4178 // the stack slot index for a given slot name if the slot is 4179 // present; otherwise returns a value < 0. The name must be an internalized 4180 // string. 4181 int StackSlotIndex(String* name); 4182 4183 // Lookup support for serialized scope info. Returns the 4184 // context slot index for a given slot name if the slot is present; otherwise 4185 // returns a value < 0. The name must be an internalized string. 4186 // If the slot is present and mode != NULL, sets *mode to the corresponding 4187 // mode for that variable. 4188 static int ContextSlotIndex(Handle<ScopeInfo> scope_info, Handle<String> name, 4189 VariableMode* mode, InitializationFlag* init_flag, 4190 MaybeAssignedFlag* maybe_assigned_flag); 4191 4192 // Lookup support for serialized scope info. Returns the 4193 // parameter index for a given parameter name if the parameter is present; 4194 // otherwise returns a value < 0. The name must be an internalized string. 4195 int ParameterIndex(String* name); 4196 4197 // Lookup support for serialized scope info. Returns the function context 4198 // slot index if the function name is present and context-allocated (named 4199 // function expressions, only), otherwise returns a value < 0. The name 4200 // must be an internalized string. 4201 int FunctionContextSlotIndex(String* name, VariableMode* mode); 4202 4203 4204 // Copies all the context locals into an object used to materialize a scope. 4205 static bool CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info, 4206 Handle<Context> context, 4207 Handle<JSObject> scope_object); 4208 4209 4210 static Handle<ScopeInfo> Create(Scope* scope, Zone* zone); 4211 4212 // Serializes empty scope info. 4213 static ScopeInfo* Empty(Isolate* isolate); 4214 4215 #ifdef DEBUG 4216 void Print(); 4217 #endif 4218 4219 // The layout of the static part of a ScopeInfo is as follows. Each entry is 4220 // numeric and occupies one array slot. 4221 // 1. A set of properties of the scope 4222 // 2. The number of parameters. This only applies to function scopes. For 4223 // non-function scopes this is 0. 4224 // 3. The number of non-parameter variables allocated on the stack. 4225 // 4. The number of non-parameter and parameter variables allocated in the 4226 // context. 4227 #define FOR_EACH_NUMERIC_FIELD(V) \ 4228 V(Flags) \ 4229 V(ParameterCount) \ 4230 V(StackLocalCount) \ 4231 V(ContextLocalCount) 4232 4233 #define FIELD_ACCESSORS(name) \ 4234 void Set##name(int value) { \ 4235 set(k##name, Smi::FromInt(value)); \ 4236 } \ 4237 int name() { \ 4238 if (length() > 0) { \ 4239 return Smi::cast(get(k##name))->value(); \ 4240 } else { \ 4241 return 0; \ 4242 } \ 4243 } 4244 FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS) 4245 #undef FIELD_ACCESSORS 4246 4247 private: 4248 enum { 4249 #define DECL_INDEX(name) k##name, 4250 FOR_EACH_NUMERIC_FIELD(DECL_INDEX) 4251 #undef DECL_INDEX 4252 #undef FOR_EACH_NUMERIC_FIELD 4253 kVariablePartIndex 4254 }; 4255 4256 // The layout of the variable part of a ScopeInfo is as follows: 4257 // 1. ParameterEntries: 4258 // This part stores the names of the parameters for function scopes. One 4259 // slot is used per parameter, so in total this part occupies 4260 // ParameterCount() slots in the array. For other scopes than function 4261 // scopes ParameterCount() is 0. 4262 // 2. StackLocalEntries: 4263 // Contains the names of local variables that are allocated on the stack, 4264 // in increasing order of the stack slot index. One slot is used per stack 4265 // local, so in total this part occupies StackLocalCount() slots in the 4266 // array. 4267 // 3. ContextLocalNameEntries: 4268 // Contains the names of local variables and parameters that are allocated 4269 // in the context. They are stored in increasing order of the context slot 4270 // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per 4271 // context local, so in total this part occupies ContextLocalCount() slots 4272 // in the array. 4273 // 4. ContextLocalInfoEntries: 4274 // Contains the variable modes and initialization flags corresponding to 4275 // the context locals in ContextLocalNameEntries. One slot is used per 4276 // context local, so in total this part occupies ContextLocalCount() 4277 // slots in the array. 4278 // 5. FunctionNameEntryIndex: 4279 // If the scope belongs to a named function expression this part contains 4280 // information about the function variable. It always occupies two array 4281 // slots: a. The name of the function variable. 4282 // b. The context or stack slot index for the variable. 4283 int ParameterEntriesIndex(); 4284 int StackLocalEntriesIndex(); 4285 int ContextLocalNameEntriesIndex(); 4286 int ContextLocalInfoEntriesIndex(); 4287 int FunctionNameEntryIndex(); 4288 4289 // Location of the function variable for named function expressions. 4290 enum FunctionVariableInfo { 4291 NONE, // No function name present. 4292 STACK, // Function 4293 CONTEXT, 4294 UNUSED 4295 }; 4296 4297 // Properties of scopes. 4298 class ScopeTypeField: public BitField<ScopeType, 0, 3> {}; 4299 class CallsEvalField: public BitField<bool, 3, 1> {}; 4300 class StrictModeField: public BitField<StrictMode, 4, 1> {}; 4301 class FunctionVariableField: public BitField<FunctionVariableInfo, 5, 2> {}; 4302 class FunctionVariableMode: public BitField<VariableMode, 7, 3> {}; 4303 class AsmModuleField : public BitField<bool, 10, 1> {}; 4304 class AsmFunctionField : public BitField<bool, 11, 1> {}; 4305 4306 // BitFields representing the encoded information for context locals in the 4307 // ContextLocalInfoEntries part. 4308 class ContextLocalMode: public BitField<VariableMode, 0, 3> {}; 4309 class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {}; 4310 class ContextLocalMaybeAssignedFlag 4311 : public BitField<MaybeAssignedFlag, 4, 1> {}; 4312 }; 4313 4314 4315 // The cache for maps used by normalized (dictionary mode) objects. 4316 // Such maps do not have property descriptors, so a typical program 4317 // needs very limited number of distinct normalized maps. 4318 class NormalizedMapCache: public FixedArray { 4319 public: 4320 static Handle<NormalizedMapCache> New(Isolate* isolate); 4321 4322 MUST_USE_RESULT MaybeHandle<Map> Get(Handle<Map> fast_map, 4323 PropertyNormalizationMode mode); 4324 void Set(Handle<Map> fast_map, Handle<Map> normalized_map); 4325 4326 void Clear(); 4327 4328 DECLARE_CAST(NormalizedMapCache) 4329 4330 static inline bool IsNormalizedMapCache(const Object* obj); 4331 4332 DECLARE_VERIFIER(NormalizedMapCache) 4333 private: 4334 static const int kEntries = 64; 4335 4336 static inline int GetIndex(Handle<Map> map); 4337 4338 // The following declarations hide base class methods. 4339 Object* get(int index); 4340 void set(int index, Object* value); 4341 }; 4342 4343 4344 // ByteArray represents fixed sized byte arrays. Used for the relocation info 4345 // that is attached to code objects. 4346 class ByteArray: public FixedArrayBase { 4347 public: 4348 inline int Size() { return RoundUp(length() + kHeaderSize, kPointerSize); } 4349 4350 // Setter and getter. 4351 inline byte get(int index); 4352 inline void set(int index, byte value); 4353 4354 // Treat contents as an int array. 4355 inline int get_int(int index); 4356 4357 static int SizeFor(int length) { 4358 return OBJECT_POINTER_ALIGN(kHeaderSize + length); 4359 } 4360 // We use byte arrays for free blocks in the heap. Given a desired size in 4361 // bytes that is a multiple of the word size and big enough to hold a byte 4362 // array, this function returns the number of elements a byte array should 4363 // have. 4364 static int LengthFor(int size_in_bytes) { 4365 DCHECK(IsAligned(size_in_bytes, kPointerSize)); 4366 DCHECK(size_in_bytes >= kHeaderSize); 4367 return size_in_bytes - kHeaderSize; 4368 } 4369 4370 // Returns data start address. 4371 inline Address GetDataStartAddress(); 4372 4373 // Returns a pointer to the ByteArray object for a given data start address. 4374 static inline ByteArray* FromDataStartAddress(Address address); 4375 4376 DECLARE_CAST(ByteArray) 4377 4378 // Dispatched behavior. 4379 inline int ByteArraySize() { 4380 return SizeFor(this->length()); 4381 } 4382 DECLARE_PRINTER(ByteArray) 4383 DECLARE_VERIFIER(ByteArray) 4384 4385 // Layout description. 4386 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize); 4387 4388 // Maximal memory consumption for a single ByteArray. 4389 static const int kMaxSize = 512 * MB; 4390 // Maximal length of a single ByteArray. 4391 static const int kMaxLength = kMaxSize - kHeaderSize; 4392 4393 private: 4394 DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray); 4395 }; 4396 4397 4398 // FreeSpace represents fixed sized areas of the heap that are not currently in 4399 // use. Used by the heap and GC. 4400 class FreeSpace: public HeapObject { 4401 public: 4402 // [size]: size of the free space including the header. 4403 inline int size() const; 4404 inline void set_size(int value); 4405 4406 inline int nobarrier_size() const; 4407 inline void nobarrier_set_size(int value); 4408 4409 inline int Size() { return size(); } 4410 4411 DECLARE_CAST(FreeSpace) 4412 4413 // Dispatched behavior. 4414 DECLARE_PRINTER(FreeSpace) 4415 DECLARE_VERIFIER(FreeSpace) 4416 4417 // Layout description. 4418 // Size is smi tagged when it is stored. 4419 static const int kSizeOffset = HeapObject::kHeaderSize; 4420 static const int kHeaderSize = kSizeOffset + kPointerSize; 4421 4422 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize); 4423 4424 private: 4425 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeSpace); 4426 }; 4427 4428 4429 // V has parameters (Type, type, TYPE, C type, element_size) 4430 #define TYPED_ARRAYS(V) \ 4431 V(Uint8, uint8, UINT8, uint8_t, 1) \ 4432 V(Int8, int8, INT8, int8_t, 1) \ 4433 V(Uint16, uint16, UINT16, uint16_t, 2) \ 4434 V(Int16, int16, INT16, int16_t, 2) \ 4435 V(Uint32, uint32, UINT32, uint32_t, 4) \ 4436 V(Int32, int32, INT32, int32_t, 4) \ 4437 V(Float32, float32, FLOAT32, float, 4) \ 4438 V(Float64, float64, FLOAT64, double, 8) \ 4439 V(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t, 1) 4440 4441 4442 4443 // An ExternalArray represents a fixed-size array of primitive values 4444 // which live outside the JavaScript heap. Its subclasses are used to 4445 // implement the CanvasArray types being defined in the WebGL 4446 // specification. As of this writing the first public draft is not yet 4447 // available, but Khronos members can access the draft at: 4448 // https://cvs.khronos.org/svn/repos/3dweb/trunk/doc/spec/WebGL-spec.html 4449 // 4450 // The semantics of these arrays differ from CanvasPixelArray. 4451 // Out-of-range values passed to the setter are converted via a C 4452 // cast, not clamping. Out-of-range indices cause exceptions to be 4453 // raised rather than being silently ignored. 4454 class ExternalArray: public FixedArrayBase { 4455 public: 4456 inline bool is_the_hole(int index) { return false; } 4457 4458 // [external_pointer]: The pointer to the external memory area backing this 4459 // external array. 4460 DECL_ACCESSORS(external_pointer, void) // Pointer to the data store. 4461 4462 DECLARE_CAST(ExternalArray) 4463 4464 // Maximal acceptable length for an external array. 4465 static const int kMaxLength = 0x3fffffff; 4466 4467 // ExternalArray headers are not quadword aligned. 4468 static const int kExternalPointerOffset = 4469 POINTER_SIZE_ALIGN(FixedArrayBase::kLengthOffset + kPointerSize); 4470 static const int kHeaderSize = kExternalPointerOffset + kPointerSize; 4471 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize); 4472 4473 private: 4474 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalArray); 4475 }; 4476 4477 4478 // A ExternalUint8ClampedArray represents a fixed-size byte array with special 4479 // semantics used for implementing the CanvasPixelArray object. Please see the 4480 // specification at: 4481 4482 // http://www.whatwg.org/specs/web-apps/current-work/ 4483 // multipage/the-canvas-element.html#canvaspixelarray 4484 // In particular, write access clamps the value written to 0 or 255 if the 4485 // value written is outside this range. 4486 class ExternalUint8ClampedArray: public ExternalArray { 4487 public: 4488 inline uint8_t* external_uint8_clamped_pointer(); 4489 4490 // Setter and getter. 4491 inline uint8_t get_scalar(int index); 4492 static inline Handle<Object> get(Handle<ExternalUint8ClampedArray> array, 4493 int index); 4494 inline void set(int index, uint8_t value); 4495 4496 // This accessor applies the correct conversion from Smi, HeapNumber 4497 // and undefined and clamps the converted value between 0 and 255. 4498 static Handle<Object> SetValue(Handle<ExternalUint8ClampedArray> array, 4499 uint32_t index, 4500 Handle<Object> value); 4501 4502 DECLARE_CAST(ExternalUint8ClampedArray) 4503 4504 // Dispatched behavior. 4505 DECLARE_PRINTER(ExternalUint8ClampedArray) 4506 DECLARE_VERIFIER(ExternalUint8ClampedArray) 4507 4508 private: 4509 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8ClampedArray); 4510 }; 4511 4512 4513 class ExternalInt8Array: public ExternalArray { 4514 public: 4515 // Setter and getter. 4516 inline int8_t get_scalar(int index); 4517 static inline Handle<Object> get(Handle<ExternalInt8Array> array, int index); 4518 inline void set(int index, int8_t value); 4519 4520 // This accessor applies the correct conversion from Smi, HeapNumber 4521 // and undefined. 4522 static Handle<Object> SetValue(Handle<ExternalInt8Array> array, 4523 uint32_t index, 4524 Handle<Object> value); 4525 4526 DECLARE_CAST(ExternalInt8Array) 4527 4528 // Dispatched behavior. 4529 DECLARE_PRINTER(ExternalInt8Array) 4530 DECLARE_VERIFIER(ExternalInt8Array) 4531 4532 private: 4533 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt8Array); 4534 }; 4535 4536 4537 class ExternalUint8Array: public ExternalArray { 4538 public: 4539 // Setter and getter. 4540 inline uint8_t get_scalar(int index); 4541 static inline Handle<Object> get(Handle<ExternalUint8Array> array, int index); 4542 inline void set(int index, uint8_t value); 4543 4544 // This accessor applies the correct conversion from Smi, HeapNumber 4545 // and undefined. 4546 static Handle<Object> SetValue(Handle<ExternalUint8Array> array, 4547 uint32_t index, 4548 Handle<Object> value); 4549 4550 DECLARE_CAST(ExternalUint8Array) 4551 4552 // Dispatched behavior. 4553 DECLARE_PRINTER(ExternalUint8Array) 4554 DECLARE_VERIFIER(ExternalUint8Array) 4555 4556 private: 4557 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint8Array); 4558 }; 4559 4560 4561 class ExternalInt16Array: public ExternalArray { 4562 public: 4563 // Setter and getter. 4564 inline int16_t get_scalar(int index); 4565 static inline Handle<Object> get(Handle<ExternalInt16Array> array, int index); 4566 inline void set(int index, int16_t value); 4567 4568 // This accessor applies the correct conversion from Smi, HeapNumber 4569 // and undefined. 4570 static Handle<Object> SetValue(Handle<ExternalInt16Array> array, 4571 uint32_t index, 4572 Handle<Object> value); 4573 4574 DECLARE_CAST(ExternalInt16Array) 4575 4576 // Dispatched behavior. 4577 DECLARE_PRINTER(ExternalInt16Array) 4578 DECLARE_VERIFIER(ExternalInt16Array) 4579 4580 private: 4581 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt16Array); 4582 }; 4583 4584 4585 class ExternalUint16Array: public ExternalArray { 4586 public: 4587 // Setter and getter. 4588 inline uint16_t get_scalar(int index); 4589 static inline Handle<Object> get(Handle<ExternalUint16Array> array, 4590 int index); 4591 inline void set(int index, uint16_t value); 4592 4593 // This accessor applies the correct conversion from Smi, HeapNumber 4594 // and undefined. 4595 static Handle<Object> SetValue(Handle<ExternalUint16Array> array, 4596 uint32_t index, 4597 Handle<Object> value); 4598 4599 DECLARE_CAST(ExternalUint16Array) 4600 4601 // Dispatched behavior. 4602 DECLARE_PRINTER(ExternalUint16Array) 4603 DECLARE_VERIFIER(ExternalUint16Array) 4604 4605 private: 4606 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint16Array); 4607 }; 4608 4609 4610 class ExternalInt32Array: public ExternalArray { 4611 public: 4612 // Setter and getter. 4613 inline int32_t get_scalar(int index); 4614 static inline Handle<Object> get(Handle<ExternalInt32Array> array, int index); 4615 inline void set(int index, int32_t value); 4616 4617 // This accessor applies the correct conversion from Smi, HeapNumber 4618 // and undefined. 4619 static Handle<Object> SetValue(Handle<ExternalInt32Array> array, 4620 uint32_t index, 4621 Handle<Object> value); 4622 4623 DECLARE_CAST(ExternalInt32Array) 4624 4625 // Dispatched behavior. 4626 DECLARE_PRINTER(ExternalInt32Array) 4627 DECLARE_VERIFIER(ExternalInt32Array) 4628 4629 private: 4630 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalInt32Array); 4631 }; 4632 4633 4634 class ExternalUint32Array: public ExternalArray { 4635 public: 4636 // Setter and getter. 4637 inline uint32_t get_scalar(int index); 4638 static inline Handle<Object> get(Handle<ExternalUint32Array> array, 4639 int index); 4640 inline void set(int index, uint32_t value); 4641 4642 // This accessor applies the correct conversion from Smi, HeapNumber 4643 // and undefined. 4644 static Handle<Object> SetValue(Handle<ExternalUint32Array> array, 4645 uint32_t index, 4646 Handle<Object> value); 4647 4648 DECLARE_CAST(ExternalUint32Array) 4649 4650 // Dispatched behavior. 4651 DECLARE_PRINTER(ExternalUint32Array) 4652 DECLARE_VERIFIER(ExternalUint32Array) 4653 4654 private: 4655 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalUint32Array); 4656 }; 4657 4658 4659 class ExternalFloat32Array: public ExternalArray { 4660 public: 4661 // Setter and getter. 4662 inline float get_scalar(int index); 4663 static inline Handle<Object> get(Handle<ExternalFloat32Array> array, 4664 int index); 4665 inline void set(int index, float value); 4666 4667 // This accessor applies the correct conversion from Smi, HeapNumber 4668 // and undefined. 4669 static Handle<Object> SetValue(Handle<ExternalFloat32Array> array, 4670 uint32_t index, 4671 Handle<Object> value); 4672 4673 DECLARE_CAST(ExternalFloat32Array) 4674 4675 // Dispatched behavior. 4676 DECLARE_PRINTER(ExternalFloat32Array) 4677 DECLARE_VERIFIER(ExternalFloat32Array) 4678 4679 private: 4680 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat32Array); 4681 }; 4682 4683 4684 class ExternalFloat64Array: public ExternalArray { 4685 public: 4686 // Setter and getter. 4687 inline double get_scalar(int index); 4688 static inline Handle<Object> get(Handle<ExternalFloat64Array> array, 4689 int index); 4690 inline void set(int index, double value); 4691 4692 // This accessor applies the correct conversion from Smi, HeapNumber 4693 // and undefined. 4694 static Handle<Object> SetValue(Handle<ExternalFloat64Array> array, 4695 uint32_t index, 4696 Handle<Object> value); 4697 4698 DECLARE_CAST(ExternalFloat64Array) 4699 4700 // Dispatched behavior. 4701 DECLARE_PRINTER(ExternalFloat64Array) 4702 DECLARE_VERIFIER(ExternalFloat64Array) 4703 4704 private: 4705 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalFloat64Array); 4706 }; 4707 4708 4709 class FixedTypedArrayBase: public FixedArrayBase { 4710 public: 4711 DECLARE_CAST(FixedTypedArrayBase) 4712 4713 static const int kDataOffset = kHeaderSize; 4714 4715 inline int size(); 4716 4717 inline int TypedArraySize(InstanceType type); 4718 4719 // Use with care: returns raw pointer into heap. 4720 inline void* DataPtr(); 4721 4722 inline int DataSize(); 4723 4724 private: 4725 inline int DataSize(InstanceType type); 4726 4727 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArrayBase); 4728 }; 4729 4730 4731 template <class Traits> 4732 class FixedTypedArray: public FixedTypedArrayBase { 4733 public: 4734 typedef typename Traits::ElementType ElementType; 4735 static const InstanceType kInstanceType = Traits::kInstanceType; 4736 4737 DECLARE_CAST(FixedTypedArray<Traits>) 4738 4739 static inline int ElementOffset(int index) { 4740 return kDataOffset + index * sizeof(ElementType); 4741 } 4742 4743 static inline int SizeFor(int length) { 4744 return ElementOffset(length); 4745 } 4746 4747 inline ElementType get_scalar(int index); 4748 static inline Handle<Object> get(Handle<FixedTypedArray> array, int index); 4749 inline void set(int index, ElementType value); 4750 4751 static inline ElementType from_int(int value); 4752 static inline ElementType from_double(double value); 4753 4754 // This accessor applies the correct conversion from Smi, HeapNumber 4755 // and undefined. 4756 static Handle<Object> SetValue(Handle<FixedTypedArray<Traits> > array, 4757 uint32_t index, 4758 Handle<Object> value); 4759 4760 DECLARE_PRINTER(FixedTypedArray) 4761 DECLARE_VERIFIER(FixedTypedArray) 4762 4763 private: 4764 DISALLOW_IMPLICIT_CONSTRUCTORS(FixedTypedArray); 4765 }; 4766 4767 #define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType, size) \ 4768 class Type##ArrayTraits { \ 4769 public: /* NOLINT */ \ 4770 typedef elementType ElementType; \ 4771 static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \ 4772 static const char* Designator() { return #type " array"; } \ 4773 static inline Handle<Object> ToHandle(Isolate* isolate, \ 4774 elementType scalar); \ 4775 static inline elementType defaultValue(); \ 4776 }; \ 4777 \ 4778 typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array; 4779 4780 TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS) 4781 4782 #undef FIXED_TYPED_ARRAY_TRAITS 4783 4784 // DeoptimizationInputData is a fixed array used to hold the deoptimization 4785 // data for code generated by the Hydrogen/Lithium compiler. It also 4786 // contains information about functions that were inlined. If N different 4787 // functions were inlined then first N elements of the literal array will 4788 // contain these functions. 4789 // 4790 // It can be empty. 4791 class DeoptimizationInputData: public FixedArray { 4792 public: 4793 // Layout description. Indices in the array. 4794 static const int kTranslationByteArrayIndex = 0; 4795 static const int kInlinedFunctionCountIndex = 1; 4796 static const int kLiteralArrayIndex = 2; 4797 static const int kOsrAstIdIndex = 3; 4798 static const int kOsrPcOffsetIndex = 4; 4799 static const int kOptimizationIdIndex = 5; 4800 static const int kSharedFunctionInfoIndex = 6; 4801 static const int kFirstDeoptEntryIndex = 7; 4802 4803 // Offsets of deopt entry elements relative to the start of the entry. 4804 static const int kAstIdRawOffset = 0; 4805 static const int kTranslationIndexOffset = 1; 4806 static const int kArgumentsStackHeightOffset = 2; 4807 static const int kPcOffset = 3; 4808 static const int kDeoptEntrySize = 4; 4809 4810 // Simple element accessors. 4811 #define DEFINE_ELEMENT_ACCESSORS(name, type) \ 4812 type* name() { \ 4813 return type::cast(get(k##name##Index)); \ 4814 } \ 4815 void Set##name(type* value) { \ 4816 set(k##name##Index, value); \ 4817 } 4818 4819 DEFINE_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray) 4820 DEFINE_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) 4821 DEFINE_ELEMENT_ACCESSORS(LiteralArray, FixedArray) 4822 DEFINE_ELEMENT_ACCESSORS(OsrAstId, Smi) 4823 DEFINE_ELEMENT_ACCESSORS(OsrPcOffset, Smi) 4824 DEFINE_ELEMENT_ACCESSORS(OptimizationId, Smi) 4825 DEFINE_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) 4826 4827 #undef DEFINE_ELEMENT_ACCESSORS 4828 4829 // Accessors for elements of the ith deoptimization entry. 4830 #define DEFINE_ENTRY_ACCESSORS(name, type) \ 4831 type* name(int i) { \ 4832 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \ 4833 } \ 4834 void Set##name(int i, type* value) { \ 4835 set(IndexForEntry(i) + k##name##Offset, value); \ 4836 } 4837 4838 DEFINE_ENTRY_ACCESSORS(AstIdRaw, Smi) 4839 DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi) 4840 DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi) 4841 DEFINE_ENTRY_ACCESSORS(Pc, Smi) 4842 4843 #undef DEFINE_DEOPT_ENTRY_ACCESSORS 4844 4845 BailoutId AstId(int i) { 4846 return BailoutId(AstIdRaw(i)->value()); 4847 } 4848 4849 void SetAstId(int i, BailoutId value) { 4850 SetAstIdRaw(i, Smi::FromInt(value.ToInt())); 4851 } 4852 4853 int DeoptCount() { 4854 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize; 4855 } 4856 4857 // Allocates a DeoptimizationInputData. 4858 static Handle<DeoptimizationInputData> New(Isolate* isolate, 4859 int deopt_entry_count, 4860 PretenureFlag pretenure); 4861 4862 DECLARE_CAST(DeoptimizationInputData) 4863 4864 #ifdef ENABLE_DISASSEMBLER 4865 void DeoptimizationInputDataPrint(OStream& os); // NOLINT 4866 #endif 4867 4868 private: 4869 static int IndexForEntry(int i) { 4870 return kFirstDeoptEntryIndex + (i * kDeoptEntrySize); 4871 } 4872 4873 4874 static int LengthFor(int entry_count) { return IndexForEntry(entry_count); } 4875 }; 4876 4877 4878 // DeoptimizationOutputData is a fixed array used to hold the deoptimization 4879 // data for code generated by the full compiler. 4880 // The format of the these objects is 4881 // [i * 2]: Ast ID for ith deoptimization. 4882 // [i * 2 + 1]: PC and state of ith deoptimization 4883 class DeoptimizationOutputData: public FixedArray { 4884 public: 4885 int DeoptPoints() { return length() / 2; } 4886 4887 BailoutId AstId(int index) { 4888 return BailoutId(Smi::cast(get(index * 2))->value()); 4889 } 4890 4891 void SetAstId(int index, BailoutId id) { 4892 set(index * 2, Smi::FromInt(id.ToInt())); 4893 } 4894 4895 Smi* PcAndState(int index) { return Smi::cast(get(1 + index * 2)); } 4896 void SetPcAndState(int index, Smi* offset) { set(1 + index * 2, offset); } 4897 4898 static int LengthOfFixedArray(int deopt_points) { 4899 return deopt_points * 2; 4900 } 4901 4902 // Allocates a DeoptimizationOutputData. 4903 static Handle<DeoptimizationOutputData> New(Isolate* isolate, 4904 int number_of_deopt_points, 4905 PretenureFlag pretenure); 4906 4907 DECLARE_CAST(DeoptimizationOutputData) 4908 4909 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 4910 void DeoptimizationOutputDataPrint(OStream& os); // NOLINT 4911 #endif 4912 }; 4913 4914 4915 // Forward declaration. 4916 class Cell; 4917 class PropertyCell; 4918 class SafepointEntry; 4919 class TypeFeedbackInfo; 4920 4921 // Code describes objects with on-the-fly generated machine code. 4922 class Code: public HeapObject { 4923 public: 4924 // Opaque data type for encapsulating code flags like kind, inline 4925 // cache state, and arguments count. 4926 typedef uint32_t Flags; 4927 4928 #define NON_IC_KIND_LIST(V) \ 4929 V(FUNCTION) \ 4930 V(OPTIMIZED_FUNCTION) \ 4931 V(STUB) \ 4932 V(HANDLER) \ 4933 V(BUILTIN) \ 4934 V(REGEXP) 4935 4936 #define IC_KIND_LIST(V) \ 4937 V(LOAD_IC) \ 4938 V(KEYED_LOAD_IC) \ 4939 V(CALL_IC) \ 4940 V(STORE_IC) \ 4941 V(KEYED_STORE_IC) \ 4942 V(BINARY_OP_IC) \ 4943 V(COMPARE_IC) \ 4944 V(COMPARE_NIL_IC) \ 4945 V(TO_BOOLEAN_IC) 4946 4947 #define CODE_KIND_LIST(V) \ 4948 NON_IC_KIND_LIST(V) \ 4949 IC_KIND_LIST(V) 4950 4951 enum Kind { 4952 #define DEFINE_CODE_KIND_ENUM(name) name, 4953 CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM) 4954 #undef DEFINE_CODE_KIND_ENUM 4955 NUMBER_OF_KINDS 4956 }; 4957 4958 // No more than 16 kinds. The value is currently encoded in four bits in 4959 // Flags. 4960 STATIC_ASSERT(NUMBER_OF_KINDS <= 16); 4961 4962 static const char* Kind2String(Kind kind); 4963 4964 // Types of stubs. 4965 enum StubType { 4966 NORMAL, 4967 FAST 4968 }; 4969 4970 static const int kPrologueOffsetNotSet = -1; 4971 4972 #ifdef ENABLE_DISASSEMBLER 4973 // Printing 4974 static const char* ICState2String(InlineCacheState state); 4975 static const char* StubType2String(StubType type); 4976 static void PrintExtraICState(OStream& os, // NOLINT 4977 Kind kind, ExtraICState extra); 4978 void Disassemble(const char* name, OStream& os); // NOLINT 4979 #endif // ENABLE_DISASSEMBLER 4980 4981 // [instruction_size]: Size of the native instructions 4982 inline int instruction_size() const; 4983 inline void set_instruction_size(int value); 4984 4985 // [relocation_info]: Code relocation information 4986 DECL_ACCESSORS(relocation_info, ByteArray) 4987 void InvalidateRelocation(); 4988 void InvalidateEmbeddedObjects(); 4989 4990 // [handler_table]: Fixed array containing offsets of exception handlers. 4991 DECL_ACCESSORS(handler_table, FixedArray) 4992 4993 // [deoptimization_data]: Array containing data for deopt. 4994 DECL_ACCESSORS(deoptimization_data, FixedArray) 4995 4996 // [raw_type_feedback_info]: This field stores various things, depending on 4997 // the kind of the code object. 4998 // FUNCTION => type feedback information. 4999 // STUB and ICs => major/minor key as Smi. 5000 DECL_ACCESSORS(raw_type_feedback_info, Object) 5001 inline Object* type_feedback_info(); 5002 inline void set_type_feedback_info( 5003 Object* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 5004 inline uint32_t stub_key(); 5005 inline void set_stub_key(uint32_t key); 5006 5007 // [next_code_link]: Link for lists of optimized or deoptimized code. 5008 // Note that storage for this field is overlapped with typefeedback_info. 5009 DECL_ACCESSORS(next_code_link, Object) 5010 5011 // [gc_metadata]: Field used to hold GC related metadata. The contents of this 5012 // field does not have to be traced during garbage collection since 5013 // it is only used by the garbage collector itself. 5014 DECL_ACCESSORS(gc_metadata, Object) 5015 5016 // [ic_age]: Inline caching age: the value of the Heap::global_ic_age 5017 // at the moment when this object was created. 5018 inline void set_ic_age(int count); 5019 inline int ic_age() const; 5020 5021 // [prologue_offset]: Offset of the function prologue, used for aging 5022 // FUNCTIONs and OPTIMIZED_FUNCTIONs. 5023 inline int prologue_offset() const; 5024 inline void set_prologue_offset(int offset); 5025 5026 // Unchecked accessors to be used during GC. 5027 inline ByteArray* unchecked_relocation_info(); 5028 5029 inline int relocation_size(); 5030 5031 // [flags]: Various code flags. 5032 inline Flags flags(); 5033 inline void set_flags(Flags flags); 5034 5035 // [flags]: Access to specific code flags. 5036 inline Kind kind(); 5037 inline InlineCacheState ic_state(); // Only valid for IC stubs. 5038 inline ExtraICState extra_ic_state(); // Only valid for IC stubs. 5039 5040 inline StubType type(); // Only valid for monomorphic IC stubs. 5041 5042 // Testers for IC stub kinds. 5043 inline bool is_inline_cache_stub(); 5044 inline bool is_debug_stub(); 5045 inline bool is_handler() { return kind() == HANDLER; } 5046 inline bool is_load_stub() { return kind() == LOAD_IC; } 5047 inline bool is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; } 5048 inline bool is_store_stub() { return kind() == STORE_IC; } 5049 inline bool is_keyed_store_stub() { return kind() == KEYED_STORE_IC; } 5050 inline bool is_call_stub() { return kind() == CALL_IC; } 5051 inline bool is_binary_op_stub() { return kind() == BINARY_OP_IC; } 5052 inline bool is_compare_ic_stub() { return kind() == COMPARE_IC; } 5053 inline bool is_compare_nil_ic_stub() { return kind() == COMPARE_NIL_IC; } 5054 inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; } 5055 inline bool is_keyed_stub(); 5056 inline bool is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; } 5057 inline bool is_weak_stub(); 5058 inline void mark_as_weak_stub(); 5059 inline bool is_invalidated_weak_stub(); 5060 inline void mark_as_invalidated_weak_stub(); 5061 5062 inline bool CanBeWeakStub() { 5063 Kind k = kind(); 5064 return (k == LOAD_IC || k == STORE_IC || k == KEYED_LOAD_IC || 5065 k == KEYED_STORE_IC || k == COMPARE_NIL_IC) && 5066 ic_state() == MONOMORPHIC; 5067 } 5068 5069 inline bool IsCodeStubOrIC(); 5070 5071 inline void set_raw_kind_specific_flags1(int value); 5072 inline void set_raw_kind_specific_flags2(int value); 5073 5074 // [is_crankshafted]: For kind STUB or ICs, tells whether or not a code 5075 // object was generated by either the hydrogen or the TurboFan optimizing 5076 // compiler (but it may not be an optimized function). 5077 inline bool is_crankshafted(); 5078 inline bool is_hydrogen_stub(); // Crankshafted, but not a function. 5079 inline void set_is_crankshafted(bool value); 5080 5081 // [is_turbofanned]: For kind STUB or OPTIMIZED_FUNCTION, tells whether the 5082 // code object was generated by the TurboFan optimizing compiler. 5083 inline bool is_turbofanned(); 5084 inline void set_is_turbofanned(bool value); 5085 5086 // [optimizable]: For FUNCTION kind, tells if it is optimizable. 5087 inline bool optimizable(); 5088 inline void set_optimizable(bool value); 5089 5090 // [has_deoptimization_support]: For FUNCTION kind, tells if it has 5091 // deoptimization support. 5092 inline bool has_deoptimization_support(); 5093 inline void set_has_deoptimization_support(bool value); 5094 5095 // [has_debug_break_slots]: For FUNCTION kind, tells if it has 5096 // been compiled with debug break slots. 5097 inline bool has_debug_break_slots(); 5098 inline void set_has_debug_break_slots(bool value); 5099 5100 // [compiled_with_optimizing]: For FUNCTION kind, tells if it has 5101 // been compiled with IsOptimizing set to true. 5102 inline bool is_compiled_optimizable(); 5103 inline void set_compiled_optimizable(bool value); 5104 5105 // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for 5106 // how long the function has been marked for OSR and therefore which 5107 // level of loop nesting we are willing to do on-stack replacement 5108 // for. 5109 inline void set_allow_osr_at_loop_nesting_level(int level); 5110 inline int allow_osr_at_loop_nesting_level(); 5111 5112 // [profiler_ticks]: For FUNCTION kind, tells for how many profiler ticks 5113 // the code object was seen on the stack with no IC patching going on. 5114 inline int profiler_ticks(); 5115 inline void set_profiler_ticks(int ticks); 5116 5117 // [builtin_index]: For BUILTIN kind, tells which builtin index it has. 5118 inline int builtin_index(); 5119 inline void set_builtin_index(int id); 5120 5121 // [stack_slots]: For kind OPTIMIZED_FUNCTION, the number of stack slots 5122 // reserved in the code prologue. 5123 inline unsigned stack_slots(); 5124 inline void set_stack_slots(unsigned slots); 5125 5126 // [safepoint_table_start]: For kind OPTIMIZED_FUNCTION, the offset in 5127 // the instruction stream where the safepoint table starts. 5128 inline unsigned safepoint_table_offset(); 5129 inline void set_safepoint_table_offset(unsigned offset); 5130 5131 // [back_edge_table_start]: For kind FUNCTION, the offset in the 5132 // instruction stream where the back edge table starts. 5133 inline unsigned back_edge_table_offset(); 5134 inline void set_back_edge_table_offset(unsigned offset); 5135 5136 inline bool back_edges_patched_for_osr(); 5137 5138 // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in. 5139 inline byte to_boolean_state(); 5140 5141 // [has_function_cache]: For kind STUB tells whether there is a function 5142 // cache is passed to the stub. 5143 inline bool has_function_cache(); 5144 inline void set_has_function_cache(bool flag); 5145 5146 5147 // [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether 5148 // the code is going to be deoptimized because of dead embedded maps. 5149 inline bool marked_for_deoptimization(); 5150 inline void set_marked_for_deoptimization(bool flag); 5151 5152 // [constant_pool]: The constant pool for this function. 5153 inline ConstantPoolArray* constant_pool(); 5154 inline void set_constant_pool(Object* constant_pool); 5155 5156 // Get the safepoint entry for the given pc. 5157 SafepointEntry GetSafepointEntry(Address pc); 5158 5159 // Find an object in a stub with a specified map 5160 Object* FindNthObject(int n, Map* match_map); 5161 5162 // Find the first allocation site in an IC stub. 5163 AllocationSite* FindFirstAllocationSite(); 5164 5165 // Find the first map in an IC stub. 5166 Map* FindFirstMap(); 5167 void FindAllMaps(MapHandleList* maps); 5168 5169 // Find the first handler in an IC stub. 5170 Code* FindFirstHandler(); 5171 5172 // Find |length| handlers and put them into |code_list|. Returns false if not 5173 // enough handlers can be found. 5174 bool FindHandlers(CodeHandleList* code_list, int length = -1); 5175 5176 // Find the handler for |map|. 5177 MaybeHandle<Code> FindHandlerForMap(Map* map); 5178 5179 // Find the first name in an IC stub. 5180 Name* FindFirstName(); 5181 5182 class FindAndReplacePattern; 5183 // For each (map-to-find, object-to-replace) pair in the pattern, this 5184 // function replaces the corresponding placeholder in the code with the 5185 // object-to-replace. The function assumes that pairs in the pattern come in 5186 // the same order as the placeholders in the code. 5187 void FindAndReplace(const FindAndReplacePattern& pattern); 5188 5189 // The entire code object including its header is copied verbatim to the 5190 // snapshot so that it can be written in one, fast, memcpy during 5191 // deserialization. The deserializer will overwrite some pointers, rather 5192 // like a runtime linker, but the random allocation addresses used in the 5193 // mksnapshot process would still be present in the unlinked snapshot data, 5194 // which would make snapshot production non-reproducible. This method wipes 5195 // out the to-be-overwritten header data for reproducible snapshots. 5196 inline void WipeOutHeader(); 5197 5198 // Flags operations. 5199 static inline Flags ComputeFlags( 5200 Kind kind, InlineCacheState ic_state = UNINITIALIZED, 5201 ExtraICState extra_ic_state = kNoExtraICState, StubType type = NORMAL, 5202 CacheHolderFlag holder = kCacheOnReceiver); 5203 5204 static inline Flags ComputeMonomorphicFlags( 5205 Kind kind, ExtraICState extra_ic_state = kNoExtraICState, 5206 CacheHolderFlag holder = kCacheOnReceiver, StubType type = NORMAL); 5207 5208 static inline Flags ComputeHandlerFlags( 5209 Kind handler_kind, StubType type = NORMAL, 5210 CacheHolderFlag holder = kCacheOnReceiver); 5211 5212 static inline InlineCacheState ExtractICStateFromFlags(Flags flags); 5213 static inline StubType ExtractTypeFromFlags(Flags flags); 5214 static inline CacheHolderFlag ExtractCacheHolderFromFlags(Flags flags); 5215 static inline Kind ExtractKindFromFlags(Flags flags); 5216 static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags); 5217 5218 static inline Flags RemoveTypeFromFlags(Flags flags); 5219 static inline Flags RemoveTypeAndHolderFromFlags(Flags flags); 5220 5221 // Convert a target address into a code object. 5222 static inline Code* GetCodeFromTargetAddress(Address address); 5223 5224 // Convert an entry address into an object. 5225 static inline Object* GetObjectFromEntryAddress(Address location_of_address); 5226 5227 // Returns the address of the first instruction. 5228 inline byte* instruction_start(); 5229 5230 // Returns the address right after the last instruction. 5231 inline byte* instruction_end(); 5232 5233 // Returns the size of the instructions, padding, and relocation information. 5234 inline int body_size(); 5235 5236 // Returns the address of the first relocation info (read backwards!). 5237 inline byte* relocation_start(); 5238 5239 // Code entry point. 5240 inline byte* entry(); 5241 5242 // Returns true if pc is inside this object's instructions. 5243 inline bool contains(byte* pc); 5244 5245 // Relocate the code by delta bytes. Called to signal that this code 5246 // object has been moved by delta bytes. 5247 void Relocate(intptr_t delta); 5248 5249 // Migrate code described by desc. 5250 void CopyFrom(const CodeDesc& desc); 5251 5252 // Returns the object size for a given body (used for allocation). 5253 static int SizeFor(int body_size) { 5254 DCHECK_SIZE_TAG_ALIGNED(body_size); 5255 return RoundUp(kHeaderSize + body_size, kCodeAlignment); 5256 } 5257 5258 // Calculate the size of the code object to report for log events. This takes 5259 // the layout of the code object into account. 5260 int ExecutableSize() { 5261 // Check that the assumptions about the layout of the code object holds. 5262 DCHECK_EQ(static_cast<int>(instruction_start() - address()), 5263 Code::kHeaderSize); 5264 return instruction_size() + Code::kHeaderSize; 5265 } 5266 5267 // Locating source position. 5268 int SourcePosition(Address pc); 5269 int SourceStatementPosition(Address pc); 5270 5271 DECLARE_CAST(Code) 5272 5273 // Dispatched behavior. 5274 int CodeSize() { return SizeFor(body_size()); } 5275 inline void CodeIterateBody(ObjectVisitor* v); 5276 5277 template<typename StaticVisitor> 5278 inline void CodeIterateBody(Heap* heap); 5279 5280 DECLARE_PRINTER(Code) 5281 DECLARE_VERIFIER(Code) 5282 5283 void ClearInlineCaches(); 5284 void ClearInlineCaches(Kind kind); 5285 5286 BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset); 5287 uint32_t TranslateAstIdToPcOffset(BailoutId ast_id); 5288 5289 #define DECLARE_CODE_AGE_ENUM(X) k##X##CodeAge, 5290 enum Age { 5291 kNotExecutedCodeAge = -2, 5292 kExecutedOnceCodeAge = -1, 5293 kNoAgeCodeAge = 0, 5294 CODE_AGE_LIST(DECLARE_CODE_AGE_ENUM) 5295 kAfterLastCodeAge, 5296 kFirstCodeAge = kNotExecutedCodeAge, 5297 kLastCodeAge = kAfterLastCodeAge - 1, 5298 kCodeAgeCount = kAfterLastCodeAge - kNotExecutedCodeAge - 1, 5299 kIsOldCodeAge = kSexagenarianCodeAge, 5300 kPreAgedCodeAge = kIsOldCodeAge - 1 5301 }; 5302 #undef DECLARE_CODE_AGE_ENUM 5303 5304 // Code aging. Indicates how many full GCs this code has survived without 5305 // being entered through the prologue. Used to determine when it is 5306 // relatively safe to flush this code object and replace it with the lazy 5307 // compilation stub. 5308 static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate); 5309 static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate); 5310 void MakeOlder(MarkingParity); 5311 static bool IsYoungSequence(Isolate* isolate, byte* sequence); 5312 bool IsOld(); 5313 Age GetAge(); 5314 // Gets the raw code age, including psuedo code-age values such as 5315 // kNotExecutedCodeAge and kExecutedOnceCodeAge. 5316 Age GetRawAge(); 5317 static inline Code* GetPreAgedCodeAgeStub(Isolate* isolate) { 5318 return GetCodeAgeStub(isolate, kNotExecutedCodeAge, NO_MARKING_PARITY); 5319 } 5320 5321 void PrintDeoptLocation(FILE* out, int bailout_id); 5322 bool CanDeoptAt(Address pc); 5323 5324 #ifdef VERIFY_HEAP 5325 void VerifyEmbeddedObjectsDependency(); 5326 #endif 5327 5328 inline bool CanContainWeakObjects() { 5329 return is_optimized_code() || is_weak_stub(); 5330 } 5331 5332 inline bool IsWeakObject(Object* object) { 5333 return (is_optimized_code() && !is_turbofanned() && 5334 IsWeakObjectInOptimizedCode(object)) || 5335 (is_weak_stub() && IsWeakObjectInIC(object)); 5336 } 5337 5338 static inline bool IsWeakObjectInOptimizedCode(Object* object); 5339 static inline bool IsWeakObjectInIC(Object* object); 5340 5341 // Max loop nesting marker used to postpose OSR. We don't take loop 5342 // nesting that is deeper than 5 levels into account. 5343 static const int kMaxLoopNestingMarker = 6; 5344 5345 // Layout description. 5346 static const int kInstructionSizeOffset = HeapObject::kHeaderSize; 5347 static const int kRelocationInfoOffset = kInstructionSizeOffset + kIntSize; 5348 static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize; 5349 static const int kDeoptimizationDataOffset = 5350 kHandlerTableOffset + kPointerSize; 5351 // For FUNCTION kind, we store the type feedback info here. 5352 static const int kTypeFeedbackInfoOffset = 5353 kDeoptimizationDataOffset + kPointerSize; 5354 static const int kNextCodeLinkOffset = kTypeFeedbackInfoOffset + kPointerSize; 5355 static const int kGCMetadataOffset = kNextCodeLinkOffset + kPointerSize; 5356 static const int kICAgeOffset = 5357 kGCMetadataOffset + kPointerSize; 5358 static const int kFlagsOffset = kICAgeOffset + kIntSize; 5359 static const int kKindSpecificFlags1Offset = kFlagsOffset + kIntSize; 5360 static const int kKindSpecificFlags2Offset = 5361 kKindSpecificFlags1Offset + kIntSize; 5362 // Note: We might be able to squeeze this into the flags above. 5363 static const int kPrologueOffset = kKindSpecificFlags2Offset + kIntSize; 5364 static const int kConstantPoolOffset = kPrologueOffset + kPointerSize; 5365 5366 static const int kHeaderPaddingStart = kConstantPoolOffset + kIntSize; 5367 5368 // Add padding to align the instruction start following right after 5369 // the Code object header. 5370 static const int kHeaderSize = 5371 (kHeaderPaddingStart + kCodeAlignmentMask) & ~kCodeAlignmentMask; 5372 5373 // Byte offsets within kKindSpecificFlags1Offset. 5374 static const int kOptimizableOffset = kKindSpecificFlags1Offset; 5375 5376 static const int kFullCodeFlags = kOptimizableOffset + 1; 5377 class FullCodeFlagsHasDeoptimizationSupportField: 5378 public BitField<bool, 0, 1> {}; // NOLINT 5379 class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {}; 5380 class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {}; 5381 5382 static const int kProfilerTicksOffset = kFullCodeFlags + 1; 5383 5384 // Flags layout. BitField<type, shift, size>. 5385 class ICStateField : public BitField<InlineCacheState, 0, 4> {}; 5386 class TypeField : public BitField<StubType, 4, 1> {}; 5387 class CacheHolderField : public BitField<CacheHolderFlag, 5, 2> {}; 5388 class KindField : public BitField<Kind, 7, 4> {}; 5389 class ExtraICStateField: public BitField<ExtraICState, 11, 5390 PlatformSmiTagging::kSmiValueSize - 11 + 1> {}; // NOLINT 5391 5392 // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION) 5393 static const int kStackSlotsFirstBit = 0; 5394 static const int kStackSlotsBitCount = 24; 5395 static const int kHasFunctionCacheBit = 5396 kStackSlotsFirstBit + kStackSlotsBitCount; 5397 static const int kMarkedForDeoptimizationBit = kHasFunctionCacheBit + 1; 5398 static const int kWeakStubBit = kMarkedForDeoptimizationBit + 1; 5399 static const int kInvalidatedWeakStubBit = kWeakStubBit + 1; 5400 static const int kIsTurbofannedBit = kInvalidatedWeakStubBit + 1; 5401 5402 STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32); 5403 STATIC_ASSERT(kIsTurbofannedBit + 1 <= 32); 5404 5405 class StackSlotsField: public BitField<int, 5406 kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT 5407 class HasFunctionCacheField : public BitField<bool, kHasFunctionCacheBit, 1> { 5408 }; // NOLINT 5409 class MarkedForDeoptimizationField 5410 : public BitField<bool, kMarkedForDeoptimizationBit, 1> {}; // NOLINT 5411 class WeakStubField : public BitField<bool, kWeakStubBit, 1> {}; // NOLINT 5412 class InvalidatedWeakStubField 5413 : public BitField<bool, kInvalidatedWeakStubBit, 1> {}; // NOLINT 5414 class IsTurbofannedField : public BitField<bool, kIsTurbofannedBit, 1> { 5415 }; // NOLINT 5416 5417 // KindSpecificFlags2 layout (ALL) 5418 static const int kIsCrankshaftedBit = 0; 5419 class IsCrankshaftedField: public BitField<bool, 5420 kIsCrankshaftedBit, 1> {}; // NOLINT 5421 5422 // KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION) 5423 static const int kSafepointTableOffsetFirstBit = kIsCrankshaftedBit + 1; 5424 static const int kSafepointTableOffsetBitCount = 24; 5425 5426 STATIC_ASSERT(kSafepointTableOffsetFirstBit + 5427 kSafepointTableOffsetBitCount <= 32); 5428 STATIC_ASSERT(1 + kSafepointTableOffsetBitCount <= 32); 5429 5430 class SafepointTableOffsetField: public BitField<int, 5431 kSafepointTableOffsetFirstBit, 5432 kSafepointTableOffsetBitCount> {}; // NOLINT 5433 5434 // KindSpecificFlags2 layout (FUNCTION) 5435 class BackEdgeTableOffsetField: public BitField<int, 5436 kIsCrankshaftedBit + 1, 27> {}; // NOLINT 5437 class AllowOSRAtLoopNestingLevelField: public BitField<int, 5438 kIsCrankshaftedBit + 1 + 27, 4> {}; // NOLINT 5439 STATIC_ASSERT(AllowOSRAtLoopNestingLevelField::kMax >= kMaxLoopNestingMarker); 5440 5441 static const int kArgumentsBits = 16; 5442 static const int kMaxArguments = (1 << kArgumentsBits) - 1; 5443 5444 // This constant should be encodable in an ARM instruction. 5445 static const int kFlagsNotUsedInLookup = 5446 TypeField::kMask | CacheHolderField::kMask; 5447 5448 private: 5449 friend class RelocIterator; 5450 friend class Deoptimizer; // For FindCodeAgeSequence. 5451 5452 void ClearInlineCaches(Kind* kind); 5453 5454 // Code aging 5455 byte* FindCodeAgeSequence(); 5456 static void GetCodeAgeAndParity(Code* code, Age* age, 5457 MarkingParity* parity); 5458 static void GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age, 5459 MarkingParity* parity); 5460 static Code* GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity); 5461 5462 // Code aging -- platform-specific 5463 static void PatchPlatformCodeAge(Isolate* isolate, 5464 byte* sequence, Age age, 5465 MarkingParity parity); 5466 5467 DISALLOW_IMPLICIT_CONSTRUCTORS(Code); 5468 }; 5469 5470 5471 class CompilationInfo; 5472 5473 // This class describes the layout of dependent codes array of a map. The 5474 // array is partitioned into several groups of dependent codes. Each group 5475 // contains codes with the same dependency on the map. The array has the 5476 // following layout for n dependency groups: 5477 // 5478 // +----+----+-----+----+---------+----------+-----+---------+-----------+ 5479 // | C1 | C2 | ... | Cn | group 1 | group 2 | ... | group n | undefined | 5480 // +----+----+-----+----+---------+----------+-----+---------+-----------+ 5481 // 5482 // The first n elements are Smis, each of them specifies the number of codes 5483 // in the corresponding group. The subsequent elements contain grouped code 5484 // objects. The suffix of the array can be filled with the undefined value if 5485 // the number of codes is less than the length of the array. The order of the 5486 // code objects within a group is not preserved. 5487 // 5488 // All code indexes used in the class are counted starting from the first 5489 // code object of the first group. In other words, code index 0 corresponds 5490 // to array index n = kCodesStartIndex. 5491 5492 class DependentCode: public FixedArray { 5493 public: 5494 enum DependencyGroup { 5495 // Group of IC stubs that weakly embed this map and depend on being 5496 // invalidated when the map is garbage collected. Dependent IC stubs form 5497 // a linked list. This group stores only the head of the list. This means 5498 // that the number_of_entries(kWeakICGroup) is 0 or 1. 5499 kWeakICGroup, 5500 // Group of code that weakly embed this map and depend on being 5501 // deoptimized when the map is garbage collected. 5502 kWeakCodeGroup, 5503 // Group of code that embed a transition to this map, and depend on being 5504 // deoptimized when the transition is replaced by a new version. 5505 kTransitionGroup, 5506 // Group of code that omit run-time prototype checks for prototypes 5507 // described by this map. The group is deoptimized whenever an object 5508 // described by this map changes shape (and transitions to a new map), 5509 // possibly invalidating the assumptions embedded in the code. 5510 kPrototypeCheckGroup, 5511 // Group of code that depends on elements not being added to objects with 5512 // this map. 5513 kElementsCantBeAddedGroup, 5514 // Group of code that depends on global property values in property cells 5515 // not being changed. 5516 kPropertyCellChangedGroup, 5517 // Group of code that omit run-time type checks for the field(s) introduced 5518 // by this map. 5519 kFieldTypeGroup, 5520 // Group of code that omit run-time type checks for initial maps of 5521 // constructors. 5522 kInitialMapChangedGroup, 5523 // Group of code that depends on tenuring information in AllocationSites 5524 // not being changed. 5525 kAllocationSiteTenuringChangedGroup, 5526 // Group of code that depends on element transition information in 5527 // AllocationSites not being changed. 5528 kAllocationSiteTransitionChangedGroup 5529 }; 5530 5531 static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1; 5532 5533 // Array for holding the index of the first code object of each group. 5534 // The last element stores the total number of code objects. 5535 class GroupStartIndexes { 5536 public: 5537 explicit GroupStartIndexes(DependentCode* entries); 5538 void Recompute(DependentCode* entries); 5539 int at(int i) { return start_indexes_[i]; } 5540 int number_of_entries() { return start_indexes_[kGroupCount]; } 5541 private: 5542 int start_indexes_[kGroupCount + 1]; 5543 }; 5544 5545 bool Contains(DependencyGroup group, Code* code); 5546 static Handle<DependentCode> Insert(Handle<DependentCode> entries, 5547 DependencyGroup group, 5548 Handle<Object> object); 5549 void UpdateToFinishedCode(DependencyGroup group, 5550 CompilationInfo* info, 5551 Code* code); 5552 void RemoveCompilationInfo(DependentCode::DependencyGroup group, 5553 CompilationInfo* info); 5554 5555 void DeoptimizeDependentCodeGroup(Isolate* isolate, 5556 DependentCode::DependencyGroup group); 5557 5558 bool MarkCodeForDeoptimization(Isolate* isolate, 5559 DependentCode::DependencyGroup group); 5560 void AddToDependentICList(Handle<Code> stub); 5561 5562 // The following low-level accessors should only be used by this class 5563 // and the mark compact collector. 5564 inline int number_of_entries(DependencyGroup group); 5565 inline void set_number_of_entries(DependencyGroup group, int value); 5566 inline bool is_code_at(int i); 5567 inline Code* code_at(int i); 5568 inline CompilationInfo* compilation_info_at(int i); 5569 inline void set_object_at(int i, Object* object); 5570 inline Object** slot_at(int i); 5571 inline Object* object_at(int i); 5572 inline void clear_at(int i); 5573 inline void copy(int from, int to); 5574 DECLARE_CAST(DependentCode) 5575 5576 static DependentCode* ForObject(Handle<HeapObject> object, 5577 DependencyGroup group); 5578 5579 static const char* DependencyGroupName(DependencyGroup group); 5580 static void SetMarkedForDeoptimization(Code* code, DependencyGroup group); 5581 5582 private: 5583 // Make a room at the end of the given group by moving out the first 5584 // code objects of the subsequent groups. 5585 inline void ExtendGroup(DependencyGroup group); 5586 static const int kCodesStartIndex = kGroupCount; 5587 }; 5588 5589 5590 // All heap objects have a Map that describes their structure. 5591 // A Map contains information about: 5592 // - Size information about the object 5593 // - How to iterate over an object (for garbage collection) 5594 class Map: public HeapObject { 5595 public: 5596 // Instance size. 5597 // Size in bytes or kVariableSizeSentinel if instances do not have 5598 // a fixed size. 5599 inline int instance_size(); 5600 inline void set_instance_size(int value); 5601 5602 // Count of properties allocated in the object. 5603 inline int inobject_properties(); 5604 inline void set_inobject_properties(int value); 5605 5606 // Count of property fields pre-allocated in the object when first allocated. 5607 inline int pre_allocated_property_fields(); 5608 inline void set_pre_allocated_property_fields(int value); 5609 5610 // Instance type. 5611 inline InstanceType instance_type(); 5612 inline void set_instance_type(InstanceType value); 5613 5614 // Tells how many unused property fields are available in the 5615 // instance (only used for JSObject in fast mode). 5616 inline int unused_property_fields(); 5617 inline void set_unused_property_fields(int value); 5618 5619 // Bit field. 5620 inline byte bit_field(); 5621 inline void set_bit_field(byte value); 5622 5623 // Bit field 2. 5624 inline byte bit_field2(); 5625 inline void set_bit_field2(byte value); 5626 5627 // Bit field 3. 5628 inline uint32_t bit_field3(); 5629 inline void set_bit_field3(uint32_t bits); 5630 5631 class EnumLengthBits: public BitField<int, 5632 0, kDescriptorIndexBitCount> {}; // NOLINT 5633 class NumberOfOwnDescriptorsBits: public BitField<int, 5634 kDescriptorIndexBitCount, kDescriptorIndexBitCount> {}; // NOLINT 5635 STATIC_ASSERT(kDescriptorIndexBitCount + kDescriptorIndexBitCount == 20); 5636 class DictionaryMap : public BitField<bool, 20, 1> {}; 5637 class OwnsDescriptors : public BitField<bool, 21, 1> {}; 5638 class HasInstanceCallHandler : public BitField<bool, 22, 1> {}; 5639 class Deprecated : public BitField<bool, 23, 1> {}; 5640 class IsFrozen : public BitField<bool, 24, 1> {}; 5641 class IsUnstable : public BitField<bool, 25, 1> {}; 5642 class IsMigrationTarget : public BitField<bool, 26, 1> {}; 5643 class DoneInobjectSlackTracking : public BitField<bool, 27, 1> {}; 5644 // Bit 28 is free. 5645 5646 // Keep this bit field at the very end for better code in 5647 // Builtins::kJSConstructStubGeneric stub. 5648 class ConstructionCount: public BitField<int, 29, 3> {}; 5649 5650 // Tells whether the object in the prototype property will be used 5651 // for instances created from this function. If the prototype 5652 // property is set to a value that is not a JSObject, the prototype 5653 // property will not be used to create instances of the function. 5654 // See ECMA-262, 13.2.2. 5655 inline void set_non_instance_prototype(bool value); 5656 inline bool has_non_instance_prototype(); 5657 5658 // Tells whether function has special prototype property. If not, prototype 5659 // property will not be created when accessed (will return undefined), 5660 // and construction from this function will not be allowed. 5661 inline void set_function_with_prototype(bool value); 5662 inline bool function_with_prototype(); 5663 5664 // Tells whether the instance with this map should be ignored by the 5665 // Object.getPrototypeOf() function and the __proto__ accessor. 5666 inline void set_is_hidden_prototype() { 5667 set_bit_field(bit_field() | (1 << kIsHiddenPrototype)); 5668 } 5669 5670 inline bool is_hidden_prototype() { 5671 return ((1 << kIsHiddenPrototype) & bit_field()) != 0; 5672 } 5673 5674 // Records and queries whether the instance has a named interceptor. 5675 inline void set_has_named_interceptor() { 5676 set_bit_field(bit_field() | (1 << kHasNamedInterceptor)); 5677 } 5678 5679 inline bool has_named_interceptor() { 5680 return ((1 << kHasNamedInterceptor) & bit_field()) != 0; 5681 } 5682 5683 // Records and queries whether the instance has an indexed interceptor. 5684 inline void set_has_indexed_interceptor() { 5685 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor)); 5686 } 5687 5688 inline bool has_indexed_interceptor() { 5689 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0; 5690 } 5691 5692 // Tells whether the instance is undetectable. 5693 // An undetectable object is a special class of JSObject: 'typeof' operator 5694 // returns undefined, ToBoolean returns false. Otherwise it behaves like 5695 // a normal JS object. It is useful for implementing undetectable 5696 // document.all in Firefox & Safari. 5697 // See https://bugzilla.mozilla.org/show_bug.cgi?id=248549. 5698 inline void set_is_undetectable() { 5699 set_bit_field(bit_field() | (1 << kIsUndetectable)); 5700 } 5701 5702 inline bool is_undetectable() { 5703 return ((1 << kIsUndetectable) & bit_field()) != 0; 5704 } 5705 5706 // Tells whether the instance has a call-as-function handler. 5707 inline void set_is_observed() { 5708 set_bit_field(bit_field() | (1 << kIsObserved)); 5709 } 5710 5711 inline bool is_observed() { 5712 return ((1 << kIsObserved) & bit_field()) != 0; 5713 } 5714 5715 inline void set_is_extensible(bool value); 5716 inline bool is_extensible(); 5717 inline void set_is_prototype_map(bool value); 5718 inline bool is_prototype_map(); 5719 5720 inline void set_elements_kind(ElementsKind elements_kind) { 5721 DCHECK(elements_kind < kElementsKindCount); 5722 DCHECK(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize)); 5723 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); 5724 DCHECK(this->elements_kind() == elements_kind); 5725 } 5726 5727 inline ElementsKind elements_kind() { 5728 return Map::ElementsKindBits::decode(bit_field2()); 5729 } 5730 5731 // Tells whether the instance has fast elements that are only Smis. 5732 inline bool has_fast_smi_elements() { 5733 return IsFastSmiElementsKind(elements_kind()); 5734 } 5735 5736 // Tells whether the instance has fast elements. 5737 inline bool has_fast_object_elements() { 5738 return IsFastObjectElementsKind(elements_kind()); 5739 } 5740 5741 inline bool has_fast_smi_or_object_elements() { 5742 return IsFastSmiOrObjectElementsKind(elements_kind()); 5743 } 5744 5745 inline bool has_fast_double_elements() { 5746 return IsFastDoubleElementsKind(elements_kind()); 5747 } 5748 5749 inline bool has_fast_elements() { 5750 return IsFastElementsKind(elements_kind()); 5751 } 5752 5753 inline bool has_sloppy_arguments_elements() { 5754 return elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS; 5755 } 5756 5757 inline bool has_external_array_elements() { 5758 return IsExternalArrayElementsKind(elements_kind()); 5759 } 5760 5761 inline bool has_fixed_typed_array_elements() { 5762 return IsFixedTypedArrayElementsKind(elements_kind()); 5763 } 5764 5765 inline bool has_dictionary_elements() { 5766 return IsDictionaryElementsKind(elements_kind()); 5767 } 5768 5769 inline bool has_slow_elements_kind() { 5770 return elements_kind() == DICTIONARY_ELEMENTS 5771 || elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS; 5772 } 5773 5774 static bool IsValidElementsTransition(ElementsKind from_kind, 5775 ElementsKind to_kind); 5776 5777 // Returns true if the current map doesn't have DICTIONARY_ELEMENTS but if a 5778 // map with DICTIONARY_ELEMENTS was found in the prototype chain. 5779 bool DictionaryElementsInPrototypeChainOnly(); 5780 5781 inline bool HasTransitionArray() const; 5782 inline bool HasElementsTransition(); 5783 inline Map* elements_transition_map(); 5784 5785 inline Map* GetTransition(int transition_index); 5786 inline int SearchTransition(Name* name); 5787 inline FixedArrayBase* GetInitialElements(); 5788 5789 DECL_ACCESSORS(transitions, TransitionArray) 5790 5791 static inline Handle<String> ExpectedTransitionKey(Handle<Map> map); 5792 static inline Handle<Map> ExpectedTransitionTarget(Handle<Map> map); 5793 5794 // Try to follow an existing transition to a field with attributes NONE. The 5795 // return value indicates whether the transition was successful. 5796 static inline Handle<Map> FindTransitionToField(Handle<Map> map, 5797 Handle<Name> key); 5798 5799 Map* FindRootMap(); 5800 Map* FindFieldOwner(int descriptor); 5801 5802 inline int GetInObjectPropertyOffset(int index); 5803 5804 int NumberOfFields(); 5805 5806 // TODO(ishell): candidate with JSObject::MigrateToMap(). 5807 bool InstancesNeedRewriting(Map* target, int target_number_of_fields, 5808 int target_inobject, int target_unused, 5809 int* old_number_of_fields); 5810 // TODO(ishell): moveit! 5811 static Handle<Map> GeneralizeAllFieldRepresentations(Handle<Map> map); 5812 MUST_USE_RESULT static Handle<HeapType> GeneralizeFieldType( 5813 Handle<HeapType> type1, 5814 Handle<HeapType> type2, 5815 Isolate* isolate); 5816 static void GeneralizeFieldType(Handle<Map> map, 5817 int modify_index, 5818 Handle<HeapType> new_field_type); 5819 static Handle<Map> GeneralizeRepresentation( 5820 Handle<Map> map, 5821 int modify_index, 5822 Representation new_representation, 5823 Handle<HeapType> new_field_type, 5824 StoreMode store_mode); 5825 static Handle<Map> CopyGeneralizeAllRepresentations( 5826 Handle<Map> map, 5827 int modify_index, 5828 StoreMode store_mode, 5829 PropertyAttributes attributes, 5830 const char* reason); 5831 static Handle<Map> CopyGeneralizeAllRepresentations( 5832 Handle<Map> map, 5833 int modify_index, 5834 StoreMode store_mode, 5835 const char* reason); 5836 5837 static Handle<Map> PrepareForDataProperty(Handle<Map> old_map, 5838 int descriptor_number, 5839 Handle<Object> value); 5840 5841 static Handle<Map> Normalize(Handle<Map> map, PropertyNormalizationMode mode); 5842 5843 // Returns the constructor name (the name (possibly, inferred name) of the 5844 // function that was used to instantiate the object). 5845 String* constructor_name(); 5846 5847 // Tells whether the map is used for JSObjects in dictionary mode (ie 5848 // normalized objects, ie objects for which HasFastProperties returns false). 5849 // A map can never be used for both dictionary mode and fast mode JSObjects. 5850 // False by default and for HeapObjects that are not JSObjects. 5851 inline void set_dictionary_map(bool value); 5852 inline bool is_dictionary_map(); 5853 5854 // Tells whether the instance needs security checks when accessing its 5855 // properties. 5856 inline void set_is_access_check_needed(bool access_check_needed); 5857 inline bool is_access_check_needed(); 5858 5859 // Returns true if map has a non-empty stub code cache. 5860 inline bool has_code_cache(); 5861 5862 // [prototype]: implicit prototype object. 5863 DECL_ACCESSORS(prototype, Object) 5864 5865 // [constructor]: points back to the function responsible for this map. 5866 DECL_ACCESSORS(constructor, Object) 5867 5868 // [instance descriptors]: describes the object. 5869 DECL_ACCESSORS(instance_descriptors, DescriptorArray) 5870 inline void InitializeDescriptors(DescriptorArray* descriptors); 5871 5872 // [stub cache]: contains stubs compiled for this map. 5873 DECL_ACCESSORS(code_cache, Object) 5874 5875 // [dependent code]: list of optimized codes that weakly embed this map. 5876 DECL_ACCESSORS(dependent_code, DependentCode) 5877 5878 // [back pointer]: points back to the parent map from which a transition 5879 // leads to this map. The field overlaps with prototype transitions and the 5880 // back pointer will be moved into the prototype transitions array if 5881 // required. 5882 inline Object* GetBackPointer(); 5883 inline void SetBackPointer(Object* value, 5884 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 5885 inline void init_back_pointer(Object* undefined); 5886 5887 // [prototype transitions]: cache of prototype transitions. 5888 // Prototype transition is a transition that happens 5889 // when we change object's prototype to a new one. 5890 // Cache format: 5891 // 0: finger - index of the first free cell in the cache 5892 // 1: back pointer that overlaps with prototype transitions field. 5893 // 2 + 2 * i: prototype 5894 // 3 + 2 * i: target map 5895 inline FixedArray* GetPrototypeTransitions(); 5896 inline bool HasPrototypeTransitions(); 5897 5898 static const int kProtoTransitionHeaderSize = 1; 5899 static const int kProtoTransitionNumberOfEntriesOffset = 0; 5900 static const int kProtoTransitionElementsPerEntry = 2; 5901 static const int kProtoTransitionPrototypeOffset = 0; 5902 static const int kProtoTransitionMapOffset = 1; 5903 5904 inline int NumberOfProtoTransitions() { 5905 FixedArray* cache = GetPrototypeTransitions(); 5906 if (cache->length() == 0) return 0; 5907 return 5908 Smi::cast(cache->get(kProtoTransitionNumberOfEntriesOffset))->value(); 5909 } 5910 5911 inline void SetNumberOfProtoTransitions(int value) { 5912 FixedArray* cache = GetPrototypeTransitions(); 5913 DCHECK(cache->length() != 0); 5914 cache->set(kProtoTransitionNumberOfEntriesOffset, Smi::FromInt(value)); 5915 } 5916 5917 // Lookup in the map's instance descriptors and fill out the result 5918 // with the given holder if the name is found. The holder may be 5919 // NULL when this function is used from the compiler. 5920 inline void LookupDescriptor(JSObject* holder, 5921 Name* name, 5922 LookupResult* result); 5923 5924 inline void LookupTransition(JSObject* holder, 5925 Name* name, 5926 LookupResult* result); 5927 5928 inline PropertyDetails GetLastDescriptorDetails(); 5929 5930 // The size of transition arrays are limited so they do not end up in large 5931 // object space. Otherwise ClearNonLiveTransitions would leak memory while 5932 // applying in-place right trimming. 5933 inline bool CanHaveMoreTransitions(); 5934 5935 int LastAdded() { 5936 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5937 DCHECK(number_of_own_descriptors > 0); 5938 return number_of_own_descriptors - 1; 5939 } 5940 5941 int NumberOfOwnDescriptors() { 5942 return NumberOfOwnDescriptorsBits::decode(bit_field3()); 5943 } 5944 5945 void SetNumberOfOwnDescriptors(int number) { 5946 DCHECK(number <= instance_descriptors()->number_of_descriptors()); 5947 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); 5948 } 5949 5950 inline Cell* RetrieveDescriptorsPointer(); 5951 5952 int EnumLength() { 5953 return EnumLengthBits::decode(bit_field3()); 5954 } 5955 5956 void SetEnumLength(int length) { 5957 if (length != kInvalidEnumCacheSentinel) { 5958 DCHECK(length >= 0); 5959 DCHECK(length == 0 || instance_descriptors()->HasEnumCache()); 5960 DCHECK(length <= NumberOfOwnDescriptors()); 5961 } 5962 set_bit_field3(EnumLengthBits::update(bit_field3(), length)); 5963 } 5964 5965 inline bool owns_descriptors(); 5966 inline void set_owns_descriptors(bool owns_descriptors); 5967 inline bool has_instance_call_handler(); 5968 inline void set_has_instance_call_handler(); 5969 inline void freeze(); 5970 inline bool is_frozen(); 5971 inline void mark_unstable(); 5972 inline bool is_stable(); 5973 inline void set_migration_target(bool value); 5974 inline bool is_migration_target(); 5975 inline void set_done_inobject_slack_tracking(bool value); 5976 inline bool done_inobject_slack_tracking(); 5977 inline void set_construction_count(int value); 5978 inline int construction_count(); 5979 inline void deprecate(); 5980 inline bool is_deprecated(); 5981 inline bool CanBeDeprecated(); 5982 // Returns a non-deprecated version of the input. If the input was not 5983 // deprecated, it is directly returned. Otherwise, the non-deprecated version 5984 // is found by re-transitioning from the root of the transition tree using the 5985 // descriptor array of the map. Returns NULL if no updated map is found. 5986 // This method also applies any pending migrations along the prototype chain. 5987 static MaybeHandle<Map> TryUpdate(Handle<Map> map) WARN_UNUSED_RESULT; 5988 // Same as above, but does not touch the prototype chain. 5989 static MaybeHandle<Map> TryUpdateInternal(Handle<Map> map) 5990 WARN_UNUSED_RESULT; 5991 5992 // Returns a non-deprecated version of the input. This method may deprecate 5993 // existing maps along the way if encodings conflict. Not for use while 5994 // gathering type feedback. Use TryUpdate in those cases instead. 5995 static Handle<Map> Update(Handle<Map> map); 5996 5997 static Handle<Map> CopyDropDescriptors(Handle<Map> map); 5998 static Handle<Map> CopyInsertDescriptor(Handle<Map> map, 5999 Descriptor* descriptor, 6000 TransitionFlag flag); 6001 6002 MUST_USE_RESULT static MaybeHandle<Map> CopyWithField( 6003 Handle<Map> map, 6004 Handle<Name> name, 6005 Handle<HeapType> type, 6006 PropertyAttributes attributes, 6007 Representation representation, 6008 TransitionFlag flag); 6009 6010 MUST_USE_RESULT static MaybeHandle<Map> CopyWithConstant( 6011 Handle<Map> map, 6012 Handle<Name> name, 6013 Handle<Object> constant, 6014 PropertyAttributes attributes, 6015 TransitionFlag flag); 6016 6017 // Returns a new map with all transitions dropped from the given map and 6018 // the ElementsKind set. 6019 static Handle<Map> TransitionElementsTo(Handle<Map> map, 6020 ElementsKind to_kind); 6021 6022 static Handle<Map> AsElementsKind(Handle<Map> map, ElementsKind kind); 6023 6024 static Handle<Map> CopyAsElementsKind(Handle<Map> map, 6025 ElementsKind kind, 6026 TransitionFlag flag); 6027 6028 static Handle<Map> CopyForObserved(Handle<Map> map); 6029 6030 static Handle<Map> CopyForFreeze(Handle<Map> map); 6031 // Maximal number of fast properties. Used to restrict the number of map 6032 // transitions to avoid an explosion in the number of maps for objects used as 6033 // dictionaries. 6034 inline bool TooManyFastProperties(StoreFromKeyed store_mode); 6035 static Handle<Map> TransitionToDataProperty(Handle<Map> map, 6036 Handle<Name> name, 6037 Handle<Object> value, 6038 PropertyAttributes attributes, 6039 StoreFromKeyed store_mode); 6040 static Handle<Map> TransitionToAccessorProperty( 6041 Handle<Map> map, Handle<Name> name, AccessorComponent component, 6042 Handle<Object> accessor, PropertyAttributes attributes); 6043 static Handle<Map> ReconfigureDataProperty(Handle<Map> map, int descriptor, 6044 PropertyAttributes attributes); 6045 6046 inline void AppendDescriptor(Descriptor* desc); 6047 6048 // Returns a copy of the map, with all transitions dropped from the 6049 // instance descriptors. 6050 static Handle<Map> Copy(Handle<Map> map); 6051 static Handle<Map> Create(Isolate* isolate, int inobject_properties); 6052 6053 // Returns the next free property index (only valid for FAST MODE). 6054 int NextFreePropertyIndex(); 6055 6056 // Returns the number of properties described in instance_descriptors 6057 // filtering out properties with the specified attributes. 6058 int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS, 6059 PropertyAttributes filter = NONE); 6060 6061 // Returns the number of slots allocated for the initial properties 6062 // backing storage for instances of this map. 6063 int InitialPropertiesLength() { 6064 return pre_allocated_property_fields() + unused_property_fields() - 6065 inobject_properties(); 6066 } 6067 6068 DECLARE_CAST(Map) 6069 6070 // Code cache operations. 6071 6072 // Clears the code cache. 6073 inline void ClearCodeCache(Heap* heap); 6074 6075 // Update code cache. 6076 static void UpdateCodeCache(Handle<Map> map, 6077 Handle<Name> name, 6078 Handle<Code> code); 6079 6080 // Extend the descriptor array of the map with the list of descriptors. 6081 // In case of duplicates, the latest descriptor is used. 6082 static void AppendCallbackDescriptors(Handle<Map> map, 6083 Handle<Object> descriptors); 6084 6085 static void EnsureDescriptorSlack(Handle<Map> map, int slack); 6086 6087 // Returns the found code or undefined if absent. 6088 Object* FindInCodeCache(Name* name, Code::Flags flags); 6089 6090 // Returns the non-negative index of the code object if it is in the 6091 // cache and -1 otherwise. 6092 int IndexInCodeCache(Object* name, Code* code); 6093 6094 // Removes a code object from the code cache at the given index. 6095 void RemoveFromCodeCache(Name* name, Code* code, int index); 6096 6097 // Set all map transitions from this map to dead maps to null. Also clear 6098 // back pointers in transition targets so that we do not process this map 6099 // again while following back pointers. 6100 void ClearNonLiveTransitions(Heap* heap); 6101 6102 // Computes a hash value for this map, to be used in HashTables and such. 6103 int Hash(); 6104 6105 // Returns the map that this map transitions to if its elements_kind 6106 // is changed to |elements_kind|, or NULL if no such map is cached yet. 6107 // |safe_to_add_transitions| is set to false if adding transitions is not 6108 // allowed. 6109 Map* LookupElementsTransitionMap(ElementsKind elements_kind); 6110 6111 // Returns the transitioned map for this map with the most generic 6112 // elements_kind that's found in |candidates|, or null handle if no match is 6113 // found at all. 6114 Handle<Map> FindTransitionedMap(MapHandleList* candidates); 6115 6116 bool CanTransition() { 6117 // Only JSObject and subtypes have map transitions and back pointers. 6118 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); 6119 return instance_type() >= FIRST_JS_OBJECT_TYPE; 6120 } 6121 6122 bool IsJSObjectMap() { 6123 return instance_type() >= FIRST_JS_OBJECT_TYPE; 6124 } 6125 bool IsJSProxyMap() { 6126 InstanceType type = instance_type(); 6127 return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE; 6128 } 6129 bool IsJSGlobalProxyMap() { 6130 return instance_type() == JS_GLOBAL_PROXY_TYPE; 6131 } 6132 bool IsJSGlobalObjectMap() { 6133 return instance_type() == JS_GLOBAL_OBJECT_TYPE; 6134 } 6135 bool IsGlobalObjectMap() { 6136 const InstanceType type = instance_type(); 6137 return type == JS_GLOBAL_OBJECT_TYPE || type == JS_BUILTINS_OBJECT_TYPE; 6138 } 6139 6140 inline bool CanOmitMapChecks(); 6141 6142 static void AddDependentCompilationInfo(Handle<Map> map, 6143 DependentCode::DependencyGroup group, 6144 CompilationInfo* info); 6145 6146 static void AddDependentCode(Handle<Map> map, 6147 DependentCode::DependencyGroup group, 6148 Handle<Code> code); 6149 static void AddDependentIC(Handle<Map> map, 6150 Handle<Code> stub); 6151 6152 bool IsMapInArrayPrototypeChain(); 6153 6154 // Dispatched behavior. 6155 DECLARE_PRINTER(Map) 6156 DECLARE_VERIFIER(Map) 6157 6158 #ifdef VERIFY_HEAP 6159 void DictionaryMapVerify(); 6160 void VerifyOmittedMapChecks(); 6161 #endif 6162 6163 inline int visitor_id(); 6164 inline void set_visitor_id(int visitor_id); 6165 6166 typedef void (*TraverseCallback)(Map* map, void* data); 6167 6168 void TraverseTransitionTree(TraverseCallback callback, void* data); 6169 6170 // When you set the prototype of an object using the __proto__ accessor you 6171 // need a new map for the object (the prototype is stored in the map). In 6172 // order not to multiply maps unnecessarily we store these as transitions in 6173 // the original map. That way we can transition to the same map if the same 6174 // prototype is set, rather than creating a new map every time. The 6175 // transitions are in the form of a map where the keys are prototype objects 6176 // and the values are the maps the are transitioned to. 6177 static const int kMaxCachedPrototypeTransitions = 256; 6178 static Handle<Map> TransitionToPrototype(Handle<Map> map, 6179 Handle<Object> prototype); 6180 6181 static const int kMaxPreAllocatedPropertyFields = 255; 6182 6183 // Layout description. 6184 static const int kInstanceSizesOffset = HeapObject::kHeaderSize; 6185 static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; 6186 static const int kBitField3Offset = kInstanceAttributesOffset + kIntSize; 6187 static const int kPrototypeOffset = kBitField3Offset + kPointerSize; 6188 static const int kConstructorOffset = kPrototypeOffset + kPointerSize; 6189 // Storage for the transition array is overloaded to directly contain a back 6190 // pointer if unused. When the map has transitions, the back pointer is 6191 // transferred to the transition array and accessed through an extra 6192 // indirection. 6193 static const int kTransitionsOrBackPointerOffset = 6194 kConstructorOffset + kPointerSize; 6195 static const int kDescriptorsOffset = 6196 kTransitionsOrBackPointerOffset + kPointerSize; 6197 static const int kCodeCacheOffset = kDescriptorsOffset + kPointerSize; 6198 static const int kDependentCodeOffset = kCodeCacheOffset + kPointerSize; 6199 static const int kSize = kDependentCodeOffset + kPointerSize; 6200 6201 // Layout of pointer fields. Heap iteration code relies on them 6202 // being continuously allocated. 6203 static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset; 6204 static const int kPointerFieldsEndOffset = kSize; 6205 6206 // Byte offsets within kInstanceSizesOffset. 6207 static const int kInstanceSizeOffset = kInstanceSizesOffset + 0; 6208 static const int kInObjectPropertiesByte = 1; 6209 static const int kInObjectPropertiesOffset = 6210 kInstanceSizesOffset + kInObjectPropertiesByte; 6211 static const int kPreAllocatedPropertyFieldsByte = 2; 6212 static const int kPreAllocatedPropertyFieldsOffset = 6213 kInstanceSizesOffset + kPreAllocatedPropertyFieldsByte; 6214 static const int kVisitorIdByte = 3; 6215 static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte; 6216 6217 // Byte offsets within kInstanceAttributesOffset attributes. 6218 #if V8_TARGET_LITTLE_ENDIAN 6219 // Order instance type and bit field together such that they can be loaded 6220 // together as a 16-bit word with instance type in the lower 8 bits regardless 6221 // of endianess. Also provide endian-independent offset to that 16-bit word. 6222 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0; 6223 static const int kBitFieldOffset = kInstanceAttributesOffset + 1; 6224 #else 6225 static const int kBitFieldOffset = kInstanceAttributesOffset + 0; 6226 static const int kInstanceTypeOffset = kInstanceAttributesOffset + 1; 6227 #endif 6228 static const int kInstanceTypeAndBitFieldOffset = 6229 kInstanceAttributesOffset + 0; 6230 static const int kBitField2Offset = kInstanceAttributesOffset + 2; 6231 static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 3; 6232 6233 STATIC_ASSERT(kInstanceTypeAndBitFieldOffset == 6234 Internals::kMapInstanceTypeAndBitFieldOffset); 6235 6236 // Bit positions for bit field. 6237 static const int kHasNonInstancePrototype = 0; 6238 static const int kIsHiddenPrototype = 1; 6239 static const int kHasNamedInterceptor = 2; 6240 static const int kHasIndexedInterceptor = 3; 6241 static const int kIsUndetectable = 4; 6242 static const int kIsObserved = 5; 6243 static const int kIsAccessCheckNeeded = 6; 6244 class FunctionWithPrototype: public BitField<bool, 7, 1> {}; 6245 6246 // Bit positions for bit field 2 6247 static const int kIsExtensible = 0; 6248 static const int kStringWrapperSafeForDefaultValueOf = 1; 6249 class IsPrototypeMapBits : public BitField<bool, 2, 1> {}; 6250 class ElementsKindBits: public BitField<ElementsKind, 3, 5> {}; 6251 6252 // Derived values from bit field 2 6253 static const int8_t kMaximumBitField2FastElementValue = static_cast<int8_t>( 6254 (FAST_ELEMENTS + 1) << Map::ElementsKindBits::kShift) - 1; 6255 static const int8_t kMaximumBitField2FastSmiElementValue = 6256 static_cast<int8_t>((FAST_SMI_ELEMENTS + 1) << 6257 Map::ElementsKindBits::kShift) - 1; 6258 static const int8_t kMaximumBitField2FastHoleyElementValue = 6259 static_cast<int8_t>((FAST_HOLEY_ELEMENTS + 1) << 6260 Map::ElementsKindBits::kShift) - 1; 6261 static const int8_t kMaximumBitField2FastHoleySmiElementValue = 6262 static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) << 6263 Map::ElementsKindBits::kShift) - 1; 6264 6265 typedef FixedBodyDescriptor<kPointerFieldsBeginOffset, 6266 kPointerFieldsEndOffset, 6267 kSize> BodyDescriptor; 6268 6269 // Compares this map to another to see if they describe equivalent objects. 6270 // If |mode| is set to CLEAR_INOBJECT_PROPERTIES, |other| is treated as if 6271 // it had exactly zero inobject properties. 6272 // The "shared" flags of both this map and |other| are ignored. 6273 bool EquivalentToForNormalization(Map* other, PropertyNormalizationMode mode); 6274 6275 private: 6276 static void ConnectElementsTransition(Handle<Map> parent, Handle<Map> child); 6277 static void ConnectTransition(Handle<Map> parent, Handle<Map> child, 6278 Handle<Name> name, SimpleTransitionFlag flag); 6279 6280 bool EquivalentToForTransition(Map* other); 6281 static Handle<Map> RawCopy(Handle<Map> map, int instance_size); 6282 static Handle<Map> ShareDescriptor(Handle<Map> map, 6283 Handle<DescriptorArray> descriptors, 6284 Descriptor* descriptor); 6285 static Handle<Map> CopyInstallDescriptors( 6286 Handle<Map> map, 6287 int new_descriptor, 6288 Handle<DescriptorArray> descriptors); 6289 static Handle<Map> CopyAddDescriptor(Handle<Map> map, 6290 Descriptor* descriptor, 6291 TransitionFlag flag); 6292 static Handle<Map> CopyReplaceDescriptors( 6293 Handle<Map> map, 6294 Handle<DescriptorArray> descriptors, 6295 TransitionFlag flag, 6296 MaybeHandle<Name> maybe_name, 6297 SimpleTransitionFlag simple_flag = FULL_TRANSITION); 6298 static Handle<Map> CopyReplaceDescriptor(Handle<Map> map, 6299 Handle<DescriptorArray> descriptors, 6300 Descriptor* descriptor, 6301 int index, 6302 TransitionFlag flag); 6303 6304 static Handle<Map> CopyNormalized(Handle<Map> map, 6305 PropertyNormalizationMode mode); 6306 6307 // Fires when the layout of an object with a leaf map changes. 6308 // This includes adding transitions to the leaf map or changing 6309 // the descriptor array. 6310 inline void NotifyLeafMapLayoutChange(); 6311 6312 static Handle<Map> TransitionElementsToSlow(Handle<Map> object, 6313 ElementsKind to_kind); 6314 6315 // Zaps the contents of backing data structures. Note that the 6316 // heap verifier (i.e. VerifyMarkingVisitor) relies on zapping of objects 6317 // holding weak references when incremental marking is used, because it also 6318 // iterates over objects that are otherwise unreachable. 6319 // In general we only want to call these functions in release mode when 6320 // heap verification is turned on. 6321 void ZapPrototypeTransitions(); 6322 void ZapTransitions(); 6323 6324 void DeprecateTransitionTree(); 6325 void DeprecateTarget(Name* key, DescriptorArray* new_descriptors); 6326 6327 Map* FindLastMatchMap(int verbatim, int length, DescriptorArray* descriptors); 6328 6329 void UpdateFieldType(int descriptor_number, Handle<Name> name, 6330 Handle<HeapType> new_type); 6331 6332 void PrintGeneralization(FILE* file, 6333 const char* reason, 6334 int modify_index, 6335 int split, 6336 int descriptors, 6337 bool constant_to_field, 6338 Representation old_representation, 6339 Representation new_representation, 6340 HeapType* old_field_type, 6341 HeapType* new_field_type); 6342 6343 static inline void SetPrototypeTransitions( 6344 Handle<Map> map, 6345 Handle<FixedArray> prototype_transitions); 6346 6347 static Handle<Map> GetPrototypeTransition(Handle<Map> map, 6348 Handle<Object> prototype); 6349 static Handle<Map> PutPrototypeTransition(Handle<Map> map, 6350 Handle<Object> prototype, 6351 Handle<Map> target_map); 6352 6353 static const int kFastPropertiesSoftLimit = 12; 6354 static const int kMaxFastProperties = 128; 6355 6356 DISALLOW_IMPLICIT_CONSTRUCTORS(Map); 6357 }; 6358 6359 6360 // An abstract superclass, a marker class really, for simple structure classes. 6361 // It doesn't carry much functionality but allows struct classes to be 6362 // identified in the type system. 6363 class Struct: public HeapObject { 6364 public: 6365 inline void InitializeBody(int object_size); 6366 DECLARE_CAST(Struct) 6367 }; 6368 6369 6370 // A simple one-element struct, useful where smis need to be boxed. 6371 class Box : public Struct { 6372 public: 6373 // [value]: the boxed contents. 6374 DECL_ACCESSORS(value, Object) 6375 6376 DECLARE_CAST(Box) 6377 6378 // Dispatched behavior. 6379 DECLARE_PRINTER(Box) 6380 DECLARE_VERIFIER(Box) 6381 6382 static const int kValueOffset = HeapObject::kHeaderSize; 6383 static const int kSize = kValueOffset + kPointerSize; 6384 6385 private: 6386 DISALLOW_IMPLICIT_CONSTRUCTORS(Box); 6387 }; 6388 6389 6390 // Script describes a script which has been added to the VM. 6391 class Script: public Struct { 6392 public: 6393 // Script types. 6394 enum Type { 6395 TYPE_NATIVE = 0, 6396 TYPE_EXTENSION = 1, 6397 TYPE_NORMAL = 2 6398 }; 6399 6400 // Script compilation types. 6401 enum CompilationType { 6402 COMPILATION_TYPE_HOST = 0, 6403 COMPILATION_TYPE_EVAL = 1 6404 }; 6405 6406 // Script compilation state. 6407 enum CompilationState { 6408 COMPILATION_STATE_INITIAL = 0, 6409 COMPILATION_STATE_COMPILED = 1 6410 }; 6411 6412 // [source]: the script source. 6413 DECL_ACCESSORS(source, Object) 6414 6415 // [name]: the script name. 6416 DECL_ACCESSORS(name, Object) 6417 6418 // [id]: the script id. 6419 DECL_ACCESSORS(id, Smi) 6420 6421 // [line_offset]: script line offset in resource from where it was extracted. 6422 DECL_ACCESSORS(line_offset, Smi) 6423 6424 // [column_offset]: script column offset in resource from where it was 6425 // extracted. 6426 DECL_ACCESSORS(column_offset, Smi) 6427 6428 // [context_data]: context data for the context this script was compiled in. 6429 DECL_ACCESSORS(context_data, Object) 6430 6431 // [wrapper]: the wrapper cache. 6432 DECL_ACCESSORS(wrapper, Foreign) 6433 6434 // [type]: the script type. 6435 DECL_ACCESSORS(type, Smi) 6436 6437 // [line_ends]: FixedArray of line ends positions. 6438 DECL_ACCESSORS(line_ends, Object) 6439 6440 // [eval_from_shared]: for eval scripts the shared funcion info for the 6441 // function from which eval was called. 6442 DECL_ACCESSORS(eval_from_shared, Object) 6443 6444 // [eval_from_instructions_offset]: the instruction offset in the code for the 6445 // function from which eval was called where eval was called. 6446 DECL_ACCESSORS(eval_from_instructions_offset, Smi) 6447 6448 // [flags]: Holds an exciting bitfield. 6449 DECL_ACCESSORS(flags, Smi) 6450 6451 // [source_url]: sourceURL from magic comment 6452 DECL_ACCESSORS(source_url, Object) 6453 6454 // [source_url]: sourceMappingURL magic comment 6455 DECL_ACCESSORS(source_mapping_url, Object) 6456 6457 // [compilation_type]: how the the script was compiled. Encoded in the 6458 // 'flags' field. 6459 inline CompilationType compilation_type(); 6460 inline void set_compilation_type(CompilationType type); 6461 6462 // [compilation_state]: determines whether the script has already been 6463 // compiled. Encoded in the 'flags' field. 6464 inline CompilationState compilation_state(); 6465 inline void set_compilation_state(CompilationState state); 6466 6467 // [is_shared_cross_origin]: An opaque boolean set by the embedder via 6468 // ScriptOrigin, and used by the embedder to make decisions about the 6469 // script's level of privilege. V8 just passes this through. Encoded in 6470 // the 'flags' field. 6471 DECL_BOOLEAN_ACCESSORS(is_shared_cross_origin) 6472 6473 DECLARE_CAST(Script) 6474 6475 // If script source is an external string, check that the underlying 6476 // resource is accessible. Otherwise, always return true. 6477 inline bool HasValidSource(); 6478 6479 // Convert code position into column number. 6480 static int GetColumnNumber(Handle<Script> script, int code_pos); 6481 6482 // Convert code position into (zero-based) line number. 6483 // The non-handlified version does not allocate, but may be much slower. 6484 static int GetLineNumber(Handle<Script> script, int code_pos); 6485 int GetLineNumber(int code_pos); 6486 6487 static Handle<Object> GetNameOrSourceURL(Handle<Script> script); 6488 6489 // Init line_ends array with code positions of line ends inside script source. 6490 static void InitLineEnds(Handle<Script> script); 6491 6492 // Get the JS object wrapping the given script; create it if none exists. 6493 static Handle<JSObject> GetWrapper(Handle<Script> script); 6494 void ClearWrapperCache(); 6495 6496 // Dispatched behavior. 6497 DECLARE_PRINTER(Script) 6498 DECLARE_VERIFIER(Script) 6499 6500 static const int kSourceOffset = HeapObject::kHeaderSize; 6501 static const int kNameOffset = kSourceOffset + kPointerSize; 6502 static const int kLineOffsetOffset = kNameOffset + kPointerSize; 6503 static const int kColumnOffsetOffset = kLineOffsetOffset + kPointerSize; 6504 static const int kContextOffset = kColumnOffsetOffset + kPointerSize; 6505 static const int kWrapperOffset = kContextOffset + kPointerSize; 6506 static const int kTypeOffset = kWrapperOffset + kPointerSize; 6507 static const int kLineEndsOffset = kTypeOffset + kPointerSize; 6508 static const int kIdOffset = kLineEndsOffset + kPointerSize; 6509 static const int kEvalFromSharedOffset = kIdOffset + kPointerSize; 6510 static const int kEvalFrominstructionsOffsetOffset = 6511 kEvalFromSharedOffset + kPointerSize; 6512 static const int kFlagsOffset = 6513 kEvalFrominstructionsOffsetOffset + kPointerSize; 6514 static const int kSourceUrlOffset = kFlagsOffset + kPointerSize; 6515 static const int kSourceMappingUrlOffset = kSourceUrlOffset + kPointerSize; 6516 static const int kSize = kSourceMappingUrlOffset + kPointerSize; 6517 6518 private: 6519 int GetLineNumberWithArray(int code_pos); 6520 6521 // Bit positions in the flags field. 6522 static const int kCompilationTypeBit = 0; 6523 static const int kCompilationStateBit = 1; 6524 static const int kIsSharedCrossOriginBit = 2; 6525 6526 DISALLOW_IMPLICIT_CONSTRUCTORS(Script); 6527 }; 6528 6529 6530 // List of builtin functions we want to identify to improve code 6531 // generation. 6532 // 6533 // Each entry has a name of a global object property holding an object 6534 // optionally followed by ".prototype", a name of a builtin function 6535 // on the object (the one the id is set for), and a label. 6536 // 6537 // Installation of ids for the selected builtin functions is handled 6538 // by the bootstrapper. 6539 #define FUNCTIONS_WITH_ID_LIST(V) \ 6540 V(Array.prototype, indexOf, ArrayIndexOf) \ 6541 V(Array.prototype, lastIndexOf, ArrayLastIndexOf) \ 6542 V(Array.prototype, push, ArrayPush) \ 6543 V(Array.prototype, pop, ArrayPop) \ 6544 V(Array.prototype, shift, ArrayShift) \ 6545 V(Function.prototype, apply, FunctionApply) \ 6546 V(String.prototype, charCodeAt, StringCharCodeAt) \ 6547 V(String.prototype, charAt, StringCharAt) \ 6548 V(String, fromCharCode, StringFromCharCode) \ 6549 V(Math, floor, MathFloor) \ 6550 V(Math, round, MathRound) \ 6551 V(Math, ceil, MathCeil) \ 6552 V(Math, abs, MathAbs) \ 6553 V(Math, log, MathLog) \ 6554 V(Math, exp, MathExp) \ 6555 V(Math, sqrt, MathSqrt) \ 6556 V(Math, pow, MathPow) \ 6557 V(Math, max, MathMax) \ 6558 V(Math, min, MathMin) \ 6559 V(Math, imul, MathImul) \ 6560 V(Math, clz32, MathClz32) \ 6561 V(Math, fround, MathFround) 6562 6563 enum BuiltinFunctionId { 6564 kArrayCode, 6565 #define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \ 6566 k##name, 6567 FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID) 6568 #undef DECLARE_FUNCTION_ID 6569 // Fake id for a special case of Math.pow. Note, it continues the 6570 // list of math functions. 6571 kMathPowHalf 6572 }; 6573 6574 6575 // SharedFunctionInfo describes the JSFunction information that can be 6576 // shared by multiple instances of the function. 6577 class SharedFunctionInfo: public HeapObject { 6578 public: 6579 // [name]: Function name. 6580 DECL_ACCESSORS(name, Object) 6581 6582 // [code]: Function code. 6583 DECL_ACCESSORS(code, Code) 6584 inline void ReplaceCode(Code* code); 6585 6586 // [optimized_code_map]: Map from native context to optimized code 6587 // and a shared literals array or Smi(0) if none. 6588 DECL_ACCESSORS(optimized_code_map, Object) 6589 6590 // Returns index i of the entry with the specified context and OSR entry. 6591 // At position i - 1 is the context, position i the code, and i + 1 the 6592 // literals array. Returns -1 when no matching entry is found. 6593 int SearchOptimizedCodeMap(Context* native_context, BailoutId osr_ast_id); 6594 6595 // Installs optimized code from the code map on the given closure. The 6596 // index has to be consistent with a search result as defined above. 6597 FixedArray* GetLiteralsFromOptimizedCodeMap(int index); 6598 6599 Code* GetCodeFromOptimizedCodeMap(int index); 6600 6601 // Clear optimized code map. 6602 void ClearOptimizedCodeMap(); 6603 6604 // Removed a specific optimized code object from the optimized code map. 6605 void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason); 6606 6607 void ClearTypeFeedbackInfo(); 6608 6609 // Trims the optimized code map after entries have been removed. 6610 void TrimOptimizedCodeMap(int shrink_by); 6611 6612 // Add a new entry to the optimized code map. 6613 static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared, 6614 Handle<Context> native_context, 6615 Handle<Code> code, 6616 Handle<FixedArray> literals, 6617 BailoutId osr_ast_id); 6618 6619 // Layout description of the optimized code map. 6620 static const int kNextMapIndex = 0; 6621 static const int kEntriesStart = 1; 6622 static const int kContextOffset = 0; 6623 static const int kCachedCodeOffset = 1; 6624 static const int kLiteralsOffset = 2; 6625 static const int kOsrAstIdOffset = 3; 6626 static const int kEntryLength = 4; 6627 static const int kInitialLength = kEntriesStart + kEntryLength; 6628 6629 // [scope_info]: Scope info. 6630 DECL_ACCESSORS(scope_info, ScopeInfo) 6631 6632 // [construct stub]: Code stub for constructing instances of this function. 6633 DECL_ACCESSORS(construct_stub, Code) 6634 6635 // Returns if this function has been compiled to native code yet. 6636 inline bool is_compiled(); 6637 6638 // [length]: The function length - usually the number of declared parameters. 6639 // Use up to 2^30 parameters. 6640 inline int length() const; 6641 inline void set_length(int value); 6642 6643 // [formal parameter count]: The declared number of parameters. 6644 inline int formal_parameter_count() const; 6645 inline void set_formal_parameter_count(int value); 6646 6647 // Set the formal parameter count so the function code will be 6648 // called without using argument adaptor frames. 6649 inline void DontAdaptArguments(); 6650 6651 // [expected_nof_properties]: Expected number of properties for the function. 6652 inline int expected_nof_properties() const; 6653 inline void set_expected_nof_properties(int value); 6654 6655 // [feedback_vector] - accumulates ast node feedback from full-codegen and 6656 // (increasingly) from crankshafted code where sufficient feedback isn't 6657 // available. 6658 DECL_ACCESSORS(feedback_vector, TypeFeedbackVector) 6659 6660 // [instance class name]: class name for instances. 6661 DECL_ACCESSORS(instance_class_name, Object) 6662 6663 // [function data]: This field holds some additional data for function. 6664 // Currently it either has FunctionTemplateInfo to make benefit the API 6665 // or Smi identifying a builtin function. 6666 // In the long run we don't want all functions to have this field but 6667 // we can fix that when we have a better model for storing hidden data 6668 // on objects. 6669 DECL_ACCESSORS(function_data, Object) 6670 6671 inline bool IsApiFunction(); 6672 inline FunctionTemplateInfo* get_api_func_data(); 6673 inline bool HasBuiltinFunctionId(); 6674 inline BuiltinFunctionId builtin_function_id(); 6675 6676 // [script info]: Script from which the function originates. 6677 DECL_ACCESSORS(script, Object) 6678 6679 // [num_literals]: Number of literals used by this function. 6680 inline int num_literals() const; 6681 inline void set_num_literals(int value); 6682 6683 // [start_position_and_type]: Field used to store both the source code 6684 // position, whether or not the function is a function expression, 6685 // and whether or not the function is a toplevel function. The two 6686 // least significants bit indicates whether the function is an 6687 // expression and the rest contains the source code position. 6688 inline int start_position_and_type() const; 6689 inline void set_start_position_and_type(int value); 6690 6691 // [debug info]: Debug information. 6692 DECL_ACCESSORS(debug_info, Object) 6693 6694 // [inferred name]: Name inferred from variable or property 6695 // assignment of this function. Used to facilitate debugging and 6696 // profiling of JavaScript code written in OO style, where almost 6697 // all functions are anonymous but are assigned to object 6698 // properties. 6699 DECL_ACCESSORS(inferred_name, String) 6700 6701 // The function's name if it is non-empty, otherwise the inferred name. 6702 String* DebugName(); 6703 6704 // Position of the 'function' token in the script source. 6705 inline int function_token_position() const; 6706 inline void set_function_token_position(int function_token_position); 6707 6708 // Position of this function in the script source. 6709 inline int start_position() const; 6710 inline void set_start_position(int start_position); 6711 6712 // End position of this function in the script source. 6713 inline int end_position() const; 6714 inline void set_end_position(int end_position); 6715 6716 // Is this function a function expression in the source code. 6717 DECL_BOOLEAN_ACCESSORS(is_expression) 6718 6719 // Is this function a top-level function (scripts, evals). 6720 DECL_BOOLEAN_ACCESSORS(is_toplevel) 6721 6722 // Bit field containing various information collected by the compiler to 6723 // drive optimization. 6724 inline int compiler_hints() const; 6725 inline void set_compiler_hints(int value); 6726 6727 inline int ast_node_count() const; 6728 inline void set_ast_node_count(int count); 6729 6730 inline int profiler_ticks() const; 6731 inline void set_profiler_ticks(int ticks); 6732 6733 // Inline cache age is used to infer whether the function survived a context 6734 // disposal or not. In the former case we reset the opt_count. 6735 inline int ic_age(); 6736 inline void set_ic_age(int age); 6737 6738 // Indicates if this function can be lazy compiled. 6739 // This is used to determine if we can safely flush code from a function 6740 // when doing GC if we expect that the function will no longer be used. 6741 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation) 6742 6743 // Indicates if this function can be lazy compiled without a context. 6744 // This is used to determine if we can force compilation without reaching 6745 // the function through program execution but through other means (e.g. heap 6746 // iteration by the debugger). 6747 DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation_without_context) 6748 6749 // Indicates whether optimizations have been disabled for this 6750 // shared function info. If a function is repeatedly optimized or if 6751 // we cannot optimize the function we disable optimization to avoid 6752 // spending time attempting to optimize it again. 6753 DECL_BOOLEAN_ACCESSORS(optimization_disabled) 6754 6755 // Indicates the language mode. 6756 inline StrictMode strict_mode(); 6757 inline void set_strict_mode(StrictMode strict_mode); 6758 6759 // False if the function definitely does not allocate an arguments object. 6760 DECL_BOOLEAN_ACCESSORS(uses_arguments) 6761 6762 // True if the function has any duplicated parameter names. 6763 DECL_BOOLEAN_ACCESSORS(has_duplicate_parameters) 6764 6765 // Indicates whether the function is a native function. 6766 // These needs special treatment in .call and .apply since 6767 // null passed as the receiver should not be translated to the 6768 // global object. 6769 DECL_BOOLEAN_ACCESSORS(native) 6770 6771 // Indicate that this builtin needs to be inlined in crankshaft. 6772 DECL_BOOLEAN_ACCESSORS(inline_builtin) 6773 6774 // Indicates that the function was created by the Function function. 6775 // Though it's anonymous, toString should treat it as if it had the name 6776 // "anonymous". We don't set the name itself so that the system does not 6777 // see a binding for it. 6778 DECL_BOOLEAN_ACCESSORS(name_should_print_as_anonymous) 6779 6780 // Indicates whether the function is a bound function created using 6781 // the bind function. 6782 DECL_BOOLEAN_ACCESSORS(bound) 6783 6784 // Indicates that the function is anonymous (the name field can be set 6785 // through the API, which does not change this flag). 6786 DECL_BOOLEAN_ACCESSORS(is_anonymous) 6787 6788 // Is this a function or top-level/eval code. 6789 DECL_BOOLEAN_ACCESSORS(is_function) 6790 6791 // Indicates that code for this function cannot be cached. 6792 DECL_BOOLEAN_ACCESSORS(dont_cache) 6793 6794 // Indicates that code for this function cannot be flushed. 6795 DECL_BOOLEAN_ACCESSORS(dont_flush) 6796 6797 // Indicates that this function is a generator. 6798 DECL_BOOLEAN_ACCESSORS(is_generator) 6799 6800 // Indicates that this function is an arrow function. 6801 DECL_BOOLEAN_ACCESSORS(is_arrow) 6802 6803 // Indicates that this function is a concise method. 6804 DECL_BOOLEAN_ACCESSORS(is_concise_method) 6805 6806 // Indicates that this function is an asm function. 6807 DECL_BOOLEAN_ACCESSORS(asm_function) 6808 6809 inline FunctionKind kind(); 6810 inline void set_kind(FunctionKind kind); 6811 6812 // Indicates whether or not the code in the shared function support 6813 // deoptimization. 6814 inline bool has_deoptimization_support(); 6815 6816 // Enable deoptimization support through recompiled code. 6817 void EnableDeoptimizationSupport(Code* recompiled); 6818 6819 // Disable (further) attempted optimization of all functions sharing this 6820 // shared function info. 6821 void DisableOptimization(BailoutReason reason); 6822 6823 inline BailoutReason DisableOptimizationReason(); 6824 6825 // Lookup the bailout ID and DCHECK that it exists in the non-optimized 6826 // code, returns whether it asserted (i.e., always true if assertions are 6827 // disabled). 6828 bool VerifyBailoutId(BailoutId id); 6829 6830 // [source code]: Source code for the function. 6831 bool HasSourceCode() const; 6832 Handle<Object> GetSourceCode(); 6833 6834 // Number of times the function was optimized. 6835 inline int opt_count(); 6836 inline void set_opt_count(int opt_count); 6837 6838 // Number of times the function was deoptimized. 6839 inline void set_deopt_count(int value); 6840 inline int deopt_count(); 6841 inline void increment_deopt_count(); 6842 6843 // Number of time we tried to re-enable optimization after it 6844 // was disabled due to high number of deoptimizations. 6845 inline void set_opt_reenable_tries(int value); 6846 inline int opt_reenable_tries(); 6847 6848 inline void TryReenableOptimization(); 6849 6850 // Stores deopt_count, opt_reenable_tries and ic_age as bit-fields. 6851 inline void set_counters(int value); 6852 inline int counters() const; 6853 6854 // Stores opt_count and bailout_reason as bit-fields. 6855 inline void set_opt_count_and_bailout_reason(int value); 6856 inline int opt_count_and_bailout_reason() const; 6857 6858 void set_bailout_reason(BailoutReason reason) { 6859 set_opt_count_and_bailout_reason( 6860 DisabledOptimizationReasonBits::update(opt_count_and_bailout_reason(), 6861 reason)); 6862 } 6863 6864 // Check whether or not this function is inlineable. 6865 bool IsInlineable(); 6866 6867 // Source size of this function. 6868 int SourceSize(); 6869 6870 // Calculate the instance size. 6871 int CalculateInstanceSize(); 6872 6873 // Calculate the number of in-object properties. 6874 int CalculateInObjectProperties(); 6875 6876 // Dispatched behavior. 6877 DECLARE_PRINTER(SharedFunctionInfo) 6878 DECLARE_VERIFIER(SharedFunctionInfo) 6879 6880 void ResetForNewContext(int new_ic_age); 6881 6882 DECLARE_CAST(SharedFunctionInfo) 6883 6884 // Constants. 6885 static const int kDontAdaptArgumentsSentinel = -1; 6886 6887 // Layout description. 6888 // Pointer fields. 6889 static const int kNameOffset = HeapObject::kHeaderSize; 6890 static const int kCodeOffset = kNameOffset + kPointerSize; 6891 static const int kOptimizedCodeMapOffset = kCodeOffset + kPointerSize; 6892 static const int kScopeInfoOffset = kOptimizedCodeMapOffset + kPointerSize; 6893 static const int kConstructStubOffset = kScopeInfoOffset + kPointerSize; 6894 static const int kInstanceClassNameOffset = 6895 kConstructStubOffset + kPointerSize; 6896 static const int kFunctionDataOffset = 6897 kInstanceClassNameOffset + kPointerSize; 6898 static const int kScriptOffset = kFunctionDataOffset + kPointerSize; 6899 static const int kDebugInfoOffset = kScriptOffset + kPointerSize; 6900 static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize; 6901 static const int kFeedbackVectorOffset = 6902 kInferredNameOffset + kPointerSize; 6903 #if V8_HOST_ARCH_32_BIT 6904 // Smi fields. 6905 static const int kLengthOffset = 6906 kFeedbackVectorOffset + kPointerSize; 6907 static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize; 6908 static const int kExpectedNofPropertiesOffset = 6909 kFormalParameterCountOffset + kPointerSize; 6910 static const int kNumLiteralsOffset = 6911 kExpectedNofPropertiesOffset + kPointerSize; 6912 static const int kStartPositionAndTypeOffset = 6913 kNumLiteralsOffset + kPointerSize; 6914 static const int kEndPositionOffset = 6915 kStartPositionAndTypeOffset + kPointerSize; 6916 static const int kFunctionTokenPositionOffset = 6917 kEndPositionOffset + kPointerSize; 6918 static const int kCompilerHintsOffset = 6919 kFunctionTokenPositionOffset + kPointerSize; 6920 static const int kOptCountAndBailoutReasonOffset = 6921 kCompilerHintsOffset + kPointerSize; 6922 static const int kCountersOffset = 6923 kOptCountAndBailoutReasonOffset + kPointerSize; 6924 static const int kAstNodeCountOffset = 6925 kCountersOffset + kPointerSize; 6926 static const int kProfilerTicksOffset = 6927 kAstNodeCountOffset + kPointerSize; 6928 6929 // Total size. 6930 static const int kSize = kProfilerTicksOffset + kPointerSize; 6931 #else 6932 // The only reason to use smi fields instead of int fields 6933 // is to allow iteration without maps decoding during 6934 // garbage collections. 6935 // To avoid wasting space on 64-bit architectures we use 6936 // the following trick: we group integer fields into pairs 6937 // First integer in each pair is shifted left by 1. 6938 // By doing this we guarantee that LSB of each kPointerSize aligned 6939 // word is not set and thus this word cannot be treated as pointer 6940 // to HeapObject during old space traversal. 6941 static const int kLengthOffset = 6942 kFeedbackVectorOffset + kPointerSize; 6943 static const int kFormalParameterCountOffset = 6944 kLengthOffset + kIntSize; 6945 6946 static const int kExpectedNofPropertiesOffset = 6947 kFormalParameterCountOffset + kIntSize; 6948 static const int kNumLiteralsOffset = 6949 kExpectedNofPropertiesOffset + kIntSize; 6950 6951 static const int kEndPositionOffset = 6952 kNumLiteralsOffset + kIntSize; 6953 static const int kStartPositionAndTypeOffset = 6954 kEndPositionOffset + kIntSize; 6955 6956 static const int kFunctionTokenPositionOffset = 6957 kStartPositionAndTypeOffset + kIntSize; 6958 static const int kCompilerHintsOffset = 6959 kFunctionTokenPositionOffset + kIntSize; 6960 6961 static const int kOptCountAndBailoutReasonOffset = 6962 kCompilerHintsOffset + kIntSize; 6963 static const int kCountersOffset = 6964 kOptCountAndBailoutReasonOffset + kIntSize; 6965 6966 static const int kAstNodeCountOffset = 6967 kCountersOffset + kIntSize; 6968 static const int kProfilerTicksOffset = 6969 kAstNodeCountOffset + kIntSize; 6970 6971 // Total size. 6972 static const int kSize = kProfilerTicksOffset + kIntSize; 6973 6974 #endif 6975 6976 static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize); 6977 6978 typedef FixedBodyDescriptor<kNameOffset, 6979 kFeedbackVectorOffset + kPointerSize, 6980 kSize> BodyDescriptor; 6981 6982 // Bit positions in start_position_and_type. 6983 // The source code start position is in the 30 most significant bits of 6984 // the start_position_and_type field. 6985 static const int kIsExpressionBit = 0; 6986 static const int kIsTopLevelBit = 1; 6987 static const int kStartPositionShift = 2; 6988 static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1); 6989 6990 // Bit positions in compiler_hints. 6991 enum CompilerHints { 6992 kAllowLazyCompilation, 6993 kAllowLazyCompilationWithoutContext, 6994 kOptimizationDisabled, 6995 kStrictModeFunction, 6996 kUsesArguments, 6997 kHasDuplicateParameters, 6998 kNative, 6999 kInlineBuiltin, 7000 kBoundFunction, 7001 kIsAnonymous, 7002 kNameShouldPrintAsAnonymous, 7003 kIsFunction, 7004 kDontCache, 7005 kDontFlush, 7006 kIsArrow, 7007 kIsGenerator, 7008 kIsConciseMethod, 7009 kIsAsmFunction, 7010 kCompilerHintsCount // Pseudo entry 7011 }; 7012 7013 class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {}; 7014 7015 class DeoptCountBits : public BitField<int, 0, 4> {}; 7016 class OptReenableTriesBits : public BitField<int, 4, 18> {}; 7017 class ICAgeBits : public BitField<int, 22, 8> {}; 7018 7019 class OptCountBits : public BitField<int, 0, 22> {}; 7020 class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {}; 7021 7022 private: 7023 #if V8_HOST_ARCH_32_BIT 7024 // On 32 bit platforms, compiler hints is a smi. 7025 static const int kCompilerHintsSmiTagSize = kSmiTagSize; 7026 static const int kCompilerHintsSize = kPointerSize; 7027 #else 7028 // On 64 bit platforms, compiler hints is not a smi, see comment above. 7029 static const int kCompilerHintsSmiTagSize = 0; 7030 static const int kCompilerHintsSize = kIntSize; 7031 #endif 7032 7033 STATIC_ASSERT(SharedFunctionInfo::kCompilerHintsCount <= 7034 SharedFunctionInfo::kCompilerHintsSize * kBitsPerByte); 7035 7036 public: 7037 // Constants for optimizing codegen for strict mode function and 7038 // native tests. 7039 // Allows to use byte-width instructions. 7040 static const int kStrictModeBitWithinByte = 7041 (kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte; 7042 7043 static const int kNativeBitWithinByte = 7044 (kNative + kCompilerHintsSmiTagSize) % kBitsPerByte; 7045 7046 #if defined(V8_TARGET_LITTLE_ENDIAN) 7047 static const int kStrictModeByteOffset = kCompilerHintsOffset + 7048 (kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte; 7049 static const int kNativeByteOffset = kCompilerHintsOffset + 7050 (kNative + kCompilerHintsSmiTagSize) / kBitsPerByte; 7051 #elif defined(V8_TARGET_BIG_ENDIAN) 7052 static const int kStrictModeByteOffset = kCompilerHintsOffset + 7053 (kCompilerHintsSize - 1) - 7054 ((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte); 7055 static const int kNativeByteOffset = kCompilerHintsOffset + 7056 (kCompilerHintsSize - 1) - 7057 ((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte); 7058 #else 7059 #error Unknown byte ordering 7060 #endif 7061 7062 private: 7063 DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo); 7064 }; 7065 7066 7067 // Printing support. 7068 struct SourceCodeOf { 7069 explicit SourceCodeOf(SharedFunctionInfo* v, int max = -1) 7070 : value(v), max_length(max) {} 7071 const SharedFunctionInfo* value; 7072 int max_length; 7073 }; 7074 7075 7076 OStream& operator<<(OStream& os, const SourceCodeOf& v); 7077 7078 7079 class JSGeneratorObject: public JSObject { 7080 public: 7081 // [function]: The function corresponding to this generator object. 7082 DECL_ACCESSORS(function, JSFunction) 7083 7084 // [context]: The context of the suspended computation. 7085 DECL_ACCESSORS(context, Context) 7086 7087 // [receiver]: The receiver of the suspended computation. 7088 DECL_ACCESSORS(receiver, Object) 7089 7090 // [continuation]: Offset into code of continuation. 7091 // 7092 // A positive offset indicates a suspended generator. The special 7093 // kGeneratorExecuting and kGeneratorClosed values indicate that a generator 7094 // cannot be resumed. 7095 inline int continuation() const; 7096 inline void set_continuation(int continuation); 7097 inline bool is_closed(); 7098 inline bool is_executing(); 7099 inline bool is_suspended(); 7100 7101 // [operand_stack]: Saved operand stack. 7102 DECL_ACCESSORS(operand_stack, FixedArray) 7103 7104 // [stack_handler_index]: Index of first stack handler in operand_stack, or -1 7105 // if the captured activation had no stack handler. 7106 inline int stack_handler_index() const; 7107 inline void set_stack_handler_index(int stack_handler_index); 7108 7109 DECLARE_CAST(JSGeneratorObject) 7110 7111 // Dispatched behavior. 7112 DECLARE_PRINTER(JSGeneratorObject) 7113 DECLARE_VERIFIER(JSGeneratorObject) 7114 7115 // Magic sentinel values for the continuation. 7116 static const int kGeneratorExecuting = -1; 7117 static const int kGeneratorClosed = 0; 7118 7119 // Layout description. 7120 static const int kFunctionOffset = JSObject::kHeaderSize; 7121 static const int kContextOffset = kFunctionOffset + kPointerSize; 7122 static const int kReceiverOffset = kContextOffset + kPointerSize; 7123 static const int kContinuationOffset = kReceiverOffset + kPointerSize; 7124 static const int kOperandStackOffset = kContinuationOffset + kPointerSize; 7125 static const int kStackHandlerIndexOffset = 7126 kOperandStackOffset + kPointerSize; 7127 static const int kSize = kStackHandlerIndexOffset + kPointerSize; 7128 7129 // Resume mode, for use by runtime functions. 7130 enum ResumeMode { NEXT, THROW }; 7131 7132 // Yielding from a generator returns an object with the following inobject 7133 // properties. See Context::iterator_result_map() for the map. 7134 static const int kResultValuePropertyIndex = 0; 7135 static const int kResultDonePropertyIndex = 1; 7136 static const int kResultPropertyCount = 2; 7137 7138 static const int kResultValuePropertyOffset = JSObject::kHeaderSize; 7139 static const int kResultDonePropertyOffset = 7140 kResultValuePropertyOffset + kPointerSize; 7141 static const int kResultSize = kResultDonePropertyOffset + kPointerSize; 7142 7143 private: 7144 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGeneratorObject); 7145 }; 7146 7147 7148 // Representation for module instance objects. 7149 class JSModule: public JSObject { 7150 public: 7151 // [context]: the context holding the module's locals, or undefined if none. 7152 DECL_ACCESSORS(context, Object) 7153 7154 // [scope_info]: Scope info. 7155 DECL_ACCESSORS(scope_info, ScopeInfo) 7156 7157 DECLARE_CAST(JSModule) 7158 7159 // Dispatched behavior. 7160 DECLARE_PRINTER(JSModule) 7161 DECLARE_VERIFIER(JSModule) 7162 7163 // Layout description. 7164 static const int kContextOffset = JSObject::kHeaderSize; 7165 static const int kScopeInfoOffset = kContextOffset + kPointerSize; 7166 static const int kSize = kScopeInfoOffset + kPointerSize; 7167 7168 private: 7169 DISALLOW_IMPLICIT_CONSTRUCTORS(JSModule); 7170 }; 7171 7172 7173 // JSFunction describes JavaScript functions. 7174 class JSFunction: public JSObject { 7175 public: 7176 // [prototype_or_initial_map]: 7177 DECL_ACCESSORS(prototype_or_initial_map, Object) 7178 7179 // [shared]: The information about the function that 7180 // can be shared by instances. 7181 DECL_ACCESSORS(shared, SharedFunctionInfo) 7182 7183 // [context]: The context for this function. 7184 inline Context* context(); 7185 inline void set_context(Object* context); 7186 inline JSObject* global_proxy(); 7187 7188 // [code]: The generated code object for this function. Executed 7189 // when the function is invoked, e.g. foo() or new foo(). See 7190 // [[Call]] and [[Construct]] description in ECMA-262, section 7191 // 8.6.2, page 27. 7192 inline Code* code(); 7193 inline void set_code(Code* code); 7194 inline void set_code_no_write_barrier(Code* code); 7195 inline void ReplaceCode(Code* code); 7196 7197 // Tells whether this function is builtin. 7198 inline bool IsBuiltin(); 7199 7200 // Tells whether this function is defined in a native script. 7201 inline bool IsFromNativeScript(); 7202 7203 // Tells whether this function is defined in an extension script. 7204 inline bool IsFromExtensionScript(); 7205 7206 // Tells whether or not the function needs arguments adaption. 7207 inline bool NeedsArgumentsAdaption(); 7208 7209 // Tells whether or not this function has been optimized. 7210 inline bool IsOptimized(); 7211 7212 // Tells whether or not this function can be optimized. 7213 inline bool IsOptimizable(); 7214 7215 // Mark this function for lazy recompilation. The function will be 7216 // recompiled the next time it is executed. 7217 void MarkForOptimization(); 7218 void MarkForConcurrentOptimization(); 7219 void MarkInOptimizationQueue(); 7220 7221 // Tells whether or not the function is already marked for lazy 7222 // recompilation. 7223 inline bool IsMarkedForOptimization(); 7224 inline bool IsMarkedForConcurrentOptimization(); 7225 7226 // Tells whether or not the function is on the concurrent recompilation queue. 7227 inline bool IsInOptimizationQueue(); 7228 7229 // Inobject slack tracking is the way to reclaim unused inobject space. 7230 // 7231 // The instance size is initially determined by adding some slack to 7232 // expected_nof_properties (to allow for a few extra properties added 7233 // after the constructor). There is no guarantee that the extra space 7234 // will not be wasted. 7235 // 7236 // Here is the algorithm to reclaim the unused inobject space: 7237 // - Detect the first constructor call for this JSFunction. 7238 // When it happens enter the "in progress" state: initialize construction 7239 // counter in the initial_map and set the |done_inobject_slack_tracking| 7240 // flag. 7241 // - While the tracking is in progress create objects filled with 7242 // one_pointer_filler_map instead of undefined_value. This way they can be 7243 // resized quickly and safely. 7244 // - Once enough (kGenerousAllocationCount) objects have been created 7245 // compute the 'slack' (traverse the map transition tree starting from the 7246 // initial_map and find the lowest value of unused_property_fields). 7247 // - Traverse the transition tree again and decrease the instance size 7248 // of every map. Existing objects will resize automatically (they are 7249 // filled with one_pointer_filler_map). All further allocations will 7250 // use the adjusted instance size. 7251 // - SharedFunctionInfo's expected_nof_properties left unmodified since 7252 // allocations made using different closures could actually create different 7253 // kind of objects (see prototype inheritance pattern). 7254 // 7255 // Important: inobject slack tracking is not attempted during the snapshot 7256 // creation. 7257 7258 static const int kGenerousAllocationCount = Map::ConstructionCount::kMax; 7259 static const int kFinishSlackTracking = 1; 7260 static const int kNoSlackTracking = 0; 7261 7262 // True if the initial_map is set and the object constructions countdown 7263 // counter is not zero. 7264 inline bool IsInobjectSlackTrackingInProgress(); 7265 7266 // Starts the tracking. 7267 // Initializes object constructions countdown counter in the initial map. 7268 // IsInobjectSlackTrackingInProgress is normally true after this call, 7269 // except when tracking have not been started (e.g. the map has no unused 7270 // properties or the snapshot is being built). 7271 void StartInobjectSlackTracking(); 7272 7273 // Completes the tracking. 7274 // IsInobjectSlackTrackingInProgress is false after this call. 7275 void CompleteInobjectSlackTracking(); 7276 7277 // [literals_or_bindings]: Fixed array holding either 7278 // the materialized literals or the bindings of a bound function. 7279 // 7280 // If the function contains object, regexp or array literals, the 7281 // literals array prefix contains the object, regexp, and array 7282 // function to be used when creating these literals. This is 7283 // necessary so that we do not dynamically lookup the object, regexp 7284 // or array functions. Performing a dynamic lookup, we might end up 7285 // using the functions from a new context that we should not have 7286 // access to. 7287 // 7288 // On bound functions, the array is a (copy-on-write) fixed-array containing 7289 // the function that was bound, bound this-value and any bound 7290 // arguments. Bound functions never contain literals. 7291 DECL_ACCESSORS(literals_or_bindings, FixedArray) 7292 7293 inline FixedArray* literals(); 7294 inline void set_literals(FixedArray* literals); 7295 7296 inline FixedArray* function_bindings(); 7297 inline void set_function_bindings(FixedArray* bindings); 7298 7299 // The initial map for an object created by this constructor. 7300 inline Map* initial_map(); 7301 static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map, 7302 Handle<Object> prototype); 7303 inline bool has_initial_map(); 7304 static void EnsureHasInitialMap(Handle<JSFunction> function); 7305 7306 // Get and set the prototype property on a JSFunction. If the 7307 // function has an initial map the prototype is set on the initial 7308 // map. Otherwise, the prototype is put in the initial map field 7309 // until an initial map is needed. 7310 inline bool has_prototype(); 7311 inline bool has_instance_prototype(); 7312 inline Object* prototype(); 7313 inline Object* instance_prototype(); 7314 static void SetPrototype(Handle<JSFunction> function, 7315 Handle<Object> value); 7316 static void SetInstancePrototype(Handle<JSFunction> function, 7317 Handle<Object> value); 7318 7319 // Creates a new closure for the fucntion with the same bindings, 7320 // bound values, and prototype. An equivalent of spec operations 7321 // ``CloneMethod`` and ``CloneBoundFunction``. 7322 static Handle<JSFunction> CloneClosure(Handle<JSFunction> function); 7323 7324 // After prototype is removed, it will not be created when accessed, and 7325 // [[Construct]] from this function will not be allowed. 7326 bool RemovePrototype(); 7327 inline bool should_have_prototype(); 7328 7329 // Accessor for this function's initial map's [[class]] 7330 // property. This is primarily used by ECMA native functions. This 7331 // method sets the class_name field of this function's initial map 7332 // to a given value. It creates an initial map if this function does 7333 // not have one. Note that this method does not copy the initial map 7334 // if it has one already, but simply replaces it with the new value. 7335 // Instances created afterwards will have a map whose [[class]] is 7336 // set to 'value', but there is no guarantees on instances created 7337 // before. 7338 void SetInstanceClassName(String* name); 7339 7340 // Returns if this function has been compiled to native code yet. 7341 inline bool is_compiled(); 7342 7343 // [next_function_link]: Links functions into various lists, e.g. the list 7344 // of optimized functions hanging off the native_context. The CodeFlusher 7345 // uses this link to chain together flushing candidates. Treated weakly 7346 // by the garbage collector. 7347 DECL_ACCESSORS(next_function_link, Object) 7348 7349 // Prints the name of the function using PrintF. 7350 void PrintName(FILE* out = stdout); 7351 7352 DECLARE_CAST(JSFunction) 7353 7354 // Iterates the objects, including code objects indirectly referenced 7355 // through pointers to the first instruction in the code object. 7356 void JSFunctionIterateBody(int object_size, ObjectVisitor* v); 7357 7358 // Dispatched behavior. 7359 DECLARE_PRINTER(JSFunction) 7360 DECLARE_VERIFIER(JSFunction) 7361 7362 // Returns the number of allocated literals. 7363 inline int NumberOfLiterals(); 7364 7365 // Retrieve the native context from a function's literal array. 7366 static Context* NativeContextFromLiterals(FixedArray* literals); 7367 7368 // Used for flags such as --hydrogen-filter. 7369 bool PassesFilter(const char* raw_filter); 7370 7371 // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to 7372 // kSize) is weak and has special handling during garbage collection. 7373 static const int kCodeEntryOffset = JSObject::kHeaderSize; 7374 static const int kPrototypeOrInitialMapOffset = 7375 kCodeEntryOffset + kPointerSize; 7376 static const int kSharedFunctionInfoOffset = 7377 kPrototypeOrInitialMapOffset + kPointerSize; 7378 static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize; 7379 static const int kLiteralsOffset = kContextOffset + kPointerSize; 7380 static const int kNonWeakFieldsEndOffset = kLiteralsOffset + kPointerSize; 7381 static const int kNextFunctionLinkOffset = kNonWeakFieldsEndOffset; 7382 static const int kSize = kNextFunctionLinkOffset + kPointerSize; 7383 7384 // Layout of the literals array. 7385 static const int kLiteralsPrefixSize = 1; 7386 static const int kLiteralNativeContextIndex = 0; 7387 7388 // Layout of the bound-function binding array. 7389 static const int kBoundFunctionIndex = 0; 7390 static const int kBoundThisIndex = 1; 7391 static const int kBoundArgumentsStartIndex = 2; 7392 7393 private: 7394 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction); 7395 }; 7396 7397 7398 // JSGlobalProxy's prototype must be a JSGlobalObject or null, 7399 // and the prototype is hidden. JSGlobalProxy always delegates 7400 // property accesses to its prototype if the prototype is not null. 7401 // 7402 // A JSGlobalProxy can be reinitialized which will preserve its identity. 7403 // 7404 // Accessing a JSGlobalProxy requires security check. 7405 7406 class JSGlobalProxy : public JSObject { 7407 public: 7408 // [native_context]: the owner native context of this global proxy object. 7409 // It is null value if this object is not used by any context. 7410 DECL_ACCESSORS(native_context, Object) 7411 7412 // [hash]: The hash code property (undefined if not initialized yet). 7413 DECL_ACCESSORS(hash, Object) 7414 7415 DECLARE_CAST(JSGlobalProxy) 7416 7417 inline bool IsDetachedFrom(GlobalObject* global) const; 7418 7419 // Dispatched behavior. 7420 DECLARE_PRINTER(JSGlobalProxy) 7421 DECLARE_VERIFIER(JSGlobalProxy) 7422 7423 // Layout description. 7424 static const int kNativeContextOffset = JSObject::kHeaderSize; 7425 static const int kHashOffset = kNativeContextOffset + kPointerSize; 7426 static const int kSize = kHashOffset + kPointerSize; 7427 7428 private: 7429 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalProxy); 7430 }; 7431 7432 7433 // Forward declaration. 7434 class JSBuiltinsObject; 7435 7436 // Common super class for JavaScript global objects and the special 7437 // builtins global objects. 7438 class GlobalObject: public JSObject { 7439 public: 7440 // [builtins]: the object holding the runtime routines written in JS. 7441 DECL_ACCESSORS(builtins, JSBuiltinsObject) 7442 7443 // [native context]: the natives corresponding to this global object. 7444 DECL_ACCESSORS(native_context, Context) 7445 7446 // [global context]: the most recent (i.e. innermost) global context. 7447 DECL_ACCESSORS(global_context, Context) 7448 7449 // [global proxy]: the global proxy object of the context 7450 DECL_ACCESSORS(global_proxy, JSObject) 7451 7452 DECLARE_CAST(GlobalObject) 7453 7454 // Layout description. 7455 static const int kBuiltinsOffset = JSObject::kHeaderSize; 7456 static const int kNativeContextOffset = kBuiltinsOffset + kPointerSize; 7457 static const int kGlobalContextOffset = kNativeContextOffset + kPointerSize; 7458 static const int kGlobalProxyOffset = kGlobalContextOffset + kPointerSize; 7459 static const int kHeaderSize = kGlobalProxyOffset + kPointerSize; 7460 7461 private: 7462 DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject); 7463 }; 7464 7465 7466 // JavaScript global object. 7467 class JSGlobalObject: public GlobalObject { 7468 public: 7469 DECLARE_CAST(JSGlobalObject) 7470 7471 // Ensure that the global object has a cell for the given property name. 7472 static Handle<PropertyCell> EnsurePropertyCell(Handle<JSGlobalObject> global, 7473 Handle<Name> name); 7474 7475 inline bool IsDetached(); 7476 7477 // Dispatched behavior. 7478 DECLARE_PRINTER(JSGlobalObject) 7479 DECLARE_VERIFIER(JSGlobalObject) 7480 7481 // Layout description. 7482 static const int kSize = GlobalObject::kHeaderSize; 7483 7484 private: 7485 DISALLOW_IMPLICIT_CONSTRUCTORS(JSGlobalObject); 7486 }; 7487 7488 7489 // Builtins global object which holds the runtime routines written in 7490 // JavaScript. 7491 class JSBuiltinsObject: public GlobalObject { 7492 public: 7493 // Accessors for the runtime routines written in JavaScript. 7494 inline Object* javascript_builtin(Builtins::JavaScript id); 7495 inline void set_javascript_builtin(Builtins::JavaScript id, Object* value); 7496 7497 // Accessors for code of the runtime routines written in JavaScript. 7498 inline Code* javascript_builtin_code(Builtins::JavaScript id); 7499 inline void set_javascript_builtin_code(Builtins::JavaScript id, Code* value); 7500 7501 DECLARE_CAST(JSBuiltinsObject) 7502 7503 // Dispatched behavior. 7504 DECLARE_PRINTER(JSBuiltinsObject) 7505 DECLARE_VERIFIER(JSBuiltinsObject) 7506 7507 // Layout description. The size of the builtins object includes 7508 // room for two pointers per runtime routine written in javascript 7509 // (function and code object). 7510 static const int kJSBuiltinsCount = Builtins::id_count; 7511 static const int kJSBuiltinsOffset = GlobalObject::kHeaderSize; 7512 static const int kJSBuiltinsCodeOffset = 7513 GlobalObject::kHeaderSize + (kJSBuiltinsCount * kPointerSize); 7514 static const int kSize = 7515 kJSBuiltinsCodeOffset + (kJSBuiltinsCount * kPointerSize); 7516 7517 static int OffsetOfFunctionWithId(Builtins::JavaScript id) { 7518 return kJSBuiltinsOffset + id * kPointerSize; 7519 } 7520 7521 static int OffsetOfCodeWithId(Builtins::JavaScript id) { 7522 return kJSBuiltinsCodeOffset + id * kPointerSize; 7523 } 7524 7525 private: 7526 DISALLOW_IMPLICIT_CONSTRUCTORS(JSBuiltinsObject); 7527 }; 7528 7529 7530 // Representation for JS Wrapper objects, String, Number, Boolean, etc. 7531 class JSValue: public JSObject { 7532 public: 7533 // [value]: the object being wrapped. 7534 DECL_ACCESSORS(value, Object) 7535 7536 DECLARE_CAST(JSValue) 7537 7538 // Dispatched behavior. 7539 DECLARE_PRINTER(JSValue) 7540 DECLARE_VERIFIER(JSValue) 7541 7542 // Layout description. 7543 static const int kValueOffset = JSObject::kHeaderSize; 7544 static const int kSize = kValueOffset + kPointerSize; 7545 7546 private: 7547 DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue); 7548 }; 7549 7550 7551 class DateCache; 7552 7553 // Representation for JS date objects. 7554 class JSDate: public JSObject { 7555 public: 7556 // If one component is NaN, all of them are, indicating a NaN time value. 7557 // [value]: the time value. 7558 DECL_ACCESSORS(value, Object) 7559 // [year]: caches year. Either undefined, smi, or NaN. 7560 DECL_ACCESSORS(year, Object) 7561 // [month]: caches month. Either undefined, smi, or NaN. 7562 DECL_ACCESSORS(month, Object) 7563 // [day]: caches day. Either undefined, smi, or NaN. 7564 DECL_ACCESSORS(day, Object) 7565 // [weekday]: caches day of week. Either undefined, smi, or NaN. 7566 DECL_ACCESSORS(weekday, Object) 7567 // [hour]: caches hours. Either undefined, smi, or NaN. 7568 DECL_ACCESSORS(hour, Object) 7569 // [min]: caches minutes. Either undefined, smi, or NaN. 7570 DECL_ACCESSORS(min, Object) 7571 // [sec]: caches seconds. Either undefined, smi, or NaN. 7572 DECL_ACCESSORS(sec, Object) 7573 // [cache stamp]: sample of the date cache stamp at the 7574 // moment when chached fields were cached. 7575 DECL_ACCESSORS(cache_stamp, Object) 7576 7577 DECLARE_CAST(JSDate) 7578 7579 // Returns the date field with the specified index. 7580 // See FieldIndex for the list of date fields. 7581 static Object* GetField(Object* date, Smi* index); 7582 7583 void SetValue(Object* value, bool is_value_nan); 7584 7585 7586 // Dispatched behavior. 7587 DECLARE_PRINTER(JSDate) 7588 DECLARE_VERIFIER(JSDate) 7589 7590 // The order is important. It must be kept in sync with date macros 7591 // in macros.py. 7592 enum FieldIndex { 7593 kDateValue, 7594 kYear, 7595 kMonth, 7596 kDay, 7597 kWeekday, 7598 kHour, 7599 kMinute, 7600 kSecond, 7601 kFirstUncachedField, 7602 kMillisecond = kFirstUncachedField, 7603 kDays, 7604 kTimeInDay, 7605 kFirstUTCField, 7606 kYearUTC = kFirstUTCField, 7607 kMonthUTC, 7608 kDayUTC, 7609 kWeekdayUTC, 7610 kHourUTC, 7611 kMinuteUTC, 7612 kSecondUTC, 7613 kMillisecondUTC, 7614 kDaysUTC, 7615 kTimeInDayUTC, 7616 kTimezoneOffset 7617 }; 7618 7619 // Layout description. 7620 static const int kValueOffset = JSObject::kHeaderSize; 7621 static const int kYearOffset = kValueOffset + kPointerSize; 7622 static const int kMonthOffset = kYearOffset + kPointerSize; 7623 static const int kDayOffset = kMonthOffset + kPointerSize; 7624 static const int kWeekdayOffset = kDayOffset + kPointerSize; 7625 static const int kHourOffset = kWeekdayOffset + kPointerSize; 7626 static const int kMinOffset = kHourOffset + kPointerSize; 7627 static const int kSecOffset = kMinOffset + kPointerSize; 7628 static const int kCacheStampOffset = kSecOffset + kPointerSize; 7629 static const int kSize = kCacheStampOffset + kPointerSize; 7630 7631 private: 7632 inline Object* DoGetField(FieldIndex index); 7633 7634 Object* GetUTCField(FieldIndex index, double value, DateCache* date_cache); 7635 7636 // Computes and caches the cacheable fields of the date. 7637 inline void SetCachedFields(int64_t local_time_ms, DateCache* date_cache); 7638 7639 7640 DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate); 7641 }; 7642 7643 7644 // Representation of message objects used for error reporting through 7645 // the API. The messages are formatted in JavaScript so this object is 7646 // a real JavaScript object. The information used for formatting the 7647 // error messages are not directly accessible from JavaScript to 7648 // prevent leaking information to user code called during error 7649 // formatting. 7650 class JSMessageObject: public JSObject { 7651 public: 7652 // [type]: the type of error message. 7653 DECL_ACCESSORS(type, String) 7654 7655 // [arguments]: the arguments for formatting the error message. 7656 DECL_ACCESSORS(arguments, JSArray) 7657 7658 // [script]: the script from which the error message originated. 7659 DECL_ACCESSORS(script, Object) 7660 7661 // [stack_frames]: an array of stack frames for this error object. 7662 DECL_ACCESSORS(stack_frames, Object) 7663 7664 // [start_position]: the start position in the script for the error message. 7665 inline int start_position() const; 7666 inline void set_start_position(int value); 7667 7668 // [end_position]: the end position in the script for the error message. 7669 inline int end_position() const; 7670 inline void set_end_position(int value); 7671 7672 DECLARE_CAST(JSMessageObject) 7673 7674 // Dispatched behavior. 7675 DECLARE_PRINTER(JSMessageObject) 7676 DECLARE_VERIFIER(JSMessageObject) 7677 7678 // Layout description. 7679 static const int kTypeOffset = JSObject::kHeaderSize; 7680 static const int kArgumentsOffset = kTypeOffset + kPointerSize; 7681 static const int kScriptOffset = kArgumentsOffset + kPointerSize; 7682 static const int kStackFramesOffset = kScriptOffset + kPointerSize; 7683 static const int kStartPositionOffset = kStackFramesOffset + kPointerSize; 7684 static const int kEndPositionOffset = kStartPositionOffset + kPointerSize; 7685 static const int kSize = kEndPositionOffset + kPointerSize; 7686 7687 typedef FixedBodyDescriptor<HeapObject::kMapOffset, 7688 kStackFramesOffset + kPointerSize, 7689 kSize> BodyDescriptor; 7690 }; 7691 7692 7693 // Regular expressions 7694 // The regular expression holds a single reference to a FixedArray in 7695 // the kDataOffset field. 7696 // The FixedArray contains the following data: 7697 // - tag : type of regexp implementation (not compiled yet, atom or irregexp) 7698 // - reference to the original source string 7699 // - reference to the original flag string 7700 // If it is an atom regexp 7701 // - a reference to a literal string to search for 7702 // If it is an irregexp regexp: 7703 // - a reference to code for Latin1 inputs (bytecode or compiled), or a smi 7704 // used for tracking the last usage (used for code flushing). 7705 // - a reference to code for UC16 inputs (bytecode or compiled), or a smi 7706 // used for tracking the last usage (used for code flushing).. 7707 // - max number of registers used by irregexp implementations. 7708 // - number of capture registers (output values) of the regexp. 7709 class JSRegExp: public JSObject { 7710 public: 7711 // Meaning of Type: 7712 // NOT_COMPILED: Initial value. No data has been stored in the JSRegExp yet. 7713 // ATOM: A simple string to match against using an indexOf operation. 7714 // IRREGEXP: Compiled with Irregexp. 7715 // IRREGEXP_NATIVE: Compiled to native code with Irregexp. 7716 enum Type { NOT_COMPILED, ATOM, IRREGEXP }; 7717 enum Flag { 7718 NONE = 0, 7719 GLOBAL = 1, 7720 IGNORE_CASE = 2, 7721 MULTILINE = 4, 7722 STICKY = 8 7723 }; 7724 7725 class Flags { 7726 public: 7727 explicit Flags(uint32_t value) : value_(value) { } 7728 bool is_global() { return (value_ & GLOBAL) != 0; } 7729 bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; } 7730 bool is_multiline() { return (value_ & MULTILINE) != 0; } 7731 bool is_sticky() { return (value_ & STICKY) != 0; } 7732 uint32_t value() { return value_; } 7733 private: 7734 uint32_t value_; 7735 }; 7736 7737 DECL_ACCESSORS(data, Object) 7738 7739 inline Type TypeTag(); 7740 inline int CaptureCount(); 7741 inline Flags GetFlags(); 7742 inline String* Pattern(); 7743 inline Object* DataAt(int index); 7744 // Set implementation data after the object has been prepared. 7745 inline void SetDataAt(int index, Object* value); 7746 7747 static int code_index(bool is_latin1) { 7748 if (is_latin1) { 7749 return kIrregexpLatin1CodeIndex; 7750 } else { 7751 return kIrregexpUC16CodeIndex; 7752 } 7753 } 7754 7755 static int saved_code_index(bool is_latin1) { 7756 if (is_latin1) { 7757 return kIrregexpLatin1CodeSavedIndex; 7758 } else { 7759 return kIrregexpUC16CodeSavedIndex; 7760 } 7761 } 7762 7763 DECLARE_CAST(JSRegExp) 7764 7765 // Dispatched behavior. 7766 DECLARE_VERIFIER(JSRegExp) 7767 7768 static const int kDataOffset = JSObject::kHeaderSize; 7769 static const int kSize = kDataOffset + kPointerSize; 7770 7771 // Indices in the data array. 7772 static const int kTagIndex = 0; 7773 static const int kSourceIndex = kTagIndex + 1; 7774 static const int kFlagsIndex = kSourceIndex + 1; 7775 static const int kDataIndex = kFlagsIndex + 1; 7776 // The data fields are used in different ways depending on the 7777 // value of the tag. 7778 // Atom regexps (literal strings). 7779 static const int kAtomPatternIndex = kDataIndex; 7780 7781 static const int kAtomDataSize = kAtomPatternIndex + 1; 7782 7783 // Irregexp compiled code or bytecode for Latin1. If compilation 7784 // fails, this fields hold an exception object that should be 7785 // thrown if the regexp is used again. 7786 static const int kIrregexpLatin1CodeIndex = kDataIndex; 7787 // Irregexp compiled code or bytecode for UC16. If compilation 7788 // fails, this fields hold an exception object that should be 7789 // thrown if the regexp is used again. 7790 static const int kIrregexpUC16CodeIndex = kDataIndex + 1; 7791 7792 // Saved instance of Irregexp compiled code or bytecode for Latin1 that 7793 // is a potential candidate for flushing. 7794 static const int kIrregexpLatin1CodeSavedIndex = kDataIndex + 2; 7795 // Saved instance of Irregexp compiled code or bytecode for UC16 that is 7796 // a potential candidate for flushing. 7797 static const int kIrregexpUC16CodeSavedIndex = kDataIndex + 3; 7798 7799 // Maximal number of registers used by either Latin1 or UC16. 7800 // Only used to check that there is enough stack space 7801 static const int kIrregexpMaxRegisterCountIndex = kDataIndex + 4; 7802 // Number of captures in the compiled regexp. 7803 static const int kIrregexpCaptureCountIndex = kDataIndex + 5; 7804 7805 static const int kIrregexpDataSize = kIrregexpCaptureCountIndex + 1; 7806 7807 // Offsets directly into the data fixed array. 7808 static const int kDataTagOffset = 7809 FixedArray::kHeaderSize + kTagIndex * kPointerSize; 7810 static const int kDataOneByteCodeOffset = 7811 FixedArray::kHeaderSize + kIrregexpLatin1CodeIndex * kPointerSize; 7812 static const int kDataUC16CodeOffset = 7813 FixedArray::kHeaderSize + kIrregexpUC16CodeIndex * kPointerSize; 7814 static const int kIrregexpCaptureCountOffset = 7815 FixedArray::kHeaderSize + kIrregexpCaptureCountIndex * kPointerSize; 7816 7817 // In-object fields. 7818 static const int kSourceFieldIndex = 0; 7819 static const int kGlobalFieldIndex = 1; 7820 static const int kIgnoreCaseFieldIndex = 2; 7821 static const int kMultilineFieldIndex = 3; 7822 static const int kLastIndexFieldIndex = 4; 7823 static const int kInObjectFieldCount = 5; 7824 7825 // The uninitialized value for a regexp code object. 7826 static const int kUninitializedValue = -1; 7827 7828 // The compilation error value for the regexp code object. The real error 7829 // object is in the saved code field. 7830 static const int kCompilationErrorValue = -2; 7831 7832 // When we store the sweep generation at which we moved the code from the 7833 // code index to the saved code index we mask it of to be in the [0:255] 7834 // range. 7835 static const int kCodeAgeMask = 0xff; 7836 }; 7837 7838 7839 class CompilationCacheShape : public BaseShape<HashTableKey*> { 7840 public: 7841 static inline bool IsMatch(HashTableKey* key, Object* value) { 7842 return key->IsMatch(value); 7843 } 7844 7845 static inline uint32_t Hash(HashTableKey* key) { 7846 return key->Hash(); 7847 } 7848 7849 static inline uint32_t HashForObject(HashTableKey* key, Object* object) { 7850 return key->HashForObject(object); 7851 } 7852 7853 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); 7854 7855 static const int kPrefixSize = 0; 7856 static const int kEntrySize = 2; 7857 }; 7858 7859 7860 class CompilationCacheTable: public HashTable<CompilationCacheTable, 7861 CompilationCacheShape, 7862 HashTableKey*> { 7863 public: 7864 // Find cached value for a string key, otherwise return null. 7865 Handle<Object> Lookup(Handle<String> src, Handle<Context> context); 7866 Handle<Object> LookupEval(Handle<String> src, 7867 Handle<SharedFunctionInfo> shared, 7868 StrictMode strict_mode, int scope_position); 7869 Handle<Object> LookupRegExp(Handle<String> source, JSRegExp::Flags flags); 7870 static Handle<CompilationCacheTable> Put( 7871 Handle<CompilationCacheTable> cache, Handle<String> src, 7872 Handle<Context> context, Handle<Object> value); 7873 static Handle<CompilationCacheTable> PutEval( 7874 Handle<CompilationCacheTable> cache, Handle<String> src, 7875 Handle<SharedFunctionInfo> context, Handle<SharedFunctionInfo> value, 7876 int scope_position); 7877 static Handle<CompilationCacheTable> PutRegExp( 7878 Handle<CompilationCacheTable> cache, Handle<String> src, 7879 JSRegExp::Flags flags, Handle<FixedArray> value); 7880 void Remove(Object* value); 7881 7882 DECLARE_CAST(CompilationCacheTable) 7883 7884 private: 7885 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable); 7886 }; 7887 7888 7889 class CodeCache: public Struct { 7890 public: 7891 DECL_ACCESSORS(default_cache, FixedArray) 7892 DECL_ACCESSORS(normal_type_cache, Object) 7893 7894 // Add the code object to the cache. 7895 static void Update( 7896 Handle<CodeCache> cache, Handle<Name> name, Handle<Code> code); 7897 7898 // Lookup code object in the cache. Returns code object if found and undefined 7899 // if not. 7900 Object* Lookup(Name* name, Code::Flags flags); 7901 7902 // Get the internal index of a code object in the cache. Returns -1 if the 7903 // code object is not in that cache. This index can be used to later call 7904 // RemoveByIndex. The cache cannot be modified between a call to GetIndex and 7905 // RemoveByIndex. 7906 int GetIndex(Object* name, Code* code); 7907 7908 // Remove an object from the cache with the provided internal index. 7909 void RemoveByIndex(Object* name, Code* code, int index); 7910 7911 DECLARE_CAST(CodeCache) 7912 7913 // Dispatched behavior. 7914 DECLARE_PRINTER(CodeCache) 7915 DECLARE_VERIFIER(CodeCache) 7916 7917 static const int kDefaultCacheOffset = HeapObject::kHeaderSize; 7918 static const int kNormalTypeCacheOffset = 7919 kDefaultCacheOffset + kPointerSize; 7920 static const int kSize = kNormalTypeCacheOffset + kPointerSize; 7921 7922 private: 7923 static void UpdateDefaultCache( 7924 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code); 7925 static void UpdateNormalTypeCache( 7926 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code); 7927 Object* LookupDefaultCache(Name* name, Code::Flags flags); 7928 Object* LookupNormalTypeCache(Name* name, Code::Flags flags); 7929 7930 // Code cache layout of the default cache. Elements are alternating name and 7931 // code objects for non normal load/store/call IC's. 7932 static const int kCodeCacheEntrySize = 2; 7933 static const int kCodeCacheEntryNameOffset = 0; 7934 static const int kCodeCacheEntryCodeOffset = 1; 7935 7936 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCache); 7937 }; 7938 7939 7940 class CodeCacheHashTableShape : public BaseShape<HashTableKey*> { 7941 public: 7942 static inline bool IsMatch(HashTableKey* key, Object* value) { 7943 return key->IsMatch(value); 7944 } 7945 7946 static inline uint32_t Hash(HashTableKey* key) { 7947 return key->Hash(); 7948 } 7949 7950 static inline uint32_t HashForObject(HashTableKey* key, Object* object) { 7951 return key->HashForObject(object); 7952 } 7953 7954 static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); 7955 7956 static const int kPrefixSize = 0; 7957 static const int kEntrySize = 2; 7958 }; 7959 7960 7961 class CodeCacheHashTable: public HashTable<CodeCacheHashTable, 7962 CodeCacheHashTableShape, 7963 HashTableKey*> { 7964 public: 7965 Object* Lookup(Name* name, Code::Flags flags); 7966 static Handle<CodeCacheHashTable> Put( 7967 Handle<CodeCacheHashTable> table, 7968 Handle<Name> name, 7969 Handle<Code> code); 7970 7971 int GetIndex(Name* name, Code::Flags flags); 7972 void RemoveByIndex(int index); 7973 7974 DECLARE_CAST(CodeCacheHashTable) 7975 7976 // Initial size of the fixed array backing the hash table. 7977 static const int kInitialSize = 64; 7978 7979 private: 7980 DISALLOW_IMPLICIT_CONSTRUCTORS(CodeCacheHashTable); 7981 }; 7982 7983 7984 class PolymorphicCodeCache: public Struct { 7985 public: 7986 DECL_ACCESSORS(cache, Object) 7987 7988 static void Update(Handle<PolymorphicCodeCache> cache, 7989 MapHandleList* maps, 7990 Code::Flags flags, 7991 Handle<Code> code); 7992 7993 7994 // Returns an undefined value if the entry is not found. 7995 Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags); 7996 7997 DECLARE_CAST(PolymorphicCodeCache) 7998 7999 // Dispatched behavior. 8000 DECLARE_PRINTER(PolymorphicCodeCache) 8001 DECLARE_VERIFIER(PolymorphicCodeCache) 8002 8003 static const int kCacheOffset = HeapObject::kHeaderSize; 8004 static const int kSize = kCacheOffset + kPointerSize; 8005 8006 private: 8007 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCache); 8008 }; 8009 8010 8011 class PolymorphicCodeCacheHashTable 8012 : public HashTable<PolymorphicCodeCacheHashTable, 8013 CodeCacheHashTableShape, 8014 HashTableKey*> { 8015 public: 8016 Object* Lookup(MapHandleList* maps, int code_kind); 8017 8018 static Handle<PolymorphicCodeCacheHashTable> Put( 8019 Handle<PolymorphicCodeCacheHashTable> hash_table, 8020 MapHandleList* maps, 8021 int code_kind, 8022 Handle<Code> code); 8023 8024 DECLARE_CAST(PolymorphicCodeCacheHashTable) 8025 8026 static const int kInitialSize = 64; 8027 private: 8028 DISALLOW_IMPLICIT_CONSTRUCTORS(PolymorphicCodeCacheHashTable); 8029 }; 8030 8031 8032 class TypeFeedbackInfo: public Struct { 8033 public: 8034 inline int ic_total_count(); 8035 inline void set_ic_total_count(int count); 8036 8037 inline int ic_with_type_info_count(); 8038 inline void change_ic_with_type_info_count(int delta); 8039 8040 inline int ic_generic_count(); 8041 inline void change_ic_generic_count(int delta); 8042 8043 inline void initialize_storage(); 8044 8045 inline void change_own_type_change_checksum(); 8046 inline int own_type_change_checksum(); 8047 8048 inline void set_inlined_type_change_checksum(int checksum); 8049 inline bool matches_inlined_type_change_checksum(int checksum); 8050 8051 8052 DECLARE_CAST(TypeFeedbackInfo) 8053 8054 // Dispatched behavior. 8055 DECLARE_PRINTER(TypeFeedbackInfo) 8056 DECLARE_VERIFIER(TypeFeedbackInfo) 8057 8058 static const int kStorage1Offset = HeapObject::kHeaderSize; 8059 static const int kStorage2Offset = kStorage1Offset + kPointerSize; 8060 static const int kStorage3Offset = kStorage2Offset + kPointerSize; 8061 static const int kSize = kStorage3Offset + kPointerSize; 8062 8063 private: 8064 static const int kTypeChangeChecksumBits = 7; 8065 8066 class ICTotalCountField: public BitField<int, 0, 8067 kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT 8068 class OwnTypeChangeChecksum: public BitField<int, 8069 kSmiValueSize - kTypeChangeChecksumBits, 8070 kTypeChangeChecksumBits> {}; // NOLINT 8071 class ICsWithTypeInfoCountField: public BitField<int, 0, 8072 kSmiValueSize - kTypeChangeChecksumBits> {}; // NOLINT 8073 class InlinedTypeChangeChecksum: public BitField<int, 8074 kSmiValueSize - kTypeChangeChecksumBits, 8075 kTypeChangeChecksumBits> {}; // NOLINT 8076 8077 DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackInfo); 8078 }; 8079 8080 8081 enum AllocationSiteMode { 8082 DONT_TRACK_ALLOCATION_SITE, 8083 TRACK_ALLOCATION_SITE, 8084 LAST_ALLOCATION_SITE_MODE = TRACK_ALLOCATION_SITE 8085 }; 8086 8087 8088 class AllocationSite: public Struct { 8089 public: 8090 static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024; 8091 static const double kPretenureRatio; 8092 static const int kPretenureMinimumCreated = 100; 8093 8094 // Values for pretenure decision field. 8095 enum PretenureDecision { 8096 kUndecided = 0, 8097 kDontTenure = 1, 8098 kMaybeTenure = 2, 8099 kTenure = 3, 8100 kZombie = 4, 8101 kLastPretenureDecisionValue = kZombie 8102 }; 8103 8104 const char* PretenureDecisionName(PretenureDecision decision); 8105 8106 DECL_ACCESSORS(transition_info, Object) 8107 // nested_site threads a list of sites that represent nested literals 8108 // walked in a particular order. So [[1, 2], 1, 2] will have one 8109 // nested_site, but [[1, 2], 3, [4]] will have a list of two. 8110 DECL_ACCESSORS(nested_site, Object) 8111 DECL_ACCESSORS(pretenure_data, Smi) 8112 DECL_ACCESSORS(pretenure_create_count, Smi) 8113 DECL_ACCESSORS(dependent_code, DependentCode) 8114 DECL_ACCESSORS(weak_next, Object) 8115 8116 inline void Initialize(); 8117 8118 // This method is expensive, it should only be called for reporting. 8119 bool IsNestedSite(); 8120 8121 // transition_info bitfields, for constructed array transition info. 8122 class ElementsKindBits: public BitField<ElementsKind, 0, 15> {}; 8123 class UnusedBits: public BitField<int, 15, 14> {}; 8124 class DoNotInlineBit: public BitField<bool, 29, 1> {}; 8125 8126 // Bitfields for pretenure_data 8127 class MementoFoundCountBits: public BitField<int, 0, 26> {}; 8128 class PretenureDecisionBits: public BitField<PretenureDecision, 26, 3> {}; 8129 class DeoptDependentCodeBit: public BitField<bool, 29, 1> {}; 8130 STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue); 8131 8132 // Increments the mementos found counter and returns true when the first 8133 // memento was found for a given allocation site. 8134 inline bool IncrementMementoFoundCount(); 8135 8136 inline void IncrementMementoCreateCount(); 8137 8138 PretenureFlag GetPretenureMode(); 8139 8140 void ResetPretenureDecision(); 8141 8142 PretenureDecision pretenure_decision() { 8143 int value = pretenure_data()->value(); 8144 return PretenureDecisionBits::decode(value); 8145 } 8146 8147 void set_pretenure_decision(PretenureDecision decision) { 8148 int value = pretenure_data()->value(); 8149 set_pretenure_data( 8150 Smi::FromInt(PretenureDecisionBits::update(value, decision)), 8151 SKIP_WRITE_BARRIER); 8152 } 8153 8154 bool deopt_dependent_code() { 8155 int value = pretenure_data()->value(); 8156 return DeoptDependentCodeBit::decode(value); 8157 } 8158 8159 void set_deopt_dependent_code(bool deopt) { 8160 int value = pretenure_data()->value(); 8161 set_pretenure_data( 8162 Smi::FromInt(DeoptDependentCodeBit::update(value, deopt)), 8163 SKIP_WRITE_BARRIER); 8164 } 8165 8166 int memento_found_count() { 8167 int value = pretenure_data()->value(); 8168 return MementoFoundCountBits::decode(value); 8169 } 8170 8171 inline void set_memento_found_count(int count); 8172 8173 int memento_create_count() { 8174 return pretenure_create_count()->value(); 8175 } 8176 8177 void set_memento_create_count(int count) { 8178 set_pretenure_create_count(Smi::FromInt(count), SKIP_WRITE_BARRIER); 8179 } 8180 8181 // The pretenuring decision is made during gc, and the zombie state allows 8182 // us to recognize when an allocation site is just being kept alive because 8183 // a later traversal of new space may discover AllocationMementos that point 8184 // to this AllocationSite. 8185 bool IsZombie() { 8186 return pretenure_decision() == kZombie; 8187 } 8188 8189 bool IsMaybeTenure() { 8190 return pretenure_decision() == kMaybeTenure; 8191 } 8192 8193 inline void MarkZombie(); 8194 8195 inline bool MakePretenureDecision(PretenureDecision current_decision, 8196 double ratio, 8197 bool maximum_size_scavenge); 8198 8199 inline bool DigestPretenuringFeedback(bool maximum_size_scavenge); 8200 8201 ElementsKind GetElementsKind() { 8202 DCHECK(!SitePointsToLiteral()); 8203 int value = Smi::cast(transition_info())->value(); 8204 return ElementsKindBits::decode(value); 8205 } 8206 8207 void SetElementsKind(ElementsKind kind) { 8208 int value = Smi::cast(transition_info())->value(); 8209 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)), 8210 SKIP_WRITE_BARRIER); 8211 } 8212 8213 bool CanInlineCall() { 8214 int value = Smi::cast(transition_info())->value(); 8215 return DoNotInlineBit::decode(value) == 0; 8216 } 8217 8218 void SetDoNotInlineCall() { 8219 int value = Smi::cast(transition_info())->value(); 8220 set_transition_info(Smi::FromInt(DoNotInlineBit::update(value, true)), 8221 SKIP_WRITE_BARRIER); 8222 } 8223 8224 bool SitePointsToLiteral() { 8225 // If transition_info is a smi, then it represents an ElementsKind 8226 // for a constructed array. Otherwise, it must be a boilerplate 8227 // for an object or array literal. 8228 return transition_info()->IsJSArray() || transition_info()->IsJSObject(); 8229 } 8230 8231 static void DigestTransitionFeedback(Handle<AllocationSite> site, 8232 ElementsKind to_kind); 8233 8234 enum Reason { 8235 TENURING, 8236 TRANSITIONS 8237 }; 8238 8239 static void AddDependentCompilationInfo(Handle<AllocationSite> site, 8240 Reason reason, 8241 CompilationInfo* info); 8242 8243 DECLARE_PRINTER(AllocationSite) 8244 DECLARE_VERIFIER(AllocationSite) 8245 8246 DECLARE_CAST(AllocationSite) 8247 static inline AllocationSiteMode GetMode( 8248 ElementsKind boilerplate_elements_kind); 8249 static inline AllocationSiteMode GetMode(ElementsKind from, ElementsKind to); 8250 static inline bool CanTrack(InstanceType type); 8251 8252 static const int kTransitionInfoOffset = HeapObject::kHeaderSize; 8253 static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize; 8254 static const int kPretenureDataOffset = kNestedSiteOffset + kPointerSize; 8255 static const int kPretenureCreateCountOffset = 8256 kPretenureDataOffset + kPointerSize; 8257 static const int kDependentCodeOffset = 8258 kPretenureCreateCountOffset + kPointerSize; 8259 static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize; 8260 static const int kSize = kWeakNextOffset + kPointerSize; 8261 8262 // During mark compact we need to take special care for the dependent code 8263 // field. 8264 static const int kPointerFieldsBeginOffset = kTransitionInfoOffset; 8265 static const int kPointerFieldsEndOffset = kDependentCodeOffset; 8266 8267 // For other visitors, use the fixed body descriptor below. 8268 typedef FixedBodyDescriptor<HeapObject::kHeaderSize, 8269 kDependentCodeOffset + kPointerSize, 8270 kSize> BodyDescriptor; 8271 8272 private: 8273 inline DependentCode::DependencyGroup ToDependencyGroup(Reason reason); 8274 bool PretenuringDecisionMade() { 8275 return pretenure_decision() != kUndecided; 8276 } 8277 8278 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite); 8279 }; 8280 8281 8282 class AllocationMemento: public Struct { 8283 public: 8284 static const int kAllocationSiteOffset = HeapObject::kHeaderSize; 8285 static const int kSize = kAllocationSiteOffset + kPointerSize; 8286 8287 DECL_ACCESSORS(allocation_site, Object) 8288 8289 bool IsValid() { 8290 return allocation_site()->IsAllocationSite() && 8291 !AllocationSite::cast(allocation_site())->IsZombie(); 8292 } 8293 AllocationSite* GetAllocationSite() { 8294 DCHECK(IsValid()); 8295 return AllocationSite::cast(allocation_site()); 8296 } 8297 8298 DECLARE_PRINTER(AllocationMemento) 8299 DECLARE_VERIFIER(AllocationMemento) 8300 8301 DECLARE_CAST(AllocationMemento) 8302 8303 private: 8304 DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationMemento); 8305 }; 8306 8307 8308 // Representation of a slow alias as part of a sloppy arguments objects. 8309 // For fast aliases (if HasSloppyArgumentsElements()): 8310 // - the parameter map contains an index into the context 8311 // - all attributes of the element have default values 8312 // For slow aliases (if HasDictionaryArgumentsElements()): 8313 // - the parameter map contains no fast alias mapping (i.e. the hole) 8314 // - this struct (in the slow backing store) contains an index into the context 8315 // - all attributes are available as part if the property details 8316 class AliasedArgumentsEntry: public Struct { 8317 public: 8318 inline int aliased_context_slot() const; 8319 inline void set_aliased_context_slot(int count); 8320 8321 DECLARE_CAST(AliasedArgumentsEntry) 8322 8323 // Dispatched behavior. 8324 DECLARE_PRINTER(AliasedArgumentsEntry) 8325 DECLARE_VERIFIER(AliasedArgumentsEntry) 8326 8327 static const int kAliasedContextSlot = HeapObject::kHeaderSize; 8328 static const int kSize = kAliasedContextSlot + kPointerSize; 8329 8330 private: 8331 DISALLOW_IMPLICIT_CONSTRUCTORS(AliasedArgumentsEntry); 8332 }; 8333 8334 8335 enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS}; 8336 enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL}; 8337 8338 8339 class StringHasher { 8340 public: 8341 explicit inline StringHasher(int length, uint32_t seed); 8342 8343 template <typename schar> 8344 static inline uint32_t HashSequentialString(const schar* chars, 8345 int length, 8346 uint32_t seed); 8347 8348 // Reads all the data, even for long strings and computes the utf16 length. 8349 static uint32_t ComputeUtf8Hash(Vector<const char> chars, 8350 uint32_t seed, 8351 int* utf16_length_out); 8352 8353 // Calculated hash value for a string consisting of 1 to 8354 // String::kMaxArrayIndexSize digits with no leading zeros (except "0"). 8355 // value is represented decimal value. 8356 static uint32_t MakeArrayIndexHash(uint32_t value, int length); 8357 8358 // No string is allowed to have a hash of zero. That value is reserved 8359 // for internal properties. If the hash calculation yields zero then we 8360 // use 27 instead. 8361 static const int kZeroHash = 27; 8362 8363 // Reusable parts of the hashing algorithm. 8364 INLINE(static uint32_t AddCharacterCore(uint32_t running_hash, uint16_t c)); 8365 INLINE(static uint32_t GetHashCore(uint32_t running_hash)); 8366 8367 protected: 8368 // Returns the value to store in the hash field of a string with 8369 // the given length and contents. 8370 uint32_t GetHashField(); 8371 // Returns true if the hash of this string can be computed without 8372 // looking at the contents. 8373 inline bool has_trivial_hash(); 8374 // Adds a block of characters to the hash. 8375 template<typename Char> 8376 inline void AddCharacters(const Char* chars, int len); 8377 8378 private: 8379 // Add a character to the hash. 8380 inline void AddCharacter(uint16_t c); 8381 // Update index. Returns true if string is still an index. 8382 inline bool UpdateIndex(uint16_t c); 8383 8384 int length_; 8385 uint32_t raw_running_hash_; 8386 uint32_t array_index_; 8387 bool is_array_index_; 8388 bool is_first_char_; 8389 DISALLOW_COPY_AND_ASSIGN(StringHasher); 8390 }; 8391 8392 8393 class IteratingStringHasher : public StringHasher { 8394 public: 8395 static inline uint32_t Hash(String* string, uint32_t seed); 8396 inline void VisitOneByteString(const uint8_t* chars, int length); 8397 inline void VisitTwoByteString(const uint16_t* chars, int length); 8398 8399 private: 8400 inline IteratingStringHasher(int len, uint32_t seed) 8401 : StringHasher(len, seed) {} 8402 DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher); 8403 }; 8404 8405 8406 // The characteristics of a string are stored in its map. Retrieving these 8407 // few bits of information is moderately expensive, involving two memory 8408 // loads where the second is dependent on the first. To improve efficiency 8409 // the shape of the string is given its own class so that it can be retrieved 8410 // once and used for several string operations. A StringShape is small enough 8411 // to be passed by value and is immutable, but be aware that flattening a 8412 // string can potentially alter its shape. Also be aware that a GC caused by 8413 // something else can alter the shape of a string due to ConsString 8414 // shortcutting. Keeping these restrictions in mind has proven to be error- 8415 // prone and so we no longer put StringShapes in variables unless there is a 8416 // concrete performance benefit at that particular point in the code. 8417 class StringShape BASE_EMBEDDED { 8418 public: 8419 inline explicit StringShape(const String* s); 8420 inline explicit StringShape(Map* s); 8421 inline explicit StringShape(InstanceType t); 8422 inline bool IsSequential(); 8423 inline bool IsExternal(); 8424 inline bool IsCons(); 8425 inline bool IsSliced(); 8426 inline bool IsIndirect(); 8427 inline bool IsExternalOneByte(); 8428 inline bool IsExternalTwoByte(); 8429 inline bool IsSequentialOneByte(); 8430 inline bool IsSequentialTwoByte(); 8431 inline bool IsInternalized(); 8432 inline StringRepresentationTag representation_tag(); 8433 inline uint32_t encoding_tag(); 8434 inline uint32_t full_representation_tag(); 8435 inline uint32_t size_tag(); 8436 #ifdef DEBUG 8437 inline uint32_t type() { return type_; } 8438 inline void invalidate() { valid_ = false; } 8439 inline bool valid() { return valid_; } 8440 #else 8441 inline void invalidate() { } 8442 #endif 8443 8444 private: 8445 uint32_t type_; 8446 #ifdef DEBUG 8447 inline void set_valid() { valid_ = true; } 8448 bool valid_; 8449 #else 8450 inline void set_valid() { } 8451 #endif 8452 }; 8453 8454 8455 // The Name abstract class captures anything that can be used as a property 8456 // name, i.e., strings and symbols. All names store a hash value. 8457 class Name: public HeapObject { 8458 public: 8459 // Get and set the hash field of the name. 8460 inline uint32_t hash_field(); 8461 inline void set_hash_field(uint32_t value); 8462 8463 // Tells whether the hash code has been computed. 8464 inline bool HasHashCode(); 8465 8466 // Returns a hash value used for the property table 8467 inline uint32_t Hash(); 8468 8469 // Equality operations. 8470 inline bool Equals(Name* other); 8471 inline static bool Equals(Handle<Name> one, Handle<Name> two); 8472 8473 // Conversion. 8474 inline bool AsArrayIndex(uint32_t* index); 8475 8476 // Whether name can only name own properties. 8477 inline bool IsOwn(); 8478 8479 DECLARE_CAST(Name) 8480 8481 DECLARE_PRINTER(Name) 8482 8483 // Layout description. 8484 static const int kHashFieldOffset = HeapObject::kHeaderSize; 8485 static const int kSize = kHashFieldOffset + kPointerSize; 8486 8487 // Mask constant for checking if a name has a computed hash code 8488 // and if it is a string that is an array index. The least significant bit 8489 // indicates whether a hash code has been computed. If the hash code has 8490 // been computed the 2nd bit tells whether the string can be used as an 8491 // array index. 8492 static const int kHashNotComputedMask = 1; 8493 static const int kIsNotArrayIndexMask = 1 << 1; 8494 static const int kNofHashBitFields = 2; 8495 8496 // Shift constant retrieving hash code from hash field. 8497 static const int kHashShift = kNofHashBitFields; 8498 8499 // Only these bits are relevant in the hash, since the top two are shifted 8500 // out. 8501 static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift; 8502 8503 // Array index strings this short can keep their index in the hash field. 8504 static const int kMaxCachedArrayIndexLength = 7; 8505 8506 // For strings which are array indexes the hash value has the string length 8507 // mixed into the hash, mainly to avoid a hash value of zero which would be 8508 // the case for the string '0'. 24 bits are used for the array index value. 8509 static const int kArrayIndexValueBits = 24; 8510 static const int kArrayIndexLengthBits = 8511 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields; 8512 8513 STATIC_ASSERT((kArrayIndexLengthBits > 0)); 8514 8515 class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields, 8516 kArrayIndexValueBits> {}; // NOLINT 8517 class ArrayIndexLengthBits : public BitField<unsigned int, 8518 kNofHashBitFields + kArrayIndexValueBits, 8519 kArrayIndexLengthBits> {}; // NOLINT 8520 8521 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we 8522 // could use a mask to test if the length of string is less than or equal to 8523 // kMaxCachedArrayIndexLength. 8524 STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1)); 8525 8526 static const unsigned int kContainsCachedArrayIndexMask = 8527 (~static_cast<unsigned>(kMaxCachedArrayIndexLength) 8528 << ArrayIndexLengthBits::kShift) | 8529 kIsNotArrayIndexMask; 8530 8531 // Value of empty hash field indicating that the hash is not computed. 8532 static const int kEmptyHashField = 8533 kIsNotArrayIndexMask | kHashNotComputedMask; 8534 8535 protected: 8536 static inline bool IsHashFieldComputed(uint32_t field); 8537 8538 private: 8539 DISALLOW_IMPLICIT_CONSTRUCTORS(Name); 8540 }; 8541 8542 8543 // ES6 symbols. 8544 class Symbol: public Name { 8545 public: 8546 // [name]: the print name of a symbol, or undefined if none. 8547 DECL_ACCESSORS(name, Object) 8548 8549 DECL_ACCESSORS(flags, Smi) 8550 8551 // [is_private]: whether this is a private symbol. 8552 DECL_BOOLEAN_ACCESSORS(is_private) 8553 8554 // [is_own]: whether this is an own symbol, that is, only used to designate 8555 // own properties of objects. 8556 DECL_BOOLEAN_ACCESSORS(is_own) 8557 8558 DECLARE_CAST(Symbol) 8559 8560 // Dispatched behavior. 8561 DECLARE_PRINTER(Symbol) 8562 DECLARE_VERIFIER(Symbol) 8563 8564 // Layout description. 8565 static const int kNameOffset = Name::kSize; 8566 static const int kFlagsOffset = kNameOffset + kPointerSize; 8567 static const int kSize = kFlagsOffset + kPointerSize; 8568 8569 typedef FixedBodyDescriptor<kNameOffset, kFlagsOffset, kSize> BodyDescriptor; 8570 8571 private: 8572 static const int kPrivateBit = 0; 8573 static const int kOwnBit = 1; 8574 8575 DISALLOW_IMPLICIT_CONSTRUCTORS(Symbol); 8576 }; 8577 8578 8579 class ConsString; 8580 8581 // The String abstract class captures JavaScript string values: 8582 // 8583 // Ecma-262: 8584 // 4.3.16 String Value 8585 // A string value is a member of the type String and is a finite 8586 // ordered sequence of zero or more 16-bit unsigned integer values. 8587 // 8588 // All string values have a length field. 8589 class String: public Name { 8590 public: 8591 enum Encoding { ONE_BYTE_ENCODING, TWO_BYTE_ENCODING }; 8592 8593 // Array index strings this short can keep their index in the hash field. 8594 static const int kMaxCachedArrayIndexLength = 7; 8595 8596 // For strings which are array indexes the hash value has the string length 8597 // mixed into the hash, mainly to avoid a hash value of zero which would be 8598 // the case for the string '0'. 24 bits are used for the array index value. 8599 static const int kArrayIndexValueBits = 24; 8600 static const int kArrayIndexLengthBits = 8601 kBitsPerInt - kArrayIndexValueBits - kNofHashBitFields; 8602 8603 STATIC_ASSERT((kArrayIndexLengthBits > 0)); 8604 8605 class ArrayIndexValueBits : public BitField<unsigned int, kNofHashBitFields, 8606 kArrayIndexValueBits> {}; // NOLINT 8607 class ArrayIndexLengthBits : public BitField<unsigned int, 8608 kNofHashBitFields + kArrayIndexValueBits, 8609 kArrayIndexLengthBits> {}; // NOLINT 8610 8611 // Check that kMaxCachedArrayIndexLength + 1 is a power of two so we 8612 // could use a mask to test if the length of string is less than or equal to 8613 // kMaxCachedArrayIndexLength. 8614 STATIC_ASSERT(IS_POWER_OF_TWO(kMaxCachedArrayIndexLength + 1)); 8615 8616 static const unsigned int kContainsCachedArrayIndexMask = 8617 (~static_cast<unsigned>(kMaxCachedArrayIndexLength) 8618 << ArrayIndexLengthBits::kShift) | 8619 kIsNotArrayIndexMask; 8620 8621 // Representation of the flat content of a String. 8622 // A non-flat string doesn't have flat content. 8623 // A flat string has content that's encoded as a sequence of either 8624 // one-byte chars or two-byte UC16. 8625 // Returned by String::GetFlatContent(). 8626 class FlatContent { 8627 public: 8628 // Returns true if the string is flat and this structure contains content. 8629 bool IsFlat() { return state_ != NON_FLAT; } 8630 // Returns true if the structure contains one-byte content. 8631 bool IsOneByte() { return state_ == ONE_BYTE; } 8632 // Returns true if the structure contains two-byte content. 8633 bool IsTwoByte() { return state_ == TWO_BYTE; } 8634 8635 // Return the one byte content of the string. Only use if IsOneByte() 8636 // returns true. 8637 Vector<const uint8_t> ToOneByteVector() { 8638 DCHECK_EQ(ONE_BYTE, state_); 8639 return Vector<const uint8_t>(onebyte_start, length_); 8640 } 8641 // Return the two-byte content of the string. Only use if IsTwoByte() 8642 // returns true. 8643 Vector<const uc16> ToUC16Vector() { 8644 DCHECK_EQ(TWO_BYTE, state_); 8645 return Vector<const uc16>(twobyte_start, length_); 8646 } 8647 8648 uc16 Get(int i) { 8649 DCHECK(i < length_); 8650 DCHECK(state_ != NON_FLAT); 8651 if (state_ == ONE_BYTE) return onebyte_start[i]; 8652 return twobyte_start[i]; 8653 } 8654 8655 private: 8656 enum State { NON_FLAT, ONE_BYTE, TWO_BYTE }; 8657 8658 // Constructors only used by String::GetFlatContent(). 8659 explicit FlatContent(const uint8_t* start, int length) 8660 : onebyte_start(start), length_(length), state_(ONE_BYTE) {} 8661 explicit FlatContent(const uc16* start, int length) 8662 : twobyte_start(start), length_(length), state_(TWO_BYTE) { } 8663 FlatContent() : onebyte_start(NULL), length_(0), state_(NON_FLAT) { } 8664 8665 union { 8666 const uint8_t* onebyte_start; 8667 const uc16* twobyte_start; 8668 }; 8669 int length_; 8670 State state_; 8671 8672 friend class String; 8673 }; 8674 8675 // Get and set the length of the string. 8676 inline int length() const; 8677 inline void set_length(int value); 8678 8679 // Get and set the length of the string using acquire loads and release 8680 // stores. 8681 inline int synchronized_length() const; 8682 inline void synchronized_set_length(int value); 8683 8684 // Returns whether this string has only one-byte chars, i.e. all of them can 8685 // be one-byte encoded. This might be the case even if the string is 8686 // two-byte. Such strings may appear when the embedder prefers 8687 // two-byte external representations even for one-byte data. 8688 inline bool IsOneByteRepresentation() const; 8689 inline bool IsTwoByteRepresentation() const; 8690 8691 // Cons and slices have an encoding flag that may not represent the actual 8692 // encoding of the underlying string. This is taken into account here. 8693 // Requires: this->IsFlat() 8694 inline bool IsOneByteRepresentationUnderneath(); 8695 inline bool IsTwoByteRepresentationUnderneath(); 8696 8697 // NOTE: this should be considered only a hint. False negatives are 8698 // possible. 8699 inline bool HasOnlyOneByteChars(); 8700 8701 // Get and set individual two byte chars in the string. 8702 inline void Set(int index, uint16_t value); 8703 // Get individual two byte char in the string. Repeated calls 8704 // to this method are not efficient unless the string is flat. 8705 INLINE(uint16_t Get(int index)); 8706 8707 // Flattens the string. Checks first inline to see if it is 8708 // necessary. Does nothing if the string is not a cons string. 8709 // Flattening allocates a sequential string with the same data as 8710 // the given string and mutates the cons string to a degenerate 8711 // form, where the first component is the new sequential string and 8712 // the second component is the empty string. If allocation fails, 8713 // this function returns a failure. If flattening succeeds, this 8714 // function returns the sequential string that is now the first 8715 // component of the cons string. 8716 // 8717 // Degenerate cons strings are handled specially by the garbage 8718 // collector (see IsShortcutCandidate). 8719 8720 static inline Handle<String> Flatten(Handle<String> string, 8721 PretenureFlag pretenure = NOT_TENURED); 8722 8723 // Tries to return the content of a flat string as a structure holding either 8724 // a flat vector of char or of uc16. 8725 // If the string isn't flat, and therefore doesn't have flat content, the 8726 // returned structure will report so, and can't provide a vector of either 8727 // kind. 8728 FlatContent GetFlatContent(); 8729 8730 // Returns the parent of a sliced string or first part of a flat cons string. 8731 // Requires: StringShape(this).IsIndirect() && this->IsFlat() 8732 inline String* GetUnderlying(); 8733 8734 // Mark the string as an undetectable object. It only applies to 8735 // one-byte and two-byte string types. 8736 bool MarkAsUndetectable(); 8737 8738 // String equality operations. 8739 inline bool Equals(String* other); 8740 inline static bool Equals(Handle<String> one, Handle<String> two); 8741 bool IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false); 8742 bool IsOneByteEqualTo(Vector<const uint8_t> str); 8743 bool IsTwoByteEqualTo(Vector<const uc16> str); 8744 8745 // Return a UTF8 representation of the string. The string is null 8746 // terminated but may optionally contain nulls. Length is returned 8747 // in length_output if length_output is not a null pointer The string 8748 // should be nearly flat, otherwise the performance of this method may 8749 // be very slow (quadratic in the length). Setting robustness_flag to 8750 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it 8751 // handles unexpected data without causing assert failures and it does not 8752 // do any heap allocations. This is useful when printing stack traces. 8753 SmartArrayPointer<char> ToCString(AllowNullsFlag allow_nulls, 8754 RobustnessFlag robustness_flag, 8755 int offset, 8756 int length, 8757 int* length_output = 0); 8758 SmartArrayPointer<char> ToCString( 8759 AllowNullsFlag allow_nulls = DISALLOW_NULLS, 8760 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL, 8761 int* length_output = 0); 8762 8763 // Return a 16 bit Unicode representation of the string. 8764 // The string should be nearly flat, otherwise the performance of 8765 // of this method may be very bad. Setting robustness_flag to 8766 // ROBUST_STRING_TRAVERSAL invokes behaviour that is robust This means it 8767 // handles unexpected data without causing assert failures and it does not 8768 // do any heap allocations. This is useful when printing stack traces. 8769 SmartArrayPointer<uc16> ToWideCString( 8770 RobustnessFlag robustness_flag = FAST_STRING_TRAVERSAL); 8771 8772 bool ComputeArrayIndex(uint32_t* index); 8773 8774 // Externalization. 8775 bool MakeExternal(v8::String::ExternalStringResource* resource); 8776 bool MakeExternal(v8::String::ExternalOneByteStringResource* resource); 8777 8778 // Conversion. 8779 inline bool AsArrayIndex(uint32_t* index); 8780 8781 DECLARE_CAST(String) 8782 8783 void PrintOn(FILE* out); 8784 8785 // For use during stack traces. Performs rudimentary sanity check. 8786 bool LooksValid(); 8787 8788 // Dispatched behavior. 8789 void StringShortPrint(StringStream* accumulator); 8790 void PrintUC16(OStream& os, int start = 0, int end = -1); // NOLINT 8791 #ifdef OBJECT_PRINT 8792 char* ToAsciiArray(); 8793 #endif 8794 DECLARE_PRINTER(String) 8795 DECLARE_VERIFIER(String) 8796 8797 inline bool IsFlat(); 8798 8799 // Layout description. 8800 static const int kLengthOffset = Name::kSize; 8801 static const int kSize = kLengthOffset + kPointerSize; 8802 8803 // Maximum number of characters to consider when trying to convert a string 8804 // value into an array index. 8805 static const int kMaxArrayIndexSize = 10; 8806 STATIC_ASSERT(kMaxArrayIndexSize < (1 << kArrayIndexLengthBits)); 8807 8808 // Max char codes. 8809 static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar; 8810 static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar; 8811 static const int kMaxUtf16CodeUnit = 0xffff; 8812 static const uint32_t kMaxUtf16CodeUnitU = kMaxUtf16CodeUnit; 8813 8814 // Value of hash field containing computed hash equal to zero. 8815 static const int kEmptyStringHash = kIsNotArrayIndexMask; 8816 8817 // Maximal string length. 8818 static const int kMaxLength = (1 << 28) - 16; 8819 8820 // Max length for computing hash. For strings longer than this limit the 8821 // string length is used as the hash value. 8822 static const int kMaxHashCalcLength = 16383; 8823 8824 // Limit for truncation in short printing. 8825 static const int kMaxShortPrintLength = 1024; 8826 8827 // Support for regular expressions. 8828 const uc16* GetTwoByteData(unsigned start); 8829 8830 // Helper function for flattening strings. 8831 template <typename sinkchar> 8832 static void WriteToFlat(String* source, 8833 sinkchar* sink, 8834 int from, 8835 int to); 8836 8837 // The return value may point to the first aligned word containing the first 8838 // non-one-byte character, rather than directly to the non-one-byte character. 8839 // If the return value is >= the passed length, the entire string was 8840 // one-byte. 8841 static inline int NonAsciiStart(const char* chars, int length) { 8842 const char* start = chars; 8843 const char* limit = chars + length; 8844 8845 if (length >= kIntptrSize) { 8846 // Check unaligned bytes. 8847 while (!IsAligned(reinterpret_cast<intptr_t>(chars), sizeof(uintptr_t))) { 8848 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) { 8849 return static_cast<int>(chars - start); 8850 } 8851 ++chars; 8852 } 8853 // Check aligned words. 8854 DCHECK(unibrow::Utf8::kMaxOneByteChar == 0x7F); 8855 const uintptr_t non_one_byte_mask = kUintptrAllBitsSet / 0xFF * 0x80; 8856 while (chars + sizeof(uintptr_t) <= limit) { 8857 if (*reinterpret_cast<const uintptr_t*>(chars) & non_one_byte_mask) { 8858 return static_cast<int>(chars - start); 8859 } 8860 chars += sizeof(uintptr_t); 8861 } 8862 } 8863 // Check remaining unaligned bytes. 8864 while (chars < limit) { 8865 if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) { 8866 return static_cast<int>(chars - start); 8867 } 8868 ++chars; 8869 } 8870 8871 return static_cast<int>(chars - start); 8872 } 8873 8874 static inline bool IsAscii(const char* chars, int length) { 8875 return NonAsciiStart(chars, length) >= length; 8876 } 8877 8878 static inline bool IsAscii(const uint8_t* chars, int length) { 8879 return 8880 NonAsciiStart(reinterpret_cast<const char*>(chars), length) >= length; 8881 } 8882 8883 static inline int NonOneByteStart(const uc16* chars, int length) { 8884 const uc16* limit = chars + length; 8885 const uc16* start = chars; 8886 while (chars < limit) { 8887 if (*chars > kMaxOneByteCharCodeU) return static_cast<int>(chars - start); 8888 ++chars; 8889 } 8890 return static_cast<int>(chars - start); 8891 } 8892 8893 static inline bool IsOneByte(const uc16* chars, int length) { 8894 return NonOneByteStart(chars, length) >= length; 8895 } 8896 8897 template<class Visitor> 8898 static inline ConsString* VisitFlat(Visitor* visitor, 8899 String* string, 8900 int offset = 0); 8901 8902 static Handle<FixedArray> CalculateLineEnds(Handle<String> string, 8903 bool include_ending_line); 8904 8905 // Use the hash field to forward to the canonical internalized string 8906 // when deserializing an internalized string. 8907 inline void SetForwardedInternalizedString(String* string); 8908 inline String* GetForwardedInternalizedString(); 8909 8910 private: 8911 friend class Name; 8912 friend class StringTableInsertionKey; 8913 8914 static Handle<String> SlowFlatten(Handle<ConsString> cons, 8915 PretenureFlag tenure); 8916 8917 // Slow case of String::Equals. This implementation works on any strings 8918 // but it is most efficient on strings that are almost flat. 8919 bool SlowEquals(String* other); 8920 8921 static bool SlowEquals(Handle<String> one, Handle<String> two); 8922 8923 // Slow case of AsArrayIndex. 8924 bool SlowAsArrayIndex(uint32_t* index); 8925 8926 // Compute and set the hash code. 8927 uint32_t ComputeAndSetHash(); 8928 8929 DISALLOW_IMPLICIT_CONSTRUCTORS(String); 8930 }; 8931 8932 8933 // The SeqString abstract class captures sequential string values. 8934 class SeqString: public String { 8935 public: 8936 DECLARE_CAST(SeqString) 8937 8938 // Layout description. 8939 static const int kHeaderSize = String::kSize; 8940 8941 // Truncate the string in-place if possible and return the result. 8942 // In case of new_length == 0, the empty string is returned without 8943 // truncating the original string. 8944 MUST_USE_RESULT static Handle<String> Truncate(Handle<SeqString> string, 8945 int new_length); 8946 private: 8947 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); 8948 }; 8949 8950 8951 // The OneByteString class captures sequential one-byte string objects. 8952 // Each character in the OneByteString is an one-byte character. 8953 class SeqOneByteString: public SeqString { 8954 public: 8955 static const bool kHasOneByteEncoding = true; 8956 8957 // Dispatched behavior. 8958 inline uint16_t SeqOneByteStringGet(int index); 8959 inline void SeqOneByteStringSet(int index, uint16_t value); 8960 8961 // Get the address of the characters in this string. 8962 inline Address GetCharsAddress(); 8963 8964 inline uint8_t* GetChars(); 8965 8966 DECLARE_CAST(SeqOneByteString) 8967 8968 // Garbage collection support. This method is called by the 8969 // garbage collector to compute the actual size of an OneByteString 8970 // instance. 8971 inline int SeqOneByteStringSize(InstanceType instance_type); 8972 8973 // Computes the size for an OneByteString instance of a given length. 8974 static int SizeFor(int length) { 8975 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize); 8976 } 8977 8978 // Maximal memory usage for a single sequential one-byte string. 8979 static const int kMaxSize = 512 * MB - 1; 8980 STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength); 8981 8982 private: 8983 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqOneByteString); 8984 }; 8985 8986 8987 // The TwoByteString class captures sequential unicode string objects. 8988 // Each character in the TwoByteString is a two-byte uint16_t. 8989 class SeqTwoByteString: public SeqString { 8990 public: 8991 static const bool kHasOneByteEncoding = false; 8992 8993 // Dispatched behavior. 8994 inline uint16_t SeqTwoByteStringGet(int index); 8995 inline void SeqTwoByteStringSet(int index, uint16_t value); 8996 8997 // Get the address of the characters in this string. 8998 inline Address GetCharsAddress(); 8999 9000 inline uc16* GetChars(); 9001 9002 // For regexp code. 9003 const uint16_t* SeqTwoByteStringGetData(unsigned start); 9004 9005 DECLARE_CAST(SeqTwoByteString) 9006 9007 // Garbage collection support. This method is called by the 9008 // garbage collector to compute the actual size of a TwoByteString 9009 // instance. 9010 inline int SeqTwoByteStringSize(InstanceType instance_type); 9011 9012 // Computes the size for a TwoByteString instance of a given length. 9013 static int SizeFor(int length) { 9014 return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize); 9015 } 9016 9017 // Maximal memory usage for a single sequential two-byte string. 9018 static const int kMaxSize = 512 * MB - 1; 9019 STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize)/sizeof(uint16_t)) >= 9020 String::kMaxLength); 9021 9022 private: 9023 DISALLOW_IMPLICIT_CONSTRUCTORS(SeqTwoByteString); 9024 }; 9025 9026 9027 // The ConsString class describes string values built by using the 9028 // addition operator on strings. A ConsString is a pair where the 9029 // first and second components are pointers to other string values. 9030 // One or both components of a ConsString can be pointers to other 9031 // ConsStrings, creating a binary tree of ConsStrings where the leaves 9032 // are non-ConsString string values. The string value represented by 9033 // a ConsString can be obtained by concatenating the leaf string 9034 // values in a left-to-right depth-first traversal of the tree. 9035 class ConsString: public String { 9036 public: 9037 // First string of the cons cell. 9038 inline String* first(); 9039 // Doesn't check that the result is a string, even in debug mode. This is 9040 // useful during GC where the mark bits confuse the checks. 9041 inline Object* unchecked_first(); 9042 inline void set_first(String* first, 9043 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 9044 9045 // Second string of the cons cell. 9046 inline String* second(); 9047 // Doesn't check that the result is a string, even in debug mode. This is 9048 // useful during GC where the mark bits confuse the checks. 9049 inline Object* unchecked_second(); 9050 inline void set_second(String* second, 9051 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 9052 9053 // Dispatched behavior. 9054 uint16_t ConsStringGet(int index); 9055 9056 DECLARE_CAST(ConsString) 9057 9058 // Layout description. 9059 static const int kFirstOffset = POINTER_SIZE_ALIGN(String::kSize); 9060 static const int kSecondOffset = kFirstOffset + kPointerSize; 9061 static const int kSize = kSecondOffset + kPointerSize; 9062 9063 // Minimum length for a cons string. 9064 static const int kMinLength = 13; 9065 9066 typedef FixedBodyDescriptor<kFirstOffset, kSecondOffset + kPointerSize, kSize> 9067 BodyDescriptor; 9068 9069 DECLARE_VERIFIER(ConsString) 9070 9071 private: 9072 DISALLOW_IMPLICIT_CONSTRUCTORS(ConsString); 9073 }; 9074 9075 9076 // The Sliced String class describes strings that are substrings of another 9077 // sequential string. The motivation is to save time and memory when creating 9078 // a substring. A Sliced String is described as a pointer to the parent, 9079 // the offset from the start of the parent string and the length. Using 9080 // a Sliced String therefore requires unpacking of the parent string and 9081 // adding the offset to the start address. A substring of a Sliced String 9082 // are not nested since the double indirection is simplified when creating 9083 // such a substring. 9084 // Currently missing features are: 9085 // - handling externalized parent strings 9086 // - external strings as parent 9087 // - truncating sliced string to enable otherwise unneeded parent to be GC'ed. 9088 class SlicedString: public String { 9089 public: 9090 inline String* parent(); 9091 inline void set_parent(String* parent, 9092 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 9093 inline int offset() const; 9094 inline void set_offset(int offset); 9095 9096 // Dispatched behavior. 9097 uint16_t SlicedStringGet(int index); 9098 9099 DECLARE_CAST(SlicedString) 9100 9101 // Layout description. 9102 static const int kParentOffset = POINTER_SIZE_ALIGN(String::kSize); 9103 static const int kOffsetOffset = kParentOffset + kPointerSize; 9104 static const int kSize = kOffsetOffset + kPointerSize; 9105 9106 // Minimum length for a sliced string. 9107 static const int kMinLength = 13; 9108 9109 typedef FixedBodyDescriptor<kParentOffset, 9110 kOffsetOffset + kPointerSize, kSize> 9111 BodyDescriptor; 9112 9113 DECLARE_VERIFIER(SlicedString) 9114 9115 private: 9116 DISALLOW_IMPLICIT_CONSTRUCTORS(SlicedString); 9117 }; 9118 9119 9120 // The ExternalString class describes string values that are backed by 9121 // a string resource that lies outside the V8 heap. ExternalStrings 9122 // consist of the length field common to all strings, a pointer to the 9123 // external resource. It is important to ensure (externally) that the 9124 // resource is not deallocated while the ExternalString is live in the 9125 // V8 heap. 9126 // 9127 // The API expects that all ExternalStrings are created through the 9128 // API. Therefore, ExternalStrings should not be used internally. 9129 class ExternalString: public String { 9130 public: 9131 DECLARE_CAST(ExternalString) 9132 9133 // Layout description. 9134 static const int kResourceOffset = POINTER_SIZE_ALIGN(String::kSize); 9135 static const int kShortSize = kResourceOffset + kPointerSize; 9136 static const int kResourceDataOffset = kResourceOffset + kPointerSize; 9137 static const int kSize = kResourceDataOffset + kPointerSize; 9138 9139 static const int kMaxShortLength = 9140 (kShortSize - SeqString::kHeaderSize) / kCharSize; 9141 9142 // Return whether external string is short (data pointer is not cached). 9143 inline bool is_short(); 9144 9145 STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset); 9146 9147 private: 9148 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalString); 9149 }; 9150 9151 9152 // The ExternalOneByteString class is an external string backed by an 9153 // one-byte string. 9154 class ExternalOneByteString : public ExternalString { 9155 public: 9156 static const bool kHasOneByteEncoding = true; 9157 9158 typedef v8::String::ExternalOneByteStringResource Resource; 9159 9160 // The underlying resource. 9161 inline const Resource* resource(); 9162 inline void set_resource(const Resource* buffer); 9163 9164 // Update the pointer cache to the external character array. 9165 // The cached pointer is always valid, as the external character array does = 9166 // not move during lifetime. Deserialization is the only exception, after 9167 // which the pointer cache has to be refreshed. 9168 inline void update_data_cache(); 9169 9170 inline const uint8_t* GetChars(); 9171 9172 // Dispatched behavior. 9173 inline uint16_t ExternalOneByteStringGet(int index); 9174 9175 DECLARE_CAST(ExternalOneByteString) 9176 9177 // Garbage collection support. 9178 inline void ExternalOneByteStringIterateBody(ObjectVisitor* v); 9179 9180 template <typename StaticVisitor> 9181 inline void ExternalOneByteStringIterateBody(); 9182 9183 private: 9184 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalOneByteString); 9185 }; 9186 9187 9188 // The ExternalTwoByteString class is an external string backed by a UTF-16 9189 // encoded string. 9190 class ExternalTwoByteString: public ExternalString { 9191 public: 9192 static const bool kHasOneByteEncoding = false; 9193 9194 typedef v8::String::ExternalStringResource Resource; 9195 9196 // The underlying string resource. 9197 inline const Resource* resource(); 9198 inline void set_resource(const Resource* buffer); 9199 9200 // Update the pointer cache to the external character array. 9201 // The cached pointer is always valid, as the external character array does = 9202 // not move during lifetime. Deserialization is the only exception, after 9203 // which the pointer cache has to be refreshed. 9204 inline void update_data_cache(); 9205 9206 inline const uint16_t* GetChars(); 9207 9208 // Dispatched behavior. 9209 inline uint16_t ExternalTwoByteStringGet(int index); 9210 9211 // For regexp code. 9212 inline const uint16_t* ExternalTwoByteStringGetData(unsigned start); 9213 9214 DECLARE_CAST(ExternalTwoByteString) 9215 9216 // Garbage collection support. 9217 inline void ExternalTwoByteStringIterateBody(ObjectVisitor* v); 9218 9219 template<typename StaticVisitor> 9220 inline void ExternalTwoByteStringIterateBody(); 9221 9222 private: 9223 DISALLOW_IMPLICIT_CONSTRUCTORS(ExternalTwoByteString); 9224 }; 9225 9226 9227 // Utility superclass for stack-allocated objects that must be updated 9228 // on gc. It provides two ways for the gc to update instances, either 9229 // iterating or updating after gc. 9230 class Relocatable BASE_EMBEDDED { 9231 public: 9232 explicit inline Relocatable(Isolate* isolate); 9233 inline virtual ~Relocatable(); 9234 virtual void IterateInstance(ObjectVisitor* v) { } 9235 virtual void PostGarbageCollection() { } 9236 9237 static void PostGarbageCollectionProcessing(Isolate* isolate); 9238 static int ArchiveSpacePerThread(); 9239 static char* ArchiveState(Isolate* isolate, char* to); 9240 static char* RestoreState(Isolate* isolate, char* from); 9241 static void Iterate(Isolate* isolate, ObjectVisitor* v); 9242 static void Iterate(ObjectVisitor* v, Relocatable* top); 9243 static char* Iterate(ObjectVisitor* v, char* t); 9244 9245 private: 9246 Isolate* isolate_; 9247 Relocatable* prev_; 9248 }; 9249 9250 9251 // A flat string reader provides random access to the contents of a 9252 // string independent of the character width of the string. The handle 9253 // must be valid as long as the reader is being used. 9254 class FlatStringReader : public Relocatable { 9255 public: 9256 FlatStringReader(Isolate* isolate, Handle<String> str); 9257 FlatStringReader(Isolate* isolate, Vector<const char> input); 9258 void PostGarbageCollection(); 9259 inline uc32 Get(int index); 9260 int length() { return length_; } 9261 private: 9262 String** str_; 9263 bool is_one_byte_; 9264 int length_; 9265 const void* start_; 9266 }; 9267 9268 9269 // A ConsStringOp that returns null. 9270 // Useful when the operation to apply on a ConsString 9271 // requires an expensive data structure. 9272 class ConsStringNullOp { 9273 public: 9274 inline ConsStringNullOp() {} 9275 static inline String* Operate(String*, unsigned*, int32_t*, unsigned*); 9276 private: 9277 DISALLOW_COPY_AND_ASSIGN(ConsStringNullOp); 9278 }; 9279 9280 9281 // This maintains an off-stack representation of the stack frames required 9282 // to traverse a ConsString, allowing an entirely iterative and restartable 9283 // traversal of the entire string 9284 class ConsStringIteratorOp { 9285 public: 9286 inline ConsStringIteratorOp() {} 9287 inline explicit ConsStringIteratorOp(ConsString* cons_string, 9288 int offset = 0) { 9289 Reset(cons_string, offset); 9290 } 9291 inline void Reset(ConsString* cons_string, int offset = 0) { 9292 depth_ = 0; 9293 // Next will always return NULL. 9294 if (cons_string == NULL) return; 9295 Initialize(cons_string, offset); 9296 } 9297 // Returns NULL when complete. 9298 inline String* Next(int* offset_out) { 9299 *offset_out = 0; 9300 if (depth_ == 0) return NULL; 9301 return Continue(offset_out); 9302 } 9303 9304 private: 9305 static const int kStackSize = 32; 9306 // Use a mask instead of doing modulo operations for stack wrapping. 9307 static const int kDepthMask = kStackSize-1; 9308 STATIC_ASSERT(IS_POWER_OF_TWO(kStackSize)); 9309 static inline int OffsetForDepth(int depth); 9310 9311 inline void PushLeft(ConsString* string); 9312 inline void PushRight(ConsString* string); 9313 inline void AdjustMaximumDepth(); 9314 inline void Pop(); 9315 inline bool StackBlown() { return maximum_depth_ - depth_ == kStackSize; } 9316 void Initialize(ConsString* cons_string, int offset); 9317 String* Continue(int* offset_out); 9318 String* NextLeaf(bool* blew_stack); 9319 String* Search(int* offset_out); 9320 9321 // Stack must always contain only frames for which right traversal 9322 // has not yet been performed. 9323 ConsString* frames_[kStackSize]; 9324 ConsString* root_; 9325 int depth_; 9326 int maximum_depth_; 9327 int consumed_; 9328 DISALLOW_COPY_AND_ASSIGN(ConsStringIteratorOp); 9329 }; 9330 9331 9332 class StringCharacterStream { 9333 public: 9334 inline StringCharacterStream(String* string, 9335 ConsStringIteratorOp* op, 9336 int offset = 0); 9337 inline uint16_t GetNext(); 9338 inline bool HasMore(); 9339 inline void Reset(String* string, int offset = 0); 9340 inline void VisitOneByteString(const uint8_t* chars, int length); 9341 inline void VisitTwoByteString(const uint16_t* chars, int length); 9342 9343 private: 9344 bool is_one_byte_; 9345 union { 9346 const uint8_t* buffer8_; 9347 const uint16_t* buffer16_; 9348 }; 9349 const uint8_t* end_; 9350 ConsStringIteratorOp* op_; 9351 DISALLOW_COPY_AND_ASSIGN(StringCharacterStream); 9352 }; 9353 9354 9355 template <typename T> 9356 class VectorIterator { 9357 public: 9358 VectorIterator(T* d, int l) : data_(Vector<const T>(d, l)), index_(0) { } 9359 explicit VectorIterator(Vector<const T> data) : data_(data), index_(0) { } 9360 T GetNext() { return data_[index_++]; } 9361 bool has_more() { return index_ < data_.length(); } 9362 private: 9363 Vector<const T> data_; 9364 int index_; 9365 }; 9366 9367 9368 // The Oddball describes objects null, undefined, true, and false. 9369 class Oddball: public HeapObject { 9370 public: 9371 // [to_string]: Cached to_string computed at startup. 9372 DECL_ACCESSORS(to_string, String) 9373 9374 // [to_number]: Cached to_number computed at startup. 9375 DECL_ACCESSORS(to_number, Object) 9376 9377 inline byte kind() const; 9378 inline void set_kind(byte kind); 9379 9380 DECLARE_CAST(Oddball) 9381 9382 // Dispatched behavior. 9383 DECLARE_VERIFIER(Oddball) 9384 9385 // Initialize the fields. 9386 static void Initialize(Isolate* isolate, 9387 Handle<Oddball> oddball, 9388 const char* to_string, 9389 Handle<Object> to_number, 9390 byte kind); 9391 9392 // Layout description. 9393 static const int kToStringOffset = HeapObject::kHeaderSize; 9394 static const int kToNumberOffset = kToStringOffset + kPointerSize; 9395 static const int kKindOffset = kToNumberOffset + kPointerSize; 9396 static const int kSize = kKindOffset + kPointerSize; 9397 9398 static const byte kFalse = 0; 9399 static const byte kTrue = 1; 9400 static const byte kNotBooleanMask = ~1; 9401 static const byte kTheHole = 2; 9402 static const byte kNull = 3; 9403 static const byte kArgumentMarker = 4; 9404 static const byte kUndefined = 5; 9405 static const byte kUninitialized = 6; 9406 static const byte kOther = 7; 9407 static const byte kException = 8; 9408 9409 typedef FixedBodyDescriptor<kToStringOffset, 9410 kToNumberOffset + kPointerSize, 9411 kSize> BodyDescriptor; 9412 9413 STATIC_ASSERT(kKindOffset == Internals::kOddballKindOffset); 9414 STATIC_ASSERT(kNull == Internals::kNullOddballKind); 9415 STATIC_ASSERT(kUndefined == Internals::kUndefinedOddballKind); 9416 9417 private: 9418 DISALLOW_IMPLICIT_CONSTRUCTORS(Oddball); 9419 }; 9420 9421 9422 class Cell: public HeapObject { 9423 public: 9424 // [value]: value of the global property. 9425 DECL_ACCESSORS(value, Object) 9426 9427 DECLARE_CAST(Cell) 9428 9429 static inline Cell* FromValueAddress(Address value) { 9430 Object* result = FromAddress(value - kValueOffset); 9431 DCHECK(result->IsCell() || result->IsPropertyCell()); 9432 return static_cast<Cell*>(result); 9433 } 9434 9435 inline Address ValueAddress() { 9436 return address() + kValueOffset; 9437 } 9438 9439 // Dispatched behavior. 9440 DECLARE_PRINTER(Cell) 9441 DECLARE_VERIFIER(Cell) 9442 9443 // Layout description. 9444 static const int kValueOffset = HeapObject::kHeaderSize; 9445 static const int kSize = kValueOffset + kPointerSize; 9446 9447 typedef FixedBodyDescriptor<kValueOffset, 9448 kValueOffset + kPointerSize, 9449 kSize> BodyDescriptor; 9450 9451 private: 9452 DISALLOW_IMPLICIT_CONSTRUCTORS(Cell); 9453 }; 9454 9455 9456 class PropertyCell: public Cell { 9457 public: 9458 // [type]: type of the global property. 9459 HeapType* type(); 9460 void set_type(HeapType* value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 9461 9462 // [dependent_code]: dependent code that depends on the type of the global 9463 // property. 9464 DECL_ACCESSORS(dependent_code, DependentCode) 9465 9466 // Sets the value of the cell and updates the type field to be the union 9467 // of the cell's current type and the value's type. If the change causes 9468 // a change of the type of the cell's contents, code dependent on the cell 9469 // will be deoptimized. 9470 static void SetValueInferType(Handle<PropertyCell> cell, 9471 Handle<Object> value); 9472 9473 // Computes the new type of the cell's contents for the given value, but 9474 // without actually modifying the 'type' field. 9475 static Handle<HeapType> UpdatedType(Handle<PropertyCell> cell, 9476 Handle<Object> value); 9477 9478 static void AddDependentCompilationInfo(Handle<PropertyCell> cell, 9479 CompilationInfo* info); 9480 9481 DECLARE_CAST(PropertyCell) 9482 9483 inline Address TypeAddress() { 9484 return address() + kTypeOffset; 9485 } 9486 9487 // Dispatched behavior. 9488 DECLARE_PRINTER(PropertyCell) 9489 DECLARE_VERIFIER(PropertyCell) 9490 9491 // Layout description. 9492 static const int kTypeOffset = kValueOffset + kPointerSize; 9493 static const int kDependentCodeOffset = kTypeOffset + kPointerSize; 9494 static const int kSize = kDependentCodeOffset + kPointerSize; 9495 9496 static const int kPointerFieldsBeginOffset = kValueOffset; 9497 static const int kPointerFieldsEndOffset = kDependentCodeOffset; 9498 9499 typedef FixedBodyDescriptor<kValueOffset, 9500 kSize, 9501 kSize> BodyDescriptor; 9502 9503 private: 9504 DECL_ACCESSORS(type_raw, Object) 9505 DISALLOW_IMPLICIT_CONSTRUCTORS(PropertyCell); 9506 }; 9507 9508 9509 // The JSProxy describes EcmaScript Harmony proxies 9510 class JSProxy: public JSReceiver { 9511 public: 9512 // [handler]: The handler property. 9513 DECL_ACCESSORS(handler, Object) 9514 9515 // [hash]: The hash code property (undefined if not initialized yet). 9516 DECL_ACCESSORS(hash, Object) 9517 9518 DECLARE_CAST(JSProxy) 9519 9520 MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler( 9521 Handle<JSProxy> proxy, 9522 Handle<Object> receiver, 9523 Handle<Name> name); 9524 MUST_USE_RESULT static inline MaybeHandle<Object> GetElementWithHandler( 9525 Handle<JSProxy> proxy, 9526 Handle<Object> receiver, 9527 uint32_t index); 9528 9529 // If the handler defines an accessor property with a setter, invoke it. 9530 // If it defines an accessor property without a setter, or a data property 9531 // that is read-only, throw. In all these cases set '*done' to true, 9532 // otherwise set it to false. 9533 MUST_USE_RESULT 9534 static MaybeHandle<Object> SetPropertyViaPrototypesWithHandler( 9535 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, 9536 Handle<Object> value, StrictMode strict_mode, bool* done); 9537 9538 MUST_USE_RESULT static Maybe<PropertyAttributes> 9539 GetPropertyAttributesWithHandler(Handle<JSProxy> proxy, 9540 Handle<Object> receiver, 9541 Handle<Name> name); 9542 MUST_USE_RESULT static Maybe<PropertyAttributes> 9543 GetElementAttributeWithHandler(Handle<JSProxy> proxy, 9544 Handle<JSReceiver> receiver, 9545 uint32_t index); 9546 MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithHandler( 9547 Handle<JSProxy> proxy, Handle<Object> receiver, Handle<Name> name, 9548 Handle<Object> value, StrictMode strict_mode); 9549 9550 // Turn the proxy into an (empty) JSObject. 9551 static void Fix(Handle<JSProxy> proxy); 9552 9553 // Initializes the body after the handler slot. 9554 inline void InitializeBody(int object_size, Object* value); 9555 9556 // Invoke a trap by name. If the trap does not exist on this's handler, 9557 // but derived_trap is non-NULL, invoke that instead. May cause GC. 9558 MUST_USE_RESULT static MaybeHandle<Object> CallTrap( 9559 Handle<JSProxy> proxy, 9560 const char* name, 9561 Handle<Object> derived_trap, 9562 int argc, 9563 Handle<Object> args[]); 9564 9565 // Dispatched behavior. 9566 DECLARE_PRINTER(JSProxy) 9567 DECLARE_VERIFIER(JSProxy) 9568 9569 // Layout description. We add padding so that a proxy has the same 9570 // size as a virgin JSObject. This is essential for becoming a JSObject 9571 // upon freeze. 9572 static const int kHandlerOffset = HeapObject::kHeaderSize; 9573 static const int kHashOffset = kHandlerOffset + kPointerSize; 9574 static const int kPaddingOffset = kHashOffset + kPointerSize; 9575 static const int kSize = JSObject::kHeaderSize; 9576 static const int kHeaderSize = kPaddingOffset; 9577 static const int kPaddingSize = kSize - kPaddingOffset; 9578 9579 STATIC_ASSERT(kPaddingSize >= 0); 9580 9581 typedef FixedBodyDescriptor<kHandlerOffset, 9582 kPaddingOffset, 9583 kSize> BodyDescriptor; 9584 9585 private: 9586 friend class JSReceiver; 9587 9588 MUST_USE_RESULT static inline MaybeHandle<Object> SetElementWithHandler( 9589 Handle<JSProxy> proxy, 9590 Handle<JSReceiver> receiver, 9591 uint32_t index, 9592 Handle<Object> value, 9593 StrictMode strict_mode); 9594 9595 MUST_USE_RESULT static Maybe<bool> HasPropertyWithHandler( 9596 Handle<JSProxy> proxy, Handle<Name> name); 9597 MUST_USE_RESULT static inline Maybe<bool> HasElementWithHandler( 9598 Handle<JSProxy> proxy, uint32_t index); 9599 9600 MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler( 9601 Handle<JSProxy> proxy, 9602 Handle<Name> name, 9603 DeleteMode mode); 9604 MUST_USE_RESULT static MaybeHandle<Object> DeleteElementWithHandler( 9605 Handle<JSProxy> proxy, 9606 uint32_t index, 9607 DeleteMode mode); 9608 9609 MUST_USE_RESULT Object* GetIdentityHash(); 9610 9611 static Handle<Smi> GetOrCreateIdentityHash(Handle<JSProxy> proxy); 9612 9613 DISALLOW_IMPLICIT_CONSTRUCTORS(JSProxy); 9614 }; 9615 9616 9617 class JSFunctionProxy: public JSProxy { 9618 public: 9619 // [call_trap]: The call trap. 9620 DECL_ACCESSORS(call_trap, Object) 9621 9622 // [construct_trap]: The construct trap. 9623 DECL_ACCESSORS(construct_trap, Object) 9624 9625 DECLARE_CAST(JSFunctionProxy) 9626 9627 // Dispatched behavior. 9628 DECLARE_PRINTER(JSFunctionProxy) 9629 DECLARE_VERIFIER(JSFunctionProxy) 9630 9631 // Layout description. 9632 static const int kCallTrapOffset = JSProxy::kPaddingOffset; 9633 static const int kConstructTrapOffset = kCallTrapOffset + kPointerSize; 9634 static const int kPaddingOffset = kConstructTrapOffset + kPointerSize; 9635 static const int kSize = JSFunction::kSize; 9636 static const int kPaddingSize = kSize - kPaddingOffset; 9637 9638 STATIC_ASSERT(kPaddingSize >= 0); 9639 9640 typedef FixedBodyDescriptor<kHandlerOffset, 9641 kConstructTrapOffset + kPointerSize, 9642 kSize> BodyDescriptor; 9643 9644 private: 9645 DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunctionProxy); 9646 }; 9647 9648 9649 class JSCollection : public JSObject { 9650 public: 9651 // [table]: the backing hash table 9652 DECL_ACCESSORS(table, Object) 9653 9654 static const int kTableOffset = JSObject::kHeaderSize; 9655 static const int kSize = kTableOffset + kPointerSize; 9656 9657 private: 9658 DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollection); 9659 }; 9660 9661 9662 // The JSSet describes EcmaScript Harmony sets 9663 class JSSet : public JSCollection { 9664 public: 9665 DECLARE_CAST(JSSet) 9666 9667 // Dispatched behavior. 9668 DECLARE_PRINTER(JSSet) 9669 DECLARE_VERIFIER(JSSet) 9670 9671 private: 9672 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSet); 9673 }; 9674 9675 9676 // The JSMap describes EcmaScript Harmony maps 9677 class JSMap : public JSCollection { 9678 public: 9679 DECLARE_CAST(JSMap) 9680 9681 // Dispatched behavior. 9682 DECLARE_PRINTER(JSMap) 9683 DECLARE_VERIFIER(JSMap) 9684 9685 private: 9686 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap); 9687 }; 9688 9689 9690 // OrderedHashTableIterator is an iterator that iterates over the keys and 9691 // values of an OrderedHashTable. 9692 // 9693 // The iterator has a reference to the underlying OrderedHashTable data, 9694 // [table], as well as the current [index] the iterator is at. 9695 // 9696 // When the OrderedHashTable is rehashed it adds a reference from the old table 9697 // to the new table as well as storing enough data about the changes so that the 9698 // iterator [index] can be adjusted accordingly. 9699 // 9700 // When the [Next] result from the iterator is requested, the iterator checks if 9701 // there is a newer table that it needs to transition to. 9702 template<class Derived, class TableType> 9703 class OrderedHashTableIterator: public JSObject { 9704 public: 9705 // [table]: the backing hash table mapping keys to values. 9706 DECL_ACCESSORS(table, Object) 9707 9708 // [index]: The index into the data table. 9709 DECL_ACCESSORS(index, Object) 9710 9711 // [kind]: The kind of iteration this is. One of the [Kind] enum values. 9712 DECL_ACCESSORS(kind, Object) 9713 9714 #ifdef OBJECT_PRINT 9715 void OrderedHashTableIteratorPrint(OStream& os); // NOLINT 9716 #endif 9717 9718 static const int kTableOffset = JSObject::kHeaderSize; 9719 static const int kIndexOffset = kTableOffset + kPointerSize; 9720 static const int kKindOffset = kIndexOffset + kPointerSize; 9721 static const int kSize = kKindOffset + kPointerSize; 9722 9723 enum Kind { 9724 kKindKeys = 1, 9725 kKindValues = 2, 9726 kKindEntries = 3 9727 }; 9728 9729 // Whether the iterator has more elements. This needs to be called before 9730 // calling |CurrentKey| and/or |CurrentValue|. 9731 bool HasMore(); 9732 9733 // Move the index forward one. 9734 void MoveNext() { 9735 set_index(Smi::FromInt(Smi::cast(index())->value() + 1)); 9736 } 9737 9738 // Populates the array with the next key and value and then moves the iterator 9739 // forward. 9740 // This returns the |kind| or 0 if the iterator is already at the end. 9741 Smi* Next(JSArray* value_array); 9742 9743 // Returns the current key of the iterator. This should only be called when 9744 // |HasMore| returns true. 9745 inline Object* CurrentKey(); 9746 9747 private: 9748 // Transitions the iterator to the non obsolete backing store. This is a NOP 9749 // if the [table] is not obsolete. 9750 void Transition(); 9751 9752 DISALLOW_IMPLICIT_CONSTRUCTORS(OrderedHashTableIterator); 9753 }; 9754 9755 9756 class JSSetIterator: public OrderedHashTableIterator<JSSetIterator, 9757 OrderedHashSet> { 9758 public: 9759 // Dispatched behavior. 9760 DECLARE_PRINTER(JSSetIterator) 9761 DECLARE_VERIFIER(JSSetIterator) 9762 9763 DECLARE_CAST(JSSetIterator) 9764 9765 // Called by |Next| to populate the array. This allows the subclasses to 9766 // populate the array differently. 9767 inline void PopulateValueArray(FixedArray* array); 9768 9769 private: 9770 DISALLOW_IMPLICIT_CONSTRUCTORS(JSSetIterator); 9771 }; 9772 9773 9774 class JSMapIterator: public OrderedHashTableIterator<JSMapIterator, 9775 OrderedHashMap> { 9776 public: 9777 // Dispatched behavior. 9778 DECLARE_PRINTER(JSMapIterator) 9779 DECLARE_VERIFIER(JSMapIterator) 9780 9781 DECLARE_CAST(JSMapIterator) 9782 9783 // Called by |Next| to populate the array. This allows the subclasses to 9784 // populate the array differently. 9785 inline void PopulateValueArray(FixedArray* array); 9786 9787 private: 9788 // Returns the current value of the iterator. This should only be called when 9789 // |HasMore| returns true. 9790 inline Object* CurrentValue(); 9791 9792 DISALLOW_IMPLICIT_CONSTRUCTORS(JSMapIterator); 9793 }; 9794 9795 9796 // Base class for both JSWeakMap and JSWeakSet 9797 class JSWeakCollection: public JSObject { 9798 public: 9799 // [table]: the backing hash table mapping keys to values. 9800 DECL_ACCESSORS(table, Object) 9801 9802 // [next]: linked list of encountered weak maps during GC. 9803 DECL_ACCESSORS(next, Object) 9804 9805 static const int kTableOffset = JSObject::kHeaderSize; 9806 static const int kNextOffset = kTableOffset + kPointerSize; 9807 static const int kSize = kNextOffset + kPointerSize; 9808 9809 private: 9810 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection); 9811 }; 9812 9813 9814 // The JSWeakMap describes EcmaScript Harmony weak maps 9815 class JSWeakMap: public JSWeakCollection { 9816 public: 9817 DECLARE_CAST(JSWeakMap) 9818 9819 // Dispatched behavior. 9820 DECLARE_PRINTER(JSWeakMap) 9821 DECLARE_VERIFIER(JSWeakMap) 9822 9823 private: 9824 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap); 9825 }; 9826 9827 9828 // The JSWeakSet describes EcmaScript Harmony weak sets 9829 class JSWeakSet: public JSWeakCollection { 9830 public: 9831 DECLARE_CAST(JSWeakSet) 9832 9833 // Dispatched behavior. 9834 DECLARE_PRINTER(JSWeakSet) 9835 DECLARE_VERIFIER(JSWeakSet) 9836 9837 private: 9838 DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakSet); 9839 }; 9840 9841 9842 class JSArrayBuffer: public JSObject { 9843 public: 9844 // [backing_store]: backing memory for this array 9845 DECL_ACCESSORS(backing_store, void) 9846 9847 // [byte_length]: length in bytes 9848 DECL_ACCESSORS(byte_length, Object) 9849 9850 // [flags] 9851 DECL_ACCESSORS(flag, Smi) 9852 9853 inline bool is_external(); 9854 inline void set_is_external(bool value); 9855 9856 inline bool should_be_freed(); 9857 inline void set_should_be_freed(bool value); 9858 9859 // [weak_next]: linked list of array buffers. 9860 DECL_ACCESSORS(weak_next, Object) 9861 9862 // [weak_first_array]: weak linked list of views. 9863 DECL_ACCESSORS(weak_first_view, Object) 9864 9865 DECLARE_CAST(JSArrayBuffer) 9866 9867 // Neutering. Only neuters the buffer, not associated typed arrays. 9868 void Neuter(); 9869 9870 // Dispatched behavior. 9871 DECLARE_PRINTER(JSArrayBuffer) 9872 DECLARE_VERIFIER(JSArrayBuffer) 9873 9874 static const int kBackingStoreOffset = JSObject::kHeaderSize; 9875 static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize; 9876 static const int kFlagOffset = kByteLengthOffset + kPointerSize; 9877 static const int kWeakNextOffset = kFlagOffset + kPointerSize; 9878 static const int kWeakFirstViewOffset = kWeakNextOffset + kPointerSize; 9879 static const int kSize = kWeakFirstViewOffset + kPointerSize; 9880 9881 static const int kSizeWithInternalFields = 9882 kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize; 9883 9884 private: 9885 // Bit position in a flag 9886 static const int kIsExternalBit = 0; 9887 static const int kShouldBeFreed = 1; 9888 9889 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer); 9890 }; 9891 9892 9893 class JSArrayBufferView: public JSObject { 9894 public: 9895 // [buffer]: ArrayBuffer that this typed array views. 9896 DECL_ACCESSORS(buffer, Object) 9897 9898 // [byte_length]: offset of typed array in bytes. 9899 DECL_ACCESSORS(byte_offset, Object) 9900 9901 // [byte_length]: length of typed array in bytes. 9902 DECL_ACCESSORS(byte_length, Object) 9903 9904 // [weak_next]: linked list of typed arrays over the same array buffer. 9905 DECL_ACCESSORS(weak_next, Object) 9906 9907 DECLARE_CAST(JSArrayBufferView) 9908 9909 DECLARE_VERIFIER(JSArrayBufferView) 9910 9911 static const int kBufferOffset = JSObject::kHeaderSize; 9912 static const int kByteOffsetOffset = kBufferOffset + kPointerSize; 9913 static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize; 9914 static const int kWeakNextOffset = kByteLengthOffset + kPointerSize; 9915 static const int kViewSize = kWeakNextOffset + kPointerSize; 9916 9917 protected: 9918 void NeuterView(); 9919 9920 private: 9921 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBufferView); 9922 }; 9923 9924 9925 class JSTypedArray: public JSArrayBufferView { 9926 public: 9927 // [length]: length of typed array in elements. 9928 DECL_ACCESSORS(length, Object) 9929 9930 // Neutering. Only neuters this typed array. 9931 void Neuter(); 9932 9933 DECLARE_CAST(JSTypedArray) 9934 9935 ExternalArrayType type(); 9936 size_t element_size(); 9937 9938 Handle<JSArrayBuffer> GetBuffer(); 9939 9940 // Dispatched behavior. 9941 DECLARE_PRINTER(JSTypedArray) 9942 DECLARE_VERIFIER(JSTypedArray) 9943 9944 static const int kLengthOffset = kViewSize + kPointerSize; 9945 static const int kSize = kLengthOffset + kPointerSize; 9946 9947 static const int kSizeWithInternalFields = 9948 kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize; 9949 9950 private: 9951 static Handle<JSArrayBuffer> MaterializeArrayBuffer( 9952 Handle<JSTypedArray> typed_array); 9953 9954 DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray); 9955 }; 9956 9957 9958 class JSDataView: public JSArrayBufferView { 9959 public: 9960 // Only neuters this DataView 9961 void Neuter(); 9962 9963 DECLARE_CAST(JSDataView) 9964 9965 // Dispatched behavior. 9966 DECLARE_PRINTER(JSDataView) 9967 DECLARE_VERIFIER(JSDataView) 9968 9969 static const int kSize = kViewSize; 9970 9971 static const int kSizeWithInternalFields = 9972 kSize + v8::ArrayBufferView::kInternalFieldCount * kPointerSize; 9973 9974 private: 9975 DISALLOW_IMPLICIT_CONSTRUCTORS(JSDataView); 9976 }; 9977 9978 9979 // Foreign describes objects pointing from JavaScript to C structures. 9980 // Since they cannot contain references to JS HeapObjects they can be 9981 // placed in old_data_space. 9982 class Foreign: public HeapObject { 9983 public: 9984 // [address]: field containing the address. 9985 inline Address foreign_address(); 9986 inline void set_foreign_address(Address value); 9987 9988 DECLARE_CAST(Foreign) 9989 9990 // Dispatched behavior. 9991 inline void ForeignIterateBody(ObjectVisitor* v); 9992 9993 template<typename StaticVisitor> 9994 inline void ForeignIterateBody(); 9995 9996 // Dispatched behavior. 9997 DECLARE_PRINTER(Foreign) 9998 DECLARE_VERIFIER(Foreign) 9999 10000 // Layout description. 10001 10002 static const int kForeignAddressOffset = HeapObject::kHeaderSize; 10003 static const int kSize = kForeignAddressOffset + kPointerSize; 10004 10005 STATIC_ASSERT(kForeignAddressOffset == Internals::kForeignAddressOffset); 10006 10007 private: 10008 DISALLOW_IMPLICIT_CONSTRUCTORS(Foreign); 10009 }; 10010 10011 10012 // The JSArray describes JavaScript Arrays 10013 // Such an array can be in one of two modes: 10014 // - fast, backing storage is a FixedArray and length <= elements.length(); 10015 // Please note: push and pop can be used to grow and shrink the array. 10016 // - slow, backing storage is a HashTable with numbers as keys. 10017 class JSArray: public JSObject { 10018 public: 10019 // [length]: The length property. 10020 DECL_ACCESSORS(length, Object) 10021 10022 // Overload the length setter to skip write barrier when the length 10023 // is set to a smi. This matches the set function on FixedArray. 10024 inline void set_length(Smi* length); 10025 10026 static void JSArrayUpdateLengthFromIndex(Handle<JSArray> array, 10027 uint32_t index, 10028 Handle<Object> value); 10029 10030 static bool IsReadOnlyLengthDescriptor(Handle<Map> jsarray_map); 10031 static bool WouldChangeReadOnlyLength(Handle<JSArray> array, uint32_t index); 10032 static MaybeHandle<Object> ReadOnlyLengthError(Handle<JSArray> array); 10033 10034 // Initialize the array with the given capacity. The function may 10035 // fail due to out-of-memory situations, but only if the requested 10036 // capacity is non-zero. 10037 static void Initialize(Handle<JSArray> array, int capacity, int length = 0); 10038 10039 // Initializes the array to a certain length. 10040 inline bool AllowsSetElementsLength(); 10041 // Can cause GC. 10042 MUST_USE_RESULT static MaybeHandle<Object> SetElementsLength( 10043 Handle<JSArray> array, 10044 Handle<Object> length); 10045 10046 // Set the content of the array to the content of storage. 10047 static inline void SetContent(Handle<JSArray> array, 10048 Handle<FixedArrayBase> storage); 10049 10050 DECLARE_CAST(JSArray) 10051 10052 // Ensures that the fixed array backing the JSArray has at 10053 // least the stated size. 10054 static inline void EnsureSize(Handle<JSArray> array, 10055 int minimum_size_of_backing_fixed_array); 10056 10057 // Expand the fixed array backing of a fast-case JSArray to at least 10058 // the requested size. 10059 static void Expand(Handle<JSArray> array, 10060 int minimum_size_of_backing_fixed_array); 10061 10062 // Dispatched behavior. 10063 DECLARE_PRINTER(JSArray) 10064 DECLARE_VERIFIER(JSArray) 10065 10066 // Number of element slots to pre-allocate for an empty array. 10067 static const int kPreallocatedArrayElements = 4; 10068 10069 // Layout description. 10070 static const int kLengthOffset = JSObject::kHeaderSize; 10071 static const int kSize = kLengthOffset + kPointerSize; 10072 10073 private: 10074 DISALLOW_IMPLICIT_CONSTRUCTORS(JSArray); 10075 }; 10076 10077 10078 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context, 10079 Handle<Map> initial_map); 10080 10081 10082 // JSRegExpResult is just a JSArray with a specific initial map. 10083 // This initial map adds in-object properties for "index" and "input" 10084 // properties, as assigned by RegExp.prototype.exec, which allows 10085 // faster creation of RegExp exec results. 10086 // This class just holds constants used when creating the result. 10087 // After creation the result must be treated as a JSArray in all regards. 10088 class JSRegExpResult: public JSArray { 10089 public: 10090 // Offsets of object fields. 10091 static const int kIndexOffset = JSArray::kSize; 10092 static const int kInputOffset = kIndexOffset + kPointerSize; 10093 static const int kSize = kInputOffset + kPointerSize; 10094 // Indices of in-object properties. 10095 static const int kIndexIndex = 0; 10096 static const int kInputIndex = 1; 10097 private: 10098 DISALLOW_IMPLICIT_CONSTRUCTORS(JSRegExpResult); 10099 }; 10100 10101 10102 class AccessorInfo: public Struct { 10103 public: 10104 DECL_ACCESSORS(name, Object) 10105 DECL_ACCESSORS(flag, Smi) 10106 DECL_ACCESSORS(expected_receiver_type, Object) 10107 10108 inline bool all_can_read(); 10109 inline void set_all_can_read(bool value); 10110 10111 inline bool all_can_write(); 10112 inline void set_all_can_write(bool value); 10113 10114 inline PropertyAttributes property_attributes(); 10115 inline void set_property_attributes(PropertyAttributes attributes); 10116 10117 // Checks whether the given receiver is compatible with this accessor. 10118 static bool IsCompatibleReceiverType(Isolate* isolate, 10119 Handle<AccessorInfo> info, 10120 Handle<HeapType> type); 10121 inline bool IsCompatibleReceiver(Object* receiver); 10122 10123 DECLARE_CAST(AccessorInfo) 10124 10125 // Dispatched behavior. 10126 DECLARE_VERIFIER(AccessorInfo) 10127 10128 // Append all descriptors to the array that are not already there. 10129 // Return number added. 10130 static int AppendUnique(Handle<Object> descriptors, 10131 Handle<FixedArray> array, 10132 int valid_descriptors); 10133 10134 static const int kNameOffset = HeapObject::kHeaderSize; 10135 static const int kFlagOffset = kNameOffset + kPointerSize; 10136 static const int kExpectedReceiverTypeOffset = kFlagOffset + kPointerSize; 10137 static const int kSize = kExpectedReceiverTypeOffset + kPointerSize; 10138 10139 private: 10140 inline bool HasExpectedReceiverType() { 10141 return expected_receiver_type()->IsFunctionTemplateInfo(); 10142 } 10143 // Bit positions in flag. 10144 static const int kAllCanReadBit = 0; 10145 static const int kAllCanWriteBit = 1; 10146 class AttributesField: public BitField<PropertyAttributes, 2, 3> {}; 10147 10148 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo); 10149 }; 10150 10151 10152 enum AccessorDescriptorType { 10153 kDescriptorBitmaskCompare, 10154 kDescriptorPointerCompare, 10155 kDescriptorPrimitiveValue, 10156 kDescriptorObjectDereference, 10157 kDescriptorPointerDereference, 10158 kDescriptorPointerShift, 10159 kDescriptorReturnObject 10160 }; 10161 10162 10163 struct BitmaskCompareDescriptor { 10164 uint32_t bitmask; 10165 uint32_t compare_value; 10166 uint8_t size; // Must be in {1,2,4}. 10167 }; 10168 10169 10170 struct PointerCompareDescriptor { 10171 void* compare_value; 10172 }; 10173 10174 10175 struct PrimitiveValueDescriptor { 10176 v8::DeclaredAccessorDescriptorDataType data_type; 10177 uint8_t bool_offset; // Must be in [0,7], used for kDescriptorBoolType. 10178 }; 10179 10180 10181 struct ObjectDerefenceDescriptor { 10182 uint8_t internal_field; 10183 }; 10184 10185 10186 struct PointerShiftDescriptor { 10187 int16_t byte_offset; 10188 }; 10189 10190 10191 struct DeclaredAccessorDescriptorData { 10192 AccessorDescriptorType type; 10193 union { 10194 struct BitmaskCompareDescriptor bitmask_compare_descriptor; 10195 struct PointerCompareDescriptor pointer_compare_descriptor; 10196 struct PrimitiveValueDescriptor primitive_value_descriptor; 10197 struct ObjectDerefenceDescriptor object_dereference_descriptor; 10198 struct PointerShiftDescriptor pointer_shift_descriptor; 10199 }; 10200 }; 10201 10202 10203 class DeclaredAccessorDescriptor; 10204 10205 10206 class DeclaredAccessorDescriptorIterator { 10207 public: 10208 explicit DeclaredAccessorDescriptorIterator( 10209 DeclaredAccessorDescriptor* descriptor); 10210 const DeclaredAccessorDescriptorData* Next(); 10211 bool Complete() const { return length_ == offset_; } 10212 private: 10213 uint8_t* array_; 10214 const int length_; 10215 int offset_; 10216 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptorIterator); 10217 }; 10218 10219 10220 class DeclaredAccessorDescriptor: public Struct { 10221 public: 10222 DECL_ACCESSORS(serialized_data, ByteArray) 10223 10224 DECLARE_CAST(DeclaredAccessorDescriptor) 10225 10226 static Handle<DeclaredAccessorDescriptor> Create( 10227 Isolate* isolate, 10228 const DeclaredAccessorDescriptorData& data, 10229 Handle<DeclaredAccessorDescriptor> previous); 10230 10231 // Dispatched behavior. 10232 DECLARE_PRINTER(DeclaredAccessorDescriptor) 10233 DECLARE_VERIFIER(DeclaredAccessorDescriptor) 10234 10235 static const int kSerializedDataOffset = HeapObject::kHeaderSize; 10236 static const int kSize = kSerializedDataOffset + kPointerSize; 10237 10238 private: 10239 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptor); 10240 }; 10241 10242 10243 class DeclaredAccessorInfo: public AccessorInfo { 10244 public: 10245 DECL_ACCESSORS(descriptor, DeclaredAccessorDescriptor) 10246 10247 DECLARE_CAST(DeclaredAccessorInfo) 10248 10249 // Dispatched behavior. 10250 DECLARE_PRINTER(DeclaredAccessorInfo) 10251 DECLARE_VERIFIER(DeclaredAccessorInfo) 10252 10253 static const int kDescriptorOffset = AccessorInfo::kSize; 10254 static const int kSize = kDescriptorOffset + kPointerSize; 10255 10256 private: 10257 DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorInfo); 10258 }; 10259 10260 10261 // An accessor must have a getter, but can have no setter. 10262 // 10263 // When setting a property, V8 searches accessors in prototypes. 10264 // If an accessor was found and it does not have a setter, 10265 // the request is ignored. 10266 // 10267 // If the accessor in the prototype has the READ_ONLY property attribute, then 10268 // a new value is added to the derived object when the property is set. 10269 // This shadows the accessor in the prototype. 10270 class ExecutableAccessorInfo: public AccessorInfo { 10271 public: 10272 DECL_ACCESSORS(getter, Object) 10273 DECL_ACCESSORS(setter, Object) 10274 DECL_ACCESSORS(data, Object) 10275 10276 DECLARE_CAST(ExecutableAccessorInfo) 10277 10278 // Dispatched behavior. 10279 DECLARE_PRINTER(ExecutableAccessorInfo) 10280 DECLARE_VERIFIER(ExecutableAccessorInfo) 10281 10282 static const int kGetterOffset = AccessorInfo::kSize; 10283 static const int kSetterOffset = kGetterOffset + kPointerSize; 10284 static const int kDataOffset = kSetterOffset + kPointerSize; 10285 static const int kSize = kDataOffset + kPointerSize; 10286 10287 inline void clear_setter(); 10288 10289 private: 10290 DISALLOW_IMPLICIT_CONSTRUCTORS(ExecutableAccessorInfo); 10291 }; 10292 10293 10294 // Support for JavaScript accessors: A pair of a getter and a setter. Each 10295 // accessor can either be 10296 // * a pointer to a JavaScript function or proxy: a real accessor 10297 // * undefined: considered an accessor by the spec, too, strangely enough 10298 // * the hole: an accessor which has not been set 10299 // * a pointer to a map: a transition used to ensure map sharing 10300 class AccessorPair: public Struct { 10301 public: 10302 DECL_ACCESSORS(getter, Object) 10303 DECL_ACCESSORS(setter, Object) 10304 10305 DECLARE_CAST(AccessorPair) 10306 10307 static Handle<AccessorPair> Copy(Handle<AccessorPair> pair); 10308 10309 Object* get(AccessorComponent component) { 10310 return component == ACCESSOR_GETTER ? getter() : setter(); 10311 } 10312 10313 void set(AccessorComponent component, Object* value) { 10314 if (component == ACCESSOR_GETTER) { 10315 set_getter(value); 10316 } else { 10317 set_setter(value); 10318 } 10319 } 10320 10321 // Note: Returns undefined instead in case of a hole. 10322 Object* GetComponent(AccessorComponent component); 10323 10324 // Set both components, skipping arguments which are a JavaScript null. 10325 void SetComponents(Object* getter, Object* setter) { 10326 if (!getter->IsNull()) set_getter(getter); 10327 if (!setter->IsNull()) set_setter(setter); 10328 } 10329 10330 bool ContainsAccessor() { 10331 return IsJSAccessor(getter()) || IsJSAccessor(setter()); 10332 } 10333 10334 // Dispatched behavior. 10335 DECLARE_PRINTER(AccessorPair) 10336 DECLARE_VERIFIER(AccessorPair) 10337 10338 static const int kGetterOffset = HeapObject::kHeaderSize; 10339 static const int kSetterOffset = kGetterOffset + kPointerSize; 10340 static const int kSize = kSetterOffset + kPointerSize; 10341 10342 private: 10343 // Strangely enough, in addition to functions and harmony proxies, the spec 10344 // requires us to consider undefined as a kind of accessor, too: 10345 // var obj = {}; 10346 // Object.defineProperty(obj, "foo", {get: undefined}); 10347 // assertTrue("foo" in obj); 10348 bool IsJSAccessor(Object* obj) { 10349 return obj->IsSpecFunction() || obj->IsUndefined(); 10350 } 10351 10352 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair); 10353 }; 10354 10355 10356 class AccessCheckInfo: public Struct { 10357 public: 10358 DECL_ACCESSORS(named_callback, Object) 10359 DECL_ACCESSORS(indexed_callback, Object) 10360 DECL_ACCESSORS(data, Object) 10361 10362 DECLARE_CAST(AccessCheckInfo) 10363 10364 // Dispatched behavior. 10365 DECLARE_PRINTER(AccessCheckInfo) 10366 DECLARE_VERIFIER(AccessCheckInfo) 10367 10368 static const int kNamedCallbackOffset = HeapObject::kHeaderSize; 10369 static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize; 10370 static const int kDataOffset = kIndexedCallbackOffset + kPointerSize; 10371 static const int kSize = kDataOffset + kPointerSize; 10372 10373 private: 10374 DISALLOW_IMPLICIT_CONSTRUCTORS(AccessCheckInfo); 10375 }; 10376 10377 10378 class InterceptorInfo: public Struct { 10379 public: 10380 DECL_ACCESSORS(getter, Object) 10381 DECL_ACCESSORS(setter, Object) 10382 DECL_ACCESSORS(query, Object) 10383 DECL_ACCESSORS(deleter, Object) 10384 DECL_ACCESSORS(enumerator, Object) 10385 DECL_ACCESSORS(data, Object) 10386 10387 DECLARE_CAST(InterceptorInfo) 10388 10389 // Dispatched behavior. 10390 DECLARE_PRINTER(InterceptorInfo) 10391 DECLARE_VERIFIER(InterceptorInfo) 10392 10393 static const int kGetterOffset = HeapObject::kHeaderSize; 10394 static const int kSetterOffset = kGetterOffset + kPointerSize; 10395 static const int kQueryOffset = kSetterOffset + kPointerSize; 10396 static const int kDeleterOffset = kQueryOffset + kPointerSize; 10397 static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; 10398 static const int kDataOffset = kEnumeratorOffset + kPointerSize; 10399 static const int kSize = kDataOffset + kPointerSize; 10400 10401 private: 10402 DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); 10403 }; 10404 10405 10406 class CallHandlerInfo: public Struct { 10407 public: 10408 DECL_ACCESSORS(callback, Object) 10409 DECL_ACCESSORS(data, Object) 10410 10411 DECLARE_CAST(CallHandlerInfo) 10412 10413 // Dispatched behavior. 10414 DECLARE_PRINTER(CallHandlerInfo) 10415 DECLARE_VERIFIER(CallHandlerInfo) 10416 10417 static const int kCallbackOffset = HeapObject::kHeaderSize; 10418 static const int kDataOffset = kCallbackOffset + kPointerSize; 10419 static const int kSize = kDataOffset + kPointerSize; 10420 10421 private: 10422 DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo); 10423 }; 10424 10425 10426 class TemplateInfo: public Struct { 10427 public: 10428 DECL_ACCESSORS(tag, Object) 10429 DECL_ACCESSORS(property_list, Object) 10430 DECL_ACCESSORS(property_accessors, Object) 10431 10432 DECLARE_VERIFIER(TemplateInfo) 10433 10434 static const int kTagOffset = HeapObject::kHeaderSize; 10435 static const int kPropertyListOffset = kTagOffset + kPointerSize; 10436 static const int kPropertyAccessorsOffset = 10437 kPropertyListOffset + kPointerSize; 10438 static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize; 10439 10440 private: 10441 DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo); 10442 }; 10443 10444 10445 class FunctionTemplateInfo: public TemplateInfo { 10446 public: 10447 DECL_ACCESSORS(serial_number, Object) 10448 DECL_ACCESSORS(call_code, Object) 10449 DECL_ACCESSORS(prototype_template, Object) 10450 DECL_ACCESSORS(parent_template, Object) 10451 DECL_ACCESSORS(named_property_handler, Object) 10452 DECL_ACCESSORS(indexed_property_handler, Object) 10453 DECL_ACCESSORS(instance_template, Object) 10454 DECL_ACCESSORS(class_name, Object) 10455 DECL_ACCESSORS(signature, Object) 10456 DECL_ACCESSORS(instance_call_handler, Object) 10457 DECL_ACCESSORS(access_check_info, Object) 10458 DECL_ACCESSORS(flag, Smi) 10459 10460 inline int length() const; 10461 inline void set_length(int value); 10462 10463 // Following properties use flag bits. 10464 DECL_BOOLEAN_ACCESSORS(hidden_prototype) 10465 DECL_BOOLEAN_ACCESSORS(undetectable) 10466 // If the bit is set, object instances created by this function 10467 // requires access check. 10468 DECL_BOOLEAN_ACCESSORS(needs_access_check) 10469 DECL_BOOLEAN_ACCESSORS(read_only_prototype) 10470 DECL_BOOLEAN_ACCESSORS(remove_prototype) 10471 DECL_BOOLEAN_ACCESSORS(do_not_cache) 10472 10473 DECLARE_CAST(FunctionTemplateInfo) 10474 10475 // Dispatched behavior. 10476 DECLARE_PRINTER(FunctionTemplateInfo) 10477 DECLARE_VERIFIER(FunctionTemplateInfo) 10478 10479 static const int kSerialNumberOffset = TemplateInfo::kHeaderSize; 10480 static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize; 10481 static const int kPrototypeTemplateOffset = 10482 kCallCodeOffset + kPointerSize; 10483 static const int kParentTemplateOffset = 10484 kPrototypeTemplateOffset + kPointerSize; 10485 static const int kNamedPropertyHandlerOffset = 10486 kParentTemplateOffset + kPointerSize; 10487 static const int kIndexedPropertyHandlerOffset = 10488 kNamedPropertyHandlerOffset + kPointerSize; 10489 static const int kInstanceTemplateOffset = 10490 kIndexedPropertyHandlerOffset + kPointerSize; 10491 static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize; 10492 static const int kSignatureOffset = kClassNameOffset + kPointerSize; 10493 static const int kInstanceCallHandlerOffset = kSignatureOffset + kPointerSize; 10494 static const int kAccessCheckInfoOffset = 10495 kInstanceCallHandlerOffset + kPointerSize; 10496 static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize; 10497 static const int kLengthOffset = kFlagOffset + kPointerSize; 10498 static const int kSize = kLengthOffset + kPointerSize; 10499 10500 // Returns true if |object| is an instance of this function template. 10501 bool IsTemplateFor(Object* object); 10502 bool IsTemplateFor(Map* map); 10503 10504 private: 10505 // Bit position in the flag, from least significant bit position. 10506 static const int kHiddenPrototypeBit = 0; 10507 static const int kUndetectableBit = 1; 10508 static const int kNeedsAccessCheckBit = 2; 10509 static const int kReadOnlyPrototypeBit = 3; 10510 static const int kRemovePrototypeBit = 4; 10511 static const int kDoNotCacheBit = 5; 10512 10513 DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo); 10514 }; 10515 10516 10517 class ObjectTemplateInfo: public TemplateInfo { 10518 public: 10519 DECL_ACCESSORS(constructor, Object) 10520 DECL_ACCESSORS(internal_field_count, Object) 10521 10522 DECLARE_CAST(ObjectTemplateInfo) 10523 10524 // Dispatched behavior. 10525 DECLARE_PRINTER(ObjectTemplateInfo) 10526 DECLARE_VERIFIER(ObjectTemplateInfo) 10527 10528 static const int kConstructorOffset = TemplateInfo::kHeaderSize; 10529 static const int kInternalFieldCountOffset = 10530 kConstructorOffset + kPointerSize; 10531 static const int kSize = kInternalFieldCountOffset + kPointerSize; 10532 }; 10533 10534 10535 class SignatureInfo: public Struct { 10536 public: 10537 DECL_ACCESSORS(receiver, Object) 10538 DECL_ACCESSORS(args, Object) 10539 10540 DECLARE_CAST(SignatureInfo) 10541 10542 // Dispatched behavior. 10543 DECLARE_PRINTER(SignatureInfo) 10544 DECLARE_VERIFIER(SignatureInfo) 10545 10546 static const int kReceiverOffset = Struct::kHeaderSize; 10547 static const int kArgsOffset = kReceiverOffset + kPointerSize; 10548 static const int kSize = kArgsOffset + kPointerSize; 10549 10550 private: 10551 DISALLOW_IMPLICIT_CONSTRUCTORS(SignatureInfo); 10552 }; 10553 10554 10555 class TypeSwitchInfo: public Struct { 10556 public: 10557 DECL_ACCESSORS(types, Object) 10558 10559 DECLARE_CAST(TypeSwitchInfo) 10560 10561 // Dispatched behavior. 10562 DECLARE_PRINTER(TypeSwitchInfo) 10563 DECLARE_VERIFIER(TypeSwitchInfo) 10564 10565 static const int kTypesOffset = Struct::kHeaderSize; 10566 static const int kSize = kTypesOffset + kPointerSize; 10567 }; 10568 10569 10570 // The DebugInfo class holds additional information for a function being 10571 // debugged. 10572 class DebugInfo: public Struct { 10573 public: 10574 // The shared function info for the source being debugged. 10575 DECL_ACCESSORS(shared, SharedFunctionInfo) 10576 // Code object for the original code. 10577 DECL_ACCESSORS(original_code, Code) 10578 // Code object for the patched code. This code object is the code object 10579 // currently active for the function. 10580 DECL_ACCESSORS(code, Code) 10581 // Fixed array holding status information for each active break point. 10582 DECL_ACCESSORS(break_points, FixedArray) 10583 10584 // Check if there is a break point at a code position. 10585 bool HasBreakPoint(int code_position); 10586 // Get the break point info object for a code position. 10587 Object* GetBreakPointInfo(int code_position); 10588 // Clear a break point. 10589 static void ClearBreakPoint(Handle<DebugInfo> debug_info, 10590 int code_position, 10591 Handle<Object> break_point_object); 10592 // Set a break point. 10593 static void SetBreakPoint(Handle<DebugInfo> debug_info, int code_position, 10594 int source_position, int statement_position, 10595 Handle<Object> break_point_object); 10596 // Get the break point objects for a code position. 10597 Object* GetBreakPointObjects(int code_position); 10598 // Find the break point info holding this break point object. 10599 static Object* FindBreakPointInfo(Handle<DebugInfo> debug_info, 10600 Handle<Object> break_point_object); 10601 // Get the number of break points for this function. 10602 int GetBreakPointCount(); 10603 10604 DECLARE_CAST(DebugInfo) 10605 10606 // Dispatched behavior. 10607 DECLARE_PRINTER(DebugInfo) 10608 DECLARE_VERIFIER(DebugInfo) 10609 10610 static const int kSharedFunctionInfoIndex = Struct::kHeaderSize; 10611 static const int kOriginalCodeIndex = kSharedFunctionInfoIndex + kPointerSize; 10612 static const int kPatchedCodeIndex = kOriginalCodeIndex + kPointerSize; 10613 static const int kActiveBreakPointsCountIndex = 10614 kPatchedCodeIndex + kPointerSize; 10615 static const int kBreakPointsStateIndex = 10616 kActiveBreakPointsCountIndex + kPointerSize; 10617 static const int kSize = kBreakPointsStateIndex + kPointerSize; 10618 10619 static const int kEstimatedNofBreakPointsInFunction = 16; 10620 10621 private: 10622 static const int kNoBreakPointInfo = -1; 10623 10624 // Lookup the index in the break_points array for a code position. 10625 int GetBreakPointInfoIndex(int code_position); 10626 10627 DISALLOW_IMPLICIT_CONSTRUCTORS(DebugInfo); 10628 }; 10629 10630 10631 // The BreakPointInfo class holds information for break points set in a 10632 // function. The DebugInfo object holds a BreakPointInfo object for each code 10633 // position with one or more break points. 10634 class BreakPointInfo: public Struct { 10635 public: 10636 // The position in the code for the break point. 10637 DECL_ACCESSORS(code_position, Smi) 10638 // The position in the source for the break position. 10639 DECL_ACCESSORS(source_position, Smi) 10640 // The position in the source for the last statement before this break 10641 // position. 10642 DECL_ACCESSORS(statement_position, Smi) 10643 // List of related JavaScript break points. 10644 DECL_ACCESSORS(break_point_objects, Object) 10645 10646 // Removes a break point. 10647 static void ClearBreakPoint(Handle<BreakPointInfo> info, 10648 Handle<Object> break_point_object); 10649 // Set a break point. 10650 static void SetBreakPoint(Handle<BreakPointInfo> info, 10651 Handle<Object> break_point_object); 10652 // Check if break point info has this break point object. 10653 static bool HasBreakPointObject(Handle<BreakPointInfo> info, 10654 Handle<Object> break_point_object); 10655 // Get the number of break points for this code position. 10656 int GetBreakPointCount(); 10657 10658 DECLARE_CAST(BreakPointInfo) 10659 10660 // Dispatched behavior. 10661 DECLARE_PRINTER(BreakPointInfo) 10662 DECLARE_VERIFIER(BreakPointInfo) 10663 10664 static const int kCodePositionIndex = Struct::kHeaderSize; 10665 static const int kSourcePositionIndex = kCodePositionIndex + kPointerSize; 10666 static const int kStatementPositionIndex = 10667 kSourcePositionIndex + kPointerSize; 10668 static const int kBreakPointObjectsIndex = 10669 kStatementPositionIndex + kPointerSize; 10670 static const int kSize = kBreakPointObjectsIndex + kPointerSize; 10671 10672 private: 10673 DISALLOW_IMPLICIT_CONSTRUCTORS(BreakPointInfo); 10674 }; 10675 10676 10677 #undef DECL_BOOLEAN_ACCESSORS 10678 #undef DECL_ACCESSORS 10679 #undef DECLARE_CAST 10680 #undef DECLARE_VERIFIER 10681 10682 #define VISITOR_SYNCHRONIZATION_TAGS_LIST(V) \ 10683 V(kStringTable, "string_table", "(Internalized strings)") \ 10684 V(kExternalStringsTable, "external_strings_table", "(External strings)") \ 10685 V(kStrongRootList, "strong_root_list", "(Strong roots)") \ 10686 V(kSmiRootList, "smi_root_list", "(Smi roots)") \ 10687 V(kInternalizedString, "internalized_string", "(Internal string)") \ 10688 V(kBootstrapper, "bootstrapper", "(Bootstrapper)") \ 10689 V(kTop, "top", "(Isolate)") \ 10690 V(kRelocatable, "relocatable", "(Relocatable)") \ 10691 V(kDebug, "debug", "(Debugger)") \ 10692 V(kCompilationCache, "compilationcache", "(Compilation cache)") \ 10693 V(kHandleScope, "handlescope", "(Handle scope)") \ 10694 V(kBuiltins, "builtins", "(Builtins)") \ 10695 V(kGlobalHandles, "globalhandles", "(Global handles)") \ 10696 V(kEternalHandles, "eternalhandles", "(Eternal handles)") \ 10697 V(kThreadManager, "threadmanager", "(Thread manager)") \ 10698 V(kExtensions, "Extensions", "(Extensions)") 10699 10700 class VisitorSynchronization : public AllStatic { 10701 public: 10702 #define DECLARE_ENUM(enum_item, ignore1, ignore2) enum_item, 10703 enum SyncTag { 10704 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_ENUM) 10705 kNumberOfSyncTags 10706 }; 10707 #undef DECLARE_ENUM 10708 10709 static const char* const kTags[kNumberOfSyncTags]; 10710 static const char* const kTagNames[kNumberOfSyncTags]; 10711 }; 10712 10713 // Abstract base class for visiting, and optionally modifying, the 10714 // pointers contained in Objects. Used in GC and serialization/deserialization. 10715 class ObjectVisitor BASE_EMBEDDED { 10716 public: 10717 virtual ~ObjectVisitor() {} 10718 10719 // Visits a contiguous arrays of pointers in the half-open range 10720 // [start, end). Any or all of the values may be modified on return. 10721 virtual void VisitPointers(Object** start, Object** end) = 0; 10722 10723 // Handy shorthand for visiting a single pointer. 10724 virtual void VisitPointer(Object** p) { VisitPointers(p, p + 1); } 10725 10726 // Visit weak next_code_link in Code object. 10727 virtual void VisitNextCodeLink(Object** p) { VisitPointers(p, p + 1); } 10728 10729 // To allow lazy clearing of inline caches the visitor has 10730 // a rich interface for iterating over Code objects.. 10731 10732 // Visits a code target in the instruction stream. 10733 virtual void VisitCodeTarget(RelocInfo* rinfo); 10734 10735 // Visits a code entry in a JS function. 10736 virtual void VisitCodeEntry(Address entry_address); 10737 10738 // Visits a global property cell reference in the instruction stream. 10739 virtual void VisitCell(RelocInfo* rinfo); 10740 10741 // Visits a runtime entry in the instruction stream. 10742 virtual void VisitRuntimeEntry(RelocInfo* rinfo) {} 10743 10744 // Visits the resource of an one-byte or two-byte string. 10745 virtual void VisitExternalOneByteString( 10746 v8::String::ExternalOneByteStringResource** resource) {} 10747 virtual void VisitExternalTwoByteString( 10748 v8::String::ExternalStringResource** resource) {} 10749 10750 // Visits a debug call target in the instruction stream. 10751 virtual void VisitDebugTarget(RelocInfo* rinfo); 10752 10753 // Visits the byte sequence in a function's prologue that contains information 10754 // about the code's age. 10755 virtual void VisitCodeAgeSequence(RelocInfo* rinfo); 10756 10757 // Visit pointer embedded into a code object. 10758 virtual void VisitEmbeddedPointer(RelocInfo* rinfo); 10759 10760 // Visits an external reference embedded into a code object. 10761 virtual void VisitExternalReference(RelocInfo* rinfo); 10762 10763 // Visits an external reference. The value may be modified on return. 10764 virtual void VisitExternalReference(Address* p) {} 10765 10766 // Visits a handle that has an embedder-assigned class ID. 10767 virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {} 10768 10769 // Intended for serialization/deserialization checking: insert, or 10770 // check for the presence of, a tag at this position in the stream. 10771 // Also used for marking up GC roots in heap snapshots. 10772 virtual void Synchronize(VisitorSynchronization::SyncTag tag) {} 10773 }; 10774 10775 10776 class StructBodyDescriptor : public 10777 FlexibleBodyDescriptor<HeapObject::kHeaderSize> { 10778 public: 10779 static inline int SizeOf(Map* map, HeapObject* object) { 10780 return map->instance_size(); 10781 } 10782 }; 10783 10784 10785 // BooleanBit is a helper class for setting and getting a bit in an 10786 // integer or Smi. 10787 class BooleanBit : public AllStatic { 10788 public: 10789 static inline bool get(Smi* smi, int bit_position) { 10790 return get(smi->value(), bit_position); 10791 } 10792 10793 static inline bool get(int value, int bit_position) { 10794 return (value & (1 << bit_position)) != 0; 10795 } 10796 10797 static inline Smi* set(Smi* smi, int bit_position, bool v) { 10798 return Smi::FromInt(set(smi->value(), bit_position, v)); 10799 } 10800 10801 static inline int set(int value, int bit_position, bool v) { 10802 if (v) { 10803 value |= (1 << bit_position); 10804 } else { 10805 value &= ~(1 << bit_position); 10806 } 10807 return value; 10808 } 10809 }; 10810 10811 } } // namespace v8::internal 10812 10813 #endif // V8_OBJECTS_H_ 10814