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/base/atomicops.h" 16 #include "src/base/bits.h" 17 #include "src/contexts-inl.h" 18 #include "src/conversions-inl.h" 19 #include "src/factory.h" 20 #include "src/field-index-inl.h" 21 #include "src/heap/heap-inl.h" 22 #include "src/heap/heap.h" 23 #include "src/isolate.h" 24 #include "src/layout-descriptor-inl.h" 25 #include "src/lookup.h" 26 #include "src/objects.h" 27 #include "src/property.h" 28 #include "src/prototype.h" 29 #include "src/transitions-inl.h" 30 #include "src/type-feedback-vector-inl.h" 31 #include "src/types-inl.h" 32 #include "src/v8memory.h" 33 34 namespace v8 { 35 namespace internal { 36 37 PropertyDetails::PropertyDetails(Smi* smi) { 38 value_ = smi->value(); 39 } 40 41 42 Smi* PropertyDetails::AsSmi() const { 43 // Ensure the upper 2 bits have the same value by sign extending it. This is 44 // necessary to be able to use the 31st bit of the property details. 45 int value = value_ << 1; 46 return Smi::FromInt(value >> 1); 47 } 48 49 50 int PropertyDetails::field_width_in_words() const { 51 DCHECK(location() == kField); 52 if (!FLAG_unbox_double_fields) return 1; 53 if (kDoubleSize == kPointerSize) return 1; 54 return representation().IsDouble() ? kDoubleSize / kPointerSize : 1; 55 } 56 57 58 #define TYPE_CHECKER(type, instancetype) \ 59 bool Object::Is##type() const { \ 60 return Object::IsHeapObject() && \ 61 HeapObject::cast(this)->map()->instance_type() == instancetype; \ 62 } 63 64 65 #define CAST_ACCESSOR(type) \ 66 type* type::cast(Object* object) { \ 67 SLOW_DCHECK(object->Is##type()); \ 68 return reinterpret_cast<type*>(object); \ 69 } \ 70 const type* type::cast(const Object* object) { \ 71 SLOW_DCHECK(object->Is##type()); \ 72 return reinterpret_cast<const type*>(object); \ 73 } 74 75 76 #define INT_ACCESSORS(holder, name, offset) \ 77 int holder::name() const { return READ_INT_FIELD(this, offset); } \ 78 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } 79 80 81 #define ACCESSORS(holder, name, type, offset) \ 82 type* holder::name() const { return type::cast(READ_FIELD(this, offset)); } \ 83 void holder::set_##name(type* value, WriteBarrierMode mode) { \ 84 WRITE_FIELD(this, offset, value); \ 85 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ 86 } 87 88 89 // Getter that returns a Smi as an int and writes an int as a Smi. 90 #define SMI_ACCESSORS(holder, name, offset) \ 91 int holder::name() const { \ 92 Object* value = READ_FIELD(this, offset); \ 93 return Smi::cast(value)->value(); \ 94 } \ 95 void holder::set_##name(int value) { \ 96 WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 97 } 98 99 #define SYNCHRONIZED_SMI_ACCESSORS(holder, name, offset) \ 100 int holder::synchronized_##name() const { \ 101 Object* value = ACQUIRE_READ_FIELD(this, offset); \ 102 return Smi::cast(value)->value(); \ 103 } \ 104 void holder::synchronized_set_##name(int value) { \ 105 RELEASE_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 106 } 107 108 #define NOBARRIER_SMI_ACCESSORS(holder, name, offset) \ 109 int holder::nobarrier_##name() const { \ 110 Object* value = NOBARRIER_READ_FIELD(this, offset); \ 111 return Smi::cast(value)->value(); \ 112 } \ 113 void holder::nobarrier_set_##name(int value) { \ 114 NOBARRIER_WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 115 } 116 117 #define BOOL_GETTER(holder, field, name, offset) \ 118 bool holder::name() const { \ 119 return BooleanBit::get(field(), offset); \ 120 } \ 121 122 123 #define BOOL_ACCESSORS(holder, field, name, offset) \ 124 bool holder::name() const { \ 125 return BooleanBit::get(field(), offset); \ 126 } \ 127 void holder::set_##name(bool value) { \ 128 set_##field(BooleanBit::set(field(), offset, value)); \ 129 } 130 131 132 bool Object::IsFixedArrayBase() const { 133 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); 134 } 135 136 137 bool Object::IsFixedArray() const { 138 if (!IsHeapObject()) return false; 139 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type(); 140 return instance_type == FIXED_ARRAY_TYPE || 141 instance_type == TRANSITION_ARRAY_TYPE; 142 } 143 144 145 // External objects are not extensible, so the map check is enough. 146 bool Object::IsExternal() const { 147 return Object::IsHeapObject() && 148 HeapObject::cast(this)->map() == 149 HeapObject::cast(this)->GetHeap()->external_map(); 150 } 151 152 153 bool Object::IsAccessorInfo() const { return IsExecutableAccessorInfo(); } 154 155 156 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE) 157 TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE) 158 TYPE_CHECKER(Symbol, SYMBOL_TYPE) 159 TYPE_CHECKER(Simd128Value, SIMD128_VALUE_TYPE) 160 161 162 #define SIMD128_TYPE_CHECKER(TYPE, Type, type, lane_count, lane_type) \ 163 bool Object::Is##Type() const { \ 164 return Object::IsHeapObject() && \ 165 HeapObject::cast(this)->map() == \ 166 HeapObject::cast(this)->GetHeap()->type##_map(); \ 167 } 168 SIMD128_TYPES(SIMD128_TYPE_CHECKER) 169 #undef SIMD128_TYPE_CHECKER 170 171 172 bool Object::IsString() const { 173 return Object::IsHeapObject() 174 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE; 175 } 176 177 178 bool Object::IsName() const { 179 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); 180 return Object::IsHeapObject() && 181 HeapObject::cast(this)->map()->instance_type() <= LAST_NAME_TYPE; 182 } 183 184 185 bool Object::IsUniqueName() const { 186 return IsInternalizedString() || IsSymbol(); 187 } 188 189 190 bool Object::IsFunction() const { 191 STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE); 192 return Object::IsHeapObject() && 193 HeapObject::cast(this)->map()->instance_type() >= FIRST_FUNCTION_TYPE; 194 } 195 196 197 bool Object::IsCallable() const { 198 return Object::IsHeapObject() && HeapObject::cast(this)->map()->is_callable(); 199 } 200 201 202 bool Object::IsConstructor() const { 203 return Object::IsHeapObject() && 204 HeapObject::cast(this)->map()->is_constructor(); 205 } 206 207 208 bool Object::IsTemplateInfo() const { 209 return IsObjectTemplateInfo() || IsFunctionTemplateInfo(); 210 } 211 212 213 bool Object::IsInternalizedString() const { 214 if (!this->IsHeapObject()) return false; 215 uint32_t type = HeapObject::cast(this)->map()->instance_type(); 216 STATIC_ASSERT(kNotInternalizedTag != 0); 217 return (type & (kIsNotStringMask | kIsNotInternalizedMask)) == 218 (kStringTag | kInternalizedTag); 219 } 220 221 222 bool Object::IsConsString() const { 223 if (!IsString()) return false; 224 return StringShape(String::cast(this)).IsCons(); 225 } 226 227 228 bool Object::IsSlicedString() const { 229 if (!IsString()) return false; 230 return StringShape(String::cast(this)).IsSliced(); 231 } 232 233 234 bool Object::IsSeqString() const { 235 if (!IsString()) return false; 236 return StringShape(String::cast(this)).IsSequential(); 237 } 238 239 240 bool Object::IsSeqOneByteString() const { 241 if (!IsString()) return false; 242 return StringShape(String::cast(this)).IsSequential() && 243 String::cast(this)->IsOneByteRepresentation(); 244 } 245 246 247 bool Object::IsSeqTwoByteString() const { 248 if (!IsString()) return false; 249 return StringShape(String::cast(this)).IsSequential() && 250 String::cast(this)->IsTwoByteRepresentation(); 251 } 252 253 254 bool Object::IsExternalString() const { 255 if (!IsString()) return false; 256 return StringShape(String::cast(this)).IsExternal(); 257 } 258 259 260 bool Object::IsExternalOneByteString() const { 261 if (!IsString()) return false; 262 return StringShape(String::cast(this)).IsExternal() && 263 String::cast(this)->IsOneByteRepresentation(); 264 } 265 266 267 bool Object::IsExternalTwoByteString() const { 268 if (!IsString()) return false; 269 return StringShape(String::cast(this)).IsExternal() && 270 String::cast(this)->IsTwoByteRepresentation(); 271 } 272 273 274 bool Object::HasValidElements() { 275 // Dictionary is covered under FixedArray. 276 return IsFixedArray() || IsFixedDoubleArray() || IsFixedTypedArrayBase(); 277 } 278 279 280 bool Object::KeyEquals(Object* second) { 281 Object* first = this; 282 if (second->IsNumber()) { 283 if (first->IsNumber()) return first->Number() == second->Number(); 284 Object* temp = first; 285 first = second; 286 second = temp; 287 } 288 if (first->IsNumber()) { 289 DCHECK_LE(0, first->Number()); 290 uint32_t expected = static_cast<uint32_t>(first->Number()); 291 uint32_t index; 292 return Name::cast(second)->AsArrayIndex(&index) && index == expected; 293 } 294 return Name::cast(first)->Equals(Name::cast(second)); 295 } 296 297 298 bool Object::FilterKey(PropertyFilter filter) { 299 if (IsSymbol()) { 300 if (filter & SKIP_SYMBOLS) return true; 301 if (Symbol::cast(this)->is_private()) return true; 302 } else { 303 if (filter & SKIP_STRINGS) return true; 304 } 305 return false; 306 } 307 308 309 Handle<Object> Object::NewStorageFor(Isolate* isolate, 310 Handle<Object> object, 311 Representation representation) { 312 if (representation.IsSmi() && object->IsUninitialized()) { 313 return handle(Smi::FromInt(0), isolate); 314 } 315 if (!representation.IsDouble()) return object; 316 double value; 317 if (object->IsUninitialized()) { 318 value = 0; 319 } else if (object->IsMutableHeapNumber()) { 320 value = HeapNumber::cast(*object)->value(); 321 } else { 322 value = object->Number(); 323 } 324 return isolate->factory()->NewHeapNumber(value, MUTABLE); 325 } 326 327 328 Handle<Object> Object::WrapForRead(Isolate* isolate, 329 Handle<Object> object, 330 Representation representation) { 331 DCHECK(!object->IsUninitialized()); 332 if (!representation.IsDouble()) { 333 DCHECK(object->FitsRepresentation(representation)); 334 return object; 335 } 336 return isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value()); 337 } 338 339 340 StringShape::StringShape(const String* str) 341 : type_(str->map()->instance_type()) { 342 set_valid(); 343 DCHECK((type_ & kIsNotStringMask) == kStringTag); 344 } 345 346 347 StringShape::StringShape(Map* map) 348 : type_(map->instance_type()) { 349 set_valid(); 350 DCHECK((type_ & kIsNotStringMask) == kStringTag); 351 } 352 353 354 StringShape::StringShape(InstanceType t) 355 : type_(static_cast<uint32_t>(t)) { 356 set_valid(); 357 DCHECK((type_ & kIsNotStringMask) == kStringTag); 358 } 359 360 361 bool StringShape::IsInternalized() { 362 DCHECK(valid()); 363 STATIC_ASSERT(kNotInternalizedTag != 0); 364 return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) == 365 (kStringTag | kInternalizedTag); 366 } 367 368 369 bool String::IsOneByteRepresentation() const { 370 uint32_t type = map()->instance_type(); 371 return (type & kStringEncodingMask) == kOneByteStringTag; 372 } 373 374 375 bool String::IsTwoByteRepresentation() const { 376 uint32_t type = map()->instance_type(); 377 return (type & kStringEncodingMask) == kTwoByteStringTag; 378 } 379 380 381 bool String::IsOneByteRepresentationUnderneath() { 382 uint32_t type = map()->instance_type(); 383 STATIC_ASSERT(kIsIndirectStringTag != 0); 384 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); 385 DCHECK(IsFlat()); 386 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { 387 case kOneByteStringTag: 388 return true; 389 case kTwoByteStringTag: 390 return false; 391 default: // Cons or sliced string. Need to go deeper. 392 return GetUnderlying()->IsOneByteRepresentation(); 393 } 394 } 395 396 397 bool String::IsTwoByteRepresentationUnderneath() { 398 uint32_t type = map()->instance_type(); 399 STATIC_ASSERT(kIsIndirectStringTag != 0); 400 STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0); 401 DCHECK(IsFlat()); 402 switch (type & (kIsIndirectStringMask | kStringEncodingMask)) { 403 case kOneByteStringTag: 404 return false; 405 case kTwoByteStringTag: 406 return true; 407 default: // Cons or sliced string. Need to go deeper. 408 return GetUnderlying()->IsTwoByteRepresentation(); 409 } 410 } 411 412 413 bool String::HasOnlyOneByteChars() { 414 uint32_t type = map()->instance_type(); 415 return (type & kOneByteDataHintMask) == kOneByteDataHintTag || 416 IsOneByteRepresentation(); 417 } 418 419 420 bool StringShape::IsCons() { 421 return (type_ & kStringRepresentationMask) == kConsStringTag; 422 } 423 424 425 bool StringShape::IsSliced() { 426 return (type_ & kStringRepresentationMask) == kSlicedStringTag; 427 } 428 429 430 bool StringShape::IsIndirect() { 431 return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag; 432 } 433 434 435 bool StringShape::IsExternal() { 436 return (type_ & kStringRepresentationMask) == kExternalStringTag; 437 } 438 439 440 bool StringShape::IsSequential() { 441 return (type_ & kStringRepresentationMask) == kSeqStringTag; 442 } 443 444 445 StringRepresentationTag StringShape::representation_tag() { 446 uint32_t tag = (type_ & kStringRepresentationMask); 447 return static_cast<StringRepresentationTag>(tag); 448 } 449 450 451 uint32_t StringShape::encoding_tag() { 452 return type_ & kStringEncodingMask; 453 } 454 455 456 uint32_t StringShape::full_representation_tag() { 457 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); 458 } 459 460 461 STATIC_ASSERT((kStringRepresentationMask | kStringEncodingMask) == 462 Internals::kFullStringRepresentationMask); 463 464 STATIC_ASSERT(static_cast<uint32_t>(kStringEncodingMask) == 465 Internals::kStringEncodingMask); 466 467 468 bool StringShape::IsSequentialOneByte() { 469 return full_representation_tag() == (kSeqStringTag | kOneByteStringTag); 470 } 471 472 473 bool StringShape::IsSequentialTwoByte() { 474 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); 475 } 476 477 478 bool StringShape::IsExternalOneByte() { 479 return full_representation_tag() == (kExternalStringTag | kOneByteStringTag); 480 } 481 482 483 STATIC_ASSERT((kExternalStringTag | kOneByteStringTag) == 484 Internals::kExternalOneByteRepresentationTag); 485 486 STATIC_ASSERT(v8::String::ONE_BYTE_ENCODING == kOneByteStringTag); 487 488 489 bool StringShape::IsExternalTwoByte() { 490 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); 491 } 492 493 494 STATIC_ASSERT((kExternalStringTag | kTwoByteStringTag) == 495 Internals::kExternalTwoByteRepresentationTag); 496 497 STATIC_ASSERT(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag); 498 499 500 uc32 FlatStringReader::Get(int index) { 501 if (is_one_byte_) { 502 return Get<uint8_t>(index); 503 } else { 504 return Get<uc16>(index); 505 } 506 } 507 508 509 template <typename Char> 510 Char FlatStringReader::Get(int index) { 511 DCHECK_EQ(is_one_byte_, sizeof(Char) == 1); 512 DCHECK(0 <= index && index <= length_); 513 if (sizeof(Char) == 1) { 514 return static_cast<Char>(static_cast<const uint8_t*>(start_)[index]); 515 } else { 516 return static_cast<Char>(static_cast<const uc16*>(start_)[index]); 517 } 518 } 519 520 521 Handle<Object> StringTableShape::AsHandle(Isolate* isolate, HashTableKey* key) { 522 return key->AsHandle(isolate); 523 } 524 525 526 Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, 527 HashTableKey* key) { 528 return key->AsHandle(isolate); 529 } 530 531 532 Handle<Object> CodeCacheHashTableShape::AsHandle(Isolate* isolate, 533 HashTableKey* key) { 534 return key->AsHandle(isolate); 535 } 536 537 template <typename Char> 538 class SequentialStringKey : public HashTableKey { 539 public: 540 explicit SequentialStringKey(Vector<const Char> string, uint32_t seed) 541 : string_(string), hash_field_(0), seed_(seed) { } 542 543 uint32_t Hash() override { 544 hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(), 545 string_.length(), 546 seed_); 547 548 uint32_t result = hash_field_ >> String::kHashShift; 549 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 550 return result; 551 } 552 553 554 uint32_t HashForObject(Object* other) override { 555 return String::cast(other)->Hash(); 556 } 557 558 Vector<const Char> string_; 559 uint32_t hash_field_; 560 uint32_t seed_; 561 }; 562 563 564 class OneByteStringKey : public SequentialStringKey<uint8_t> { 565 public: 566 OneByteStringKey(Vector<const uint8_t> str, uint32_t seed) 567 : SequentialStringKey<uint8_t>(str, seed) { } 568 569 bool IsMatch(Object* string) override { 570 return String::cast(string)->IsOneByteEqualTo(string_); 571 } 572 573 Handle<Object> AsHandle(Isolate* isolate) override; 574 }; 575 576 577 class SeqOneByteSubStringKey : public HashTableKey { 578 public: 579 SeqOneByteSubStringKey(Handle<SeqOneByteString> string, int from, int length) 580 : string_(string), from_(from), length_(length) { 581 DCHECK(string_->IsSeqOneByteString()); 582 } 583 584 uint32_t Hash() override { 585 DCHECK(length_ >= 0); 586 DCHECK(from_ + length_ <= string_->length()); 587 const uint8_t* chars = string_->GetChars() + from_; 588 hash_field_ = StringHasher::HashSequentialString( 589 chars, length_, string_->GetHeap()->HashSeed()); 590 uint32_t result = hash_field_ >> String::kHashShift; 591 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 592 return result; 593 } 594 595 uint32_t HashForObject(Object* other) override { 596 return String::cast(other)->Hash(); 597 } 598 599 bool IsMatch(Object* string) override; 600 Handle<Object> AsHandle(Isolate* isolate) override; 601 602 private: 603 Handle<SeqOneByteString> string_; 604 int from_; 605 int length_; 606 uint32_t hash_field_; 607 }; 608 609 610 class TwoByteStringKey : public SequentialStringKey<uc16> { 611 public: 612 explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed) 613 : SequentialStringKey<uc16>(str, seed) { } 614 615 bool IsMatch(Object* string) override { 616 return String::cast(string)->IsTwoByteEqualTo(string_); 617 } 618 619 Handle<Object> AsHandle(Isolate* isolate) override; 620 }; 621 622 623 // Utf8StringKey carries a vector of chars as key. 624 class Utf8StringKey : public HashTableKey { 625 public: 626 explicit Utf8StringKey(Vector<const char> string, uint32_t seed) 627 : string_(string), hash_field_(0), seed_(seed) { } 628 629 bool IsMatch(Object* string) override { 630 return String::cast(string)->IsUtf8EqualTo(string_); 631 } 632 633 uint32_t Hash() override { 634 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; 635 hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_); 636 uint32_t result = hash_field_ >> String::kHashShift; 637 DCHECK(result != 0); // Ensure that the hash value of 0 is never computed. 638 return result; 639 } 640 641 uint32_t HashForObject(Object* other) override { 642 return String::cast(other)->Hash(); 643 } 644 645 Handle<Object> AsHandle(Isolate* isolate) override { 646 if (hash_field_ == 0) Hash(); 647 return isolate->factory()->NewInternalizedStringFromUtf8( 648 string_, chars_, hash_field_); 649 } 650 651 Vector<const char> string_; 652 uint32_t hash_field_; 653 int chars_; // Caches the number of characters when computing the hash code. 654 uint32_t seed_; 655 }; 656 657 658 bool Object::IsNumber() const { 659 return IsSmi() || IsHeapNumber(); 660 } 661 662 663 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE) 664 TYPE_CHECKER(BytecodeArray, BYTECODE_ARRAY_TYPE) 665 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE) 666 667 668 bool Object::IsFiller() const { 669 if (!Object::IsHeapObject()) return false; 670 InstanceType instance_type = HeapObject::cast(this)->map()->instance_type(); 671 return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE; 672 } 673 674 675 676 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size) \ 677 TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE) 678 679 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER) 680 #undef TYPED_ARRAY_TYPE_CHECKER 681 682 683 bool Object::IsFixedTypedArrayBase() const { 684 if (!Object::IsHeapObject()) return false; 685 686 InstanceType instance_type = 687 HeapObject::cast(this)->map()->instance_type(); 688 return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && 689 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE); 690 } 691 692 693 bool Object::IsJSReceiver() const { 694 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 695 return IsHeapObject() && 696 HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE; 697 } 698 699 700 bool Object::IsJSObject() const { 701 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 702 return IsHeapObject() && HeapObject::cast(this)->map()->IsJSObjectMap(); 703 } 704 705 706 bool Object::IsJSProxy() const { 707 if (!Object::IsHeapObject()) return false; 708 return HeapObject::cast(this)->map()->IsJSProxyMap(); 709 } 710 711 712 TYPE_CHECKER(JSSet, JS_SET_TYPE) 713 TYPE_CHECKER(JSMap, JS_MAP_TYPE) 714 TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE) 715 TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE) 716 TYPE_CHECKER(JSIteratorResult, JS_ITERATOR_RESULT_TYPE) 717 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE) 718 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE) 719 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE) 720 TYPE_CHECKER(Map, MAP_TYPE) 721 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) 722 TYPE_CHECKER(WeakFixedArray, FIXED_ARRAY_TYPE) 723 TYPE_CHECKER(TransitionArray, TRANSITION_ARRAY_TYPE) 724 725 726 bool Object::IsJSWeakCollection() const { 727 return IsJSWeakMap() || IsJSWeakSet(); 728 } 729 730 731 bool Object::IsDescriptorArray() const { 732 return IsFixedArray(); 733 } 734 735 736 bool Object::IsArrayList() const { return IsFixedArray(); } 737 738 739 bool Object::IsLayoutDescriptor() const { 740 return IsSmi() || IsFixedTypedArrayBase(); 741 } 742 743 744 bool Object::IsTypeFeedbackVector() const { return IsFixedArray(); } 745 746 747 bool Object::IsTypeFeedbackMetadata() const { return IsFixedArray(); } 748 749 750 bool Object::IsLiteralsArray() const { return IsFixedArray(); } 751 752 753 bool Object::IsDeoptimizationInputData() const { 754 // Must be a fixed array. 755 if (!IsFixedArray()) return false; 756 757 // There's no sure way to detect the difference between a fixed array and 758 // a deoptimization data array. Since this is used for asserts we can 759 // check that the length is zero or else the fixed size plus a multiple of 760 // the entry size. 761 int length = FixedArray::cast(this)->length(); 762 if (length == 0) return true; 763 764 length -= DeoptimizationInputData::kFirstDeoptEntryIndex; 765 return length >= 0 && length % DeoptimizationInputData::kDeoptEntrySize == 0; 766 } 767 768 769 bool Object::IsDeoptimizationOutputData() const { 770 if (!IsFixedArray()) return false; 771 // There's actually no way to see the difference between a fixed array and 772 // a deoptimization data array. Since this is used for asserts we can check 773 // that the length is plausible though. 774 if (FixedArray::cast(this)->length() % 2 != 0) return false; 775 return true; 776 } 777 778 779 bool Object::IsHandlerTable() const { 780 if (!IsFixedArray()) return false; 781 // There's actually no way to see the difference between a fixed array and 782 // a handler table array. 783 return true; 784 } 785 786 787 bool Object::IsDependentCode() const { 788 if (!IsFixedArray()) return false; 789 // There's actually no way to see the difference between a fixed array and 790 // a dependent codes array. 791 return true; 792 } 793 794 795 bool Object::IsContext() const { 796 if (!Object::IsHeapObject()) return false; 797 Map* map = HeapObject::cast(this)->map(); 798 Heap* heap = map->GetHeap(); 799 return (map == heap->function_context_map() || 800 map == heap->catch_context_map() || 801 map == heap->with_context_map() || 802 map == heap->native_context_map() || 803 map == heap->block_context_map() || 804 map == heap->module_context_map() || 805 map == heap->script_context_map()); 806 } 807 808 809 bool Object::IsNativeContext() const { 810 return Object::IsHeapObject() && 811 HeapObject::cast(this)->map() == 812 HeapObject::cast(this)->GetHeap()->native_context_map(); 813 } 814 815 816 bool Object::IsScriptContextTable() const { 817 if (!Object::IsHeapObject()) return false; 818 Map* map = HeapObject::cast(this)->map(); 819 Heap* heap = map->GetHeap(); 820 return map == heap->script_context_table_map(); 821 } 822 823 824 bool Object::IsScopeInfo() const { 825 return Object::IsHeapObject() && 826 HeapObject::cast(this)->map() == 827 HeapObject::cast(this)->GetHeap()->scope_info_map(); 828 } 829 830 831 TYPE_CHECKER(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) 832 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE) 833 834 835 template <> inline bool Is<JSFunction>(Object* obj) { 836 return obj->IsJSFunction(); 837 } 838 839 840 TYPE_CHECKER(Code, CODE_TYPE) 841 TYPE_CHECKER(Oddball, ODDBALL_TYPE) 842 TYPE_CHECKER(Cell, CELL_TYPE) 843 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE) 844 TYPE_CHECKER(WeakCell, WEAK_CELL_TYPE) 845 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE) 846 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE) 847 TYPE_CHECKER(JSModule, JS_MODULE_TYPE) 848 TYPE_CHECKER(JSValue, JS_VALUE_TYPE) 849 TYPE_CHECKER(JSDate, JS_DATE_TYPE) 850 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) 851 852 853 bool Object::IsStringWrapper() const { 854 return IsJSValue() && JSValue::cast(this)->value()->IsString(); 855 } 856 857 858 TYPE_CHECKER(Foreign, FOREIGN_TYPE) 859 860 861 bool Object::IsBoolean() const { 862 return IsOddball() && 863 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); 864 } 865 866 867 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE) 868 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE) 869 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE) 870 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE) 871 872 873 bool Object::IsJSArrayBufferView() const { 874 return IsJSDataView() || IsJSTypedArray(); 875 } 876 877 878 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE) 879 880 881 template <> inline bool Is<JSArray>(Object* obj) { 882 return obj->IsJSArray(); 883 } 884 885 886 bool Object::IsHashTable() const { 887 return Object::IsHeapObject() && 888 HeapObject::cast(this)->map() == 889 HeapObject::cast(this)->GetHeap()->hash_table_map(); 890 } 891 892 893 bool Object::IsWeakHashTable() const { 894 return IsHashTable(); 895 } 896 897 898 bool Object::IsDictionary() const { 899 return IsHashTable() && 900 this != HeapObject::cast(this)->GetHeap()->string_table(); 901 } 902 903 904 bool Object::IsNameDictionary() const { 905 return IsDictionary(); 906 } 907 908 909 bool Object::IsGlobalDictionary() const { return IsDictionary(); } 910 911 912 bool Object::IsSeededNumberDictionary() const { 913 return IsDictionary(); 914 } 915 916 917 bool Object::IsUnseededNumberDictionary() const { 918 return IsDictionary(); 919 } 920 921 922 bool Object::IsStringTable() const { 923 return IsHashTable(); 924 } 925 926 927 bool Object::IsNormalizedMapCache() const { 928 return NormalizedMapCache::IsNormalizedMapCache(this); 929 } 930 931 932 int NormalizedMapCache::GetIndex(Handle<Map> map) { 933 return map->Hash() % NormalizedMapCache::kEntries; 934 } 935 936 937 bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) { 938 if (!obj->IsFixedArray()) return false; 939 if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) { 940 return false; 941 } 942 #ifdef VERIFY_HEAP 943 if (FLAG_verify_heap) { 944 reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))-> 945 NormalizedMapCacheVerify(); 946 } 947 #endif 948 return true; 949 } 950 951 952 bool Object::IsCompilationCacheTable() const { 953 return IsHashTable(); 954 } 955 956 957 bool Object::IsCodeCacheHashTable() const { 958 return IsHashTable(); 959 } 960 961 962 bool Object::IsPolymorphicCodeCacheHashTable() const { 963 return IsHashTable(); 964 } 965 966 967 bool Object::IsMapCache() const { 968 return IsHashTable(); 969 } 970 971 972 bool Object::IsObjectHashTable() const { 973 return IsHashTable(); 974 } 975 976 977 bool Object::IsOrderedHashTable() const { 978 return IsHeapObject() && 979 HeapObject::cast(this)->map() == 980 HeapObject::cast(this)->GetHeap()->ordered_hash_table_map(); 981 } 982 983 984 bool Object::IsOrderedHashSet() const { 985 return IsOrderedHashTable(); 986 } 987 988 989 bool Object::IsOrderedHashMap() const { 990 return IsOrderedHashTable(); 991 } 992 993 994 bool Object::IsPrimitive() const { 995 return IsSmi() || HeapObject::cast(this)->map()->IsPrimitiveMap(); 996 } 997 998 999 bool Object::IsJSGlobalProxy() const { 1000 bool result = IsHeapObject() && 1001 (HeapObject::cast(this)->map()->instance_type() == 1002 JS_GLOBAL_PROXY_TYPE); 1003 DCHECK(!result || 1004 HeapObject::cast(this)->map()->is_access_check_needed()); 1005 return result; 1006 } 1007 1008 1009 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE) 1010 1011 1012 bool Object::IsUndetectableObject() const { 1013 return IsHeapObject() 1014 && HeapObject::cast(this)->map()->is_undetectable(); 1015 } 1016 1017 1018 bool Object::IsAccessCheckNeeded() const { 1019 if (!IsHeapObject()) return false; 1020 if (IsJSGlobalProxy()) { 1021 const JSGlobalProxy* proxy = JSGlobalProxy::cast(this); 1022 JSGlobalObject* global = proxy->GetIsolate()->context()->global_object(); 1023 return proxy->IsDetachedFrom(global); 1024 } 1025 return HeapObject::cast(this)->map()->is_access_check_needed(); 1026 } 1027 1028 1029 bool Object::IsStruct() const { 1030 if (!IsHeapObject()) return false; 1031 switch (HeapObject::cast(this)->map()->instance_type()) { 1032 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true; 1033 STRUCT_LIST(MAKE_STRUCT_CASE) 1034 #undef MAKE_STRUCT_CASE 1035 default: return false; 1036 } 1037 } 1038 1039 1040 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ 1041 bool Object::Is##Name() const { \ 1042 return Object::IsHeapObject() \ 1043 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \ 1044 } 1045 STRUCT_LIST(MAKE_STRUCT_PREDICATE) 1046 #undef MAKE_STRUCT_PREDICATE 1047 1048 1049 bool Object::IsUndefined() const { 1050 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined; 1051 } 1052 1053 1054 bool Object::IsNull() const { 1055 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull; 1056 } 1057 1058 1059 bool Object::IsTheHole() const { 1060 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole; 1061 } 1062 1063 1064 bool Object::IsException() const { 1065 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException; 1066 } 1067 1068 1069 bool Object::IsUninitialized() const { 1070 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized; 1071 } 1072 1073 1074 bool Object::IsTrue() const { 1075 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue; 1076 } 1077 1078 1079 bool Object::IsFalse() const { 1080 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse; 1081 } 1082 1083 1084 bool Object::IsArgumentsMarker() const { 1085 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker; 1086 } 1087 1088 1089 double Object::Number() const { 1090 DCHECK(IsNumber()); 1091 return IsSmi() 1092 ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value()) 1093 : reinterpret_cast<const HeapNumber*>(this)->value(); 1094 } 1095 1096 1097 bool Object::IsNaN() const { 1098 return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value()); 1099 } 1100 1101 1102 bool Object::IsMinusZero() const { 1103 return this->IsHeapNumber() && 1104 i::IsMinusZero(HeapNumber::cast(this)->value()); 1105 } 1106 1107 1108 Representation Object::OptimalRepresentation() { 1109 if (!FLAG_track_fields) return Representation::Tagged(); 1110 if (IsSmi()) { 1111 return Representation::Smi(); 1112 } else if (FLAG_track_double_fields && IsHeapNumber()) { 1113 return Representation::Double(); 1114 } else if (FLAG_track_computed_fields && IsUninitialized()) { 1115 return Representation::None(); 1116 } else if (FLAG_track_heap_object_fields) { 1117 DCHECK(IsHeapObject()); 1118 return Representation::HeapObject(); 1119 } else { 1120 return Representation::Tagged(); 1121 } 1122 } 1123 1124 1125 ElementsKind Object::OptimalElementsKind() { 1126 if (IsSmi()) return FAST_SMI_ELEMENTS; 1127 if (IsNumber()) return FAST_DOUBLE_ELEMENTS; 1128 return FAST_ELEMENTS; 1129 } 1130 1131 1132 bool Object::FitsRepresentation(Representation representation) { 1133 if (FLAG_track_fields && representation.IsNone()) { 1134 return false; 1135 } else if (FLAG_track_fields && representation.IsSmi()) { 1136 return IsSmi(); 1137 } else if (FLAG_track_double_fields && representation.IsDouble()) { 1138 return IsMutableHeapNumber() || IsNumber(); 1139 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 1140 return IsHeapObject(); 1141 } 1142 return true; 1143 } 1144 1145 1146 // static 1147 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate, 1148 Handle<Object> object) { 1149 return ToObject( 1150 isolate, object, handle(isolate->context()->native_context(), isolate)); 1151 } 1152 1153 1154 // static 1155 MaybeHandle<Object> Object::ToPrimitive(Handle<Object> input, 1156 ToPrimitiveHint hint) { 1157 if (input->IsPrimitive()) return input; 1158 return JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input), hint); 1159 } 1160 1161 1162 bool Object::HasSpecificClassOf(String* name) { 1163 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name); 1164 } 1165 1166 1167 MaybeHandle<Object> Object::GetProperty(Handle<Object> object, 1168 Handle<Name> name, 1169 LanguageMode language_mode) { 1170 LookupIterator it(object, name); 1171 return GetProperty(&it, language_mode); 1172 } 1173 1174 1175 MaybeHandle<Object> Object::GetElement(Isolate* isolate, Handle<Object> object, 1176 uint32_t index, 1177 LanguageMode language_mode) { 1178 LookupIterator it(isolate, object, index); 1179 return GetProperty(&it, language_mode); 1180 } 1181 1182 1183 MaybeHandle<Object> Object::SetElement(Isolate* isolate, Handle<Object> object, 1184 uint32_t index, Handle<Object> value, 1185 LanguageMode language_mode) { 1186 LookupIterator it(isolate, object, index); 1187 MAYBE_RETURN_NULL( 1188 SetProperty(&it, value, language_mode, MAY_BE_STORE_FROM_KEYED)); 1189 return value; 1190 } 1191 1192 1193 MaybeHandle<Object> Object::GetPrototype(Isolate* isolate, 1194 Handle<Object> receiver) { 1195 // We don't expect access checks to be needed on JSProxy objects. 1196 DCHECK(!receiver->IsAccessCheckNeeded() || receiver->IsJSObject()); 1197 PrototypeIterator iter(isolate, receiver, 1198 PrototypeIterator::START_AT_RECEIVER); 1199 do { 1200 if (!iter.AdvanceFollowingProxies()) return MaybeHandle<Object>(); 1201 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); 1202 return PrototypeIterator::GetCurrent(iter); 1203 } 1204 1205 1206 MaybeHandle<Object> Object::GetProperty(Isolate* isolate, Handle<Object> object, 1207 const char* name, 1208 LanguageMode language_mode) { 1209 Handle<String> str = isolate->factory()->InternalizeUtf8String(name); 1210 return GetProperty(object, str, language_mode); 1211 } 1212 1213 1214 #define FIELD_ADDR(p, offset) \ 1215 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) 1216 1217 #define FIELD_ADDR_CONST(p, offset) \ 1218 (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag) 1219 1220 #define READ_FIELD(p, offset) \ 1221 (*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset))) 1222 1223 #define ACQUIRE_READ_FIELD(p, offset) \ 1224 reinterpret_cast<Object*>(base::Acquire_Load( \ 1225 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset)))) 1226 1227 #define NOBARRIER_READ_FIELD(p, offset) \ 1228 reinterpret_cast<Object*>(base::NoBarrier_Load( \ 1229 reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset)))) 1230 1231 #define WRITE_FIELD(p, offset, value) \ 1232 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) 1233 1234 #define RELEASE_WRITE_FIELD(p, offset, value) \ 1235 base::Release_Store( \ 1236 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \ 1237 reinterpret_cast<base::AtomicWord>(value)); 1238 1239 #define NOBARRIER_WRITE_FIELD(p, offset, value) \ 1240 base::NoBarrier_Store( \ 1241 reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \ 1242 reinterpret_cast<base::AtomicWord>(value)); 1243 1244 #define WRITE_BARRIER(heap, object, offset, value) \ 1245 heap->incremental_marking()->RecordWrite( \ 1246 object, HeapObject::RawField(object, offset), value); \ 1247 if (heap->InNewSpace(value)) { \ 1248 heap->RecordWrite(object->address(), offset); \ 1249 } 1250 1251 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode) \ 1252 if (mode != SKIP_WRITE_BARRIER) { \ 1253 if (mode == UPDATE_WRITE_BARRIER) { \ 1254 heap->incremental_marking()->RecordWrite( \ 1255 object, HeapObject::RawField(object, offset), value); \ 1256 } \ 1257 if (heap->InNewSpace(value)) { \ 1258 heap->RecordWrite(object->address(), offset); \ 1259 } \ 1260 } 1261 1262 #define READ_DOUBLE_FIELD(p, offset) \ 1263 ReadDoubleValue(FIELD_ADDR_CONST(p, offset)) 1264 1265 #define WRITE_DOUBLE_FIELD(p, offset, value) \ 1266 WriteDoubleValue(FIELD_ADDR(p, offset), value) 1267 1268 #define READ_INT_FIELD(p, offset) \ 1269 (*reinterpret_cast<const int*>(FIELD_ADDR_CONST(p, offset))) 1270 1271 #define WRITE_INT_FIELD(p, offset, value) \ 1272 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) 1273 1274 #define READ_INTPTR_FIELD(p, offset) \ 1275 (*reinterpret_cast<const intptr_t*>(FIELD_ADDR_CONST(p, offset))) 1276 1277 #define WRITE_INTPTR_FIELD(p, offset, value) \ 1278 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value) 1279 1280 #define READ_UINT8_FIELD(p, offset) \ 1281 (*reinterpret_cast<const uint8_t*>(FIELD_ADDR_CONST(p, offset))) 1282 1283 #define WRITE_UINT8_FIELD(p, offset, value) \ 1284 (*reinterpret_cast<uint8_t*>(FIELD_ADDR(p, offset)) = value) 1285 1286 #define READ_INT8_FIELD(p, offset) \ 1287 (*reinterpret_cast<const int8_t*>(FIELD_ADDR_CONST(p, offset))) 1288 1289 #define WRITE_INT8_FIELD(p, offset, value) \ 1290 (*reinterpret_cast<int8_t*>(FIELD_ADDR(p, offset)) = value) 1291 1292 #define READ_UINT16_FIELD(p, offset) \ 1293 (*reinterpret_cast<const uint16_t*>(FIELD_ADDR_CONST(p, offset))) 1294 1295 #define WRITE_UINT16_FIELD(p, offset, value) \ 1296 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value) 1297 1298 #define READ_INT16_FIELD(p, offset) \ 1299 (*reinterpret_cast<const int16_t*>(FIELD_ADDR_CONST(p, offset))) 1300 1301 #define WRITE_INT16_FIELD(p, offset, value) \ 1302 (*reinterpret_cast<int16_t*>(FIELD_ADDR(p, offset)) = value) 1303 1304 #define READ_UINT32_FIELD(p, offset) \ 1305 (*reinterpret_cast<const uint32_t*>(FIELD_ADDR_CONST(p, offset))) 1306 1307 #define WRITE_UINT32_FIELD(p, offset, value) \ 1308 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value) 1309 1310 #define READ_INT32_FIELD(p, offset) \ 1311 (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset))) 1312 1313 #define WRITE_INT32_FIELD(p, offset, value) \ 1314 (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value) 1315 1316 #define READ_FLOAT_FIELD(p, offset) \ 1317 (*reinterpret_cast<const float*>(FIELD_ADDR_CONST(p, offset))) 1318 1319 #define WRITE_FLOAT_FIELD(p, offset, value) \ 1320 (*reinterpret_cast<float*>(FIELD_ADDR(p, offset)) = value) 1321 1322 #define READ_UINT64_FIELD(p, offset) \ 1323 (*reinterpret_cast<const uint64_t*>(FIELD_ADDR_CONST(p, offset))) 1324 1325 #define WRITE_UINT64_FIELD(p, offset, value) \ 1326 (*reinterpret_cast<uint64_t*>(FIELD_ADDR(p, offset)) = value) 1327 1328 #define READ_INT64_FIELD(p, offset) \ 1329 (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset))) 1330 1331 #define WRITE_INT64_FIELD(p, offset, value) \ 1332 (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value) 1333 1334 #define READ_BYTE_FIELD(p, offset) \ 1335 (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset))) 1336 1337 #define NOBARRIER_READ_BYTE_FIELD(p, offset) \ 1338 static_cast<byte>(base::NoBarrier_Load( \ 1339 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)))) 1340 1341 #define WRITE_BYTE_FIELD(p, offset, value) \ 1342 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value) 1343 1344 #define NOBARRIER_WRITE_BYTE_FIELD(p, offset, value) \ 1345 base::NoBarrier_Store( \ 1346 reinterpret_cast<base::Atomic8*>(FIELD_ADDR(p, offset)), \ 1347 static_cast<base::Atomic8>(value)); 1348 1349 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) { 1350 return reinterpret_cast<Object**>(FIELD_ADDR(obj, byte_offset)); 1351 } 1352 1353 1354 MapWord MapWord::FromMap(const Map* map) { 1355 return MapWord(reinterpret_cast<uintptr_t>(map)); 1356 } 1357 1358 1359 Map* MapWord::ToMap() { 1360 return reinterpret_cast<Map*>(value_); 1361 } 1362 1363 1364 bool MapWord::IsForwardingAddress() { 1365 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_)); 1366 } 1367 1368 1369 MapWord MapWord::FromForwardingAddress(HeapObject* object) { 1370 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag; 1371 return MapWord(reinterpret_cast<uintptr_t>(raw)); 1372 } 1373 1374 1375 HeapObject* MapWord::ToForwardingAddress() { 1376 DCHECK(IsForwardingAddress()); 1377 return HeapObject::FromAddress(reinterpret_cast<Address>(value_)); 1378 } 1379 1380 1381 #ifdef VERIFY_HEAP 1382 void HeapObject::VerifyObjectField(int offset) { 1383 VerifyPointer(READ_FIELD(this, offset)); 1384 } 1385 1386 void HeapObject::VerifySmiField(int offset) { 1387 CHECK(READ_FIELD(this, offset)->IsSmi()); 1388 } 1389 #endif 1390 1391 1392 Heap* HeapObject::GetHeap() const { 1393 Heap* heap = 1394 MemoryChunk::FromAddress(reinterpret_cast<const byte*>(this))->heap(); 1395 SLOW_DCHECK(heap != NULL); 1396 return heap; 1397 } 1398 1399 1400 Isolate* HeapObject::GetIsolate() const { 1401 return GetHeap()->isolate(); 1402 } 1403 1404 1405 Map* HeapObject::map() const { 1406 #ifdef DEBUG 1407 // Clear mark potentially added by PathTracer. 1408 uintptr_t raw_value = 1409 map_word().ToRawValue() & ~static_cast<uintptr_t>(PathTracer::kMarkTag); 1410 return MapWord::FromRawValue(raw_value).ToMap(); 1411 #else 1412 return map_word().ToMap(); 1413 #endif 1414 } 1415 1416 1417 void HeapObject::set_map(Map* value) { 1418 set_map_word(MapWord::FromMap(value)); 1419 if (value != NULL) { 1420 // TODO(1600) We are passing NULL as a slot because maps can never be on 1421 // evacuation candidate. 1422 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value); 1423 } 1424 } 1425 1426 1427 Map* HeapObject::synchronized_map() { 1428 return synchronized_map_word().ToMap(); 1429 } 1430 1431 1432 void HeapObject::synchronized_set_map(Map* value) { 1433 synchronized_set_map_word(MapWord::FromMap(value)); 1434 if (value != NULL) { 1435 // TODO(1600) We are passing NULL as a slot because maps can never be on 1436 // evacuation candidate. 1437 value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value); 1438 } 1439 } 1440 1441 1442 void HeapObject::synchronized_set_map_no_write_barrier(Map* value) { 1443 synchronized_set_map_word(MapWord::FromMap(value)); 1444 } 1445 1446 1447 // Unsafe accessor omitting write barrier. 1448 void HeapObject::set_map_no_write_barrier(Map* value) { 1449 set_map_word(MapWord::FromMap(value)); 1450 } 1451 1452 1453 MapWord HeapObject::map_word() const { 1454 return MapWord( 1455 reinterpret_cast<uintptr_t>(NOBARRIER_READ_FIELD(this, kMapOffset))); 1456 } 1457 1458 1459 void HeapObject::set_map_word(MapWord map_word) { 1460 NOBARRIER_WRITE_FIELD( 1461 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1462 } 1463 1464 1465 MapWord HeapObject::synchronized_map_word() const { 1466 return MapWord( 1467 reinterpret_cast<uintptr_t>(ACQUIRE_READ_FIELD(this, kMapOffset))); 1468 } 1469 1470 1471 void HeapObject::synchronized_set_map_word(MapWord map_word) { 1472 RELEASE_WRITE_FIELD( 1473 this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1474 } 1475 1476 1477 int HeapObject::Size() { 1478 return SizeFromMap(map()); 1479 } 1480 1481 1482 double HeapNumber::value() const { 1483 return READ_DOUBLE_FIELD(this, kValueOffset); 1484 } 1485 1486 1487 void HeapNumber::set_value(double value) { 1488 WRITE_DOUBLE_FIELD(this, kValueOffset, value); 1489 } 1490 1491 1492 int HeapNumber::get_exponent() { 1493 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> 1494 kExponentShift) - kExponentBias; 1495 } 1496 1497 1498 int HeapNumber::get_sign() { 1499 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; 1500 } 1501 1502 1503 bool Simd128Value::Equals(Simd128Value* that) { 1504 #define SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \ 1505 if (this->Is##Type()) { \ 1506 if (!that->Is##Type()) return false; \ 1507 return Type::cast(this)->Equals(Type::cast(that)); \ 1508 } 1509 SIMD128_TYPES(SIMD128_VALUE) 1510 #undef SIMD128_VALUE 1511 return false; 1512 } 1513 1514 1515 // static 1516 bool Simd128Value::Equals(Handle<Simd128Value> one, Handle<Simd128Value> two) { 1517 return one->Equals(*two); 1518 } 1519 1520 1521 #define SIMD128_VALUE_EQUALS(TYPE, Type, type, lane_count, lane_type) \ 1522 bool Type::Equals(Type* that) { \ 1523 for (int lane = 0; lane < lane_count; ++lane) { \ 1524 if (this->get_lane(lane) != that->get_lane(lane)) return false; \ 1525 } \ 1526 return true; \ 1527 } 1528 SIMD128_TYPES(SIMD128_VALUE_EQUALS) 1529 #undef SIMD128_VALUE_EQUALS 1530 1531 1532 #if defined(V8_TARGET_LITTLE_ENDIAN) 1533 #define SIMD128_READ_LANE(lane_type, lane_count, field_type, field_size) \ 1534 lane_type value = \ 1535 READ_##field_type##_FIELD(this, kValueOffset + lane * field_size); 1536 #elif defined(V8_TARGET_BIG_ENDIAN) 1537 #define SIMD128_READ_LANE(lane_type, lane_count, field_type, field_size) \ 1538 lane_type value = READ_##field_type##_FIELD( \ 1539 this, kValueOffset + (lane_count - lane - 1) * field_size); 1540 #else 1541 #error Unknown byte ordering 1542 #endif 1543 1544 #if defined(V8_TARGET_LITTLE_ENDIAN) 1545 #define SIMD128_WRITE_LANE(lane_count, field_type, field_size, value) \ 1546 WRITE_##field_type##_FIELD(this, kValueOffset + lane * field_size, value); 1547 #elif defined(V8_TARGET_BIG_ENDIAN) 1548 #define SIMD128_WRITE_LANE(lane_count, field_type, field_size, value) \ 1549 WRITE_##field_type##_FIELD( \ 1550 this, kValueOffset + (lane_count - lane - 1) * field_size, value); 1551 #else 1552 #error Unknown byte ordering 1553 #endif 1554 1555 #define SIMD128_NUMERIC_LANE_FNS(type, lane_type, lane_count, field_type, \ 1556 field_size) \ 1557 lane_type type::get_lane(int lane) const { \ 1558 DCHECK(lane < lane_count && lane >= 0); \ 1559 SIMD128_READ_LANE(lane_type, lane_count, field_type, field_size) \ 1560 return value; \ 1561 } \ 1562 \ 1563 void type::set_lane(int lane, lane_type value) { \ 1564 DCHECK(lane < lane_count && lane >= 0); \ 1565 SIMD128_WRITE_LANE(lane_count, field_type, field_size, value) \ 1566 } 1567 1568 SIMD128_NUMERIC_LANE_FNS(Float32x4, float, 4, FLOAT, kFloatSize) 1569 SIMD128_NUMERIC_LANE_FNS(Int32x4, int32_t, 4, INT32, kInt32Size) 1570 SIMD128_NUMERIC_LANE_FNS(Uint32x4, uint32_t, 4, UINT32, kInt32Size) 1571 SIMD128_NUMERIC_LANE_FNS(Int16x8, int16_t, 8, INT16, kShortSize) 1572 SIMD128_NUMERIC_LANE_FNS(Uint16x8, uint16_t, 8, UINT16, kShortSize) 1573 SIMD128_NUMERIC_LANE_FNS(Int8x16, int8_t, 16, INT8, kCharSize) 1574 SIMD128_NUMERIC_LANE_FNS(Uint8x16, uint8_t, 16, UINT8, kCharSize) 1575 #undef SIMD128_NUMERIC_LANE_FNS 1576 1577 1578 #define SIMD128_BOOLEAN_LANE_FNS(type, lane_type, lane_count, field_type, \ 1579 field_size) \ 1580 bool type::get_lane(int lane) const { \ 1581 DCHECK(lane < lane_count && lane >= 0); \ 1582 SIMD128_READ_LANE(lane_type, lane_count, field_type, field_size) \ 1583 DCHECK(value == 0 || value == -1); \ 1584 return value != 0; \ 1585 } \ 1586 \ 1587 void type::set_lane(int lane, bool value) { \ 1588 DCHECK(lane < lane_count && lane >= 0); \ 1589 int32_t int_val = value ? -1 : 0; \ 1590 SIMD128_WRITE_LANE(lane_count, field_type, field_size, int_val) \ 1591 } 1592 1593 SIMD128_BOOLEAN_LANE_FNS(Bool32x4, int32_t, 4, INT32, kInt32Size) 1594 SIMD128_BOOLEAN_LANE_FNS(Bool16x8, int16_t, 8, INT16, kShortSize) 1595 SIMD128_BOOLEAN_LANE_FNS(Bool8x16, int8_t, 16, INT8, kCharSize) 1596 #undef SIMD128_BOOLEAN_LANE_FNS 1597 1598 #undef SIMD128_READ_LANE 1599 #undef SIMD128_WRITE_LANE 1600 1601 1602 ACCESSORS(JSReceiver, properties, FixedArray, kPropertiesOffset) 1603 1604 1605 Object** FixedArray::GetFirstElementAddress() { 1606 return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0))); 1607 } 1608 1609 1610 bool FixedArray::ContainsOnlySmisOrHoles() { 1611 Object* the_hole = GetHeap()->the_hole_value(); 1612 Object** current = GetFirstElementAddress(); 1613 for (int i = 0; i < length(); ++i) { 1614 Object* candidate = *current++; 1615 if (!candidate->IsSmi() && candidate != the_hole) return false; 1616 } 1617 return true; 1618 } 1619 1620 1621 FixedArrayBase* JSObject::elements() const { 1622 Object* array = READ_FIELD(this, kElementsOffset); 1623 return static_cast<FixedArrayBase*>(array); 1624 } 1625 1626 1627 void AllocationSite::Initialize() { 1628 set_transition_info(Smi::FromInt(0)); 1629 SetElementsKind(GetInitialFastElementsKind()); 1630 set_nested_site(Smi::FromInt(0)); 1631 set_pretenure_data(0); 1632 set_pretenure_create_count(0); 1633 set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()), 1634 SKIP_WRITE_BARRIER); 1635 } 1636 1637 1638 bool AllocationSite::IsZombie() { return pretenure_decision() == kZombie; } 1639 1640 1641 bool AllocationSite::IsMaybeTenure() { 1642 return pretenure_decision() == kMaybeTenure; 1643 } 1644 1645 1646 bool AllocationSite::PretenuringDecisionMade() { 1647 return pretenure_decision() != kUndecided; 1648 } 1649 1650 1651 void AllocationSite::MarkZombie() { 1652 DCHECK(!IsZombie()); 1653 Initialize(); 1654 set_pretenure_decision(kZombie); 1655 } 1656 1657 1658 ElementsKind AllocationSite::GetElementsKind() { 1659 DCHECK(!SitePointsToLiteral()); 1660 int value = Smi::cast(transition_info())->value(); 1661 return ElementsKindBits::decode(value); 1662 } 1663 1664 1665 void AllocationSite::SetElementsKind(ElementsKind kind) { 1666 int value = Smi::cast(transition_info())->value(); 1667 set_transition_info(Smi::FromInt(ElementsKindBits::update(value, kind)), 1668 SKIP_WRITE_BARRIER); 1669 } 1670 1671 1672 bool AllocationSite::CanInlineCall() { 1673 int value = Smi::cast(transition_info())->value(); 1674 return DoNotInlineBit::decode(value) == 0; 1675 } 1676 1677 1678 void AllocationSite::SetDoNotInlineCall() { 1679 int value = Smi::cast(transition_info())->value(); 1680 set_transition_info(Smi::FromInt(DoNotInlineBit::update(value, true)), 1681 SKIP_WRITE_BARRIER); 1682 } 1683 1684 1685 bool AllocationSite::SitePointsToLiteral() { 1686 // If transition_info is a smi, then it represents an ElementsKind 1687 // for a constructed array. Otherwise, it must be a boilerplate 1688 // for an object or array literal. 1689 return transition_info()->IsJSArray() || transition_info()->IsJSObject(); 1690 } 1691 1692 1693 // Heuristic: We only need to create allocation site info if the boilerplate 1694 // elements kind is the initial elements kind. 1695 AllocationSiteMode AllocationSite::GetMode( 1696 ElementsKind boilerplate_elements_kind) { 1697 if (IsFastSmiElementsKind(boilerplate_elements_kind)) { 1698 return TRACK_ALLOCATION_SITE; 1699 } 1700 1701 return DONT_TRACK_ALLOCATION_SITE; 1702 } 1703 1704 1705 AllocationSiteMode AllocationSite::GetMode(ElementsKind from, 1706 ElementsKind to) { 1707 if (IsFastSmiElementsKind(from) && 1708 IsMoreGeneralElementsKindTransition(from, to)) { 1709 return TRACK_ALLOCATION_SITE; 1710 } 1711 1712 return DONT_TRACK_ALLOCATION_SITE; 1713 } 1714 1715 1716 inline bool AllocationSite::CanTrack(InstanceType type) { 1717 if (FLAG_allocation_site_pretenuring) { 1718 return type == JS_ARRAY_TYPE || 1719 type == JS_OBJECT_TYPE || 1720 type < FIRST_NONSTRING_TYPE; 1721 } 1722 return type == JS_ARRAY_TYPE; 1723 } 1724 1725 1726 AllocationSite::PretenureDecision AllocationSite::pretenure_decision() { 1727 int value = pretenure_data(); 1728 return PretenureDecisionBits::decode(value); 1729 } 1730 1731 1732 void AllocationSite::set_pretenure_decision(PretenureDecision decision) { 1733 int value = pretenure_data(); 1734 set_pretenure_data(PretenureDecisionBits::update(value, decision)); 1735 } 1736 1737 1738 bool AllocationSite::deopt_dependent_code() { 1739 int value = pretenure_data(); 1740 return DeoptDependentCodeBit::decode(value); 1741 } 1742 1743 1744 void AllocationSite::set_deopt_dependent_code(bool deopt) { 1745 int value = pretenure_data(); 1746 set_pretenure_data(DeoptDependentCodeBit::update(value, deopt)); 1747 } 1748 1749 1750 int AllocationSite::memento_found_count() { 1751 int value = pretenure_data(); 1752 return MementoFoundCountBits::decode(value); 1753 } 1754 1755 1756 inline void AllocationSite::set_memento_found_count(int count) { 1757 int value = pretenure_data(); 1758 // Verify that we can count more mementos than we can possibly find in one 1759 // new space collection. 1760 DCHECK((GetHeap()->MaxSemiSpaceSize() / 1761 (Heap::kMinObjectSizeInWords * kPointerSize + 1762 AllocationMemento::kSize)) < MementoFoundCountBits::kMax); 1763 DCHECK(count < MementoFoundCountBits::kMax); 1764 set_pretenure_data(MementoFoundCountBits::update(value, count)); 1765 } 1766 1767 1768 int AllocationSite::memento_create_count() { return pretenure_create_count(); } 1769 1770 1771 void AllocationSite::set_memento_create_count(int count) { 1772 set_pretenure_create_count(count); 1773 } 1774 1775 1776 bool AllocationSite::IncrementMementoFoundCount(int increment) { 1777 if (IsZombie()) return false; 1778 1779 int value = memento_found_count(); 1780 set_memento_found_count(value + increment); 1781 return memento_found_count() >= kPretenureMinimumCreated; 1782 } 1783 1784 1785 inline void AllocationSite::IncrementMementoCreateCount() { 1786 DCHECK(FLAG_allocation_site_pretenuring); 1787 int value = memento_create_count(); 1788 set_memento_create_count(value + 1); 1789 } 1790 1791 1792 inline bool AllocationSite::MakePretenureDecision( 1793 PretenureDecision current_decision, 1794 double ratio, 1795 bool maximum_size_scavenge) { 1796 // Here we just allow state transitions from undecided or maybe tenure 1797 // to don't tenure, maybe tenure, or tenure. 1798 if ((current_decision == kUndecided || current_decision == kMaybeTenure)) { 1799 if (ratio >= kPretenureRatio) { 1800 // We just transition into tenure state when the semi-space was at 1801 // maximum capacity. 1802 if (maximum_size_scavenge) { 1803 set_deopt_dependent_code(true); 1804 set_pretenure_decision(kTenure); 1805 // Currently we just need to deopt when we make a state transition to 1806 // tenure. 1807 return true; 1808 } 1809 set_pretenure_decision(kMaybeTenure); 1810 } else { 1811 set_pretenure_decision(kDontTenure); 1812 } 1813 } 1814 return false; 1815 } 1816 1817 1818 inline bool AllocationSite::DigestPretenuringFeedback( 1819 bool maximum_size_scavenge) { 1820 bool deopt = false; 1821 int create_count = memento_create_count(); 1822 int found_count = memento_found_count(); 1823 bool minimum_mementos_created = create_count >= kPretenureMinimumCreated; 1824 double ratio = 1825 minimum_mementos_created || FLAG_trace_pretenuring_statistics ? 1826 static_cast<double>(found_count) / create_count : 0.0; 1827 PretenureDecision current_decision = pretenure_decision(); 1828 1829 if (minimum_mementos_created) { 1830 deopt = MakePretenureDecision( 1831 current_decision, ratio, maximum_size_scavenge); 1832 } 1833 1834 if (FLAG_trace_pretenuring_statistics) { 1835 PrintIsolate(GetIsolate(), 1836 "pretenuring: AllocationSite(%p): (created, found, ratio) " 1837 "(%d, %d, %f) %s => %s\n", 1838 this, create_count, found_count, ratio, 1839 PretenureDecisionName(current_decision), 1840 PretenureDecisionName(pretenure_decision())); 1841 } 1842 1843 // Clear feedback calculation fields until the next gc. 1844 set_memento_found_count(0); 1845 set_memento_create_count(0); 1846 return deopt; 1847 } 1848 1849 1850 bool AllocationMemento::IsValid() { 1851 return allocation_site()->IsAllocationSite() && 1852 !AllocationSite::cast(allocation_site())->IsZombie(); 1853 } 1854 1855 1856 AllocationSite* AllocationMemento::GetAllocationSite() { 1857 DCHECK(IsValid()); 1858 return AllocationSite::cast(allocation_site()); 1859 } 1860 1861 1862 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) { 1863 JSObject::ValidateElements(object); 1864 ElementsKind elements_kind = object->map()->elements_kind(); 1865 if (!IsFastObjectElementsKind(elements_kind)) { 1866 if (IsFastHoleyElementsKind(elements_kind)) { 1867 TransitionElementsKind(object, FAST_HOLEY_ELEMENTS); 1868 } else { 1869 TransitionElementsKind(object, FAST_ELEMENTS); 1870 } 1871 } 1872 } 1873 1874 1875 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1876 Object** objects, 1877 uint32_t count, 1878 EnsureElementsMode mode) { 1879 ElementsKind current_kind = object->map()->elements_kind(); 1880 ElementsKind target_kind = current_kind; 1881 { 1882 DisallowHeapAllocation no_allocation; 1883 DCHECK(mode != ALLOW_COPIED_DOUBLE_ELEMENTS); 1884 bool is_holey = IsFastHoleyElementsKind(current_kind); 1885 if (current_kind == FAST_HOLEY_ELEMENTS) return; 1886 Heap* heap = object->GetHeap(); 1887 Object* the_hole = heap->the_hole_value(); 1888 for (uint32_t i = 0; i < count; ++i) { 1889 Object* current = *objects++; 1890 if (current == the_hole) { 1891 is_holey = true; 1892 target_kind = GetHoleyElementsKind(target_kind); 1893 } else if (!current->IsSmi()) { 1894 if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) { 1895 if (IsFastSmiElementsKind(target_kind)) { 1896 if (is_holey) { 1897 target_kind = FAST_HOLEY_DOUBLE_ELEMENTS; 1898 } else { 1899 target_kind = FAST_DOUBLE_ELEMENTS; 1900 } 1901 } 1902 } else if (is_holey) { 1903 target_kind = FAST_HOLEY_ELEMENTS; 1904 break; 1905 } else { 1906 target_kind = FAST_ELEMENTS; 1907 } 1908 } 1909 } 1910 } 1911 if (target_kind != current_kind) { 1912 TransitionElementsKind(object, target_kind); 1913 } 1914 } 1915 1916 1917 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 1918 Handle<FixedArrayBase> elements, 1919 uint32_t length, 1920 EnsureElementsMode mode) { 1921 Heap* heap = object->GetHeap(); 1922 if (elements->map() != heap->fixed_double_array_map()) { 1923 DCHECK(elements->map() == heap->fixed_array_map() || 1924 elements->map() == heap->fixed_cow_array_map()); 1925 if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) { 1926 mode = DONT_ALLOW_DOUBLE_ELEMENTS; 1927 } 1928 Object** objects = 1929 Handle<FixedArray>::cast(elements)->GetFirstElementAddress(); 1930 EnsureCanContainElements(object, objects, length, mode); 1931 return; 1932 } 1933 1934 DCHECK(mode == ALLOW_COPIED_DOUBLE_ELEMENTS); 1935 if (object->GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) { 1936 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); 1937 } else if (object->GetElementsKind() == FAST_SMI_ELEMENTS) { 1938 Handle<FixedDoubleArray> double_array = 1939 Handle<FixedDoubleArray>::cast(elements); 1940 for (uint32_t i = 0; i < length; ++i) { 1941 if (double_array->is_the_hole(i)) { 1942 TransitionElementsKind(object, FAST_HOLEY_DOUBLE_ELEMENTS); 1943 return; 1944 } 1945 } 1946 TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); 1947 } 1948 } 1949 1950 1951 void JSObject::SetMapAndElements(Handle<JSObject> object, 1952 Handle<Map> new_map, 1953 Handle<FixedArrayBase> value) { 1954 JSObject::MigrateToMap(object, new_map); 1955 DCHECK((object->map()->has_fast_smi_or_object_elements() || 1956 (*value == object->GetHeap()->empty_fixed_array())) == 1957 (value->map() == object->GetHeap()->fixed_array_map() || 1958 value->map() == object->GetHeap()->fixed_cow_array_map())); 1959 DCHECK((*value == object->GetHeap()->empty_fixed_array()) || 1960 (object->map()->has_fast_double_elements() == 1961 value->IsFixedDoubleArray())); 1962 object->set_elements(*value); 1963 } 1964 1965 1966 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) { 1967 WRITE_FIELD(this, kElementsOffset, value); 1968 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode); 1969 } 1970 1971 1972 void JSObject::initialize_elements() { 1973 FixedArrayBase* elements = map()->GetInitialElements(); 1974 WRITE_FIELD(this, kElementsOffset, elements); 1975 } 1976 1977 1978 InterceptorInfo* JSObject::GetIndexedInterceptor() { 1979 DCHECK(map()->has_indexed_interceptor()); 1980 JSFunction* constructor = JSFunction::cast(map()->GetConstructor()); 1981 DCHECK(constructor->shared()->IsApiFunction()); 1982 Object* result = 1983 constructor->shared()->get_api_func_data()->indexed_property_handler(); 1984 return InterceptorInfo::cast(result); 1985 } 1986 1987 1988 ACCESSORS(Oddball, to_string, String, kToStringOffset) 1989 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) 1990 ACCESSORS(Oddball, type_of, String, kTypeOfOffset) 1991 1992 1993 byte Oddball::kind() const { 1994 return Smi::cast(READ_FIELD(this, kKindOffset))->value(); 1995 } 1996 1997 1998 void Oddball::set_kind(byte value) { 1999 WRITE_FIELD(this, kKindOffset, Smi::FromInt(value)); 2000 } 2001 2002 2003 // static 2004 Handle<Object> Oddball::ToNumber(Handle<Oddball> input) { 2005 return handle(input->to_number(), input->GetIsolate()); 2006 } 2007 2008 2009 ACCESSORS(Cell, value, Object, kValueOffset) 2010 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset) 2011 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset) 2012 ACCESSORS(PropertyCell, value, Object, kValueOffset) 2013 2014 2015 PropertyDetails PropertyCell::property_details() { 2016 return PropertyDetails(Smi::cast(property_details_raw())); 2017 } 2018 2019 2020 void PropertyCell::set_property_details(PropertyDetails details) { 2021 set_property_details_raw(details.AsSmi()); 2022 } 2023 2024 2025 Object* WeakCell::value() const { return READ_FIELD(this, kValueOffset); } 2026 2027 2028 void WeakCell::clear() { 2029 // Either the garbage collector is clearing the cell or we are simply 2030 // initializing the root empty weak cell. 2031 DCHECK(GetHeap()->gc_state() == Heap::MARK_COMPACT || 2032 this == GetHeap()->empty_weak_cell()); 2033 WRITE_FIELD(this, kValueOffset, Smi::FromInt(0)); 2034 } 2035 2036 2037 void WeakCell::initialize(HeapObject* val) { 2038 WRITE_FIELD(this, kValueOffset, val); 2039 Heap* heap = GetHeap(); 2040 // We just have to execute the generational barrier here because we never 2041 // mark through a weak cell and collect evacuation candidates when we process 2042 // all weak cells. 2043 if (heap->InNewSpace(val)) { 2044 heap->RecordWrite(address(), kValueOffset); 2045 } 2046 } 2047 2048 2049 bool WeakCell::cleared() const { return value() == Smi::FromInt(0); } 2050 2051 2052 Object* WeakCell::next() const { return READ_FIELD(this, kNextOffset); } 2053 2054 2055 void WeakCell::set_next(Object* val, WriteBarrierMode mode) { 2056 WRITE_FIELD(this, kNextOffset, val); 2057 if (mode == UPDATE_WRITE_BARRIER) { 2058 WRITE_BARRIER(GetHeap(), this, kNextOffset, val); 2059 } 2060 } 2061 2062 2063 void WeakCell::clear_next(Object* the_hole_value) { 2064 DCHECK_EQ(GetHeap()->the_hole_value(), the_hole_value); 2065 set_next(the_hole_value, SKIP_WRITE_BARRIER); 2066 } 2067 2068 2069 bool WeakCell::next_cleared() { return next()->IsTheHole(); } 2070 2071 2072 int JSObject::GetHeaderSize() { return GetHeaderSize(map()->instance_type()); } 2073 2074 2075 int JSObject::GetHeaderSize(InstanceType type) { 2076 // Check for the most common kind of JavaScript object before 2077 // falling into the generic switch. This speeds up the internal 2078 // field operations considerably on average. 2079 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize; 2080 switch (type) { 2081 case JS_GENERATOR_OBJECT_TYPE: 2082 return JSGeneratorObject::kSize; 2083 case JS_MODULE_TYPE: 2084 return JSModule::kSize; 2085 case JS_GLOBAL_PROXY_TYPE: 2086 return JSGlobalProxy::kSize; 2087 case JS_GLOBAL_OBJECT_TYPE: 2088 return JSGlobalObject::kSize; 2089 case JS_BOUND_FUNCTION_TYPE: 2090 return JSBoundFunction::kSize; 2091 case JS_FUNCTION_TYPE: 2092 return JSFunction::kSize; 2093 case JS_VALUE_TYPE: 2094 return JSValue::kSize; 2095 case JS_DATE_TYPE: 2096 return JSDate::kSize; 2097 case JS_ARRAY_TYPE: 2098 return JSArray::kSize; 2099 case JS_ARRAY_BUFFER_TYPE: 2100 return JSArrayBuffer::kSize; 2101 case JS_TYPED_ARRAY_TYPE: 2102 return JSTypedArray::kSize; 2103 case JS_DATA_VIEW_TYPE: 2104 return JSDataView::kSize; 2105 case JS_SET_TYPE: 2106 return JSSet::kSize; 2107 case JS_MAP_TYPE: 2108 return JSMap::kSize; 2109 case JS_SET_ITERATOR_TYPE: 2110 return JSSetIterator::kSize; 2111 case JS_MAP_ITERATOR_TYPE: 2112 return JSMapIterator::kSize; 2113 case JS_ITERATOR_RESULT_TYPE: 2114 return JSIteratorResult::kSize; 2115 case JS_WEAK_MAP_TYPE: 2116 return JSWeakMap::kSize; 2117 case JS_WEAK_SET_TYPE: 2118 return JSWeakSet::kSize; 2119 case JS_PROMISE_TYPE: 2120 return JSObject::kHeaderSize; 2121 case JS_REGEXP_TYPE: 2122 return JSRegExp::kSize; 2123 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 2124 return JSObject::kHeaderSize; 2125 case JS_MESSAGE_OBJECT_TYPE: 2126 return JSMessageObject::kSize; 2127 default: 2128 UNREACHABLE(); 2129 return 0; 2130 } 2131 } 2132 2133 2134 int JSObject::GetInternalFieldCount(Map* map) { 2135 int instance_size = map->instance_size(); 2136 if (instance_size == kVariableSizeSentinel) return 0; 2137 InstanceType instance_type = map->instance_type(); 2138 return ((instance_size - GetHeaderSize(instance_type)) >> kPointerSizeLog2) - 2139 map->GetInObjectProperties(); 2140 } 2141 2142 2143 int JSObject::GetInternalFieldCount() { return GetInternalFieldCount(map()); } 2144 2145 2146 int JSObject::GetInternalFieldOffset(int index) { 2147 DCHECK(index < GetInternalFieldCount() && index >= 0); 2148 return GetHeaderSize() + (kPointerSize * index); 2149 } 2150 2151 2152 Object* JSObject::GetInternalField(int index) { 2153 DCHECK(index < GetInternalFieldCount() && index >= 0); 2154 // Internal objects do follow immediately after the header, whereas in-object 2155 // properties are at the end of the object. Therefore there is no need 2156 // to adjust the index here. 2157 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); 2158 } 2159 2160 2161 void JSObject::SetInternalField(int index, Object* value) { 2162 DCHECK(index < GetInternalFieldCount() && index >= 0); 2163 // Internal objects do follow immediately after the header, whereas in-object 2164 // properties are at the end of the object. Therefore there is no need 2165 // to adjust the index here. 2166 int offset = GetHeaderSize() + (kPointerSize * index); 2167 WRITE_FIELD(this, offset, value); 2168 WRITE_BARRIER(GetHeap(), this, offset, value); 2169 } 2170 2171 2172 void JSObject::SetInternalField(int index, Smi* value) { 2173 DCHECK(index < GetInternalFieldCount() && index >= 0); 2174 // Internal objects do follow immediately after the header, whereas in-object 2175 // properties are at the end of the object. Therefore there is no need 2176 // to adjust the index here. 2177 int offset = GetHeaderSize() + (kPointerSize * index); 2178 WRITE_FIELD(this, offset, value); 2179 } 2180 2181 2182 bool JSObject::IsUnboxedDoubleField(FieldIndex index) { 2183 if (!FLAG_unbox_double_fields) return false; 2184 return map()->IsUnboxedDoubleField(index); 2185 } 2186 2187 2188 bool Map::IsUnboxedDoubleField(FieldIndex index) { 2189 if (!FLAG_unbox_double_fields) return false; 2190 if (index.is_hidden_field() || !index.is_inobject()) return false; 2191 return !layout_descriptor()->IsTagged(index.property_index()); 2192 } 2193 2194 2195 // Access fast-case object properties at index. The use of these routines 2196 // is needed to correctly distinguish between properties stored in-object and 2197 // properties stored in the properties array. 2198 Object* JSObject::RawFastPropertyAt(FieldIndex index) { 2199 DCHECK(!IsUnboxedDoubleField(index)); 2200 if (index.is_inobject()) { 2201 return READ_FIELD(this, index.offset()); 2202 } else { 2203 return properties()->get(index.outobject_array_index()); 2204 } 2205 } 2206 2207 2208 double JSObject::RawFastDoublePropertyAt(FieldIndex index) { 2209 DCHECK(IsUnboxedDoubleField(index)); 2210 return READ_DOUBLE_FIELD(this, index.offset()); 2211 } 2212 2213 2214 void JSObject::RawFastPropertyAtPut(FieldIndex index, Object* value) { 2215 if (index.is_inobject()) { 2216 int offset = index.offset(); 2217 WRITE_FIELD(this, offset, value); 2218 WRITE_BARRIER(GetHeap(), this, offset, value); 2219 } else { 2220 properties()->set(index.outobject_array_index(), value); 2221 } 2222 } 2223 2224 2225 void JSObject::RawFastDoublePropertyAtPut(FieldIndex index, double value) { 2226 WRITE_DOUBLE_FIELD(this, index.offset(), value); 2227 } 2228 2229 2230 void JSObject::FastPropertyAtPut(FieldIndex index, Object* value) { 2231 if (IsUnboxedDoubleField(index)) { 2232 DCHECK(value->IsMutableHeapNumber()); 2233 RawFastDoublePropertyAtPut(index, HeapNumber::cast(value)->value()); 2234 } else { 2235 RawFastPropertyAtPut(index, value); 2236 } 2237 } 2238 2239 2240 void JSObject::WriteToField(int descriptor, Object* value) { 2241 DisallowHeapAllocation no_gc; 2242 2243 DescriptorArray* desc = map()->instance_descriptors(); 2244 PropertyDetails details = desc->GetDetails(descriptor); 2245 2246 DCHECK(details.type() == DATA); 2247 2248 FieldIndex index = FieldIndex::ForDescriptor(map(), descriptor); 2249 if (details.representation().IsDouble()) { 2250 // Nothing more to be done. 2251 if (value->IsUninitialized()) return; 2252 if (IsUnboxedDoubleField(index)) { 2253 RawFastDoublePropertyAtPut(index, value->Number()); 2254 } else { 2255 HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index)); 2256 DCHECK(box->IsMutableHeapNumber()); 2257 box->set_value(value->Number()); 2258 } 2259 } else { 2260 RawFastPropertyAtPut(index, value); 2261 } 2262 } 2263 2264 2265 int JSObject::GetInObjectPropertyOffset(int index) { 2266 return map()->GetInObjectPropertyOffset(index); 2267 } 2268 2269 2270 Object* JSObject::InObjectPropertyAt(int index) { 2271 int offset = GetInObjectPropertyOffset(index); 2272 return READ_FIELD(this, offset); 2273 } 2274 2275 2276 Object* JSObject::InObjectPropertyAtPut(int index, 2277 Object* value, 2278 WriteBarrierMode mode) { 2279 // Adjust for the number of properties stored in the object. 2280 int offset = GetInObjectPropertyOffset(index); 2281 WRITE_FIELD(this, offset, value); 2282 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); 2283 return value; 2284 } 2285 2286 2287 void JSObject::InitializeBody(Map* map, int start_offset, 2288 Object* pre_allocated_value, 2289 Object* filler_value) { 2290 DCHECK(!filler_value->IsHeapObject() || 2291 !GetHeap()->InNewSpace(filler_value)); 2292 DCHECK(!pre_allocated_value->IsHeapObject() || 2293 !GetHeap()->InNewSpace(pre_allocated_value)); 2294 int size = map->instance_size(); 2295 int offset = start_offset; 2296 if (filler_value != pre_allocated_value) { 2297 int end_of_pre_allocated_offset = 2298 size - (map->unused_property_fields() * kPointerSize); 2299 DCHECK_LE(kHeaderSize, end_of_pre_allocated_offset); 2300 while (offset < end_of_pre_allocated_offset) { 2301 WRITE_FIELD(this, offset, pre_allocated_value); 2302 offset += kPointerSize; 2303 } 2304 } 2305 while (offset < size) { 2306 WRITE_FIELD(this, offset, filler_value); 2307 offset += kPointerSize; 2308 } 2309 } 2310 2311 2312 bool Map::TooManyFastProperties(StoreFromKeyed store_mode) { 2313 if (unused_property_fields() != 0) return false; 2314 if (is_prototype_map()) return false; 2315 int minimum = store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ? 128 : 12; 2316 int limit = Max(minimum, GetInObjectProperties()); 2317 int external = NumberOfFields() - GetInObjectProperties(); 2318 return external > limit; 2319 } 2320 2321 2322 void Struct::InitializeBody(int object_size) { 2323 Object* value = GetHeap()->undefined_value(); 2324 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 2325 WRITE_FIELD(this, offset, value); 2326 } 2327 } 2328 2329 2330 bool Object::ToArrayLength(uint32_t* index) { return Object::ToUint32(index); } 2331 2332 2333 bool Object::ToArrayIndex(uint32_t* index) { 2334 return Object::ToUint32(index) && *index != kMaxUInt32; 2335 } 2336 2337 2338 bool Object::IsStringObjectWithCharacterAt(uint32_t index) { 2339 if (!this->IsJSValue()) return false; 2340 2341 JSValue* js_value = JSValue::cast(this); 2342 if (!js_value->value()->IsString()) return false; 2343 2344 String* str = String::cast(js_value->value()); 2345 if (index >= static_cast<uint32_t>(str->length())) return false; 2346 2347 return true; 2348 } 2349 2350 2351 void Object::VerifyApiCallResultType() { 2352 #if DEBUG 2353 if (!(IsSmi() || IsString() || IsSymbol() || IsJSReceiver() || 2354 IsHeapNumber() || IsSimd128Value() || IsUndefined() || IsTrue() || 2355 IsFalse() || IsNull())) { 2356 FATAL("API call returned invalid object"); 2357 } 2358 #endif // DEBUG 2359 } 2360 2361 2362 Object* FixedArray::get(int index) const { 2363 SLOW_DCHECK(index >= 0 && index < this->length()); 2364 return READ_FIELD(this, kHeaderSize + index * kPointerSize); 2365 } 2366 2367 2368 Handle<Object> FixedArray::get(Handle<FixedArray> array, int index) { 2369 return handle(array->get(index), array->GetIsolate()); 2370 } 2371 2372 2373 bool FixedArray::is_the_hole(int index) { 2374 return get(index) == GetHeap()->the_hole_value(); 2375 } 2376 2377 2378 void FixedArray::set(int index, Smi* value) { 2379 DCHECK(map() != GetHeap()->fixed_cow_array_map()); 2380 DCHECK(index >= 0 && index < this->length()); 2381 DCHECK(reinterpret_cast<Object*>(value)->IsSmi()); 2382 int offset = kHeaderSize + index * kPointerSize; 2383 WRITE_FIELD(this, offset, value); 2384 } 2385 2386 2387 void FixedArray::set(int index, Object* value) { 2388 DCHECK_NE(GetHeap()->fixed_cow_array_map(), map()); 2389 DCHECK(IsFixedArray()); 2390 DCHECK(index >= 0 && index < this->length()); 2391 int offset = kHeaderSize + index * kPointerSize; 2392 WRITE_FIELD(this, offset, value); 2393 WRITE_BARRIER(GetHeap(), this, offset, value); 2394 } 2395 2396 2397 double FixedDoubleArray::get_scalar(int index) { 2398 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2399 map() != GetHeap()->fixed_array_map()); 2400 DCHECK(index >= 0 && index < this->length()); 2401 DCHECK(!is_the_hole(index)); 2402 return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize); 2403 } 2404 2405 2406 uint64_t FixedDoubleArray::get_representation(int index) { 2407 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2408 map() != GetHeap()->fixed_array_map()); 2409 DCHECK(index >= 0 && index < this->length()); 2410 int offset = kHeaderSize + index * kDoubleSize; 2411 return READ_UINT64_FIELD(this, offset); 2412 } 2413 2414 2415 Handle<Object> FixedDoubleArray::get(Handle<FixedDoubleArray> array, 2416 int index) { 2417 if (array->is_the_hole(index)) { 2418 return array->GetIsolate()->factory()->the_hole_value(); 2419 } else { 2420 return array->GetIsolate()->factory()->NewNumber(array->get_scalar(index)); 2421 } 2422 } 2423 2424 2425 void FixedDoubleArray::set(int index, double value) { 2426 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2427 map() != GetHeap()->fixed_array_map()); 2428 int offset = kHeaderSize + index * kDoubleSize; 2429 if (std::isnan(value)) { 2430 WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN()); 2431 } else { 2432 WRITE_DOUBLE_FIELD(this, offset, value); 2433 } 2434 DCHECK(!is_the_hole(index)); 2435 } 2436 2437 2438 void FixedDoubleArray::set_the_hole(int index) { 2439 DCHECK(map() != GetHeap()->fixed_cow_array_map() && 2440 map() != GetHeap()->fixed_array_map()); 2441 int offset = kHeaderSize + index * kDoubleSize; 2442 WRITE_UINT64_FIELD(this, offset, kHoleNanInt64); 2443 } 2444 2445 2446 bool FixedDoubleArray::is_the_hole(int index) { 2447 return get_representation(index) == kHoleNanInt64; 2448 } 2449 2450 2451 double* FixedDoubleArray::data_start() { 2452 return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize)); 2453 } 2454 2455 2456 void FixedDoubleArray::FillWithHoles(int from, int to) { 2457 for (int i = from; i < to; i++) { 2458 set_the_hole(i); 2459 } 2460 } 2461 2462 2463 Object* WeakFixedArray::Get(int index) const { 2464 Object* raw = FixedArray::cast(this)->get(index + kFirstIndex); 2465 if (raw->IsSmi()) return raw; 2466 DCHECK(raw->IsWeakCell()); 2467 return WeakCell::cast(raw)->value(); 2468 } 2469 2470 2471 bool WeakFixedArray::IsEmptySlot(int index) const { 2472 DCHECK(index < Length()); 2473 return Get(index)->IsSmi(); 2474 } 2475 2476 2477 void WeakFixedArray::Clear(int index) { 2478 FixedArray::cast(this)->set(index + kFirstIndex, Smi::FromInt(0)); 2479 } 2480 2481 2482 int WeakFixedArray::Length() const { 2483 return FixedArray::cast(this)->length() - kFirstIndex; 2484 } 2485 2486 2487 int WeakFixedArray::last_used_index() const { 2488 return Smi::cast(FixedArray::cast(this)->get(kLastUsedIndexIndex))->value(); 2489 } 2490 2491 2492 void WeakFixedArray::set_last_used_index(int index) { 2493 FixedArray::cast(this)->set(kLastUsedIndexIndex, Smi::FromInt(index)); 2494 } 2495 2496 2497 template <class T> 2498 T* WeakFixedArray::Iterator::Next() { 2499 if (list_ != NULL) { 2500 // Assert that list did not change during iteration. 2501 DCHECK_EQ(last_used_index_, list_->last_used_index()); 2502 while (index_ < list_->Length()) { 2503 Object* item = list_->Get(index_++); 2504 if (item != Empty()) return T::cast(item); 2505 } 2506 list_ = NULL; 2507 } 2508 return NULL; 2509 } 2510 2511 2512 int ArrayList::Length() { 2513 if (FixedArray::cast(this)->length() == 0) return 0; 2514 return Smi::cast(FixedArray::cast(this)->get(kLengthIndex))->value(); 2515 } 2516 2517 2518 void ArrayList::SetLength(int length) { 2519 return FixedArray::cast(this)->set(kLengthIndex, Smi::FromInt(length)); 2520 } 2521 2522 2523 Object* ArrayList::Get(int index) { 2524 return FixedArray::cast(this)->get(kFirstIndex + index); 2525 } 2526 2527 2528 Object** ArrayList::Slot(int index) { 2529 return data_start() + kFirstIndex + index; 2530 } 2531 2532 2533 void ArrayList::Set(int index, Object* obj) { 2534 FixedArray::cast(this)->set(kFirstIndex + index, obj); 2535 } 2536 2537 2538 void ArrayList::Clear(int index, Object* undefined) { 2539 DCHECK(undefined->IsUndefined()); 2540 FixedArray::cast(this) 2541 ->set(kFirstIndex + index, undefined, SKIP_WRITE_BARRIER); 2542 } 2543 2544 2545 WriteBarrierMode HeapObject::GetWriteBarrierMode( 2546 const DisallowHeapAllocation& promise) { 2547 Heap* heap = GetHeap(); 2548 if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER; 2549 if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER; 2550 return UPDATE_WRITE_BARRIER; 2551 } 2552 2553 2554 AllocationAlignment HeapObject::RequiredAlignment() { 2555 #ifdef V8_HOST_ARCH_32_BIT 2556 if ((IsFixedFloat64Array() || IsFixedDoubleArray()) && 2557 FixedArrayBase::cast(this)->length() != 0) { 2558 return kDoubleAligned; 2559 } 2560 if (IsHeapNumber()) return kDoubleUnaligned; 2561 if (IsSimd128Value()) return kSimd128Unaligned; 2562 #endif // V8_HOST_ARCH_32_BIT 2563 return kWordAligned; 2564 } 2565 2566 2567 void FixedArray::set(int index, 2568 Object* value, 2569 WriteBarrierMode mode) { 2570 DCHECK(map() != GetHeap()->fixed_cow_array_map()); 2571 DCHECK(index >= 0 && index < this->length()); 2572 int offset = kHeaderSize + index * kPointerSize; 2573 WRITE_FIELD(this, offset, value); 2574 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); 2575 } 2576 2577 2578 void FixedArray::NoWriteBarrierSet(FixedArray* array, 2579 int index, 2580 Object* value) { 2581 DCHECK(array->map() != array->GetHeap()->fixed_cow_array_map()); 2582 DCHECK(index >= 0 && index < array->length()); 2583 DCHECK(!array->GetHeap()->InNewSpace(value)); 2584 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value); 2585 } 2586 2587 2588 void FixedArray::set_undefined(int index) { 2589 DCHECK(map() != GetHeap()->fixed_cow_array_map()); 2590 DCHECK(index >= 0 && index < this->length()); 2591 DCHECK(!GetHeap()->InNewSpace(GetHeap()->undefined_value())); 2592 WRITE_FIELD(this, 2593 kHeaderSize + index * kPointerSize, 2594 GetHeap()->undefined_value()); 2595 } 2596 2597 2598 void FixedArray::set_null(int index) { 2599 DCHECK(index >= 0 && index < this->length()); 2600 DCHECK(!GetHeap()->InNewSpace(GetHeap()->null_value())); 2601 WRITE_FIELD(this, 2602 kHeaderSize + index * kPointerSize, 2603 GetHeap()->null_value()); 2604 } 2605 2606 2607 void FixedArray::set_the_hole(int index) { 2608 DCHECK(map() != GetHeap()->fixed_cow_array_map()); 2609 DCHECK(index >= 0 && index < this->length()); 2610 DCHECK(!GetHeap()->InNewSpace(GetHeap()->the_hole_value())); 2611 WRITE_FIELD(this, 2612 kHeaderSize + index * kPointerSize, 2613 GetHeap()->the_hole_value()); 2614 } 2615 2616 2617 void FixedArray::FillWithHoles(int from, int to) { 2618 for (int i = from; i < to; i++) { 2619 set_the_hole(i); 2620 } 2621 } 2622 2623 2624 Object** FixedArray::data_start() { 2625 return HeapObject::RawField(this, kHeaderSize); 2626 } 2627 2628 2629 Object** FixedArray::RawFieldOfElementAt(int index) { 2630 return HeapObject::RawField(this, OffsetOfElementAt(index)); 2631 } 2632 2633 2634 bool DescriptorArray::IsEmpty() { 2635 DCHECK(length() >= kFirstIndex || 2636 this == GetHeap()->empty_descriptor_array()); 2637 return length() < kFirstIndex; 2638 } 2639 2640 2641 int DescriptorArray::number_of_descriptors() { 2642 DCHECK(length() >= kFirstIndex || IsEmpty()); 2643 int len = length(); 2644 return len == 0 ? 0 : Smi::cast(get(kDescriptorLengthIndex))->value(); 2645 } 2646 2647 2648 int DescriptorArray::number_of_descriptors_storage() { 2649 int len = length(); 2650 return len == 0 ? 0 : (len - kFirstIndex) / kDescriptorSize; 2651 } 2652 2653 2654 int DescriptorArray::NumberOfSlackDescriptors() { 2655 return number_of_descriptors_storage() - number_of_descriptors(); 2656 } 2657 2658 2659 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) { 2660 WRITE_FIELD( 2661 this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors)); 2662 } 2663 2664 2665 inline int DescriptorArray::number_of_entries() { 2666 return number_of_descriptors(); 2667 } 2668 2669 2670 bool DescriptorArray::HasEnumCache() { 2671 return !IsEmpty() && !get(kEnumCacheIndex)->IsSmi(); 2672 } 2673 2674 2675 void DescriptorArray::CopyEnumCacheFrom(DescriptorArray* array) { 2676 set(kEnumCacheIndex, array->get(kEnumCacheIndex)); 2677 } 2678 2679 2680 FixedArray* DescriptorArray::GetEnumCache() { 2681 DCHECK(HasEnumCache()); 2682 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2683 return FixedArray::cast(bridge->get(kEnumCacheBridgeCacheIndex)); 2684 } 2685 2686 2687 bool DescriptorArray::HasEnumIndicesCache() { 2688 if (IsEmpty()) return false; 2689 Object* object = get(kEnumCacheIndex); 2690 if (object->IsSmi()) return false; 2691 FixedArray* bridge = FixedArray::cast(object); 2692 return !bridge->get(kEnumCacheBridgeIndicesCacheIndex)->IsSmi(); 2693 } 2694 2695 2696 FixedArray* DescriptorArray::GetEnumIndicesCache() { 2697 DCHECK(HasEnumIndicesCache()); 2698 FixedArray* bridge = FixedArray::cast(get(kEnumCacheIndex)); 2699 return FixedArray::cast(bridge->get(kEnumCacheBridgeIndicesCacheIndex)); 2700 } 2701 2702 2703 Object** DescriptorArray::GetEnumCacheSlot() { 2704 DCHECK(HasEnumCache()); 2705 return HeapObject::RawField(reinterpret_cast<HeapObject*>(this), 2706 kEnumCacheOffset); 2707 } 2708 2709 2710 // Perform a binary search in a fixed array. Low and high are entry indices. If 2711 // there are three entries in this array it should be called with low=0 and 2712 // high=2. 2713 template <SearchMode search_mode, typename T> 2714 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries, 2715 int* out_insertion_index) { 2716 DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == NULL); 2717 uint32_t hash = name->Hash(); 2718 int limit = high; 2719 2720 DCHECK(low <= high); 2721 2722 while (low != high) { 2723 int mid = low + (high - low) / 2; 2724 Name* mid_name = array->GetSortedKey(mid); 2725 uint32_t mid_hash = mid_name->Hash(); 2726 2727 if (mid_hash >= hash) { 2728 high = mid; 2729 } else { 2730 low = mid + 1; 2731 } 2732 } 2733 2734 for (; low <= limit; ++low) { 2735 int sort_index = array->GetSortedKeyIndex(low); 2736 Name* entry = array->GetKey(sort_index); 2737 uint32_t current_hash = entry->Hash(); 2738 if (current_hash != hash) { 2739 if (out_insertion_index != NULL) { 2740 *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1); 2741 } 2742 return T::kNotFound; 2743 } 2744 if (entry->Equals(name)) { 2745 if (search_mode == ALL_ENTRIES || sort_index < valid_entries) { 2746 return sort_index; 2747 } 2748 return T::kNotFound; 2749 } 2750 } 2751 2752 if (out_insertion_index != NULL) *out_insertion_index = limit + 1; 2753 return T::kNotFound; 2754 } 2755 2756 2757 // Perform a linear search in this fixed array. len is the number of entry 2758 // indices that are valid. 2759 template <SearchMode search_mode, typename T> 2760 int LinearSearch(T* array, Name* name, int len, int valid_entries, 2761 int* out_insertion_index) { 2762 uint32_t hash = name->Hash(); 2763 if (search_mode == ALL_ENTRIES) { 2764 for (int number = 0; number < len; number++) { 2765 int sorted_index = array->GetSortedKeyIndex(number); 2766 Name* entry = array->GetKey(sorted_index); 2767 uint32_t current_hash = entry->Hash(); 2768 if (current_hash > hash) { 2769 if (out_insertion_index != NULL) *out_insertion_index = sorted_index; 2770 return T::kNotFound; 2771 } 2772 if (current_hash == hash && entry->Equals(name)) return sorted_index; 2773 } 2774 if (out_insertion_index != NULL) *out_insertion_index = len; 2775 return T::kNotFound; 2776 } else { 2777 DCHECK(len >= valid_entries); 2778 DCHECK_NULL(out_insertion_index); // Not supported here. 2779 for (int number = 0; number < valid_entries; number++) { 2780 Name* entry = array->GetKey(number); 2781 uint32_t current_hash = entry->Hash(); 2782 if (current_hash == hash && entry->Equals(name)) return number; 2783 } 2784 return T::kNotFound; 2785 } 2786 } 2787 2788 2789 template <SearchMode search_mode, typename T> 2790 int Search(T* array, Name* name, int valid_entries, int* out_insertion_index) { 2791 if (search_mode == VALID_ENTRIES) { 2792 SLOW_DCHECK(array->IsSortedNoDuplicates(valid_entries)); 2793 } else { 2794 SLOW_DCHECK(array->IsSortedNoDuplicates()); 2795 } 2796 2797 int nof = array->number_of_entries(); 2798 if (nof == 0) { 2799 if (out_insertion_index != NULL) *out_insertion_index = 0; 2800 return T::kNotFound; 2801 } 2802 2803 // Fast case: do linear search for small arrays. 2804 const int kMaxElementsForLinearSearch = 8; 2805 if ((search_mode == ALL_ENTRIES && 2806 nof <= kMaxElementsForLinearSearch) || 2807 (search_mode == VALID_ENTRIES && 2808 valid_entries <= (kMaxElementsForLinearSearch * 3))) { 2809 return LinearSearch<search_mode>(array, name, nof, valid_entries, 2810 out_insertion_index); 2811 } 2812 2813 // Slow case: perform binary search. 2814 return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries, 2815 out_insertion_index); 2816 } 2817 2818 2819 int DescriptorArray::Search(Name* name, int valid_descriptors) { 2820 return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors, NULL); 2821 } 2822 2823 2824 int DescriptorArray::SearchWithCache(Name* name, Map* map) { 2825 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); 2826 if (number_of_own_descriptors == 0) return kNotFound; 2827 2828 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache(); 2829 int number = cache->Lookup(map, name); 2830 2831 if (number == DescriptorLookupCache::kAbsent) { 2832 number = Search(name, number_of_own_descriptors); 2833 cache->Update(map, name, number); 2834 } 2835 2836 return number; 2837 } 2838 2839 2840 PropertyDetails Map::GetLastDescriptorDetails() { 2841 return instance_descriptors()->GetDetails(LastAdded()); 2842 } 2843 2844 2845 int Map::LastAdded() { 2846 int number_of_own_descriptors = NumberOfOwnDescriptors(); 2847 DCHECK(number_of_own_descriptors > 0); 2848 return number_of_own_descriptors - 1; 2849 } 2850 2851 2852 int Map::NumberOfOwnDescriptors() { 2853 return NumberOfOwnDescriptorsBits::decode(bit_field3()); 2854 } 2855 2856 2857 void Map::SetNumberOfOwnDescriptors(int number) { 2858 DCHECK(number <= instance_descriptors()->number_of_descriptors()); 2859 set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number)); 2860 } 2861 2862 2863 int Map::EnumLength() { return EnumLengthBits::decode(bit_field3()); } 2864 2865 2866 void Map::SetEnumLength(int length) { 2867 if (length != kInvalidEnumCacheSentinel) { 2868 DCHECK(length >= 0); 2869 DCHECK(length == 0 || instance_descriptors()->HasEnumCache()); 2870 DCHECK(length <= NumberOfOwnDescriptors()); 2871 } 2872 set_bit_field3(EnumLengthBits::update(bit_field3(), length)); 2873 } 2874 2875 2876 FixedArrayBase* Map::GetInitialElements() { 2877 if (has_fast_smi_or_object_elements() || 2878 has_fast_double_elements()) { 2879 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); 2880 return GetHeap()->empty_fixed_array(); 2881 } else if (has_fixed_typed_array_elements()) { 2882 FixedTypedArrayBase* empty_array = 2883 GetHeap()->EmptyFixedTypedArrayForMap(this); 2884 DCHECK(!GetHeap()->InNewSpace(empty_array)); 2885 return empty_array; 2886 } else { 2887 UNREACHABLE(); 2888 } 2889 return NULL; 2890 } 2891 2892 2893 Object** DescriptorArray::GetKeySlot(int descriptor_number) { 2894 DCHECK(descriptor_number < number_of_descriptors()); 2895 return RawFieldOfElementAt(ToKeyIndex(descriptor_number)); 2896 } 2897 2898 2899 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) { 2900 return GetKeySlot(descriptor_number); 2901 } 2902 2903 2904 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) { 2905 return GetValueSlot(descriptor_number - 1) + 1; 2906 } 2907 2908 2909 Name* DescriptorArray::GetKey(int descriptor_number) { 2910 DCHECK(descriptor_number < number_of_descriptors()); 2911 return Name::cast(get(ToKeyIndex(descriptor_number))); 2912 } 2913 2914 2915 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) { 2916 return GetDetails(descriptor_number).pointer(); 2917 } 2918 2919 2920 Name* DescriptorArray::GetSortedKey(int descriptor_number) { 2921 return GetKey(GetSortedKeyIndex(descriptor_number)); 2922 } 2923 2924 2925 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) { 2926 PropertyDetails details = GetDetails(descriptor_index); 2927 set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi()); 2928 } 2929 2930 2931 void DescriptorArray::SetRepresentation(int descriptor_index, 2932 Representation representation) { 2933 DCHECK(!representation.IsNone()); 2934 PropertyDetails details = GetDetails(descriptor_index); 2935 set(ToDetailsIndex(descriptor_index), 2936 details.CopyWithRepresentation(representation).AsSmi()); 2937 } 2938 2939 2940 Object** DescriptorArray::GetValueSlot(int descriptor_number) { 2941 DCHECK(descriptor_number < number_of_descriptors()); 2942 return RawFieldOfElementAt(ToValueIndex(descriptor_number)); 2943 } 2944 2945 2946 int DescriptorArray::GetValueOffset(int descriptor_number) { 2947 return OffsetOfElementAt(ToValueIndex(descriptor_number)); 2948 } 2949 2950 2951 Object* DescriptorArray::GetValue(int descriptor_number) { 2952 DCHECK(descriptor_number < number_of_descriptors()); 2953 return get(ToValueIndex(descriptor_number)); 2954 } 2955 2956 2957 void DescriptorArray::SetValue(int descriptor_index, Object* value) { 2958 set(ToValueIndex(descriptor_index), value); 2959 } 2960 2961 2962 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { 2963 DCHECK(descriptor_number < number_of_descriptors()); 2964 Object* details = get(ToDetailsIndex(descriptor_number)); 2965 return PropertyDetails(Smi::cast(details)); 2966 } 2967 2968 2969 PropertyType DescriptorArray::GetType(int descriptor_number) { 2970 return GetDetails(descriptor_number).type(); 2971 } 2972 2973 2974 int DescriptorArray::GetFieldIndex(int descriptor_number) { 2975 DCHECK(GetDetails(descriptor_number).location() == kField); 2976 return GetDetails(descriptor_number).field_index(); 2977 } 2978 2979 2980 HeapType* DescriptorArray::GetFieldType(int descriptor_number) { 2981 DCHECK(GetDetails(descriptor_number).location() == kField); 2982 Object* value = GetValue(descriptor_number); 2983 if (value->IsWeakCell()) { 2984 if (WeakCell::cast(value)->cleared()) return HeapType::None(); 2985 value = WeakCell::cast(value)->value(); 2986 } 2987 return HeapType::cast(value); 2988 } 2989 2990 2991 Object* DescriptorArray::GetConstant(int descriptor_number) { 2992 return GetValue(descriptor_number); 2993 } 2994 2995 2996 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { 2997 DCHECK(GetType(descriptor_number) == ACCESSOR_CONSTANT); 2998 return GetValue(descriptor_number); 2999 } 3000 3001 3002 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { 3003 DCHECK(GetType(descriptor_number) == ACCESSOR_CONSTANT); 3004 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); 3005 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); 3006 } 3007 3008 3009 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { 3010 desc->Init(handle(GetKey(descriptor_number), GetIsolate()), 3011 handle(GetValue(descriptor_number), GetIsolate()), 3012 GetDetails(descriptor_number)); 3013 } 3014 3015 3016 void DescriptorArray::SetDescriptor(int descriptor_number, Descriptor* desc) { 3017 // Range check. 3018 DCHECK(descriptor_number < number_of_descriptors()); 3019 set(ToKeyIndex(descriptor_number), *desc->GetKey()); 3020 set(ToValueIndex(descriptor_number), *desc->GetValue()); 3021 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); 3022 } 3023 3024 3025 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { 3026 // Range check. 3027 DCHECK(descriptor_number < number_of_descriptors()); 3028 3029 set(ToKeyIndex(descriptor_number), *desc->GetKey()); 3030 set(ToValueIndex(descriptor_number), *desc->GetValue()); 3031 set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi()); 3032 } 3033 3034 3035 void DescriptorArray::Append(Descriptor* desc) { 3036 DisallowHeapAllocation no_gc; 3037 int descriptor_number = number_of_descriptors(); 3038 SetNumberOfDescriptors(descriptor_number + 1); 3039 Set(descriptor_number, desc); 3040 3041 uint32_t hash = desc->GetKey()->Hash(); 3042 3043 int insertion; 3044 3045 for (insertion = descriptor_number; insertion > 0; --insertion) { 3046 Name* key = GetSortedKey(insertion - 1); 3047 if (key->Hash() <= hash) break; 3048 SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); 3049 } 3050 3051 SetSortedKey(insertion, descriptor_number); 3052 } 3053 3054 3055 void DescriptorArray::SwapSortedKeys(int first, int second) { 3056 int first_key = GetSortedKeyIndex(first); 3057 SetSortedKey(first, GetSortedKeyIndex(second)); 3058 SetSortedKey(second, first_key); 3059 } 3060 3061 3062 PropertyType DescriptorArray::Entry::type() { return descs_->GetType(index_); } 3063 3064 3065 Object* DescriptorArray::Entry::GetCallbackObject() { 3066 return descs_->GetValue(index_); 3067 } 3068 3069 3070 int HashTableBase::NumberOfElements() { 3071 return Smi::cast(get(kNumberOfElementsIndex))->value(); 3072 } 3073 3074 3075 int HashTableBase::NumberOfDeletedElements() { 3076 return Smi::cast(get(kNumberOfDeletedElementsIndex))->value(); 3077 } 3078 3079 3080 int HashTableBase::Capacity() { 3081 return Smi::cast(get(kCapacityIndex))->value(); 3082 } 3083 3084 3085 void HashTableBase::ElementAdded() { 3086 SetNumberOfElements(NumberOfElements() + 1); 3087 } 3088 3089 3090 void HashTableBase::ElementRemoved() { 3091 SetNumberOfElements(NumberOfElements() - 1); 3092 SetNumberOfDeletedElements(NumberOfDeletedElements() + 1); 3093 } 3094 3095 3096 void HashTableBase::ElementsRemoved(int n) { 3097 SetNumberOfElements(NumberOfElements() - n); 3098 SetNumberOfDeletedElements(NumberOfDeletedElements() + n); 3099 } 3100 3101 3102 // static 3103 int HashTableBase::ComputeCapacity(int at_least_space_for) { 3104 const int kMinCapacity = 4; 3105 int capacity = base::bits::RoundUpToPowerOfTwo32(at_least_space_for * 2); 3106 return Max(capacity, kMinCapacity); 3107 } 3108 3109 3110 bool HashTableBase::IsKey(Object* k) { 3111 return !k->IsTheHole() && !k->IsUndefined(); 3112 } 3113 3114 3115 void HashTableBase::SetNumberOfElements(int nof) { 3116 set(kNumberOfElementsIndex, Smi::FromInt(nof)); 3117 } 3118 3119 3120 void HashTableBase::SetNumberOfDeletedElements(int nod) { 3121 set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); 3122 } 3123 3124 3125 template <typename Derived, typename Shape, typename Key> 3126 int HashTable<Derived, Shape, Key>::FindEntry(Key key) { 3127 return FindEntry(GetIsolate(), key); 3128 } 3129 3130 3131 template<typename Derived, typename Shape, typename Key> 3132 int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key) { 3133 return FindEntry(isolate, key, HashTable::Hash(key)); 3134 } 3135 3136 3137 // Find entry for key otherwise return kNotFound. 3138 template <typename Derived, typename Shape, typename Key> 3139 int HashTable<Derived, Shape, Key>::FindEntry(Isolate* isolate, Key key, 3140 int32_t hash) { 3141 uint32_t capacity = Capacity(); 3142 uint32_t entry = FirstProbe(hash, capacity); 3143 uint32_t count = 1; 3144 // EnsureCapacity will guarantee the hash table is never full. 3145 while (true) { 3146 Object* element = KeyAt(entry); 3147 // Empty entry. Uses raw unchecked accessors because it is called by the 3148 // string table during bootstrapping. 3149 if (element == isolate->heap()->root(Heap::kUndefinedValueRootIndex)) break; 3150 if (element != isolate->heap()->root(Heap::kTheHoleValueRootIndex) && 3151 Shape::IsMatch(key, element)) return entry; 3152 entry = NextProbe(entry, count++, capacity); 3153 } 3154 return kNotFound; 3155 } 3156 3157 3158 bool SeededNumberDictionary::requires_slow_elements() { 3159 Object* max_index_object = get(kMaxNumberKeyIndex); 3160 if (!max_index_object->IsSmi()) return false; 3161 return 0 != 3162 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); 3163 } 3164 3165 3166 uint32_t SeededNumberDictionary::max_number_key() { 3167 DCHECK(!requires_slow_elements()); 3168 Object* max_index_object = get(kMaxNumberKeyIndex); 3169 if (!max_index_object->IsSmi()) return 0; 3170 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); 3171 return value >> kRequiresSlowElementsTagSize; 3172 } 3173 3174 3175 void SeededNumberDictionary::set_requires_slow_elements() { 3176 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); 3177 } 3178 3179 3180 // ------------------------------------ 3181 // Cast operations 3182 3183 3184 CAST_ACCESSOR(AccessorInfo) 3185 CAST_ACCESSOR(ArrayList) 3186 CAST_ACCESSOR(Bool16x8) 3187 CAST_ACCESSOR(Bool32x4) 3188 CAST_ACCESSOR(Bool8x16) 3189 CAST_ACCESSOR(ByteArray) 3190 CAST_ACCESSOR(BytecodeArray) 3191 CAST_ACCESSOR(Cell) 3192 CAST_ACCESSOR(Code) 3193 CAST_ACCESSOR(CodeCacheHashTable) 3194 CAST_ACCESSOR(CompilationCacheTable) 3195 CAST_ACCESSOR(ConsString) 3196 CAST_ACCESSOR(DeoptimizationInputData) 3197 CAST_ACCESSOR(DeoptimizationOutputData) 3198 CAST_ACCESSOR(DependentCode) 3199 CAST_ACCESSOR(DescriptorArray) 3200 CAST_ACCESSOR(ExternalOneByteString) 3201 CAST_ACCESSOR(ExternalString) 3202 CAST_ACCESSOR(ExternalTwoByteString) 3203 CAST_ACCESSOR(FixedArray) 3204 CAST_ACCESSOR(FixedArrayBase) 3205 CAST_ACCESSOR(FixedDoubleArray) 3206 CAST_ACCESSOR(FixedTypedArrayBase) 3207 CAST_ACCESSOR(Float32x4) 3208 CAST_ACCESSOR(Foreign) 3209 CAST_ACCESSOR(GlobalDictionary) 3210 CAST_ACCESSOR(HandlerTable) 3211 CAST_ACCESSOR(HeapObject) 3212 CAST_ACCESSOR(Int16x8) 3213 CAST_ACCESSOR(Int32x4) 3214 CAST_ACCESSOR(Int8x16) 3215 CAST_ACCESSOR(JSArray) 3216 CAST_ACCESSOR(JSArrayBuffer) 3217 CAST_ACCESSOR(JSArrayBufferView) 3218 CAST_ACCESSOR(JSBoundFunction) 3219 CAST_ACCESSOR(JSDataView) 3220 CAST_ACCESSOR(JSDate) 3221 CAST_ACCESSOR(JSFunction) 3222 CAST_ACCESSOR(JSGeneratorObject) 3223 CAST_ACCESSOR(JSGlobalObject) 3224 CAST_ACCESSOR(JSGlobalProxy) 3225 CAST_ACCESSOR(JSMap) 3226 CAST_ACCESSOR(JSMapIterator) 3227 CAST_ACCESSOR(JSMessageObject) 3228 CAST_ACCESSOR(JSModule) 3229 CAST_ACCESSOR(JSObject) 3230 CAST_ACCESSOR(JSProxy) 3231 CAST_ACCESSOR(JSReceiver) 3232 CAST_ACCESSOR(JSRegExp) 3233 CAST_ACCESSOR(JSSet) 3234 CAST_ACCESSOR(JSSetIterator) 3235 CAST_ACCESSOR(JSIteratorResult) 3236 CAST_ACCESSOR(JSTypedArray) 3237 CAST_ACCESSOR(JSValue) 3238 CAST_ACCESSOR(JSWeakMap) 3239 CAST_ACCESSOR(JSWeakSet) 3240 CAST_ACCESSOR(LayoutDescriptor) 3241 CAST_ACCESSOR(Map) 3242 CAST_ACCESSOR(Name) 3243 CAST_ACCESSOR(NameDictionary) 3244 CAST_ACCESSOR(NormalizedMapCache) 3245 CAST_ACCESSOR(Object) 3246 CAST_ACCESSOR(ObjectHashTable) 3247 CAST_ACCESSOR(Oddball) 3248 CAST_ACCESSOR(OrderedHashMap) 3249 CAST_ACCESSOR(OrderedHashSet) 3250 CAST_ACCESSOR(PolymorphicCodeCacheHashTable) 3251 CAST_ACCESSOR(PropertyCell) 3252 CAST_ACCESSOR(ScopeInfo) 3253 CAST_ACCESSOR(SeededNumberDictionary) 3254 CAST_ACCESSOR(SeqOneByteString) 3255 CAST_ACCESSOR(SeqString) 3256 CAST_ACCESSOR(SeqTwoByteString) 3257 CAST_ACCESSOR(SharedFunctionInfo) 3258 CAST_ACCESSOR(Simd128Value) 3259 CAST_ACCESSOR(SlicedString) 3260 CAST_ACCESSOR(Smi) 3261 CAST_ACCESSOR(String) 3262 CAST_ACCESSOR(StringTable) 3263 CAST_ACCESSOR(Struct) 3264 CAST_ACCESSOR(Symbol) 3265 CAST_ACCESSOR(Uint16x8) 3266 CAST_ACCESSOR(Uint32x4) 3267 CAST_ACCESSOR(Uint8x16) 3268 CAST_ACCESSOR(UnseededNumberDictionary) 3269 CAST_ACCESSOR(WeakCell) 3270 CAST_ACCESSOR(WeakFixedArray) 3271 CAST_ACCESSOR(WeakHashTable) 3272 3273 3274 // static 3275 template <class Traits> 3276 STATIC_CONST_MEMBER_DEFINITION const InstanceType 3277 FixedTypedArray<Traits>::kInstanceType; 3278 3279 3280 template <class Traits> 3281 FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) { 3282 SLOW_DCHECK(object->IsHeapObject() && 3283 HeapObject::cast(object)->map()->instance_type() == 3284 Traits::kInstanceType); 3285 return reinterpret_cast<FixedTypedArray<Traits>*>(object); 3286 } 3287 3288 3289 template <class Traits> 3290 const FixedTypedArray<Traits>* 3291 FixedTypedArray<Traits>::cast(const Object* object) { 3292 SLOW_DCHECK(object->IsHeapObject() && 3293 HeapObject::cast(object)->map()->instance_type() == 3294 Traits::kInstanceType); 3295 return reinterpret_cast<FixedTypedArray<Traits>*>(object); 3296 } 3297 3298 3299 #define DEFINE_DEOPT_ELEMENT_ACCESSORS(name, type) \ 3300 type* DeoptimizationInputData::name() { \ 3301 return type::cast(get(k##name##Index)); \ 3302 } \ 3303 void DeoptimizationInputData::Set##name(type* value) { \ 3304 set(k##name##Index, value); \ 3305 } 3306 3307 DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray) 3308 DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) 3309 DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray) 3310 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrAstId, Smi) 3311 DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi) 3312 DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi) 3313 DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object) 3314 DEFINE_DEOPT_ELEMENT_ACCESSORS(WeakCellCache, Object) 3315 3316 #undef DEFINE_DEOPT_ELEMENT_ACCESSORS 3317 3318 3319 #define DEFINE_DEOPT_ENTRY_ACCESSORS(name, type) \ 3320 type* DeoptimizationInputData::name(int i) { \ 3321 return type::cast(get(IndexForEntry(i) + k##name##Offset)); \ 3322 } \ 3323 void DeoptimizationInputData::Set##name(int i, type* value) { \ 3324 set(IndexForEntry(i) + k##name##Offset, value); \ 3325 } 3326 3327 DEFINE_DEOPT_ENTRY_ACCESSORS(AstIdRaw, Smi) 3328 DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi) 3329 DEFINE_DEOPT_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi) 3330 DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi) 3331 3332 #undef DEFINE_DEOPT_ENTRY_ACCESSORS 3333 3334 3335 BailoutId DeoptimizationInputData::AstId(int i) { 3336 return BailoutId(AstIdRaw(i)->value()); 3337 } 3338 3339 3340 void DeoptimizationInputData::SetAstId(int i, BailoutId value) { 3341 SetAstIdRaw(i, Smi::FromInt(value.ToInt())); 3342 } 3343 3344 3345 int DeoptimizationInputData::DeoptCount() { 3346 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize; 3347 } 3348 3349 3350 int DeoptimizationOutputData::DeoptPoints() { return length() / 2; } 3351 3352 3353 BailoutId DeoptimizationOutputData::AstId(int index) { 3354 return BailoutId(Smi::cast(get(index * 2))->value()); 3355 } 3356 3357 3358 void DeoptimizationOutputData::SetAstId(int index, BailoutId id) { 3359 set(index * 2, Smi::FromInt(id.ToInt())); 3360 } 3361 3362 3363 Smi* DeoptimizationOutputData::PcAndState(int index) { 3364 return Smi::cast(get(1 + index * 2)); 3365 } 3366 3367 3368 void DeoptimizationOutputData::SetPcAndState(int index, Smi* offset) { 3369 set(1 + index * 2, offset); 3370 } 3371 3372 3373 Object* LiteralsArray::get(int index) const { return FixedArray::get(index); } 3374 3375 3376 void LiteralsArray::set(int index, Object* value) { 3377 FixedArray::set(index, value); 3378 } 3379 3380 3381 void LiteralsArray::set(int index, Smi* value) { 3382 FixedArray::set(index, value); 3383 } 3384 3385 3386 void LiteralsArray::set(int index, Object* value, WriteBarrierMode mode) { 3387 FixedArray::set(index, value, mode); 3388 } 3389 3390 3391 LiteralsArray* LiteralsArray::cast(Object* object) { 3392 SLOW_DCHECK(object->IsLiteralsArray()); 3393 return reinterpret_cast<LiteralsArray*>(object); 3394 } 3395 3396 3397 TypeFeedbackVector* LiteralsArray::feedback_vector() const { 3398 return TypeFeedbackVector::cast(get(kVectorIndex)); 3399 } 3400 3401 3402 void LiteralsArray::set_feedback_vector(TypeFeedbackVector* vector) { 3403 set(kVectorIndex, vector); 3404 } 3405 3406 3407 Object* LiteralsArray::literal(int literal_index) const { 3408 return get(kFirstLiteralIndex + literal_index); 3409 } 3410 3411 3412 void LiteralsArray::set_literal(int literal_index, Object* literal) { 3413 set(kFirstLiteralIndex + literal_index, literal); 3414 } 3415 3416 3417 int LiteralsArray::literals_count() const { 3418 return length() - kFirstLiteralIndex; 3419 } 3420 3421 3422 void HandlerTable::SetRangeStart(int index, int value) { 3423 set(index * kRangeEntrySize + kRangeStartIndex, Smi::FromInt(value)); 3424 } 3425 3426 3427 void HandlerTable::SetRangeEnd(int index, int value) { 3428 set(index * kRangeEntrySize + kRangeEndIndex, Smi::FromInt(value)); 3429 } 3430 3431 3432 void HandlerTable::SetRangeHandler(int index, int offset, 3433 CatchPrediction prediction) { 3434 int value = HandlerOffsetField::encode(offset) | 3435 HandlerPredictionField::encode(prediction); 3436 set(index * kRangeEntrySize + kRangeHandlerIndex, Smi::FromInt(value)); 3437 } 3438 3439 3440 void HandlerTable::SetRangeDepth(int index, int value) { 3441 set(index * kRangeEntrySize + kRangeDepthIndex, Smi::FromInt(value)); 3442 } 3443 3444 3445 void HandlerTable::SetReturnOffset(int index, int value) { 3446 set(index * kReturnEntrySize + kReturnOffsetIndex, Smi::FromInt(value)); 3447 } 3448 3449 3450 void HandlerTable::SetReturnHandler(int index, int offset, 3451 CatchPrediction prediction) { 3452 int value = HandlerOffsetField::encode(offset) | 3453 HandlerPredictionField::encode(prediction); 3454 set(index * kReturnEntrySize + kReturnHandlerIndex, Smi::FromInt(value)); 3455 } 3456 3457 3458 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) 3459 STRUCT_LIST(MAKE_STRUCT_CAST) 3460 #undef MAKE_STRUCT_CAST 3461 3462 3463 template <typename Derived, typename Shape, typename Key> 3464 HashTable<Derived, Shape, Key>* 3465 HashTable<Derived, Shape, Key>::cast(Object* obj) { 3466 SLOW_DCHECK(obj->IsHashTable()); 3467 return reinterpret_cast<HashTable*>(obj); 3468 } 3469 3470 3471 template <typename Derived, typename Shape, typename Key> 3472 const HashTable<Derived, Shape, Key>* 3473 HashTable<Derived, Shape, Key>::cast(const Object* obj) { 3474 SLOW_DCHECK(obj->IsHashTable()); 3475 return reinterpret_cast<const HashTable*>(obj); 3476 } 3477 3478 3479 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) 3480 SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) 3481 3482 SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 3483 NOBARRIER_SMI_ACCESSORS(FreeSpace, size, kSizeOffset) 3484 3485 SMI_ACCESSORS(String, length, kLengthOffset) 3486 SYNCHRONIZED_SMI_ACCESSORS(String, length, kLengthOffset) 3487 3488 3489 int FreeSpace::Size() { return size(); } 3490 3491 3492 FreeSpace* FreeSpace::next() { 3493 DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) || 3494 (!GetHeap()->deserialization_complete() && map() == NULL)); 3495 DCHECK_LE(kNextOffset + kPointerSize, nobarrier_size()); 3496 return reinterpret_cast<FreeSpace*>( 3497 Memory::Address_at(address() + kNextOffset)); 3498 } 3499 3500 3501 void FreeSpace::set_next(FreeSpace* next) { 3502 DCHECK(map() == GetHeap()->root(Heap::kFreeSpaceMapRootIndex) || 3503 (!GetHeap()->deserialization_complete() && map() == NULL)); 3504 DCHECK_LE(kNextOffset + kPointerSize, nobarrier_size()); 3505 base::NoBarrier_Store( 3506 reinterpret_cast<base::AtomicWord*>(address() + kNextOffset), 3507 reinterpret_cast<base::AtomicWord>(next)); 3508 } 3509 3510 3511 FreeSpace* FreeSpace::cast(HeapObject* o) { 3512 SLOW_DCHECK(!o->GetHeap()->deserialization_complete() || o->IsFreeSpace()); 3513 return reinterpret_cast<FreeSpace*>(o); 3514 } 3515 3516 3517 uint32_t Name::hash_field() { 3518 return READ_UINT32_FIELD(this, kHashFieldOffset); 3519 } 3520 3521 3522 void Name::set_hash_field(uint32_t value) { 3523 WRITE_UINT32_FIELD(this, kHashFieldOffset, value); 3524 #if V8_HOST_ARCH_64_BIT 3525 #if V8_TARGET_LITTLE_ENDIAN 3526 WRITE_UINT32_FIELD(this, kHashFieldSlot + kIntSize, 0); 3527 #else 3528 WRITE_UINT32_FIELD(this, kHashFieldSlot, 0); 3529 #endif 3530 #endif 3531 } 3532 3533 3534 bool Name::Equals(Name* other) { 3535 if (other == this) return true; 3536 if ((this->IsInternalizedString() && other->IsInternalizedString()) || 3537 this->IsSymbol() || other->IsSymbol()) { 3538 return false; 3539 } 3540 return String::cast(this)->SlowEquals(String::cast(other)); 3541 } 3542 3543 3544 bool Name::Equals(Handle<Name> one, Handle<Name> two) { 3545 if (one.is_identical_to(two)) return true; 3546 if ((one->IsInternalizedString() && two->IsInternalizedString()) || 3547 one->IsSymbol() || two->IsSymbol()) { 3548 return false; 3549 } 3550 return String::SlowEquals(Handle<String>::cast(one), 3551 Handle<String>::cast(two)); 3552 } 3553 3554 3555 ACCESSORS(Symbol, name, Object, kNameOffset) 3556 SMI_ACCESSORS(Symbol, flags, kFlagsOffset) 3557 BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit) 3558 BOOL_ACCESSORS(Symbol, flags, is_well_known_symbol, kWellKnownSymbolBit) 3559 3560 3561 bool String::Equals(String* other) { 3562 if (other == this) return true; 3563 if (this->IsInternalizedString() && other->IsInternalizedString()) { 3564 return false; 3565 } 3566 return SlowEquals(other); 3567 } 3568 3569 3570 bool String::Equals(Handle<String> one, Handle<String> two) { 3571 if (one.is_identical_to(two)) return true; 3572 if (one->IsInternalizedString() && two->IsInternalizedString()) { 3573 return false; 3574 } 3575 return SlowEquals(one, two); 3576 } 3577 3578 3579 Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) { 3580 if (!string->IsConsString()) return string; 3581 Handle<ConsString> cons = Handle<ConsString>::cast(string); 3582 if (cons->IsFlat()) return handle(cons->first()); 3583 return SlowFlatten(cons, pretenure); 3584 } 3585 3586 3587 Handle<Name> Name::Flatten(Handle<Name> name, PretenureFlag pretenure) { 3588 if (name->IsSymbol()) return name; 3589 return String::Flatten(Handle<String>::cast(name)); 3590 } 3591 3592 3593 uint16_t String::Get(int index) { 3594 DCHECK(index >= 0 && index < length()); 3595 switch (StringShape(this).full_representation_tag()) { 3596 case kSeqStringTag | kOneByteStringTag: 3597 return SeqOneByteString::cast(this)->SeqOneByteStringGet(index); 3598 case kSeqStringTag | kTwoByteStringTag: 3599 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); 3600 case kConsStringTag | kOneByteStringTag: 3601 case kConsStringTag | kTwoByteStringTag: 3602 return ConsString::cast(this)->ConsStringGet(index); 3603 case kExternalStringTag | kOneByteStringTag: 3604 return ExternalOneByteString::cast(this)->ExternalOneByteStringGet(index); 3605 case kExternalStringTag | kTwoByteStringTag: 3606 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); 3607 case kSlicedStringTag | kOneByteStringTag: 3608 case kSlicedStringTag | kTwoByteStringTag: 3609 return SlicedString::cast(this)->SlicedStringGet(index); 3610 default: 3611 break; 3612 } 3613 3614 UNREACHABLE(); 3615 return 0; 3616 } 3617 3618 3619 void String::Set(int index, uint16_t value) { 3620 DCHECK(index >= 0 && index < length()); 3621 DCHECK(StringShape(this).IsSequential()); 3622 3623 return this->IsOneByteRepresentation() 3624 ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value) 3625 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); 3626 } 3627 3628 3629 bool String::IsFlat() { 3630 if (!StringShape(this).IsCons()) return true; 3631 return ConsString::cast(this)->second()->length() == 0; 3632 } 3633 3634 3635 String* String::GetUnderlying() { 3636 // Giving direct access to underlying string only makes sense if the 3637 // wrapping string is already flattened. 3638 DCHECK(this->IsFlat()); 3639 DCHECK(StringShape(this).IsIndirect()); 3640 STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset); 3641 const int kUnderlyingOffset = SlicedString::kParentOffset; 3642 return String::cast(READ_FIELD(this, kUnderlyingOffset)); 3643 } 3644 3645 3646 template<class Visitor> 3647 ConsString* String::VisitFlat(Visitor* visitor, 3648 String* string, 3649 const int offset) { 3650 int slice_offset = offset; 3651 const int length = string->length(); 3652 DCHECK(offset <= length); 3653 while (true) { 3654 int32_t type = string->map()->instance_type(); 3655 switch (type & (kStringRepresentationMask | kStringEncodingMask)) { 3656 case kSeqStringTag | kOneByteStringTag: 3657 visitor->VisitOneByteString( 3658 SeqOneByteString::cast(string)->GetChars() + slice_offset, 3659 length - offset); 3660 return NULL; 3661 3662 case kSeqStringTag | kTwoByteStringTag: 3663 visitor->VisitTwoByteString( 3664 SeqTwoByteString::cast(string)->GetChars() + slice_offset, 3665 length - offset); 3666 return NULL; 3667 3668 case kExternalStringTag | kOneByteStringTag: 3669 visitor->VisitOneByteString( 3670 ExternalOneByteString::cast(string)->GetChars() + slice_offset, 3671 length - offset); 3672 return NULL; 3673 3674 case kExternalStringTag | kTwoByteStringTag: 3675 visitor->VisitTwoByteString( 3676 ExternalTwoByteString::cast(string)->GetChars() + slice_offset, 3677 length - offset); 3678 return NULL; 3679 3680 case kSlicedStringTag | kOneByteStringTag: 3681 case kSlicedStringTag | kTwoByteStringTag: { 3682 SlicedString* slicedString = SlicedString::cast(string); 3683 slice_offset += slicedString->offset(); 3684 string = slicedString->parent(); 3685 continue; 3686 } 3687 3688 case kConsStringTag | kOneByteStringTag: 3689 case kConsStringTag | kTwoByteStringTag: 3690 return ConsString::cast(string); 3691 3692 default: 3693 UNREACHABLE(); 3694 return NULL; 3695 } 3696 } 3697 } 3698 3699 3700 template <> 3701 inline Vector<const uint8_t> String::GetCharVector() { 3702 String::FlatContent flat = GetFlatContent(); 3703 DCHECK(flat.IsOneByte()); 3704 return flat.ToOneByteVector(); 3705 } 3706 3707 3708 template <> 3709 inline Vector<const uc16> String::GetCharVector() { 3710 String::FlatContent flat = GetFlatContent(); 3711 DCHECK(flat.IsTwoByte()); 3712 return flat.ToUC16Vector(); 3713 } 3714 3715 3716 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) { 3717 DCHECK(index >= 0 && index < length()); 3718 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 3719 } 3720 3721 3722 void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) { 3723 DCHECK(index >= 0 && index < length() && value <= kMaxOneByteCharCode); 3724 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, 3725 static_cast<byte>(value)); 3726 } 3727 3728 3729 Address SeqOneByteString::GetCharsAddress() { 3730 return FIELD_ADDR(this, kHeaderSize); 3731 } 3732 3733 3734 uint8_t* SeqOneByteString::GetChars() { 3735 return reinterpret_cast<uint8_t*>(GetCharsAddress()); 3736 } 3737 3738 3739 Address SeqTwoByteString::GetCharsAddress() { 3740 return FIELD_ADDR(this, kHeaderSize); 3741 } 3742 3743 3744 uc16* SeqTwoByteString::GetChars() { 3745 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize)); 3746 } 3747 3748 3749 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) { 3750 DCHECK(index >= 0 && index < length()); 3751 return READ_UINT16_FIELD(this, kHeaderSize + index * kShortSize); 3752 } 3753 3754 3755 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { 3756 DCHECK(index >= 0 && index < length()); 3757 WRITE_UINT16_FIELD(this, kHeaderSize + index * kShortSize, value); 3758 } 3759 3760 3761 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { 3762 return SizeFor(length()); 3763 } 3764 3765 3766 int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) { 3767 return SizeFor(length()); 3768 } 3769 3770 3771 String* SlicedString::parent() { 3772 return String::cast(READ_FIELD(this, kParentOffset)); 3773 } 3774 3775 3776 void SlicedString::set_parent(String* parent, WriteBarrierMode mode) { 3777 DCHECK(parent->IsSeqString() || parent->IsExternalString()); 3778 WRITE_FIELD(this, kParentOffset, parent); 3779 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode); 3780 } 3781 3782 3783 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset) 3784 3785 3786 String* ConsString::first() { 3787 return String::cast(READ_FIELD(this, kFirstOffset)); 3788 } 3789 3790 3791 Object* ConsString::unchecked_first() { 3792 return READ_FIELD(this, kFirstOffset); 3793 } 3794 3795 3796 void ConsString::set_first(String* value, WriteBarrierMode mode) { 3797 WRITE_FIELD(this, kFirstOffset, value); 3798 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode); 3799 } 3800 3801 3802 String* ConsString::second() { 3803 return String::cast(READ_FIELD(this, kSecondOffset)); 3804 } 3805 3806 3807 Object* ConsString::unchecked_second() { 3808 return READ_FIELD(this, kSecondOffset); 3809 } 3810 3811 3812 void ConsString::set_second(String* value, WriteBarrierMode mode) { 3813 WRITE_FIELD(this, kSecondOffset, value); 3814 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode); 3815 } 3816 3817 3818 bool ExternalString::is_short() { 3819 InstanceType type = map()->instance_type(); 3820 return (type & kShortExternalStringMask) == kShortExternalStringTag; 3821 } 3822 3823 3824 const ExternalOneByteString::Resource* ExternalOneByteString::resource() { 3825 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 3826 } 3827 3828 3829 void ExternalOneByteString::update_data_cache() { 3830 if (is_short()) return; 3831 const char** data_field = 3832 reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset)); 3833 *data_field = resource()->data(); 3834 } 3835 3836 3837 void ExternalOneByteString::set_resource( 3838 const ExternalOneByteString::Resource* resource) { 3839 DCHECK(IsAligned(reinterpret_cast<intptr_t>(resource), kPointerSize)); 3840 *reinterpret_cast<const Resource**>( 3841 FIELD_ADDR(this, kResourceOffset)) = resource; 3842 if (resource != NULL) update_data_cache(); 3843 } 3844 3845 3846 const uint8_t* ExternalOneByteString::GetChars() { 3847 return reinterpret_cast<const uint8_t*>(resource()->data()); 3848 } 3849 3850 3851 uint16_t ExternalOneByteString::ExternalOneByteStringGet(int index) { 3852 DCHECK(index >= 0 && index < length()); 3853 return GetChars()[index]; 3854 } 3855 3856 3857 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() { 3858 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 3859 } 3860 3861 3862 void ExternalTwoByteString::update_data_cache() { 3863 if (is_short()) return; 3864 const uint16_t** data_field = 3865 reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset)); 3866 *data_field = resource()->data(); 3867 } 3868 3869 3870 void ExternalTwoByteString::set_resource( 3871 const ExternalTwoByteString::Resource* resource) { 3872 *reinterpret_cast<const Resource**>( 3873 FIELD_ADDR(this, kResourceOffset)) = resource; 3874 if (resource != NULL) update_data_cache(); 3875 } 3876 3877 3878 const uint16_t* ExternalTwoByteString::GetChars() { 3879 return resource()->data(); 3880 } 3881 3882 3883 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) { 3884 DCHECK(index >= 0 && index < length()); 3885 return GetChars()[index]; 3886 } 3887 3888 3889 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData( 3890 unsigned start) { 3891 return GetChars() + start; 3892 } 3893 3894 3895 int ConsStringIterator::OffsetForDepth(int depth) { return depth & kDepthMask; } 3896 3897 3898 void ConsStringIterator::PushLeft(ConsString* string) { 3899 frames_[depth_++ & kDepthMask] = string; 3900 } 3901 3902 3903 void ConsStringIterator::PushRight(ConsString* string) { 3904 // Inplace update. 3905 frames_[(depth_-1) & kDepthMask] = string; 3906 } 3907 3908 3909 void ConsStringIterator::AdjustMaximumDepth() { 3910 if (depth_ > maximum_depth_) maximum_depth_ = depth_; 3911 } 3912 3913 3914 void ConsStringIterator::Pop() { 3915 DCHECK(depth_ > 0); 3916 DCHECK(depth_ <= maximum_depth_); 3917 depth_--; 3918 } 3919 3920 3921 uint16_t StringCharacterStream::GetNext() { 3922 DCHECK(buffer8_ != NULL && end_ != NULL); 3923 // Advance cursor if needed. 3924 if (buffer8_ == end_) HasMore(); 3925 DCHECK(buffer8_ < end_); 3926 return is_one_byte_ ? *buffer8_++ : *buffer16_++; 3927 } 3928 3929 3930 StringCharacterStream::StringCharacterStream(String* string, int offset) 3931 : is_one_byte_(false) { 3932 Reset(string, offset); 3933 } 3934 3935 3936 void StringCharacterStream::Reset(String* string, int offset) { 3937 buffer8_ = NULL; 3938 end_ = NULL; 3939 ConsString* cons_string = String::VisitFlat(this, string, offset); 3940 iter_.Reset(cons_string, offset); 3941 if (cons_string != NULL) { 3942 string = iter_.Next(&offset); 3943 if (string != NULL) String::VisitFlat(this, string, offset); 3944 } 3945 } 3946 3947 3948 bool StringCharacterStream::HasMore() { 3949 if (buffer8_ != end_) return true; 3950 int offset; 3951 String* string = iter_.Next(&offset); 3952 DCHECK_EQ(offset, 0); 3953 if (string == NULL) return false; 3954 String::VisitFlat(this, string); 3955 DCHECK(buffer8_ != end_); 3956 return true; 3957 } 3958 3959 3960 void StringCharacterStream::VisitOneByteString( 3961 const uint8_t* chars, int length) { 3962 is_one_byte_ = true; 3963 buffer8_ = chars; 3964 end_ = chars + length; 3965 } 3966 3967 3968 void StringCharacterStream::VisitTwoByteString( 3969 const uint16_t* chars, int length) { 3970 is_one_byte_ = false; 3971 buffer16_ = chars; 3972 end_ = reinterpret_cast<const uint8_t*>(chars + length); 3973 } 3974 3975 3976 int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); } 3977 3978 3979 byte ByteArray::get(int index) { 3980 DCHECK(index >= 0 && index < this->length()); 3981 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 3982 } 3983 3984 3985 void ByteArray::set(int index, byte value) { 3986 DCHECK(index >= 0 && index < this->length()); 3987 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 3988 } 3989 3990 3991 int ByteArray::get_int(int index) { 3992 DCHECK(index >= 0 && (index * kIntSize) < this->length()); 3993 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize); 3994 } 3995 3996 3997 ByteArray* ByteArray::FromDataStartAddress(Address address) { 3998 DCHECK_TAG_ALIGNED(address); 3999 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag); 4000 } 4001 4002 4003 int ByteArray::ByteArraySize() { return SizeFor(this->length()); } 4004 4005 4006 Address ByteArray::GetDataStartAddress() { 4007 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 4008 } 4009 4010 4011 byte BytecodeArray::get(int index) { 4012 DCHECK(index >= 0 && index < this->length()); 4013 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 4014 } 4015 4016 4017 void BytecodeArray::set(int index, byte value) { 4018 DCHECK(index >= 0 && index < this->length()); 4019 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 4020 } 4021 4022 4023 void BytecodeArray::set_frame_size(int frame_size) { 4024 DCHECK_GE(frame_size, 0); 4025 DCHECK(IsAligned(frame_size, static_cast<unsigned>(kPointerSize))); 4026 WRITE_INT_FIELD(this, kFrameSizeOffset, frame_size); 4027 } 4028 4029 4030 int BytecodeArray::frame_size() const { 4031 return READ_INT_FIELD(this, kFrameSizeOffset); 4032 } 4033 4034 4035 int BytecodeArray::register_count() const { 4036 return frame_size() / kPointerSize; 4037 } 4038 4039 4040 void BytecodeArray::set_parameter_count(int number_of_parameters) { 4041 DCHECK_GE(number_of_parameters, 0); 4042 // Parameter count is stored as the size on stack of the parameters to allow 4043 // it to be used directly by generated code. 4044 WRITE_INT_FIELD(this, kParameterSizeOffset, 4045 (number_of_parameters << kPointerSizeLog2)); 4046 } 4047 4048 4049 int BytecodeArray::parameter_count() const { 4050 // Parameter count is stored as the size on stack of the parameters to allow 4051 // it to be used directly by generated code. 4052 return READ_INT_FIELD(this, kParameterSizeOffset) >> kPointerSizeLog2; 4053 } 4054 4055 4056 ACCESSORS(BytecodeArray, constant_pool, FixedArray, kConstantPoolOffset) 4057 4058 4059 Address BytecodeArray::GetFirstBytecodeAddress() { 4060 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 4061 } 4062 4063 4064 int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); } 4065 4066 4067 ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset) 4068 4069 4070 void* FixedTypedArrayBase::external_pointer() const { 4071 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset); 4072 return reinterpret_cast<void*>(ptr); 4073 } 4074 4075 4076 void FixedTypedArrayBase::set_external_pointer(void* value, 4077 WriteBarrierMode mode) { 4078 intptr_t ptr = reinterpret_cast<intptr_t>(value); 4079 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr); 4080 } 4081 4082 4083 void* FixedTypedArrayBase::DataPtr() { 4084 return reinterpret_cast<void*>( 4085 reinterpret_cast<intptr_t>(base_pointer()) + 4086 reinterpret_cast<intptr_t>(external_pointer())); 4087 } 4088 4089 4090 int FixedTypedArrayBase::ElementSize(InstanceType type) { 4091 int element_size; 4092 switch (type) { 4093 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 4094 case FIXED_##TYPE##_ARRAY_TYPE: \ 4095 element_size = size; \ 4096 break; 4097 4098 TYPED_ARRAYS(TYPED_ARRAY_CASE) 4099 #undef TYPED_ARRAY_CASE 4100 default: 4101 UNREACHABLE(); 4102 return 0; 4103 } 4104 return element_size; 4105 } 4106 4107 4108 int FixedTypedArrayBase::DataSize(InstanceType type) { 4109 if (base_pointer() == Smi::FromInt(0)) return 0; 4110 return length() * ElementSize(type); 4111 } 4112 4113 4114 int FixedTypedArrayBase::DataSize() { 4115 return DataSize(map()->instance_type()); 4116 } 4117 4118 4119 int FixedTypedArrayBase::size() { 4120 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize()); 4121 } 4122 4123 4124 int FixedTypedArrayBase::TypedArraySize(InstanceType type) { 4125 return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type)); 4126 } 4127 4128 4129 int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) { 4130 return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type)); 4131 } 4132 4133 4134 uint8_t Uint8ArrayTraits::defaultValue() { return 0; } 4135 4136 4137 uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; } 4138 4139 4140 int8_t Int8ArrayTraits::defaultValue() { return 0; } 4141 4142 4143 uint16_t Uint16ArrayTraits::defaultValue() { return 0; } 4144 4145 4146 int16_t Int16ArrayTraits::defaultValue() { return 0; } 4147 4148 4149 uint32_t Uint32ArrayTraits::defaultValue() { return 0; } 4150 4151 4152 int32_t Int32ArrayTraits::defaultValue() { return 0; } 4153 4154 4155 float Float32ArrayTraits::defaultValue() { 4156 return std::numeric_limits<float>::quiet_NaN(); 4157 } 4158 4159 4160 double Float64ArrayTraits::defaultValue() { 4161 return std::numeric_limits<double>::quiet_NaN(); 4162 } 4163 4164 4165 template <class Traits> 4166 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) { 4167 DCHECK((index >= 0) && (index < this->length())); 4168 ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr()); 4169 return ptr[index]; 4170 } 4171 4172 4173 template <class Traits> 4174 void FixedTypedArray<Traits>::set(int index, ElementType value) { 4175 DCHECK((index >= 0) && (index < this->length())); 4176 ElementType* ptr = reinterpret_cast<ElementType*>(DataPtr()); 4177 ptr[index] = value; 4178 } 4179 4180 4181 template <class Traits> 4182 typename Traits::ElementType FixedTypedArray<Traits>::from_int(int value) { 4183 return static_cast<ElementType>(value); 4184 } 4185 4186 4187 template <> inline 4188 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_int(int value) { 4189 if (value < 0) return 0; 4190 if (value > 0xFF) return 0xFF; 4191 return static_cast<uint8_t>(value); 4192 } 4193 4194 4195 template <class Traits> 4196 typename Traits::ElementType FixedTypedArray<Traits>::from_double( 4197 double value) { 4198 return static_cast<ElementType>(DoubleToInt32(value)); 4199 } 4200 4201 4202 template<> inline 4203 uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from_double(double value) { 4204 // Handle NaNs and less than zero values which clamp to zero. 4205 if (!(value > 0)) return 0; 4206 if (value > 0xFF) return 0xFF; 4207 return static_cast<uint8_t>(lrint(value)); 4208 } 4209 4210 4211 template<> inline 4212 float FixedTypedArray<Float32ArrayTraits>::from_double(double value) { 4213 return static_cast<float>(value); 4214 } 4215 4216 4217 template<> inline 4218 double FixedTypedArray<Float64ArrayTraits>::from_double(double value) { 4219 return value; 4220 } 4221 4222 4223 template <class Traits> 4224 Handle<Object> FixedTypedArray<Traits>::get( 4225 Handle<FixedTypedArray<Traits> > array, 4226 int index) { 4227 return Traits::ToHandle(array->GetIsolate(), array->get_scalar(index)); 4228 } 4229 4230 4231 template <class Traits> 4232 void FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) { 4233 ElementType cast_value = Traits::defaultValue(); 4234 if (value->IsSmi()) { 4235 int int_value = Smi::cast(value)->value(); 4236 cast_value = from_int(int_value); 4237 } else if (value->IsHeapNumber()) { 4238 double double_value = HeapNumber::cast(value)->value(); 4239 cast_value = from_double(double_value); 4240 } else { 4241 // Clamp undefined to the default value. All other types have been 4242 // converted to a number type further up in the call chain. 4243 DCHECK(value->IsUndefined()); 4244 } 4245 set(index, cast_value); 4246 } 4247 4248 4249 Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) { 4250 return handle(Smi::FromInt(scalar), isolate); 4251 } 4252 4253 4254 Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate, 4255 uint8_t scalar) { 4256 return handle(Smi::FromInt(scalar), isolate); 4257 } 4258 4259 4260 Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) { 4261 return handle(Smi::FromInt(scalar), isolate); 4262 } 4263 4264 4265 Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) { 4266 return handle(Smi::FromInt(scalar), isolate); 4267 } 4268 4269 4270 Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) { 4271 return handle(Smi::FromInt(scalar), isolate); 4272 } 4273 4274 4275 Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) { 4276 return isolate->factory()->NewNumberFromUint(scalar); 4277 } 4278 4279 4280 Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) { 4281 return isolate->factory()->NewNumberFromInt(scalar); 4282 } 4283 4284 4285 Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) { 4286 return isolate->factory()->NewNumber(scalar); 4287 } 4288 4289 4290 Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) { 4291 return isolate->factory()->NewNumber(scalar); 4292 } 4293 4294 4295 int Map::visitor_id() { 4296 return READ_BYTE_FIELD(this, kVisitorIdOffset); 4297 } 4298 4299 4300 void Map::set_visitor_id(int id) { 4301 DCHECK(0 <= id && id < 256); 4302 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id)); 4303 } 4304 4305 4306 int Map::instance_size() { 4307 return NOBARRIER_READ_BYTE_FIELD( 4308 this, kInstanceSizeOffset) << kPointerSizeLog2; 4309 } 4310 4311 4312 int Map::inobject_properties_or_constructor_function_index() { 4313 return READ_BYTE_FIELD(this, 4314 kInObjectPropertiesOrConstructorFunctionIndexOffset); 4315 } 4316 4317 4318 void Map::set_inobject_properties_or_constructor_function_index(int value) { 4319 DCHECK(0 <= value && value < 256); 4320 WRITE_BYTE_FIELD(this, kInObjectPropertiesOrConstructorFunctionIndexOffset, 4321 static_cast<byte>(value)); 4322 } 4323 4324 4325 int Map::GetInObjectProperties() { 4326 DCHECK(IsJSObjectMap()); 4327 return inobject_properties_or_constructor_function_index(); 4328 } 4329 4330 4331 void Map::SetInObjectProperties(int value) { 4332 DCHECK(IsJSObjectMap()); 4333 set_inobject_properties_or_constructor_function_index(value); 4334 } 4335 4336 4337 int Map::GetConstructorFunctionIndex() { 4338 DCHECK(IsPrimitiveMap()); 4339 return inobject_properties_or_constructor_function_index(); 4340 } 4341 4342 4343 void Map::SetConstructorFunctionIndex(int value) { 4344 DCHECK(IsPrimitiveMap()); 4345 set_inobject_properties_or_constructor_function_index(value); 4346 } 4347 4348 4349 int Map::GetInObjectPropertyOffset(int index) { 4350 // Adjust for the number of properties stored in the object. 4351 index -= GetInObjectProperties(); 4352 DCHECK(index <= 0); 4353 return instance_size() + (index * kPointerSize); 4354 } 4355 4356 4357 Handle<Map> Map::AddMissingTransitionsForTesting( 4358 Handle<Map> split_map, Handle<DescriptorArray> descriptors, 4359 Handle<LayoutDescriptor> full_layout_descriptor) { 4360 return AddMissingTransitions(split_map, descriptors, full_layout_descriptor); 4361 } 4362 4363 4364 int HeapObject::SizeFromMap(Map* map) { 4365 int instance_size = map->instance_size(); 4366 if (instance_size != kVariableSizeSentinel) return instance_size; 4367 // Only inline the most frequent cases. 4368 InstanceType instance_type = map->instance_type(); 4369 if (instance_type == FIXED_ARRAY_TYPE || 4370 instance_type == TRANSITION_ARRAY_TYPE) { 4371 return FixedArray::SizeFor( 4372 reinterpret_cast<FixedArray*>(this)->synchronized_length()); 4373 } 4374 if (instance_type == ONE_BYTE_STRING_TYPE || 4375 instance_type == ONE_BYTE_INTERNALIZED_STRING_TYPE) { 4376 // Strings may get concurrently truncated, hence we have to access its 4377 // length synchronized. 4378 return SeqOneByteString::SizeFor( 4379 reinterpret_cast<SeqOneByteString*>(this)->synchronized_length()); 4380 } 4381 if (instance_type == BYTE_ARRAY_TYPE) { 4382 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 4383 } 4384 if (instance_type == BYTECODE_ARRAY_TYPE) { 4385 return reinterpret_cast<BytecodeArray*>(this)->BytecodeArraySize(); 4386 } 4387 if (instance_type == FREE_SPACE_TYPE) { 4388 return reinterpret_cast<FreeSpace*>(this)->nobarrier_size(); 4389 } 4390 if (instance_type == STRING_TYPE || 4391 instance_type == INTERNALIZED_STRING_TYPE) { 4392 // Strings may get concurrently truncated, hence we have to access its 4393 // length synchronized. 4394 return SeqTwoByteString::SizeFor( 4395 reinterpret_cast<SeqTwoByteString*>(this)->synchronized_length()); 4396 } 4397 if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) { 4398 return FixedDoubleArray::SizeFor( 4399 reinterpret_cast<FixedDoubleArray*>(this)->length()); 4400 } 4401 if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE && 4402 instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) { 4403 return reinterpret_cast<FixedTypedArrayBase*>( 4404 this)->TypedArraySize(instance_type); 4405 } 4406 DCHECK(instance_type == CODE_TYPE); 4407 return reinterpret_cast<Code*>(this)->CodeSize(); 4408 } 4409 4410 4411 void Map::set_instance_size(int value) { 4412 DCHECK_EQ(0, value & (kPointerSize - 1)); 4413 value >>= kPointerSizeLog2; 4414 DCHECK(0 <= value && value < 256); 4415 NOBARRIER_WRITE_BYTE_FIELD( 4416 this, kInstanceSizeOffset, static_cast<byte>(value)); 4417 } 4418 4419 4420 void Map::clear_unused() { WRITE_BYTE_FIELD(this, kUnusedOffset, 0); } 4421 4422 4423 InstanceType Map::instance_type() { 4424 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset)); 4425 } 4426 4427 4428 void Map::set_instance_type(InstanceType value) { 4429 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value); 4430 } 4431 4432 4433 int Map::unused_property_fields() { 4434 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset); 4435 } 4436 4437 4438 void Map::set_unused_property_fields(int value) { 4439 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255)); 4440 } 4441 4442 4443 byte Map::bit_field() const { return READ_BYTE_FIELD(this, kBitFieldOffset); } 4444 4445 4446 void Map::set_bit_field(byte value) { 4447 WRITE_BYTE_FIELD(this, kBitFieldOffset, value); 4448 } 4449 4450 4451 byte Map::bit_field2() const { return READ_BYTE_FIELD(this, kBitField2Offset); } 4452 4453 4454 void Map::set_bit_field2(byte value) { 4455 WRITE_BYTE_FIELD(this, kBitField2Offset, value); 4456 } 4457 4458 4459 void Map::set_non_instance_prototype(bool value) { 4460 if (value) { 4461 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); 4462 } else { 4463 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype)); 4464 } 4465 } 4466 4467 4468 bool Map::has_non_instance_prototype() { 4469 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; 4470 } 4471 4472 4473 void Map::set_is_constructor() { 4474 set_bit_field(bit_field() | (1 << kIsConstructor)); 4475 } 4476 4477 4478 bool Map::is_constructor() const { 4479 return ((1 << kIsConstructor) & bit_field()) != 0; 4480 } 4481 4482 4483 void Map::set_is_hidden_prototype() { 4484 set_bit_field3(IsHiddenPrototype::update(bit_field3(), true)); 4485 } 4486 4487 4488 bool Map::is_hidden_prototype() const { 4489 return IsHiddenPrototype::decode(bit_field3()); 4490 } 4491 4492 4493 void Map::set_has_indexed_interceptor() { 4494 set_bit_field(bit_field() | (1 << kHasIndexedInterceptor)); 4495 } 4496 4497 4498 bool Map::has_indexed_interceptor() { 4499 return ((1 << kHasIndexedInterceptor) & bit_field()) != 0; 4500 } 4501 4502 4503 void Map::set_is_undetectable() { 4504 set_bit_field(bit_field() | (1 << kIsUndetectable)); 4505 } 4506 4507 4508 bool Map::is_undetectable() { 4509 return ((1 << kIsUndetectable) & bit_field()) != 0; 4510 } 4511 4512 4513 void Map::set_is_observed() { set_bit_field(bit_field() | (1 << kIsObserved)); } 4514 4515 bool Map::is_observed() { return ((1 << kIsObserved) & bit_field()) != 0; } 4516 4517 4518 void Map::set_has_named_interceptor() { 4519 set_bit_field(bit_field() | (1 << kHasNamedInterceptor)); 4520 } 4521 4522 4523 bool Map::has_named_interceptor() { 4524 return ((1 << kHasNamedInterceptor) & bit_field()) != 0; 4525 } 4526 4527 4528 void Map::set_is_access_check_needed(bool access_check_needed) { 4529 if (access_check_needed) { 4530 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); 4531 } else { 4532 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); 4533 } 4534 } 4535 4536 4537 bool Map::is_access_check_needed() { 4538 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0; 4539 } 4540 4541 4542 void Map::set_is_extensible(bool value) { 4543 if (value) { 4544 set_bit_field2(bit_field2() | (1 << kIsExtensible)); 4545 } else { 4546 set_bit_field2(bit_field2() & ~(1 << kIsExtensible)); 4547 } 4548 } 4549 4550 bool Map::is_extensible() { 4551 return ((1 << kIsExtensible) & bit_field2()) != 0; 4552 } 4553 4554 4555 void Map::set_is_prototype_map(bool value) { 4556 set_bit_field2(IsPrototypeMapBits::update(bit_field2(), value)); 4557 } 4558 4559 bool Map::is_prototype_map() const { 4560 return IsPrototypeMapBits::decode(bit_field2()); 4561 } 4562 4563 4564 void Map::set_elements_kind(ElementsKind elements_kind) { 4565 DCHECK(static_cast<int>(elements_kind) < kElementsKindCount); 4566 DCHECK(kElementsKindCount <= (1 << Map::ElementsKindBits::kSize)); 4567 set_bit_field2(Map::ElementsKindBits::update(bit_field2(), elements_kind)); 4568 DCHECK(this->elements_kind() == elements_kind); 4569 } 4570 4571 4572 ElementsKind Map::elements_kind() { 4573 return Map::ElementsKindBits::decode(bit_field2()); 4574 } 4575 4576 4577 bool Map::has_fast_smi_elements() { 4578 return IsFastSmiElementsKind(elements_kind()); 4579 } 4580 4581 bool Map::has_fast_object_elements() { 4582 return IsFastObjectElementsKind(elements_kind()); 4583 } 4584 4585 bool Map::has_fast_smi_or_object_elements() { 4586 return IsFastSmiOrObjectElementsKind(elements_kind()); 4587 } 4588 4589 bool Map::has_fast_double_elements() { 4590 return IsFastDoubleElementsKind(elements_kind()); 4591 } 4592 4593 bool Map::has_fast_elements() { return IsFastElementsKind(elements_kind()); } 4594 4595 bool Map::has_sloppy_arguments_elements() { 4596 return IsSloppyArgumentsElements(elements_kind()); 4597 } 4598 4599 bool Map::has_fixed_typed_array_elements() { 4600 return IsFixedTypedArrayElementsKind(elements_kind()); 4601 } 4602 4603 bool Map::has_dictionary_elements() { 4604 return IsDictionaryElementsKind(elements_kind()); 4605 } 4606 4607 4608 void Map::set_dictionary_map(bool value) { 4609 uint32_t new_bit_field3 = DictionaryMap::update(bit_field3(), value); 4610 new_bit_field3 = IsUnstable::update(new_bit_field3, value); 4611 set_bit_field3(new_bit_field3); 4612 } 4613 4614 4615 bool Map::is_dictionary_map() { 4616 return DictionaryMap::decode(bit_field3()); 4617 } 4618 4619 4620 Code::Flags Code::flags() { 4621 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset)); 4622 } 4623 4624 4625 void Map::set_owns_descriptors(bool owns_descriptors) { 4626 set_bit_field3(OwnsDescriptors::update(bit_field3(), owns_descriptors)); 4627 } 4628 4629 4630 bool Map::owns_descriptors() { 4631 return OwnsDescriptors::decode(bit_field3()); 4632 } 4633 4634 4635 void Map::set_is_callable() { set_bit_field(bit_field() | (1 << kIsCallable)); } 4636 4637 4638 bool Map::is_callable() const { 4639 return ((1 << kIsCallable) & bit_field()) != 0; 4640 } 4641 4642 4643 void Map::deprecate() { 4644 set_bit_field3(Deprecated::update(bit_field3(), true)); 4645 } 4646 4647 4648 bool Map::is_deprecated() { 4649 return Deprecated::decode(bit_field3()); 4650 } 4651 4652 4653 void Map::set_migration_target(bool value) { 4654 set_bit_field3(IsMigrationTarget::update(bit_field3(), value)); 4655 } 4656 4657 4658 bool Map::is_migration_target() { 4659 return IsMigrationTarget::decode(bit_field3()); 4660 } 4661 4662 4663 void Map::set_is_strong() { 4664 set_bit_field3(IsStrong::update(bit_field3(), true)); 4665 } 4666 4667 4668 bool Map::is_strong() { 4669 return IsStrong::decode(bit_field3()); 4670 } 4671 4672 4673 void Map::set_new_target_is_base(bool value) { 4674 set_bit_field3(NewTargetIsBase::update(bit_field3(), value)); 4675 } 4676 4677 4678 bool Map::new_target_is_base() { return NewTargetIsBase::decode(bit_field3()); } 4679 4680 4681 void Map::set_construction_counter(int value) { 4682 set_bit_field3(ConstructionCounter::update(bit_field3(), value)); 4683 } 4684 4685 4686 int Map::construction_counter() { 4687 return ConstructionCounter::decode(bit_field3()); 4688 } 4689 4690 4691 void Map::mark_unstable() { 4692 set_bit_field3(IsUnstable::update(bit_field3(), true)); 4693 } 4694 4695 4696 bool Map::is_stable() { 4697 return !IsUnstable::decode(bit_field3()); 4698 } 4699 4700 4701 bool Map::has_code_cache() { 4702 return code_cache() != GetIsolate()->heap()->empty_fixed_array(); 4703 } 4704 4705 4706 bool Map::CanBeDeprecated() { 4707 int descriptor = LastAdded(); 4708 for (int i = 0; i <= descriptor; i++) { 4709 PropertyDetails details = instance_descriptors()->GetDetails(i); 4710 if (details.representation().IsNone()) return true; 4711 if (details.representation().IsSmi()) return true; 4712 if (details.representation().IsDouble()) return true; 4713 if (details.representation().IsHeapObject()) return true; 4714 if (details.type() == DATA_CONSTANT) return true; 4715 } 4716 return false; 4717 } 4718 4719 4720 void Map::NotifyLeafMapLayoutChange() { 4721 if (is_stable()) { 4722 mark_unstable(); 4723 dependent_code()->DeoptimizeDependentCodeGroup( 4724 GetIsolate(), 4725 DependentCode::kPrototypeCheckGroup); 4726 } 4727 } 4728 4729 4730 bool Map::CanTransition() { 4731 // Only JSObject and subtypes have map transitions and back pointers. 4732 STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE); 4733 return instance_type() >= FIRST_JS_OBJECT_TYPE; 4734 } 4735 4736 4737 bool Map::IsBooleanMap() { return this == GetHeap()->boolean_map(); } 4738 bool Map::IsPrimitiveMap() { 4739 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); 4740 return instance_type() <= LAST_PRIMITIVE_TYPE; 4741 } 4742 bool Map::IsJSReceiverMap() { 4743 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); 4744 return instance_type() >= FIRST_JS_RECEIVER_TYPE; 4745 } 4746 bool Map::IsJSObjectMap() { 4747 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE); 4748 return instance_type() >= FIRST_JS_OBJECT_TYPE; 4749 } 4750 bool Map::IsJSArrayMap() { return instance_type() == JS_ARRAY_TYPE; } 4751 bool Map::IsJSFunctionMap() { return instance_type() == JS_FUNCTION_TYPE; } 4752 bool Map::IsStringMap() { return instance_type() < FIRST_NONSTRING_TYPE; } 4753 bool Map::IsJSProxyMap() { return instance_type() == JS_PROXY_TYPE; } 4754 bool Map::IsJSGlobalProxyMap() { 4755 return instance_type() == JS_GLOBAL_PROXY_TYPE; 4756 } 4757 bool Map::IsJSGlobalObjectMap() { 4758 return instance_type() == JS_GLOBAL_OBJECT_TYPE; 4759 } 4760 bool Map::IsJSTypedArrayMap() { return instance_type() == JS_TYPED_ARRAY_TYPE; } 4761 bool Map::IsJSDataViewMap() { return instance_type() == JS_DATA_VIEW_TYPE; } 4762 4763 4764 bool Map::CanOmitMapChecks() { 4765 return is_stable() && FLAG_omit_map_checks_for_leaf_maps; 4766 } 4767 4768 4769 DependentCode* DependentCode::next_link() { 4770 return DependentCode::cast(get(kNextLinkIndex)); 4771 } 4772 4773 4774 void DependentCode::set_next_link(DependentCode* next) { 4775 set(kNextLinkIndex, next); 4776 } 4777 4778 4779 int DependentCode::flags() { return Smi::cast(get(kFlagsIndex))->value(); } 4780 4781 4782 void DependentCode::set_flags(int flags) { 4783 set(kFlagsIndex, Smi::FromInt(flags)); 4784 } 4785 4786 4787 int DependentCode::count() { return CountField::decode(flags()); } 4788 4789 void DependentCode::set_count(int value) { 4790 set_flags(CountField::update(flags(), value)); 4791 } 4792 4793 4794 DependentCode::DependencyGroup DependentCode::group() { 4795 return static_cast<DependencyGroup>(GroupField::decode(flags())); 4796 } 4797 4798 4799 void DependentCode::set_group(DependentCode::DependencyGroup group) { 4800 set_flags(GroupField::update(flags(), static_cast<int>(group))); 4801 } 4802 4803 4804 void DependentCode::set_object_at(int i, Object* object) { 4805 set(kCodesStartIndex + i, object); 4806 } 4807 4808 4809 Object* DependentCode::object_at(int i) { 4810 return get(kCodesStartIndex + i); 4811 } 4812 4813 4814 void DependentCode::clear_at(int i) { 4815 set_undefined(kCodesStartIndex + i); 4816 } 4817 4818 4819 void DependentCode::copy(int from, int to) { 4820 set(kCodesStartIndex + to, get(kCodesStartIndex + from)); 4821 } 4822 4823 4824 void Code::set_flags(Code::Flags flags) { 4825 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1); 4826 WRITE_INT_FIELD(this, kFlagsOffset, flags); 4827 } 4828 4829 4830 Code::Kind Code::kind() { 4831 return ExtractKindFromFlags(flags()); 4832 } 4833 4834 4835 bool Code::IsCodeStubOrIC() { 4836 return kind() == STUB || kind() == HANDLER || kind() == LOAD_IC || 4837 kind() == KEYED_LOAD_IC || kind() == CALL_IC || kind() == STORE_IC || 4838 kind() == KEYED_STORE_IC || kind() == BINARY_OP_IC || 4839 kind() == COMPARE_IC || kind() == COMPARE_NIL_IC || 4840 kind() == TO_BOOLEAN_IC; 4841 } 4842 4843 4844 bool Code::IsJavaScriptCode() { 4845 return kind() == FUNCTION || kind() == OPTIMIZED_FUNCTION || 4846 is_interpreter_entry_trampoline(); 4847 } 4848 4849 4850 InlineCacheState Code::ic_state() { 4851 InlineCacheState result = ExtractICStateFromFlags(flags()); 4852 // Only allow uninitialized or debugger states for non-IC code 4853 // objects. This is used in the debugger to determine whether or not 4854 // a call to code object has been replaced with a debug break call. 4855 DCHECK(is_inline_cache_stub() || 4856 result == UNINITIALIZED || 4857 result == DEBUG_STUB); 4858 return result; 4859 } 4860 4861 4862 ExtraICState Code::extra_ic_state() { 4863 DCHECK(is_inline_cache_stub() || ic_state() == DEBUG_STUB); 4864 return ExtractExtraICStateFromFlags(flags()); 4865 } 4866 4867 4868 Code::StubType Code::type() { 4869 return ExtractTypeFromFlags(flags()); 4870 } 4871 4872 4873 // For initialization. 4874 void Code::set_raw_kind_specific_flags1(int value) { 4875 WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value); 4876 } 4877 4878 4879 void Code::set_raw_kind_specific_flags2(int value) { 4880 WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value); 4881 } 4882 4883 4884 inline bool Code::is_crankshafted() { 4885 return IsCrankshaftedField::decode( 4886 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)); 4887 } 4888 4889 4890 inline bool Code::is_hydrogen_stub() { 4891 return is_crankshafted() && kind() != OPTIMIZED_FUNCTION; 4892 } 4893 4894 4895 inline bool Code::is_interpreter_entry_trampoline() { 4896 Handle<Code> interpreter_entry = 4897 GetIsolate()->builtins()->InterpreterEntryTrampoline(); 4898 return interpreter_entry.location() != nullptr && *interpreter_entry == this; 4899 } 4900 4901 inline void Code::set_is_crankshafted(bool value) { 4902 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 4903 int updated = IsCrankshaftedField::update(previous, value); 4904 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 4905 } 4906 4907 4908 inline bool Code::is_turbofanned() { 4909 return IsTurbofannedField::decode( 4910 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4911 } 4912 4913 4914 inline void Code::set_is_turbofanned(bool value) { 4915 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4916 int updated = IsTurbofannedField::update(previous, value); 4917 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4918 } 4919 4920 4921 inline bool Code::can_have_weak_objects() { 4922 DCHECK(kind() == OPTIMIZED_FUNCTION); 4923 return CanHaveWeakObjectsField::decode( 4924 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 4925 } 4926 4927 4928 inline void Code::set_can_have_weak_objects(bool value) { 4929 DCHECK(kind() == OPTIMIZED_FUNCTION); 4930 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 4931 int updated = CanHaveWeakObjectsField::update(previous, value); 4932 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 4933 } 4934 4935 4936 bool Code::has_deoptimization_support() { 4937 DCHECK_EQ(FUNCTION, kind()); 4938 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4939 return FullCodeFlagsHasDeoptimizationSupportField::decode(flags); 4940 } 4941 4942 4943 void Code::set_has_deoptimization_support(bool value) { 4944 DCHECK_EQ(FUNCTION, kind()); 4945 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4946 flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value); 4947 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 4948 } 4949 4950 4951 bool Code::has_debug_break_slots() { 4952 DCHECK_EQ(FUNCTION, kind()); 4953 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4954 return FullCodeFlagsHasDebugBreakSlotsField::decode(flags); 4955 } 4956 4957 4958 void Code::set_has_debug_break_slots(bool value) { 4959 DCHECK_EQ(FUNCTION, kind()); 4960 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4961 flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value); 4962 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 4963 } 4964 4965 4966 bool Code::has_reloc_info_for_serialization() { 4967 DCHECK_EQ(FUNCTION, kind()); 4968 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4969 return FullCodeFlagsHasRelocInfoForSerialization::decode(flags); 4970 } 4971 4972 4973 void Code::set_has_reloc_info_for_serialization(bool value) { 4974 DCHECK_EQ(FUNCTION, kind()); 4975 unsigned flags = READ_UINT32_FIELD(this, kFullCodeFlags); 4976 flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value); 4977 WRITE_UINT32_FIELD(this, kFullCodeFlags, flags); 4978 } 4979 4980 4981 int Code::allow_osr_at_loop_nesting_level() { 4982 DCHECK_EQ(FUNCTION, kind()); 4983 int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 4984 return AllowOSRAtLoopNestingLevelField::decode(fields); 4985 } 4986 4987 4988 void Code::set_allow_osr_at_loop_nesting_level(int level) { 4989 DCHECK_EQ(FUNCTION, kind()); 4990 DCHECK(level >= 0 && level <= kMaxLoopNestingMarker); 4991 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 4992 int updated = AllowOSRAtLoopNestingLevelField::update(previous, level); 4993 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 4994 } 4995 4996 4997 int Code::profiler_ticks() { 4998 DCHECK_EQ(FUNCTION, kind()); 4999 return ProfilerTicksField::decode( 5000 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5001 } 5002 5003 5004 void Code::set_profiler_ticks(int ticks) { 5005 if (kind() == FUNCTION) { 5006 unsigned previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5007 unsigned updated = ProfilerTicksField::update(previous, ticks); 5008 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5009 } 5010 } 5011 5012 5013 int Code::builtin_index() { 5014 return READ_INT32_FIELD(this, kKindSpecificFlags1Offset); 5015 } 5016 5017 5018 void Code::set_builtin_index(int index) { 5019 WRITE_INT32_FIELD(this, kKindSpecificFlags1Offset, index); 5020 } 5021 5022 5023 unsigned Code::stack_slots() { 5024 DCHECK(is_crankshafted()); 5025 return StackSlotsField::decode( 5026 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5027 } 5028 5029 5030 void Code::set_stack_slots(unsigned slots) { 5031 CHECK(slots <= (1 << kStackSlotsBitCount)); 5032 DCHECK(is_crankshafted()); 5033 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5034 int updated = StackSlotsField::update(previous, slots); 5035 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5036 } 5037 5038 5039 unsigned Code::safepoint_table_offset() { 5040 DCHECK(is_crankshafted()); 5041 return SafepointTableOffsetField::decode( 5042 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)); 5043 } 5044 5045 5046 void Code::set_safepoint_table_offset(unsigned offset) { 5047 CHECK(offset <= (1 << kSafepointTableOffsetBitCount)); 5048 DCHECK(is_crankshafted()); 5049 DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize))); 5050 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5051 int updated = SafepointTableOffsetField::update(previous, offset); 5052 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 5053 } 5054 5055 5056 unsigned Code::back_edge_table_offset() { 5057 DCHECK_EQ(FUNCTION, kind()); 5058 return BackEdgeTableOffsetField::decode( 5059 READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2; 5060 } 5061 5062 5063 void Code::set_back_edge_table_offset(unsigned offset) { 5064 DCHECK_EQ(FUNCTION, kind()); 5065 DCHECK(IsAligned(offset, static_cast<unsigned>(kPointerSize))); 5066 offset = offset >> kPointerSizeLog2; 5067 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); 5068 int updated = BackEdgeTableOffsetField::update(previous, offset); 5069 WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated); 5070 } 5071 5072 5073 bool Code::back_edges_patched_for_osr() { 5074 DCHECK_EQ(FUNCTION, kind()); 5075 return allow_osr_at_loop_nesting_level() > 0; 5076 } 5077 5078 5079 uint16_t Code::to_boolean_state() { return extra_ic_state(); } 5080 5081 5082 bool Code::marked_for_deoptimization() { 5083 DCHECK(kind() == OPTIMIZED_FUNCTION); 5084 return MarkedForDeoptimizationField::decode( 5085 READ_UINT32_FIELD(this, kKindSpecificFlags1Offset)); 5086 } 5087 5088 5089 void Code::set_marked_for_deoptimization(bool flag) { 5090 DCHECK(kind() == OPTIMIZED_FUNCTION); 5091 DCHECK(!flag || AllowDeoptimization::IsAllowed(GetIsolate())); 5092 int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset); 5093 int updated = MarkedForDeoptimizationField::update(previous, flag); 5094 WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated); 5095 } 5096 5097 5098 bool Code::is_inline_cache_stub() { 5099 Kind kind = this->kind(); 5100 switch (kind) { 5101 #define CASE(name) case name: return true; 5102 IC_KIND_LIST(CASE) 5103 #undef CASE 5104 default: return false; 5105 } 5106 } 5107 5108 5109 bool Code::is_keyed_stub() { 5110 return is_keyed_load_stub() || is_keyed_store_stub(); 5111 } 5112 5113 5114 bool Code::is_debug_stub() { return ic_state() == DEBUG_STUB; } 5115 bool Code::is_handler() { return kind() == HANDLER; } 5116 bool Code::is_load_stub() { return kind() == LOAD_IC; } 5117 bool Code::is_keyed_load_stub() { return kind() == KEYED_LOAD_IC; } 5118 bool Code::is_store_stub() { return kind() == STORE_IC; } 5119 bool Code::is_keyed_store_stub() { return kind() == KEYED_STORE_IC; } 5120 bool Code::is_call_stub() { return kind() == CALL_IC; } 5121 bool Code::is_binary_op_stub() { return kind() == BINARY_OP_IC; } 5122 bool Code::is_compare_ic_stub() { return kind() == COMPARE_IC; } 5123 bool Code::is_compare_nil_ic_stub() { return kind() == COMPARE_NIL_IC; } 5124 bool Code::is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; } 5125 bool Code::is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; } 5126 5127 5128 bool Code::embeds_maps_weakly() { 5129 Kind k = kind(); 5130 return (k == LOAD_IC || k == STORE_IC || k == KEYED_LOAD_IC || 5131 k == KEYED_STORE_IC || k == COMPARE_NIL_IC) && 5132 ic_state() == MONOMORPHIC; 5133 } 5134 5135 5136 Address Code::constant_pool() { 5137 Address constant_pool = NULL; 5138 if (FLAG_enable_embedded_constant_pool) { 5139 int offset = constant_pool_offset(); 5140 if (offset < instruction_size()) { 5141 constant_pool = FIELD_ADDR(this, kHeaderSize + offset); 5142 } 5143 } 5144 return constant_pool; 5145 } 5146 5147 5148 Code::Flags Code::ComputeFlags(Kind kind, InlineCacheState ic_state, 5149 ExtraICState extra_ic_state, StubType type, 5150 CacheHolderFlag holder) { 5151 // Compute the bit mask. 5152 unsigned int bits = KindField::encode(kind) 5153 | ICStateField::encode(ic_state) 5154 | TypeField::encode(type) 5155 | ExtraICStateField::encode(extra_ic_state) 5156 | CacheHolderField::encode(holder); 5157 return static_cast<Flags>(bits); 5158 } 5159 5160 5161 Code::Flags Code::ComputeMonomorphicFlags(Kind kind, 5162 ExtraICState extra_ic_state, 5163 CacheHolderFlag holder, 5164 StubType type) { 5165 return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, holder); 5166 } 5167 5168 5169 Code::Flags Code::ComputeHandlerFlags(Kind handler_kind, StubType type, 5170 CacheHolderFlag holder) { 5171 return ComputeFlags(Code::HANDLER, MONOMORPHIC, handler_kind, type, holder); 5172 } 5173 5174 5175 Code::Kind Code::ExtractKindFromFlags(Flags flags) { 5176 return KindField::decode(flags); 5177 } 5178 5179 5180 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) { 5181 return ICStateField::decode(flags); 5182 } 5183 5184 5185 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) { 5186 return ExtraICStateField::decode(flags); 5187 } 5188 5189 5190 Code::StubType Code::ExtractTypeFromFlags(Flags flags) { 5191 return TypeField::decode(flags); 5192 } 5193 5194 5195 CacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) { 5196 return CacheHolderField::decode(flags); 5197 } 5198 5199 5200 Code::Flags Code::RemoveTypeFromFlags(Flags flags) { 5201 int bits = flags & ~TypeField::kMask; 5202 return static_cast<Flags>(bits); 5203 } 5204 5205 5206 Code::Flags Code::RemoveTypeAndHolderFromFlags(Flags flags) { 5207 int bits = flags & ~TypeField::kMask & ~CacheHolderField::kMask; 5208 return static_cast<Flags>(bits); 5209 } 5210 5211 5212 Code* Code::GetCodeFromTargetAddress(Address address) { 5213 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize); 5214 // GetCodeFromTargetAddress might be called when marking objects during mark 5215 // sweep. reinterpret_cast is therefore used instead of the more appropriate 5216 // Code::cast. Code::cast does not work when the object's map is 5217 // marked. 5218 Code* result = reinterpret_cast<Code*>(code); 5219 return result; 5220 } 5221 5222 5223 Object* Code::GetObjectFromEntryAddress(Address location_of_address) { 5224 return HeapObject:: 5225 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize); 5226 } 5227 5228 5229 bool Code::CanContainWeakObjects() { 5230 return is_optimized_code() && can_have_weak_objects(); 5231 } 5232 5233 5234 bool Code::IsWeakObject(Object* object) { 5235 return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object)); 5236 } 5237 5238 5239 bool Code::IsWeakObjectInOptimizedCode(Object* object) { 5240 if (object->IsMap()) { 5241 return Map::cast(object)->CanTransition() && 5242 FLAG_weak_embedded_maps_in_optimized_code; 5243 } 5244 if (object->IsCell()) { 5245 object = Cell::cast(object)->value(); 5246 } else if (object->IsPropertyCell()) { 5247 object = PropertyCell::cast(object)->value(); 5248 } 5249 if (object->IsJSReceiver()) { 5250 return FLAG_weak_embedded_objects_in_optimized_code; 5251 } 5252 if (object->IsContext()) { 5253 // Contexts of inlined functions are embedded in optimized code. 5254 return FLAG_weak_embedded_objects_in_optimized_code; 5255 } 5256 return false; 5257 } 5258 5259 5260 class Code::FindAndReplacePattern { 5261 public: 5262 FindAndReplacePattern() : count_(0) { } 5263 void Add(Handle<Map> map_to_find, Handle<Object> obj_to_replace) { 5264 DCHECK(count_ < kMaxCount); 5265 find_[count_] = map_to_find; 5266 replace_[count_] = obj_to_replace; 5267 ++count_; 5268 } 5269 private: 5270 static const int kMaxCount = 4; 5271 int count_; 5272 Handle<Map> find_[kMaxCount]; 5273 Handle<Object> replace_[kMaxCount]; 5274 friend class Code; 5275 }; 5276 5277 5278 Object* Map::prototype() const { 5279 return READ_FIELD(this, kPrototypeOffset); 5280 } 5281 5282 5283 void Map::set_prototype(Object* value, WriteBarrierMode mode) { 5284 DCHECK(value->IsNull() || value->IsJSReceiver()); 5285 WRITE_FIELD(this, kPrototypeOffset, value); 5286 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode); 5287 } 5288 5289 5290 LayoutDescriptor* Map::layout_descriptor_gc_safe() { 5291 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); 5292 return LayoutDescriptor::cast_gc_safe(layout_desc); 5293 } 5294 5295 5296 bool Map::HasFastPointerLayout() const { 5297 Object* layout_desc = READ_FIELD(this, kLayoutDecriptorOffset); 5298 return LayoutDescriptor::IsFastPointerLayout(layout_desc); 5299 } 5300 5301 5302 void Map::UpdateDescriptors(DescriptorArray* descriptors, 5303 LayoutDescriptor* layout_desc) { 5304 set_instance_descriptors(descriptors); 5305 if (FLAG_unbox_double_fields) { 5306 if (layout_descriptor()->IsSlowLayout()) { 5307 set_layout_descriptor(layout_desc); 5308 } 5309 #ifdef VERIFY_HEAP 5310 // TODO(ishell): remove these checks from VERIFY_HEAP mode. 5311 if (FLAG_verify_heap) { 5312 CHECK(layout_descriptor()->IsConsistentWithMap(this)); 5313 CHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); 5314 } 5315 #else 5316 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); 5317 DCHECK(visitor_id() == Heap::GetStaticVisitorIdForMap(this)); 5318 #endif 5319 } 5320 } 5321 5322 5323 void Map::InitializeDescriptors(DescriptorArray* descriptors, 5324 LayoutDescriptor* layout_desc) { 5325 int len = descriptors->number_of_descriptors(); 5326 set_instance_descriptors(descriptors); 5327 SetNumberOfOwnDescriptors(len); 5328 5329 if (FLAG_unbox_double_fields) { 5330 set_layout_descriptor(layout_desc); 5331 #ifdef VERIFY_HEAP 5332 // TODO(ishell): remove these checks from VERIFY_HEAP mode. 5333 if (FLAG_verify_heap) { 5334 CHECK(layout_descriptor()->IsConsistentWithMap(this)); 5335 } 5336 #else 5337 SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this)); 5338 #endif 5339 set_visitor_id(Heap::GetStaticVisitorIdForMap(this)); 5340 } 5341 } 5342 5343 5344 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset) 5345 ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDecriptorOffset) 5346 5347 5348 void Map::set_bit_field3(uint32_t bits) { 5349 if (kInt32Size != kPointerSize) { 5350 WRITE_UINT32_FIELD(this, kBitField3Offset + kInt32Size, 0); 5351 } 5352 WRITE_UINT32_FIELD(this, kBitField3Offset, bits); 5353 } 5354 5355 5356 uint32_t Map::bit_field3() const { 5357 return READ_UINT32_FIELD(this, kBitField3Offset); 5358 } 5359 5360 5361 LayoutDescriptor* Map::GetLayoutDescriptor() { 5362 return FLAG_unbox_double_fields ? layout_descriptor() 5363 : LayoutDescriptor::FastPointerLayout(); 5364 } 5365 5366 5367 void Map::AppendDescriptor(Descriptor* desc) { 5368 DescriptorArray* descriptors = instance_descriptors(); 5369 int number_of_own_descriptors = NumberOfOwnDescriptors(); 5370 DCHECK(descriptors->number_of_descriptors() == number_of_own_descriptors); 5371 descriptors->Append(desc); 5372 SetNumberOfOwnDescriptors(number_of_own_descriptors + 1); 5373 5374 // This function does not support appending double field descriptors and 5375 // it should never try to (otherwise, layout descriptor must be updated too). 5376 #ifdef DEBUG 5377 PropertyDetails details = desc->GetDetails(); 5378 CHECK(details.type() != DATA || !details.representation().IsDouble()); 5379 #endif 5380 } 5381 5382 5383 Object* Map::GetBackPointer() { 5384 Object* object = constructor_or_backpointer(); 5385 if (object->IsMap()) { 5386 return object; 5387 } 5388 return GetIsolate()->heap()->undefined_value(); 5389 } 5390 5391 5392 Map* Map::ElementsTransitionMap() { 5393 return TransitionArray::SearchSpecial( 5394 this, GetHeap()->elements_transition_symbol()); 5395 } 5396 5397 5398 ACCESSORS(Map, raw_transitions, Object, kTransitionsOrPrototypeInfoOffset) 5399 5400 5401 Object* Map::prototype_info() const { 5402 DCHECK(is_prototype_map()); 5403 return READ_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset); 5404 } 5405 5406 5407 void Map::set_prototype_info(Object* value, WriteBarrierMode mode) { 5408 DCHECK(is_prototype_map()); 5409 WRITE_FIELD(this, Map::kTransitionsOrPrototypeInfoOffset, value); 5410 CONDITIONAL_WRITE_BARRIER( 5411 GetHeap(), this, Map::kTransitionsOrPrototypeInfoOffset, value, mode); 5412 } 5413 5414 5415 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { 5416 DCHECK(instance_type() >= FIRST_JS_RECEIVER_TYPE); 5417 DCHECK((value->IsMap() && GetBackPointer()->IsUndefined())); 5418 DCHECK(!value->IsMap() || 5419 Map::cast(value)->GetConstructor() == constructor_or_backpointer()); 5420 set_constructor_or_backpointer(value, mode); 5421 } 5422 5423 5424 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) 5425 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset) 5426 ACCESSORS(Map, weak_cell_cache, Object, kWeakCellCacheOffset) 5427 ACCESSORS(Map, constructor_or_backpointer, Object, 5428 kConstructorOrBackPointerOffset) 5429 5430 5431 Object* Map::GetConstructor() const { 5432 Object* maybe_constructor = constructor_or_backpointer(); 5433 // Follow any back pointers. 5434 while (maybe_constructor->IsMap()) { 5435 maybe_constructor = 5436 Map::cast(maybe_constructor)->constructor_or_backpointer(); 5437 } 5438 return maybe_constructor; 5439 } 5440 5441 5442 void Map::SetConstructor(Object* constructor, WriteBarrierMode mode) { 5443 // Never overwrite a back pointer with a constructor. 5444 DCHECK(!constructor_or_backpointer()->IsMap()); 5445 set_constructor_or_backpointer(constructor, mode); 5446 } 5447 5448 5449 Handle<Map> Map::CopyInitialMap(Handle<Map> map) { 5450 return CopyInitialMap(map, map->instance_size(), map->GetInObjectProperties(), 5451 map->unused_property_fields()); 5452 } 5453 5454 5455 ACCESSORS(JSBoundFunction, length, Object, kLengthOffset) 5456 ACCESSORS(JSBoundFunction, name, Object, kNameOffset) 5457 ACCESSORS(JSBoundFunction, bound_target_function, JSReceiver, 5458 kBoundTargetFunctionOffset) 5459 ACCESSORS(JSBoundFunction, bound_this, Object, kBoundThisOffset) 5460 ACCESSORS(JSBoundFunction, bound_arguments, FixedArray, kBoundArgumentsOffset) 5461 ACCESSORS(JSBoundFunction, creation_context, Context, kCreationContextOffset) 5462 5463 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) 5464 ACCESSORS(JSFunction, literals, LiteralsArray, kLiteralsOffset) 5465 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset) 5466 5467 ACCESSORS(JSGlobalObject, native_context, Context, kNativeContextOffset) 5468 ACCESSORS(JSGlobalObject, global_proxy, JSObject, kGlobalProxyOffset) 5469 5470 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset) 5471 ACCESSORS(JSGlobalProxy, hash, Object, kHashOffset) 5472 5473 ACCESSORS(AccessorInfo, name, Object, kNameOffset) 5474 SMI_ACCESSORS(AccessorInfo, flag, kFlagOffset) 5475 ACCESSORS(AccessorInfo, expected_receiver_type, Object, 5476 kExpectedReceiverTypeOffset) 5477 5478 ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset) 5479 ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset) 5480 ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset) 5481 5482 ACCESSORS(Box, value, Object, kValueOffset) 5483 5484 ACCESSORS(PrototypeInfo, prototype_users, Object, kPrototypeUsersOffset) 5485 SMI_ACCESSORS(PrototypeInfo, registry_slot, kRegistrySlotOffset) 5486 ACCESSORS(PrototypeInfo, validity_cell, Object, kValidityCellOffset) 5487 5488 ACCESSORS(SloppyBlockWithEvalContextExtension, scope_info, ScopeInfo, 5489 kScopeInfoOffset) 5490 ACCESSORS(SloppyBlockWithEvalContextExtension, extension, JSObject, 5491 kExtensionOffset) 5492 5493 ACCESSORS(AccessorPair, getter, Object, kGetterOffset) 5494 ACCESSORS(AccessorPair, setter, Object, kSetterOffset) 5495 5496 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset) 5497 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset) 5498 ACCESSORS(AccessCheckInfo, callback, Object, kCallbackOffset) 5499 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) 5500 5501 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset) 5502 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset) 5503 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) 5504 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) 5505 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) 5506 ACCESSORS(InterceptorInfo, data, Object, kDataOffset) 5507 SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset) 5508 BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols, 5509 kCanInterceptSymbolsBit) 5510 BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit) 5511 BOOL_ACCESSORS(InterceptorInfo, flags, non_masking, kNonMasking) 5512 5513 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) 5514 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) 5515 ACCESSORS(CallHandlerInfo, fast_handler, Object, kFastHandlerOffset) 5516 5517 ACCESSORS(TemplateInfo, tag, Object, kTagOffset) 5518 SMI_ACCESSORS(TemplateInfo, number_of_properties, kNumberOfProperties) 5519 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset) 5520 ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset) 5521 5522 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset) 5523 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset) 5524 ACCESSORS(FunctionTemplateInfo, prototype_template, Object, 5525 kPrototypeTemplateOffset) 5526 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset) 5527 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object, 5528 kNamedPropertyHandlerOffset) 5529 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object, 5530 kIndexedPropertyHandlerOffset) 5531 ACCESSORS(FunctionTemplateInfo, instance_template, Object, 5532 kInstanceTemplateOffset) 5533 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset) 5534 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset) 5535 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object, 5536 kInstanceCallHandlerOffset) 5537 ACCESSORS(FunctionTemplateInfo, access_check_info, Object, 5538 kAccessCheckInfoOffset) 5539 SMI_ACCESSORS(FunctionTemplateInfo, flag, kFlagOffset) 5540 5541 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) 5542 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, 5543 kInternalFieldCountOffset) 5544 5545 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset) 5546 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset) 5547 SMI_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset) 5548 SMI_ACCESSORS(AllocationSite, pretenure_create_count, 5549 kPretenureCreateCountOffset) 5550 ACCESSORS(AllocationSite, dependent_code, DependentCode, 5551 kDependentCodeOffset) 5552 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset) 5553 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset) 5554 5555 ACCESSORS(Script, source, Object, kSourceOffset) 5556 ACCESSORS(Script, name, Object, kNameOffset) 5557 SMI_ACCESSORS(Script, id, kIdOffset) 5558 SMI_ACCESSORS(Script, line_offset, kLineOffsetOffset) 5559 SMI_ACCESSORS(Script, column_offset, kColumnOffsetOffset) 5560 ACCESSORS(Script, context_data, Object, kContextOffset) 5561 ACCESSORS(Script, wrapper, HeapObject, kWrapperOffset) 5562 SMI_ACCESSORS(Script, type, kTypeOffset) 5563 ACCESSORS(Script, line_ends, Object, kLineEndsOffset) 5564 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset) 5565 SMI_ACCESSORS(Script, eval_from_instructions_offset, 5566 kEvalFrominstructionsOffsetOffset) 5567 ACCESSORS(Script, shared_function_infos, Object, kSharedFunctionInfosOffset) 5568 SMI_ACCESSORS(Script, flags, kFlagsOffset) 5569 ACCESSORS(Script, source_url, Object, kSourceUrlOffset) 5570 ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset) 5571 5572 Script::CompilationType Script::compilation_type() { 5573 return BooleanBit::get(flags(), kCompilationTypeBit) ? 5574 COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST; 5575 } 5576 void Script::set_compilation_type(CompilationType type) { 5577 set_flags(BooleanBit::set(flags(), kCompilationTypeBit, 5578 type == COMPILATION_TYPE_EVAL)); 5579 } 5580 bool Script::hide_source() { return BooleanBit::get(flags(), kHideSourceBit); } 5581 void Script::set_hide_source(bool value) { 5582 set_flags(BooleanBit::set(flags(), kHideSourceBit, value)); 5583 } 5584 Script::CompilationState Script::compilation_state() { 5585 return BooleanBit::get(flags(), kCompilationStateBit) ? 5586 COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL; 5587 } 5588 void Script::set_compilation_state(CompilationState state) { 5589 set_flags(BooleanBit::set(flags(), kCompilationStateBit, 5590 state == COMPILATION_STATE_COMPILED)); 5591 } 5592 ScriptOriginOptions Script::origin_options() { 5593 return ScriptOriginOptions((flags() & kOriginOptionsMask) >> 5594 kOriginOptionsShift); 5595 } 5596 void Script::set_origin_options(ScriptOriginOptions origin_options) { 5597 DCHECK(!(origin_options.Flags() & ~((1 << kOriginOptionsSize) - 1))); 5598 set_flags((flags() & ~kOriginOptionsMask) | 5599 (origin_options.Flags() << kOriginOptionsShift)); 5600 } 5601 5602 5603 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) 5604 ACCESSORS(DebugInfo, code, Code, kCodeIndex) 5605 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) 5606 5607 SMI_ACCESSORS(BreakPointInfo, code_position, kCodePositionIndex) 5608 SMI_ACCESSORS(BreakPointInfo, source_position, kSourcePositionIndex) 5609 SMI_ACCESSORS(BreakPointInfo, statement_position, kStatementPositionIndex) 5610 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) 5611 5612 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset) 5613 ACCESSORS(SharedFunctionInfo, optimized_code_map, FixedArray, 5614 kOptimizedCodeMapOffset) 5615 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) 5616 ACCESSORS(SharedFunctionInfo, feedback_vector, TypeFeedbackVector, 5617 kFeedbackVectorOffset) 5618 #if TRACE_MAPS 5619 SMI_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset) 5620 #endif 5621 ACCESSORS(SharedFunctionInfo, instance_class_name, Object, 5622 kInstanceClassNameOffset) 5623 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) 5624 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset) 5625 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset) 5626 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset) 5627 5628 5629 SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset) 5630 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype, 5631 kHiddenPrototypeBit) 5632 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit) 5633 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check, 5634 kNeedsAccessCheckBit) 5635 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype, 5636 kReadOnlyPrototypeBit) 5637 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype, 5638 kRemovePrototypeBit) 5639 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, 5640 kDoNotCacheBit) 5641 BOOL_ACCESSORS(FunctionTemplateInfo, flag, instantiated, kInstantiatedBit) 5642 BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, 5643 kAcceptAnyReceiver) 5644 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression, 5645 kIsExpressionBit) 5646 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel, 5647 kIsTopLevelBit) 5648 5649 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, allows_lazy_compilation, 5650 kAllowLazyCompilation) 5651 BOOL_ACCESSORS(SharedFunctionInfo, 5652 compiler_hints, 5653 allows_lazy_compilation_without_context, 5654 kAllowLazyCompilationWithoutContext) 5655 BOOL_ACCESSORS(SharedFunctionInfo, 5656 compiler_hints, 5657 uses_arguments, 5658 kUsesArguments) 5659 BOOL_ACCESSORS(SharedFunctionInfo, 5660 compiler_hints, 5661 has_duplicate_parameters, 5662 kHasDuplicateParameters) 5663 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, asm_function, kIsAsmFunction) 5664 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, deserialized, kDeserialized) 5665 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, never_compiled, 5666 kNeverCompiled) 5667 5668 5669 #if V8_HOST_ARCH_32_BIT 5670 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) 5671 SMI_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count, 5672 kFormalParameterCountOffset) 5673 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties, 5674 kExpectedNofPropertiesOffset) 5675 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset) 5676 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type, 5677 kStartPositionAndTypeOffset) 5678 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset) 5679 SMI_ACCESSORS(SharedFunctionInfo, function_token_position, 5680 kFunctionTokenPositionOffset) 5681 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints, 5682 kCompilerHintsOffset) 5683 SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason, 5684 kOptCountAndBailoutReasonOffset) 5685 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset) 5686 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset) 5687 SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset) 5688 5689 #else 5690 5691 #if V8_TARGET_LITTLE_ENDIAN 5692 #define PSEUDO_SMI_LO_ALIGN 0 5693 #define PSEUDO_SMI_HI_ALIGN kIntSize 5694 #else 5695 #define PSEUDO_SMI_LO_ALIGN kIntSize 5696 #define PSEUDO_SMI_HI_ALIGN 0 5697 #endif 5698 5699 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \ 5700 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_LO_ALIGN); \ 5701 int holder::name() const { \ 5702 int value = READ_INT_FIELD(this, offset); \ 5703 DCHECK(kHeapObjectTag == 1); \ 5704 DCHECK((value & kHeapObjectTag) == 0); \ 5705 return value >> 1; \ 5706 } \ 5707 void holder::set_##name(int value) { \ 5708 DCHECK(kHeapObjectTag == 1); \ 5709 DCHECK((value & 0xC0000000) == 0xC0000000 || (value & 0xC0000000) == 0x0); \ 5710 WRITE_INT_FIELD(this, offset, (value << 1) & ~kHeapObjectTag); \ 5711 } 5712 5713 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \ 5714 STATIC_ASSERT(holder::offset % kPointerSize == PSEUDO_SMI_HI_ALIGN); \ 5715 INT_ACCESSORS(holder, name, offset) 5716 5717 5718 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset) 5719 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, internal_formal_parameter_count, 5720 kFormalParameterCountOffset) 5721 5722 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5723 expected_nof_properties, 5724 kExpectedNofPropertiesOffset) 5725 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset) 5726 5727 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset) 5728 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5729 start_position_and_type, 5730 kStartPositionAndTypeOffset) 5731 5732 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5733 function_token_position, 5734 kFunctionTokenPositionOffset) 5735 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5736 compiler_hints, 5737 kCompilerHintsOffset) 5738 5739 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5740 opt_count_and_bailout_reason, 5741 kOptCountAndBailoutReasonOffset) 5742 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset) 5743 5744 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 5745 ast_node_count, 5746 kAstNodeCountOffset) 5747 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 5748 profiler_ticks, 5749 kProfilerTicksOffset) 5750 5751 #endif 5752 5753 5754 BOOL_GETTER(SharedFunctionInfo, 5755 compiler_hints, 5756 optimization_disabled, 5757 kOptimizationDisabled) 5758 5759 5760 void SharedFunctionInfo::set_optimization_disabled(bool disable) { 5761 set_compiler_hints(BooleanBit::set(compiler_hints(), 5762 kOptimizationDisabled, 5763 disable)); 5764 } 5765 5766 5767 LanguageMode SharedFunctionInfo::language_mode() { 5768 STATIC_ASSERT(LANGUAGE_END == 3); 5769 return construct_language_mode( 5770 BooleanBit::get(compiler_hints(), kStrictModeFunction), 5771 BooleanBit::get(compiler_hints(), kStrongModeFunction)); 5772 } 5773 5774 5775 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) { 5776 STATIC_ASSERT(LANGUAGE_END == 3); 5777 // We only allow language mode transitions that set the same language mode 5778 // again or go up in the chain: 5779 DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode)); 5780 int hints = compiler_hints(); 5781 hints = BooleanBit::set(hints, kStrictModeFunction, is_strict(language_mode)); 5782 hints = BooleanBit::set(hints, kStrongModeFunction, is_strong(language_mode)); 5783 set_compiler_hints(hints); 5784 } 5785 5786 5787 FunctionKind SharedFunctionInfo::kind() { 5788 return FunctionKindBits::decode(compiler_hints()); 5789 } 5790 5791 5792 void SharedFunctionInfo::set_kind(FunctionKind kind) { 5793 DCHECK(IsValidFunctionKind(kind)); 5794 int hints = compiler_hints(); 5795 hints = FunctionKindBits::update(hints, kind); 5796 set_compiler_hints(hints); 5797 } 5798 5799 5800 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, needs_home_object, 5801 kNeedsHomeObject) 5802 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative) 5803 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, force_inline, kForceInline) 5804 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, 5805 name_should_print_as_anonymous, 5806 kNameShouldPrintAsAnonymous) 5807 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous) 5808 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction) 5809 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft, 5810 kDontCrankshaft) 5811 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush) 5812 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow) 5813 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator) 5814 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method, 5815 kIsConciseMethod) 5816 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_accessor_function, 5817 kIsAccessorFunction) 5818 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_default_constructor, 5819 kIsDefaultConstructor) 5820 5821 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) 5822 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) 5823 5824 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset) 5825 5826 bool Script::HasValidSource() { 5827 Object* src = this->source(); 5828 if (!src->IsString()) return true; 5829 String* src_str = String::cast(src); 5830 if (!StringShape(src_str).IsExternal()) return true; 5831 if (src_str->IsOneByteRepresentation()) { 5832 return ExternalOneByteString::cast(src)->resource() != NULL; 5833 } else if (src_str->IsTwoByteRepresentation()) { 5834 return ExternalTwoByteString::cast(src)->resource() != NULL; 5835 } 5836 return true; 5837 } 5838 5839 5840 void SharedFunctionInfo::DontAdaptArguments() { 5841 DCHECK(code()->kind() == Code::BUILTIN); 5842 set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel); 5843 } 5844 5845 5846 int SharedFunctionInfo::start_position() const { 5847 return start_position_and_type() >> kStartPositionShift; 5848 } 5849 5850 5851 void SharedFunctionInfo::set_start_position(int start_position) { 5852 set_start_position_and_type((start_position << kStartPositionShift) 5853 | (start_position_and_type() & ~kStartPositionMask)); 5854 } 5855 5856 5857 Code* SharedFunctionInfo::code() const { 5858 return Code::cast(READ_FIELD(this, kCodeOffset)); 5859 } 5860 5861 5862 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) { 5863 DCHECK(value->kind() != Code::OPTIMIZED_FUNCTION); 5864 WRITE_FIELD(this, kCodeOffset, value); 5865 CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode); 5866 } 5867 5868 5869 void SharedFunctionInfo::ReplaceCode(Code* value) { 5870 // If the GC metadata field is already used then the function was 5871 // enqueued as a code flushing candidate and we remove it now. 5872 if (code()->gc_metadata() != NULL) { 5873 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); 5874 flusher->EvictCandidate(this); 5875 } 5876 5877 DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL); 5878 #ifdef DEBUG 5879 Code::VerifyRecompiledCode(code(), value); 5880 #endif // DEBUG 5881 5882 set_code(value); 5883 5884 if (is_compiled()) set_never_compiled(false); 5885 } 5886 5887 5888 ScopeInfo* SharedFunctionInfo::scope_info() const { 5889 return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset)); 5890 } 5891 5892 5893 void SharedFunctionInfo::set_scope_info(ScopeInfo* value, 5894 WriteBarrierMode mode) { 5895 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value)); 5896 CONDITIONAL_WRITE_BARRIER(GetHeap(), 5897 this, 5898 kScopeInfoOffset, 5899 reinterpret_cast<Object*>(value), 5900 mode); 5901 } 5902 5903 5904 bool SharedFunctionInfo::is_compiled() { 5905 Builtins* builtins = GetIsolate()->builtins(); 5906 DCHECK(code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent)); 5907 DCHECK(code() != builtins->builtin(Builtins::kCompileOptimized)); 5908 return code() != builtins->builtin(Builtins::kCompileLazy); 5909 } 5910 5911 5912 bool SharedFunctionInfo::has_simple_parameters() { 5913 return scope_info()->HasSimpleParameters(); 5914 } 5915 5916 5917 bool SharedFunctionInfo::HasDebugInfo() { 5918 bool has_debug_info = debug_info()->IsStruct(); 5919 DCHECK(!has_debug_info || HasDebugCode()); 5920 return has_debug_info; 5921 } 5922 5923 5924 DebugInfo* SharedFunctionInfo::GetDebugInfo() { 5925 DCHECK(HasDebugInfo()); 5926 return DebugInfo::cast(debug_info()); 5927 } 5928 5929 5930 bool SharedFunctionInfo::HasDebugCode() { 5931 return code()->kind() == Code::FUNCTION && code()->has_debug_break_slots(); 5932 } 5933 5934 5935 bool SharedFunctionInfo::IsApiFunction() { 5936 return function_data()->IsFunctionTemplateInfo(); 5937 } 5938 5939 5940 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() { 5941 DCHECK(IsApiFunction()); 5942 return FunctionTemplateInfo::cast(function_data()); 5943 } 5944 5945 5946 bool SharedFunctionInfo::HasBuiltinFunctionId() { 5947 return function_data()->IsSmi(); 5948 } 5949 5950 5951 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() { 5952 DCHECK(HasBuiltinFunctionId()); 5953 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value()); 5954 } 5955 5956 5957 bool SharedFunctionInfo::HasBytecodeArray() { 5958 return function_data()->IsBytecodeArray(); 5959 } 5960 5961 5962 BytecodeArray* SharedFunctionInfo::bytecode_array() { 5963 DCHECK(HasBytecodeArray()); 5964 return BytecodeArray::cast(function_data()); 5965 } 5966 5967 5968 int SharedFunctionInfo::ic_age() { 5969 return ICAgeBits::decode(counters()); 5970 } 5971 5972 5973 void SharedFunctionInfo::set_ic_age(int ic_age) { 5974 set_counters(ICAgeBits::update(counters(), ic_age)); 5975 } 5976 5977 5978 int SharedFunctionInfo::deopt_count() { 5979 return DeoptCountBits::decode(counters()); 5980 } 5981 5982 5983 void SharedFunctionInfo::set_deopt_count(int deopt_count) { 5984 set_counters(DeoptCountBits::update(counters(), deopt_count)); 5985 } 5986 5987 5988 void SharedFunctionInfo::increment_deopt_count() { 5989 int value = counters(); 5990 int deopt_count = DeoptCountBits::decode(value); 5991 deopt_count = (deopt_count + 1) & DeoptCountBits::kMax; 5992 set_counters(DeoptCountBits::update(value, deopt_count)); 5993 } 5994 5995 5996 int SharedFunctionInfo::opt_reenable_tries() { 5997 return OptReenableTriesBits::decode(counters()); 5998 } 5999 6000 6001 void SharedFunctionInfo::set_opt_reenable_tries(int tries) { 6002 set_counters(OptReenableTriesBits::update(counters(), tries)); 6003 } 6004 6005 6006 int SharedFunctionInfo::opt_count() { 6007 return OptCountBits::decode(opt_count_and_bailout_reason()); 6008 } 6009 6010 6011 void SharedFunctionInfo::set_opt_count(int opt_count) { 6012 set_opt_count_and_bailout_reason( 6013 OptCountBits::update(opt_count_and_bailout_reason(), opt_count)); 6014 } 6015 6016 6017 BailoutReason SharedFunctionInfo::disable_optimization_reason() { 6018 return static_cast<BailoutReason>( 6019 DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason())); 6020 } 6021 6022 6023 bool SharedFunctionInfo::has_deoptimization_support() { 6024 Code* code = this->code(); 6025 return code->kind() == Code::FUNCTION && code->has_deoptimization_support(); 6026 } 6027 6028 6029 void SharedFunctionInfo::TryReenableOptimization() { 6030 int tries = opt_reenable_tries(); 6031 set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax); 6032 // We reenable optimization whenever the number of tries is a large 6033 // enough power of 2. 6034 if (tries >= 16 && (((tries - 1) & tries) == 0)) { 6035 set_optimization_disabled(false); 6036 set_opt_count(0); 6037 set_deopt_count(0); 6038 } 6039 } 6040 6041 6042 void SharedFunctionInfo::set_disable_optimization_reason(BailoutReason reason) { 6043 set_opt_count_and_bailout_reason(DisabledOptimizationReasonBits::update( 6044 opt_count_and_bailout_reason(), reason)); 6045 } 6046 6047 6048 bool SharedFunctionInfo::IsBuiltin() { 6049 Object* script_obj = script(); 6050 if (script_obj->IsUndefined()) return true; 6051 Script* script = Script::cast(script_obj); 6052 Script::Type type = static_cast<Script::Type>(script->type()); 6053 return type != Script::TYPE_NORMAL; 6054 } 6055 6056 6057 bool SharedFunctionInfo::IsSubjectToDebugging() { return !IsBuiltin(); } 6058 6059 6060 bool SharedFunctionInfo::OptimizedCodeMapIsCleared() const { 6061 return optimized_code_map() == GetHeap()->cleared_optimized_code_map(); 6062 } 6063 6064 6065 // static 6066 void SharedFunctionInfo::AddToOptimizedCodeMap( 6067 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, 6068 Handle<Code> code, Handle<LiteralsArray> literals, BailoutId osr_ast_id) { 6069 AddToOptimizedCodeMapInternal(shared, native_context, code, literals, 6070 osr_ast_id); 6071 } 6072 6073 6074 // static 6075 void SharedFunctionInfo::AddLiteralsToOptimizedCodeMap( 6076 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, 6077 Handle<LiteralsArray> literals) { 6078 Isolate* isolate = shared->GetIsolate(); 6079 Handle<Oddball> undefined = isolate->factory()->undefined_value(); 6080 AddToOptimizedCodeMapInternal(shared, native_context, undefined, literals, 6081 BailoutId::None()); 6082 } 6083 6084 6085 bool JSFunction::IsOptimized() { 6086 return code()->kind() == Code::OPTIMIZED_FUNCTION; 6087 } 6088 6089 6090 bool JSFunction::IsMarkedForOptimization() { 6091 return code() == GetIsolate()->builtins()->builtin( 6092 Builtins::kCompileOptimized); 6093 } 6094 6095 6096 bool JSFunction::IsMarkedForConcurrentOptimization() { 6097 return code() == GetIsolate()->builtins()->builtin( 6098 Builtins::kCompileOptimizedConcurrent); 6099 } 6100 6101 6102 bool JSFunction::IsInOptimizationQueue() { 6103 return code() == GetIsolate()->builtins()->builtin( 6104 Builtins::kInOptimizationQueue); 6105 } 6106 6107 6108 void JSFunction::CompleteInobjectSlackTrackingIfActive() { 6109 if (has_initial_map() && initial_map()->IsInobjectSlackTrackingInProgress()) { 6110 initial_map()->CompleteInobjectSlackTracking(); 6111 } 6112 } 6113 6114 6115 bool Map::IsInobjectSlackTrackingInProgress() { 6116 return construction_counter() != Map::kNoSlackTracking; 6117 } 6118 6119 6120 void Map::InobjectSlackTrackingStep() { 6121 if (!IsInobjectSlackTrackingInProgress()) return; 6122 int counter = construction_counter(); 6123 set_construction_counter(counter - 1); 6124 if (counter == kSlackTrackingCounterEnd) { 6125 CompleteInobjectSlackTracking(); 6126 } 6127 } 6128 6129 6130 Code* JSFunction::code() { 6131 return Code::cast( 6132 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset))); 6133 } 6134 6135 6136 void JSFunction::set_code(Code* value) { 6137 DCHECK(!GetHeap()->InNewSpace(value)); 6138 Address entry = value->entry(); 6139 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); 6140 GetHeap()->incremental_marking()->RecordWriteOfCodeEntry( 6141 this, 6142 HeapObject::RawField(this, kCodeEntryOffset), 6143 value); 6144 } 6145 6146 6147 void JSFunction::set_code_no_write_barrier(Code* value) { 6148 DCHECK(!GetHeap()->InNewSpace(value)); 6149 Address entry = value->entry(); 6150 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); 6151 } 6152 6153 6154 void JSFunction::ReplaceCode(Code* code) { 6155 bool was_optimized = IsOptimized(); 6156 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION; 6157 6158 if (was_optimized && is_optimized) { 6159 shared()->EvictFromOptimizedCodeMap(this->code(), 6160 "Replacing with another optimized code"); 6161 } 6162 6163 set_code(code); 6164 6165 // Add/remove the function from the list of optimized functions for this 6166 // context based on the state change. 6167 if (!was_optimized && is_optimized) { 6168 context()->native_context()->AddOptimizedFunction(this); 6169 } 6170 if (was_optimized && !is_optimized) { 6171 // TODO(titzer): linear in the number of optimized functions; fix! 6172 context()->native_context()->RemoveOptimizedFunction(this); 6173 } 6174 } 6175 6176 6177 Context* JSFunction::context() { 6178 return Context::cast(READ_FIELD(this, kContextOffset)); 6179 } 6180 6181 6182 JSObject* JSFunction::global_proxy() { 6183 return context()->global_proxy(); 6184 } 6185 6186 6187 Context* JSFunction::native_context() { return context()->native_context(); } 6188 6189 6190 void JSFunction::set_context(Object* value) { 6191 DCHECK(value->IsUndefined() || value->IsContext()); 6192 WRITE_FIELD(this, kContextOffset, value); 6193 WRITE_BARRIER(GetHeap(), this, kContextOffset, value); 6194 } 6195 6196 ACCESSORS(JSFunction, prototype_or_initial_map, Object, 6197 kPrototypeOrInitialMapOffset) 6198 6199 6200 Map* JSFunction::initial_map() { 6201 return Map::cast(prototype_or_initial_map()); 6202 } 6203 6204 6205 bool JSFunction::has_initial_map() { 6206 return prototype_or_initial_map()->IsMap(); 6207 } 6208 6209 6210 bool JSFunction::has_instance_prototype() { 6211 return has_initial_map() || !prototype_or_initial_map()->IsTheHole(); 6212 } 6213 6214 6215 bool JSFunction::has_prototype() { 6216 return map()->has_non_instance_prototype() || has_instance_prototype(); 6217 } 6218 6219 6220 Object* JSFunction::instance_prototype() { 6221 DCHECK(has_instance_prototype()); 6222 if (has_initial_map()) return initial_map()->prototype(); 6223 // When there is no initial map and the prototype is a JSObject, the 6224 // initial map field is used for the prototype field. 6225 return prototype_or_initial_map(); 6226 } 6227 6228 6229 Object* JSFunction::prototype() { 6230 DCHECK(has_prototype()); 6231 // If the function's prototype property has been set to a non-JSObject 6232 // value, that value is stored in the constructor field of the map. 6233 if (map()->has_non_instance_prototype()) { 6234 Object* prototype = map()->GetConstructor(); 6235 // The map must have a prototype in that field, not a back pointer. 6236 DCHECK(!prototype->IsMap()); 6237 return prototype; 6238 } 6239 return instance_prototype(); 6240 } 6241 6242 6243 bool JSFunction::is_compiled() { 6244 Builtins* builtins = GetIsolate()->builtins(); 6245 return code() != builtins->builtin(Builtins::kCompileLazy) && 6246 code() != builtins->builtin(Builtins::kCompileOptimized) && 6247 code() != builtins->builtin(Builtins::kCompileOptimizedConcurrent); 6248 } 6249 6250 6251 int JSFunction::NumberOfLiterals() { 6252 return literals()->length(); 6253 } 6254 6255 6256 ACCESSORS(JSProxy, target, JSReceiver, kTargetOffset) 6257 ACCESSORS(JSProxy, handler, Object, kHandlerOffset) 6258 ACCESSORS(JSProxy, hash, Object, kHashOffset) 6259 6260 bool JSProxy::IsRevoked() const { return !handler()->IsJSReceiver(); } 6261 6262 ACCESSORS(JSCollection, table, Object, kTableOffset) 6263 6264 6265 #define ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(name, type, offset) \ 6266 template<class Derived, class TableType> \ 6267 type* OrderedHashTableIterator<Derived, TableType>::name() const { \ 6268 return type::cast(READ_FIELD(this, offset)); \ 6269 } \ 6270 template<class Derived, class TableType> \ 6271 void OrderedHashTableIterator<Derived, TableType>::set_##name( \ 6272 type* value, WriteBarrierMode mode) { \ 6273 WRITE_FIELD(this, offset, value); \ 6274 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode); \ 6275 } 6276 6277 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset) 6278 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset) 6279 ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset) 6280 6281 #undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS 6282 6283 6284 ACCESSORS(JSWeakCollection, table, Object, kTableOffset) 6285 ACCESSORS(JSWeakCollection, next, Object, kNextOffset) 6286 6287 6288 Address Foreign::foreign_address() { 6289 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset)); 6290 } 6291 6292 6293 void Foreign::set_foreign_address(Address value) { 6294 WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value)); 6295 } 6296 6297 6298 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset) 6299 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset) 6300 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset) 6301 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset) 6302 ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset) 6303 6304 bool JSGeneratorObject::is_suspended() { 6305 DCHECK_LT(kGeneratorExecuting, kGeneratorClosed); 6306 DCHECK_EQ(kGeneratorClosed, 0); 6307 return continuation() > 0; 6308 } 6309 6310 bool JSGeneratorObject::is_closed() { 6311 return continuation() == kGeneratorClosed; 6312 } 6313 6314 bool JSGeneratorObject::is_executing() { 6315 return continuation() == kGeneratorExecuting; 6316 } 6317 6318 ACCESSORS(JSModule, context, Object, kContextOffset) 6319 ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset) 6320 6321 6322 ACCESSORS(JSValue, value, Object, kValueOffset) 6323 6324 6325 HeapNumber* HeapNumber::cast(Object* object) { 6326 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); 6327 return reinterpret_cast<HeapNumber*>(object); 6328 } 6329 6330 6331 const HeapNumber* HeapNumber::cast(const Object* object) { 6332 SLOW_DCHECK(object->IsHeapNumber() || object->IsMutableHeapNumber()); 6333 return reinterpret_cast<const HeapNumber*>(object); 6334 } 6335 6336 6337 ACCESSORS(JSDate, value, Object, kValueOffset) 6338 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset) 6339 ACCESSORS(JSDate, year, Object, kYearOffset) 6340 ACCESSORS(JSDate, month, Object, kMonthOffset) 6341 ACCESSORS(JSDate, day, Object, kDayOffset) 6342 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset) 6343 ACCESSORS(JSDate, hour, Object, kHourOffset) 6344 ACCESSORS(JSDate, min, Object, kMinOffset) 6345 ACCESSORS(JSDate, sec, Object, kSecOffset) 6346 6347 6348 SMI_ACCESSORS(JSMessageObject, type, kTypeOffset) 6349 ACCESSORS(JSMessageObject, argument, Object, kArgumentsOffset) 6350 ACCESSORS(JSMessageObject, script, Object, kScriptOffset) 6351 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset) 6352 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset) 6353 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset) 6354 6355 6356 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset) 6357 INT_ACCESSORS(Code, prologue_offset, kPrologueOffset) 6358 INT_ACCESSORS(Code, constant_pool_offset, kConstantPoolOffset) 6359 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset) 6360 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset) 6361 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset) 6362 ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset) 6363 ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset) 6364 6365 6366 void Code::WipeOutHeader() { 6367 WRITE_FIELD(this, kRelocationInfoOffset, NULL); 6368 WRITE_FIELD(this, kHandlerTableOffset, NULL); 6369 WRITE_FIELD(this, kDeoptimizationDataOffset, NULL); 6370 // Do not wipe out major/minor keys on a code stub or IC 6371 if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) { 6372 WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL); 6373 } 6374 WRITE_FIELD(this, kNextCodeLinkOffset, NULL); 6375 WRITE_FIELD(this, kGCMetadataOffset, NULL); 6376 } 6377 6378 6379 Object* Code::type_feedback_info() { 6380 DCHECK(kind() == FUNCTION); 6381 return raw_type_feedback_info(); 6382 } 6383 6384 6385 void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) { 6386 DCHECK(kind() == FUNCTION); 6387 set_raw_type_feedback_info(value, mode); 6388 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset, 6389 value, mode); 6390 } 6391 6392 6393 uint32_t Code::stub_key() { 6394 DCHECK(IsCodeStubOrIC()); 6395 Smi* smi_key = Smi::cast(raw_type_feedback_info()); 6396 return static_cast<uint32_t>(smi_key->value()); 6397 } 6398 6399 6400 void Code::set_stub_key(uint32_t key) { 6401 DCHECK(IsCodeStubOrIC()); 6402 set_raw_type_feedback_info(Smi::FromInt(key)); 6403 } 6404 6405 6406 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset) 6407 INT_ACCESSORS(Code, ic_age, kICAgeOffset) 6408 6409 6410 byte* Code::instruction_start() { 6411 return FIELD_ADDR(this, kHeaderSize); 6412 } 6413 6414 6415 byte* Code::instruction_end() { 6416 return instruction_start() + instruction_size(); 6417 } 6418 6419 6420 int Code::body_size() { 6421 return RoundUp(instruction_size(), kObjectAlignment); 6422 } 6423 6424 6425 ByteArray* Code::unchecked_relocation_info() { 6426 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset)); 6427 } 6428 6429 6430 byte* Code::relocation_start() { 6431 return unchecked_relocation_info()->GetDataStartAddress(); 6432 } 6433 6434 6435 int Code::relocation_size() { 6436 return unchecked_relocation_info()->length(); 6437 } 6438 6439 6440 byte* Code::entry() { 6441 return instruction_start(); 6442 } 6443 6444 6445 bool Code::contains(byte* inner_pointer) { 6446 return (address() <= inner_pointer) && (inner_pointer <= address() + Size()); 6447 } 6448 6449 6450 int Code::ExecutableSize() { 6451 // Check that the assumptions about the layout of the code object holds. 6452 DCHECK_EQ(static_cast<int>(instruction_start() - address()), 6453 Code::kHeaderSize); 6454 return instruction_size() + Code::kHeaderSize; 6455 } 6456 6457 6458 int Code::CodeSize() { return SizeFor(body_size()); } 6459 6460 6461 ACCESSORS(JSArray, length, Object, kLengthOffset) 6462 6463 6464 void* JSArrayBuffer::backing_store() const { 6465 intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset); 6466 return reinterpret_cast<void*>(ptr); 6467 } 6468 6469 6470 void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) { 6471 intptr_t ptr = reinterpret_cast<intptr_t>(value); 6472 WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr); 6473 } 6474 6475 6476 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset) 6477 6478 6479 void JSArrayBuffer::set_bit_field(uint32_t bits) { 6480 if (kInt32Size != kPointerSize) { 6481 #if V8_TARGET_LITTLE_ENDIAN 6482 WRITE_UINT32_FIELD(this, kBitFieldSlot + kInt32Size, 0); 6483 #else 6484 WRITE_UINT32_FIELD(this, kBitFieldSlot, 0); 6485 #endif 6486 } 6487 WRITE_UINT32_FIELD(this, kBitFieldOffset, bits); 6488 } 6489 6490 6491 uint32_t JSArrayBuffer::bit_field() const { 6492 return READ_UINT32_FIELD(this, kBitFieldOffset); 6493 } 6494 6495 6496 bool JSArrayBuffer::is_external() { return IsExternal::decode(bit_field()); } 6497 6498 6499 void JSArrayBuffer::set_is_external(bool value) { 6500 set_bit_field(IsExternal::update(bit_field(), value)); 6501 } 6502 6503 6504 bool JSArrayBuffer::is_neuterable() { 6505 return IsNeuterable::decode(bit_field()); 6506 } 6507 6508 6509 void JSArrayBuffer::set_is_neuterable(bool value) { 6510 set_bit_field(IsNeuterable::update(bit_field(), value)); 6511 } 6512 6513 6514 bool JSArrayBuffer::was_neutered() { return WasNeutered::decode(bit_field()); } 6515 6516 6517 void JSArrayBuffer::set_was_neutered(bool value) { 6518 set_bit_field(WasNeutered::update(bit_field(), value)); 6519 } 6520 6521 6522 bool JSArrayBuffer::is_shared() { return IsShared::decode(bit_field()); } 6523 6524 6525 void JSArrayBuffer::set_is_shared(bool value) { 6526 set_bit_field(IsShared::update(bit_field(), value)); 6527 } 6528 6529 6530 Object* JSArrayBufferView::byte_offset() const { 6531 if (WasNeutered()) return Smi::FromInt(0); 6532 return Object::cast(READ_FIELD(this, kByteOffsetOffset)); 6533 } 6534 6535 6536 void JSArrayBufferView::set_byte_offset(Object* value, WriteBarrierMode mode) { 6537 WRITE_FIELD(this, kByteOffsetOffset, value); 6538 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteOffsetOffset, value, mode); 6539 } 6540 6541 6542 Object* JSArrayBufferView::byte_length() const { 6543 if (WasNeutered()) return Smi::FromInt(0); 6544 return Object::cast(READ_FIELD(this, kByteLengthOffset)); 6545 } 6546 6547 6548 void JSArrayBufferView::set_byte_length(Object* value, WriteBarrierMode mode) { 6549 WRITE_FIELD(this, kByteLengthOffset, value); 6550 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteLengthOffset, value, mode); 6551 } 6552 6553 6554 ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset) 6555 #ifdef VERIFY_HEAP 6556 ACCESSORS(JSArrayBufferView, raw_byte_offset, Object, kByteOffsetOffset) 6557 ACCESSORS(JSArrayBufferView, raw_byte_length, Object, kByteLengthOffset) 6558 #endif 6559 6560 6561 bool JSArrayBufferView::WasNeutered() const { 6562 return JSArrayBuffer::cast(buffer())->was_neutered(); 6563 } 6564 6565 6566 Object* JSTypedArray::length() const { 6567 if (WasNeutered()) return Smi::FromInt(0); 6568 return Object::cast(READ_FIELD(this, kLengthOffset)); 6569 } 6570 6571 6572 uint32_t JSTypedArray::length_value() const { 6573 if (WasNeutered()) return 0; 6574 uint32_t index = 0; 6575 CHECK(Object::cast(READ_FIELD(this, kLengthOffset))->ToArrayLength(&index)); 6576 return index; 6577 } 6578 6579 6580 void JSTypedArray::set_length(Object* value, WriteBarrierMode mode) { 6581 WRITE_FIELD(this, kLengthOffset, value); 6582 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kLengthOffset, value, mode); 6583 } 6584 6585 6586 #ifdef VERIFY_HEAP 6587 ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset) 6588 #endif 6589 6590 6591 ACCESSORS(JSRegExp, data, Object, kDataOffset) 6592 ACCESSORS(JSRegExp, flags, Object, kFlagsOffset) 6593 ACCESSORS(JSRegExp, source, Object, kSourceOffset) 6594 6595 6596 JSRegExp::Type JSRegExp::TypeTag() { 6597 Object* data = this->data(); 6598 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED; 6599 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex)); 6600 return static_cast<JSRegExp::Type>(smi->value()); 6601 } 6602 6603 6604 int JSRegExp::CaptureCount() { 6605 switch (TypeTag()) { 6606 case ATOM: 6607 return 0; 6608 case IRREGEXP: 6609 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value(); 6610 default: 6611 UNREACHABLE(); 6612 return -1; 6613 } 6614 } 6615 6616 6617 JSRegExp::Flags JSRegExp::GetFlags() { 6618 DCHECK(this->data()->IsFixedArray()); 6619 Object* data = this->data(); 6620 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex)); 6621 return Flags(smi->value()); 6622 } 6623 6624 6625 String* JSRegExp::Pattern() { 6626 DCHECK(this->data()->IsFixedArray()); 6627 Object* data = this->data(); 6628 String* pattern = String::cast(FixedArray::cast(data)->get(kSourceIndex)); 6629 return pattern; 6630 } 6631 6632 6633 Object* JSRegExp::DataAt(int index) { 6634 DCHECK(TypeTag() != NOT_COMPILED); 6635 return FixedArray::cast(data())->get(index); 6636 } 6637 6638 6639 void JSRegExp::SetDataAt(int index, Object* value) { 6640 DCHECK(TypeTag() != NOT_COMPILED); 6641 DCHECK(index >= kDataIndex); // Only implementation data can be set this way. 6642 FixedArray::cast(data())->set(index, value); 6643 } 6644 6645 6646 ElementsKind JSObject::GetElementsKind() { 6647 ElementsKind kind = map()->elements_kind(); 6648 #if VERIFY_HEAP && DEBUG 6649 FixedArrayBase* fixed_array = 6650 reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset)); 6651 6652 // If a GC was caused while constructing this object, the elements 6653 // pointer may point to a one pointer filler map. 6654 if (ElementsAreSafeToExamine()) { 6655 Map* map = fixed_array->map(); 6656 DCHECK((IsFastSmiOrObjectElementsKind(kind) && 6657 (map == GetHeap()->fixed_array_map() || 6658 map == GetHeap()->fixed_cow_array_map())) || 6659 (IsFastDoubleElementsKind(kind) && 6660 (fixed_array->IsFixedDoubleArray() || 6661 fixed_array == GetHeap()->empty_fixed_array())) || 6662 (kind == DICTIONARY_ELEMENTS && 6663 fixed_array->IsFixedArray() && 6664 fixed_array->IsDictionary()) || 6665 (kind > DICTIONARY_ELEMENTS)); 6666 DCHECK(!IsSloppyArgumentsElements(kind) || 6667 (elements()->IsFixedArray() && elements()->length() >= 2)); 6668 } 6669 #endif 6670 return kind; 6671 } 6672 6673 6674 bool JSObject::HasFastObjectElements() { 6675 return IsFastObjectElementsKind(GetElementsKind()); 6676 } 6677 6678 6679 bool JSObject::HasFastSmiElements() { 6680 return IsFastSmiElementsKind(GetElementsKind()); 6681 } 6682 6683 6684 bool JSObject::HasFastSmiOrObjectElements() { 6685 return IsFastSmiOrObjectElementsKind(GetElementsKind()); 6686 } 6687 6688 6689 bool JSObject::HasFastDoubleElements() { 6690 return IsFastDoubleElementsKind(GetElementsKind()); 6691 } 6692 6693 6694 bool JSObject::HasFastHoleyElements() { 6695 return IsFastHoleyElementsKind(GetElementsKind()); 6696 } 6697 6698 6699 bool JSObject::HasFastElements() { 6700 return IsFastElementsKind(GetElementsKind()); 6701 } 6702 6703 6704 bool JSObject::HasDictionaryElements() { 6705 return GetElementsKind() == DICTIONARY_ELEMENTS; 6706 } 6707 6708 6709 bool JSObject::HasFastArgumentsElements() { 6710 return GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS; 6711 } 6712 6713 6714 bool JSObject::HasSlowArgumentsElements() { 6715 return GetElementsKind() == SLOW_SLOPPY_ARGUMENTS_ELEMENTS; 6716 } 6717 6718 6719 bool JSObject::HasSloppyArgumentsElements() { 6720 return IsSloppyArgumentsElements(GetElementsKind()); 6721 } 6722 6723 6724 bool JSObject::HasFixedTypedArrayElements() { 6725 HeapObject* array = elements(); 6726 DCHECK(array != NULL); 6727 return array->IsFixedTypedArrayBase(); 6728 } 6729 6730 6731 #define FIXED_TYPED_ELEMENTS_CHECK(Type, type, TYPE, ctype, size) \ 6732 bool JSObject::HasFixed##Type##Elements() { \ 6733 HeapObject* array = elements(); \ 6734 DCHECK(array != NULL); \ 6735 if (!array->IsHeapObject()) \ 6736 return false; \ 6737 return array->map()->instance_type() == FIXED_##TYPE##_ARRAY_TYPE; \ 6738 } 6739 6740 TYPED_ARRAYS(FIXED_TYPED_ELEMENTS_CHECK) 6741 6742 #undef FIXED_TYPED_ELEMENTS_CHECK 6743 6744 6745 bool JSObject::HasNamedInterceptor() { 6746 return map()->has_named_interceptor(); 6747 } 6748 6749 6750 bool JSObject::HasIndexedInterceptor() { 6751 return map()->has_indexed_interceptor(); 6752 } 6753 6754 6755 GlobalDictionary* JSObject::global_dictionary() { 6756 DCHECK(!HasFastProperties()); 6757 DCHECK(IsJSGlobalObject()); 6758 return GlobalDictionary::cast(properties()); 6759 } 6760 6761 6762 SeededNumberDictionary* JSObject::element_dictionary() { 6763 DCHECK(HasDictionaryElements()); 6764 return SeededNumberDictionary::cast(elements()); 6765 } 6766 6767 6768 bool Name::IsHashFieldComputed(uint32_t field) { 6769 return (field & kHashNotComputedMask) == 0; 6770 } 6771 6772 6773 bool Name::HasHashCode() { 6774 return IsHashFieldComputed(hash_field()); 6775 } 6776 6777 6778 uint32_t Name::Hash() { 6779 // Fast case: has hash code already been computed? 6780 uint32_t field = hash_field(); 6781 if (IsHashFieldComputed(field)) return field >> kHashShift; 6782 // Slow case: compute hash code and set it. Has to be a string. 6783 return String::cast(this)->ComputeAndSetHash(); 6784 } 6785 6786 6787 bool Name::IsPrivate() { 6788 return this->IsSymbol() && Symbol::cast(this)->is_private(); 6789 } 6790 6791 6792 StringHasher::StringHasher(int length, uint32_t seed) 6793 : length_(length), 6794 raw_running_hash_(seed), 6795 array_index_(0), 6796 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), 6797 is_first_char_(true) { 6798 DCHECK(FLAG_randomize_hashes || raw_running_hash_ == 0); 6799 } 6800 6801 6802 bool StringHasher::has_trivial_hash() { 6803 return length_ > String::kMaxHashCalcLength; 6804 } 6805 6806 6807 uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) { 6808 running_hash += c; 6809 running_hash += (running_hash << 10); 6810 running_hash ^= (running_hash >> 6); 6811 return running_hash; 6812 } 6813 6814 6815 uint32_t StringHasher::GetHashCore(uint32_t running_hash) { 6816 running_hash += (running_hash << 3); 6817 running_hash ^= (running_hash >> 11); 6818 running_hash += (running_hash << 15); 6819 if ((running_hash & String::kHashBitMask) == 0) { 6820 return kZeroHash; 6821 } 6822 return running_hash; 6823 } 6824 6825 6826 uint32_t StringHasher::ComputeRunningHash(uint32_t running_hash, 6827 const uc16* chars, int length) { 6828 DCHECK_NOT_NULL(chars); 6829 DCHECK(length >= 0); 6830 for (int i = 0; i < length; ++i) { 6831 running_hash = AddCharacterCore(running_hash, *chars++); 6832 } 6833 return running_hash; 6834 } 6835 6836 6837 uint32_t StringHasher::ComputeRunningHashOneByte(uint32_t running_hash, 6838 const char* chars, 6839 int length) { 6840 DCHECK_NOT_NULL(chars); 6841 DCHECK(length >= 0); 6842 for (int i = 0; i < length; ++i) { 6843 uint16_t c = static_cast<uint16_t>(*chars++); 6844 running_hash = AddCharacterCore(running_hash, c); 6845 } 6846 return running_hash; 6847 } 6848 6849 6850 void StringHasher::AddCharacter(uint16_t c) { 6851 // Use the Jenkins one-at-a-time hash function to update the hash 6852 // for the given character. 6853 raw_running_hash_ = AddCharacterCore(raw_running_hash_, c); 6854 } 6855 6856 6857 bool StringHasher::UpdateIndex(uint16_t c) { 6858 DCHECK(is_array_index_); 6859 if (c < '0' || c > '9') { 6860 is_array_index_ = false; 6861 return false; 6862 } 6863 int d = c - '0'; 6864 if (is_first_char_) { 6865 is_first_char_ = false; 6866 if (c == '0' && length_ > 1) { 6867 is_array_index_ = false; 6868 return false; 6869 } 6870 } 6871 if (array_index_ > 429496729U - ((d + 3) >> 3)) { 6872 is_array_index_ = false; 6873 return false; 6874 } 6875 array_index_ = array_index_ * 10 + d; 6876 return true; 6877 } 6878 6879 6880 template<typename Char> 6881 inline void StringHasher::AddCharacters(const Char* chars, int length) { 6882 DCHECK(sizeof(Char) == 1 || sizeof(Char) == 2); 6883 int i = 0; 6884 if (is_array_index_) { 6885 for (; i < length; i++) { 6886 AddCharacter(chars[i]); 6887 if (!UpdateIndex(chars[i])) { 6888 i++; 6889 break; 6890 } 6891 } 6892 } 6893 for (; i < length; i++) { 6894 DCHECK(!is_array_index_); 6895 AddCharacter(chars[i]); 6896 } 6897 } 6898 6899 6900 template <typename schar> 6901 uint32_t StringHasher::HashSequentialString(const schar* chars, 6902 int length, 6903 uint32_t seed) { 6904 StringHasher hasher(length, seed); 6905 if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length); 6906 return hasher.GetHashField(); 6907 } 6908 6909 6910 IteratingStringHasher::IteratingStringHasher(int len, uint32_t seed) 6911 : StringHasher(len, seed) {} 6912 6913 6914 uint32_t IteratingStringHasher::Hash(String* string, uint32_t seed) { 6915 IteratingStringHasher hasher(string->length(), seed); 6916 // Nothing to do. 6917 if (hasher.has_trivial_hash()) return hasher.GetHashField(); 6918 ConsString* cons_string = String::VisitFlat(&hasher, string); 6919 if (cons_string == nullptr) return hasher.GetHashField(); 6920 hasher.VisitConsString(cons_string); 6921 return hasher.GetHashField(); 6922 } 6923 6924 6925 void IteratingStringHasher::VisitOneByteString(const uint8_t* chars, 6926 int length) { 6927 AddCharacters(chars, length); 6928 } 6929 6930 6931 void IteratingStringHasher::VisitTwoByteString(const uint16_t* chars, 6932 int length) { 6933 AddCharacters(chars, length); 6934 } 6935 6936 6937 bool Name::AsArrayIndex(uint32_t* index) { 6938 return IsString() && String::cast(this)->AsArrayIndex(index); 6939 } 6940 6941 6942 bool String::AsArrayIndex(uint32_t* index) { 6943 uint32_t field = hash_field(); 6944 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) { 6945 return false; 6946 } 6947 return SlowAsArrayIndex(index); 6948 } 6949 6950 6951 void String::SetForwardedInternalizedString(String* canonical) { 6952 DCHECK(IsInternalizedString()); 6953 DCHECK(HasHashCode()); 6954 if (canonical == this) return; // No need to forward. 6955 DCHECK(SlowEquals(canonical)); 6956 DCHECK(canonical->IsInternalizedString()); 6957 DCHECK(canonical->HasHashCode()); 6958 WRITE_FIELD(this, kHashFieldSlot, canonical); 6959 // Setting the hash field to a tagged value sets the LSB, causing the hash 6960 // code to be interpreted as uninitialized. We use this fact to recognize 6961 // that we have a forwarded string. 6962 DCHECK(!HasHashCode()); 6963 } 6964 6965 6966 String* String::GetForwardedInternalizedString() { 6967 DCHECK(IsInternalizedString()); 6968 if (HasHashCode()) return this; 6969 String* canonical = String::cast(READ_FIELD(this, kHashFieldSlot)); 6970 DCHECK(canonical->IsInternalizedString()); 6971 DCHECK(SlowEquals(canonical)); 6972 DCHECK(canonical->HasHashCode()); 6973 return canonical; 6974 } 6975 6976 6977 // static 6978 Maybe<bool> Object::GreaterThan(Handle<Object> x, Handle<Object> y, 6979 Strength strength) { 6980 Maybe<ComparisonResult> result = Compare(x, y, strength); 6981 if (result.IsJust()) { 6982 switch (result.FromJust()) { 6983 case ComparisonResult::kGreaterThan: 6984 return Just(true); 6985 case ComparisonResult::kLessThan: 6986 case ComparisonResult::kEqual: 6987 case ComparisonResult::kUndefined: 6988 return Just(false); 6989 } 6990 } 6991 return Nothing<bool>(); 6992 } 6993 6994 6995 // static 6996 Maybe<bool> Object::GreaterThanOrEqual(Handle<Object> x, Handle<Object> y, 6997 Strength strength) { 6998 Maybe<ComparisonResult> result = Compare(x, y, strength); 6999 if (result.IsJust()) { 7000 switch (result.FromJust()) { 7001 case ComparisonResult::kEqual: 7002 case ComparisonResult::kGreaterThan: 7003 return Just(true); 7004 case ComparisonResult::kLessThan: 7005 case ComparisonResult::kUndefined: 7006 return Just(false); 7007 } 7008 } 7009 return Nothing<bool>(); 7010 } 7011 7012 7013 // static 7014 Maybe<bool> Object::LessThan(Handle<Object> x, Handle<Object> y, 7015 Strength strength) { 7016 Maybe<ComparisonResult> result = Compare(x, y, strength); 7017 if (result.IsJust()) { 7018 switch (result.FromJust()) { 7019 case ComparisonResult::kLessThan: 7020 return Just(true); 7021 case ComparisonResult::kEqual: 7022 case ComparisonResult::kGreaterThan: 7023 case ComparisonResult::kUndefined: 7024 return Just(false); 7025 } 7026 } 7027 return Nothing<bool>(); 7028 } 7029 7030 7031 // static 7032 Maybe<bool> Object::LessThanOrEqual(Handle<Object> x, Handle<Object> y, 7033 Strength strength) { 7034 Maybe<ComparisonResult> result = Compare(x, y, strength); 7035 if (result.IsJust()) { 7036 switch (result.FromJust()) { 7037 case ComparisonResult::kEqual: 7038 case ComparisonResult::kLessThan: 7039 return Just(true); 7040 case ComparisonResult::kGreaterThan: 7041 case ComparisonResult::kUndefined: 7042 return Just(false); 7043 } 7044 } 7045 return Nothing<bool>(); 7046 } 7047 7048 7049 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object, 7050 Handle<Name> name, 7051 LanguageMode language_mode) { 7052 LookupIterator it = 7053 LookupIterator::PropertyOrElement(name->GetIsolate(), object, name); 7054 return GetProperty(&it, language_mode); 7055 } 7056 7057 7058 MaybeHandle<Object> Object::GetPropertyOrElement(Handle<JSReceiver> holder, 7059 Handle<Name> name, 7060 Handle<Object> receiver, 7061 LanguageMode language_mode) { 7062 LookupIterator it = LookupIterator::PropertyOrElement( 7063 name->GetIsolate(), receiver, name, holder); 7064 return GetProperty(&it, language_mode); 7065 } 7066 7067 7068 void JSReceiver::initialize_properties() { 7069 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); 7070 DCHECK(!GetHeap()->InNewSpace(GetHeap()->empty_properties_dictionary())); 7071 if (map()->is_dictionary_map()) { 7072 WRITE_FIELD(this, kPropertiesOffset, 7073 GetHeap()->empty_properties_dictionary()); 7074 } else { 7075 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); 7076 } 7077 } 7078 7079 7080 bool JSReceiver::HasFastProperties() { 7081 DCHECK(properties()->IsDictionary() == map()->is_dictionary_map()); 7082 return !properties()->IsDictionary(); 7083 } 7084 7085 7086 NameDictionary* JSReceiver::property_dictionary() { 7087 DCHECK(!HasFastProperties()); 7088 DCHECK(!IsJSGlobalObject()); 7089 return NameDictionary::cast(properties()); 7090 } 7091 7092 7093 Maybe<bool> JSReceiver::HasProperty(Handle<JSReceiver> object, 7094 Handle<Name> name) { 7095 LookupIterator it = 7096 LookupIterator::PropertyOrElement(object->GetIsolate(), object, name); 7097 return HasProperty(&it); 7098 } 7099 7100 7101 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object, 7102 Handle<Name> name) { 7103 if (object->IsJSObject()) { // Shortcut 7104 LookupIterator it = LookupIterator::PropertyOrElement( 7105 object->GetIsolate(), object, name, LookupIterator::HIDDEN); 7106 return HasProperty(&it); 7107 } 7108 7109 Maybe<PropertyAttributes> attributes = 7110 JSReceiver::GetOwnPropertyAttributes(object, name); 7111 MAYBE_RETURN(attributes, Nothing<bool>()); 7112 return Just(attributes.FromJust() != ABSENT); 7113 } 7114 7115 7116 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes( 7117 Handle<JSReceiver> object, Handle<Name> name) { 7118 LookupIterator it = 7119 LookupIterator::PropertyOrElement(name->GetIsolate(), object, name); 7120 return GetPropertyAttributes(&it); 7121 } 7122 7123 7124 Maybe<PropertyAttributes> JSReceiver::GetOwnPropertyAttributes( 7125 Handle<JSReceiver> object, Handle<Name> name) { 7126 LookupIterator it = LookupIterator::PropertyOrElement( 7127 name->GetIsolate(), object, name, LookupIterator::HIDDEN); 7128 return GetPropertyAttributes(&it); 7129 } 7130 7131 7132 Maybe<bool> JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) { 7133 LookupIterator it(object->GetIsolate(), object, index); 7134 return HasProperty(&it); 7135 } 7136 7137 7138 Maybe<PropertyAttributes> JSReceiver::GetElementAttributes( 7139 Handle<JSReceiver> object, uint32_t index) { 7140 Isolate* isolate = object->GetIsolate(); 7141 LookupIterator it(isolate, object, index); 7142 return GetPropertyAttributes(&it); 7143 } 7144 7145 7146 Maybe<PropertyAttributes> JSReceiver::GetOwnElementAttributes( 7147 Handle<JSReceiver> object, uint32_t index) { 7148 Isolate* isolate = object->GetIsolate(); 7149 LookupIterator it(isolate, object, index, LookupIterator::HIDDEN); 7150 return GetPropertyAttributes(&it); 7151 } 7152 7153 7154 bool JSGlobalObject::IsDetached() { 7155 return JSGlobalProxy::cast(global_proxy())->IsDetachedFrom(this); 7156 } 7157 7158 7159 bool JSGlobalProxy::IsDetachedFrom(JSGlobalObject* global) const { 7160 const PrototypeIterator iter(this->GetIsolate(), 7161 const_cast<JSGlobalProxy*>(this)); 7162 return iter.GetCurrent() != global; 7163 } 7164 7165 7166 Handle<Smi> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) { 7167 return object->IsJSProxy() 7168 ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object)) 7169 : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object)); 7170 } 7171 7172 7173 Object* JSReceiver::GetIdentityHash() { 7174 return IsJSProxy() 7175 ? JSProxy::cast(this)->GetIdentityHash() 7176 : JSObject::cast(this)->GetIdentityHash(); 7177 } 7178 7179 7180 bool AccessorInfo::all_can_read() { 7181 return BooleanBit::get(flag(), kAllCanReadBit); 7182 } 7183 7184 7185 void AccessorInfo::set_all_can_read(bool value) { 7186 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value)); 7187 } 7188 7189 7190 bool AccessorInfo::all_can_write() { 7191 return BooleanBit::get(flag(), kAllCanWriteBit); 7192 } 7193 7194 7195 void AccessorInfo::set_all_can_write(bool value) { 7196 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value)); 7197 } 7198 7199 7200 bool AccessorInfo::is_special_data_property() { 7201 return BooleanBit::get(flag(), kSpecialDataProperty); 7202 } 7203 7204 7205 void AccessorInfo::set_is_special_data_property(bool value) { 7206 set_flag(BooleanBit::set(flag(), kSpecialDataProperty, value)); 7207 } 7208 7209 7210 PropertyAttributes AccessorInfo::property_attributes() { 7211 return AttributesField::decode(static_cast<uint32_t>(flag())); 7212 } 7213 7214 7215 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) { 7216 set_flag(AttributesField::update(flag(), attributes)); 7217 } 7218 7219 7220 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) { 7221 if (!HasExpectedReceiverType()) return true; 7222 if (!receiver->IsJSObject()) return false; 7223 return FunctionTemplateInfo::cast(expected_receiver_type()) 7224 ->IsTemplateFor(JSObject::cast(receiver)->map()); 7225 } 7226 7227 7228 bool AccessorInfo::HasExpectedReceiverType() { 7229 return expected_receiver_type()->IsFunctionTemplateInfo(); 7230 } 7231 7232 7233 Object* AccessorPair::get(AccessorComponent component) { 7234 return component == ACCESSOR_GETTER ? getter() : setter(); 7235 } 7236 7237 7238 void AccessorPair::set(AccessorComponent component, Object* value) { 7239 if (component == ACCESSOR_GETTER) { 7240 set_getter(value); 7241 } else { 7242 set_setter(value); 7243 } 7244 } 7245 7246 7247 void AccessorPair::SetComponents(Object* getter, Object* setter) { 7248 if (!getter->IsNull()) set_getter(getter); 7249 if (!setter->IsNull()) set_setter(setter); 7250 } 7251 7252 7253 bool AccessorPair::Equals(AccessorPair* pair) { 7254 return (this == pair) || pair->Equals(getter(), setter()); 7255 } 7256 7257 7258 bool AccessorPair::Equals(Object* getter_value, Object* setter_value) { 7259 return (getter() == getter_value) && (setter() == setter_value); 7260 } 7261 7262 7263 bool AccessorPair::ContainsAccessor() { 7264 return IsJSAccessor(getter()) || IsJSAccessor(setter()); 7265 } 7266 7267 7268 bool AccessorPair::IsJSAccessor(Object* obj) { 7269 return obj->IsCallable() || obj->IsUndefined(); 7270 } 7271 7272 7273 template<typename Derived, typename Shape, typename Key> 7274 void Dictionary<Derived, Shape, Key>::SetEntry(int entry, 7275 Handle<Object> key, 7276 Handle<Object> value) { 7277 this->SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0))); 7278 } 7279 7280 7281 template<typename Derived, typename Shape, typename Key> 7282 void Dictionary<Derived, Shape, Key>::SetEntry(int entry, 7283 Handle<Object> key, 7284 Handle<Object> value, 7285 PropertyDetails details) { 7286 Shape::SetEntry(static_cast<Derived*>(this), entry, key, value, details); 7287 } 7288 7289 7290 template <typename Key> 7291 template <typename Dictionary> 7292 void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry, 7293 Handle<Object> key, 7294 Handle<Object> value, 7295 PropertyDetails details) { 7296 STATIC_ASSERT(Dictionary::kEntrySize == 3); 7297 DCHECK(!key->IsName() || details.dictionary_index() > 0); 7298 int index = dict->EntryToIndex(entry); 7299 DisallowHeapAllocation no_gc; 7300 WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); 7301 dict->set(index, *key, mode); 7302 dict->set(index + 1, *value, mode); 7303 dict->set(index + 2, details.AsSmi()); 7304 } 7305 7306 7307 template <typename Dictionary> 7308 void GlobalDictionaryShape::SetEntry(Dictionary* dict, int entry, 7309 Handle<Object> key, Handle<Object> value, 7310 PropertyDetails details) { 7311 STATIC_ASSERT(Dictionary::kEntrySize == 2); 7312 DCHECK(!key->IsName() || details.dictionary_index() > 0); 7313 DCHECK(value->IsPropertyCell()); 7314 int index = dict->EntryToIndex(entry); 7315 DisallowHeapAllocation no_gc; 7316 WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); 7317 dict->set(index, *key, mode); 7318 dict->set(index + 1, *value, mode); 7319 PropertyCell::cast(*value)->set_property_details(details); 7320 } 7321 7322 7323 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { 7324 DCHECK(other->IsNumber()); 7325 return key == static_cast<uint32_t>(other->Number()); 7326 } 7327 7328 7329 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) { 7330 return ComputeIntegerHash(key, 0); 7331 } 7332 7333 7334 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key, 7335 Object* other) { 7336 DCHECK(other->IsNumber()); 7337 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0); 7338 } 7339 7340 7341 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { 7342 return ComputeIntegerHash(key, seed); 7343 } 7344 7345 7346 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key, 7347 uint32_t seed, 7348 Object* other) { 7349 DCHECK(other->IsNumber()); 7350 return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed); 7351 } 7352 7353 7354 Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) { 7355 return isolate->factory()->NewNumberFromUint(key); 7356 } 7357 7358 7359 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object* other) { 7360 // We know that all entries in a hash table had their hash keys created. 7361 // Use that knowledge to have fast failure. 7362 if (key->Hash() != Name::cast(other)->Hash()) return false; 7363 return key->Equals(Name::cast(other)); 7364 } 7365 7366 7367 uint32_t NameDictionaryShape::Hash(Handle<Name> key) { 7368 return key->Hash(); 7369 } 7370 7371 7372 uint32_t NameDictionaryShape::HashForObject(Handle<Name> key, Object* other) { 7373 return Name::cast(other)->Hash(); 7374 } 7375 7376 7377 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate, 7378 Handle<Name> key) { 7379 DCHECK(key->IsUniqueName()); 7380 return key; 7381 } 7382 7383 7384 Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices( 7385 Handle<NameDictionary> dictionary) { 7386 return DerivedDictionary::GenerateNewEnumerationIndices(dictionary); 7387 } 7388 7389 7390 template <typename Dictionary> 7391 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary* dict, int entry) { 7392 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 7393 Object* raw_value = dict->ValueAt(entry); 7394 DCHECK(raw_value->IsPropertyCell()); 7395 PropertyCell* cell = PropertyCell::cast(raw_value); 7396 return cell->property_details(); 7397 } 7398 7399 7400 template <typename Dictionary> 7401 void GlobalDictionaryShape::DetailsAtPut(Dictionary* dict, int entry, 7402 PropertyDetails value) { 7403 DCHECK(entry >= 0); // Not found is -1, which is not caught by get(). 7404 Object* raw_value = dict->ValueAt(entry); 7405 DCHECK(raw_value->IsPropertyCell()); 7406 PropertyCell* cell = PropertyCell::cast(raw_value); 7407 cell->set_property_details(value); 7408 } 7409 7410 7411 template <typename Dictionary> 7412 bool GlobalDictionaryShape::IsDeleted(Dictionary* dict, int entry) { 7413 DCHECK(dict->ValueAt(entry)->IsPropertyCell()); 7414 return PropertyCell::cast(dict->ValueAt(entry))->value()->IsTheHole(); 7415 } 7416 7417 7418 bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object* other) { 7419 return key->SameValue(other); 7420 } 7421 7422 7423 uint32_t ObjectHashTableShape::Hash(Handle<Object> key) { 7424 return Smi::cast(key->GetHash())->value(); 7425 } 7426 7427 7428 uint32_t ObjectHashTableShape::HashForObject(Handle<Object> key, 7429 Object* other) { 7430 return Smi::cast(other->GetHash())->value(); 7431 } 7432 7433 7434 Handle<Object> ObjectHashTableShape::AsHandle(Isolate* isolate, 7435 Handle<Object> key) { 7436 return key; 7437 } 7438 7439 7440 Handle<ObjectHashTable> ObjectHashTable::Shrink( 7441 Handle<ObjectHashTable> table, Handle<Object> key) { 7442 return DerivedHashTable::Shrink(table, key); 7443 } 7444 7445 7446 Object* OrderedHashMap::ValueAt(int entry) { 7447 return get(EntryToIndex(entry) + kValueOffset); 7448 } 7449 7450 7451 template <int entrysize> 7452 bool WeakHashTableShape<entrysize>::IsMatch(Handle<Object> key, Object* other) { 7453 if (other->IsWeakCell()) other = WeakCell::cast(other)->value(); 7454 return key->IsWeakCell() ? WeakCell::cast(*key)->value() == other 7455 : *key == other; 7456 } 7457 7458 7459 template <int entrysize> 7460 uint32_t WeakHashTableShape<entrysize>::Hash(Handle<Object> key) { 7461 intptr_t hash = 7462 key->IsWeakCell() 7463 ? reinterpret_cast<intptr_t>(WeakCell::cast(*key)->value()) 7464 : reinterpret_cast<intptr_t>(*key); 7465 return (uint32_t)(hash & 0xFFFFFFFF); 7466 } 7467 7468 7469 template <int entrysize> 7470 uint32_t WeakHashTableShape<entrysize>::HashForObject(Handle<Object> key, 7471 Object* other) { 7472 if (other->IsWeakCell()) other = WeakCell::cast(other)->value(); 7473 intptr_t hash = reinterpret_cast<intptr_t>(other); 7474 return (uint32_t)(hash & 0xFFFFFFFF); 7475 } 7476 7477 7478 template <int entrysize> 7479 Handle<Object> WeakHashTableShape<entrysize>::AsHandle(Isolate* isolate, 7480 Handle<Object> key) { 7481 return key; 7482 } 7483 7484 7485 bool ScopeInfo::IsAsmModule() { return AsmModuleField::decode(Flags()); } 7486 7487 7488 bool ScopeInfo::IsAsmFunction() { return AsmFunctionField::decode(Flags()); } 7489 7490 7491 bool ScopeInfo::HasSimpleParameters() { 7492 return HasSimpleParametersField::decode(Flags()); 7493 } 7494 7495 7496 #define SCOPE_INFO_FIELD_ACCESSORS(name) \ 7497 void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \ 7498 int ScopeInfo::name() { \ 7499 if (length() > 0) { \ 7500 return Smi::cast(get(k##name))->value(); \ 7501 } else { \ 7502 return 0; \ 7503 } \ 7504 } 7505 FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(SCOPE_INFO_FIELD_ACCESSORS) 7506 #undef SCOPE_INFO_FIELD_ACCESSORS 7507 7508 7509 void Map::ClearCodeCache(Heap* heap) { 7510 // No write barrier is needed since empty_fixed_array is not in new space. 7511 // Please note this function is used during marking: 7512 // - MarkCompactCollector::MarkUnmarkedObject 7513 // - IncrementalMarking::Step 7514 DCHECK(!heap->InNewSpace(heap->empty_fixed_array())); 7515 WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array()); 7516 } 7517 7518 7519 int Map::SlackForArraySize(int old_size, int size_limit) { 7520 const int max_slack = size_limit - old_size; 7521 CHECK_LE(0, max_slack); 7522 if (old_size < 4) { 7523 DCHECK_LE(1, max_slack); 7524 return 1; 7525 } 7526 return Min(max_slack, old_size / 4); 7527 } 7528 7529 7530 void JSArray::set_length(Smi* length) { 7531 // Don't need a write barrier for a Smi. 7532 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); 7533 } 7534 7535 7536 bool JSArray::SetLengthWouldNormalize(Heap* heap, uint32_t new_length) { 7537 // If the new array won't fit in a some non-trivial fraction of the max old 7538 // space size, then force it to go dictionary mode. 7539 uint32_t max_fast_array_size = 7540 static_cast<uint32_t>((heap->MaxOldGenerationSize() / kDoubleSize) / 4); 7541 return new_length >= max_fast_array_size; 7542 } 7543 7544 7545 bool JSArray::AllowsSetLength() { 7546 bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray(); 7547 DCHECK(result == !HasFixedTypedArrayElements()); 7548 return result; 7549 } 7550 7551 7552 void JSArray::SetContent(Handle<JSArray> array, 7553 Handle<FixedArrayBase> storage) { 7554 EnsureCanContainElements(array, storage, storage->length(), 7555 ALLOW_COPIED_DOUBLE_ELEMENTS); 7556 7557 DCHECK((storage->map() == array->GetHeap()->fixed_double_array_map() && 7558 IsFastDoubleElementsKind(array->GetElementsKind())) || 7559 ((storage->map() != array->GetHeap()->fixed_double_array_map()) && 7560 (IsFastObjectElementsKind(array->GetElementsKind()) || 7561 (IsFastSmiElementsKind(array->GetElementsKind()) && 7562 Handle<FixedArray>::cast(storage)->ContainsOnlySmisOrHoles())))); 7563 array->set_elements(*storage); 7564 array->set_length(Smi::FromInt(storage->length())); 7565 } 7566 7567 7568 int TypeFeedbackInfo::ic_total_count() { 7569 int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 7570 return ICTotalCountField::decode(current); 7571 } 7572 7573 7574 void TypeFeedbackInfo::set_ic_total_count(int count) { 7575 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 7576 value = ICTotalCountField::update(value, 7577 ICTotalCountField::decode(count)); 7578 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value)); 7579 } 7580 7581 7582 int TypeFeedbackInfo::ic_with_type_info_count() { 7583 int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 7584 return ICsWithTypeInfoCountField::decode(current); 7585 } 7586 7587 7588 void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) { 7589 if (delta == 0) return; 7590 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 7591 int new_count = ICsWithTypeInfoCountField::decode(value) + delta; 7592 // We can get negative count here when the type-feedback info is 7593 // shared between two code objects. The can only happen when 7594 // the debugger made a shallow copy of code object (see Heap::CopyCode). 7595 // Since we do not optimize when the debugger is active, we can skip 7596 // this counter update. 7597 if (new_count >= 0) { 7598 new_count &= ICsWithTypeInfoCountField::kMask; 7599 value = ICsWithTypeInfoCountField::update(value, new_count); 7600 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value)); 7601 } 7602 } 7603 7604 7605 int TypeFeedbackInfo::ic_generic_count() { 7606 return Smi::cast(READ_FIELD(this, kStorage3Offset))->value(); 7607 } 7608 7609 7610 void TypeFeedbackInfo::change_ic_generic_count(int delta) { 7611 if (delta == 0) return; 7612 int new_count = ic_generic_count() + delta; 7613 if (new_count >= 0) { 7614 new_count &= ~Smi::kMinValue; 7615 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(new_count)); 7616 } 7617 } 7618 7619 7620 void TypeFeedbackInfo::initialize_storage() { 7621 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0)); 7622 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0)); 7623 WRITE_FIELD(this, kStorage3Offset, Smi::FromInt(0)); 7624 } 7625 7626 7627 void TypeFeedbackInfo::change_own_type_change_checksum() { 7628 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 7629 int checksum = OwnTypeChangeChecksum::decode(value); 7630 checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits); 7631 value = OwnTypeChangeChecksum::update(value, checksum); 7632 // Ensure packed bit field is in Smi range. 7633 if (value > Smi::kMaxValue) value |= Smi::kMinValue; 7634 if (value < Smi::kMinValue) value &= ~Smi::kMinValue; 7635 WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value)); 7636 } 7637 7638 7639 void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) { 7640 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 7641 int mask = (1 << kTypeChangeChecksumBits) - 1; 7642 value = InlinedTypeChangeChecksum::update(value, checksum & mask); 7643 // Ensure packed bit field is in Smi range. 7644 if (value > Smi::kMaxValue) value |= Smi::kMinValue; 7645 if (value < Smi::kMinValue) value &= ~Smi::kMinValue; 7646 WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value)); 7647 } 7648 7649 7650 int TypeFeedbackInfo::own_type_change_checksum() { 7651 int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value(); 7652 return OwnTypeChangeChecksum::decode(value); 7653 } 7654 7655 7656 bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) { 7657 int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value(); 7658 int mask = (1 << kTypeChangeChecksumBits) - 1; 7659 return InlinedTypeChangeChecksum::decode(value) == (checksum & mask); 7660 } 7661 7662 7663 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot) 7664 7665 7666 Relocatable::Relocatable(Isolate* isolate) { 7667 isolate_ = isolate; 7668 prev_ = isolate->relocatable_top(); 7669 isolate->set_relocatable_top(this); 7670 } 7671 7672 7673 Relocatable::~Relocatable() { 7674 DCHECK_EQ(isolate_->relocatable_top(), this); 7675 isolate_->set_relocatable_top(prev_); 7676 } 7677 7678 7679 template<class Derived, class TableType> 7680 Object* OrderedHashTableIterator<Derived, TableType>::CurrentKey() { 7681 TableType* table(TableType::cast(this->table())); 7682 int index = Smi::cast(this->index())->value(); 7683 Object* key = table->KeyAt(index); 7684 DCHECK(!key->IsTheHole()); 7685 return key; 7686 } 7687 7688 7689 void JSSetIterator::PopulateValueArray(FixedArray* array) { 7690 array->set(0, CurrentKey()); 7691 } 7692 7693 7694 void JSMapIterator::PopulateValueArray(FixedArray* array) { 7695 array->set(0, CurrentKey()); 7696 array->set(1, CurrentValue()); 7697 } 7698 7699 7700 Object* JSMapIterator::CurrentValue() { 7701 OrderedHashMap* table(OrderedHashMap::cast(this->table())); 7702 int index = Smi::cast(this->index())->value(); 7703 Object* value = table->ValueAt(index); 7704 DCHECK(!value->IsTheHole()); 7705 return value; 7706 } 7707 7708 7709 ACCESSORS(JSIteratorResult, done, Object, kDoneOffset) 7710 ACCESSORS(JSIteratorResult, value, Object, kValueOffset) 7711 7712 7713 String::SubStringRange::SubStringRange(String* string, int first, int length) 7714 : string_(string), 7715 first_(first), 7716 length_(length == -1 ? string->length() : length) {} 7717 7718 7719 class String::SubStringRange::iterator final { 7720 public: 7721 typedef std::forward_iterator_tag iterator_category; 7722 typedef int difference_type; 7723 typedef uc16 value_type; 7724 typedef uc16* pointer; 7725 typedef uc16& reference; 7726 7727 iterator(const iterator& other) 7728 : content_(other.content_), offset_(other.offset_) {} 7729 7730 uc16 operator*() { return content_.Get(offset_); } 7731 bool operator==(const iterator& other) const { 7732 return content_.UsesSameString(other.content_) && offset_ == other.offset_; 7733 } 7734 bool operator!=(const iterator& other) const { 7735 return !content_.UsesSameString(other.content_) || offset_ != other.offset_; 7736 } 7737 iterator& operator++() { 7738 ++offset_; 7739 return *this; 7740 } 7741 iterator operator++(int); 7742 7743 private: 7744 friend class String; 7745 iterator(String* from, int offset) 7746 : content_(from->GetFlatContent()), offset_(offset) {} 7747 String::FlatContent content_; 7748 int offset_; 7749 }; 7750 7751 7752 String::SubStringRange::iterator String::SubStringRange::begin() { 7753 return String::SubStringRange::iterator(string_, first_); 7754 } 7755 7756 7757 String::SubStringRange::iterator String::SubStringRange::end() { 7758 return String::SubStringRange::iterator(string_, first_ + length_); 7759 } 7760 7761 7762 // Predictably converts HeapObject* or Address to uint32 by calculating 7763 // offset of the address in respective MemoryChunk. 7764 static inline uint32_t ObjectAddressForHashing(void* object) { 7765 uint32_t value = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object)); 7766 return value & MemoryChunk::kAlignmentMask; 7767 } 7768 7769 7770 #undef TYPE_CHECKER 7771 #undef CAST_ACCESSOR 7772 #undef INT_ACCESSORS 7773 #undef ACCESSORS 7774 #undef SMI_ACCESSORS 7775 #undef SYNCHRONIZED_SMI_ACCESSORS 7776 #undef NOBARRIER_SMI_ACCESSORS 7777 #undef BOOL_GETTER 7778 #undef BOOL_ACCESSORS 7779 #undef FIELD_ADDR 7780 #undef FIELD_ADDR_CONST 7781 #undef READ_FIELD 7782 #undef NOBARRIER_READ_FIELD 7783 #undef WRITE_FIELD 7784 #undef NOBARRIER_WRITE_FIELD 7785 #undef WRITE_BARRIER 7786 #undef CONDITIONAL_WRITE_BARRIER 7787 #undef READ_DOUBLE_FIELD 7788 #undef WRITE_DOUBLE_FIELD 7789 #undef READ_INT_FIELD 7790 #undef WRITE_INT_FIELD 7791 #undef READ_INTPTR_FIELD 7792 #undef WRITE_INTPTR_FIELD 7793 #undef READ_UINT8_FIELD 7794 #undef WRITE_UINT8_FIELD 7795 #undef READ_INT8_FIELD 7796 #undef WRITE_INT8_FIELD 7797 #undef READ_UINT16_FIELD 7798 #undef WRITE_UINT16_FIELD 7799 #undef READ_INT16_FIELD 7800 #undef WRITE_INT16_FIELD 7801 #undef READ_UINT32_FIELD 7802 #undef WRITE_UINT32_FIELD 7803 #undef READ_INT32_FIELD 7804 #undef WRITE_INT32_FIELD 7805 #undef READ_FLOAT_FIELD 7806 #undef WRITE_FLOAT_FIELD 7807 #undef READ_UINT64_FIELD 7808 #undef WRITE_UINT64_FIELD 7809 #undef READ_INT64_FIELD 7810 #undef WRITE_INT64_FIELD 7811 #undef READ_BYTE_FIELD 7812 #undef WRITE_BYTE_FIELD 7813 #undef NOBARRIER_READ_BYTE_FIELD 7814 #undef NOBARRIER_WRITE_BYTE_FIELD 7815 7816 } // namespace internal 7817 } // namespace v8 7818 7819 #endif // V8_OBJECTS_INL_H_ 7820