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