1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 // 28 // Review notes: 29 // 30 // - The use of macros in these inline functions may seem superfluous 31 // but it is absolutely needed to make sure gcc generates optimal 32 // code. gcc is not happy when attempting to inline too deep. 33 // 34 35 #ifndef V8_OBJECTS_INL_H_ 36 #define V8_OBJECTS_INL_H_ 37 38 #include "objects.h" 39 #include "contexts.h" 40 #include "conversions-inl.h" 41 #include "heap.h" 42 #include "isolate.h" 43 #include "property.h" 44 #include "spaces.h" 45 #include "v8memory.h" 46 47 namespace v8 { 48 namespace internal { 49 50 PropertyDetails::PropertyDetails(Smi* smi) { 51 value_ = smi->value(); 52 } 53 54 55 Smi* PropertyDetails::AsSmi() { 56 return Smi::FromInt(value_); 57 } 58 59 60 PropertyDetails PropertyDetails::AsDeleted() { 61 Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1)); 62 return PropertyDetails(smi); 63 } 64 65 66 #define CAST_ACCESSOR(type) \ 67 type* type::cast(Object* object) { \ 68 ASSERT(object->Is##type()); \ 69 return reinterpret_cast<type*>(object); \ 70 } 71 72 73 #define INT_ACCESSORS(holder, name, offset) \ 74 int holder::name() { return READ_INT_FIELD(this, offset); } \ 75 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } 76 77 78 #define ACCESSORS(holder, name, type, offset) \ 79 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \ 80 void holder::set_##name(type* value, WriteBarrierMode mode) { \ 81 WRITE_FIELD(this, offset, value); \ 82 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); \ 83 } 84 85 86 // GC-safe accessors do not use HeapObject::GetHeap(), but access TLS instead. 87 #define ACCESSORS_GCSAFE(holder, name, type, offset) \ 88 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \ 89 void holder::set_##name(type* value, WriteBarrierMode mode) { \ 90 WRITE_FIELD(this, offset, value); \ 91 CONDITIONAL_WRITE_BARRIER(HEAP, this, offset, mode); \ 92 } 93 94 95 #define SMI_ACCESSORS(holder, name, offset) \ 96 int holder::name() { \ 97 Object* value = READ_FIELD(this, offset); \ 98 return Smi::cast(value)->value(); \ 99 } \ 100 void holder::set_##name(int value) { \ 101 WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 102 } 103 104 105 #define BOOL_GETTER(holder, field, name, offset) \ 106 bool holder::name() { \ 107 return BooleanBit::get(field(), offset); \ 108 } \ 109 110 111 #define BOOL_ACCESSORS(holder, field, name, offset) \ 112 bool holder::name() { \ 113 return BooleanBit::get(field(), offset); \ 114 } \ 115 void holder::set_##name(bool value) { \ 116 set_##field(BooleanBit::set(field(), offset, value)); \ 117 } 118 119 120 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { 121 // There is a constraint on the object; check. 122 if (!this->IsJSObject()) return false; 123 // Fetch the constructor function of the object. 124 Object* cons_obj = JSObject::cast(this)->map()->constructor(); 125 if (!cons_obj->IsJSFunction()) return false; 126 JSFunction* fun = JSFunction::cast(cons_obj); 127 // Iterate through the chain of inheriting function templates to 128 // see if the required one occurs. 129 for (Object* type = fun->shared()->function_data(); 130 type->IsFunctionTemplateInfo(); 131 type = FunctionTemplateInfo::cast(type)->parent_template()) { 132 if (type == expected) return true; 133 } 134 // Didn't find the required type in the inheritance chain. 135 return false; 136 } 137 138 139 bool Object::IsSmi() { 140 return HAS_SMI_TAG(this); 141 } 142 143 144 bool Object::IsHeapObject() { 145 return Internals::HasHeapObjectTag(this); 146 } 147 148 149 bool Object::IsHeapNumber() { 150 return Object::IsHeapObject() 151 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE; 152 } 153 154 155 bool Object::IsString() { 156 return Object::IsHeapObject() 157 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE; 158 } 159 160 161 bool Object::IsSymbol() { 162 if (!this->IsHeapObject()) return false; 163 uint32_t type = HeapObject::cast(this)->map()->instance_type(); 164 // Because the symbol tag is non-zero and no non-string types have the 165 // symbol bit set we can test for symbols with a very simple test 166 // operation. 167 ASSERT(kSymbolTag != 0); 168 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); 169 return (type & kIsSymbolMask) != 0; 170 } 171 172 173 bool Object::IsConsString() { 174 if (!this->IsHeapObject()) return false; 175 uint32_t type = HeapObject::cast(this)->map()->instance_type(); 176 return (type & (kIsNotStringMask | kStringRepresentationMask)) == 177 (kStringTag | kConsStringTag); 178 } 179 180 181 bool Object::IsSeqString() { 182 if (!IsString()) return false; 183 return StringShape(String::cast(this)).IsSequential(); 184 } 185 186 187 bool Object::IsSeqAsciiString() { 188 if (!IsString()) return false; 189 return StringShape(String::cast(this)).IsSequential() && 190 String::cast(this)->IsAsciiRepresentation(); 191 } 192 193 194 bool Object::IsSeqTwoByteString() { 195 if (!IsString()) return false; 196 return StringShape(String::cast(this)).IsSequential() && 197 String::cast(this)->IsTwoByteRepresentation(); 198 } 199 200 201 bool Object::IsExternalString() { 202 if (!IsString()) return false; 203 return StringShape(String::cast(this)).IsExternal(); 204 } 205 206 207 bool Object::IsExternalAsciiString() { 208 if (!IsString()) return false; 209 return StringShape(String::cast(this)).IsExternal() && 210 String::cast(this)->IsAsciiRepresentation(); 211 } 212 213 214 bool Object::IsExternalTwoByteString() { 215 if (!IsString()) return false; 216 return StringShape(String::cast(this)).IsExternal() && 217 String::cast(this)->IsTwoByteRepresentation(); 218 } 219 220 221 StringShape::StringShape(String* str) 222 : type_(str->map()->instance_type()) { 223 set_valid(); 224 ASSERT((type_ & kIsNotStringMask) == kStringTag); 225 } 226 227 228 StringShape::StringShape(Map* map) 229 : type_(map->instance_type()) { 230 set_valid(); 231 ASSERT((type_ & kIsNotStringMask) == kStringTag); 232 } 233 234 235 StringShape::StringShape(InstanceType t) 236 : type_(static_cast<uint32_t>(t)) { 237 set_valid(); 238 ASSERT((type_ & kIsNotStringMask) == kStringTag); 239 } 240 241 242 bool StringShape::IsSymbol() { 243 ASSERT(valid()); 244 ASSERT(kSymbolTag != 0); 245 return (type_ & kIsSymbolMask) != 0; 246 } 247 248 249 bool String::IsAsciiRepresentation() { 250 uint32_t type = map()->instance_type(); 251 return (type & kStringEncodingMask) == kAsciiStringTag; 252 } 253 254 255 bool String::IsTwoByteRepresentation() { 256 uint32_t type = map()->instance_type(); 257 return (type & kStringEncodingMask) == kTwoByteStringTag; 258 } 259 260 261 bool String::HasOnlyAsciiChars() { 262 uint32_t type = map()->instance_type(); 263 return (type & kStringEncodingMask) == kAsciiStringTag || 264 (type & kAsciiDataHintMask) == kAsciiDataHintTag; 265 } 266 267 268 bool StringShape::IsCons() { 269 return (type_ & kStringRepresentationMask) == kConsStringTag; 270 } 271 272 273 bool StringShape::IsExternal() { 274 return (type_ & kStringRepresentationMask) == kExternalStringTag; 275 } 276 277 278 bool StringShape::IsSequential() { 279 return (type_ & kStringRepresentationMask) == kSeqStringTag; 280 } 281 282 283 StringRepresentationTag StringShape::representation_tag() { 284 uint32_t tag = (type_ & kStringRepresentationMask); 285 return static_cast<StringRepresentationTag>(tag); 286 } 287 288 289 uint32_t StringShape::full_representation_tag() { 290 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); 291 } 292 293 294 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) == 295 Internals::kFullStringRepresentationMask); 296 297 298 bool StringShape::IsSequentialAscii() { 299 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag); 300 } 301 302 303 bool StringShape::IsSequentialTwoByte() { 304 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); 305 } 306 307 308 bool StringShape::IsExternalAscii() { 309 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag); 310 } 311 312 313 bool StringShape::IsExternalTwoByte() { 314 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); 315 } 316 317 318 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) == 319 Internals::kExternalTwoByteRepresentationTag); 320 321 322 uc32 FlatStringReader::Get(int index) { 323 ASSERT(0 <= index && index <= length_); 324 if (is_ascii_) { 325 return static_cast<const byte*>(start_)[index]; 326 } else { 327 return static_cast<const uc16*>(start_)[index]; 328 } 329 } 330 331 332 bool Object::IsNumber() { 333 return IsSmi() || IsHeapNumber(); 334 } 335 336 337 bool Object::IsByteArray() { 338 return Object::IsHeapObject() 339 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE; 340 } 341 342 343 bool Object::IsExternalPixelArray() { 344 return Object::IsHeapObject() && 345 HeapObject::cast(this)->map()->instance_type() == 346 EXTERNAL_PIXEL_ARRAY_TYPE; 347 } 348 349 350 bool Object::IsExternalArray() { 351 if (!Object::IsHeapObject()) 352 return false; 353 InstanceType instance_type = 354 HeapObject::cast(this)->map()->instance_type(); 355 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE && 356 instance_type <= LAST_EXTERNAL_ARRAY_TYPE); 357 } 358 359 360 bool Object::IsExternalByteArray() { 361 return Object::IsHeapObject() && 362 HeapObject::cast(this)->map()->instance_type() == 363 EXTERNAL_BYTE_ARRAY_TYPE; 364 } 365 366 367 bool Object::IsExternalUnsignedByteArray() { 368 return Object::IsHeapObject() && 369 HeapObject::cast(this)->map()->instance_type() == 370 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE; 371 } 372 373 374 bool Object::IsExternalShortArray() { 375 return Object::IsHeapObject() && 376 HeapObject::cast(this)->map()->instance_type() == 377 EXTERNAL_SHORT_ARRAY_TYPE; 378 } 379 380 381 bool Object::IsExternalUnsignedShortArray() { 382 return Object::IsHeapObject() && 383 HeapObject::cast(this)->map()->instance_type() == 384 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE; 385 } 386 387 388 bool Object::IsExternalIntArray() { 389 return Object::IsHeapObject() && 390 HeapObject::cast(this)->map()->instance_type() == 391 EXTERNAL_INT_ARRAY_TYPE; 392 } 393 394 395 bool Object::IsExternalUnsignedIntArray() { 396 return Object::IsHeapObject() && 397 HeapObject::cast(this)->map()->instance_type() == 398 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE; 399 } 400 401 402 bool Object::IsExternalFloatArray() { 403 return Object::IsHeapObject() && 404 HeapObject::cast(this)->map()->instance_type() == 405 EXTERNAL_FLOAT_ARRAY_TYPE; 406 } 407 408 409 bool MaybeObject::IsFailure() { 410 return HAS_FAILURE_TAG(this); 411 } 412 413 414 bool MaybeObject::IsRetryAfterGC() { 415 return HAS_FAILURE_TAG(this) 416 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC; 417 } 418 419 420 bool MaybeObject::IsOutOfMemory() { 421 return HAS_FAILURE_TAG(this) 422 && Failure::cast(this)->IsOutOfMemoryException(); 423 } 424 425 426 bool MaybeObject::IsException() { 427 return this == Failure::Exception(); 428 } 429 430 431 bool MaybeObject::IsTheHole() { 432 return !IsFailure() && ToObjectUnchecked()->IsTheHole(); 433 } 434 435 436 Failure* Failure::cast(MaybeObject* obj) { 437 ASSERT(HAS_FAILURE_TAG(obj)); 438 return reinterpret_cast<Failure*>(obj); 439 } 440 441 442 bool Object::IsJSObject() { 443 return IsHeapObject() 444 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE; 445 } 446 447 448 bool Object::IsJSContextExtensionObject() { 449 return IsHeapObject() 450 && (HeapObject::cast(this)->map()->instance_type() == 451 JS_CONTEXT_EXTENSION_OBJECT_TYPE); 452 } 453 454 455 bool Object::IsMap() { 456 return Object::IsHeapObject() 457 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE; 458 } 459 460 461 bool Object::IsFixedArray() { 462 return Object::IsHeapObject() 463 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE; 464 } 465 466 467 bool Object::IsDescriptorArray() { 468 return IsFixedArray(); 469 } 470 471 472 bool Object::IsDeoptimizationInputData() { 473 // Must be a fixed array. 474 if (!IsFixedArray()) return false; 475 476 // There's no sure way to detect the difference between a fixed array and 477 // a deoptimization data array. Since this is used for asserts we can 478 // check that the length is zero or else the fixed size plus a multiple of 479 // the entry size. 480 int length = FixedArray::cast(this)->length(); 481 if (length == 0) return true; 482 483 length -= DeoptimizationInputData::kFirstDeoptEntryIndex; 484 return length >= 0 && 485 length % DeoptimizationInputData::kDeoptEntrySize == 0; 486 } 487 488 489 bool Object::IsDeoptimizationOutputData() { 490 if (!IsFixedArray()) return false; 491 // There's actually no way to see the difference between a fixed array and 492 // a deoptimization data array. Since this is used for asserts we can check 493 // that the length is plausible though. 494 if (FixedArray::cast(this)->length() % 2 != 0) return false; 495 return true; 496 } 497 498 499 bool Object::IsContext() { 500 if (Object::IsHeapObject()) { 501 Heap* heap = HeapObject::cast(this)->GetHeap(); 502 return (HeapObject::cast(this)->map() == heap->context_map() || 503 HeapObject::cast(this)->map() == heap->catch_context_map() || 504 HeapObject::cast(this)->map() == heap->global_context_map()); 505 } 506 return false; 507 } 508 509 510 bool Object::IsCatchContext() { 511 return Object::IsHeapObject() && 512 HeapObject::cast(this)->map() == 513 HeapObject::cast(this)->GetHeap()->catch_context_map(); 514 } 515 516 517 bool Object::IsGlobalContext() { 518 return Object::IsHeapObject() && 519 HeapObject::cast(this)->map() == 520 HeapObject::cast(this)->GetHeap()->global_context_map(); 521 } 522 523 524 bool Object::IsJSFunction() { 525 return Object::IsHeapObject() 526 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE; 527 } 528 529 530 template <> inline bool Is<JSFunction>(Object* obj) { 531 return obj->IsJSFunction(); 532 } 533 534 535 bool Object::IsCode() { 536 return Object::IsHeapObject() 537 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE; 538 } 539 540 541 bool Object::IsOddball() { 542 ASSERT(HEAP->is_safe_to_read_maps()); 543 return Object::IsHeapObject() 544 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE; 545 } 546 547 548 bool Object::IsJSGlobalPropertyCell() { 549 return Object::IsHeapObject() 550 && HeapObject::cast(this)->map()->instance_type() 551 == JS_GLOBAL_PROPERTY_CELL_TYPE; 552 } 553 554 555 bool Object::IsSharedFunctionInfo() { 556 return Object::IsHeapObject() && 557 (HeapObject::cast(this)->map()->instance_type() == 558 SHARED_FUNCTION_INFO_TYPE); 559 } 560 561 562 bool Object::IsJSValue() { 563 return Object::IsHeapObject() 564 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE; 565 } 566 567 568 bool Object::IsJSMessageObject() { 569 return Object::IsHeapObject() 570 && (HeapObject::cast(this)->map()->instance_type() == 571 JS_MESSAGE_OBJECT_TYPE); 572 } 573 574 575 bool Object::IsStringWrapper() { 576 return IsJSValue() && JSValue::cast(this)->value()->IsString(); 577 } 578 579 580 bool Object::IsProxy() { 581 return Object::IsHeapObject() 582 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE; 583 } 584 585 586 bool Object::IsBoolean() { 587 return IsOddball() && 588 ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0); 589 } 590 591 592 bool Object::IsJSArray() { 593 return Object::IsHeapObject() 594 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE; 595 } 596 597 598 bool Object::IsJSRegExp() { 599 return Object::IsHeapObject() 600 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE; 601 } 602 603 604 template <> inline bool Is<JSArray>(Object* obj) { 605 return obj->IsJSArray(); 606 } 607 608 609 bool Object::IsHashTable() { 610 return Object::IsHeapObject() && 611 HeapObject::cast(this)->map() == 612 HeapObject::cast(this)->GetHeap()->hash_table_map(); 613 } 614 615 616 bool Object::IsDictionary() { 617 return IsHashTable() && this != 618 HeapObject::cast(this)->GetHeap()->symbol_table(); 619 } 620 621 622 bool Object::IsSymbolTable() { 623 return IsHashTable() && this == 624 HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table(); 625 } 626 627 628 bool Object::IsJSFunctionResultCache() { 629 if (!IsFixedArray()) return false; 630 FixedArray* self = FixedArray::cast(this); 631 int length = self->length(); 632 if (length < JSFunctionResultCache::kEntriesIndex) return false; 633 if ((length - JSFunctionResultCache::kEntriesIndex) 634 % JSFunctionResultCache::kEntrySize != 0) { 635 return false; 636 } 637 #ifdef DEBUG 638 reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify(); 639 #endif 640 return true; 641 } 642 643 644 bool Object::IsNormalizedMapCache() { 645 if (!IsFixedArray()) return false; 646 if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) { 647 return false; 648 } 649 #ifdef DEBUG 650 reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify(); 651 #endif 652 return true; 653 } 654 655 656 bool Object::IsCompilationCacheTable() { 657 return IsHashTable(); 658 } 659 660 661 bool Object::IsCodeCacheHashTable() { 662 return IsHashTable(); 663 } 664 665 666 bool Object::IsMapCache() { 667 return IsHashTable(); 668 } 669 670 671 bool Object::IsPrimitive() { 672 return IsOddball() || IsNumber() || IsString(); 673 } 674 675 676 bool Object::IsJSGlobalProxy() { 677 bool result = IsHeapObject() && 678 (HeapObject::cast(this)->map()->instance_type() == 679 JS_GLOBAL_PROXY_TYPE); 680 ASSERT(!result || IsAccessCheckNeeded()); 681 return result; 682 } 683 684 685 bool Object::IsGlobalObject() { 686 if (!IsHeapObject()) return false; 687 688 InstanceType type = HeapObject::cast(this)->map()->instance_type(); 689 return type == JS_GLOBAL_OBJECT_TYPE || 690 type == JS_BUILTINS_OBJECT_TYPE; 691 } 692 693 694 bool Object::IsJSGlobalObject() { 695 return IsHeapObject() && 696 (HeapObject::cast(this)->map()->instance_type() == 697 JS_GLOBAL_OBJECT_TYPE); 698 } 699 700 701 bool Object::IsJSBuiltinsObject() { 702 return IsHeapObject() && 703 (HeapObject::cast(this)->map()->instance_type() == 704 JS_BUILTINS_OBJECT_TYPE); 705 } 706 707 708 bool Object::IsUndetectableObject() { 709 return IsHeapObject() 710 && HeapObject::cast(this)->map()->is_undetectable(); 711 } 712 713 714 bool Object::IsAccessCheckNeeded() { 715 return IsHeapObject() 716 && HeapObject::cast(this)->map()->is_access_check_needed(); 717 } 718 719 720 bool Object::IsStruct() { 721 if (!IsHeapObject()) return false; 722 switch (HeapObject::cast(this)->map()->instance_type()) { 723 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true; 724 STRUCT_LIST(MAKE_STRUCT_CASE) 725 #undef MAKE_STRUCT_CASE 726 default: return false; 727 } 728 } 729 730 731 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ 732 bool Object::Is##Name() { \ 733 return Object::IsHeapObject() \ 734 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \ 735 } 736 STRUCT_LIST(MAKE_STRUCT_PREDICATE) 737 #undef MAKE_STRUCT_PREDICATE 738 739 740 bool Object::IsUndefined() { 741 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined; 742 } 743 744 745 bool Object::IsNull() { 746 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull; 747 } 748 749 750 bool Object::IsTheHole() { 751 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole; 752 } 753 754 755 bool Object::IsTrue() { 756 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue; 757 } 758 759 760 bool Object::IsFalse() { 761 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse; 762 } 763 764 765 bool Object::IsArgumentsMarker() { 766 return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker; 767 } 768 769 770 double Object::Number() { 771 ASSERT(IsNumber()); 772 return IsSmi() 773 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value()) 774 : reinterpret_cast<HeapNumber*>(this)->value(); 775 } 776 777 778 MaybeObject* Object::ToSmi() { 779 if (IsSmi()) return this; 780 if (IsHeapNumber()) { 781 double value = HeapNumber::cast(this)->value(); 782 int int_value = FastD2I(value); 783 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { 784 return Smi::FromInt(int_value); 785 } 786 } 787 return Failure::Exception(); 788 } 789 790 791 bool Object::HasSpecificClassOf(String* name) { 792 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name); 793 } 794 795 796 MaybeObject* Object::GetElement(uint32_t index) { 797 // GetElement can trigger a getter which can cause allocation. 798 // This was not always the case. This ASSERT is here to catch 799 // leftover incorrect uses. 800 ASSERT(HEAP->IsAllocationAllowed()); 801 return GetElementWithReceiver(this, index); 802 } 803 804 805 Object* Object::GetElementNoExceptionThrown(uint32_t index) { 806 MaybeObject* maybe = GetElementWithReceiver(this, index); 807 ASSERT(!maybe->IsFailure()); 808 Object* result = NULL; // Initialization to please compiler. 809 maybe->ToObject(&result); 810 return result; 811 } 812 813 814 MaybeObject* Object::GetProperty(String* key) { 815 PropertyAttributes attributes; 816 return GetPropertyWithReceiver(this, key, &attributes); 817 } 818 819 820 MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) { 821 return GetPropertyWithReceiver(this, key, attributes); 822 } 823 824 825 #define FIELD_ADDR(p, offset) \ 826 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) 827 828 #define READ_FIELD(p, offset) \ 829 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset))) 830 831 #define WRITE_FIELD(p, offset, value) \ 832 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) 833 834 // TODO(isolates): Pass heap in to these macros. 835 #define WRITE_BARRIER(object, offset) \ 836 object->GetHeap()->RecordWrite(object->address(), offset); 837 838 // CONDITIONAL_WRITE_BARRIER must be issued after the actual 839 // write due to the assert validating the written value. 840 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, mode) \ 841 if (mode == UPDATE_WRITE_BARRIER) { \ 842 heap->RecordWrite(object->address(), offset); \ 843 } else { \ 844 ASSERT(mode == SKIP_WRITE_BARRIER); \ 845 ASSERT(heap->InNewSpace(object) || \ 846 !heap->InNewSpace(READ_FIELD(object, offset)) || \ 847 Page::FromAddress(object->address())-> \ 848 IsRegionDirty(object->address() + offset)); \ 849 } 850 851 #ifndef V8_TARGET_ARCH_MIPS 852 #define READ_DOUBLE_FIELD(p, offset) \ 853 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset))) 854 #else // V8_TARGET_ARCH_MIPS 855 // Prevent gcc from using load-double (mips ldc1) on (possibly) 856 // non-64-bit aligned HeapNumber::value. 857 static inline double read_double_field(HeapNumber* p, int offset) { 858 union conversion { 859 double d; 860 uint32_t u[2]; 861 } c; 862 c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))); 863 c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))); 864 return c.d; 865 } 866 #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset) 867 #endif // V8_TARGET_ARCH_MIPS 868 869 870 #ifndef V8_TARGET_ARCH_MIPS 871 #define WRITE_DOUBLE_FIELD(p, offset, value) \ 872 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value) 873 #else // V8_TARGET_ARCH_MIPS 874 // Prevent gcc from using store-double (mips sdc1) on (possibly) 875 // non-64-bit aligned HeapNumber::value. 876 static inline void write_double_field(HeapNumber* p, int offset, 877 double value) { 878 union conversion { 879 double d; 880 uint32_t u[2]; 881 } c; 882 c.d = value; 883 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0]; 884 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1]; 885 } 886 #define WRITE_DOUBLE_FIELD(p, offset, value) \ 887 write_double_field(p, offset, value) 888 #endif // V8_TARGET_ARCH_MIPS 889 890 891 #define READ_INT_FIELD(p, offset) \ 892 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset))) 893 894 #define WRITE_INT_FIELD(p, offset, value) \ 895 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) 896 897 #define READ_INTPTR_FIELD(p, offset) \ 898 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset))) 899 900 #define WRITE_INTPTR_FIELD(p, offset, value) \ 901 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value) 902 903 #define READ_UINT32_FIELD(p, offset) \ 904 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) 905 906 #define WRITE_UINT32_FIELD(p, offset, value) \ 907 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value) 908 909 #define READ_SHORT_FIELD(p, offset) \ 910 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset))) 911 912 #define WRITE_SHORT_FIELD(p, offset, value) \ 913 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value) 914 915 #define READ_BYTE_FIELD(p, offset) \ 916 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset))) 917 918 #define WRITE_BYTE_FIELD(p, offset, value) \ 919 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value) 920 921 922 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) { 923 return &READ_FIELD(obj, byte_offset); 924 } 925 926 927 int Smi::value() { 928 return Internals::SmiValue(this); 929 } 930 931 932 Smi* Smi::FromInt(int value) { 933 ASSERT(Smi::IsValid(value)); 934 int smi_shift_bits = kSmiTagSize + kSmiShiftSize; 935 intptr_t tagged_value = 936 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag; 937 return reinterpret_cast<Smi*>(tagged_value); 938 } 939 940 941 Smi* Smi::FromIntptr(intptr_t value) { 942 ASSERT(Smi::IsValid(value)); 943 int smi_shift_bits = kSmiTagSize + kSmiShiftSize; 944 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag); 945 } 946 947 948 Failure::Type Failure::type() const { 949 return static_cast<Type>(value() & kFailureTypeTagMask); 950 } 951 952 953 bool Failure::IsInternalError() const { 954 return type() == INTERNAL_ERROR; 955 } 956 957 958 bool Failure::IsOutOfMemoryException() const { 959 return type() == OUT_OF_MEMORY_EXCEPTION; 960 } 961 962 963 AllocationSpace Failure::allocation_space() const { 964 ASSERT_EQ(RETRY_AFTER_GC, type()); 965 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize) 966 & kSpaceTagMask); 967 } 968 969 970 Failure* Failure::InternalError() { 971 return Construct(INTERNAL_ERROR); 972 } 973 974 975 Failure* Failure::Exception() { 976 return Construct(EXCEPTION); 977 } 978 979 980 Failure* Failure::OutOfMemoryException() { 981 return Construct(OUT_OF_MEMORY_EXCEPTION); 982 } 983 984 985 intptr_t Failure::value() const { 986 return static_cast<intptr_t>( 987 reinterpret_cast<uintptr_t>(this) >> kFailureTagSize); 988 } 989 990 991 Failure* Failure::RetryAfterGC() { 992 return RetryAfterGC(NEW_SPACE); 993 } 994 995 996 Failure* Failure::RetryAfterGC(AllocationSpace space) { 997 ASSERT((space & ~kSpaceTagMask) == 0); 998 return Construct(RETRY_AFTER_GC, space); 999 } 1000 1001 1002 Failure* Failure::Construct(Type type, intptr_t value) { 1003 uintptr_t info = 1004 (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type; 1005 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info); 1006 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag); 1007 } 1008 1009 1010 bool Smi::IsValid(intptr_t value) { 1011 #ifdef DEBUG 1012 bool in_range = (value >= kMinValue) && (value <= kMaxValue); 1013 #endif 1014 1015 #ifdef V8_TARGET_ARCH_X64 1016 // To be representable as a long smi, the value must be a 32-bit integer. 1017 bool result = (value == static_cast<int32_t>(value)); 1018 #else 1019 // To be representable as an tagged small integer, the two 1020 // most-significant bits of 'value' must be either 00 or 11 due to 1021 // sign-extension. To check this we add 01 to the two 1022 // most-significant bits, and check if the most-significant bit is 0 1023 // 1024 // CAUTION: The original code below: 1025 // bool result = ((value + 0x40000000) & 0x80000000) == 0; 1026 // may lead to incorrect results according to the C language spec, and 1027 // in fact doesn't work correctly with gcc4.1.1 in some cases: The 1028 // compiler may produce undefined results in case of signed integer 1029 // overflow. The computation must be done w/ unsigned ints. 1030 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U); 1031 #endif 1032 ASSERT(result == in_range); 1033 return result; 1034 } 1035 1036 1037 MapWord MapWord::FromMap(Map* map) { 1038 return MapWord(reinterpret_cast<uintptr_t>(map)); 1039 } 1040 1041 1042 Map* MapWord::ToMap() { 1043 return reinterpret_cast<Map*>(value_); 1044 } 1045 1046 1047 bool MapWord::IsForwardingAddress() { 1048 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_)); 1049 } 1050 1051 1052 MapWord MapWord::FromForwardingAddress(HeapObject* object) { 1053 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag; 1054 return MapWord(reinterpret_cast<uintptr_t>(raw)); 1055 } 1056 1057 1058 HeapObject* MapWord::ToForwardingAddress() { 1059 ASSERT(IsForwardingAddress()); 1060 return HeapObject::FromAddress(reinterpret_cast<Address>(value_)); 1061 } 1062 1063 1064 bool MapWord::IsMarked() { 1065 return (value_ & kMarkingMask) == 0; 1066 } 1067 1068 1069 void MapWord::SetMark() { 1070 value_ &= ~kMarkingMask; 1071 } 1072 1073 1074 void MapWord::ClearMark() { 1075 value_ |= kMarkingMask; 1076 } 1077 1078 1079 bool MapWord::IsOverflowed() { 1080 return (value_ & kOverflowMask) != 0; 1081 } 1082 1083 1084 void MapWord::SetOverflow() { 1085 value_ |= kOverflowMask; 1086 } 1087 1088 1089 void MapWord::ClearOverflow() { 1090 value_ &= ~kOverflowMask; 1091 } 1092 1093 1094 MapWord MapWord::EncodeAddress(Address map_address, int offset) { 1095 // Offset is the distance in live bytes from the first live object in the 1096 // same page. The offset between two objects in the same page should not 1097 // exceed the object area size of a page. 1098 ASSERT(0 <= offset && offset < Page::kObjectAreaSize); 1099 1100 uintptr_t compact_offset = offset >> kObjectAlignmentBits; 1101 ASSERT(compact_offset < (1 << kForwardingOffsetBits)); 1102 1103 Page* map_page = Page::FromAddress(map_address); 1104 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index); 1105 1106 uintptr_t map_page_offset = 1107 map_page->Offset(map_address) >> kMapAlignmentBits; 1108 1109 uintptr_t encoding = 1110 (compact_offset << kForwardingOffsetShift) | 1111 (map_page_offset << kMapPageOffsetShift) | 1112 (map_page->mc_page_index << kMapPageIndexShift); 1113 return MapWord(encoding); 1114 } 1115 1116 1117 Address MapWord::DecodeMapAddress(MapSpace* map_space) { 1118 int map_page_index = 1119 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift); 1120 ASSERT_MAP_PAGE_INDEX(map_page_index); 1121 1122 int map_page_offset = static_cast<int>( 1123 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) << 1124 kMapAlignmentBits); 1125 1126 return (map_space->PageAddress(map_page_index) + map_page_offset); 1127 } 1128 1129 1130 int MapWord::DecodeOffset() { 1131 // The offset field is represented in the kForwardingOffsetBits 1132 // most-significant bits. 1133 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits; 1134 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize)); 1135 return static_cast<int>(offset); 1136 } 1137 1138 1139 MapWord MapWord::FromEncodedAddress(Address address) { 1140 return MapWord(reinterpret_cast<uintptr_t>(address)); 1141 } 1142 1143 1144 Address MapWord::ToEncodedAddress() { 1145 return reinterpret_cast<Address>(value_); 1146 } 1147 1148 1149 #ifdef DEBUG 1150 void HeapObject::VerifyObjectField(int offset) { 1151 VerifyPointer(READ_FIELD(this, offset)); 1152 } 1153 1154 void HeapObject::VerifySmiField(int offset) { 1155 ASSERT(READ_FIELD(this, offset)->IsSmi()); 1156 } 1157 #endif 1158 1159 1160 Heap* HeapObject::GetHeap() { 1161 // During GC, the map pointer in HeapObject is used in various ways that 1162 // prevent us from retrieving Heap from the map. 1163 // Assert that we are not in GC, implement GC code in a way that it doesn't 1164 // pull heap from the map. 1165 ASSERT(HEAP->is_safe_to_read_maps()); 1166 return map()->heap(); 1167 } 1168 1169 1170 Isolate* HeapObject::GetIsolate() { 1171 return GetHeap()->isolate(); 1172 } 1173 1174 1175 Map* HeapObject::map() { 1176 return map_word().ToMap(); 1177 } 1178 1179 1180 void HeapObject::set_map(Map* value) { 1181 set_map_word(MapWord::FromMap(value)); 1182 } 1183 1184 1185 MapWord HeapObject::map_word() { 1186 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset))); 1187 } 1188 1189 1190 void HeapObject::set_map_word(MapWord map_word) { 1191 // WRITE_FIELD does not invoke write barrier, but there is no need 1192 // here. 1193 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1194 } 1195 1196 1197 HeapObject* HeapObject::FromAddress(Address address) { 1198 ASSERT_TAG_ALIGNED(address); 1199 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag); 1200 } 1201 1202 1203 Address HeapObject::address() { 1204 return reinterpret_cast<Address>(this) - kHeapObjectTag; 1205 } 1206 1207 1208 int HeapObject::Size() { 1209 return SizeFromMap(map()); 1210 } 1211 1212 1213 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) { 1214 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)), 1215 reinterpret_cast<Object**>(FIELD_ADDR(this, end))); 1216 } 1217 1218 1219 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) { 1220 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset))); 1221 } 1222 1223 1224 bool HeapObject::IsMarked() { 1225 return map_word().IsMarked(); 1226 } 1227 1228 1229 void HeapObject::SetMark() { 1230 ASSERT(!IsMarked()); 1231 MapWord first_word = map_word(); 1232 first_word.SetMark(); 1233 set_map_word(first_word); 1234 } 1235 1236 1237 void HeapObject::ClearMark() { 1238 ASSERT(IsMarked()); 1239 MapWord first_word = map_word(); 1240 first_word.ClearMark(); 1241 set_map_word(first_word); 1242 } 1243 1244 1245 bool HeapObject::IsOverflowed() { 1246 return map_word().IsOverflowed(); 1247 } 1248 1249 1250 void HeapObject::SetOverflow() { 1251 MapWord first_word = map_word(); 1252 first_word.SetOverflow(); 1253 set_map_word(first_word); 1254 } 1255 1256 1257 void HeapObject::ClearOverflow() { 1258 ASSERT(IsOverflowed()); 1259 MapWord first_word = map_word(); 1260 first_word.ClearOverflow(); 1261 set_map_word(first_word); 1262 } 1263 1264 1265 double HeapNumber::value() { 1266 return READ_DOUBLE_FIELD(this, kValueOffset); 1267 } 1268 1269 1270 void HeapNumber::set_value(double value) { 1271 WRITE_DOUBLE_FIELD(this, kValueOffset, value); 1272 } 1273 1274 1275 int HeapNumber::get_exponent() { 1276 return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >> 1277 kExponentShift) - kExponentBias; 1278 } 1279 1280 1281 int HeapNumber::get_sign() { 1282 return READ_INT_FIELD(this, kExponentOffset) & kSignMask; 1283 } 1284 1285 1286 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset) 1287 1288 1289 HeapObject* JSObject::elements() { 1290 Object* array = READ_FIELD(this, kElementsOffset); 1291 // In the assert below Dictionary is covered under FixedArray. 1292 ASSERT(array->IsFixedArray() || array->IsExternalArray()); 1293 return reinterpret_cast<HeapObject*>(array); 1294 } 1295 1296 1297 void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) { 1298 ASSERT(map()->has_fast_elements() == 1299 (value->map() == GetHeap()->fixed_array_map() || 1300 value->map() == GetHeap()->fixed_cow_array_map())); 1301 // In the assert below Dictionary is covered under FixedArray. 1302 ASSERT(value->IsFixedArray() || value->IsExternalArray()); 1303 WRITE_FIELD(this, kElementsOffset, value); 1304 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, mode); 1305 } 1306 1307 1308 void JSObject::initialize_properties() { 1309 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); 1310 WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array()); 1311 } 1312 1313 1314 void JSObject::initialize_elements() { 1315 ASSERT(map()->has_fast_elements()); 1316 ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array())); 1317 WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array()); 1318 } 1319 1320 1321 MaybeObject* JSObject::ResetElements() { 1322 Object* obj; 1323 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); 1324 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1325 } 1326 set_map(Map::cast(obj)); 1327 initialize_elements(); 1328 return this; 1329 } 1330 1331 1332 ACCESSORS(Oddball, to_string, String, kToStringOffset) 1333 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) 1334 1335 1336 byte Oddball::kind() { 1337 return READ_BYTE_FIELD(this, kKindOffset); 1338 } 1339 1340 1341 void Oddball::set_kind(byte value) { 1342 WRITE_BYTE_FIELD(this, kKindOffset, value); 1343 } 1344 1345 1346 Object* JSGlobalPropertyCell::value() { 1347 return READ_FIELD(this, kValueOffset); 1348 } 1349 1350 1351 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) { 1352 // The write barrier is not used for global property cells. 1353 ASSERT(!val->IsJSGlobalPropertyCell()); 1354 WRITE_FIELD(this, kValueOffset, val); 1355 } 1356 1357 1358 int JSObject::GetHeaderSize() { 1359 InstanceType type = map()->instance_type(); 1360 // Check for the most common kind of JavaScript object before 1361 // falling into the generic switch. This speeds up the internal 1362 // field operations considerably on average. 1363 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize; 1364 switch (type) { 1365 case JS_GLOBAL_PROXY_TYPE: 1366 return JSGlobalProxy::kSize; 1367 case JS_GLOBAL_OBJECT_TYPE: 1368 return JSGlobalObject::kSize; 1369 case JS_BUILTINS_OBJECT_TYPE: 1370 return JSBuiltinsObject::kSize; 1371 case JS_FUNCTION_TYPE: 1372 return JSFunction::kSize; 1373 case JS_VALUE_TYPE: 1374 return JSValue::kSize; 1375 case JS_ARRAY_TYPE: 1376 return JSValue::kSize; 1377 case JS_REGEXP_TYPE: 1378 return JSValue::kSize; 1379 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 1380 return JSObject::kHeaderSize; 1381 case JS_MESSAGE_OBJECT_TYPE: 1382 return JSMessageObject::kSize; 1383 default: 1384 UNREACHABLE(); 1385 return 0; 1386 } 1387 } 1388 1389 1390 int JSObject::GetInternalFieldCount() { 1391 ASSERT(1 << kPointerSizeLog2 == kPointerSize); 1392 // Make sure to adjust for the number of in-object properties. These 1393 // properties do contribute to the size, but are not internal fields. 1394 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) - 1395 map()->inobject_properties(); 1396 } 1397 1398 1399 int JSObject::GetInternalFieldOffset(int index) { 1400 ASSERT(index < GetInternalFieldCount() && index >= 0); 1401 return GetHeaderSize() + (kPointerSize * index); 1402 } 1403 1404 1405 Object* JSObject::GetInternalField(int index) { 1406 ASSERT(index < GetInternalFieldCount() && index >= 0); 1407 // Internal objects do follow immediately after the header, whereas in-object 1408 // properties are at the end of the object. Therefore there is no need 1409 // to adjust the index here. 1410 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); 1411 } 1412 1413 1414 void JSObject::SetInternalField(int index, Object* value) { 1415 ASSERT(index < GetInternalFieldCount() && index >= 0); 1416 // Internal objects do follow immediately after the header, whereas in-object 1417 // properties are at the end of the object. Therefore there is no need 1418 // to adjust the index here. 1419 int offset = GetHeaderSize() + (kPointerSize * index); 1420 WRITE_FIELD(this, offset, value); 1421 WRITE_BARRIER(this, offset); 1422 } 1423 1424 1425 // Access fast-case object properties at index. The use of these routines 1426 // is needed to correctly distinguish between properties stored in-object and 1427 // properties stored in the properties array. 1428 Object* JSObject::FastPropertyAt(int index) { 1429 // Adjust for the number of properties stored in the object. 1430 index -= map()->inobject_properties(); 1431 if (index < 0) { 1432 int offset = map()->instance_size() + (index * kPointerSize); 1433 return READ_FIELD(this, offset); 1434 } else { 1435 ASSERT(index < properties()->length()); 1436 return properties()->get(index); 1437 } 1438 } 1439 1440 1441 Object* JSObject::FastPropertyAtPut(int index, Object* value) { 1442 // Adjust for the number of properties stored in the object. 1443 index -= map()->inobject_properties(); 1444 if (index < 0) { 1445 int offset = map()->instance_size() + (index * kPointerSize); 1446 WRITE_FIELD(this, offset, value); 1447 WRITE_BARRIER(this, offset); 1448 } else { 1449 ASSERT(index < properties()->length()); 1450 properties()->set(index, value); 1451 } 1452 return value; 1453 } 1454 1455 1456 int JSObject::GetInObjectPropertyOffset(int index) { 1457 // Adjust for the number of properties stored in the object. 1458 index -= map()->inobject_properties(); 1459 ASSERT(index < 0); 1460 return map()->instance_size() + (index * kPointerSize); 1461 } 1462 1463 1464 Object* JSObject::InObjectPropertyAt(int index) { 1465 // Adjust for the number of properties stored in the object. 1466 index -= map()->inobject_properties(); 1467 ASSERT(index < 0); 1468 int offset = map()->instance_size() + (index * kPointerSize); 1469 return READ_FIELD(this, offset); 1470 } 1471 1472 1473 Object* JSObject::InObjectPropertyAtPut(int index, 1474 Object* value, 1475 WriteBarrierMode mode) { 1476 // Adjust for the number of properties stored in the object. 1477 index -= map()->inobject_properties(); 1478 ASSERT(index < 0); 1479 int offset = map()->instance_size() + (index * kPointerSize); 1480 WRITE_FIELD(this, offset, value); 1481 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); 1482 return value; 1483 } 1484 1485 1486 1487 void JSObject::InitializeBody(int object_size, Object* value) { 1488 ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value)); 1489 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 1490 WRITE_FIELD(this, offset, value); 1491 } 1492 } 1493 1494 1495 bool JSObject::HasFastProperties() { 1496 return !properties()->IsDictionary(); 1497 } 1498 1499 1500 int JSObject::MaxFastProperties() { 1501 // Allow extra fast properties if the object has more than 1502 // kMaxFastProperties in-object properties. When this is the case, 1503 // it is very unlikely that the object is being used as a dictionary 1504 // and there is a good chance that allowing more map transitions 1505 // will be worth it. 1506 return Max(map()->inobject_properties(), kMaxFastProperties); 1507 } 1508 1509 1510 void Struct::InitializeBody(int object_size) { 1511 Object* value = GetHeap()->undefined_value(); 1512 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 1513 WRITE_FIELD(this, offset, value); 1514 } 1515 } 1516 1517 1518 bool Object::ToArrayIndex(uint32_t* index) { 1519 if (IsSmi()) { 1520 int value = Smi::cast(this)->value(); 1521 if (value < 0) return false; 1522 *index = value; 1523 return true; 1524 } 1525 if (IsHeapNumber()) { 1526 double value = HeapNumber::cast(this)->value(); 1527 uint32_t uint_value = static_cast<uint32_t>(value); 1528 if (value == static_cast<double>(uint_value)) { 1529 *index = uint_value; 1530 return true; 1531 } 1532 } 1533 return false; 1534 } 1535 1536 1537 bool Object::IsStringObjectWithCharacterAt(uint32_t index) { 1538 if (!this->IsJSValue()) return false; 1539 1540 JSValue* js_value = JSValue::cast(this); 1541 if (!js_value->value()->IsString()) return false; 1542 1543 String* str = String::cast(js_value->value()); 1544 if (index >= (uint32_t)str->length()) return false; 1545 1546 return true; 1547 } 1548 1549 1550 Object* FixedArray::get(int index) { 1551 ASSERT(index >= 0 && index < this->length()); 1552 return READ_FIELD(this, kHeaderSize + index * kPointerSize); 1553 } 1554 1555 1556 void FixedArray::set(int index, Smi* value) { 1557 ASSERT(map() != HEAP->fixed_cow_array_map()); 1558 ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); 1559 int offset = kHeaderSize + index * kPointerSize; 1560 WRITE_FIELD(this, offset, value); 1561 } 1562 1563 1564 void FixedArray::set(int index, Object* value) { 1565 ASSERT(map() != HEAP->fixed_cow_array_map()); 1566 ASSERT(index >= 0 && index < this->length()); 1567 int offset = kHeaderSize + index * kPointerSize; 1568 WRITE_FIELD(this, offset, value); 1569 WRITE_BARRIER(this, offset); 1570 } 1571 1572 1573 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) { 1574 if (GetHeap()->InNewSpace(this)) return SKIP_WRITE_BARRIER; 1575 return UPDATE_WRITE_BARRIER; 1576 } 1577 1578 1579 void FixedArray::set(int index, 1580 Object* value, 1581 WriteBarrierMode mode) { 1582 ASSERT(map() != HEAP->fixed_cow_array_map()); 1583 ASSERT(index >= 0 && index < this->length()); 1584 int offset = kHeaderSize + index * kPointerSize; 1585 WRITE_FIELD(this, offset, value); 1586 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, mode); 1587 } 1588 1589 1590 void FixedArray::fast_set(FixedArray* array, int index, Object* value) { 1591 ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map()); 1592 ASSERT(index >= 0 && index < array->length()); 1593 ASSERT(!HEAP->InNewSpace(value)); 1594 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value); 1595 } 1596 1597 1598 void FixedArray::set_undefined(int index) { 1599 ASSERT(map() != HEAP->fixed_cow_array_map()); 1600 set_undefined(GetHeap(), index); 1601 } 1602 1603 1604 void FixedArray::set_undefined(Heap* heap, int index) { 1605 ASSERT(index >= 0 && index < this->length()); 1606 ASSERT(!heap->InNewSpace(heap->undefined_value())); 1607 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, 1608 heap->undefined_value()); 1609 } 1610 1611 1612 void FixedArray::set_null(int index) { 1613 set_null(GetHeap(), index); 1614 } 1615 1616 1617 void FixedArray::set_null(Heap* heap, int index) { 1618 ASSERT(index >= 0 && index < this->length()); 1619 ASSERT(!heap->InNewSpace(heap->null_value())); 1620 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value()); 1621 } 1622 1623 1624 void FixedArray::set_the_hole(int index) { 1625 ASSERT(map() != HEAP->fixed_cow_array_map()); 1626 ASSERT(index >= 0 && index < this->length()); 1627 ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value())); 1628 WRITE_FIELD(this, 1629 kHeaderSize + index * kPointerSize, 1630 GetHeap()->the_hole_value()); 1631 } 1632 1633 1634 void FixedArray::set_unchecked(int index, Smi* value) { 1635 ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); 1636 int offset = kHeaderSize + index * kPointerSize; 1637 WRITE_FIELD(this, offset, value); 1638 } 1639 1640 1641 void FixedArray::set_unchecked(Heap* heap, 1642 int index, 1643 Object* value, 1644 WriteBarrierMode mode) { 1645 int offset = kHeaderSize + index * kPointerSize; 1646 WRITE_FIELD(this, offset, value); 1647 CONDITIONAL_WRITE_BARRIER(heap, this, offset, mode); 1648 } 1649 1650 1651 void FixedArray::set_null_unchecked(Heap* heap, int index) { 1652 ASSERT(index >= 0 && index < this->length()); 1653 ASSERT(!HEAP->InNewSpace(heap->null_value())); 1654 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value()); 1655 } 1656 1657 1658 Object** FixedArray::data_start() { 1659 return HeapObject::RawField(this, kHeaderSize); 1660 } 1661 1662 1663 bool DescriptorArray::IsEmpty() { 1664 ASSERT(this->length() > kFirstIndex || 1665 this == HEAP->empty_descriptor_array()); 1666 return length() <= kFirstIndex; 1667 } 1668 1669 1670 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { 1671 Object* tmp = array->get(first); 1672 fast_set(array, first, array->get(second)); 1673 fast_set(array, second, tmp); 1674 } 1675 1676 1677 int DescriptorArray::Search(String* name) { 1678 SLOW_ASSERT(IsSortedNoDuplicates()); 1679 1680 // Check for empty descriptor array. 1681 int nof = number_of_descriptors(); 1682 if (nof == 0) return kNotFound; 1683 1684 // Fast case: do linear search for small arrays. 1685 const int kMaxElementsForLinearSearch = 8; 1686 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { 1687 return LinearSearch(name, nof); 1688 } 1689 1690 // Slow case: perform binary search. 1691 return BinarySearch(name, 0, nof - 1); 1692 } 1693 1694 1695 int DescriptorArray::SearchWithCache(String* name) { 1696 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name); 1697 if (number == DescriptorLookupCache::kAbsent) { 1698 number = Search(name); 1699 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number); 1700 } 1701 return number; 1702 } 1703 1704 1705 String* DescriptorArray::GetKey(int descriptor_number) { 1706 ASSERT(descriptor_number < number_of_descriptors()); 1707 return String::cast(get(ToKeyIndex(descriptor_number))); 1708 } 1709 1710 1711 Object* DescriptorArray::GetValue(int descriptor_number) { 1712 ASSERT(descriptor_number < number_of_descriptors()); 1713 return GetContentArray()->get(ToValueIndex(descriptor_number)); 1714 } 1715 1716 1717 Smi* DescriptorArray::GetDetails(int descriptor_number) { 1718 ASSERT(descriptor_number < number_of_descriptors()); 1719 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number))); 1720 } 1721 1722 1723 PropertyType DescriptorArray::GetType(int descriptor_number) { 1724 ASSERT(descriptor_number < number_of_descriptors()); 1725 return PropertyDetails(GetDetails(descriptor_number)).type(); 1726 } 1727 1728 1729 int DescriptorArray::GetFieldIndex(int descriptor_number) { 1730 return Descriptor::IndexFromValue(GetValue(descriptor_number)); 1731 } 1732 1733 1734 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { 1735 return JSFunction::cast(GetValue(descriptor_number)); 1736 } 1737 1738 1739 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { 1740 ASSERT(GetType(descriptor_number) == CALLBACKS); 1741 return GetValue(descriptor_number); 1742 } 1743 1744 1745 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { 1746 ASSERT(GetType(descriptor_number) == CALLBACKS); 1747 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number)); 1748 return reinterpret_cast<AccessorDescriptor*>(p->proxy()); 1749 } 1750 1751 1752 bool DescriptorArray::IsProperty(int descriptor_number) { 1753 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE; 1754 } 1755 1756 1757 bool DescriptorArray::IsTransition(int descriptor_number) { 1758 PropertyType t = GetType(descriptor_number); 1759 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION || 1760 t == EXTERNAL_ARRAY_TRANSITION; 1761 } 1762 1763 1764 bool DescriptorArray::IsNullDescriptor(int descriptor_number) { 1765 return GetType(descriptor_number) == NULL_DESCRIPTOR; 1766 } 1767 1768 1769 bool DescriptorArray::IsDontEnum(int descriptor_number) { 1770 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum(); 1771 } 1772 1773 1774 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { 1775 desc->Init(GetKey(descriptor_number), 1776 GetValue(descriptor_number), 1777 PropertyDetails(GetDetails(descriptor_number))); 1778 } 1779 1780 1781 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { 1782 // Range check. 1783 ASSERT(descriptor_number < number_of_descriptors()); 1784 1785 // Make sure none of the elements in desc are in new space. 1786 ASSERT(!HEAP->InNewSpace(desc->GetKey())); 1787 ASSERT(!HEAP->InNewSpace(desc->GetValue())); 1788 1789 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey()); 1790 FixedArray* content_array = GetContentArray(); 1791 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue()); 1792 fast_set(content_array, ToDetailsIndex(descriptor_number), 1793 desc->GetDetails().AsSmi()); 1794 } 1795 1796 1797 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) { 1798 Descriptor desc; 1799 src->Get(src_index, &desc); 1800 Set(index, &desc); 1801 } 1802 1803 1804 void DescriptorArray::Swap(int first, int second) { 1805 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second)); 1806 FixedArray* content_array = GetContentArray(); 1807 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second)); 1808 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second)); 1809 } 1810 1811 1812 template<typename Shape, typename Key> 1813 int HashTable<Shape, Key>::FindEntry(Key key) { 1814 return FindEntry(GetIsolate(), key); 1815 } 1816 1817 1818 // Find entry for key otherwise return kNotFound. 1819 template<typename Shape, typename Key> 1820 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) { 1821 uint32_t capacity = Capacity(); 1822 uint32_t entry = FirstProbe(Shape::Hash(key), capacity); 1823 uint32_t count = 1; 1824 // EnsureCapacity will guarantee the hash table is never full. 1825 while (true) { 1826 Object* element = KeyAt(entry); 1827 if (element == isolate->heap()->undefined_value()) break; // Empty entry. 1828 if (element != isolate->heap()->null_value() && 1829 Shape::IsMatch(key, element)) return entry; 1830 entry = NextProbe(entry, count++, capacity); 1831 } 1832 return kNotFound; 1833 } 1834 1835 1836 bool NumberDictionary::requires_slow_elements() { 1837 Object* max_index_object = get(kMaxNumberKeyIndex); 1838 if (!max_index_object->IsSmi()) return false; 1839 return 0 != 1840 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); 1841 } 1842 1843 uint32_t NumberDictionary::max_number_key() { 1844 ASSERT(!requires_slow_elements()); 1845 Object* max_index_object = get(kMaxNumberKeyIndex); 1846 if (!max_index_object->IsSmi()) return 0; 1847 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); 1848 return value >> kRequiresSlowElementsTagSize; 1849 } 1850 1851 void NumberDictionary::set_requires_slow_elements() { 1852 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); 1853 } 1854 1855 1856 // ------------------------------------ 1857 // Cast operations 1858 1859 1860 CAST_ACCESSOR(FixedArray) 1861 CAST_ACCESSOR(DescriptorArray) 1862 CAST_ACCESSOR(DeoptimizationInputData) 1863 CAST_ACCESSOR(DeoptimizationOutputData) 1864 CAST_ACCESSOR(SymbolTable) 1865 CAST_ACCESSOR(JSFunctionResultCache) 1866 CAST_ACCESSOR(NormalizedMapCache) 1867 CAST_ACCESSOR(CompilationCacheTable) 1868 CAST_ACCESSOR(CodeCacheHashTable) 1869 CAST_ACCESSOR(MapCache) 1870 CAST_ACCESSOR(String) 1871 CAST_ACCESSOR(SeqString) 1872 CAST_ACCESSOR(SeqAsciiString) 1873 CAST_ACCESSOR(SeqTwoByteString) 1874 CAST_ACCESSOR(ConsString) 1875 CAST_ACCESSOR(ExternalString) 1876 CAST_ACCESSOR(ExternalAsciiString) 1877 CAST_ACCESSOR(ExternalTwoByteString) 1878 CAST_ACCESSOR(JSObject) 1879 CAST_ACCESSOR(Smi) 1880 CAST_ACCESSOR(HeapObject) 1881 CAST_ACCESSOR(HeapNumber) 1882 CAST_ACCESSOR(Oddball) 1883 CAST_ACCESSOR(JSGlobalPropertyCell) 1884 CAST_ACCESSOR(SharedFunctionInfo) 1885 CAST_ACCESSOR(Map) 1886 CAST_ACCESSOR(JSFunction) 1887 CAST_ACCESSOR(GlobalObject) 1888 CAST_ACCESSOR(JSGlobalProxy) 1889 CAST_ACCESSOR(JSGlobalObject) 1890 CAST_ACCESSOR(JSBuiltinsObject) 1891 CAST_ACCESSOR(Code) 1892 CAST_ACCESSOR(JSArray) 1893 CAST_ACCESSOR(JSRegExp) 1894 CAST_ACCESSOR(Proxy) 1895 CAST_ACCESSOR(ByteArray) 1896 CAST_ACCESSOR(ExternalArray) 1897 CAST_ACCESSOR(ExternalByteArray) 1898 CAST_ACCESSOR(ExternalUnsignedByteArray) 1899 CAST_ACCESSOR(ExternalShortArray) 1900 CAST_ACCESSOR(ExternalUnsignedShortArray) 1901 CAST_ACCESSOR(ExternalIntArray) 1902 CAST_ACCESSOR(ExternalUnsignedIntArray) 1903 CAST_ACCESSOR(ExternalFloatArray) 1904 CAST_ACCESSOR(ExternalPixelArray) 1905 CAST_ACCESSOR(Struct) 1906 1907 1908 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) 1909 STRUCT_LIST(MAKE_STRUCT_CAST) 1910 #undef MAKE_STRUCT_CAST 1911 1912 1913 template <typename Shape, typename Key> 1914 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) { 1915 ASSERT(obj->IsHashTable()); 1916 return reinterpret_cast<HashTable*>(obj); 1917 } 1918 1919 1920 SMI_ACCESSORS(FixedArray, length, kLengthOffset) 1921 SMI_ACCESSORS(ByteArray, length, kLengthOffset) 1922 1923 INT_ACCESSORS(ExternalArray, length, kLengthOffset) 1924 1925 1926 SMI_ACCESSORS(String, length, kLengthOffset) 1927 1928 1929 uint32_t String::hash_field() { 1930 return READ_UINT32_FIELD(this, kHashFieldOffset); 1931 } 1932 1933 1934 void String::set_hash_field(uint32_t value) { 1935 WRITE_UINT32_FIELD(this, kHashFieldOffset, value); 1936 #if V8_HOST_ARCH_64_BIT 1937 WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0); 1938 #endif 1939 } 1940 1941 1942 bool String::Equals(String* other) { 1943 if (other == this) return true; 1944 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) { 1945 return false; 1946 } 1947 return SlowEquals(other); 1948 } 1949 1950 1951 MaybeObject* String::TryFlatten(PretenureFlag pretenure) { 1952 if (!StringShape(this).IsCons()) return this; 1953 ConsString* cons = ConsString::cast(this); 1954 if (cons->second()->length() == 0) return cons->first(); 1955 return SlowTryFlatten(pretenure); 1956 } 1957 1958 1959 String* String::TryFlattenGetString(PretenureFlag pretenure) { 1960 MaybeObject* flat = TryFlatten(pretenure); 1961 Object* successfully_flattened; 1962 if (flat->ToObject(&successfully_flattened)) { 1963 return String::cast(successfully_flattened); 1964 } 1965 return this; 1966 } 1967 1968 1969 uint16_t String::Get(int index) { 1970 ASSERT(index >= 0 && index < length()); 1971 switch (StringShape(this).full_representation_tag()) { 1972 case kSeqStringTag | kAsciiStringTag: 1973 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); 1974 case kSeqStringTag | kTwoByteStringTag: 1975 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); 1976 case kConsStringTag | kAsciiStringTag: 1977 case kConsStringTag | kTwoByteStringTag: 1978 return ConsString::cast(this)->ConsStringGet(index); 1979 case kExternalStringTag | kAsciiStringTag: 1980 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); 1981 case kExternalStringTag | kTwoByteStringTag: 1982 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); 1983 default: 1984 break; 1985 } 1986 1987 UNREACHABLE(); 1988 return 0; 1989 } 1990 1991 1992 void String::Set(int index, uint16_t value) { 1993 ASSERT(index >= 0 && index < length()); 1994 ASSERT(StringShape(this).IsSequential()); 1995 1996 return this->IsAsciiRepresentation() 1997 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) 1998 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); 1999 } 2000 2001 2002 bool String::IsFlat() { 2003 switch (StringShape(this).representation_tag()) { 2004 case kConsStringTag: { 2005 String* second = ConsString::cast(this)->second(); 2006 // Only flattened strings have second part empty. 2007 return second->length() == 0; 2008 } 2009 default: 2010 return true; 2011 } 2012 } 2013 2014 2015 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { 2016 ASSERT(index >= 0 && index < length()); 2017 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 2018 } 2019 2020 2021 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) { 2022 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode); 2023 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, 2024 static_cast<byte>(value)); 2025 } 2026 2027 2028 Address SeqAsciiString::GetCharsAddress() { 2029 return FIELD_ADDR(this, kHeaderSize); 2030 } 2031 2032 2033 char* SeqAsciiString::GetChars() { 2034 return reinterpret_cast<char*>(GetCharsAddress()); 2035 } 2036 2037 2038 Address SeqTwoByteString::GetCharsAddress() { 2039 return FIELD_ADDR(this, kHeaderSize); 2040 } 2041 2042 2043 uc16* SeqTwoByteString::GetChars() { 2044 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize)); 2045 } 2046 2047 2048 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) { 2049 ASSERT(index >= 0 && index < length()); 2050 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); 2051 } 2052 2053 2054 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { 2055 ASSERT(index >= 0 && index < length()); 2056 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); 2057 } 2058 2059 2060 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { 2061 return SizeFor(length()); 2062 } 2063 2064 2065 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { 2066 return SizeFor(length()); 2067 } 2068 2069 2070 String* ConsString::first() { 2071 return String::cast(READ_FIELD(this, kFirstOffset)); 2072 } 2073 2074 2075 Object* ConsString::unchecked_first() { 2076 return READ_FIELD(this, kFirstOffset); 2077 } 2078 2079 2080 void ConsString::set_first(String* value, WriteBarrierMode mode) { 2081 WRITE_FIELD(this, kFirstOffset, value); 2082 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, mode); 2083 } 2084 2085 2086 String* ConsString::second() { 2087 return String::cast(READ_FIELD(this, kSecondOffset)); 2088 } 2089 2090 2091 Object* ConsString::unchecked_second() { 2092 return READ_FIELD(this, kSecondOffset); 2093 } 2094 2095 2096 void ConsString::set_second(String* value, WriteBarrierMode mode) { 2097 WRITE_FIELD(this, kSecondOffset, value); 2098 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, mode); 2099 } 2100 2101 2102 ExternalAsciiString::Resource* ExternalAsciiString::resource() { 2103 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 2104 } 2105 2106 2107 void ExternalAsciiString::set_resource( 2108 ExternalAsciiString::Resource* resource) { 2109 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource; 2110 } 2111 2112 2113 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() { 2114 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 2115 } 2116 2117 2118 void ExternalTwoByteString::set_resource( 2119 ExternalTwoByteString::Resource* resource) { 2120 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource; 2121 } 2122 2123 2124 void JSFunctionResultCache::MakeZeroSize() { 2125 set_finger_index(kEntriesIndex); 2126 set_size(kEntriesIndex); 2127 } 2128 2129 2130 void JSFunctionResultCache::Clear() { 2131 int cache_size = size(); 2132 Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex)); 2133 MemsetPointer(entries_start, 2134 GetHeap()->the_hole_value(), 2135 cache_size - kEntriesIndex); 2136 MakeZeroSize(); 2137 } 2138 2139 2140 int JSFunctionResultCache::size() { 2141 return Smi::cast(get(kCacheSizeIndex))->value(); 2142 } 2143 2144 2145 void JSFunctionResultCache::set_size(int size) { 2146 set(kCacheSizeIndex, Smi::FromInt(size)); 2147 } 2148 2149 2150 int JSFunctionResultCache::finger_index() { 2151 return Smi::cast(get(kFingerIndex))->value(); 2152 } 2153 2154 2155 void JSFunctionResultCache::set_finger_index(int finger_index) { 2156 set(kFingerIndex, Smi::FromInt(finger_index)); 2157 } 2158 2159 2160 byte ByteArray::get(int index) { 2161 ASSERT(index >= 0 && index < this->length()); 2162 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 2163 } 2164 2165 2166 void ByteArray::set(int index, byte value) { 2167 ASSERT(index >= 0 && index < this->length()); 2168 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 2169 } 2170 2171 2172 int ByteArray::get_int(int index) { 2173 ASSERT(index >= 0 && (index * kIntSize) < this->length()); 2174 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize); 2175 } 2176 2177 2178 ByteArray* ByteArray::FromDataStartAddress(Address address) { 2179 ASSERT_TAG_ALIGNED(address); 2180 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag); 2181 } 2182 2183 2184 Address ByteArray::GetDataStartAddress() { 2185 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 2186 } 2187 2188 2189 uint8_t* ExternalPixelArray::external_pixel_pointer() { 2190 return reinterpret_cast<uint8_t*>(external_pointer()); 2191 } 2192 2193 2194 uint8_t ExternalPixelArray::get(int index) { 2195 ASSERT((index >= 0) && (index < this->length())); 2196 uint8_t* ptr = external_pixel_pointer(); 2197 return ptr[index]; 2198 } 2199 2200 2201 void ExternalPixelArray::set(int index, uint8_t value) { 2202 ASSERT((index >= 0) && (index < this->length())); 2203 uint8_t* ptr = external_pixel_pointer(); 2204 ptr[index] = value; 2205 } 2206 2207 2208 void* ExternalArray::external_pointer() { 2209 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset); 2210 return reinterpret_cast<void*>(ptr); 2211 } 2212 2213 2214 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) { 2215 intptr_t ptr = reinterpret_cast<intptr_t>(value); 2216 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr); 2217 } 2218 2219 2220 int8_t ExternalByteArray::get(int index) { 2221 ASSERT((index >= 0) && (index < this->length())); 2222 int8_t* ptr = static_cast<int8_t*>(external_pointer()); 2223 return ptr[index]; 2224 } 2225 2226 2227 void ExternalByteArray::set(int index, int8_t value) { 2228 ASSERT((index >= 0) && (index < this->length())); 2229 int8_t* ptr = static_cast<int8_t*>(external_pointer()); 2230 ptr[index] = value; 2231 } 2232 2233 2234 uint8_t ExternalUnsignedByteArray::get(int index) { 2235 ASSERT((index >= 0) && (index < this->length())); 2236 uint8_t* ptr = static_cast<uint8_t*>(external_pointer()); 2237 return ptr[index]; 2238 } 2239 2240 2241 void ExternalUnsignedByteArray::set(int index, uint8_t value) { 2242 ASSERT((index >= 0) && (index < this->length())); 2243 uint8_t* ptr = static_cast<uint8_t*>(external_pointer()); 2244 ptr[index] = value; 2245 } 2246 2247 2248 int16_t ExternalShortArray::get(int index) { 2249 ASSERT((index >= 0) && (index < this->length())); 2250 int16_t* ptr = static_cast<int16_t*>(external_pointer()); 2251 return ptr[index]; 2252 } 2253 2254 2255 void ExternalShortArray::set(int index, int16_t value) { 2256 ASSERT((index >= 0) && (index < this->length())); 2257 int16_t* ptr = static_cast<int16_t*>(external_pointer()); 2258 ptr[index] = value; 2259 } 2260 2261 2262 uint16_t ExternalUnsignedShortArray::get(int index) { 2263 ASSERT((index >= 0) && (index < this->length())); 2264 uint16_t* ptr = static_cast<uint16_t*>(external_pointer()); 2265 return ptr[index]; 2266 } 2267 2268 2269 void ExternalUnsignedShortArray::set(int index, uint16_t value) { 2270 ASSERT((index >= 0) && (index < this->length())); 2271 uint16_t* ptr = static_cast<uint16_t*>(external_pointer()); 2272 ptr[index] = value; 2273 } 2274 2275 2276 int32_t ExternalIntArray::get(int index) { 2277 ASSERT((index >= 0) && (index < this->length())); 2278 int32_t* ptr = static_cast<int32_t*>(external_pointer()); 2279 return ptr[index]; 2280 } 2281 2282 2283 void ExternalIntArray::set(int index, int32_t value) { 2284 ASSERT((index >= 0) && (index < this->length())); 2285 int32_t* ptr = static_cast<int32_t*>(external_pointer()); 2286 ptr[index] = value; 2287 } 2288 2289 2290 uint32_t ExternalUnsignedIntArray::get(int index) { 2291 ASSERT((index >= 0) && (index < this->length())); 2292 uint32_t* ptr = static_cast<uint32_t*>(external_pointer()); 2293 return ptr[index]; 2294 } 2295 2296 2297 void ExternalUnsignedIntArray::set(int index, uint32_t value) { 2298 ASSERT((index >= 0) && (index < this->length())); 2299 uint32_t* ptr = static_cast<uint32_t*>(external_pointer()); 2300 ptr[index] = value; 2301 } 2302 2303 2304 float ExternalFloatArray::get(int index) { 2305 ASSERT((index >= 0) && (index < this->length())); 2306 float* ptr = static_cast<float*>(external_pointer()); 2307 return ptr[index]; 2308 } 2309 2310 2311 void ExternalFloatArray::set(int index, float value) { 2312 ASSERT((index >= 0) && (index < this->length())); 2313 float* ptr = static_cast<float*>(external_pointer()); 2314 ptr[index] = value; 2315 } 2316 2317 2318 int Map::visitor_id() { 2319 return READ_BYTE_FIELD(this, kVisitorIdOffset); 2320 } 2321 2322 2323 void Map::set_visitor_id(int id) { 2324 ASSERT(0 <= id && id < 256); 2325 WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id)); 2326 } 2327 2328 2329 int Map::instance_size() { 2330 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2; 2331 } 2332 2333 2334 int Map::inobject_properties() { 2335 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset); 2336 } 2337 2338 2339 int Map::pre_allocated_property_fields() { 2340 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset); 2341 } 2342 2343 2344 int HeapObject::SizeFromMap(Map* map) { 2345 int instance_size = map->instance_size(); 2346 if (instance_size != kVariableSizeSentinel) return instance_size; 2347 // We can ignore the "symbol" bit becase it is only set for symbols 2348 // and implies a string type. 2349 int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask; 2350 // Only inline the most frequent cases. 2351 if (instance_type == FIXED_ARRAY_TYPE) { 2352 return FixedArray::BodyDescriptor::SizeOf(map, this); 2353 } 2354 if (instance_type == ASCII_STRING_TYPE) { 2355 return SeqAsciiString::SizeFor( 2356 reinterpret_cast<SeqAsciiString*>(this)->length()); 2357 } 2358 if (instance_type == BYTE_ARRAY_TYPE) { 2359 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 2360 } 2361 if (instance_type == STRING_TYPE) { 2362 return SeqTwoByteString::SizeFor( 2363 reinterpret_cast<SeqTwoByteString*>(this)->length()); 2364 } 2365 ASSERT(instance_type == CODE_TYPE); 2366 return reinterpret_cast<Code*>(this)->CodeSize(); 2367 } 2368 2369 2370 void Map::set_instance_size(int value) { 2371 ASSERT_EQ(0, value & (kPointerSize - 1)); 2372 value >>= kPointerSizeLog2; 2373 ASSERT(0 <= value && value < 256); 2374 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value)); 2375 } 2376 2377 2378 void Map::set_inobject_properties(int value) { 2379 ASSERT(0 <= value && value < 256); 2380 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value)); 2381 } 2382 2383 2384 void Map::set_pre_allocated_property_fields(int value) { 2385 ASSERT(0 <= value && value < 256); 2386 WRITE_BYTE_FIELD(this, 2387 kPreAllocatedPropertyFieldsOffset, 2388 static_cast<byte>(value)); 2389 } 2390 2391 2392 InstanceType Map::instance_type() { 2393 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset)); 2394 } 2395 2396 2397 void Map::set_instance_type(InstanceType value) { 2398 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value); 2399 } 2400 2401 2402 int Map::unused_property_fields() { 2403 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset); 2404 } 2405 2406 2407 void Map::set_unused_property_fields(int value) { 2408 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255)); 2409 } 2410 2411 2412 byte Map::bit_field() { 2413 return READ_BYTE_FIELD(this, kBitFieldOffset); 2414 } 2415 2416 2417 void Map::set_bit_field(byte value) { 2418 WRITE_BYTE_FIELD(this, kBitFieldOffset, value); 2419 } 2420 2421 2422 byte Map::bit_field2() { 2423 return READ_BYTE_FIELD(this, kBitField2Offset); 2424 } 2425 2426 2427 void Map::set_bit_field2(byte value) { 2428 WRITE_BYTE_FIELD(this, kBitField2Offset, value); 2429 } 2430 2431 2432 void Map::set_non_instance_prototype(bool value) { 2433 if (value) { 2434 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); 2435 } else { 2436 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype)); 2437 } 2438 } 2439 2440 2441 bool Map::has_non_instance_prototype() { 2442 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; 2443 } 2444 2445 2446 void Map::set_function_with_prototype(bool value) { 2447 if (value) { 2448 set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype)); 2449 } else { 2450 set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype)); 2451 } 2452 } 2453 2454 2455 bool Map::function_with_prototype() { 2456 return ((1 << kFunctionWithPrototype) & bit_field2()) != 0; 2457 } 2458 2459 2460 void Map::set_is_access_check_needed(bool access_check_needed) { 2461 if (access_check_needed) { 2462 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); 2463 } else { 2464 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); 2465 } 2466 } 2467 2468 2469 bool Map::is_access_check_needed() { 2470 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0; 2471 } 2472 2473 2474 void Map::set_is_extensible(bool value) { 2475 if (value) { 2476 set_bit_field2(bit_field2() | (1 << kIsExtensible)); 2477 } else { 2478 set_bit_field2(bit_field2() & ~(1 << kIsExtensible)); 2479 } 2480 } 2481 2482 bool Map::is_extensible() { 2483 return ((1 << kIsExtensible) & bit_field2()) != 0; 2484 } 2485 2486 2487 void Map::set_attached_to_shared_function_info(bool value) { 2488 if (value) { 2489 set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo)); 2490 } else { 2491 set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo)); 2492 } 2493 } 2494 2495 bool Map::attached_to_shared_function_info() { 2496 return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0; 2497 } 2498 2499 2500 void Map::set_is_shared(bool value) { 2501 if (value) { 2502 set_bit_field2(bit_field2() | (1 << kIsShared)); 2503 } else { 2504 set_bit_field2(bit_field2() & ~(1 << kIsShared)); 2505 } 2506 } 2507 2508 bool Map::is_shared() { 2509 return ((1 << kIsShared) & bit_field2()) != 0; 2510 } 2511 2512 2513 JSFunction* Map::unchecked_constructor() { 2514 return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset)); 2515 } 2516 2517 2518 FixedArray* Map::unchecked_prototype_transitions() { 2519 return reinterpret_cast<FixedArray*>( 2520 READ_FIELD(this, kPrototypeTransitionsOffset)); 2521 } 2522 2523 2524 Code::Flags Code::flags() { 2525 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset)); 2526 } 2527 2528 2529 void Code::set_flags(Code::Flags flags) { 2530 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1); 2531 // Make sure that all call stubs have an arguments count. 2532 ASSERT((ExtractKindFromFlags(flags) != CALL_IC && 2533 ExtractKindFromFlags(flags) != KEYED_CALL_IC) || 2534 ExtractArgumentsCountFromFlags(flags) >= 0); 2535 WRITE_INT_FIELD(this, kFlagsOffset, flags); 2536 } 2537 2538 2539 Code::Kind Code::kind() { 2540 return ExtractKindFromFlags(flags()); 2541 } 2542 2543 2544 InLoopFlag Code::ic_in_loop() { 2545 return ExtractICInLoopFromFlags(flags()); 2546 } 2547 2548 2549 InlineCacheState Code::ic_state() { 2550 InlineCacheState result = ExtractICStateFromFlags(flags()); 2551 // Only allow uninitialized or debugger states for non-IC code 2552 // objects. This is used in the debugger to determine whether or not 2553 // a call to code object has been replaced with a debug break call. 2554 ASSERT(is_inline_cache_stub() || 2555 result == UNINITIALIZED || 2556 result == DEBUG_BREAK || 2557 result == DEBUG_PREPARE_STEP_IN); 2558 return result; 2559 } 2560 2561 2562 Code::ExtraICState Code::extra_ic_state() { 2563 ASSERT(is_inline_cache_stub()); 2564 return ExtractExtraICStateFromFlags(flags()); 2565 } 2566 2567 2568 PropertyType Code::type() { 2569 ASSERT(ic_state() == MONOMORPHIC); 2570 return ExtractTypeFromFlags(flags()); 2571 } 2572 2573 2574 int Code::arguments_count() { 2575 ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB); 2576 return ExtractArgumentsCountFromFlags(flags()); 2577 } 2578 2579 2580 int Code::major_key() { 2581 ASSERT(kind() == STUB || 2582 kind() == TYPE_RECORDING_BINARY_OP_IC || 2583 kind() == COMPARE_IC); 2584 return READ_BYTE_FIELD(this, kStubMajorKeyOffset); 2585 } 2586 2587 2588 void Code::set_major_key(int major) { 2589 ASSERT(kind() == STUB || 2590 kind() == TYPE_RECORDING_BINARY_OP_IC || 2591 kind() == COMPARE_IC); 2592 ASSERT(0 <= major && major < 256); 2593 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major); 2594 } 2595 2596 2597 bool Code::optimizable() { 2598 ASSERT(kind() == FUNCTION); 2599 return READ_BYTE_FIELD(this, kOptimizableOffset) == 1; 2600 } 2601 2602 2603 void Code::set_optimizable(bool value) { 2604 ASSERT(kind() == FUNCTION); 2605 WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0); 2606 } 2607 2608 2609 bool Code::has_deoptimization_support() { 2610 ASSERT(kind() == FUNCTION); 2611 return READ_BYTE_FIELD(this, kHasDeoptimizationSupportOffset) == 1; 2612 } 2613 2614 2615 void Code::set_has_deoptimization_support(bool value) { 2616 ASSERT(kind() == FUNCTION); 2617 WRITE_BYTE_FIELD(this, kHasDeoptimizationSupportOffset, value ? 1 : 0); 2618 } 2619 2620 2621 int Code::allow_osr_at_loop_nesting_level() { 2622 ASSERT(kind() == FUNCTION); 2623 return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset); 2624 } 2625 2626 2627 void Code::set_allow_osr_at_loop_nesting_level(int level) { 2628 ASSERT(kind() == FUNCTION); 2629 ASSERT(level >= 0 && level <= kMaxLoopNestingMarker); 2630 WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level); 2631 } 2632 2633 2634 unsigned Code::stack_slots() { 2635 ASSERT(kind() == OPTIMIZED_FUNCTION); 2636 return READ_UINT32_FIELD(this, kStackSlotsOffset); 2637 } 2638 2639 2640 void Code::set_stack_slots(unsigned slots) { 2641 ASSERT(kind() == OPTIMIZED_FUNCTION); 2642 WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots); 2643 } 2644 2645 2646 unsigned Code::safepoint_table_offset() { 2647 ASSERT(kind() == OPTIMIZED_FUNCTION); 2648 return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset); 2649 } 2650 2651 2652 void Code::set_safepoint_table_offset(unsigned offset) { 2653 ASSERT(kind() == OPTIMIZED_FUNCTION); 2654 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize))); 2655 WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset); 2656 } 2657 2658 2659 unsigned Code::stack_check_table_offset() { 2660 ASSERT(kind() == FUNCTION); 2661 return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset); 2662 } 2663 2664 2665 void Code::set_stack_check_table_offset(unsigned offset) { 2666 ASSERT(kind() == FUNCTION); 2667 ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize))); 2668 WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset); 2669 } 2670 2671 2672 CheckType Code::check_type() { 2673 ASSERT(is_call_stub() || is_keyed_call_stub()); 2674 byte type = READ_BYTE_FIELD(this, kCheckTypeOffset); 2675 return static_cast<CheckType>(type); 2676 } 2677 2678 2679 void Code::set_check_type(CheckType value) { 2680 ASSERT(is_call_stub() || is_keyed_call_stub()); 2681 WRITE_BYTE_FIELD(this, kCheckTypeOffset, value); 2682 } 2683 2684 2685 ExternalArrayType Code::external_array_type() { 2686 ASSERT(is_external_array_load_stub() || is_external_array_store_stub()); 2687 byte type = READ_BYTE_FIELD(this, kExternalArrayTypeOffset); 2688 return static_cast<ExternalArrayType>(type); 2689 } 2690 2691 2692 void Code::set_external_array_type(ExternalArrayType value) { 2693 ASSERT(is_external_array_load_stub() || is_external_array_store_stub()); 2694 WRITE_BYTE_FIELD(this, kExternalArrayTypeOffset, value); 2695 } 2696 2697 2698 byte Code::type_recording_binary_op_type() { 2699 ASSERT(is_type_recording_binary_op_stub()); 2700 return READ_BYTE_FIELD(this, kBinaryOpTypeOffset); 2701 } 2702 2703 2704 void Code::set_type_recording_binary_op_type(byte value) { 2705 ASSERT(is_type_recording_binary_op_stub()); 2706 WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value); 2707 } 2708 2709 2710 byte Code::type_recording_binary_op_result_type() { 2711 ASSERT(is_type_recording_binary_op_stub()); 2712 return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset); 2713 } 2714 2715 2716 void Code::set_type_recording_binary_op_result_type(byte value) { 2717 ASSERT(is_type_recording_binary_op_stub()); 2718 WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value); 2719 } 2720 2721 2722 byte Code::compare_state() { 2723 ASSERT(is_compare_ic_stub()); 2724 return READ_BYTE_FIELD(this, kCompareStateOffset); 2725 } 2726 2727 2728 void Code::set_compare_state(byte value) { 2729 ASSERT(is_compare_ic_stub()); 2730 WRITE_BYTE_FIELD(this, kCompareStateOffset, value); 2731 } 2732 2733 2734 bool Code::is_inline_cache_stub() { 2735 Kind kind = this->kind(); 2736 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND; 2737 } 2738 2739 2740 Code::Flags Code::ComputeFlags(Kind kind, 2741 InLoopFlag in_loop, 2742 InlineCacheState ic_state, 2743 ExtraICState extra_ic_state, 2744 PropertyType type, 2745 int argc, 2746 InlineCacheHolderFlag holder) { 2747 // Extra IC state is only allowed for monomorphic call IC stubs 2748 // or for store IC stubs. 2749 ASSERT(extra_ic_state == kNoExtraICState || 2750 (kind == CALL_IC && (ic_state == MONOMORPHIC || 2751 ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)) || 2752 (kind == STORE_IC) || 2753 (kind == KEYED_STORE_IC)); 2754 // Compute the bit mask. 2755 int bits = kind << kFlagsKindShift; 2756 if (in_loop) bits |= kFlagsICInLoopMask; 2757 bits |= ic_state << kFlagsICStateShift; 2758 bits |= type << kFlagsTypeShift; 2759 bits |= extra_ic_state << kFlagsExtraICStateShift; 2760 bits |= argc << kFlagsArgumentsCountShift; 2761 if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask; 2762 // Cast to flags and validate result before returning it. 2763 Flags result = static_cast<Flags>(bits); 2764 ASSERT(ExtractKindFromFlags(result) == kind); 2765 ASSERT(ExtractICStateFromFlags(result) == ic_state); 2766 ASSERT(ExtractICInLoopFromFlags(result) == in_loop); 2767 ASSERT(ExtractTypeFromFlags(result) == type); 2768 ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state); 2769 ASSERT(ExtractArgumentsCountFromFlags(result) == argc); 2770 return result; 2771 } 2772 2773 2774 Code::Flags Code::ComputeMonomorphicFlags(Kind kind, 2775 PropertyType type, 2776 ExtraICState extra_ic_state, 2777 InlineCacheHolderFlag holder, 2778 InLoopFlag in_loop, 2779 int argc) { 2780 return ComputeFlags( 2781 kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder); 2782 } 2783 2784 2785 Code::Kind Code::ExtractKindFromFlags(Flags flags) { 2786 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift; 2787 return static_cast<Kind>(bits); 2788 } 2789 2790 2791 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) { 2792 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift; 2793 return static_cast<InlineCacheState>(bits); 2794 } 2795 2796 2797 Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) { 2798 int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift; 2799 return static_cast<ExtraICState>(bits); 2800 } 2801 2802 2803 InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) { 2804 int bits = (flags & kFlagsICInLoopMask); 2805 return bits != 0 ? IN_LOOP : NOT_IN_LOOP; 2806 } 2807 2808 2809 PropertyType Code::ExtractTypeFromFlags(Flags flags) { 2810 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift; 2811 return static_cast<PropertyType>(bits); 2812 } 2813 2814 2815 int Code::ExtractArgumentsCountFromFlags(Flags flags) { 2816 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift; 2817 } 2818 2819 2820 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) { 2821 int bits = (flags & kFlagsCacheInPrototypeMapMask); 2822 return bits != 0 ? PROTOTYPE_MAP : OWN_MAP; 2823 } 2824 2825 2826 Code::Flags Code::RemoveTypeFromFlags(Flags flags) { 2827 int bits = flags & ~kFlagsTypeMask; 2828 return static_cast<Flags>(bits); 2829 } 2830 2831 2832 Code* Code::GetCodeFromTargetAddress(Address address) { 2833 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize); 2834 // GetCodeFromTargetAddress might be called when marking objects during mark 2835 // sweep. reinterpret_cast is therefore used instead of the more appropriate 2836 // Code::cast. Code::cast does not work when the object's map is 2837 // marked. 2838 Code* result = reinterpret_cast<Code*>(code); 2839 return result; 2840 } 2841 2842 2843 Isolate* Map::isolate() { 2844 return heap()->isolate(); 2845 } 2846 2847 2848 Heap* Map::heap() { 2849 // NOTE: address() helper is not used to save one instruction. 2850 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_; 2851 ASSERT(heap != NULL); 2852 ASSERT(heap->isolate() == Isolate::Current()); 2853 return heap; 2854 } 2855 2856 2857 Heap* Code::heap() { 2858 // NOTE: address() helper is not used to save one instruction. 2859 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_; 2860 ASSERT(heap != NULL); 2861 ASSERT(heap->isolate() == Isolate::Current()); 2862 return heap; 2863 } 2864 2865 2866 Isolate* Code::isolate() { 2867 return heap()->isolate(); 2868 } 2869 2870 2871 Heap* JSGlobalPropertyCell::heap() { 2872 // NOTE: address() helper is not used to save one instruction. 2873 Heap* heap = Page::FromAddress(reinterpret_cast<Address>(this))->heap_; 2874 ASSERT(heap != NULL); 2875 ASSERT(heap->isolate() == Isolate::Current()); 2876 return heap; 2877 } 2878 2879 2880 Isolate* JSGlobalPropertyCell::isolate() { 2881 return heap()->isolate(); 2882 } 2883 2884 2885 Object* Code::GetObjectFromEntryAddress(Address location_of_address) { 2886 return HeapObject:: 2887 FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize); 2888 } 2889 2890 2891 Object* Map::prototype() { 2892 return READ_FIELD(this, kPrototypeOffset); 2893 } 2894 2895 2896 void Map::set_prototype(Object* value, WriteBarrierMode mode) { 2897 ASSERT(value->IsNull() || value->IsJSObject()); 2898 WRITE_FIELD(this, kPrototypeOffset, value); 2899 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, mode); 2900 } 2901 2902 2903 MaybeObject* Map::GetFastElementsMap() { 2904 if (has_fast_elements()) return this; 2905 Object* obj; 2906 { MaybeObject* maybe_obj = CopyDropTransitions(); 2907 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2908 } 2909 Map* new_map = Map::cast(obj); 2910 new_map->set_has_fast_elements(true); 2911 isolate()->counters()->map_slow_to_fast_elements()->Increment(); 2912 return new_map; 2913 } 2914 2915 2916 MaybeObject* Map::GetSlowElementsMap() { 2917 if (!has_fast_elements()) return this; 2918 Object* obj; 2919 { MaybeObject* maybe_obj = CopyDropTransitions(); 2920 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2921 } 2922 Map* new_map = Map::cast(obj); 2923 new_map->set_has_fast_elements(false); 2924 isolate()->counters()->map_fast_to_slow_elements()->Increment(); 2925 return new_map; 2926 } 2927 2928 2929 ACCESSORS(Map, instance_descriptors, DescriptorArray, 2930 kInstanceDescriptorsOffset) 2931 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset) 2932 ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset) 2933 ACCESSORS(Map, constructor, Object, kConstructorOffset) 2934 2935 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) 2936 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset) 2937 ACCESSORS_GCSAFE(JSFunction, next_function_link, Object, 2938 kNextFunctionLinkOffset) 2939 2940 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) 2941 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset) 2942 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset) 2943 2944 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset) 2945 2946 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset) 2947 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset) 2948 ACCESSORS(AccessorInfo, data, Object, kDataOffset) 2949 ACCESSORS(AccessorInfo, name, Object, kNameOffset) 2950 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset) 2951 2952 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset) 2953 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset) 2954 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) 2955 2956 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset) 2957 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset) 2958 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) 2959 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) 2960 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) 2961 ACCESSORS(InterceptorInfo, data, Object, kDataOffset) 2962 2963 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) 2964 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) 2965 2966 ACCESSORS(TemplateInfo, tag, Object, kTagOffset) 2967 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset) 2968 2969 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset) 2970 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset) 2971 ACCESSORS(FunctionTemplateInfo, property_accessors, Object, 2972 kPropertyAccessorsOffset) 2973 ACCESSORS(FunctionTemplateInfo, prototype_template, Object, 2974 kPrototypeTemplateOffset) 2975 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset) 2976 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object, 2977 kNamedPropertyHandlerOffset) 2978 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object, 2979 kIndexedPropertyHandlerOffset) 2980 ACCESSORS(FunctionTemplateInfo, instance_template, Object, 2981 kInstanceTemplateOffset) 2982 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset) 2983 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset) 2984 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object, 2985 kInstanceCallHandlerOffset) 2986 ACCESSORS(FunctionTemplateInfo, access_check_info, Object, 2987 kAccessCheckInfoOffset) 2988 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) 2989 2990 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) 2991 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, 2992 kInternalFieldCountOffset) 2993 2994 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) 2995 ACCESSORS(SignatureInfo, args, Object, kArgsOffset) 2996 2997 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset) 2998 2999 ACCESSORS(Script, source, Object, kSourceOffset) 3000 ACCESSORS(Script, name, Object, kNameOffset) 3001 ACCESSORS(Script, id, Object, kIdOffset) 3002 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset) 3003 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset) 3004 ACCESSORS(Script, data, Object, kDataOffset) 3005 ACCESSORS(Script, context_data, Object, kContextOffset) 3006 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset) 3007 ACCESSORS(Script, type, Smi, kTypeOffset) 3008 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset) 3009 ACCESSORS(Script, line_ends, Object, kLineEndsOffset) 3010 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset) 3011 ACCESSORS(Script, eval_from_instructions_offset, Smi, 3012 kEvalFrominstructionsOffsetOffset) 3013 3014 #ifdef ENABLE_DEBUGGER_SUPPORT 3015 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) 3016 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex) 3017 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex) 3018 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) 3019 3020 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex) 3021 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex) 3022 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex) 3023 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) 3024 #endif 3025 3026 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset) 3027 ACCESSORS_GCSAFE(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) 3028 ACCESSORS_GCSAFE(SharedFunctionInfo, initial_map, Object, kInitialMapOffset) 3029 ACCESSORS(SharedFunctionInfo, instance_class_name, Object, 3030 kInstanceClassNameOffset) 3031 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) 3032 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset) 3033 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset) 3034 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset) 3035 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object, 3036 kThisPropertyAssignmentsOffset) 3037 3038 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype, 3039 kHiddenPrototypeBit) 3040 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit) 3041 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check, 3042 kNeedsAccessCheckBit) 3043 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression, 3044 kIsExpressionBit) 3045 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel, 3046 kIsTopLevelBit) 3047 BOOL_GETTER(SharedFunctionInfo, compiler_hints, 3048 has_only_simple_this_property_assignments, 3049 kHasOnlySimpleThisPropertyAssignments) 3050 BOOL_ACCESSORS(SharedFunctionInfo, 3051 compiler_hints, 3052 allows_lazy_compilation, 3053 kAllowLazyCompilation) 3054 3055 3056 #if V8_HOST_ARCH_32_BIT 3057 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) 3058 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count, 3059 kFormalParameterCountOffset) 3060 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties, 3061 kExpectedNofPropertiesOffset) 3062 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset) 3063 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type, 3064 kStartPositionAndTypeOffset) 3065 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset) 3066 SMI_ACCESSORS(SharedFunctionInfo, function_token_position, 3067 kFunctionTokenPositionOffset) 3068 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints, 3069 kCompilerHintsOffset) 3070 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count, 3071 kThisPropertyAssignmentsCountOffset) 3072 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset) 3073 #else 3074 3075 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \ 3076 STATIC_ASSERT(holder::offset % kPointerSize == 0); \ 3077 int holder::name() { \ 3078 int value = READ_INT_FIELD(this, offset); \ 3079 ASSERT(kHeapObjectTag == 1); \ 3080 ASSERT((value & kHeapObjectTag) == 0); \ 3081 return value >> 1; \ 3082 } \ 3083 void holder::set_##name(int value) { \ 3084 ASSERT(kHeapObjectTag == 1); \ 3085 ASSERT((value & 0xC0000000) == 0xC0000000 || \ 3086 (value & 0xC0000000) == 0x000000000); \ 3087 WRITE_INT_FIELD(this, \ 3088 offset, \ 3089 (value << 1) & ~kHeapObjectTag); \ 3090 } 3091 3092 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \ 3093 STATIC_ASSERT(holder::offset % kPointerSize == kIntSize); \ 3094 INT_ACCESSORS(holder, name, offset) 3095 3096 3097 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset) 3098 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 3099 formal_parameter_count, 3100 kFormalParameterCountOffset) 3101 3102 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 3103 expected_nof_properties, 3104 kExpectedNofPropertiesOffset) 3105 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset) 3106 3107 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset) 3108 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 3109 start_position_and_type, 3110 kStartPositionAndTypeOffset) 3111 3112 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 3113 function_token_position, 3114 kFunctionTokenPositionOffset) 3115 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, 3116 compiler_hints, 3117 kCompilerHintsOffset) 3118 3119 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, 3120 this_property_assignments_count, 3121 kThisPropertyAssignmentsCountOffset) 3122 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset) 3123 #endif 3124 3125 3126 int SharedFunctionInfo::construction_count() { 3127 return READ_BYTE_FIELD(this, kConstructionCountOffset); 3128 } 3129 3130 3131 void SharedFunctionInfo::set_construction_count(int value) { 3132 ASSERT(0 <= value && value < 256); 3133 WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value)); 3134 } 3135 3136 3137 bool SharedFunctionInfo::live_objects_may_exist() { 3138 return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0; 3139 } 3140 3141 3142 void SharedFunctionInfo::set_live_objects_may_exist(bool value) { 3143 if (value) { 3144 set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist)); 3145 } else { 3146 set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist)); 3147 } 3148 } 3149 3150 3151 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() { 3152 return initial_map() != HEAP->undefined_value(); 3153 } 3154 3155 3156 bool SharedFunctionInfo::optimization_disabled() { 3157 return BooleanBit::get(compiler_hints(), kOptimizationDisabled); 3158 } 3159 3160 3161 void SharedFunctionInfo::set_optimization_disabled(bool disable) { 3162 set_compiler_hints(BooleanBit::set(compiler_hints(), 3163 kOptimizationDisabled, 3164 disable)); 3165 // If disabling optimizations we reflect that in the code object so 3166 // it will not be counted as optimizable code. 3167 if ((code()->kind() == Code::FUNCTION) && disable) { 3168 code()->set_optimizable(false); 3169 } 3170 } 3171 3172 3173 bool SharedFunctionInfo::strict_mode() { 3174 return BooleanBit::get(compiler_hints(), kStrictModeFunction); 3175 } 3176 3177 3178 void SharedFunctionInfo::set_strict_mode(bool value) { 3179 set_compiler_hints(BooleanBit::set(compiler_hints(), 3180 kStrictModeFunction, 3181 value)); 3182 } 3183 3184 3185 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) 3186 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) 3187 3188 bool Script::HasValidSource() { 3189 Object* src = this->source(); 3190 if (!src->IsString()) return true; 3191 String* src_str = String::cast(src); 3192 if (!StringShape(src_str).IsExternal()) return true; 3193 if (src_str->IsAsciiRepresentation()) { 3194 return ExternalAsciiString::cast(src)->resource() != NULL; 3195 } else if (src_str->IsTwoByteRepresentation()) { 3196 return ExternalTwoByteString::cast(src)->resource() != NULL; 3197 } 3198 return true; 3199 } 3200 3201 3202 void SharedFunctionInfo::DontAdaptArguments() { 3203 ASSERT(code()->kind() == Code::BUILTIN); 3204 set_formal_parameter_count(kDontAdaptArgumentsSentinel); 3205 } 3206 3207 3208 int SharedFunctionInfo::start_position() { 3209 return start_position_and_type() >> kStartPositionShift; 3210 } 3211 3212 3213 void SharedFunctionInfo::set_start_position(int start_position) { 3214 set_start_position_and_type((start_position << kStartPositionShift) 3215 | (start_position_and_type() & ~kStartPositionMask)); 3216 } 3217 3218 3219 Code* SharedFunctionInfo::code() { 3220 return Code::cast(READ_FIELD(this, kCodeOffset)); 3221 } 3222 3223 3224 Code* SharedFunctionInfo::unchecked_code() { 3225 return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset)); 3226 } 3227 3228 3229 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) { 3230 WRITE_FIELD(this, kCodeOffset, value); 3231 ASSERT(!Isolate::Current()->heap()->InNewSpace(value)); 3232 } 3233 3234 3235 SerializedScopeInfo* SharedFunctionInfo::scope_info() { 3236 return reinterpret_cast<SerializedScopeInfo*>( 3237 READ_FIELD(this, kScopeInfoOffset)); 3238 } 3239 3240 3241 void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value, 3242 WriteBarrierMode mode) { 3243 WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value)); 3244 CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kScopeInfoOffset, mode); 3245 } 3246 3247 3248 Smi* SharedFunctionInfo::deopt_counter() { 3249 return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset)); 3250 } 3251 3252 3253 void SharedFunctionInfo::set_deopt_counter(Smi* value) { 3254 WRITE_FIELD(this, kDeoptCounterOffset, value); 3255 } 3256 3257 3258 bool SharedFunctionInfo::is_compiled() { 3259 return code() != 3260 Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile); 3261 } 3262 3263 3264 bool SharedFunctionInfo::IsApiFunction() { 3265 return function_data()->IsFunctionTemplateInfo(); 3266 } 3267 3268 3269 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() { 3270 ASSERT(IsApiFunction()); 3271 return FunctionTemplateInfo::cast(function_data()); 3272 } 3273 3274 3275 bool SharedFunctionInfo::HasBuiltinFunctionId() { 3276 return function_data()->IsSmi(); 3277 } 3278 3279 3280 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() { 3281 ASSERT(HasBuiltinFunctionId()); 3282 return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value()); 3283 } 3284 3285 3286 int SharedFunctionInfo::code_age() { 3287 return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask; 3288 } 3289 3290 3291 void SharedFunctionInfo::set_code_age(int code_age) { 3292 set_compiler_hints(compiler_hints() | 3293 ((code_age & kCodeAgeMask) << kCodeAgeShift)); 3294 } 3295 3296 3297 bool SharedFunctionInfo::has_deoptimization_support() { 3298 Code* code = this->code(); 3299 return code->kind() == Code::FUNCTION && code->has_deoptimization_support(); 3300 } 3301 3302 3303 bool JSFunction::IsBuiltin() { 3304 return context()->global()->IsJSBuiltinsObject(); 3305 } 3306 3307 3308 bool JSFunction::NeedsArgumentsAdaption() { 3309 return shared()->formal_parameter_count() != 3310 SharedFunctionInfo::kDontAdaptArgumentsSentinel; 3311 } 3312 3313 3314 bool JSFunction::IsOptimized() { 3315 return code()->kind() == Code::OPTIMIZED_FUNCTION; 3316 } 3317 3318 3319 bool JSFunction::IsOptimizable() { 3320 return code()->kind() == Code::FUNCTION && code()->optimizable(); 3321 } 3322 3323 3324 bool JSFunction::IsMarkedForLazyRecompilation() { 3325 return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile); 3326 } 3327 3328 3329 Code* JSFunction::code() { 3330 return Code::cast(unchecked_code()); 3331 } 3332 3333 3334 Code* JSFunction::unchecked_code() { 3335 return reinterpret_cast<Code*>( 3336 Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset))); 3337 } 3338 3339 3340 void JSFunction::set_code(Code* value) { 3341 // Skip the write barrier because code is never in new space. 3342 ASSERT(!HEAP->InNewSpace(value)); 3343 Address entry = value->entry(); 3344 WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry)); 3345 } 3346 3347 3348 void JSFunction::ReplaceCode(Code* code) { 3349 bool was_optimized = IsOptimized(); 3350 bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION; 3351 3352 set_code(code); 3353 3354 // Add/remove the function from the list of optimized functions for this 3355 // context based on the state change. 3356 if (!was_optimized && is_optimized) { 3357 context()->global_context()->AddOptimizedFunction(this); 3358 } 3359 if (was_optimized && !is_optimized) { 3360 context()->global_context()->RemoveOptimizedFunction(this); 3361 } 3362 } 3363 3364 3365 Context* JSFunction::context() { 3366 return Context::cast(READ_FIELD(this, kContextOffset)); 3367 } 3368 3369 3370 Object* JSFunction::unchecked_context() { 3371 return READ_FIELD(this, kContextOffset); 3372 } 3373 3374 3375 SharedFunctionInfo* JSFunction::unchecked_shared() { 3376 return reinterpret_cast<SharedFunctionInfo*>( 3377 READ_FIELD(this, kSharedFunctionInfoOffset)); 3378 } 3379 3380 3381 void JSFunction::set_context(Object* value) { 3382 ASSERT(value->IsUndefined() || value->IsContext()); 3383 WRITE_FIELD(this, kContextOffset, value); 3384 WRITE_BARRIER(this, kContextOffset); 3385 } 3386 3387 ACCESSORS(JSFunction, prototype_or_initial_map, Object, 3388 kPrototypeOrInitialMapOffset) 3389 3390 3391 Map* JSFunction::initial_map() { 3392 return Map::cast(prototype_or_initial_map()); 3393 } 3394 3395 3396 void JSFunction::set_initial_map(Map* value) { 3397 set_prototype_or_initial_map(value); 3398 } 3399 3400 3401 bool JSFunction::has_initial_map() { 3402 return prototype_or_initial_map()->IsMap(); 3403 } 3404 3405 3406 bool JSFunction::has_instance_prototype() { 3407 return has_initial_map() || !prototype_or_initial_map()->IsTheHole(); 3408 } 3409 3410 3411 bool JSFunction::has_prototype() { 3412 return map()->has_non_instance_prototype() || has_instance_prototype(); 3413 } 3414 3415 3416 Object* JSFunction::instance_prototype() { 3417 ASSERT(has_instance_prototype()); 3418 if (has_initial_map()) return initial_map()->prototype(); 3419 // When there is no initial map and the prototype is a JSObject, the 3420 // initial map field is used for the prototype field. 3421 return prototype_or_initial_map(); 3422 } 3423 3424 3425 Object* JSFunction::prototype() { 3426 ASSERT(has_prototype()); 3427 // If the function's prototype property has been set to a non-JSObject 3428 // value, that value is stored in the constructor field of the map. 3429 if (map()->has_non_instance_prototype()) return map()->constructor(); 3430 return instance_prototype(); 3431 } 3432 3433 bool JSFunction::should_have_prototype() { 3434 return map()->function_with_prototype(); 3435 } 3436 3437 3438 bool JSFunction::is_compiled() { 3439 return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); 3440 } 3441 3442 3443 int JSFunction::NumberOfLiterals() { 3444 return literals()->length(); 3445 } 3446 3447 3448 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) { 3449 ASSERT(id < kJSBuiltinsCount); // id is unsigned. 3450 return READ_FIELD(this, OffsetOfFunctionWithId(id)); 3451 } 3452 3453 3454 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id, 3455 Object* value) { 3456 ASSERT(id < kJSBuiltinsCount); // id is unsigned. 3457 WRITE_FIELD(this, OffsetOfFunctionWithId(id), value); 3458 WRITE_BARRIER(this, OffsetOfFunctionWithId(id)); 3459 } 3460 3461 3462 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) { 3463 ASSERT(id < kJSBuiltinsCount); // id is unsigned. 3464 return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id))); 3465 } 3466 3467 3468 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id, 3469 Code* value) { 3470 ASSERT(id < kJSBuiltinsCount); // id is unsigned. 3471 WRITE_FIELD(this, OffsetOfCodeWithId(id), value); 3472 ASSERT(!HEAP->InNewSpace(value)); 3473 } 3474 3475 3476 Address Proxy::proxy() { 3477 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset)); 3478 } 3479 3480 3481 void Proxy::set_proxy(Address value) { 3482 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value)); 3483 } 3484 3485 3486 ACCESSORS(JSValue, value, Object, kValueOffset) 3487 3488 3489 JSValue* JSValue::cast(Object* obj) { 3490 ASSERT(obj->IsJSValue()); 3491 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize); 3492 return reinterpret_cast<JSValue*>(obj); 3493 } 3494 3495 3496 ACCESSORS(JSMessageObject, type, String, kTypeOffset) 3497 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset) 3498 ACCESSORS(JSMessageObject, script, Object, kScriptOffset) 3499 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset) 3500 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset) 3501 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset) 3502 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset) 3503 3504 3505 JSMessageObject* JSMessageObject::cast(Object* obj) { 3506 ASSERT(obj->IsJSMessageObject()); 3507 ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize); 3508 return reinterpret_cast<JSMessageObject*>(obj); 3509 } 3510 3511 3512 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset) 3513 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset) 3514 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset) 3515 3516 3517 byte* Code::instruction_start() { 3518 return FIELD_ADDR(this, kHeaderSize); 3519 } 3520 3521 3522 byte* Code::instruction_end() { 3523 return instruction_start() + instruction_size(); 3524 } 3525 3526 3527 int Code::body_size() { 3528 return RoundUp(instruction_size(), kObjectAlignment); 3529 } 3530 3531 3532 FixedArray* Code::unchecked_deoptimization_data() { 3533 return reinterpret_cast<FixedArray*>( 3534 READ_FIELD(this, kDeoptimizationDataOffset)); 3535 } 3536 3537 3538 ByteArray* Code::unchecked_relocation_info() { 3539 return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset)); 3540 } 3541 3542 3543 byte* Code::relocation_start() { 3544 return unchecked_relocation_info()->GetDataStartAddress(); 3545 } 3546 3547 3548 int Code::relocation_size() { 3549 return unchecked_relocation_info()->length(); 3550 } 3551 3552 3553 byte* Code::entry() { 3554 return instruction_start(); 3555 } 3556 3557 3558 bool Code::contains(byte* pc) { 3559 return (instruction_start() <= pc) && 3560 (pc <= instruction_start() + instruction_size()); 3561 } 3562 3563 3564 ACCESSORS(JSArray, length, Object, kLengthOffset) 3565 3566 3567 ACCESSORS(JSRegExp, data, Object, kDataOffset) 3568 3569 3570 JSRegExp::Type JSRegExp::TypeTag() { 3571 Object* data = this->data(); 3572 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED; 3573 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex)); 3574 return static_cast<JSRegExp::Type>(smi->value()); 3575 } 3576 3577 3578 int JSRegExp::CaptureCount() { 3579 switch (TypeTag()) { 3580 case ATOM: 3581 return 0; 3582 case IRREGEXP: 3583 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value(); 3584 default: 3585 UNREACHABLE(); 3586 return -1; 3587 } 3588 } 3589 3590 3591 JSRegExp::Flags JSRegExp::GetFlags() { 3592 ASSERT(this->data()->IsFixedArray()); 3593 Object* data = this->data(); 3594 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex)); 3595 return Flags(smi->value()); 3596 } 3597 3598 3599 String* JSRegExp::Pattern() { 3600 ASSERT(this->data()->IsFixedArray()); 3601 Object* data = this->data(); 3602 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex)); 3603 return pattern; 3604 } 3605 3606 3607 Object* JSRegExp::DataAt(int index) { 3608 ASSERT(TypeTag() != NOT_COMPILED); 3609 return FixedArray::cast(data())->get(index); 3610 } 3611 3612 3613 void JSRegExp::SetDataAt(int index, Object* value) { 3614 ASSERT(TypeTag() != NOT_COMPILED); 3615 ASSERT(index >= kDataIndex); // Only implementation data can be set this way. 3616 FixedArray::cast(data())->set(index, value); 3617 } 3618 3619 3620 JSObject::ElementsKind JSObject::GetElementsKind() { 3621 if (map()->has_fast_elements()) { 3622 ASSERT(elements()->map() == GetHeap()->fixed_array_map() || 3623 elements()->map() == GetHeap()->fixed_cow_array_map()); 3624 return FAST_ELEMENTS; 3625 } 3626 HeapObject* array = elements(); 3627 if (array->IsFixedArray()) { 3628 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a 3629 // FixedArray, but FAST_ELEMENTS is already handled above. 3630 ASSERT(array->IsDictionary()); 3631 return DICTIONARY_ELEMENTS; 3632 } 3633 ASSERT(!map()->has_fast_elements()); 3634 if (array->IsExternalArray()) { 3635 switch (array->map()->instance_type()) { 3636 case EXTERNAL_BYTE_ARRAY_TYPE: 3637 return EXTERNAL_BYTE_ELEMENTS; 3638 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 3639 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS; 3640 case EXTERNAL_SHORT_ARRAY_TYPE: 3641 return EXTERNAL_SHORT_ELEMENTS; 3642 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 3643 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS; 3644 case EXTERNAL_INT_ARRAY_TYPE: 3645 return EXTERNAL_INT_ELEMENTS; 3646 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 3647 return EXTERNAL_UNSIGNED_INT_ELEMENTS; 3648 case EXTERNAL_PIXEL_ARRAY_TYPE: 3649 return EXTERNAL_PIXEL_ELEMENTS; 3650 default: 3651 break; 3652 } 3653 } 3654 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE); 3655 return EXTERNAL_FLOAT_ELEMENTS; 3656 } 3657 3658 3659 bool JSObject::HasFastElements() { 3660 return GetElementsKind() == FAST_ELEMENTS; 3661 } 3662 3663 3664 bool JSObject::HasDictionaryElements() { 3665 return GetElementsKind() == DICTIONARY_ELEMENTS; 3666 } 3667 3668 3669 bool JSObject::HasExternalArrayElements() { 3670 HeapObject* array = elements(); 3671 ASSERT(array != NULL); 3672 return array->IsExternalArray(); 3673 } 3674 3675 3676 #define EXTERNAL_ELEMENTS_CHECK(name, type) \ 3677 bool JSObject::HasExternal##name##Elements() { \ 3678 HeapObject* array = elements(); \ 3679 ASSERT(array != NULL); \ 3680 if (!array->IsHeapObject()) \ 3681 return false; \ 3682 return array->map()->instance_type() == type; \ 3683 } 3684 3685 3686 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE) 3687 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE) 3688 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE) 3689 EXTERNAL_ELEMENTS_CHECK(UnsignedShort, 3690 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE) 3691 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE) 3692 EXTERNAL_ELEMENTS_CHECK(UnsignedInt, 3693 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE) 3694 EXTERNAL_ELEMENTS_CHECK(Float, 3695 EXTERNAL_FLOAT_ARRAY_TYPE) 3696 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE) 3697 3698 3699 bool JSObject::HasNamedInterceptor() { 3700 return map()->has_named_interceptor(); 3701 } 3702 3703 3704 bool JSObject::HasIndexedInterceptor() { 3705 return map()->has_indexed_interceptor(); 3706 } 3707 3708 3709 bool JSObject::AllowsSetElementsLength() { 3710 bool result = elements()->IsFixedArray(); 3711 ASSERT(result == !HasExternalArrayElements()); 3712 return result; 3713 } 3714 3715 3716 MaybeObject* JSObject::EnsureWritableFastElements() { 3717 ASSERT(HasFastElements()); 3718 FixedArray* elems = FixedArray::cast(elements()); 3719 Isolate* isolate = GetIsolate(); 3720 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; 3721 Object* writable_elems; 3722 { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap( 3723 elems, isolate->heap()->fixed_array_map()); 3724 if (!maybe_writable_elems->ToObject(&writable_elems)) { 3725 return maybe_writable_elems; 3726 } 3727 } 3728 set_elements(FixedArray::cast(writable_elems)); 3729 isolate->counters()->cow_arrays_converted()->Increment(); 3730 return writable_elems; 3731 } 3732 3733 3734 StringDictionary* JSObject::property_dictionary() { 3735 ASSERT(!HasFastProperties()); 3736 return StringDictionary::cast(properties()); 3737 } 3738 3739 3740 NumberDictionary* JSObject::element_dictionary() { 3741 ASSERT(HasDictionaryElements()); 3742 return NumberDictionary::cast(elements()); 3743 } 3744 3745 3746 bool String::IsHashFieldComputed(uint32_t field) { 3747 return (field & kHashNotComputedMask) == 0; 3748 } 3749 3750 3751 bool String::HasHashCode() { 3752 return IsHashFieldComputed(hash_field()); 3753 } 3754 3755 3756 uint32_t String::Hash() { 3757 // Fast case: has hash code already been computed? 3758 uint32_t field = hash_field(); 3759 if (IsHashFieldComputed(field)) return field >> kHashShift; 3760 // Slow case: compute hash code and set it. 3761 return ComputeAndSetHash(); 3762 } 3763 3764 3765 StringHasher::StringHasher(int length) 3766 : length_(length), 3767 raw_running_hash_(0), 3768 array_index_(0), 3769 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), 3770 is_first_char_(true), 3771 is_valid_(true) { } 3772 3773 3774 bool StringHasher::has_trivial_hash() { 3775 return length_ > String::kMaxHashCalcLength; 3776 } 3777 3778 3779 void StringHasher::AddCharacter(uc32 c) { 3780 // Use the Jenkins one-at-a-time hash function to update the hash 3781 // for the given character. 3782 raw_running_hash_ += c; 3783 raw_running_hash_ += (raw_running_hash_ << 10); 3784 raw_running_hash_ ^= (raw_running_hash_ >> 6); 3785 // Incremental array index computation. 3786 if (is_array_index_) { 3787 if (c < '0' || c > '9') { 3788 is_array_index_ = false; 3789 } else { 3790 int d = c - '0'; 3791 if (is_first_char_) { 3792 is_first_char_ = false; 3793 if (c == '0' && length_ > 1) { 3794 is_array_index_ = false; 3795 return; 3796 } 3797 } 3798 if (array_index_ > 429496729U - ((d + 2) >> 3)) { 3799 is_array_index_ = false; 3800 } else { 3801 array_index_ = array_index_ * 10 + d; 3802 } 3803 } 3804 } 3805 } 3806 3807 3808 void StringHasher::AddCharacterNoIndex(uc32 c) { 3809 ASSERT(!is_array_index()); 3810 raw_running_hash_ += c; 3811 raw_running_hash_ += (raw_running_hash_ << 10); 3812 raw_running_hash_ ^= (raw_running_hash_ >> 6); 3813 } 3814 3815 3816 uint32_t StringHasher::GetHash() { 3817 // Get the calculated raw hash value and do some more bit ops to distribute 3818 // the hash further. Ensure that we never return zero as the hash value. 3819 uint32_t result = raw_running_hash_; 3820 result += (result << 3); 3821 result ^= (result >> 11); 3822 result += (result << 15); 3823 if (result == 0) { 3824 result = 27; 3825 } 3826 return result; 3827 } 3828 3829 3830 template <typename schar> 3831 uint32_t HashSequentialString(const schar* chars, int length) { 3832 StringHasher hasher(length); 3833 if (!hasher.has_trivial_hash()) { 3834 int i; 3835 for (i = 0; hasher.is_array_index() && (i < length); i++) { 3836 hasher.AddCharacter(chars[i]); 3837 } 3838 for (; i < length; i++) { 3839 hasher.AddCharacterNoIndex(chars[i]); 3840 } 3841 } 3842 return hasher.GetHashField(); 3843 } 3844 3845 3846 bool String::AsArrayIndex(uint32_t* index) { 3847 uint32_t field = hash_field(); 3848 if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) { 3849 return false; 3850 } 3851 return SlowAsArrayIndex(index); 3852 } 3853 3854 3855 Object* JSObject::GetPrototype() { 3856 return JSObject::cast(this)->map()->prototype(); 3857 } 3858 3859 3860 PropertyAttributes JSObject::GetPropertyAttribute(String* key) { 3861 return GetPropertyAttributeWithReceiver(this, key); 3862 } 3863 3864 // TODO(504): this may be useful in other places too where JSGlobalProxy 3865 // is used. 3866 Object* JSObject::BypassGlobalProxy() { 3867 if (IsJSGlobalProxy()) { 3868 Object* proto = GetPrototype(); 3869 if (proto->IsNull()) return GetHeap()->undefined_value(); 3870 ASSERT(proto->IsJSGlobalObject()); 3871 return proto; 3872 } 3873 return this; 3874 } 3875 3876 3877 bool JSObject::HasHiddenPropertiesObject() { 3878 ASSERT(!IsJSGlobalProxy()); 3879 return GetPropertyAttributePostInterceptor(this, 3880 GetHeap()->hidden_symbol(), 3881 false) != ABSENT; 3882 } 3883 3884 3885 Object* JSObject::GetHiddenPropertiesObject() { 3886 ASSERT(!IsJSGlobalProxy()); 3887 PropertyAttributes attributes; 3888 // You can't install a getter on a property indexed by the hidden symbol, 3889 // so we can be sure that GetLocalPropertyPostInterceptor returns a real 3890 // object. 3891 Object* result = 3892 GetLocalPropertyPostInterceptor(this, 3893 GetHeap()->hidden_symbol(), 3894 &attributes)->ToObjectUnchecked(); 3895 return result; 3896 } 3897 3898 3899 MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) { 3900 ASSERT(!IsJSGlobalProxy()); 3901 return SetPropertyPostInterceptor(GetHeap()->hidden_symbol(), 3902 hidden_obj, 3903 DONT_ENUM, 3904 kNonStrictMode); 3905 } 3906 3907 3908 bool JSObject::HasElement(uint32_t index) { 3909 return HasElementWithReceiver(this, index); 3910 } 3911 3912 3913 bool AccessorInfo::all_can_read() { 3914 return BooleanBit::get(flag(), kAllCanReadBit); 3915 } 3916 3917 3918 void AccessorInfo::set_all_can_read(bool value) { 3919 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value)); 3920 } 3921 3922 3923 bool AccessorInfo::all_can_write() { 3924 return BooleanBit::get(flag(), kAllCanWriteBit); 3925 } 3926 3927 3928 void AccessorInfo::set_all_can_write(bool value) { 3929 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value)); 3930 } 3931 3932 3933 bool AccessorInfo::prohibits_overwriting() { 3934 return BooleanBit::get(flag(), kProhibitsOverwritingBit); 3935 } 3936 3937 3938 void AccessorInfo::set_prohibits_overwriting(bool value) { 3939 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value)); 3940 } 3941 3942 3943 PropertyAttributes AccessorInfo::property_attributes() { 3944 return AttributesField::decode(static_cast<uint32_t>(flag()->value())); 3945 } 3946 3947 3948 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) { 3949 ASSERT(AttributesField::is_valid(attributes)); 3950 int rest_value = flag()->value() & ~AttributesField::mask(); 3951 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes))); 3952 } 3953 3954 3955 template<typename Shape, typename Key> 3956 void Dictionary<Shape, Key>::SetEntry(int entry, 3957 Object* key, 3958 Object* value) { 3959 SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0))); 3960 } 3961 3962 3963 template<typename Shape, typename Key> 3964 void Dictionary<Shape, Key>::SetEntry(int entry, 3965 Object* key, 3966 Object* value, 3967 PropertyDetails details) { 3968 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0); 3969 int index = HashTable<Shape, Key>::EntryToIndex(entry); 3970 AssertNoAllocation no_gc; 3971 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc); 3972 FixedArray::set(index, key, mode); 3973 FixedArray::set(index+1, value, mode); 3974 FixedArray::fast_set(this, index+2, details.AsSmi()); 3975 } 3976 3977 3978 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { 3979 ASSERT(other->IsNumber()); 3980 return key == static_cast<uint32_t>(other->Number()); 3981 } 3982 3983 3984 uint32_t NumberDictionaryShape::Hash(uint32_t key) { 3985 return ComputeIntegerHash(key); 3986 } 3987 3988 3989 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { 3990 ASSERT(other->IsNumber()); 3991 return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); 3992 } 3993 3994 3995 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { 3996 return Isolate::Current()->heap()->NumberFromUint32(key); 3997 } 3998 3999 4000 bool StringDictionaryShape::IsMatch(String* key, Object* other) { 4001 // We know that all entries in a hash table had their hash keys created. 4002 // Use that knowledge to have fast failure. 4003 if (key->Hash() != String::cast(other)->Hash()) return false; 4004 return key->Equals(String::cast(other)); 4005 } 4006 4007 4008 uint32_t StringDictionaryShape::Hash(String* key) { 4009 return key->Hash(); 4010 } 4011 4012 4013 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { 4014 return String::cast(other)->Hash(); 4015 } 4016 4017 4018 MaybeObject* StringDictionaryShape::AsObject(String* key) { 4019 return key; 4020 } 4021 4022 4023 void Map::ClearCodeCache(Heap* heap) { 4024 // No write barrier is needed since empty_fixed_array is not in new space. 4025 // Please note this function is used during marking: 4026 // - MarkCompactCollector::MarkUnmarkedObject 4027 ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array())); 4028 WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array()); 4029 } 4030 4031 4032 void JSArray::EnsureSize(int required_size) { 4033 ASSERT(HasFastElements()); 4034 FixedArray* elts = FixedArray::cast(elements()); 4035 const int kArraySizeThatFitsComfortablyInNewSpace = 128; 4036 if (elts->length() < required_size) { 4037 // Doubling in size would be overkill, but leave some slack to avoid 4038 // constantly growing. 4039 Expand(required_size + (required_size >> 3)); 4040 // It's a performance benefit to keep a frequently used array in new-space. 4041 } else if (!GetHeap()->new_space()->Contains(elts) && 4042 required_size < kArraySizeThatFitsComfortablyInNewSpace) { 4043 // Expand will allocate a new backing store in new space even if the size 4044 // we asked for isn't larger than what we had before. 4045 Expand(required_size); 4046 } 4047 } 4048 4049 4050 void JSArray::set_length(Smi* length) { 4051 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); 4052 } 4053 4054 4055 void JSArray::SetContent(FixedArray* storage) { 4056 set_length(Smi::FromInt(storage->length())); 4057 set_elements(storage); 4058 } 4059 4060 4061 MaybeObject* FixedArray::Copy() { 4062 if (length() == 0) return this; 4063 return GetHeap()->CopyFixedArray(this); 4064 } 4065 4066 4067 Relocatable::Relocatable(Isolate* isolate) { 4068 ASSERT(isolate == Isolate::Current()); 4069 isolate_ = isolate; 4070 prev_ = isolate->relocatable_top(); 4071 isolate->set_relocatable_top(this); 4072 } 4073 4074 4075 Relocatable::~Relocatable() { 4076 ASSERT(isolate_ == Isolate::Current()); 4077 ASSERT_EQ(isolate_->relocatable_top(), this); 4078 isolate_->set_relocatable_top(prev_); 4079 } 4080 4081 4082 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) { 4083 return map->instance_size(); 4084 } 4085 4086 4087 void Proxy::ProxyIterateBody(ObjectVisitor* v) { 4088 v->VisitExternalReference( 4089 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset))); 4090 } 4091 4092 4093 template<typename StaticVisitor> 4094 void Proxy::ProxyIterateBody() { 4095 StaticVisitor::VisitExternalReference( 4096 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset))); 4097 } 4098 4099 4100 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) { 4101 typedef v8::String::ExternalAsciiStringResource Resource; 4102 v->VisitExternalAsciiString( 4103 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); 4104 } 4105 4106 4107 template<typename StaticVisitor> 4108 void ExternalAsciiString::ExternalAsciiStringIterateBody() { 4109 typedef v8::String::ExternalAsciiStringResource Resource; 4110 StaticVisitor::VisitExternalAsciiString( 4111 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); 4112 } 4113 4114 4115 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) { 4116 typedef v8::String::ExternalStringResource Resource; 4117 v->VisitExternalTwoByteString( 4118 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); 4119 } 4120 4121 4122 template<typename StaticVisitor> 4123 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() { 4124 typedef v8::String::ExternalStringResource Resource; 4125 StaticVisitor::VisitExternalTwoByteString( 4126 reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset))); 4127 } 4128 4129 #define SLOT_ADDR(obj, offset) \ 4130 reinterpret_cast<Object**>((obj)->address() + offset) 4131 4132 template<int start_offset, int end_offset, int size> 4133 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody( 4134 HeapObject* obj, 4135 ObjectVisitor* v) { 4136 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset)); 4137 } 4138 4139 4140 template<int start_offset> 4141 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj, 4142 int object_size, 4143 ObjectVisitor* v) { 4144 v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size)); 4145 } 4146 4147 #undef SLOT_ADDR 4148 4149 4150 #undef CAST_ACCESSOR 4151 #undef INT_ACCESSORS 4152 #undef SMI_ACCESSORS 4153 #undef ACCESSORS 4154 #undef FIELD_ADDR 4155 #undef READ_FIELD 4156 #undef WRITE_FIELD 4157 #undef WRITE_BARRIER 4158 #undef CONDITIONAL_WRITE_BARRIER 4159 #undef READ_MEMADDR_FIELD 4160 #undef WRITE_MEMADDR_FIELD 4161 #undef READ_DOUBLE_FIELD 4162 #undef WRITE_DOUBLE_FIELD 4163 #undef READ_INT_FIELD 4164 #undef WRITE_INT_FIELD 4165 #undef READ_SHORT_FIELD 4166 #undef WRITE_SHORT_FIELD 4167 #undef READ_BYTE_FIELD 4168 #undef WRITE_BYTE_FIELD 4169 4170 4171 } } // namespace v8::internal 4172 4173 #endif // V8_OBJECTS_INL_H_ 4174