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 // Review notes: 6 // 7 // - The use of macros in these inline functions may seem superfluous 8 // but it is absolutely needed to make sure gcc generates optimal 9 // code. gcc is not happy when attempting to inline too deep. 10 // 11 12 #ifndef V8_OBJECTS_INL_H_ 13 #define V8_OBJECTS_INL_H_ 14 15 #include "src/objects.h" 16 17 #include "src/base/atomicops.h" 18 #include "src/base/bits.h" 19 #include "src/base/tsan.h" 20 #include "src/builtins/builtins.h" 21 #include "src/contexts-inl.h" 22 #include "src/conversions-inl.h" 23 #include "src/feedback-vector-inl.h" 24 #include "src/field-index-inl.h" 25 #include "src/handles-inl.h" 26 #include "src/heap/factory.h" 27 #include "src/heap/heap-inl.h" 28 #include "src/isolate-inl.h" 29 #include "src/keys.h" 30 #include "src/layout-descriptor-inl.h" 31 #include "src/lookup-cache-inl.h" 32 #include "src/lookup-inl.h" 33 #include "src/maybe-handles-inl.h" 34 #include "src/objects/bigint.h" 35 #include "src/objects/descriptor-array.h" 36 #include "src/objects/js-proxy-inl.h" 37 #include "src/objects/literal-objects.h" 38 #include "src/objects/maybe-object-inl.h" 39 #include "src/objects/regexp-match-info.h" 40 #include "src/objects/scope-info.h" 41 #include "src/objects/template-objects.h" 42 #include "src/objects/templates.h" 43 #include "src/property-details.h" 44 #include "src/property.h" 45 #include "src/prototype-inl.h" 46 #include "src/roots-inl.h" 47 #include "src/transitions-inl.h" 48 #include "src/v8memory.h" 49 50 // Has to be the last include (doesn't have include guards): 51 #include "src/objects/object-macros.h" 52 53 namespace v8 { 54 namespace internal { 55 56 PropertyDetails::PropertyDetails(Smi* smi) { 57 value_ = smi->value(); 58 } 59 60 61 Smi* PropertyDetails::AsSmi() const { 62 // Ensure the upper 2 bits have the same value by sign extending it. This is 63 // necessary to be able to use the 31st bit of the property details. 64 int value = value_ << 1; 65 return Smi::FromInt(value >> 1); 66 } 67 68 69 int PropertyDetails::field_width_in_words() const { 70 DCHECK_EQ(location(), kField); 71 if (!FLAG_unbox_double_fields) return 1; 72 if (kDoubleSize == kPointerSize) return 1; 73 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; 74 } 75 76 namespace InstanceTypeChecker { 77 78 // Define type checkers for classes with single instance type. 79 INSTANCE_TYPE_CHECKERS_SINGLE(INSTANCE_TYPE_CHECKER); 80 81 #define TYPED_ARRAY_INSTANCE_TYPE_CHECKER(Type, type, TYPE, ctype) \ 82 INSTANCE_TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE) 83 TYPED_ARRAYS(TYPED_ARRAY_INSTANCE_TYPE_CHECKER) 84 #undef TYPED_ARRAY_INSTANCE_TYPE_CHECKER 85 86 #define STRUCT_INSTANCE_TYPE_CHECKER(NAME, Name, name) \ 87 INSTANCE_TYPE_CHECKER(Name, NAME##_TYPE) 88 STRUCT_LIST(STRUCT_INSTANCE_TYPE_CHECKER) 89 #undef STRUCT_INSTANCE_TYPE_CHECKER 90 91 // Define type checkers for classes with ranges of instance types. 92 #define INSTANCE_TYPE_CHECKER_RANGE(type, first_instance_type, \ 93 last_instance_type) \ 94 V8_INLINE bool Is##type(InstanceType instance_type) { \ 95 return instance_type >= first_instance_type && \ 96 instance_type <= last_instance_type; \ 97 } 98 INSTANCE_TYPE_CHECKERS_RANGE(INSTANCE_TYPE_CHECKER_RANGE); 99 #undef INSTANCE_TYPE_CHECKER_RANGE 100 101 V8_INLINE bool IsFixedArrayBase(InstanceType instance_type) { 102 return IsFixedArray(instance_type) || IsFixedDoubleArray(instance_type) || 103 IsFixedTypedArrayBase(instance_type); 104 } 105 106 V8_INLINE bool IsHeapObject(InstanceType instance_type) { return true; } 107 108 V8_INLINE bool IsInternalizedString(InstanceType instance_type) { 109 STATIC_ASSERT(kNotInternalizedTag != 0); 110 return (instance_type & (kIsNotStringMask | kIsNotInternalizedMask)) == 111 (kStringTag | kInternalizedTag); 112 } 113 114 V8_INLINE bool IsJSObject(InstanceType instance_type) { 115 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); 116 return instance_type >= FIRST_JS_OBJECT_TYPE; 117 } 118 119 } // namespace InstanceTypeChecker 120 121 // TODO(v8:7786): For instance types that have a single map instance on the 122 // roots, and when that map is a embedded in the binary, compare against the map 123 // pointer rather than looking up the instance type. 124 INSTANCE_TYPE_CHECKERS(TYPE_CHECKER); 125 126 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype) \ 127 TYPE_CHECKER(Fixed##Type##Array) 128 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER) 129 #undef TYPED_ARRAY_TYPE_CHECKER 130 131 bool HeapObject::IsUncompiledData() const { 132 return IsUncompiledDataWithoutPreParsedScope() || 133 IsUncompiledDataWithPreParsedScope(); 134 } 135 136 bool HeapObject::IsSloppyArgumentsElements() const { 137 return IsFixedArrayExact(); 138 } 139 140 bool HeapObject::IsJSSloppyArgumentsObject() const { 141 return IsJSArgumentsObject(); 142 } 143 144 bool HeapObject::IsJSGeneratorObject() const { 145 return map()->instance_type() == JS_GENERATOR_OBJECT_TYPE || 146 IsJSAsyncGeneratorObject(); 147 } 148 149 bool HeapObject::IsDataHandler() const { 150 return IsLoadHandler() || IsStoreHandler(); 151 } 152 153 bool HeapObject::IsClassBoilerplate() const { return IsFixedArrayExact(); } 154 155 bool HeapObject::IsExternal(Isolate* isolate) const { 156 return map()->FindRootMap(isolate) == isolate->heap()->external_map(); 157 } 158 159 #define IS_TYPE_FUNCTION_DEF(type_) \ 160 bool Object::Is##type_() const { \ 161 return IsHeapObject() && HeapObject::cast(this)->Is##type_(); \ 162 } 163 HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DEF) 164 #undef IS_TYPE_FUNCTION_DEF 165 166 #define IS_TYPE_FUNCTION_DEF(Type, Value) \ 167 bool Object::Is##Type(Isolate* isolate) const { \ 168 return Is##Type(ReadOnlyRoots(isolate->heap())); \ 169 } \ 170 bool Object::Is##Type(ReadOnlyRoots roots) const { \ 171 return this == roots.Value(); \ 172 } \ 173 bool Object::Is##Type() const { \ 174 return IsHeapObject() && HeapObject::cast(this)->Is##Type(); \ 175 } \ 176 bool HeapObject::Is##Type(Isolate* isolate) const { \ 177 return Object::Is##Type(isolate); \ 178 } \ 179 bool HeapObject::Is##Type(ReadOnlyRoots roots) const { \ 180 return Object::Is##Type(roots); \ 181 } \ 182 bool HeapObject::Is##Type() const { return Is##Type(GetReadOnlyRoots()); } 183 ODDBALL_LIST(IS_TYPE_FUNCTION_DEF) 184 #undef IS_TYPE_FUNCTION_DEF 185 186 bool Object::IsNullOrUndefined(Isolate* isolate) const { 187 return IsNullOrUndefined(ReadOnlyRoots(isolate)); 188 } 189 190 bool Object::IsNullOrUndefined(ReadOnlyRoots roots) const { 191 return IsNull(roots) || IsUndefined(roots); 192 } 193 194 bool Object::IsNullOrUndefined() const { 195 return IsHeapObject() && HeapObject::cast(this)->IsNullOrUndefined(); 196 } 197 198 bool HeapObject::IsNullOrUndefined(Isolate* isolate) const { 199 return Object::IsNullOrUndefined(isolate); 200 } 201 202 bool HeapObject::IsNullOrUndefined(ReadOnlyRoots roots) const { 203 return Object::IsNullOrUndefined(roots); 204 } 205 206 bool HeapObject::IsNullOrUndefined() const { 207 return IsNullOrUndefined(GetReadOnlyRoots()); 208 } 209 210 bool HeapObject::IsUniqueName() const { 211 return IsInternalizedString() || IsSymbol(); 212 } 213 214 bool HeapObject::IsFunction() const { 215 STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 216 return map()->instance_type() >= FIRST_FUNCTION_TYPE; 217 } 218 219 bool HeapObject::IsCallable() const { return map()->is_callable(); } 220 221 bool HeapObject::IsConstructor() const { return map()->is_constructor(); } 222 223 bool HeapObject::IsModuleInfo() const { 224 return map() == GetReadOnlyRoots().module_info_map(); 225 } 226 227 bool HeapObject::IsTemplateInfo() const { 228 return IsObjectTemplateInfo() || IsFunctionTemplateInfo(); 229 } 230 231 bool HeapObject::IsConsString() const { 232 if (!IsString()) return false; 233 return StringShape(String::cast(this)).IsCons(); 234 } 235 236 bool HeapObject::IsThinString() const { 237 if (!IsString()) return false; 238 return StringShape(String::cast(this)).IsThin(); 239 } 240 241 bool HeapObject::IsSlicedString() const { 242 if (!IsString()) return false; 243 return StringShape(String::cast(this)).IsSliced(); 244 } 245 246 bool HeapObject::IsSeqString() const { 247 if (!IsString()) return false; 248 return StringShape(String::cast(this)).IsSequential(); 249 } 250 251 bool HeapObject::IsSeqOneByteString() const { 252 if (!IsString()) return false; 253 return StringShape(String::cast(this)).IsSequential() && 254 String::cast(this)->IsOneByteRepresentation(); 255 } 256 257 bool HeapObject::IsSeqTwoByteString() const { 258 if (!IsString()) return false; 259 return StringShape(String::cast(this)).IsSequential() && 260 String::cast(this)->IsTwoByteRepresentation(); 261 } 262 263 bool HeapObject::IsExternalString() const { 264 if (!IsString()) return false; 265 return StringShape(String::cast(this)).IsExternal(); 266 } 267 268 bool HeapObject::IsExternalOneByteString() const { 269 if (!IsString()) return false; 270 return StringShape(String::cast(this)).IsExternal() && 271 String::cast(this)->IsOneByteRepresentation(); 272 } 273 274 bool HeapObject::IsExternalTwoByteString() const { 275 if (!IsString()) return false; 276 return StringShape(String::cast(this)).IsExternal() && 277 String::cast(this)->IsTwoByteRepresentation(); 278 } 279 280 bool Object::IsNumber() const { return IsSmi() || IsHeapNumber(); } 281 282 bool Object::IsNumeric() const { return IsNumber() || IsBigInt(); } 283 284 bool HeapObject::IsFiller() const { 285 InstanceType instance_type = map()->instance_type(); 286 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; 287 } 288 289 bool HeapObject::IsJSReceiver() const { 290 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 291 return map()->instance_type() >= FIRST_JS_RECEIVER_TYPE; 292 } 293 294 bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); } 295 296 bool HeapObject::IsJSWeakCollection() const { 297 return IsJSWeakMap() || IsJSWeakSet(); 298 } 299 300 bool HeapObject::IsJSCollection() const { return IsJSMap() || IsJSSet(); } 301 302 bool HeapObject::IsPromiseReactionJobTask() const { 303 return IsPromiseFulfillReactionJobTask() || IsPromiseRejectReactionJobTask(); 304 } 305 306 bool HeapObject::IsEnumCache() const { return IsTuple2(); } 307 308 bool HeapObject::IsFrameArray() const { return IsFixedArrayExact(); } 309 310 bool HeapObject::IsArrayList() const { 311 return map() == GetReadOnlyRoots().array_list_map() || 312 this == GetReadOnlyRoots().empty_fixed_array(); 313 } 314 315 bool HeapObject::IsRegExpMatchInfo() const { return IsFixedArrayExact(); } 316 317 bool Object::IsLayoutDescriptor() const { return IsSmi() || IsByteArray(); } 318 319 bool HeapObject::IsDeoptimizationData() const { 320 // Must be a fixed array. 321 if (!IsFixedArrayExact()) return false; 322 323 // There's no sure way to detect the difference between a fixed array and 324 // a deoptimization data array. Since this is used for asserts we can 325 // check that the length is zero or else the fixed size plus a multiple of 326 // the entry size. 327 int length = FixedArray::cast(this)->length(); 328 if (length == 0) return true; 329 330 length -= DeoptimizationData::kFirstDeoptEntryIndex; 331 return length >= 0 && length % DeoptimizationData::kDeoptEntrySize == 0; 332 } 333 334 bool HeapObject::IsHandlerTable() const { 335 if (!IsFixedArrayExact()) return false; 336 // There's actually no way to see the difference between a fixed array and 337 // a handler table array. 338 return true; 339 } 340 341 bool HeapObject::IsTemplateList() const { 342 if (!IsFixedArrayExact()) return false; 343 // There's actually no way to see the difference between a fixed array and 344 // a template list. 345 if (FixedArray::cast(this)->length() < 1) return false; 346 return true; 347 } 348 349 bool HeapObject::IsDependentCode() const { 350 if (!IsWeakFixedArray()) return false; 351 // There's actually no way to see the difference between a weak fixed array 352 // and a dependent codes array. 353 return true; 354 } 355 356 bool HeapObject::IsAbstractCode() const { 357 return IsBytecodeArray() || IsCode(); 358 } 359 360 bool HeapObject::IsStringWrapper() const { 361 return IsJSValue() && JSValue::cast(this)->value()->IsString(); 362 } 363 364 bool HeapObject::IsBooleanWrapper() const { 365 return IsJSValue() && JSValue::cast(this)->value()->IsBoolean(); 366 } 367 368 bool HeapObject::IsScriptWrapper() const { 369 return IsJSValue() && JSValue::cast(this)->value()->IsScript(); 370 } 371 372 bool HeapObject::IsNumberWrapper() const { 373 return IsJSValue() && JSValue::cast(this)->value()->IsNumber(); 374 } 375 376 bool HeapObject::IsBigIntWrapper() const { 377 return IsJSValue() && JSValue::cast(this)->value()->IsBigInt(); 378 } 379 380 bool HeapObject::IsSymbolWrapper() const { 381 return IsJSValue() && JSValue::cast(this)->value()->IsSymbol(); 382 } 383 384 bool HeapObject::IsBoolean() const { 385 return IsOddball() && 386 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); 387 } 388 389 bool HeapObject::IsJSArrayBufferView() const { 390 return IsJSDataView() || IsJSTypedArray(); 391 } 392 393 bool HeapObject::IsStringSet() const { return IsHashTable(); } 394 395 bool HeapObject::IsObjectHashSet() const { return IsHashTable(); } 396 397 bool HeapObject::IsNormalizedMapCache() const { 398 return NormalizedMapCache::IsNormalizedMapCache(this); 399 } 400 401 bool HeapObject::IsCompilationCacheTable() const { return IsHashTable(); } 402 403 bool HeapObject::IsMapCache() const { return IsHashTable(); } 404 405 bool HeapObject::IsObjectHashTable() const { return IsHashTable(); } 406 407 bool Object::IsSmallOrderedHashTable() const { 408 return IsSmallOrderedHashSet() || IsSmallOrderedHashMap(); 409 } 410 411 bool Object::IsPrimitive() const { 412 return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); 413 } 414 415 // static 416 Maybe<bool> Object::IsArray(Handle<Object> object) { 417 if (object->IsSmi()) return Just(false); 418 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); 419 if (heap_object->IsJSArray()) return Just(true); 420 if (!heap_object->IsJSProxy()) return Just(false); 421 return JSProxy::IsArray(Handle<JSProxy>::cast(object)); 422 } 423 424 bool HeapObject::IsUndetectable() const { return map()->is_undetectable(); } 425 426 bool HeapObject::IsAccessCheckNeeded() const { 427 if (IsJSGlobalProxy()) { 428 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this); 429 JSGlobalObject* global = proxy->GetIsolate()->context()->global_object(); 430 return proxy->IsDetachedFrom(global); 431 } 432 return map()->is_access_check_needed(); 433 } 434 435 bool HeapObject::IsStruct() const { 436 switch (map()->instance_type()) { 437 #define MAKE_STRUCT_CASE(NAME, Name, name) \ 438 case NAME##_TYPE: \ 439 return true; 440 STRUCT_LIST(MAKE_STRUCT_CASE) 441 #undef MAKE_STRUCT_CASE 442 default: 443 return false; 444 } 445 } 446 447 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ 448 bool Object::Is##Name() const { \ 449 return IsHeapObject() && HeapObject::cast(this)->Is##Name(); \ 450 } \ 451 TYPE_CHECKER(Name) 452 STRUCT_LIST(MAKE_STRUCT_PREDICATE) 453 #undef MAKE_STRUCT_PREDICATE 454 455 double Object::Number() const { 456 DCHECK(IsNumber()); 457 return IsSmi() 458 ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value()) 459 : reinterpret_cast<const HeapNumber*>(this)->value(); 460 } 461 462 bool Object::IsNaN() const { 463 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); 464 } 465 466 bool Object::IsMinusZero() const { 467 return this->IsHeapNumber() && 468 i::IsMinusZero(HeapNumber::cast(this)->value()); 469 } 470 471 // ------------------------------------ 472 // Cast operations 473 474 CAST_ACCESSOR(AccessorPair) 475 CAST_ACCESSOR(AllocationMemento) 476 CAST_ACCESSOR(AllocationSite) 477 CAST_ACCESSOR(AsyncGeneratorRequest) 478 CAST_ACCESSOR(BigInt) 479 CAST_ACCESSOR(ObjectBoilerplateDescription) 480 CAST_ACCESSOR(Cell) 481 CAST_ACCESSOR(ArrayBoilerplateDescription) 482 CAST_ACCESSOR(DataHandler) 483 CAST_ACCESSOR(DescriptorArray) 484 CAST_ACCESSOR(EphemeronHashTable) 485 CAST_ACCESSOR(EnumCache) 486 CAST_ACCESSOR(FeedbackCell) 487 CAST_ACCESSOR(Foreign) 488 CAST_ACCESSOR(GlobalDictionary) 489 CAST_ACCESSOR(HeapObject) 490 CAST_ACCESSOR(JSAsyncFromSyncIterator) 491 CAST_ACCESSOR(JSBoundFunction) 492 CAST_ACCESSOR(JSDataView) 493 CAST_ACCESSOR(JSDate) 494 CAST_ACCESSOR(JSFunction) 495 CAST_ACCESSOR(JSGlobalObject) 496 CAST_ACCESSOR(JSGlobalProxy) 497 CAST_ACCESSOR(JSMessageObject) 498 CAST_ACCESSOR(JSObject) 499 CAST_ACCESSOR(JSReceiver) 500 CAST_ACCESSOR(JSStringIterator) 501 CAST_ACCESSOR(JSValue) 502 CAST_ACCESSOR(HeapNumber) 503 CAST_ACCESSOR(LayoutDescriptor) 504 CAST_ACCESSOR(MutableHeapNumber) 505 CAST_ACCESSOR(NameDictionary) 506 CAST_ACCESSOR(NormalizedMapCache) 507 CAST_ACCESSOR(NumberDictionary) 508 CAST_ACCESSOR(Object) 509 CAST_ACCESSOR(ObjectHashSet) 510 CAST_ACCESSOR(ObjectHashTable) 511 CAST_ACCESSOR(Oddball) 512 CAST_ACCESSOR(OrderedHashMap) 513 CAST_ACCESSOR(OrderedHashSet) 514 CAST_ACCESSOR(PropertyArray) 515 CAST_ACCESSOR(PropertyCell) 516 CAST_ACCESSOR(RegExpMatchInfo) 517 CAST_ACCESSOR(ScopeInfo) 518 CAST_ACCESSOR(SimpleNumberDictionary) 519 CAST_ACCESSOR(SmallOrderedHashMap) 520 CAST_ACCESSOR(SmallOrderedHashSet) 521 CAST_ACCESSOR(Smi) 522 CAST_ACCESSOR(SourcePositionTableWithFrameCache) 523 CAST_ACCESSOR(StackFrameInfo) 524 CAST_ACCESSOR(StringSet) 525 CAST_ACCESSOR(StringTable) 526 CAST_ACCESSOR(Struct) 527 CAST_ACCESSOR(TemplateObjectDescription) 528 CAST_ACCESSOR(Tuple2) 529 CAST_ACCESSOR(Tuple3) 530 531 bool Object::HasValidElements() { 532 // Dictionary is covered under FixedArray. 533 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); 534 } 535 536 bool Object::KeyEquals(Object* second) { 537 Object* first = this; 538 if (second->IsNumber()) { 539 if (first->IsNumber()) return first->Number() == second->Number(); 540 Object* temp = first; 541 first = second; 542 second = temp; 543 } 544 if (first->IsNumber()) { 545 DCHECK_LE(0, first->Number()); 546 uint32_t expected = static_cast<uint32_t>(first->Number()); 547 uint32_t index; 548 return Name::cast(second)->AsArrayIndex(&index) && index == expected; 549 } 550 return Name::cast(first)->Equals(Name::cast(second)); 551 } 552 553 bool Object::FilterKey(PropertyFilter filter) { 554 DCHECK(!IsPropertyCell()); 555 if (IsSymbol()) { 556 if (filter & SKIP_SYMBOLS) return true; 557 if (Symbol::cast(this)->is_private()) return true; 558 } else { 559 if (filter & SKIP_STRINGS) return true; 560 } 561 return false; 562 } 563 564 Handle<Object> Object::NewStorageFor(Isolate* isolate, Handle<Object> object, 565 Representation representation) { 566 if (!representation.IsDouble()) return object; 567 auto result = isolate->factory()->NewMutableHeapNumberWithHoleNaN(); 568 if (object->IsUninitialized(isolate)) { 569 result->set_value_as_bits(kHoleNanInt64); 570 } else if (object->IsMutableHeapNumber()) { 571 // Ensure that all bits of the double value are preserved. 572 result->set_value_as_bits( 573 MutableHeapNumber::cast(*object)->value_as_bits()); 574 } else { 575 result->set_value(object->Number()); 576 } 577 return result; 578 } 579 580 Handle<Object> Object::WrapForRead(Isolate* isolate, Handle<Object> object, 581 Representation representation) { 582 DCHECK(!object->IsUninitialized(isolate)); 583 if (!representation.IsDouble()) { 584 DCHECK(object->FitsRepresentation(representation)); 585 return object; 586 } 587 return isolate->factory()->NewHeapNumber( 588 MutableHeapNumber::cast(*object)->value()); 589 } 590 591 Representation Object::OptimalRepresentation() { 592 if (!FLAG_track_fields) return Representation::Tagged(); 593 if (IsSmi()) { 594 return Representation::Smi(); 595 } else if (FLAG_track_double_fields && IsHeapNumber()) { 596 return Representation::Double(); 597 } else if (FLAG_track_computed_fields && IsUninitialized()) { 598 return Representation::None(); 599 } else if (FLAG_track_heap_object_fields) { 600 DCHECK(IsHeapObject()); 601 return Representation::HeapObject(); 602 } else { 603 return Representation::Tagged(); 604 } 605 } 606 607 608 ElementsKind Object::OptimalElementsKind() { 609 if (IsSmi()) return PACKED_SMI_ELEMENTS; 610 if (IsNumber()) return PACKED_DOUBLE_ELEMENTS; 611 return PACKED_ELEMENTS; 612 } 613 614 615 bool Object::FitsRepresentation(Representation representation) { 616 if (FLAG_track_fields && representation.IsSmi()) { 617 return IsSmi(); 618 } else if (FLAG_track_double_fields && representation.IsDouble()) { 619 return IsMutableHeapNumber() || IsNumber(); 620 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 621 return IsHeapObject(); 622 } else if (FLAG_track_fields && representation.IsNone()) { 623 return false; 624 } 625 return true; 626 } 627 628 bool Object::ToUint32(uint32_t* value) const { 629 if (IsSmi()) { 630 int num = Smi::ToInt(this); 631 if (num < 0) return false; 632 *value = static_cast<uint32_t>(num); 633 return true; 634 } 635 if (IsHeapNumber()) { 636 double num = HeapNumber::cast(this)->value(); 637 return DoubleToUint32IfEqualToSelf(num, value); 638 } 639 return false; 640 } 641 642 // static 643 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate, 644 Handle<Object> object, 645 const char* method_name) { 646 if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object); 647 return ToObject(isolate, object, isolate->native_context(), method_name); 648 } 649 650 651 // static 652 MaybeHandle<Name> Object::ToName(Isolate* isolate, Handle<Object> input) { 653 if (input->IsName()) return Handle<Name>::cast(input); 654 return ConvertToName(isolate, input); 655 } 656 657 // static 658 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate, 659 Handle<Object> value) { 660 if (value->IsSmi() || HeapObject::cast(*value)->IsName()) return value; 661 return ConvertToPropertyKey(isolate, value); 662 } 663 664 // static 665 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input, 666 ToPrimitiveHint hint) { 667 if (input->IsPrimitive()) return input; 668 return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint); 669 } 670 671 // static 672 MaybeHandle<Object> Object::ToNumber(Isolate* isolate, Handle<Object> input) { 673 if (input->IsNumber()) return input; // Shortcut. 674 return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber); 675 } 676 677 // static 678 MaybeHandle<Object> Object::ToNumeric(Isolate* isolate, Handle<Object> input) { 679 if (input->IsNumber() || input->IsBigInt()) return input; // Shortcut. 680 return ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumeric); 681 } 682 683 // static 684 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) { 685 if (input->IsSmi()) return input; 686 return ConvertToInteger(isolate, input); 687 } 688 689 // static 690 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) { 691 if (input->IsSmi()) return input; 692 return ConvertToInt32(isolate, input); 693 } 694 695 // static 696 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) { 697 if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate); 698 return ConvertToUint32(isolate, input); 699 } 700 701 // static 702 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) { 703 if (input->IsString()) return Handle<String>::cast(input); 704 return ConvertToString(isolate, input); 705 } 706 707 // static 708 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) { 709 if (input->IsSmi()) { 710 int value = std::max(Smi::ToInt(*input), 0); 711 return handle(Smi::FromInt(value), isolate); 712 } 713 return ConvertToLength(isolate, input); 714 } 715 716 // static 717 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input, 718 MessageTemplate::Template error_index) { 719 if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input; 720 return ConvertToIndex(isolate, input, error_index); 721 } 722 723 MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object, 724 Handle<Name> name) { 725 LookupIterator it(isolate, object, name); 726 if (!it.IsFound()) return it.factory()->undefined_value(); 727 return GetProperty(&it); 728 } 729 730 MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate, 731 Handle<JSReceiver> receiver, 732 Handle<Name> name) { 733 LookupIterator it(isolate, receiver, name, receiver); 734 if (!it.IsFound()) return it.factory()->undefined_value(); 735 return Object::GetProperty(&it); 736 } 737 738 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object, 739 uint32_t index) { 740 LookupIterator it(isolate, object, index); 741 if (!it.IsFound()) return it.factory()->undefined_value(); 742 return GetProperty(&it); 743 } 744 745 MaybeHandle<Object> JSReceiver::GetElement(Isolate* isolate, 746 Handle<JSReceiver> receiver, 747 uint32_t index) { 748 LookupIterator it(isolate, receiver, index, receiver); 749 if (!it.IsFound()) return it.factory()->undefined_value(); 750 return Object::GetProperty(&it); 751 } 752 753 Handle<Object> JSReceiver::GetDataProperty(Handle<JSReceiver> object, 754 Handle<Name> name) { 755 LookupIterator it(object, name, object, 756 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); 757 if (!it.IsFound()) return it.factory()->undefined_value(); 758 return GetDataProperty(&it); 759 } 760 761 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object, 762 uint32_t index, Handle<Object> value, 763 LanguageMode language_mode) { 764 LookupIterator it(isolate, object, index); 765 MAYBE_RETURN_NULL( 766 SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED)); 767 return value; 768 } 769 770 MaybeHandle<Object> JSReceiver::GetPrototype(Isolate* isolate, 771 Handle<JSReceiver> receiver) { 772 // We don't expect access checks to be needed on JSProxy objects. 773 DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject()); 774 PrototypeIterator iter(isolate, receiver, kStartAtReceiver, 775 PrototypeIterator::END_AT_NON_HIDDEN); 776 do { 777 if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>(); 778 } while (!iter.IsAtEnd()); 779 return PrototypeIterator::GetCurrent(iter); 780 } 781 782 MaybeHandle<Object> JSReceiver::GetProperty(Isolate* isolate, 783 Handle<JSReceiver> receiver, 784 const char* name) { 785 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); 786 return GetProperty(isolate, receiver, str); 787 } 788 789 // static 790 V8_WARN_UNUSED_RESULT MaybeHandle<FixedArray> JSReceiver::OwnPropertyKeys( 791 Handle<JSReceiver> object) { 792 return KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, 793 ALL_PROPERTIES, 794 GetKeysConversion::kConvertToString); 795 } 796 797 bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) { 798 DisallowHeapAllocation no_gc; 799 HeapObject* prototype = HeapObject::cast(object->map()->prototype()); 800 ReadOnlyRoots roots(isolate); 801 HeapObject* null = roots.null_value(); 802 HeapObject* empty_fixed_array = roots.empty_fixed_array(); 803 HeapObject* empty_slow_element_dictionary = 804 roots.empty_slow_element_dictionary(); 805 while (prototype != null) { 806 Map* map = prototype->map(); 807 if (map->IsCustomElementsReceiverMap()) return false; 808 HeapObject* elements = JSObject::cast(prototype)->elements(); 809 if (elements != empty_fixed_array && 810 elements != empty_slow_element_dictionary) { 811 return false; 812 } 813 prototype = HeapObject::cast(map->prototype()); 814 } 815 return true; 816 } 817 818 Object** HeapObject::RawField(const HeapObject* obj, int byte_offset) { 819 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset)); 820 } 821 822 MaybeObject** HeapObject::RawMaybeWeakField(HeapObject* obj, int byte_offset) { 823 return reinterpret_cast<MaybeObject**>(FIELD_ADDR(obj, byte_offset)); 824 } 825 826 int Smi::ToInt(const Object* object) { return Smi::cast(object)->value(); } 827 828 MapWord MapWord::FromMap(const Map* map) { 829 return MapWord(reinterpret_cast<uintptr_t>(map)); 830 } 831 832 Map* MapWord::ToMap() const { return reinterpret_cast<Map*>(value_); } 833 834 bool MapWord::IsForwardingAddress() const { 835 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_)); 836 } 837 838 839 MapWord MapWord::FromForwardingAddress(HeapObject* object) { 840 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag; 841 return MapWord(static_cast<uintptr_t>(raw)); 842 } 843 844 845 HeapObject* MapWord::ToForwardingAddress() { 846 DCHECK(IsForwardingAddress()); 847 return HeapObject::FromAddress(static_cast<Address>(value_)); 848 } 849 850 851 #ifdef VERIFY_HEAP 852 void HeapObject::VerifyObjectField(Isolate* isolate, int offset) { 853 VerifyPointer(isolate, READ_FIELD(this, offset)); 854 } 855 856 void HeapObject::VerifyMaybeObjectField(Isolate* isolate, int offset) { 857 MaybeObject::VerifyMaybeObjectPointer(isolate, READ_WEAK_FIELD(this, offset)); 858 } 859 860 void HeapObject::VerifySmiField(int offset) { 861 CHECK(READ_FIELD(this, offset)->IsSmi()); 862 } 863 #endif 864 865 ReadOnlyRoots HeapObject::GetReadOnlyRoots() const { 866 // TODO(v8:7464): When RO_SPACE is embedded, this will access a global 867 // variable instead. 868 return ReadOnlyRoots(MemoryChunk::FromHeapObject(this)->heap()); 869 } 870 871 Heap* NeverReadOnlySpaceObject::GetHeap() const { 872 MemoryChunk* chunk = 873 MemoryChunk::FromAddress(reinterpret_cast<Address>(this)); 874 // Make sure we are not accessing an object in RO space. 875 SLOW_DCHECK(chunk->owner()->identity() != RO_SPACE); 876 Heap* heap = chunk->heap(); 877 SLOW_DCHECK(heap != nullptr); 878 return heap; 879 } 880 881 Isolate* NeverReadOnlySpaceObject::GetIsolate() const { 882 return GetHeap()->isolate(); 883 } 884 885 Map* HeapObject::map() const { 886 return map_word().ToMap(); 887 } 888 889 890 void HeapObject::set_map(Map* value) { 891 if (value != nullptr) { 892 #ifdef VERIFY_HEAP 893 Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value); 894 #endif 895 } 896 set_map_word(MapWord::FromMap(value)); 897 if (value != nullptr) { 898 // TODO(1600) We are passing nullptr as a slot because maps can never be on 899 // evacuation candidate. 900 MarkingBarrier(this, nullptr, value); 901 } 902 } 903 904 Map* HeapObject::synchronized_map() const { 905 return synchronized_map_word().ToMap(); 906 } 907 908 909 void HeapObject::synchronized_set_map(Map* value) { 910 if (value != nullptr) { 911 #ifdef VERIFY_HEAP 912 Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value); 913 #endif 914 } 915 synchronized_set_map_word(MapWord::FromMap(value)); 916 if (value != nullptr) { 917 // TODO(1600) We are passing nullptr as a slot because maps can never be on 918 // evacuation candidate. 919 MarkingBarrier(this, nullptr, value); 920 } 921 } 922 923 924 // Unsafe accessor omitting write barrier. 925 void HeapObject::set_map_no_write_barrier(Map* value) { 926 if (value != nullptr) { 927 #ifdef VERIFY_HEAP 928 Heap::FromWritableHeapObject(this)->VerifyObjectLayoutChange(this, value); 929 #endif 930 } 931 set_map_word(MapWord::FromMap(value)); 932 } 933 934 void HeapObject::set_map_after_allocation(Map* value, WriteBarrierMode mode) { 935 set_map_word(MapWord::FromMap(value)); 936 if (mode != SKIP_WRITE_BARRIER) { 937 DCHECK_NOT_NULL(value); 938 // TODO(1600) We are passing nullptr as a slot because maps can never be on 939 // evacuation candidate. 940 MarkingBarrier(this, nullptr, value); 941 } 942 } 943 944 HeapObject** HeapObject::map_slot() { 945 return reinterpret_cast<HeapObject**>(FIELD_ADDR(this, kMapOffset)); 946 } 947 948 MapWord HeapObject::map_word() const { 949 return MapWord( 950 reinterpret_cast<uintptr_t>(RELAXED_READ_FIELD(this, kMapOffset))); 951 } 952 953 954 void HeapObject::set_map_word(MapWord map_word) { 955 RELAXED_WRITE_FIELD(this, kMapOffset, 956 reinterpret_cast<Object*>(map_word.value_)); 957 } 958 959 960 MapWord HeapObject::synchronized_map_word() const { 961 return MapWord( 962 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset))); 963 } 964 965 966 void HeapObject::synchronized_set_map_word(MapWord map_word) { 967 RELEASE_WRITE_FIELD( 968 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 969 } 970 971 int HeapObject::Size() const { return SizeFromMap(map()); } 972 973 double HeapNumberBase::value() const { 974 return READ_DOUBLE_FIELD(this, kValueOffset); 975 } 976 977 void HeapNumberBase::set_value(double value) { 978 WRITE_DOUBLE_FIELD(this, kValueOffset, value); 979 } 980 981 uint64_t HeapNumberBase::value_as_bits() const { 982 return READ_UINT64_FIELD(this, kValueOffset); 983 } 984 985 void HeapNumberBase::set_value_as_bits(uint64_t bits) { 986 WRITE_UINT64_FIELD(this, kValueOffset, bits); 987 } 988 989 int HeapNumberBase::get_exponent() { 990 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> 991 kExponentShift) - kExponentBias; 992 } 993 994 int HeapNumberBase::get_sign() { 995 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; 996 } 997 998 ACCESSORS(JSReceiver, raw_properties_or_hash, Object, kPropertiesOrHashOffset) 999 1000 FixedArrayBase* JSObject::elements() const { 1001 Object* array = READ_FIELD(this, kElementsOffset); 1002 return static_cast<FixedArrayBase*>(array); 1003 } 1004 1005 bool AllocationSite::HasWeakNext() const { 1006 return map() == GetReadOnlyRoots().allocation_site_map(); 1007 } 1008 1009 void AllocationSite::Initialize() { 1010 set_transition_info_or_boilerplate(Smi::kZero); 1011 SetElementsKind(GetInitialFastElementsKind()); 1012 set_nested_site(Smi::kZero); 1013 set_pretenure_data(0); 1014 set_pretenure_create_count(0); 1015 set_dependent_code( 1016 DependentCode::cast(GetReadOnlyRoots().empty_weak_fixed_array()), 1017 SKIP_WRITE_BARRIER); 1018 } 1019 1020 bool AllocationSite::IsZombie() const { 1021 return pretenure_decision() == kZombie; 1022 } 1023 1024 bool AllocationSite::IsMaybeTenure() const { 1025 return pretenure_decision() == kMaybeTenure; 1026 } 1027 1028 bool AllocationSite::PretenuringDecisionMade() const { 1029 return pretenure_decision() != kUndecided; 1030 } 1031 1032 1033 void AllocationSite::MarkZombie() { 1034 DCHECK(!IsZombie()); 1035 Initialize(); 1036 set_pretenure_decision(kZombie); 1037 } 1038 1039 ElementsKind AllocationSite::GetElementsKind() const { 1040 return ElementsKindBits::decode(transition_info()); 1041 } 1042 1043 1044 void AllocationSite::SetElementsKind(ElementsKind kind) { 1045 set_transition_info(ElementsKindBits::update(transition_info(), kind)); 1046 } 1047 1048 bool AllocationSite::CanInlineCall() const { 1049 return DoNotInlineBit::decode(transition_info()) == 0; 1050 } 1051 1052 1053 void AllocationSite::SetDoNotInlineCall() { 1054 set_transition_info(DoNotInlineBit::update(transition_info(), true)); 1055 } 1056 1057 bool AllocationSite::PointsToLiteral() const { 1058 Object* raw_value = transition_info_or_boilerplate(); 1059 DCHECK_EQ(!raw_value->IsSmi(), 1060 raw_value->IsJSArray() || raw_value->IsJSObject()); 1061 return !raw_value->IsSmi(); 1062 } 1063 1064 1065 // Heuristic: We only need to create allocation site info if the boilerplate 1066 // elements kind is the initial elements kind. 1067 bool AllocationSite::ShouldTrack(ElementsKind boilerplate_elements_kind) { 1068 return IsSmiElementsKind(boilerplate_elements_kind); 1069 } 1070 1071 inline bool AllocationSite::CanTrack(InstanceType type) { 1072 if (FLAG_allocation_site_pretenuring) { 1073 // TurboFan doesn't care at all about String pretenuring feedback, 1074 // so don't bother even trying to track that. 1075 return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE; 1076 } 1077 return type == JS_ARRAY_TYPE; 1078 } 1079 1080 AllocationSite::PretenureDecision AllocationSite::pretenure_decision() const { 1081 return PretenureDecisionBits::decode(pretenure_data()); 1082 } 1083 1084 void AllocationSite::set_pretenure_decision(PretenureDecision decision) { 1085 int32_t value = pretenure_data(); 1086 set_pretenure_data(PretenureDecisionBits::update(value, decision)); 1087 } 1088 1089 bool AllocationSite::deopt_dependent_code() const { 1090 return DeoptDependentCodeBit::decode(pretenure_data()); 1091 } 1092 1093 void AllocationSite::set_deopt_dependent_code(bool deopt) { 1094 int32_t value = pretenure_data(); 1095 set_pretenure_data(DeoptDependentCodeBit::update(value, deopt)); 1096 } 1097 1098 int AllocationSite::memento_found_count() const { 1099 return MementoFoundCountBits::decode(pretenure_data()); 1100 } 1101 1102 inline void AllocationSite::set_memento_found_count(int count) { 1103 int32_t value = pretenure_data(); 1104 // Verify that we can count more mementos than we can possibly find in one 1105 // new space collection. 1106 DCHECK((GetHeap()->MaxSemiSpaceSize() / 1107 (Heap::kMinObjectSizeInWords * kPointerSize + 1108 AllocationMemento::kSize)) < MementoFoundCountBits::kMax); 1109 DCHECK_LT(count, MementoFoundCountBits::kMax); 1110 set_pretenure_data(MementoFoundCountBits::update(value, count)); 1111 } 1112 1113 int AllocationSite::memento_create_count() const { 1114 return pretenure_create_count(); 1115 } 1116 1117 void AllocationSite::set_memento_create_count(int count) { 1118 set_pretenure_create_count(count); 1119 } 1120 1121 bool AllocationSite::IncrementMementoFoundCount(int increment) { 1122 if (IsZombie()) return false; 1123 1124 int value = memento_found_count(); 1125 set_memento_found_count(value + increment); 1126 return memento_found_count() >= kPretenureMinimumCreated; 1127 } 1128 1129 1130 inline void AllocationSite::IncrementMementoCreateCount() { 1131 DCHECK(FLAG_allocation_site_pretenuring); 1132 int value = memento_create_count(); 1133 set_memento_create_count(value + 1); 1134 } 1135 1136 bool AllocationMemento::IsValid() const { 1137 return allocation_site()->IsAllocationSite() && 1138 !AllocationSite::cast(allocation_site())->IsZombie(); 1139 } 1140 1141 AllocationSite* AllocationMemento::GetAllocationSite() const { 1142 DCHECK(IsValid()); 1143 return AllocationSite::cast(allocation_site()); 1144 } 1145 1146 Address AllocationMemento::GetAllocationSiteUnchecked() const { 1147 return reinterpret_cast<Address>(allocation_site()); 1148 } 1149 1150 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) { 1151 JSObject::ValidateElements(*object); 1152 ElementsKind elements_kind = object->map()->elements_kind(); 1153 if (!IsObjectElementsKind(elements_kind)) { 1154 if (IsHoleyElementsKind(elements_kind)) { 1155 TransitionElementsKind(object, HOLEY_ELEMENTS); 1156 } else { 1157 TransitionElementsKind(object, PACKED_ELEMENTS); 1158 } 1159 } 1160 } 1161 1162 1163 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1164 Object** objects, 1165 uint32_t count, 1166 EnsureElementsMode mode) { 1167 ElementsKind current_kind = object->GetElementsKind(); 1168 ElementsKind target_kind = current_kind; 1169 { 1170 DisallowHeapAllocation no_allocation; 1171 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS); 1172 bool is_holey = IsHoleyElementsKind(current_kind); 1173 if (current_kind == HOLEY_ELEMENTS) return; 1174 Object* the_hole = object->GetReadOnlyRoots().the_hole_value(); 1175 for (uint32_t i = 0; i < count; ++i) { 1176 Object* current = *objects++; 1177 if (current == the_hole) { 1178 is_holey = true; 1179 target_kind = GetHoleyElementsKind(target_kind); 1180 } else if (!current->IsSmi()) { 1181 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) { 1182 if (IsSmiElementsKind(target_kind)) { 1183 if (is_holey) { 1184 target_kind = HOLEY_DOUBLE_ELEMENTS; 1185 } else { 1186 target_kind = PACKED_DOUBLE_ELEMENTS; 1187 } 1188 } 1189 } else if (is_holey) { 1190 target_kind = HOLEY_ELEMENTS; 1191 break; 1192 } else { 1193 target_kind = PACKED_ELEMENTS; 1194 } 1195 } 1196 } 1197 } 1198 if (target_kind != current_kind) { 1199 TransitionElementsKind(object, target_kind); 1200 } 1201 } 1202 1203 1204 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1205 Handle<FixedArrayBase> elements, 1206 uint32_t length, 1207 EnsureElementsMode mode) { 1208 ReadOnlyRoots roots = object->GetReadOnlyRoots(); 1209 if (elements->map() != roots.fixed_double_array_map()) { 1210 DCHECK(elements->map() == roots.fixed_array_map() || 1211 elements->map() == roots.fixed_cow_array_map()); 1212 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) { 1213 mode = DONT_ALLOW_DOUBLE_ELEMENTS; 1214 } 1215 Object** objects = 1216 Handle<FixedArray>::cast(elements)->GetFirstElementAddress(); 1217 EnsureCanContainElements(object, objects, length, mode); 1218 return; 1219 } 1220 1221 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS); 1222 if (object->GetElementsKind() == HOLEY_SMI_ELEMENTS) { 1223 TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS); 1224 } else if (object->GetElementsKind() == PACKED_SMI_ELEMENTS) { 1225 Handle<FixedDoubleArray> double_array = 1226 Handle<FixedDoubleArray>::cast(elements); 1227 for (uint32_t i = 0; i < length; ++i) { 1228 if (double_array->is_the_hole(i)) { 1229 TransitionElementsKind(object, HOLEY_DOUBLE_ELEMENTS); 1230 return; 1231 } 1232 } 1233 TransitionElementsKind(object, PACKED_DOUBLE_ELEMENTS); 1234 } 1235 } 1236 1237 1238 void JSObject::SetMapAndElements(Handle<JSObject> object, 1239 Handle<Map> new_map, 1240 Handle<FixedArrayBase> value) { 1241 JSObject::MigrateToMap(object, new_map); 1242 DCHECK((object->map()->has_fast_smi_or_object_elements() || 1243 (*value == object->GetReadOnlyRoots().empty_fixed_array()) || 1244 object->map()->has_fast_string_wrapper_elements()) == 1245 (value->map() == object->GetReadOnlyRoots().fixed_array_map() || 1246 value->map() == object->GetReadOnlyRoots().fixed_cow_array_map())); 1247 DCHECK((*value == object->GetReadOnlyRoots().empty_fixed_array()) || 1248 (object->map()->has_fast_double_elements() == 1249 value->IsFixedDoubleArray())); 1250 object->set_elements(*value); 1251 } 1252 1253 1254 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { 1255 WRITE_FIELD(this, kElementsOffset, value); 1256 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, value, mode); 1257 } 1258 1259 1260 void JSObject::initialize_elements() { 1261 FixedArrayBase* elements = map()->GetInitialElements(); 1262 WRITE_FIELD(this, kElementsOffset, elements); 1263 } 1264 1265 1266 InterceptorInfo* JSObject::GetIndexedInterceptor() { 1267 return map()->GetIndexedInterceptor(); 1268 } 1269 1270 InterceptorInfo* JSObject::GetNamedInterceptor() { 1271 return map()->GetNamedInterceptor(); 1272 } 1273 1274 double Oddball::to_number_raw() const { 1275 return READ_DOUBLE_FIELD(this, kToNumberRawOffset); 1276 } 1277 1278 void Oddball::set_to_number_raw(double value) { 1279 WRITE_DOUBLE_FIELD(this, kToNumberRawOffset, value); 1280 } 1281 1282 void Oddball::set_to_number_raw_as_bits(uint64_t bits) { 1283 WRITE_UINT64_FIELD(this, kToNumberRawOffset, bits); 1284 } 1285 1286 ACCESSORS(Oddball, to_string, String, kToStringOffset) 1287 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) 1288 ACCESSORS(Oddball, type_of, String, kTypeOfOffset) 1289 1290 byte Oddball::kind() const { return Smi::ToInt(READ_FIELD(this, kKindOffset)); } 1291 1292 void Oddball::set_kind(byte value) { 1293 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value)); 1294 } 1295 1296 1297 // static 1298 Handle<Object> Oddball::ToNumber(Isolate* isolate, Handle<Oddball> input) { 1299 return handle(input->to_number(), isolate); 1300 } 1301 1302 1303 ACCESSORS(Cell, value, Object, kValueOffset) 1304 ACCESSORS(FeedbackCell, value, HeapObject, kValueOffset) 1305 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset) 1306 ACCESSORS(PropertyCell, name, Name, kNameOffset) 1307 ACCESSORS(PropertyCell, value, Object, kValueOffset) 1308 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset) 1309 1310 PropertyDetails PropertyCell::property_details() const { 1311 return PropertyDetails(Smi::cast(property_details_raw())); 1312 } 1313 1314 1315 void PropertyCell::set_property_details(PropertyDetails details) { 1316 set_property_details_raw(details.AsSmi()); 1317 } 1318 1319 int JSObject::GetHeaderSize() const { return GetHeaderSize(map()); } 1320 1321 int JSObject::GetHeaderSize(const Map* map) { 1322 // Check for the most common kind of JavaScript object before 1323 // falling into the generic switch. This speeds up the internal 1324 // field operations considerably on average. 1325 InstanceType instance_type = map->instance_type(); 1326 return instance_type == JS_OBJECT_TYPE 1327 ? JSObject::kHeaderSize 1328 : GetHeaderSize(instance_type, map->has_prototype_slot()); 1329 } 1330 1331 inline bool IsSpecialReceiverInstanceType(InstanceType instance_type) { 1332 return instance_type <= LAST_SPECIAL_RECEIVER_TYPE; 1333 } 1334 1335 // This should be in objects/map-inl.h, but can't, because of a cyclic 1336 // dependency. 1337 bool Map::IsSpecialReceiverMap() const { 1338 bool result = IsSpecialReceiverInstanceType(instance_type()); 1339 DCHECK_IMPLIES(!result, 1340 !has_named_interceptor() && !is_access_check_needed()); 1341 return result; 1342 } 1343 1344 inline bool IsCustomElementsReceiverInstanceType(InstanceType instance_type) { 1345 return instance_type <= LAST_CUSTOM_ELEMENTS_RECEIVER; 1346 } 1347 1348 // This should be in objects/map-inl.h, but can't, because of a cyclic 1349 // dependency. 1350 bool Map::IsCustomElementsReceiverMap() const { 1351 return IsCustomElementsReceiverInstanceType(instance_type()); 1352 } 1353 1354 // static 1355 int JSObject::GetEmbedderFieldCount(const Map* map) { 1356 int instance_size = map->instance_size(); 1357 if (instance_size == kVariableSizeSentinel) return 0; 1358 return ((instance_size - GetHeaderSize(map)) >> kPointerSizeLog2) - 1359 map->GetInObjectProperties(); 1360 } 1361 1362 int JSObject::GetEmbedderFieldCount() const { 1363 return GetEmbedderFieldCount(map()); 1364 } 1365 1366 int JSObject::GetEmbedderFieldOffset(int index) { 1367 DCHECK(index < GetEmbedderFieldCount() && index >= 0); 1368 return GetHeaderSize() + (kPointerSize * index); 1369 } 1370 1371 Object* JSObject::GetEmbedderField(int index) { 1372 DCHECK(index < GetEmbedderFieldCount() && index >= 0); 1373 // Internal objects do follow immediately after the header, whereas in-object 1374 // properties are at the end of the object. Therefore there is no need 1375 // to adjust the index here. 1376 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); 1377 } 1378 1379 void JSObject::SetEmbedderField(int index, Object* value) { 1380 DCHECK(index < GetEmbedderFieldCount() && index >= 0); 1381 // Internal objects do follow immediately after the header, whereas in-object 1382 // properties are at the end of the object. Therefore there is no need 1383 // to adjust the index here. 1384 int offset = GetHeaderSize() + (kPointerSize * index); 1385 WRITE_FIELD(this, offset, value); 1386 WRITE_BARRIER(this, offset, value); 1387 } 1388 1389 void JSObject::SetEmbedderField(int index, Smi* value) { 1390 DCHECK(index < GetEmbedderFieldCount() && index >= 0); 1391 // Internal objects do follow immediately after the header, whereas in-object 1392 // properties are at the end of the object. Therefore there is no need 1393 // to adjust the index here. 1394 int offset = GetHeaderSize() + (kPointerSize * index); 1395 WRITE_FIELD(this, offset, value); 1396 } 1397 1398 1399 bool JSObject::IsUnboxedDoubleField(FieldIndex index) { 1400 if (!FLAG_unbox_double_fields) return false; 1401 return map()->IsUnboxedDoubleField(index); 1402 } 1403 1404 // Access fast-case object properties at index. The use of these routines 1405 // is needed to correctly distinguish between properties stored in-object and 1406 // properties stored in the properties array. 1407 Object* JSObject::RawFastPropertyAt(FieldIndex index) { 1408 DCHECK(!IsUnboxedDoubleField(index)); 1409 if (index.is_inobject()) { 1410 return READ_FIELD(this, index.offset()); 1411 } else { 1412 return property_array()->get(index.outobject_array_index()); 1413 } 1414 } 1415 1416 1417 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { 1418 DCHECK(IsUnboxedDoubleField(index)); 1419 return READ_DOUBLE_FIELD(this, index.offset()); 1420 } 1421 1422 uint64_t JSObject::RawFastDoublePropertyAsBitsAt(FieldIndex index) { 1423 DCHECK(IsUnboxedDoubleField(index)); 1424 return READ_UINT64_FIELD(this, index.offset()); 1425 } 1426 1427 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { 1428 if (index.is_inobject()) { 1429 int offset = index.offset(); 1430 WRITE_FIELD(this, offset, value); 1431 WRITE_BARRIER(this, offset, value); 1432 } else { 1433 property_array()->set(index.outobject_array_index(), value); 1434 } 1435 } 1436 1437 void JSObject::RawFastDoublePropertyAsBitsAtPut(FieldIndex index, 1438 uint64_t bits) { 1439 // Double unboxing is enabled only on 64-bit platforms. 1440 DCHECK_EQ(kDoubleSize, kPointerSize); 1441 Address field_addr = FIELD_ADDR(this, index.offset()); 1442 base::Relaxed_Store(reinterpret_cast<base::AtomicWord*>(field_addr), 1443 static_cast<base::AtomicWord>(bits)); 1444 } 1445 1446 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { 1447 if (IsUnboxedDoubleField(index)) { 1448 DCHECK(value->IsMutableHeapNumber()); 1449 // Ensure that all bits of the double value are preserved. 1450 RawFastDoublePropertyAsBitsAtPut( 1451 index, MutableHeapNumber::cast(value)->value_as_bits()); 1452 } else { 1453 RawFastPropertyAtPut(index, value); 1454 } 1455 } 1456 1457 void JSObject::WriteToField(int descriptor, PropertyDetails details, 1458 Object* value) { 1459 DCHECK_EQ(kField, details.location()); 1460 DCHECK_EQ(kData, details.kind()); 1461 DisallowHeapAllocation no_gc; 1462 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); 1463 if (details.representation().IsDouble()) { 1464 // Nothing more to be done. 1465 if (value->IsUninitialized()) { 1466 return; 1467 } 1468 // Manipulating the signaling NaN used for the hole and uninitialized 1469 // double field sentinel in C++, e.g. with bit_cast or value()/set_value(), 1470 // will change its value on ia32 (the x87 stack is used to return values 1471 // and stores to the stack silently clear the signalling bit). 1472 uint64_t bits; 1473 if (value->IsSmi()) { 1474 bits = bit_cast<uint64_t>(static_cast<double>(Smi::ToInt(value))); 1475 } else { 1476 DCHECK(value->IsHeapNumber()); 1477 bits = HeapNumber::cast(value)->value_as_bits(); 1478 } 1479 if (IsUnboxedDoubleField(index)) { 1480 RawFastDoublePropertyAsBitsAtPut(index, bits); 1481 } else { 1482 auto box = MutableHeapNumber::cast(RawFastPropertyAt(index)); 1483 box->set_value_as_bits(bits); 1484 } 1485 } else { 1486 RawFastPropertyAtPut(index, value); 1487 } 1488 } 1489 1490 int JSObject::GetInObjectPropertyOffset(int index) { 1491 return map()->GetInObjectPropertyOffset(index); 1492 } 1493 1494 1495 Object* JSObject::InObjectPropertyAt(int index) { 1496 int offset = GetInObjectPropertyOffset(index); 1497 return READ_FIELD(this, offset); 1498 } 1499 1500 1501 Object* JSObject::InObjectPropertyAtPut(int index, 1502 Object* value, 1503 WriteBarrierMode mode) { 1504 // Adjust for the number of properties stored in the object. 1505 int offset = GetInObjectPropertyOffset(index); 1506 WRITE_FIELD(this, offset, value); 1507 CONDITIONAL_WRITE_BARRIER(this, offset, value, mode); 1508 return value; 1509 } 1510 1511 1512 void JSObject::InitializeBody(Map* map, int start_offset, 1513 Object* pre_allocated_value, 1514 Object* filler_value) { 1515 DCHECK(!filler_value->IsHeapObject() || !Heap::InNewSpace(filler_value)); 1516 DCHECK(!pre_allocated_value->IsHeapObject() || 1517 !Heap::InNewSpace(pre_allocated_value)); 1518 int size = map->instance_size(); 1519 int offset = start_offset; 1520 if (filler_value != pre_allocated_value) { 1521 int end_of_pre_allocated_offset = 1522 size - (map->UnusedPropertyFields() * kPointerSize); 1523 DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset); 1524 while (offset < end_of_pre_allocated_offset) { 1525 WRITE_FIELD(this, offset, pre_allocated_value); 1526 offset += kPointerSize; 1527 } 1528 } 1529 while (offset < size) { 1530 WRITE_FIELD(this, offset, filler_value); 1531 offset += kPointerSize; 1532 } 1533 } 1534 1535 void Struct::InitializeBody(int object_size) { 1536 Object* value = GetReadOnlyRoots().undefined_value(); 1537 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 1538 WRITE_FIELD(this, offset, value); 1539 } 1540 } 1541 1542 bool Object::ToArrayLength(uint32_t* index) const { 1543 return Object::ToUint32(index); 1544 } 1545 1546 bool Object::ToArrayIndex(uint32_t* index) const { 1547 return Object::ToUint32(index) && *index != kMaxUInt32; 1548 } 1549 1550 1551 void Object::VerifyApiCallResultType() { 1552 #if DEBUG 1553 if (IsSmi()) return; 1554 DCHECK(IsHeapObject()); 1555 if (!(IsString() || IsSymbol() || IsJSReceiver() || IsHeapNumber() || 1556 IsBigInt() || IsUndefined() || IsTrue() || IsFalse() || IsNull())) { 1557 FATAL("API call returned invalid object"); 1558 } 1559 #endif // DEBUG 1560 } 1561 1562 Object* PropertyArray::get(int index) const { 1563 DCHECK_GE(index, 0); 1564 DCHECK_LE(index, this->length()); 1565 return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize); 1566 } 1567 1568 void PropertyArray::set(int index, Object* value) { 1569 DCHECK(IsPropertyArray()); 1570 DCHECK_GE(index, 0); 1571 DCHECK_LT(index, this->length()); 1572 int offset = kHeaderSize + index * kPointerSize; 1573 RELAXED_WRITE_FIELD(this, offset, value); 1574 WRITE_BARRIER(this, offset, value); 1575 } 1576 1577 int RegExpMatchInfo::NumberOfCaptureRegisters() { 1578 DCHECK_GE(length(), kLastMatchOverhead); 1579 Object* obj = get(kNumberOfCapturesIndex); 1580 return Smi::ToInt(obj); 1581 } 1582 1583 void RegExpMatchInfo::SetNumberOfCaptureRegisters(int value) { 1584 DCHECK_GE(length(), kLastMatchOverhead); 1585 set(kNumberOfCapturesIndex, Smi::FromInt(value)); 1586 } 1587 1588 String* RegExpMatchInfo::LastSubject() { 1589 DCHECK_GE(length(), kLastMatchOverhead); 1590 Object* obj = get(kLastSubjectIndex); 1591 return String::cast(obj); 1592 } 1593 1594 void RegExpMatchInfo::SetLastSubject(String* value) { 1595 DCHECK_GE(length(), kLastMatchOverhead); 1596 set(kLastSubjectIndex, value); 1597 } 1598 1599 Object* RegExpMatchInfo::LastInput() { 1600 DCHECK_GE(length(), kLastMatchOverhead); 1601 return get(kLastInputIndex); 1602 } 1603 1604 void RegExpMatchInfo::SetLastInput(Object* value) { 1605 DCHECK_GE(length(), kLastMatchOverhead); 1606 set(kLastInputIndex, value); 1607 } 1608 1609 int RegExpMatchInfo::Capture(int i) { 1610 DCHECK_LT(i, NumberOfCaptureRegisters()); 1611 Object* obj = get(kFirstCaptureIndex + i); 1612 return Smi::ToInt(obj); 1613 } 1614 1615 void RegExpMatchInfo::SetCapture(int i, int value) { 1616 DCHECK_LT(i, NumberOfCaptureRegisters()); 1617 set(kFirstCaptureIndex + i, Smi::FromInt(value)); 1618 } 1619 1620 WriteBarrierMode HeapObject::GetWriteBarrierMode( 1621 const DisallowHeapAllocation& promise) { 1622 Heap* heap = Heap::FromWritableHeapObject(this); 1623 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER; 1624 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER; 1625 return UPDATE_WRITE_BARRIER; 1626 } 1627 1628 AllocationAlignment HeapObject::RequiredAlignment(Map* map) { 1629 #ifdef V8_HOST_ARCH_32_BIT 1630 int instance_type = map->instance_type(); 1631 if (instance_type == FIXED_FLOAT64_ARRAY_TYPE || 1632 instance_type == FIXED_DOUBLE_ARRAY_TYPE) { 1633 return kDoubleAligned; 1634 } 1635 if (instance_type == HEAP_NUMBER_TYPE) return kDoubleUnaligned; 1636 #endif // V8_HOST_ARCH_32_BIT 1637 return kWordAligned; 1638 } 1639 1640 bool HeapObject::NeedsRehashing() const { 1641 switch (map()->instance_type()) { 1642 case DESCRIPTOR_ARRAY_TYPE: 1643 return DescriptorArray::cast(this)->number_of_descriptors() > 1; 1644 case TRANSITION_ARRAY_TYPE: 1645 return TransitionArray::cast(this)->number_of_entries() > 1; 1646 case ORDERED_HASH_MAP_TYPE: 1647 return OrderedHashMap::cast(this)->NumberOfElements() > 0; 1648 case ORDERED_HASH_SET_TYPE: 1649 return OrderedHashSet::cast(this)->NumberOfElements() > 0; 1650 case NAME_DICTIONARY_TYPE: 1651 case GLOBAL_DICTIONARY_TYPE: 1652 case NUMBER_DICTIONARY_TYPE: 1653 case SIMPLE_NUMBER_DICTIONARY_TYPE: 1654 case STRING_TABLE_TYPE: 1655 case HASH_TABLE_TYPE: 1656 case SMALL_ORDERED_HASH_MAP_TYPE: 1657 case SMALL_ORDERED_HASH_SET_TYPE: 1658 return true; 1659 default: 1660 return false; 1661 } 1662 } 1663 1664 Address HeapObject::GetFieldAddress(int field_offset) const { 1665 return FIELD_ADDR(this, field_offset); 1666 } 1667 1668 void PropertyArray::set(int index, Object* value, WriteBarrierMode mode) { 1669 DCHECK_GE(index, 0); 1670 DCHECK_LT(index, this->length()); 1671 int offset = kHeaderSize + index * kPointerSize; 1672 RELAXED_WRITE_FIELD(this, offset, value); 1673 CONDITIONAL_WRITE_BARRIER(this, offset, value, mode); 1674 } 1675 1676 Object** PropertyArray::data_start() { 1677 return HeapObject::RawField(this, kHeaderSize); 1678 } 1679 1680 ACCESSORS(EnumCache, keys, FixedArray, kKeysOffset) 1681 ACCESSORS(EnumCache, indices, FixedArray, kIndicesOffset) 1682 1683 int DescriptorArray::number_of_descriptors() const { 1684 return Smi::ToInt(get(kDescriptorLengthIndex)->ToSmi()); 1685 } 1686 1687 int DescriptorArray::number_of_descriptors_storage() const { 1688 return (length() - kFirstIndex) / kEntrySize; 1689 } 1690 1691 int DescriptorArray::NumberOfSlackDescriptors() const { 1692 return number_of_descriptors_storage() - number_of_descriptors(); 1693 } 1694 1695 1696 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { 1697 set(kDescriptorLengthIndex, 1698 MaybeObject::FromObject(Smi::FromInt(number_of_descriptors))); 1699 } 1700 1701 inline int DescriptorArray::number_of_entries() const { 1702 return number_of_descriptors(); 1703 } 1704 1705 void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) { 1706 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); 1707 } 1708 1709 EnumCache* DescriptorArray::GetEnumCache() { 1710 return EnumCache::cast(get(kEnumCacheIndex)->ToStrongHeapObject()); 1711 } 1712 1713 // Perform a binary search in a fixed array. 1714 template <SearchMode search_mode, typename T> 1715 int BinarySearch(T* array, Name* name, int valid_entries, 1716 int* out_insertion_index) { 1717 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr); 1718 int low = 0; 1719 int high = array->number_of_entries() - 1; 1720 uint32_t hash = name->hash_field(); 1721 int limit = high; 1722 1723 DCHECK(low <= high); 1724 1725 while (low != high) { 1726 int mid = low + (high - low) / 2; 1727 Name* mid_name = array->GetSortedKey(mid); 1728 uint32_t mid_hash = mid_name->hash_field(); 1729 1730 if (mid_hash >= hash) { 1731 high = mid; 1732 } else { 1733 low = mid + 1; 1734 } 1735 } 1736 1737 for (; low <= limit; ++low) { 1738 int sort_index = array->GetSortedKeyIndex(low); 1739 Name* entry = array->GetKey(sort_index); 1740 uint32_t current_hash = entry->hash_field(); 1741 if (current_hash != hash) { 1742 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 1743 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); 1744 } 1745 return T::kNotFound; 1746 } 1747 if (entry == name) { 1748 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) { 1749 return sort_index; 1750 } 1751 return T::kNotFound; 1752 } 1753 } 1754 1755 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 1756 *out_insertion_index = limit + 1; 1757 } 1758 return T::kNotFound; 1759 } 1760 1761 1762 // Perform a linear search in this fixed array. len is the number of entry 1763 // indices that are valid. 1764 template <SearchMode search_mode, typename T> 1765 int LinearSearch(T* array, Name* name, int valid_entries, 1766 int* out_insertion_index) { 1767 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 1768 uint32_t hash = name->hash_field(); 1769 int len = array->number_of_entries(); 1770 for (int number = 0; number < len; number++) { 1771 int sorted_index = array->GetSortedKeyIndex(number); 1772 Name* entry = array->GetKey(sorted_index); 1773 uint32_t current_hash = entry->hash_field(); 1774 if (current_hash > hash) { 1775 *out_insertion_index = sorted_index; 1776 return T::kNotFound; 1777 } 1778 if (entry == name) return sorted_index; 1779 } 1780 *out_insertion_index = len; 1781 return T::kNotFound; 1782 } else { 1783 DCHECK_LE(valid_entries, array->number_of_entries()); 1784 DCHECK_NULL(out_insertion_index); // Not supported here. 1785 for (int number = 0; number < valid_entries; number++) { 1786 if (array->GetKey(number) == name) return number; 1787 } 1788 return T::kNotFound; 1789 } 1790 } 1791 1792 template <SearchMode search_mode, typename T> 1793 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) { 1794 SLOW_DCHECK(array->IsSortedNoDuplicates()); 1795 1796 if (valid_entries == 0) { 1797 if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) { 1798 *out_insertion_index = 0; 1799 } 1800 return T::kNotFound; 1801 } 1802 1803 // Fast case: do linear search for small arrays. 1804 const int kMaxElementsForLinearSearch = 8; 1805 if (valid_entries <= kMaxElementsForLinearSearch) { 1806 return LinearSearch<search_mode>(array, name, valid_entries, 1807 out_insertion_index); 1808 } 1809 1810 // Slow case: perform binary search. 1811 return BinarySearch<search_mode>(array, name, valid_entries, 1812 out_insertion_index); 1813 } 1814 1815 1816 int DescriptorArray::Search(Name* name, int valid_descriptors) { 1817 DCHECK(name->IsUniqueName()); 1818 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, 1819 nullptr); 1820 } 1821 1822 int DescriptorArray::Search(Name* name, Map* map) { 1823 DCHECK(name->IsUniqueName()); 1824 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 1825 if (number_of_own_descriptors == 0) return kNotFound; 1826 return Search(name, number_of_own_descriptors); 1827 } 1828 1829 int DescriptorArray::SearchWithCache(Isolate* isolate, Name* name, Map* map) { 1830 DCHECK(name->IsUniqueName()); 1831 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 1832 if (number_of_own_descriptors == 0) return kNotFound; 1833 1834 DescriptorLookupCache* cache = isolate->descriptor_lookup_cache(); 1835 int number = cache->Lookup(map, name); 1836 1837 if (number == DescriptorLookupCache::kAbsent) { 1838 number = Search(name, number_of_own_descriptors); 1839 cache->Update(map, name, number); 1840 } 1841 1842 return number; 1843 } 1844 1845 1846 Object** DescriptorArray::GetKeySlot(int descriptor_number) { 1847 DCHECK(descriptor_number < number_of_descriptors()); 1848 DCHECK((*RawFieldOfElementAt(ToKeyIndex(descriptor_number)))->IsObject()); 1849 return reinterpret_cast<Object**>( 1850 RawFieldOfElementAt(ToKeyIndex(descriptor_number))); 1851 } 1852 1853 MaybeObject** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { 1854 return reinterpret_cast<MaybeObject**>(GetKeySlot(descriptor_number)); 1855 } 1856 1857 MaybeObject** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) { 1858 return GetValueSlot(descriptor_number - 1) + 1; 1859 } 1860 1861 1862 Name* DescriptorArray::GetKey(int descriptor_number) { 1863 DCHECK(descriptor_number < number_of_descriptors()); 1864 return Name::cast(get(ToKeyIndex(descriptor_number))->ToStrongHeapObject()); 1865 } 1866 1867 1868 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) { 1869 return GetDetails(descriptor_number).pointer(); 1870 } 1871 1872 1873 Name* DescriptorArray::GetSortedKey(int descriptor_number) { 1874 return GetKey(GetSortedKeyIndex(descriptor_number)); 1875 } 1876 1877 1878 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) { 1879 PropertyDetails details = GetDetails(descriptor_index); 1880 set(ToDetailsIndex(descriptor_index), 1881 MaybeObject::FromObject(details.set_pointer(pointer).AsSmi())); 1882 } 1883 1884 MaybeObject** DescriptorArray::GetValueSlot(int descriptor_number) { 1885 DCHECK(descriptor_number < number_of_descriptors()); 1886 return RawFieldOfElementAt(ToValueIndex(descriptor_number)); 1887 } 1888 1889 1890 int DescriptorArray::GetValueOffset(int descriptor_number) { 1891 return OffsetOfElementAt(ToValueIndex(descriptor_number)); 1892 } 1893 1894 Object* DescriptorArray::GetStrongValue(int descriptor_number) { 1895 DCHECK(descriptor_number < number_of_descriptors()); 1896 return get(ToValueIndex(descriptor_number))->ToObject(); 1897 } 1898 1899 1900 void DescriptorArray::SetValue(int descriptor_index, Object* value) { 1901 set(ToValueIndex(descriptor_index), MaybeObject::FromObject(value)); 1902 } 1903 1904 MaybeObject* DescriptorArray::GetValue(int descriptor_number) { 1905 DCHECK_LT(descriptor_number, number_of_descriptors()); 1906 return get(ToValueIndex(descriptor_number)); 1907 } 1908 1909 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { 1910 DCHECK(descriptor_number < number_of_descriptors()); 1911 MaybeObject* details = get(ToDetailsIndex(descriptor_number)); 1912 return PropertyDetails(details->ToSmi()); 1913 } 1914 1915 int DescriptorArray::GetFieldIndex(int descriptor_number) { 1916 DCHECK_EQ(GetDetails(descriptor_number).location(), kField); 1917 return GetDetails(descriptor_number).field_index(); 1918 } 1919 1920 FieldType* DescriptorArray::GetFieldType(int descriptor_number) { 1921 DCHECK_EQ(GetDetails(descriptor_number).location(), kField); 1922 MaybeObject* wrapped_type = GetValue(descriptor_number); 1923 return Map::UnwrapFieldType(wrapped_type); 1924 } 1925 1926 void DescriptorArray::Set(int descriptor_number, Name* key, MaybeObject* value, 1927 PropertyDetails details) { 1928 // Range check. 1929 DCHECK(descriptor_number < number_of_descriptors()); 1930 set(ToKeyIndex(descriptor_number), MaybeObject::FromObject(key)); 1931 set(ToValueIndex(descriptor_number), value); 1932 set(ToDetailsIndex(descriptor_number), 1933 MaybeObject::FromObject(details.AsSmi())); 1934 } 1935 1936 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { 1937 Name* key = *desc->GetKey(); 1938 MaybeObject* value = *desc->GetValue(); 1939 Set(descriptor_number, key, value, desc->GetDetails()); 1940 } 1941 1942 1943 void DescriptorArray::Append(Descriptor* desc) { 1944 DisallowHeapAllocation no_gc; 1945 int descriptor_number = number_of_descriptors(); 1946 SetNumberOfDescriptors(descriptor_number + 1); 1947 Set(descriptor_number, desc); 1948 1949 uint32_t hash = desc->GetKey()->Hash(); 1950 1951 int insertion; 1952 1953 for (insertion = descriptor_number; insertion > 0; --insertion) { 1954 Name* key = GetSortedKey(insertion - 1); 1955 if (key->Hash() <= hash) break; 1956 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); 1957 } 1958 1959 SetSortedKey(insertion, descriptor_number); 1960 } 1961 1962 1963 void DescriptorArray::SwapSortedKeys(int first, int second) { 1964 int first_key = GetSortedKeyIndex(first); 1965 SetSortedKey(first, GetSortedKeyIndex(second)); 1966 SetSortedKey(second, first_key); 1967 } 1968 1969 MaybeObject* DescriptorArray::get(int index) const { 1970 return WeakFixedArray::Get(index); 1971 } 1972 1973 void DescriptorArray::set(int index, MaybeObject* value) { 1974 WeakFixedArray::Set(index, value); 1975 } 1976 1977 bool StringSetShape::IsMatch(String* key, Object* value) { 1978 DCHECK(value->IsString()); 1979 return key->Equals(String::cast(value)); 1980 } 1981 1982 uint32_t StringSetShape::Hash(Isolate* isolate, String* key) { 1983 return key->Hash(); 1984 } 1985 1986 uint32_t StringSetShape::HashForObject(Isolate* isolate, Object* object) { 1987 return String::cast(object)->Hash(); 1988 } 1989 1990 StringTableKey::StringTableKey(uint32_t hash_field) 1991 : HashTableKey(hash_field >> Name::kHashShift), hash_field_(hash_field) {} 1992 1993 void StringTableKey::set_hash_field(uint32_t hash_field) { 1994 hash_field_ = hash_field; 1995 set_hash(hash_field >> Name::kHashShift); 1996 } 1997 1998 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, 1999 StringTableKey* key) { 2000 return key->AsHandle(isolate); 2001 } 2002 2003 uint32_t StringTableShape::HashForObject(Isolate* isolate, Object* object) { 2004 return String::cast(object)->Hash(); 2005 } 2006 2007 int StringTableShape::GetMapRootIndex() { 2008 return Heap::kStringTableMapRootIndex; 2009 } 2010 2011 bool NumberDictionary::requires_slow_elements() { 2012 Object* max_index_object = get(kMaxNumberKeyIndex); 2013 if (!max_index_object->IsSmi()) return false; 2014 return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask); 2015 } 2016 2017 uint32_t NumberDictionary::max_number_key() { 2018 DCHECK(!requires_slow_elements()); 2019 Object* max_index_object = get(kMaxNumberKeyIndex); 2020 if (!max_index_object->IsSmi()) return 0; 2021 uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object)); 2022 return value >> kRequiresSlowElementsTagSize; 2023 } 2024 2025 void NumberDictionary::set_requires_slow_elements() { 2026 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); 2027 } 2028 2029 DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray) 2030 DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) 2031 DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray) 2032 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi) 2033 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi) 2034 DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi) 2035 DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>) 2036 2037 DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi) 2038 DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi) 2039 DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi) 2040 2041 int PropertyArray::length() const { 2042 Object* value_obj = READ_FIELD(this, kLengthAndHashOffset); 2043 int value = Smi::ToInt(value_obj); 2044 return LengthField::decode(value); 2045 } 2046 2047 void PropertyArray::initialize_length(int len) { 2048 SLOW_DCHECK(len >= 0); 2049 SLOW_DCHECK(len < LengthField::kMax); 2050 WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(len)); 2051 } 2052 2053 int PropertyArray::synchronized_length() const { 2054 Object* value_obj = ACQUIRE_READ_FIELD(this, kLengthAndHashOffset); 2055 int value = Smi::ToInt(value_obj); 2056 return LengthField::decode(value); 2057 } 2058 2059 int PropertyArray::Hash() const { 2060 Object* value_obj = READ_FIELD(this, kLengthAndHashOffset); 2061 int value = Smi::ToInt(value_obj); 2062 return HashField::decode(value); 2063 } 2064 2065 void PropertyArray::SetHash(int hash) { 2066 Object* value_obj = READ_FIELD(this, kLengthAndHashOffset); 2067 int value = Smi::ToInt(value_obj); 2068 value = HashField::update(value, hash); 2069 WRITE_FIELD(this, kLengthAndHashOffset, Smi::FromInt(value)); 2070 } 2071 2072 SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 2073 RELAXED_SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 2074 2075 2076 int FreeSpace::Size() { return size(); } 2077 2078 2079 FreeSpace* FreeSpace::next() { 2080 DCHECK(map() == Heap::FromWritableHeapObject(this)->root( 2081 Heap::kFreeSpaceMapRootIndex) || 2082 (!Heap::FromWritableHeapObject(this)->deserialization_complete() && 2083 map() == nullptr)); 2084 DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size()); 2085 return reinterpret_cast<FreeSpace*>(Memory<Address>(address() + kNextOffset)); 2086 } 2087 2088 2089 void FreeSpace::set_next(FreeSpace* next) { 2090 DCHECK(map() == Heap::FromWritableHeapObject(this)->root( 2091 Heap::kFreeSpaceMapRootIndex) || 2092 (!Heap::FromWritableHeapObject(this)->deserialization_complete() && 2093 map() == nullptr)); 2094 DCHECK_LE(kNextOffset + kPointerSize, relaxed_read_size()); 2095 base::Relaxed_Store( 2096 reinterpret_cast<base::AtomicWord*>(address() + kNextOffset), 2097 reinterpret_cast<base::AtomicWord>(next)); 2098 } 2099 2100 2101 FreeSpace* FreeSpace::cast(HeapObject* o) { 2102 SLOW_DCHECK(!Heap::FromWritableHeapObject(o)->deserialization_complete() || 2103 o->IsFreeSpace()); 2104 return reinterpret_cast<FreeSpace*>(o); 2105 } 2106 2107 int HeapObject::SizeFromMap(Map* map) const { 2108 int instance_size = map->instance_size(); 2109 if (instance_size != kVariableSizeSentinel) return instance_size; 2110 // Only inline the most frequent cases. 2111 InstanceType instance_type = map->instance_type(); 2112 if (instance_type >= FIRST_FIXED_ARRAY_TYPE && 2113 instance_type <= LAST_FIXED_ARRAY_TYPE) { 2114 return FixedArray::SizeFor( 2115 reinterpret_cast<const FixedArray*>(this)->synchronized_length()); 2116 } 2117 if (instance_type == ONE_BYTE_STRING_TYPE || 2118 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) { 2119 // Strings may get concurrently truncated, hence we have to access its 2120 // length synchronized. 2121 return SeqOneByteString::SizeFor( 2122 reinterpret_cast<const SeqOneByteString*>(this)->synchronized_length()); 2123 } 2124 if (instance_type == BYTE_ARRAY_TYPE) { 2125 return ByteArray::SizeFor( 2126 reinterpret_cast<const ByteArray*>(this)->synchronized_length()); 2127 } 2128 if (instance_type == BYTECODE_ARRAY_TYPE) { 2129 return BytecodeArray::SizeFor( 2130 reinterpret_cast<const BytecodeArray*>(this)->synchronized_length()); 2131 } 2132 if (instance_type == FREE_SPACE_TYPE) { 2133 return reinterpret_cast<const FreeSpace*>(this)->relaxed_read_size(); 2134 } 2135 if (instance_type == STRING_TYPE || 2136 instance_type == INTERNALIZED_STRING_TYPE) { 2137 // Strings may get concurrently truncated, hence we have to access its 2138 // length synchronized. 2139 return SeqTwoByteString::SizeFor( 2140 reinterpret_cast<const SeqTwoByteString*>(this)->synchronized_length()); 2141 } 2142 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { 2143 return FixedDoubleArray::SizeFor( 2144 reinterpret_cast<const FixedDoubleArray*>(this)->synchronized_length()); 2145 } 2146 if (instance_type == FEEDBACK_METADATA_TYPE) { 2147 return FeedbackMetadata::SizeFor( 2148 reinterpret_cast<const FeedbackMetadata*>(this) 2149 ->synchronized_slot_count()); 2150 } 2151 if (instance_type >= FIRST_WEAK_FIXED_ARRAY_TYPE && 2152 instance_type <= LAST_WEAK_FIXED_ARRAY_TYPE) { 2153 return WeakFixedArray::SizeFor( 2154 reinterpret_cast<const WeakFixedArray*>(this)->synchronized_length()); 2155 } 2156 if (instance_type == WEAK_ARRAY_LIST_TYPE) { 2157 return WeakArrayList::SizeForCapacity( 2158 reinterpret_cast<const WeakArrayList*>(this)->synchronized_capacity()); 2159 } 2160 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && 2161 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) { 2162 return reinterpret_cast<const FixedTypedArrayBase*>(this)->TypedArraySize( 2163 instance_type); 2164 } 2165 if (instance_type == SMALL_ORDERED_HASH_SET_TYPE) { 2166 return SmallOrderedHashSet::SizeFor( 2167 reinterpret_cast<const SmallOrderedHashSet*>(this)->Capacity()); 2168 } 2169 if (instance_type == PROPERTY_ARRAY_TYPE) { 2170 return PropertyArray::SizeFor( 2171 reinterpret_cast<const PropertyArray*>(this)->synchronized_length()); 2172 } 2173 if (instance_type == SMALL_ORDERED_HASH_MAP_TYPE) { 2174 return SmallOrderedHashMap::SizeFor( 2175 reinterpret_cast<const SmallOrderedHashMap*>(this)->Capacity()); 2176 } 2177 if (instance_type == FEEDBACK_VECTOR_TYPE) { 2178 return FeedbackVector::SizeFor( 2179 reinterpret_cast<const FeedbackVector*>(this)->length()); 2180 } 2181 if (instance_type == BIGINT_TYPE) { 2182 return BigInt::SizeFor(reinterpret_cast<const BigInt*>(this)->length()); 2183 } 2184 if (instance_type == PRE_PARSED_SCOPE_DATA_TYPE) { 2185 return PreParsedScopeData::SizeFor( 2186 reinterpret_cast<const PreParsedScopeData*>(this)->length()); 2187 } 2188 DCHECK(instance_type == CODE_TYPE); 2189 return reinterpret_cast<const Code*>(this)->CodeSize(); 2190 } 2191 2192 Object* JSBoundFunction::raw_bound_target_function() const { 2193 return READ_FIELD(this, kBoundTargetFunctionOffset); 2194 } 2195 2196 ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver, 2197 kBoundTargetFunctionOffset) 2198 ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset) 2199 ACCESSORS(JSBoundFunction, bound_arguments, FixedArray, kBoundArgumentsOffset) 2200 2201 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) 2202 ACCESSORS(JSFunction, feedback_cell, FeedbackCell, kFeedbackCellOffset) 2203 2204 ACCESSORS(JSGlobalObject, native_context, Context, kNativeContextOffset) 2205 ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset) 2206 2207 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) 2208 2209 ACCESSORS(AsyncGeneratorRequest, next, Object, kNextOffset) 2210 SMI_ACCESSORS(AsyncGeneratorRequest, resume_mode, kResumeModeOffset) 2211 ACCESSORS(AsyncGeneratorRequest, value, Object, kValueOffset) 2212 ACCESSORS(AsyncGeneratorRequest, promise, Object, kPromiseOffset) 2213 2214 ACCESSORS(Tuple2, value1, Object, kValue1Offset) 2215 ACCESSORS(Tuple2, value2, Object, kValue2Offset) 2216 ACCESSORS(Tuple3, value3, Object, kValue3Offset) 2217 2218 ACCESSORS(TemplateObjectDescription, raw_strings, FixedArray, kRawStringsOffset) 2219 ACCESSORS(TemplateObjectDescription, cooked_strings, FixedArray, 2220 kCookedStringsOffset) 2221 2222 ACCESSORS(AccessorPair, getter, Object, kGetterOffset) 2223 ACCESSORS(AccessorPair, setter, Object, kSetterOffset) 2224 2225 ACCESSORS(AllocationSite, transition_info_or_boilerplate, Object, 2226 kTransitionInfoOrBoilerplateOffset) 2227 2228 JSObject* AllocationSite::boilerplate() const { 2229 DCHECK(PointsToLiteral()); 2230 return JSObject::cast(transition_info_or_boilerplate()); 2231 } 2232 2233 void AllocationSite::set_boilerplate(JSObject* object, WriteBarrierMode mode) { 2234 set_transition_info_or_boilerplate(object, mode); 2235 } 2236 2237 int AllocationSite::transition_info() const { 2238 DCHECK(!PointsToLiteral()); 2239 return Smi::cast(transition_info_or_boilerplate())->value(); 2240 } 2241 2242 void AllocationSite::set_transition_info(int value) { 2243 DCHECK(!PointsToLiteral()); 2244 set_transition_info_or_boilerplate(Smi::FromInt(value), SKIP_WRITE_BARRIER); 2245 } 2246 2247 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset) 2248 INT32_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset) 2249 INT32_ACCESSORS(AllocationSite, pretenure_create_count, 2250 kPretenureCreateCountOffset) 2251 ACCESSORS(AllocationSite, dependent_code, DependentCode, 2252 kDependentCodeOffset) 2253 ACCESSORS_CHECKED(AllocationSite, weak_next, Object, kWeakNextOffset, 2254 HasWeakNext()) 2255 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset) 2256 2257 SMI_ACCESSORS(StackFrameInfo, line_number, kLineNumberIndex) 2258 SMI_ACCESSORS(StackFrameInfo, column_number, kColumnNumberIndex) 2259 SMI_ACCESSORS(StackFrameInfo, script_id, kScriptIdIndex) 2260 ACCESSORS(StackFrameInfo, script_name, Object, kScriptNameIndex) 2261 ACCESSORS(StackFrameInfo, script_name_or_source_url, Object, 2262 kScriptNameOrSourceUrlIndex) 2263 ACCESSORS(StackFrameInfo, function_name, Object, kFunctionNameIndex) 2264 SMI_ACCESSORS(StackFrameInfo, flag, kFlagIndex) 2265 BOOL_ACCESSORS(StackFrameInfo, flag, is_eval, kIsEvalBit) 2266 BOOL_ACCESSORS(StackFrameInfo, flag, is_constructor, kIsConstructorBit) 2267 BOOL_ACCESSORS(StackFrameInfo, flag, is_wasm, kIsWasmBit) 2268 SMI_ACCESSORS(StackFrameInfo, id, kIdIndex) 2269 2270 ACCESSORS(SourcePositionTableWithFrameCache, source_position_table, ByteArray, 2271 kSourcePositionTableIndex) 2272 ACCESSORS(SourcePositionTableWithFrameCache, stack_frame_cache, 2273 SimpleNumberDictionary, kStackFrameCacheIndex) 2274 2275 2276 FeedbackVector* JSFunction::feedback_vector() const { 2277 DCHECK(has_feedback_vector()); 2278 return FeedbackVector::cast(feedback_cell()->value()); 2279 } 2280 2281 // Code objects that are marked for deoptimization are not considered to be 2282 // optimized. This is because the JSFunction might have been already 2283 // deoptimized but its code() still needs to be unlinked, which will happen on 2284 // its next activation. 2285 // TODO(jupvfranco): rename this function. Maybe RunOptimizedCode, 2286 // or IsValidOptimizedCode. 2287 bool JSFunction::IsOptimized() { 2288 return code()->kind() == Code::OPTIMIZED_FUNCTION && 2289 !code()->marked_for_deoptimization(); 2290 } 2291 2292 bool JSFunction::HasOptimizedCode() { 2293 return IsOptimized() || 2294 (has_feedback_vector() && feedback_vector()->has_optimized_code() && 2295 !feedback_vector()->optimized_code()->marked_for_deoptimization()); 2296 } 2297 2298 bool JSFunction::HasOptimizationMarker() { 2299 return has_feedback_vector() && feedback_vector()->has_optimization_marker(); 2300 } 2301 2302 void JSFunction::ClearOptimizationMarker() { 2303 DCHECK(has_feedback_vector()); 2304 feedback_vector()->ClearOptimizationMarker(); 2305 } 2306 2307 // Optimized code marked for deoptimization will tier back down to running 2308 // interpreted on its next activation, and already doesn't count as IsOptimized. 2309 bool JSFunction::IsInterpreted() { 2310 return code()->is_interpreter_trampoline_builtin() || 2311 (code()->kind() == Code::OPTIMIZED_FUNCTION && 2312 code()->marked_for_deoptimization()); 2313 } 2314 2315 bool JSFunction::ChecksOptimizationMarker() { 2316 return code()->checks_optimization_marker(); 2317 } 2318 2319 bool JSFunction::IsMarkedForOptimization() { 2320 return has_feedback_vector() && feedback_vector()->optimization_marker() == 2321 OptimizationMarker::kCompileOptimized; 2322 } 2323 2324 2325 bool JSFunction::IsMarkedForConcurrentOptimization() { 2326 return has_feedback_vector() && 2327 feedback_vector()->optimization_marker() == 2328 OptimizationMarker::kCompileOptimizedConcurrent; 2329 } 2330 2331 2332 bool JSFunction::IsInOptimizationQueue() { 2333 return has_feedback_vector() && feedback_vector()->optimization_marker() == 2334 OptimizationMarker::kInOptimizationQueue; 2335 } 2336 2337 2338 void JSFunction::CompleteInobjectSlackTrackingIfActive() { 2339 if (!has_prototype_slot()) return; 2340 if (has_initial_map() && initial_map()->IsInobjectSlackTrackingInProgress()) { 2341 initial_map()->CompleteInobjectSlackTracking(GetIsolate()); 2342 } 2343 } 2344 2345 AbstractCode* JSFunction::abstract_code() { 2346 if (IsInterpreted()) { 2347 return AbstractCode::cast(shared()->GetBytecodeArray()); 2348 } else { 2349 return AbstractCode::cast(code()); 2350 } 2351 } 2352 2353 Code* JSFunction::code() { return Code::cast(READ_FIELD(this, kCodeOffset)); } 2354 2355 void JSFunction::set_code(Code* value) { 2356 DCHECK(!Heap::InNewSpace(value)); 2357 WRITE_FIELD(this, kCodeOffset, value); 2358 MarkingBarrier(this, HeapObject::RawField(this, kCodeOffset), value); 2359 } 2360 2361 2362 void JSFunction::set_code_no_write_barrier(Code* value) { 2363 DCHECK(!Heap::InNewSpace(value)); 2364 WRITE_FIELD(this, kCodeOffset, value); 2365 } 2366 2367 void JSFunction::ClearOptimizedCodeSlot(const char* reason) { 2368 if (has_feedback_vector() && feedback_vector()->has_optimized_code()) { 2369 if (FLAG_trace_opt) { 2370 PrintF("[evicting entry from optimizing code feedback slot (%s) for ", 2371 reason); 2372 ShortPrint(); 2373 PrintF("]\n"); 2374 } 2375 feedback_vector()->ClearOptimizedCode(); 2376 } 2377 } 2378 2379 void JSFunction::SetOptimizationMarker(OptimizationMarker marker) { 2380 DCHECK(has_feedback_vector()); 2381 DCHECK(ChecksOptimizationMarker()); 2382 DCHECK(!HasOptimizedCode()); 2383 2384 feedback_vector()->SetOptimizationMarker(marker); 2385 } 2386 2387 bool JSFunction::has_feedback_vector() const { 2388 return !feedback_cell()->value()->IsUndefined(); 2389 } 2390 2391 Context* JSFunction::context() { 2392 return Context::cast(READ_FIELD(this, kContextOffset)); 2393 } 2394 2395 bool JSFunction::has_context() const { 2396 return READ_FIELD(this, kContextOffset)->IsContext(); 2397 } 2398 2399 JSGlobalProxy* JSFunction::global_proxy() { return context()->global_proxy(); } 2400 2401 Context* JSFunction::native_context() { return context()->native_context(); } 2402 2403 2404 void JSFunction::set_context(Object* value) { 2405 DCHECK(value->IsUndefined() || value->IsContext()); 2406 WRITE_FIELD(this, kContextOffset, value); 2407 WRITE_BARRIER(this, kContextOffset, value); 2408 } 2409 2410 ACCESSORS_CHECKED(JSFunction, prototype_or_initial_map, Object, 2411 kPrototypeOrInitialMapOffset, map()->has_prototype_slot()) 2412 2413 bool JSFunction::has_prototype_slot() const { 2414 return map()->has_prototype_slot(); 2415 } 2416 2417 Map* JSFunction::initial_map() { 2418 return Map::cast(prototype_or_initial_map()); 2419 } 2420 2421 2422 bool JSFunction::has_initial_map() { 2423 DCHECK(has_prototype_slot()); 2424 return prototype_or_initial_map()->IsMap(); 2425 } 2426 2427 2428 bool JSFunction::has_instance_prototype() { 2429 DCHECK(has_prototype_slot()); 2430 return has_initial_map() || !prototype_or_initial_map()->IsTheHole(); 2431 } 2432 2433 bool JSFunction::has_prototype() { 2434 DCHECK(has_prototype_slot()); 2435 return map()->has_non_instance_prototype() || has_instance_prototype(); 2436 } 2437 2438 bool JSFunction::has_prototype_property() { 2439 return (has_prototype_slot() && IsConstructor()) || 2440 IsGeneratorFunction(shared()->kind()); 2441 } 2442 2443 bool JSFunction::PrototypeRequiresRuntimeLookup() { 2444 return !has_prototype_property() || map()->has_non_instance_prototype(); 2445 } 2446 2447 Object* JSFunction::instance_prototype() { 2448 DCHECK(has_instance_prototype()); 2449 if (has_initial_map()) return initial_map()->prototype(); 2450 // When there is no initial map and the prototype is a JSReceiver, the 2451 // initial map field is used for the prototype field. 2452 return prototype_or_initial_map(); 2453 } 2454 2455 2456 Object* JSFunction::prototype() { 2457 DCHECK(has_prototype()); 2458 // If the function's prototype property has been set to a non-JSReceiver 2459 // value, that value is stored in the constructor field of the map. 2460 if (map()->has_non_instance_prototype()) { 2461 Object* prototype = map()->GetConstructor(); 2462 // The map must have a prototype in that field, not a back pointer. 2463 DCHECK(!prototype->IsMap()); 2464 DCHECK(!prototype->IsFunctionTemplateInfo()); 2465 return prototype; 2466 } 2467 return instance_prototype(); 2468 } 2469 2470 2471 bool JSFunction::is_compiled() { 2472 return code()->builtin_index() != Builtins::kCompileLazy; 2473 } 2474 2475 // static 2476 bool Foreign::IsNormalized(Object* value) { 2477 if (value == Smi::kZero) return true; 2478 return Foreign::cast(value)->foreign_address() != kNullAddress; 2479 } 2480 2481 Address Foreign::foreign_address() { 2482 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset)); 2483 } 2484 2485 void Foreign::set_foreign_address(Address value) { 2486 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value)); 2487 } 2488 2489 template <class Derived> 2490 void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index, 2491 Object* value) { 2492 Address entry_offset = GetDataEntryOffset(entry, relative_index); 2493 RELAXED_WRITE_FIELD(this, entry_offset, value); 2494 WRITE_BARRIER(this, static_cast<int>(entry_offset), value); 2495 } 2496 2497 ACCESSORS(JSValue, value, Object, kValueOffset) 2498 2499 2500 ACCESSORS(JSDate, value, Object, kValueOffset) 2501 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset) 2502 ACCESSORS(JSDate, year, Object, kYearOffset) 2503 ACCESSORS(JSDate, month, Object, kMonthOffset) 2504 ACCESSORS(JSDate, day, Object, kDayOffset) 2505 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset) 2506 ACCESSORS(JSDate, hour, Object, kHourOffset) 2507 ACCESSORS(JSDate, min, Object, kMinOffset) 2508 ACCESSORS(JSDate, sec, Object, kSecOffset) 2509 2510 2511 SMI_ACCESSORS(JSMessageObject, type, kTypeOffset) 2512 ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset) 2513 ACCESSORS(JSMessageObject, script, Script, kScriptOffset) 2514 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset) 2515 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset) 2516 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset) 2517 SMI_ACCESSORS(JSMessageObject, error_level, kErrorLevelOffset) 2518 2519 ElementsKind JSObject::GetElementsKind() const { 2520 ElementsKind kind = map()->elements_kind(); 2521 #if VERIFY_HEAP && DEBUG 2522 FixedArrayBase* fixed_array = 2523 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); 2524 2525 // If a GC was caused while constructing this object, the elements 2526 // pointer may point to a one pointer filler map. 2527 if (ElementsAreSafeToExamine()) { 2528 Map* map = fixed_array->map(); 2529 if (IsSmiOrObjectElementsKind(kind)) { 2530 DCHECK(map == GetReadOnlyRoots().fixed_array_map() || 2531 map == GetReadOnlyRoots().fixed_cow_array_map()); 2532 } else if (IsDoubleElementsKind(kind)) { 2533 DCHECK(fixed_array->IsFixedDoubleArray() || 2534 fixed_array == GetReadOnlyRoots().empty_fixed_array()); 2535 } else if (kind == DICTIONARY_ELEMENTS) { 2536 DCHECK(fixed_array->IsFixedArray()); 2537 DCHECK(fixed_array->IsDictionary()); 2538 } else { 2539 DCHECK(kind > DICTIONARY_ELEMENTS); 2540 } 2541 DCHECK(!IsSloppyArgumentsElementsKind(kind) || 2542 (elements()->IsFixedArray() && elements()->length() >= 2)); 2543 } 2544 #endif 2545 return kind; 2546 } 2547 2548 bool JSObject::HasObjectElements() { 2549 return IsObjectElementsKind(GetElementsKind()); 2550 } 2551 2552 bool JSObject::HasSmiElements() { return IsSmiElementsKind(GetElementsKind()); } 2553 2554 bool JSObject::HasSmiOrObjectElements() { 2555 return IsSmiOrObjectElementsKind(GetElementsKind()); 2556 } 2557 2558 bool JSObject::HasDoubleElements() { 2559 return IsDoubleElementsKind(GetElementsKind()); 2560 } 2561 2562 bool JSObject::HasHoleyElements() { 2563 return IsHoleyElementsKind(GetElementsKind()); 2564 } 2565 2566 2567 bool JSObject::HasFastElements() { 2568 return IsFastElementsKind(GetElementsKind()); 2569 } 2570 2571 bool JSObject::HasFastPackedElements() { 2572 return IsFastPackedElementsKind(GetElementsKind()); 2573 } 2574 2575 bool JSObject::HasDictionaryElements() { 2576 return GetElementsKind() == DICTIONARY_ELEMENTS; 2577 } 2578 2579 2580 bool JSObject::HasFastArgumentsElements() { 2581 return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS; 2582 } 2583 2584 2585 bool JSObject::HasSlowArgumentsElements() { 2586 return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 2587 } 2588 2589 2590 bool JSObject::HasSloppyArgumentsElements() { 2591 return IsSloppyArgumentsElementsKind(GetElementsKind()); 2592 } 2593 2594 bool JSObject::HasStringWrapperElements() { 2595 return IsStringWrapperElementsKind(GetElementsKind()); 2596 } 2597 2598 bool JSObject::HasFastStringWrapperElements() { 2599 return GetElementsKind() == FAST_STRING_WRAPPER_ELEMENTS; 2600 } 2601 2602 bool JSObject::HasSlowStringWrapperElements() { 2603 return GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS; 2604 } 2605 2606 bool JSObject::HasFixedTypedArrayElements() { 2607 DCHECK_NOT_NULL(elements()); 2608 return map()->has_fixed_typed_array_elements(); 2609 } 2610 2611 #define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype) \ 2612 bool JSObject::HasFixed##Type##Elements() { \ 2613 HeapObject* array = elements(); \ 2614 DCHECK_NOT_NULL(array); \ 2615 if (!array->IsHeapObject()) return false; \ 2616 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \ 2617 } 2618 2619 TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK) 2620 2621 #undef FIXED_TYPED_ELEMENTS_CHECK 2622 2623 2624 bool JSObject::HasNamedInterceptor() { 2625 return map()->has_named_interceptor(); 2626 } 2627 2628 2629 bool JSObject::HasIndexedInterceptor() { 2630 return map()->has_indexed_interceptor(); 2631 } 2632 2633 void JSGlobalObject::set_global_dictionary(GlobalDictionary* dictionary) { 2634 DCHECK(IsJSGlobalObject()); 2635 set_raw_properties_or_hash(dictionary); 2636 } 2637 2638 GlobalDictionary* JSGlobalObject::global_dictionary() { 2639 DCHECK(!HasFastProperties()); 2640 DCHECK(IsJSGlobalObject()); 2641 return GlobalDictionary::cast(raw_properties_or_hash()); 2642 } 2643 2644 NumberDictionary* JSObject::element_dictionary() { 2645 DCHECK(HasDictionaryElements() || HasSlowStringWrapperElements()); 2646 return NumberDictionary::cast(elements()); 2647 } 2648 2649 // static 2650 Maybe<bool> Object::GreaterThan(Isolate* isolate, Handle<Object> x, 2651 Handle<Object> y) { 2652 Maybe<ComparisonResult> result = Compare(isolate, x, y); 2653 if (result.IsJust()) { 2654 switch (result.FromJust()) { 2655 case ComparisonResult::kGreaterThan: 2656 return Just(true); 2657 case ComparisonResult::kLessThan: 2658 case ComparisonResult::kEqual: 2659 case ComparisonResult::kUndefined: 2660 return Just(false); 2661 } 2662 } 2663 return Nothing<bool>(); 2664 } 2665 2666 2667 // static 2668 Maybe<bool> Object::GreaterThanOrEqual(Isolate* isolate, Handle<Object> x, 2669 Handle<Object> y) { 2670 Maybe<ComparisonResult> result = Compare(isolate, x, y); 2671 if (result.IsJust()) { 2672 switch (result.FromJust()) { 2673 case ComparisonResult::kEqual: 2674 case ComparisonResult::kGreaterThan: 2675 return Just(true); 2676 case ComparisonResult::kLessThan: 2677 case ComparisonResult::kUndefined: 2678 return Just(false); 2679 } 2680 } 2681 return Nothing<bool>(); 2682 } 2683 2684 2685 // static 2686 Maybe<bool> Object::LessThan(Isolate* isolate, Handle<Object> x, 2687 Handle<Object> y) { 2688 Maybe<ComparisonResult> result = Compare(isolate, x, y); 2689 if (result.IsJust()) { 2690 switch (result.FromJust()) { 2691 case ComparisonResult::kLessThan: 2692 return Just(true); 2693 case ComparisonResult::kEqual: 2694 case ComparisonResult::kGreaterThan: 2695 case ComparisonResult::kUndefined: 2696 return Just(false); 2697 } 2698 } 2699 return Nothing<bool>(); 2700 } 2701 2702 2703 // static 2704 Maybe<bool> Object::LessThanOrEqual(Isolate* isolate, Handle<Object> x, 2705 Handle<Object> y) { 2706 Maybe<ComparisonResult> result = Compare(isolate, x, y); 2707 if (result.IsJust()) { 2708 switch (result.FromJust()) { 2709 case ComparisonResult::kEqual: 2710 case ComparisonResult::kLessThan: 2711 return Just(true); 2712 case ComparisonResult::kGreaterThan: 2713 case ComparisonResult::kUndefined: 2714 return Just(false); 2715 } 2716 } 2717 return Nothing<bool>(); 2718 } 2719 2720 MaybeHandle<Object> Object::GetPropertyOrElement(Isolate* isolate, 2721 Handle<Object> object, 2722 Handle<Name> name) { 2723 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); 2724 return GetProperty(&it); 2725 } 2726 2727 MaybeHandle<Object> Object::SetPropertyOrElement(Isolate* isolate, 2728 Handle<Object> object, 2729 Handle<Name> name, 2730 Handle<Object> value, 2731 LanguageMode language_mode, 2732 StoreFromKeyed store_mode) { 2733 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name); 2734 MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode)); 2735 return value; 2736 } 2737 2738 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> receiver, 2739 Handle<Name> name, 2740 Handle<JSReceiver> holder) { 2741 LookupIterator it = LookupIterator::PropertyOrElement(holder->GetIsolate(), 2742 receiver, name, holder); 2743 return GetProperty(&it); 2744 } 2745 2746 2747 void JSReceiver::initialize_properties() { 2748 Heap* heap = GetHeap(); 2749 ReadOnlyRoots roots(heap); 2750 DCHECK(!Heap::InNewSpace(roots.empty_fixed_array())); 2751 DCHECK(!Heap::InNewSpace(heap->empty_property_dictionary())); 2752 if (map()->is_dictionary_map()) { 2753 WRITE_FIELD(this, kPropertiesOrHashOffset, 2754 heap->empty_property_dictionary()); 2755 } else { 2756 WRITE_FIELD(this, kPropertiesOrHashOffset, roots.empty_fixed_array()); 2757 } 2758 } 2759 2760 bool JSReceiver::HasFastProperties() const { 2761 DCHECK( 2762 raw_properties_or_hash()->IsSmi() || 2763 (raw_properties_or_hash()->IsDictionary() == map()->is_dictionary_map())); 2764 return !map()->is_dictionary_map(); 2765 } 2766 2767 NameDictionary* JSReceiver::property_dictionary() const { 2768 DCHECK(!IsJSGlobalObject()); 2769 DCHECK(!HasFastProperties()); 2770 2771 Object* prop = raw_properties_or_hash(); 2772 if (prop->IsSmi()) { 2773 return GetHeap()->empty_property_dictionary(); 2774 } 2775 2776 return NameDictionary::cast(prop); 2777 } 2778 2779 // TODO(gsathya): Pass isolate directly to this function and access 2780 // the heap from this. 2781 PropertyArray* JSReceiver::property_array() const { 2782 DCHECK(HasFastProperties()); 2783 2784 Object* prop = raw_properties_or_hash(); 2785 if (prop->IsSmi() || prop == GetReadOnlyRoots().empty_fixed_array()) { 2786 return GetReadOnlyRoots().empty_property_array(); 2787 } 2788 2789 return PropertyArray::cast(prop); 2790 } 2791 2792 Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object, 2793 Handle<Name> name) { 2794 LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(), 2795 object, name, object); 2796 return HasProperty(&it); 2797 } 2798 2799 2800 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object, 2801 uint32_t index) { 2802 if (object->IsJSModuleNamespace()) return Just(false); 2803 2804 if (object->IsJSObject()) { // Shortcut. 2805 LookupIterator it(object->GetIsolate(), object, index, object, 2806 LookupIterator::OWN); 2807 return HasProperty(&it); 2808 } 2809 2810 Maybe<PropertyAttributes> attributes = 2811 JSReceiver::GetOwnPropertyAttributes(object, index); 2812 MAYBE_RETURN(attributes, Nothing<bool>()); 2813 return Just(attributes.FromJust() != ABSENT); 2814 } 2815 2816 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( 2817 Handle<JSReceiver> object, Handle<Name> name) { 2818 LookupIterator it = LookupIterator::PropertyOrElement(object->GetIsolate(), 2819 object, name, object); 2820 return GetPropertyAttributes(&it); 2821 } 2822 2823 2824 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( 2825 Handle<JSReceiver> object, Handle<Name> name) { 2826 LookupIterator it = LookupIterator::PropertyOrElement( 2827 object->GetIsolate(), object, name, object, LookupIterator::OWN); 2828 return GetPropertyAttributes(&it); 2829 } 2830 2831 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( 2832 Handle<JSReceiver> object, uint32_t index) { 2833 LookupIterator it(object->GetIsolate(), object, index, object, 2834 LookupIterator::OWN); 2835 return GetPropertyAttributes(&it); 2836 } 2837 2838 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) { 2839 LookupIterator it(object->GetIsolate(), object, index, object); 2840 return HasProperty(&it); 2841 } 2842 2843 2844 Maybe<PropertyAttributes> JSReceiver::GetElementAttributes( 2845 Handle<JSReceiver> object, uint32_t index) { 2846 Isolate* isolate = object->GetIsolate(); 2847 LookupIterator it(isolate, object, index, object); 2848 return GetPropertyAttributes(&it); 2849 } 2850 2851 2852 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes( 2853 Handle<JSReceiver> object, uint32_t index) { 2854 Isolate* isolate = object->GetIsolate(); 2855 LookupIterator it(isolate, object, index, object, LookupIterator::OWN); 2856 return GetPropertyAttributes(&it); 2857 } 2858 2859 2860 bool JSGlobalObject::IsDetached() { 2861 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this); 2862 } 2863 2864 2865 bool JSGlobalProxy::IsDetachedFrom(JSGlobalObject* global) const { 2866 const PrototypeIterator iter(this->GetIsolate(), 2867 const_cast<JSGlobalProxy*>(this)); 2868 return iter.GetCurrent() != global; 2869 } 2870 2871 inline int JSGlobalProxy::SizeWithEmbedderFields(int embedder_field_count) { 2872 DCHECK_GE(embedder_field_count, 0); 2873 return kSize + embedder_field_count * kPointerSize; 2874 } 2875 2876 Object* AccessorPair::get(AccessorComponent component) { 2877 return component == ACCESSOR_GETTER ? getter() : setter(); 2878 } 2879 2880 2881 void AccessorPair::set(AccessorComponent component, Object* value) { 2882 if (component == ACCESSOR_GETTER) { 2883 set_getter(value); 2884 } else { 2885 set_setter(value); 2886 } 2887 } 2888 2889 2890 void AccessorPair::SetComponents(Object* getter, Object* setter) { 2891 if (!getter->IsNull()) set_getter(getter); 2892 if (!setter->IsNull()) set_setter(setter); 2893 } 2894 2895 bool AccessorPair::Equals(AccessorPair* pair) { 2896 return (this == pair) || pair->Equals(getter(), setter()); 2897 } 2898 2899 2900 bool AccessorPair::Equals(Object* getter_value, Object* setter_value) { 2901 return (getter() == getter_value) && (setter() == setter_value); 2902 } 2903 2904 2905 bool AccessorPair::ContainsAccessor() { 2906 return IsJSAccessor(getter()) || IsJSAccessor(setter()); 2907 } 2908 2909 2910 bool AccessorPair::IsJSAccessor(Object* obj) { 2911 return obj->IsCallable() || obj->IsUndefined(); 2912 } 2913 2914 template <typename Derived, typename Shape> 2915 void Dictionary<Derived, Shape>::ClearEntry(Isolate* isolate, int entry) { 2916 Object* the_hole = this->GetReadOnlyRoots().the_hole_value(); 2917 PropertyDetails details = PropertyDetails::Empty(); 2918 Derived::cast(this)->SetEntry(isolate, entry, the_hole, the_hole, details); 2919 } 2920 2921 template <typename Derived, typename Shape> 2922 void Dictionary<Derived, Shape>::SetEntry(Isolate* isolate, int entry, 2923 Object* key, Object* value, 2924 PropertyDetails details) { 2925 DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3); 2926 DCHECK(!key->IsName() || details.dictionary_index() > 0); 2927 int index = DerivedHashTable::EntryToIndex(entry); 2928 DisallowHeapAllocation no_gc; 2929 WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc); 2930 this->set(index + Derived::kEntryKeyIndex, key, mode); 2931 this->set(index + Derived::kEntryValueIndex, value, mode); 2932 if (Shape::kHasDetails) DetailsAtPut(isolate, entry, details); 2933 } 2934 2935 Object* GlobalDictionaryShape::Unwrap(Object* object) { 2936 return PropertyCell::cast(object)->name(); 2937 } 2938 2939 int GlobalDictionaryShape::GetMapRootIndex() { 2940 return Heap::kGlobalDictionaryMapRootIndex; 2941 } 2942 2943 Name* NameDictionary::NameAt(int entry) { return Name::cast(KeyAt(entry)); } 2944 2945 int NameDictionaryShape::GetMapRootIndex() { 2946 return Heap::kNameDictionaryMapRootIndex; 2947 } 2948 2949 PropertyCell* GlobalDictionary::CellAt(int entry) { 2950 DCHECK(KeyAt(entry)->IsPropertyCell()); 2951 return PropertyCell::cast(KeyAt(entry)); 2952 } 2953 2954 bool GlobalDictionaryShape::IsLive(ReadOnlyRoots roots, Object* k) { 2955 DCHECK_NE(roots.the_hole_value(), k); 2956 return k != roots.undefined_value(); 2957 } 2958 2959 bool GlobalDictionaryShape::IsKey(ReadOnlyRoots roots, Object* k) { 2960 return IsLive(roots, k) && !PropertyCell::cast(k)->value()->IsTheHole(roots); 2961 } 2962 2963 Name* GlobalDictionary::NameAt(int entry) { return CellAt(entry)->name(); } 2964 Object* GlobalDictionary::ValueAt(int entry) { return CellAt(entry)->value(); } 2965 2966 void GlobalDictionary::SetEntry(Isolate* isolate, int entry, Object* key, 2967 Object* value, PropertyDetails details) { 2968 DCHECK_EQ(key, PropertyCell::cast(value)->name()); 2969 set(EntryToIndex(entry) + kEntryKeyIndex, value); 2970 DetailsAtPut(isolate, entry, details); 2971 } 2972 2973 void GlobalDictionary::ValueAtPut(int entry, Object* value) { 2974 set(EntryToIndex(entry), value); 2975 } 2976 2977 bool NumberDictionaryBaseShape::IsMatch(uint32_t key, Object* other) { 2978 DCHECK(other->IsNumber()); 2979 return key == static_cast<uint32_t>(other->Number()); 2980 } 2981 2982 uint32_t NumberDictionaryBaseShape::Hash(Isolate* isolate, uint32_t key) { 2983 return ComputeIntegerHash(key, isolate->heap()->HashSeed()); 2984 } 2985 2986 uint32_t NumberDictionaryBaseShape::HashForObject(Isolate* isolate, 2987 Object* other) { 2988 DCHECK(other->IsNumber()); 2989 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 2990 isolate->heap()->HashSeed()); 2991 } 2992 2993 Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate, 2994 uint32_t key) { 2995 return isolate->factory()->NewNumberFromUint(key); 2996 } 2997 2998 int NumberDictionaryShape::GetMapRootIndex() { 2999 return Heap::kNumberDictionaryMapRootIndex; 3000 } 3001 3002 int SimpleNumberDictionaryShape::GetMapRootIndex() { 3003 return Heap::kSimpleNumberDictionaryMapRootIndex; 3004 } 3005 3006 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) { 3007 DCHECK(other->IsTheHole() || Name::cast(other)->IsUniqueName()); 3008 DCHECK(key->IsUniqueName()); 3009 return *key == other; 3010 } 3011 3012 uint32_t NameDictionaryShape::Hash(Isolate* isolate, Handle<Name> key) { 3013 return key->Hash(); 3014 } 3015 3016 uint32_t NameDictionaryShape::HashForObject(Isolate* isolate, Object* other) { 3017 return Name::cast(other)->Hash(); 3018 } 3019 3020 bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object* other) { 3021 DCHECK(PropertyCell::cast(other)->name()->IsUniqueName()); 3022 return *key == PropertyCell::cast(other)->name(); 3023 } 3024 3025 uint32_t GlobalDictionaryShape::HashForObject(Isolate* isolate, Object* other) { 3026 return PropertyCell::cast(other)->name()->Hash(); 3027 } 3028 3029 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate, 3030 Handle<Name> key) { 3031 DCHECK(key->IsUniqueName()); 3032 return key; 3033 } 3034 3035 3036 template <typename Dictionary> 3037 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) { 3038 DCHECK_LE(0, entry); // Not found is -1, which is not caught by get(). 3039 return dict->CellAt(entry)->property_details(); 3040 } 3041 3042 template <typename Dictionary> 3043 void GlobalDictionaryShape::DetailsAtPut(Isolate* isolate, Dictionary* dict, 3044 int entry, PropertyDetails value) { 3045 DCHECK_LE(0, entry); // Not found is -1, which is not caught by get(). 3046 PropertyCell* cell = dict->CellAt(entry); 3047 if (cell->property_details().IsReadOnly() != value.IsReadOnly()) { 3048 cell->dependent_code()->DeoptimizeDependentCodeGroup( 3049 isolate, DependentCode::kPropertyCellChangedGroup); 3050 } 3051 cell->set_property_details(value); 3052 } 3053 3054 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) { 3055 return key->SameValue(other); 3056 } 3057 3058 uint32_t ObjectHashTableShape::Hash(Isolate* isolate, Handle<Object> key) { 3059 return Smi::ToInt(key->GetHash()); 3060 } 3061 3062 uint32_t ObjectHashTableShape::HashForObject(Isolate* isolate, Object* other) { 3063 return Smi::ToInt(other->GetHash()); 3064 } 3065 3066 // static 3067 Object* Object::GetSimpleHash(Object* object) { 3068 DisallowHeapAllocation no_gc; 3069 if (object->IsSmi()) { 3070 uint32_t hash = ComputeIntegerHash(Smi::ToInt(object)); 3071 return Smi::FromInt(hash & Smi::kMaxValue); 3072 } 3073 if (object->IsHeapNumber()) { 3074 double num = HeapNumber::cast(object)->value(); 3075 if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue); 3076 // Use ComputeIntegerHash for all values in Signed32 range, including -0, 3077 // which is considered equal to 0 because collections use SameValueZero. 3078 uint32_t hash; 3079 // Check range before conversion to avoid undefined behavior. 3080 if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) { 3081 hash = ComputeIntegerHash(FastD2I(num)); 3082 } else { 3083 hash = ComputeLongHash(double_to_uint64(num)); 3084 } 3085 return Smi::FromInt(hash & Smi::kMaxValue); 3086 } 3087 if (object->IsName()) { 3088 uint32_t hash = Name::cast(object)->Hash(); 3089 return Smi::FromInt(hash); 3090 } 3091 if (object->IsOddball()) { 3092 uint32_t hash = Oddball::cast(object)->to_string()->Hash(); 3093 return Smi::FromInt(hash); 3094 } 3095 if (object->IsBigInt()) { 3096 uint32_t hash = BigInt::cast(object)->Hash(); 3097 return Smi::FromInt(hash & Smi::kMaxValue); 3098 } 3099 DCHECK(object->IsJSReceiver()); 3100 return object; 3101 } 3102 3103 Object* Object::GetHash() { 3104 DisallowHeapAllocation no_gc; 3105 Object* hash = GetSimpleHash(this); 3106 if (hash->IsSmi()) return hash; 3107 3108 DCHECK(IsJSReceiver()); 3109 JSReceiver* receiver = JSReceiver::cast(this); 3110 Isolate* isolate = receiver->GetIsolate(); 3111 return receiver->GetIdentityHash(isolate); 3112 } 3113 3114 Handle<Object> ObjectHashTableShape::AsHandle(Handle<Object> key) { 3115 return key; 3116 } 3117 3118 Relocatable::Relocatable(Isolate* isolate) { 3119 isolate_ = isolate; 3120 prev_ = isolate->relocatable_top(); 3121 isolate->set_relocatable_top(this); 3122 } 3123 3124 3125 Relocatable::~Relocatable() { 3126 DCHECK_EQ(isolate_->relocatable_top(), this); 3127 isolate_->set_relocatable_top(prev_); 3128 } 3129 3130 3131 template<class Derived, class TableType> 3132 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { 3133 TableType* table(TableType::cast(this->table())); 3134 int index = Smi::ToInt(this->index()); 3135 Object* key = table->KeyAt(index); 3136 DCHECK(!key->IsTheHole()); 3137 return key; 3138 } 3139 3140 // Predictably converts HeapObject* or Address to uint32 by calculating 3141 // offset of the address in respective MemoryChunk. 3142 static inline uint32_t ObjectAddressForHashing(void* object) { 3143 uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)); 3144 return value & MemoryChunk::kAlignmentMask; 3145 } 3146 3147 static inline Handle<Object> MakeEntryPair(Isolate* isolate, uint32_t index, 3148 Handle<Object> value) { 3149 Handle<Object> key = isolate->factory()->Uint32ToString(index); 3150 Handle<FixedArray> entry_storage = 3151 isolate->factory()->NewUninitializedFixedArray(2); 3152 { 3153 entry_storage->set(0, *key, SKIP_WRITE_BARRIER); 3154 entry_storage->set(1, *value, SKIP_WRITE_BARRIER); 3155 } 3156 return isolate->factory()->NewJSArrayWithElements(entry_storage, 3157 PACKED_ELEMENTS, 2); 3158 } 3159 3160 static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key, 3161 Handle<Object> value) { 3162 Handle<FixedArray> entry_storage = 3163 isolate->factory()->NewUninitializedFixedArray(2); 3164 { 3165 entry_storage->set(0, *key, SKIP_WRITE_BARRIER); 3166 entry_storage->set(1, *value, SKIP_WRITE_BARRIER); 3167 } 3168 return isolate->factory()->NewJSArrayWithElements(entry_storage, 3169 PACKED_ELEMENTS, 2); 3170 } 3171 3172 ACCESSORS(JSIteratorResult, value, Object, kValueOffset) 3173 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset) 3174 3175 ACCESSORS(JSAsyncFromSyncIterator, sync_iterator, JSReceiver, 3176 kSyncIteratorOffset) 3177 ACCESSORS(JSAsyncFromSyncIterator, next, Object, kNextOffset) 3178 3179 ACCESSORS(JSStringIterator, string, String, kStringOffset) 3180 SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset) 3181 3182 bool ScopeInfo::IsAsmModule() const { return AsmModuleField::decode(Flags()); } 3183 3184 bool ScopeInfo::HasSimpleParameters() const { 3185 return HasSimpleParametersField::decode(Flags()); 3186 } 3187 3188 #define FIELD_ACCESSORS(name) \ 3189 void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \ 3190 int ScopeInfo::name() const { \ 3191 if (length() > 0) { \ 3192 return Smi::ToInt(get(k##name)); \ 3193 } else { \ 3194 return 0; \ 3195 } \ 3196 } 3197 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS) 3198 #undef FIELD_ACCESSORS 3199 3200 FreshlyAllocatedBigInt* FreshlyAllocatedBigInt::cast(Object* object) { 3201 SLOW_DCHECK(object->IsBigInt()); 3202 return reinterpret_cast<FreshlyAllocatedBigInt*>(object); 3203 } 3204 3205 } // namespace internal 3206 } // namespace v8 3207 3208 #include "src/objects/object-macros-undef.h" 3209 3210 #endif // V8_OBJECTS_INL_H_ 3211