1 // Copyright 2006-2008 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 "property.h" 42 43 namespace v8 { 44 namespace internal { 45 46 PropertyDetails::PropertyDetails(Smi* smi) { 47 value_ = smi->value(); 48 } 49 50 51 Smi* PropertyDetails::AsSmi() { 52 return Smi::FromInt(value_); 53 } 54 55 56 PropertyDetails PropertyDetails::AsDeleted() { 57 PropertyDetails d(DONT_ENUM, NORMAL); 58 Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1)); 59 return PropertyDetails(smi); 60 } 61 62 63 #define CAST_ACCESSOR(type) \ 64 type* type::cast(Object* object) { \ 65 ASSERT(object->Is##type()); \ 66 return reinterpret_cast<type*>(object); \ 67 } 68 69 70 #define INT_ACCESSORS(holder, name, offset) \ 71 int holder::name() { return READ_INT_FIELD(this, offset); } \ 72 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); } 73 74 75 #define ACCESSORS(holder, name, type, offset) \ 76 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \ 77 void holder::set_##name(type* value, WriteBarrierMode mode) { \ 78 WRITE_FIELD(this, offset, value); \ 79 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \ 80 } 81 82 83 84 #define SMI_ACCESSORS(holder, name, offset) \ 85 int holder::name() { \ 86 Object* value = READ_FIELD(this, offset); \ 87 return Smi::cast(value)->value(); \ 88 } \ 89 void holder::set_##name(int value) { \ 90 WRITE_FIELD(this, offset, Smi::FromInt(value)); \ 91 } 92 93 94 #define BOOL_GETTER(holder, field, name, offset) \ 95 bool holder::name() { \ 96 return BooleanBit::get(field(), offset); \ 97 } \ 98 99 100 #define BOOL_ACCESSORS(holder, field, name, offset) \ 101 bool holder::name() { \ 102 return BooleanBit::get(field(), offset); \ 103 } \ 104 void holder::set_##name(bool value) { \ 105 set_##field(BooleanBit::set(field(), offset, value)); \ 106 } 107 108 109 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) { 110 // There is a constraint on the object; check. 111 if (!this->IsJSObject()) return false; 112 // Fetch the constructor function of the object. 113 Object* cons_obj = JSObject::cast(this)->map()->constructor(); 114 if (!cons_obj->IsJSFunction()) return false; 115 JSFunction* fun = JSFunction::cast(cons_obj); 116 // Iterate through the chain of inheriting function templates to 117 // see if the required one occurs. 118 for (Object* type = fun->shared()->function_data(); 119 type->IsFunctionTemplateInfo(); 120 type = FunctionTemplateInfo::cast(type)->parent_template()) { 121 if (type == expected) return true; 122 } 123 // Didn't find the required type in the inheritance chain. 124 return false; 125 } 126 127 128 bool Object::IsSmi() { 129 return HAS_SMI_TAG(this); 130 } 131 132 133 bool Object::IsHeapObject() { 134 return Internals::HasHeapObjectTag(this); 135 } 136 137 138 bool Object::IsHeapNumber() { 139 return Object::IsHeapObject() 140 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE; 141 } 142 143 144 bool Object::IsString() { 145 return Object::IsHeapObject() 146 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE; 147 } 148 149 150 bool Object::IsSymbol() { 151 if (!this->IsHeapObject()) return false; 152 uint32_t type = HeapObject::cast(this)->map()->instance_type(); 153 // Because the symbol tag is non-zero and no non-string types have the 154 // symbol bit set we can test for symbols with a very simple test 155 // operation. 156 ASSERT(kSymbolTag != 0); 157 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE); 158 return (type & kIsSymbolMask) != 0; 159 } 160 161 162 bool Object::IsConsString() { 163 if (!this->IsHeapObject()) return false; 164 uint32_t type = HeapObject::cast(this)->map()->instance_type(); 165 return (type & (kIsNotStringMask | kStringRepresentationMask)) == 166 (kStringTag | kConsStringTag); 167 } 168 169 170 bool Object::IsSeqString() { 171 if (!IsString()) return false; 172 return StringShape(String::cast(this)).IsSequential(); 173 } 174 175 176 bool Object::IsSeqAsciiString() { 177 if (!IsString()) return false; 178 return StringShape(String::cast(this)).IsSequential() && 179 String::cast(this)->IsAsciiRepresentation(); 180 } 181 182 183 bool Object::IsSeqTwoByteString() { 184 if (!IsString()) return false; 185 return StringShape(String::cast(this)).IsSequential() && 186 String::cast(this)->IsTwoByteRepresentation(); 187 } 188 189 190 bool Object::IsExternalString() { 191 if (!IsString()) return false; 192 return StringShape(String::cast(this)).IsExternal(); 193 } 194 195 196 bool Object::IsExternalAsciiString() { 197 if (!IsString()) return false; 198 return StringShape(String::cast(this)).IsExternal() && 199 String::cast(this)->IsAsciiRepresentation(); 200 } 201 202 203 bool Object::IsExternalTwoByteString() { 204 if (!IsString()) return false; 205 return StringShape(String::cast(this)).IsExternal() && 206 String::cast(this)->IsTwoByteRepresentation(); 207 } 208 209 210 StringShape::StringShape(String* str) 211 : type_(str->map()->instance_type()) { 212 set_valid(); 213 ASSERT((type_ & kIsNotStringMask) == kStringTag); 214 } 215 216 217 StringShape::StringShape(Map* map) 218 : type_(map->instance_type()) { 219 set_valid(); 220 ASSERT((type_ & kIsNotStringMask) == kStringTag); 221 } 222 223 224 StringShape::StringShape(InstanceType t) 225 : type_(static_cast<uint32_t>(t)) { 226 set_valid(); 227 ASSERT((type_ & kIsNotStringMask) == kStringTag); 228 } 229 230 231 bool StringShape::IsSymbol() { 232 ASSERT(valid()); 233 ASSERT(kSymbolTag != 0); 234 return (type_ & kIsSymbolMask) != 0; 235 } 236 237 238 bool String::IsAsciiRepresentation() { 239 uint32_t type = map()->instance_type(); 240 if ((type & kStringRepresentationMask) == kConsStringTag && 241 ConsString::cast(this)->second()->length() == 0) { 242 return ConsString::cast(this)->first()->IsAsciiRepresentation(); 243 } 244 return (type & kStringEncodingMask) == kAsciiStringTag; 245 } 246 247 248 bool String::IsTwoByteRepresentation() { 249 uint32_t type = map()->instance_type(); 250 if ((type & kStringRepresentationMask) == kConsStringTag && 251 ConsString::cast(this)->second()->length() == 0) { 252 return ConsString::cast(this)->first()->IsTwoByteRepresentation(); 253 } 254 return (type & kStringEncodingMask) == kTwoByteStringTag; 255 } 256 257 258 bool StringShape::IsCons() { 259 return (type_ & kStringRepresentationMask) == kConsStringTag; 260 } 261 262 263 bool StringShape::IsExternal() { 264 return (type_ & kStringRepresentationMask) == kExternalStringTag; 265 } 266 267 268 bool StringShape::IsSequential() { 269 return (type_ & kStringRepresentationMask) == kSeqStringTag; 270 } 271 272 273 StringRepresentationTag StringShape::representation_tag() { 274 uint32_t tag = (type_ & kStringRepresentationMask); 275 return static_cast<StringRepresentationTag>(tag); 276 } 277 278 279 uint32_t StringShape::full_representation_tag() { 280 return (type_ & (kStringRepresentationMask | kStringEncodingMask)); 281 } 282 283 284 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) == 285 Internals::kFullStringRepresentationMask); 286 287 288 bool StringShape::IsSequentialAscii() { 289 return full_representation_tag() == (kSeqStringTag | kAsciiStringTag); 290 } 291 292 293 bool StringShape::IsSequentialTwoByte() { 294 return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag); 295 } 296 297 298 bool StringShape::IsExternalAscii() { 299 return full_representation_tag() == (kExternalStringTag | kAsciiStringTag); 300 } 301 302 303 bool StringShape::IsExternalTwoByte() { 304 return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag); 305 } 306 307 308 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) == 309 Internals::kExternalTwoByteRepresentationTag); 310 311 312 uc32 FlatStringReader::Get(int index) { 313 ASSERT(0 <= index && index <= length_); 314 if (is_ascii_) { 315 return static_cast<const byte*>(start_)[index]; 316 } else { 317 return static_cast<const uc16*>(start_)[index]; 318 } 319 } 320 321 322 bool Object::IsNumber() { 323 return IsSmi() || IsHeapNumber(); 324 } 325 326 327 bool Object::IsByteArray() { 328 return Object::IsHeapObject() 329 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE; 330 } 331 332 333 bool Object::IsPixelArray() { 334 return Object::IsHeapObject() && 335 HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE; 336 } 337 338 339 bool Object::IsExternalArray() { 340 if (!Object::IsHeapObject()) 341 return false; 342 InstanceType instance_type = 343 HeapObject::cast(this)->map()->instance_type(); 344 return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE && 345 instance_type <= LAST_EXTERNAL_ARRAY_TYPE); 346 } 347 348 349 bool Object::IsExternalByteArray() { 350 return Object::IsHeapObject() && 351 HeapObject::cast(this)->map()->instance_type() == 352 EXTERNAL_BYTE_ARRAY_TYPE; 353 } 354 355 356 bool Object::IsExternalUnsignedByteArray() { 357 return Object::IsHeapObject() && 358 HeapObject::cast(this)->map()->instance_type() == 359 EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE; 360 } 361 362 363 bool Object::IsExternalShortArray() { 364 return Object::IsHeapObject() && 365 HeapObject::cast(this)->map()->instance_type() == 366 EXTERNAL_SHORT_ARRAY_TYPE; 367 } 368 369 370 bool Object::IsExternalUnsignedShortArray() { 371 return Object::IsHeapObject() && 372 HeapObject::cast(this)->map()->instance_type() == 373 EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE; 374 } 375 376 377 bool Object::IsExternalIntArray() { 378 return Object::IsHeapObject() && 379 HeapObject::cast(this)->map()->instance_type() == 380 EXTERNAL_INT_ARRAY_TYPE; 381 } 382 383 384 bool Object::IsExternalUnsignedIntArray() { 385 return Object::IsHeapObject() && 386 HeapObject::cast(this)->map()->instance_type() == 387 EXTERNAL_UNSIGNED_INT_ARRAY_TYPE; 388 } 389 390 391 bool Object::IsExternalFloatArray() { 392 return Object::IsHeapObject() && 393 HeapObject::cast(this)->map()->instance_type() == 394 EXTERNAL_FLOAT_ARRAY_TYPE; 395 } 396 397 398 bool Object::IsFailure() { 399 return HAS_FAILURE_TAG(this); 400 } 401 402 403 bool Object::IsRetryAfterGC() { 404 return HAS_FAILURE_TAG(this) 405 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC; 406 } 407 408 409 bool Object::IsOutOfMemoryFailure() { 410 return HAS_FAILURE_TAG(this) 411 && Failure::cast(this)->IsOutOfMemoryException(); 412 } 413 414 415 bool Object::IsException() { 416 return this == Failure::Exception(); 417 } 418 419 420 bool Object::IsJSObject() { 421 return IsHeapObject() 422 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE; 423 } 424 425 426 bool Object::IsJSContextExtensionObject() { 427 return IsHeapObject() 428 && (HeapObject::cast(this)->map()->instance_type() == 429 JS_CONTEXT_EXTENSION_OBJECT_TYPE); 430 } 431 432 433 bool Object::IsMap() { 434 return Object::IsHeapObject() 435 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE; 436 } 437 438 439 bool Object::IsFixedArray() { 440 return Object::IsHeapObject() 441 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE; 442 } 443 444 445 bool Object::IsDescriptorArray() { 446 return IsFixedArray(); 447 } 448 449 450 bool Object::IsContext() { 451 return Object::IsHeapObject() 452 && (HeapObject::cast(this)->map() == Heap::context_map() || 453 HeapObject::cast(this)->map() == Heap::catch_context_map() || 454 HeapObject::cast(this)->map() == Heap::global_context_map()); 455 } 456 457 458 bool Object::IsCatchContext() { 459 return Object::IsHeapObject() 460 && HeapObject::cast(this)->map() == Heap::catch_context_map(); 461 } 462 463 464 bool Object::IsGlobalContext() { 465 return Object::IsHeapObject() 466 && HeapObject::cast(this)->map() == Heap::global_context_map(); 467 } 468 469 470 bool Object::IsJSFunction() { 471 return Object::IsHeapObject() 472 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE; 473 } 474 475 476 template <> inline bool Is<JSFunction>(Object* obj) { 477 return obj->IsJSFunction(); 478 } 479 480 481 bool Object::IsCode() { 482 return Object::IsHeapObject() 483 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE; 484 } 485 486 487 bool Object::IsOddball() { 488 return Object::IsHeapObject() 489 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE; 490 } 491 492 493 bool Object::IsJSGlobalPropertyCell() { 494 return Object::IsHeapObject() 495 && HeapObject::cast(this)->map()->instance_type() 496 == JS_GLOBAL_PROPERTY_CELL_TYPE; 497 } 498 499 500 bool Object::IsSharedFunctionInfo() { 501 return Object::IsHeapObject() && 502 (HeapObject::cast(this)->map()->instance_type() == 503 SHARED_FUNCTION_INFO_TYPE); 504 } 505 506 507 bool Object::IsJSValue() { 508 return Object::IsHeapObject() 509 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE; 510 } 511 512 513 bool Object::IsStringWrapper() { 514 return IsJSValue() && JSValue::cast(this)->value()->IsString(); 515 } 516 517 518 bool Object::IsProxy() { 519 return Object::IsHeapObject() 520 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE; 521 } 522 523 524 bool Object::IsBoolean() { 525 return IsTrue() || IsFalse(); 526 } 527 528 529 bool Object::IsJSArray() { 530 return Object::IsHeapObject() 531 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE; 532 } 533 534 535 bool Object::IsJSRegExp() { 536 return Object::IsHeapObject() 537 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE; 538 } 539 540 541 template <> inline bool Is<JSArray>(Object* obj) { 542 return obj->IsJSArray(); 543 } 544 545 546 bool Object::IsHashTable() { 547 return Object::IsHeapObject() 548 && HeapObject::cast(this)->map() == Heap::hash_table_map(); 549 } 550 551 552 bool Object::IsDictionary() { 553 return IsHashTable() && this != Heap::symbol_table(); 554 } 555 556 557 bool Object::IsSymbolTable() { 558 return IsHashTable() && this == Heap::raw_unchecked_symbol_table(); 559 } 560 561 562 bool Object::IsCompilationCacheTable() { 563 return IsHashTable(); 564 } 565 566 567 bool Object::IsMapCache() { 568 return IsHashTable(); 569 } 570 571 572 bool Object::IsPrimitive() { 573 return IsOddball() || IsNumber() || IsString(); 574 } 575 576 577 bool Object::IsJSGlobalProxy() { 578 bool result = IsHeapObject() && 579 (HeapObject::cast(this)->map()->instance_type() == 580 JS_GLOBAL_PROXY_TYPE); 581 ASSERT(!result || IsAccessCheckNeeded()); 582 return result; 583 } 584 585 586 bool Object::IsGlobalObject() { 587 if (!IsHeapObject()) return false; 588 589 InstanceType type = HeapObject::cast(this)->map()->instance_type(); 590 return type == JS_GLOBAL_OBJECT_TYPE || 591 type == JS_BUILTINS_OBJECT_TYPE; 592 } 593 594 595 bool Object::IsJSGlobalObject() { 596 return IsHeapObject() && 597 (HeapObject::cast(this)->map()->instance_type() == 598 JS_GLOBAL_OBJECT_TYPE); 599 } 600 601 602 bool Object::IsJSBuiltinsObject() { 603 return IsHeapObject() && 604 (HeapObject::cast(this)->map()->instance_type() == 605 JS_BUILTINS_OBJECT_TYPE); 606 } 607 608 609 bool Object::IsUndetectableObject() { 610 return IsHeapObject() 611 && HeapObject::cast(this)->map()->is_undetectable(); 612 } 613 614 615 bool Object::IsAccessCheckNeeded() { 616 return IsHeapObject() 617 && HeapObject::cast(this)->map()->is_access_check_needed(); 618 } 619 620 621 bool Object::IsStruct() { 622 if (!IsHeapObject()) return false; 623 switch (HeapObject::cast(this)->map()->instance_type()) { 624 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true; 625 STRUCT_LIST(MAKE_STRUCT_CASE) 626 #undef MAKE_STRUCT_CASE 627 default: return false; 628 } 629 } 630 631 632 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \ 633 bool Object::Is##Name() { \ 634 return Object::IsHeapObject() \ 635 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \ 636 } 637 STRUCT_LIST(MAKE_STRUCT_PREDICATE) 638 #undef MAKE_STRUCT_PREDICATE 639 640 641 bool Object::IsUndefined() { 642 return this == Heap::undefined_value(); 643 } 644 645 646 bool Object::IsTheHole() { 647 return this == Heap::the_hole_value(); 648 } 649 650 651 bool Object::IsNull() { 652 return this == Heap::null_value(); 653 } 654 655 656 bool Object::IsTrue() { 657 return this == Heap::true_value(); 658 } 659 660 661 bool Object::IsFalse() { 662 return this == Heap::false_value(); 663 } 664 665 666 double Object::Number() { 667 ASSERT(IsNumber()); 668 return IsSmi() 669 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value()) 670 : reinterpret_cast<HeapNumber*>(this)->value(); 671 } 672 673 674 675 Object* Object::ToSmi() { 676 if (IsSmi()) return this; 677 if (IsHeapNumber()) { 678 double value = HeapNumber::cast(this)->value(); 679 int int_value = FastD2I(value); 680 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) { 681 return Smi::FromInt(int_value); 682 } 683 } 684 return Failure::Exception(); 685 } 686 687 688 bool Object::HasSpecificClassOf(String* name) { 689 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name); 690 } 691 692 693 Object* Object::GetElement(uint32_t index) { 694 return GetElementWithReceiver(this, index); 695 } 696 697 698 Object* Object::GetProperty(String* key) { 699 PropertyAttributes attributes; 700 return GetPropertyWithReceiver(this, key, &attributes); 701 } 702 703 704 Object* Object::GetProperty(String* key, PropertyAttributes* attributes) { 705 return GetPropertyWithReceiver(this, key, attributes); 706 } 707 708 709 #define FIELD_ADDR(p, offset) \ 710 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) 711 712 #define READ_FIELD(p, offset) \ 713 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset))) 714 715 #define WRITE_FIELD(p, offset, value) \ 716 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) 717 718 719 #define WRITE_BARRIER(object, offset) \ 720 Heap::RecordWrite(object->address(), offset); 721 722 // CONDITIONAL_WRITE_BARRIER must be issued after the actual 723 // write due to the assert validating the written value. 724 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \ 725 if (mode == UPDATE_WRITE_BARRIER) { \ 726 Heap::RecordWrite(object->address(), offset); \ 727 } else { \ 728 ASSERT(mode == SKIP_WRITE_BARRIER); \ 729 ASSERT(Heap::InNewSpace(object) || \ 730 !Heap::InNewSpace(READ_FIELD(object, offset))); \ 731 } 732 733 #define READ_DOUBLE_FIELD(p, offset) \ 734 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset))) 735 736 #define WRITE_DOUBLE_FIELD(p, offset, value) \ 737 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value) 738 739 #define READ_INT_FIELD(p, offset) \ 740 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset))) 741 742 #define WRITE_INT_FIELD(p, offset, value) \ 743 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value) 744 745 #define READ_INTPTR_FIELD(p, offset) \ 746 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset))) 747 748 #define WRITE_INTPTR_FIELD(p, offset, value) \ 749 (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value) 750 751 #define READ_UINT32_FIELD(p, offset) \ 752 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) 753 754 #define WRITE_UINT32_FIELD(p, offset, value) \ 755 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value) 756 757 #define READ_SHORT_FIELD(p, offset) \ 758 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset))) 759 760 #define WRITE_SHORT_FIELD(p, offset, value) \ 761 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value) 762 763 #define READ_BYTE_FIELD(p, offset) \ 764 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset))) 765 766 #define WRITE_BYTE_FIELD(p, offset, value) \ 767 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value) 768 769 770 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) { 771 return &READ_FIELD(obj, byte_offset); 772 } 773 774 775 int Smi::value() { 776 return Internals::SmiValue(this); 777 } 778 779 780 Smi* Smi::FromInt(int value) { 781 ASSERT(Smi::IsValid(value)); 782 int smi_shift_bits = kSmiTagSize + kSmiShiftSize; 783 intptr_t tagged_value = 784 (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag; 785 return reinterpret_cast<Smi*>(tagged_value); 786 } 787 788 789 Smi* Smi::FromIntptr(intptr_t value) { 790 ASSERT(Smi::IsValid(value)); 791 int smi_shift_bits = kSmiTagSize + kSmiShiftSize; 792 return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag); 793 } 794 795 796 Failure::Type Failure::type() const { 797 return static_cast<Type>(value() & kFailureTypeTagMask); 798 } 799 800 801 bool Failure::IsInternalError() const { 802 return type() == INTERNAL_ERROR; 803 } 804 805 806 bool Failure::IsOutOfMemoryException() const { 807 return type() == OUT_OF_MEMORY_EXCEPTION; 808 } 809 810 811 int Failure::requested() const { 812 const int kShiftBits = 813 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits; 814 STATIC_ASSERT(kShiftBits >= 0); 815 ASSERT(type() == RETRY_AFTER_GC); 816 return static_cast<int>(value() >> kShiftBits); 817 } 818 819 820 AllocationSpace Failure::allocation_space() const { 821 ASSERT_EQ(RETRY_AFTER_GC, type()); 822 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize) 823 & kSpaceTagMask); 824 } 825 826 827 Failure* Failure::InternalError() { 828 return Construct(INTERNAL_ERROR); 829 } 830 831 832 Failure* Failure::Exception() { 833 return Construct(EXCEPTION); 834 } 835 836 837 Failure* Failure::OutOfMemoryException() { 838 return Construct(OUT_OF_MEMORY_EXCEPTION); 839 } 840 841 842 intptr_t Failure::value() const { 843 return reinterpret_cast<intptr_t>(this) >> kFailureTagSize; 844 } 845 846 847 Failure* Failure::RetryAfterGC(int requested_bytes) { 848 // Assert that the space encoding fits in the three bytes allotted for it. 849 ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0); 850 intptr_t requested = requested_bytes >> kObjectAlignmentBits; 851 int tag_bits = kSpaceTagSize + kFailureTypeTagSize; 852 if (((requested << tag_bits) >> tag_bits) != requested) { 853 // No room for entire requested size in the bits. Round down to 854 // maximally representable size. 855 requested = static_cast<intptr_t>( 856 (~static_cast<uintptr_t>(0)) >> (tag_bits + 1)); 857 } 858 int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE; 859 return Construct(RETRY_AFTER_GC, value); 860 } 861 862 863 Failure* Failure::Construct(Type type, intptr_t value) { 864 intptr_t info = (static_cast<intptr_t>(value) << kFailureTypeTagSize) | type; 865 ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info); 866 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag); 867 } 868 869 870 bool Smi::IsValid(intptr_t value) { 871 #ifdef DEBUG 872 bool in_range = (value >= kMinValue) && (value <= kMaxValue); 873 #endif 874 875 #ifdef V8_TARGET_ARCH_X64 876 // To be representable as a long smi, the value must be a 32-bit integer. 877 bool result = (value == static_cast<int32_t>(value)); 878 #else 879 // To be representable as an tagged small integer, the two 880 // most-significant bits of 'value' must be either 00 or 11 due to 881 // sign-extension. To check this we add 01 to the two 882 // most-significant bits, and check if the most-significant bit is 0 883 // 884 // CAUTION: The original code below: 885 // bool result = ((value + 0x40000000) & 0x80000000) == 0; 886 // may lead to incorrect results according to the C language spec, and 887 // in fact doesn't work correctly with gcc4.1.1 in some cases: The 888 // compiler may produce undefined results in case of signed integer 889 // overflow. The computation must be done w/ unsigned ints. 890 bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U); 891 #endif 892 ASSERT(result == in_range); 893 return result; 894 } 895 896 897 MapWord MapWord::FromMap(Map* map) { 898 return MapWord(reinterpret_cast<uintptr_t>(map)); 899 } 900 901 902 Map* MapWord::ToMap() { 903 return reinterpret_cast<Map*>(value_); 904 } 905 906 907 bool MapWord::IsForwardingAddress() { 908 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_)); 909 } 910 911 912 MapWord MapWord::FromForwardingAddress(HeapObject* object) { 913 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag; 914 return MapWord(reinterpret_cast<uintptr_t>(raw)); 915 } 916 917 918 HeapObject* MapWord::ToForwardingAddress() { 919 ASSERT(IsForwardingAddress()); 920 return HeapObject::FromAddress(reinterpret_cast<Address>(value_)); 921 } 922 923 924 bool MapWord::IsMarked() { 925 return (value_ & kMarkingMask) == 0; 926 } 927 928 929 void MapWord::SetMark() { 930 value_ &= ~kMarkingMask; 931 } 932 933 934 void MapWord::ClearMark() { 935 value_ |= kMarkingMask; 936 } 937 938 939 bool MapWord::IsOverflowed() { 940 return (value_ & kOverflowMask) != 0; 941 } 942 943 944 void MapWord::SetOverflow() { 945 value_ |= kOverflowMask; 946 } 947 948 949 void MapWord::ClearOverflow() { 950 value_ &= ~kOverflowMask; 951 } 952 953 954 MapWord MapWord::EncodeAddress(Address map_address, int offset) { 955 // Offset is the distance in live bytes from the first live object in the 956 // same page. The offset between two objects in the same page should not 957 // exceed the object area size of a page. 958 ASSERT(0 <= offset && offset < Page::kObjectAreaSize); 959 960 uintptr_t compact_offset = offset >> kObjectAlignmentBits; 961 ASSERT(compact_offset < (1 << kForwardingOffsetBits)); 962 963 Page* map_page = Page::FromAddress(map_address); 964 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index); 965 966 uintptr_t map_page_offset = 967 map_page->Offset(map_address) >> kMapAlignmentBits; 968 969 uintptr_t encoding = 970 (compact_offset << kForwardingOffsetShift) | 971 (map_page_offset << kMapPageOffsetShift) | 972 (map_page->mc_page_index << kMapPageIndexShift); 973 return MapWord(encoding); 974 } 975 976 977 Address MapWord::DecodeMapAddress(MapSpace* map_space) { 978 int map_page_index = 979 static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift); 980 ASSERT_MAP_PAGE_INDEX(map_page_index); 981 982 int map_page_offset = static_cast<int>( 983 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) << 984 kMapAlignmentBits); 985 986 return (map_space->PageAddress(map_page_index) + map_page_offset); 987 } 988 989 990 int MapWord::DecodeOffset() { 991 // The offset field is represented in the kForwardingOffsetBits 992 // most-significant bits. 993 uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits; 994 ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize)); 995 return static_cast<int>(offset); 996 } 997 998 999 MapWord MapWord::FromEncodedAddress(Address address) { 1000 return MapWord(reinterpret_cast<uintptr_t>(address)); 1001 } 1002 1003 1004 Address MapWord::ToEncodedAddress() { 1005 return reinterpret_cast<Address>(value_); 1006 } 1007 1008 1009 #ifdef DEBUG 1010 void HeapObject::VerifyObjectField(int offset) { 1011 VerifyPointer(READ_FIELD(this, offset)); 1012 } 1013 #endif 1014 1015 1016 Map* HeapObject::map() { 1017 return map_word().ToMap(); 1018 } 1019 1020 1021 void HeapObject::set_map(Map* value) { 1022 set_map_word(MapWord::FromMap(value)); 1023 } 1024 1025 1026 MapWord HeapObject::map_word() { 1027 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset))); 1028 } 1029 1030 1031 void HeapObject::set_map_word(MapWord map_word) { 1032 // WRITE_FIELD does not update the remembered set, but there is no need 1033 // here. 1034 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_)); 1035 } 1036 1037 1038 HeapObject* HeapObject::FromAddress(Address address) { 1039 ASSERT_TAG_ALIGNED(address); 1040 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag); 1041 } 1042 1043 1044 Address HeapObject::address() { 1045 return reinterpret_cast<Address>(this) - kHeapObjectTag; 1046 } 1047 1048 1049 int HeapObject::Size() { 1050 return SizeFromMap(map()); 1051 } 1052 1053 1054 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) { 1055 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)), 1056 reinterpret_cast<Object**>(FIELD_ADDR(this, end))); 1057 } 1058 1059 1060 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) { 1061 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset))); 1062 } 1063 1064 1065 bool HeapObject::IsMarked() { 1066 return map_word().IsMarked(); 1067 } 1068 1069 1070 void HeapObject::SetMark() { 1071 ASSERT(!IsMarked()); 1072 MapWord first_word = map_word(); 1073 first_word.SetMark(); 1074 set_map_word(first_word); 1075 } 1076 1077 1078 void HeapObject::ClearMark() { 1079 ASSERT(IsMarked()); 1080 MapWord first_word = map_word(); 1081 first_word.ClearMark(); 1082 set_map_word(first_word); 1083 } 1084 1085 1086 bool HeapObject::IsOverflowed() { 1087 return map_word().IsOverflowed(); 1088 } 1089 1090 1091 void HeapObject::SetOverflow() { 1092 MapWord first_word = map_word(); 1093 first_word.SetOverflow(); 1094 set_map_word(first_word); 1095 } 1096 1097 1098 void HeapObject::ClearOverflow() { 1099 ASSERT(IsOverflowed()); 1100 MapWord first_word = map_word(); 1101 first_word.ClearOverflow(); 1102 set_map_word(first_word); 1103 } 1104 1105 1106 double HeapNumber::value() { 1107 return READ_DOUBLE_FIELD(this, kValueOffset); 1108 } 1109 1110 1111 void HeapNumber::set_value(double value) { 1112 WRITE_DOUBLE_FIELD(this, kValueOffset, value); 1113 } 1114 1115 1116 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset) 1117 1118 1119 Array* JSObject::elements() { 1120 Object* array = READ_FIELD(this, kElementsOffset); 1121 // In the assert below Dictionary is covered under FixedArray. 1122 ASSERT(array->IsFixedArray() || array->IsPixelArray() || 1123 array->IsExternalArray()); 1124 return reinterpret_cast<Array*>(array); 1125 } 1126 1127 1128 void JSObject::set_elements(Array* value, WriteBarrierMode mode) { 1129 // In the assert below Dictionary is covered under FixedArray. 1130 ASSERT(value->IsFixedArray() || value->IsPixelArray() || 1131 value->IsExternalArray()); 1132 WRITE_FIELD(this, kElementsOffset, value); 1133 CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode); 1134 } 1135 1136 1137 void JSObject::initialize_properties() { 1138 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); 1139 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array()); 1140 } 1141 1142 1143 void JSObject::initialize_elements() { 1144 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); 1145 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array()); 1146 } 1147 1148 1149 ACCESSORS(Oddball, to_string, String, kToStringOffset) 1150 ACCESSORS(Oddball, to_number, Object, kToNumberOffset) 1151 1152 1153 Object* JSGlobalPropertyCell::value() { 1154 return READ_FIELD(this, kValueOffset); 1155 } 1156 1157 1158 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) { 1159 // The write barrier is not used for global property cells. 1160 ASSERT(!val->IsJSGlobalPropertyCell()); 1161 WRITE_FIELD(this, kValueOffset, val); 1162 } 1163 1164 1165 int JSObject::GetHeaderSize() { 1166 InstanceType type = map()->instance_type(); 1167 // Check for the most common kind of JavaScript object before 1168 // falling into the generic switch. This speeds up the internal 1169 // field operations considerably on average. 1170 if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize; 1171 switch (type) { 1172 case JS_GLOBAL_PROXY_TYPE: 1173 return JSGlobalProxy::kSize; 1174 case JS_GLOBAL_OBJECT_TYPE: 1175 return JSGlobalObject::kSize; 1176 case JS_BUILTINS_OBJECT_TYPE: 1177 return JSBuiltinsObject::kSize; 1178 case JS_FUNCTION_TYPE: 1179 return JSFunction::kSize; 1180 case JS_VALUE_TYPE: 1181 return JSValue::kSize; 1182 case JS_ARRAY_TYPE: 1183 return JSValue::kSize; 1184 case JS_REGEXP_TYPE: 1185 return JSValue::kSize; 1186 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: 1187 return JSObject::kHeaderSize; 1188 default: 1189 UNREACHABLE(); 1190 return 0; 1191 } 1192 } 1193 1194 1195 int JSObject::GetInternalFieldCount() { 1196 ASSERT(1 << kPointerSizeLog2 == kPointerSize); 1197 // Make sure to adjust for the number of in-object properties. These 1198 // properties do contribute to the size, but are not internal fields. 1199 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) - 1200 map()->inobject_properties(); 1201 } 1202 1203 1204 Object* JSObject::GetInternalField(int index) { 1205 ASSERT(index < GetInternalFieldCount() && index >= 0); 1206 // Internal objects do follow immediately after the header, whereas in-object 1207 // properties are at the end of the object. Therefore there is no need 1208 // to adjust the index here. 1209 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); 1210 } 1211 1212 1213 void JSObject::SetInternalField(int index, Object* value) { 1214 ASSERT(index < GetInternalFieldCount() && index >= 0); 1215 // Internal objects do follow immediately after the header, whereas in-object 1216 // properties are at the end of the object. Therefore there is no need 1217 // to adjust the index here. 1218 int offset = GetHeaderSize() + (kPointerSize * index); 1219 WRITE_FIELD(this, offset, value); 1220 WRITE_BARRIER(this, offset); 1221 } 1222 1223 1224 // Access fast-case object properties at index. The use of these routines 1225 // is needed to correctly distinguish between properties stored in-object and 1226 // properties stored in the properties array. 1227 Object* JSObject::FastPropertyAt(int index) { 1228 // Adjust for the number of properties stored in the object. 1229 index -= map()->inobject_properties(); 1230 if (index < 0) { 1231 int offset = map()->instance_size() + (index * kPointerSize); 1232 return READ_FIELD(this, offset); 1233 } else { 1234 ASSERT(index < properties()->length()); 1235 return properties()->get(index); 1236 } 1237 } 1238 1239 1240 Object* JSObject::FastPropertyAtPut(int index, Object* value) { 1241 // Adjust for the number of properties stored in the object. 1242 index -= map()->inobject_properties(); 1243 if (index < 0) { 1244 int offset = map()->instance_size() + (index * kPointerSize); 1245 WRITE_FIELD(this, offset, value); 1246 WRITE_BARRIER(this, offset); 1247 } else { 1248 ASSERT(index < properties()->length()); 1249 properties()->set(index, value); 1250 } 1251 return value; 1252 } 1253 1254 1255 Object* JSObject::InObjectPropertyAt(int index) { 1256 // Adjust for the number of properties stored in the object. 1257 index -= map()->inobject_properties(); 1258 ASSERT(index < 0); 1259 int offset = map()->instance_size() + (index * kPointerSize); 1260 return READ_FIELD(this, offset); 1261 } 1262 1263 1264 Object* JSObject::InObjectPropertyAtPut(int index, 1265 Object* value, 1266 WriteBarrierMode mode) { 1267 // Adjust for the number of properties stored in the object. 1268 index -= map()->inobject_properties(); 1269 ASSERT(index < 0); 1270 int offset = map()->instance_size() + (index * kPointerSize); 1271 WRITE_FIELD(this, offset, value); 1272 CONDITIONAL_WRITE_BARRIER(this, offset, mode); 1273 return value; 1274 } 1275 1276 1277 1278 void JSObject::InitializeBody(int object_size) { 1279 Object* value = Heap::undefined_value(); 1280 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 1281 WRITE_FIELD(this, offset, value); 1282 } 1283 } 1284 1285 1286 void Struct::InitializeBody(int object_size) { 1287 Object* value = Heap::undefined_value(); 1288 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) { 1289 WRITE_FIELD(this, offset, value); 1290 } 1291 } 1292 1293 1294 bool JSObject::HasFastProperties() { 1295 return !properties()->IsDictionary(); 1296 } 1297 1298 1299 bool Array::IndexFromObject(Object* object, uint32_t* index) { 1300 if (object->IsSmi()) { 1301 int value = Smi::cast(object)->value(); 1302 if (value < 0) return false; 1303 *index = value; 1304 return true; 1305 } 1306 if (object->IsHeapNumber()) { 1307 double value = HeapNumber::cast(object)->value(); 1308 uint32_t uint_value = static_cast<uint32_t>(value); 1309 if (value == static_cast<double>(uint_value)) { 1310 *index = uint_value; 1311 return true; 1312 } 1313 } 1314 return false; 1315 } 1316 1317 1318 bool Object::IsStringObjectWithCharacterAt(uint32_t index) { 1319 if (!this->IsJSValue()) return false; 1320 1321 JSValue* js_value = JSValue::cast(this); 1322 if (!js_value->value()->IsString()) return false; 1323 1324 String* str = String::cast(js_value->value()); 1325 if (index >= (uint32_t)str->length()) return false; 1326 1327 return true; 1328 } 1329 1330 1331 Object* FixedArray::get(int index) { 1332 ASSERT(index >= 0 && index < this->length()); 1333 return READ_FIELD(this, kHeaderSize + index * kPointerSize); 1334 } 1335 1336 1337 void FixedArray::set(int index, Smi* value) { 1338 ASSERT(reinterpret_cast<Object*>(value)->IsSmi()); 1339 int offset = kHeaderSize + index * kPointerSize; 1340 WRITE_FIELD(this, offset, value); 1341 } 1342 1343 1344 void FixedArray::set(int index, Object* value) { 1345 ASSERT(index >= 0 && index < this->length()); 1346 int offset = kHeaderSize + index * kPointerSize; 1347 WRITE_FIELD(this, offset, value); 1348 WRITE_BARRIER(this, offset); 1349 } 1350 1351 1352 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) { 1353 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER; 1354 return UPDATE_WRITE_BARRIER; 1355 } 1356 1357 1358 void FixedArray::set(int index, 1359 Object* value, 1360 WriteBarrierMode mode) { 1361 ASSERT(index >= 0 && index < this->length()); 1362 int offset = kHeaderSize + index * kPointerSize; 1363 WRITE_FIELD(this, offset, value); 1364 CONDITIONAL_WRITE_BARRIER(this, offset, mode); 1365 } 1366 1367 1368 void FixedArray::fast_set(FixedArray* array, int index, Object* value) { 1369 ASSERT(index >= 0 && index < array->length()); 1370 ASSERT(!Heap::InNewSpace(value)); 1371 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value); 1372 } 1373 1374 1375 void FixedArray::set_undefined(int index) { 1376 ASSERT(index >= 0 && index < this->length()); 1377 ASSERT(!Heap::InNewSpace(Heap::undefined_value())); 1378 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, 1379 Heap::undefined_value()); 1380 } 1381 1382 1383 void FixedArray::set_null(int index) { 1384 ASSERT(index >= 0 && index < this->length()); 1385 ASSERT(!Heap::InNewSpace(Heap::null_value())); 1386 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value()); 1387 } 1388 1389 1390 void FixedArray::set_the_hole(int index) { 1391 ASSERT(index >= 0 && index < this->length()); 1392 ASSERT(!Heap::InNewSpace(Heap::the_hole_value())); 1393 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value()); 1394 } 1395 1396 1397 bool DescriptorArray::IsEmpty() { 1398 ASSERT(this == Heap::empty_descriptor_array() || 1399 this->length() > 2); 1400 return this == Heap::empty_descriptor_array(); 1401 } 1402 1403 1404 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) { 1405 Object* tmp = array->get(first); 1406 fast_set(array, first, array->get(second)); 1407 fast_set(array, second, tmp); 1408 } 1409 1410 1411 int DescriptorArray::Search(String* name) { 1412 SLOW_ASSERT(IsSortedNoDuplicates()); 1413 1414 // Check for empty descriptor array. 1415 int nof = number_of_descriptors(); 1416 if (nof == 0) return kNotFound; 1417 1418 // Fast case: do linear search for small arrays. 1419 const int kMaxElementsForLinearSearch = 8; 1420 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { 1421 return LinearSearch(name, nof); 1422 } 1423 1424 // Slow case: perform binary search. 1425 return BinarySearch(name, 0, nof - 1); 1426 } 1427 1428 1429 String* DescriptorArray::GetKey(int descriptor_number) { 1430 ASSERT(descriptor_number < number_of_descriptors()); 1431 return String::cast(get(ToKeyIndex(descriptor_number))); 1432 } 1433 1434 1435 Object* DescriptorArray::GetValue(int descriptor_number) { 1436 ASSERT(descriptor_number < number_of_descriptors()); 1437 return GetContentArray()->get(ToValueIndex(descriptor_number)); 1438 } 1439 1440 1441 Smi* DescriptorArray::GetDetails(int descriptor_number) { 1442 ASSERT(descriptor_number < number_of_descriptors()); 1443 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number))); 1444 } 1445 1446 1447 PropertyType DescriptorArray::GetType(int descriptor_number) { 1448 ASSERT(descriptor_number < number_of_descriptors()); 1449 return PropertyDetails(GetDetails(descriptor_number)).type(); 1450 } 1451 1452 1453 int DescriptorArray::GetFieldIndex(int descriptor_number) { 1454 return Descriptor::IndexFromValue(GetValue(descriptor_number)); 1455 } 1456 1457 1458 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { 1459 return JSFunction::cast(GetValue(descriptor_number)); 1460 } 1461 1462 1463 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { 1464 ASSERT(GetType(descriptor_number) == CALLBACKS); 1465 return GetValue(descriptor_number); 1466 } 1467 1468 1469 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { 1470 ASSERT(GetType(descriptor_number) == CALLBACKS); 1471 Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number)); 1472 return reinterpret_cast<AccessorDescriptor*>(p->proxy()); 1473 } 1474 1475 1476 bool DescriptorArray::IsProperty(int descriptor_number) { 1477 return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE; 1478 } 1479 1480 1481 bool DescriptorArray::IsTransition(int descriptor_number) { 1482 PropertyType t = GetType(descriptor_number); 1483 return t == MAP_TRANSITION || t == CONSTANT_TRANSITION; 1484 } 1485 1486 1487 bool DescriptorArray::IsNullDescriptor(int descriptor_number) { 1488 return GetType(descriptor_number) == NULL_DESCRIPTOR; 1489 } 1490 1491 1492 bool DescriptorArray::IsDontEnum(int descriptor_number) { 1493 return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum(); 1494 } 1495 1496 1497 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { 1498 desc->Init(GetKey(descriptor_number), 1499 GetValue(descriptor_number), 1500 GetDetails(descriptor_number)); 1501 } 1502 1503 1504 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) { 1505 // Range check. 1506 ASSERT(descriptor_number < number_of_descriptors()); 1507 1508 // Make sure none of the elements in desc are in new space. 1509 ASSERT(!Heap::InNewSpace(desc->GetKey())); 1510 ASSERT(!Heap::InNewSpace(desc->GetValue())); 1511 1512 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey()); 1513 FixedArray* content_array = GetContentArray(); 1514 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue()); 1515 fast_set(content_array, ToDetailsIndex(descriptor_number), 1516 desc->GetDetails().AsSmi()); 1517 } 1518 1519 1520 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) { 1521 Descriptor desc; 1522 src->Get(src_index, &desc); 1523 Set(index, &desc); 1524 } 1525 1526 1527 void DescriptorArray::Swap(int first, int second) { 1528 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second)); 1529 FixedArray* content_array = GetContentArray(); 1530 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second)); 1531 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second)); 1532 } 1533 1534 1535 bool NumberDictionary::requires_slow_elements() { 1536 Object* max_index_object = get(kMaxNumberKeyIndex); 1537 if (!max_index_object->IsSmi()) return false; 1538 return 0 != 1539 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); 1540 } 1541 1542 uint32_t NumberDictionary::max_number_key() { 1543 ASSERT(!requires_slow_elements()); 1544 Object* max_index_object = get(kMaxNumberKeyIndex); 1545 if (!max_index_object->IsSmi()) return 0; 1546 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value()); 1547 return value >> kRequiresSlowElementsTagSize; 1548 } 1549 1550 void NumberDictionary::set_requires_slow_elements() { 1551 set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); 1552 } 1553 1554 1555 // ------------------------------------ 1556 // Cast operations 1557 1558 1559 CAST_ACCESSOR(FixedArray) 1560 CAST_ACCESSOR(DescriptorArray) 1561 CAST_ACCESSOR(SymbolTable) 1562 CAST_ACCESSOR(CompilationCacheTable) 1563 CAST_ACCESSOR(MapCache) 1564 CAST_ACCESSOR(String) 1565 CAST_ACCESSOR(SeqString) 1566 CAST_ACCESSOR(SeqAsciiString) 1567 CAST_ACCESSOR(SeqTwoByteString) 1568 CAST_ACCESSOR(ConsString) 1569 CAST_ACCESSOR(ExternalString) 1570 CAST_ACCESSOR(ExternalAsciiString) 1571 CAST_ACCESSOR(ExternalTwoByteString) 1572 CAST_ACCESSOR(JSObject) 1573 CAST_ACCESSOR(Smi) 1574 CAST_ACCESSOR(Failure) 1575 CAST_ACCESSOR(HeapObject) 1576 CAST_ACCESSOR(HeapNumber) 1577 CAST_ACCESSOR(Oddball) 1578 CAST_ACCESSOR(JSGlobalPropertyCell) 1579 CAST_ACCESSOR(SharedFunctionInfo) 1580 CAST_ACCESSOR(Map) 1581 CAST_ACCESSOR(JSFunction) 1582 CAST_ACCESSOR(GlobalObject) 1583 CAST_ACCESSOR(JSGlobalProxy) 1584 CAST_ACCESSOR(JSGlobalObject) 1585 CAST_ACCESSOR(JSBuiltinsObject) 1586 CAST_ACCESSOR(Code) 1587 CAST_ACCESSOR(JSArray) 1588 CAST_ACCESSOR(JSRegExp) 1589 CAST_ACCESSOR(Proxy) 1590 CAST_ACCESSOR(ByteArray) 1591 CAST_ACCESSOR(PixelArray) 1592 CAST_ACCESSOR(ExternalArray) 1593 CAST_ACCESSOR(ExternalByteArray) 1594 CAST_ACCESSOR(ExternalUnsignedByteArray) 1595 CAST_ACCESSOR(ExternalShortArray) 1596 CAST_ACCESSOR(ExternalUnsignedShortArray) 1597 CAST_ACCESSOR(ExternalIntArray) 1598 CAST_ACCESSOR(ExternalUnsignedIntArray) 1599 CAST_ACCESSOR(ExternalFloatArray) 1600 CAST_ACCESSOR(Struct) 1601 1602 1603 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name) 1604 STRUCT_LIST(MAKE_STRUCT_CAST) 1605 #undef MAKE_STRUCT_CAST 1606 1607 1608 template <typename Shape, typename Key> 1609 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) { 1610 ASSERT(obj->IsHashTable()); 1611 return reinterpret_cast<HashTable*>(obj); 1612 } 1613 1614 1615 INT_ACCESSORS(Array, length, kLengthOffset) 1616 1617 1618 INT_ACCESSORS(String, length, kLengthOffset) 1619 1620 1621 uint32_t String::hash_field() { 1622 return READ_UINT32_FIELD(this, kHashFieldOffset); 1623 } 1624 1625 1626 void String::set_hash_field(uint32_t value) { 1627 WRITE_UINT32_FIELD(this, kHashFieldOffset, value); 1628 } 1629 1630 1631 bool String::Equals(String* other) { 1632 if (other == this) return true; 1633 if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) { 1634 return false; 1635 } 1636 return SlowEquals(other); 1637 } 1638 1639 1640 Object* String::TryFlattenIfNotFlat() { 1641 // We don't need to flatten strings that are already flat. Since this code 1642 // is inlined, it can be helpful in the flat case to not call out to Flatten. 1643 if (!IsFlat()) { 1644 return TryFlatten(); 1645 } 1646 return this; 1647 } 1648 1649 1650 uint16_t String::Get(int index) { 1651 ASSERT(index >= 0 && index < length()); 1652 switch (StringShape(this).full_representation_tag()) { 1653 case kSeqStringTag | kAsciiStringTag: 1654 return SeqAsciiString::cast(this)->SeqAsciiStringGet(index); 1655 case kSeqStringTag | kTwoByteStringTag: 1656 return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index); 1657 case kConsStringTag | kAsciiStringTag: 1658 case kConsStringTag | kTwoByteStringTag: 1659 return ConsString::cast(this)->ConsStringGet(index); 1660 case kExternalStringTag | kAsciiStringTag: 1661 return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index); 1662 case kExternalStringTag | kTwoByteStringTag: 1663 return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index); 1664 default: 1665 break; 1666 } 1667 1668 UNREACHABLE(); 1669 return 0; 1670 } 1671 1672 1673 void String::Set(int index, uint16_t value) { 1674 ASSERT(index >= 0 && index < length()); 1675 ASSERT(StringShape(this).IsSequential()); 1676 1677 return this->IsAsciiRepresentation() 1678 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value) 1679 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value); 1680 } 1681 1682 1683 bool String::IsFlat() { 1684 switch (StringShape(this).representation_tag()) { 1685 case kConsStringTag: { 1686 String* second = ConsString::cast(this)->second(); 1687 // Only flattened strings have second part empty. 1688 return second->length() == 0; 1689 } 1690 default: 1691 return true; 1692 } 1693 } 1694 1695 1696 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) { 1697 ASSERT(index >= 0 && index < length()); 1698 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 1699 } 1700 1701 1702 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) { 1703 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode); 1704 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, 1705 static_cast<byte>(value)); 1706 } 1707 1708 1709 Address SeqAsciiString::GetCharsAddress() { 1710 return FIELD_ADDR(this, kHeaderSize); 1711 } 1712 1713 1714 char* SeqAsciiString::GetChars() { 1715 return reinterpret_cast<char*>(GetCharsAddress()); 1716 } 1717 1718 1719 Address SeqTwoByteString::GetCharsAddress() { 1720 return FIELD_ADDR(this, kHeaderSize); 1721 } 1722 1723 1724 uc16* SeqTwoByteString::GetChars() { 1725 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize)); 1726 } 1727 1728 1729 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) { 1730 ASSERT(index >= 0 && index < length()); 1731 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize); 1732 } 1733 1734 1735 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { 1736 ASSERT(index >= 0 && index < length()); 1737 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value); 1738 } 1739 1740 1741 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { 1742 uint32_t length = READ_INT_FIELD(this, kLengthOffset); 1743 return SizeFor(length); 1744 } 1745 1746 1747 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) { 1748 uint32_t length = READ_INT_FIELD(this, kLengthOffset); 1749 return SizeFor(length); 1750 } 1751 1752 1753 String* ConsString::first() { 1754 return String::cast(READ_FIELD(this, kFirstOffset)); 1755 } 1756 1757 1758 Object* ConsString::unchecked_first() { 1759 return READ_FIELD(this, kFirstOffset); 1760 } 1761 1762 1763 void ConsString::set_first(String* value, WriteBarrierMode mode) { 1764 WRITE_FIELD(this, kFirstOffset, value); 1765 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode); 1766 } 1767 1768 1769 String* ConsString::second() { 1770 return String::cast(READ_FIELD(this, kSecondOffset)); 1771 } 1772 1773 1774 Object* ConsString::unchecked_second() { 1775 return READ_FIELD(this, kSecondOffset); 1776 } 1777 1778 1779 void ConsString::set_second(String* value, WriteBarrierMode mode) { 1780 WRITE_FIELD(this, kSecondOffset, value); 1781 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode); 1782 } 1783 1784 1785 ExternalAsciiString::Resource* ExternalAsciiString::resource() { 1786 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 1787 } 1788 1789 1790 void ExternalAsciiString::set_resource( 1791 ExternalAsciiString::Resource* resource) { 1792 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource; 1793 } 1794 1795 1796 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() { 1797 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)); 1798 } 1799 1800 1801 void ExternalTwoByteString::set_resource( 1802 ExternalTwoByteString::Resource* resource) { 1803 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource; 1804 } 1805 1806 1807 byte ByteArray::get(int index) { 1808 ASSERT(index >= 0 && index < this->length()); 1809 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize); 1810 } 1811 1812 1813 void ByteArray::set(int index, byte value) { 1814 ASSERT(index >= 0 && index < this->length()); 1815 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value); 1816 } 1817 1818 1819 int ByteArray::get_int(int index) { 1820 ASSERT(index >= 0 && (index * kIntSize) < this->length()); 1821 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize); 1822 } 1823 1824 1825 ByteArray* ByteArray::FromDataStartAddress(Address address) { 1826 ASSERT_TAG_ALIGNED(address); 1827 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag); 1828 } 1829 1830 1831 Address ByteArray::GetDataStartAddress() { 1832 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize; 1833 } 1834 1835 1836 uint8_t* PixelArray::external_pointer() { 1837 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset); 1838 return reinterpret_cast<uint8_t*>(ptr); 1839 } 1840 1841 1842 void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) { 1843 intptr_t ptr = reinterpret_cast<intptr_t>(value); 1844 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr); 1845 } 1846 1847 1848 uint8_t PixelArray::get(int index) { 1849 ASSERT((index >= 0) && (index < this->length())); 1850 uint8_t* ptr = external_pointer(); 1851 return ptr[index]; 1852 } 1853 1854 1855 void PixelArray::set(int index, uint8_t value) { 1856 ASSERT((index >= 0) && (index < this->length())); 1857 uint8_t* ptr = external_pointer(); 1858 ptr[index] = value; 1859 } 1860 1861 1862 void* ExternalArray::external_pointer() { 1863 intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset); 1864 return reinterpret_cast<void*>(ptr); 1865 } 1866 1867 1868 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) { 1869 intptr_t ptr = reinterpret_cast<intptr_t>(value); 1870 WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr); 1871 } 1872 1873 1874 int8_t ExternalByteArray::get(int index) { 1875 ASSERT((index >= 0) && (index < this->length())); 1876 int8_t* ptr = static_cast<int8_t*>(external_pointer()); 1877 return ptr[index]; 1878 } 1879 1880 1881 void ExternalByteArray::set(int index, int8_t value) { 1882 ASSERT((index >= 0) && (index < this->length())); 1883 int8_t* ptr = static_cast<int8_t*>(external_pointer()); 1884 ptr[index] = value; 1885 } 1886 1887 1888 uint8_t ExternalUnsignedByteArray::get(int index) { 1889 ASSERT((index >= 0) && (index < this->length())); 1890 uint8_t* ptr = static_cast<uint8_t*>(external_pointer()); 1891 return ptr[index]; 1892 } 1893 1894 1895 void ExternalUnsignedByteArray::set(int index, uint8_t value) { 1896 ASSERT((index >= 0) && (index < this->length())); 1897 uint8_t* ptr = static_cast<uint8_t*>(external_pointer()); 1898 ptr[index] = value; 1899 } 1900 1901 1902 int16_t ExternalShortArray::get(int index) { 1903 ASSERT((index >= 0) && (index < this->length())); 1904 int16_t* ptr = static_cast<int16_t*>(external_pointer()); 1905 return ptr[index]; 1906 } 1907 1908 1909 void ExternalShortArray::set(int index, int16_t value) { 1910 ASSERT((index >= 0) && (index < this->length())); 1911 int16_t* ptr = static_cast<int16_t*>(external_pointer()); 1912 ptr[index] = value; 1913 } 1914 1915 1916 uint16_t ExternalUnsignedShortArray::get(int index) { 1917 ASSERT((index >= 0) && (index < this->length())); 1918 uint16_t* ptr = static_cast<uint16_t*>(external_pointer()); 1919 return ptr[index]; 1920 } 1921 1922 1923 void ExternalUnsignedShortArray::set(int index, uint16_t value) { 1924 ASSERT((index >= 0) && (index < this->length())); 1925 uint16_t* ptr = static_cast<uint16_t*>(external_pointer()); 1926 ptr[index] = value; 1927 } 1928 1929 1930 int32_t ExternalIntArray::get(int index) { 1931 ASSERT((index >= 0) && (index < this->length())); 1932 int32_t* ptr = static_cast<int32_t*>(external_pointer()); 1933 return ptr[index]; 1934 } 1935 1936 1937 void ExternalIntArray::set(int index, int32_t value) { 1938 ASSERT((index >= 0) && (index < this->length())); 1939 int32_t* ptr = static_cast<int32_t*>(external_pointer()); 1940 ptr[index] = value; 1941 } 1942 1943 1944 uint32_t ExternalUnsignedIntArray::get(int index) { 1945 ASSERT((index >= 0) && (index < this->length())); 1946 uint32_t* ptr = static_cast<uint32_t*>(external_pointer()); 1947 return ptr[index]; 1948 } 1949 1950 1951 void ExternalUnsignedIntArray::set(int index, uint32_t value) { 1952 ASSERT((index >= 0) && (index < this->length())); 1953 uint32_t* ptr = static_cast<uint32_t*>(external_pointer()); 1954 ptr[index] = value; 1955 } 1956 1957 1958 float ExternalFloatArray::get(int index) { 1959 ASSERT((index >= 0) && (index < this->length())); 1960 float* ptr = static_cast<float*>(external_pointer()); 1961 return ptr[index]; 1962 } 1963 1964 1965 void ExternalFloatArray::set(int index, float value) { 1966 ASSERT((index >= 0) && (index < this->length())); 1967 float* ptr = static_cast<float*>(external_pointer()); 1968 ptr[index] = value; 1969 } 1970 1971 1972 int Map::instance_size() { 1973 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2; 1974 } 1975 1976 1977 int Map::inobject_properties() { 1978 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset); 1979 } 1980 1981 1982 int Map::pre_allocated_property_fields() { 1983 return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset); 1984 } 1985 1986 1987 int HeapObject::SizeFromMap(Map* map) { 1988 InstanceType instance_type = map->instance_type(); 1989 // Only inline the most frequent cases. 1990 if (instance_type == JS_OBJECT_TYPE || 1991 (instance_type & (kIsNotStringMask | kStringRepresentationMask)) == 1992 (kStringTag | kConsStringTag) || 1993 instance_type == JS_ARRAY_TYPE) return map->instance_size(); 1994 if (instance_type == FIXED_ARRAY_TYPE) { 1995 return reinterpret_cast<FixedArray*>(this)->FixedArraySize(); 1996 } 1997 if (instance_type == BYTE_ARRAY_TYPE) { 1998 return reinterpret_cast<ByteArray*>(this)->ByteArraySize(); 1999 } 2000 // Otherwise do the general size computation. 2001 return SlowSizeFromMap(map); 2002 } 2003 2004 2005 void Map::set_instance_size(int value) { 2006 ASSERT_EQ(0, value & (kPointerSize - 1)); 2007 value >>= kPointerSizeLog2; 2008 ASSERT(0 <= value && value < 256); 2009 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value)); 2010 } 2011 2012 2013 void Map::set_inobject_properties(int value) { 2014 ASSERT(0 <= value && value < 256); 2015 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value)); 2016 } 2017 2018 2019 void Map::set_pre_allocated_property_fields(int value) { 2020 ASSERT(0 <= value && value < 256); 2021 WRITE_BYTE_FIELD(this, 2022 kPreAllocatedPropertyFieldsOffset, 2023 static_cast<byte>(value)); 2024 } 2025 2026 2027 InstanceType Map::instance_type() { 2028 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset)); 2029 } 2030 2031 2032 void Map::set_instance_type(InstanceType value) { 2033 ASSERT(0 <= value && value < 256); 2034 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value); 2035 } 2036 2037 2038 int Map::unused_property_fields() { 2039 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset); 2040 } 2041 2042 2043 void Map::set_unused_property_fields(int value) { 2044 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255)); 2045 } 2046 2047 2048 byte Map::bit_field() { 2049 return READ_BYTE_FIELD(this, kBitFieldOffset); 2050 } 2051 2052 2053 void Map::set_bit_field(byte value) { 2054 WRITE_BYTE_FIELD(this, kBitFieldOffset, value); 2055 } 2056 2057 2058 byte Map::bit_field2() { 2059 return READ_BYTE_FIELD(this, kBitField2Offset); 2060 } 2061 2062 2063 void Map::set_bit_field2(byte value) { 2064 WRITE_BYTE_FIELD(this, kBitField2Offset, value); 2065 } 2066 2067 2068 void Map::set_non_instance_prototype(bool value) { 2069 if (value) { 2070 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); 2071 } else { 2072 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype)); 2073 } 2074 } 2075 2076 2077 bool Map::has_non_instance_prototype() { 2078 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0; 2079 } 2080 2081 2082 void Map::set_is_access_check_needed(bool access_check_needed) { 2083 if (access_check_needed) { 2084 set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded)); 2085 } else { 2086 set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded)); 2087 } 2088 } 2089 2090 2091 bool Map::is_access_check_needed() { 2092 return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0; 2093 } 2094 2095 2096 Code::Flags Code::flags() { 2097 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset)); 2098 } 2099 2100 2101 void Code::set_flags(Code::Flags flags) { 2102 STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1); 2103 // Make sure that all call stubs have an arguments count. 2104 ASSERT(ExtractKindFromFlags(flags) != CALL_IC || 2105 ExtractArgumentsCountFromFlags(flags) >= 0); 2106 WRITE_INT_FIELD(this, kFlagsOffset, flags); 2107 } 2108 2109 2110 Code::Kind Code::kind() { 2111 return ExtractKindFromFlags(flags()); 2112 } 2113 2114 2115 InLoopFlag Code::ic_in_loop() { 2116 return ExtractICInLoopFromFlags(flags()); 2117 } 2118 2119 2120 InlineCacheState Code::ic_state() { 2121 InlineCacheState result = ExtractICStateFromFlags(flags()); 2122 // Only allow uninitialized or debugger states for non-IC code 2123 // objects. This is used in the debugger to determine whether or not 2124 // a call to code object has been replaced with a debug break call. 2125 ASSERT(is_inline_cache_stub() || 2126 result == UNINITIALIZED || 2127 result == DEBUG_BREAK || 2128 result == DEBUG_PREPARE_STEP_IN); 2129 return result; 2130 } 2131 2132 2133 PropertyType Code::type() { 2134 ASSERT(ic_state() == MONOMORPHIC); 2135 return ExtractTypeFromFlags(flags()); 2136 } 2137 2138 2139 int Code::arguments_count() { 2140 ASSERT(is_call_stub() || kind() == STUB); 2141 return ExtractArgumentsCountFromFlags(flags()); 2142 } 2143 2144 2145 CodeStub::Major Code::major_key() { 2146 ASSERT(kind() == STUB); 2147 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this, 2148 kStubMajorKeyOffset)); 2149 } 2150 2151 2152 void Code::set_major_key(CodeStub::Major major) { 2153 ASSERT(kind() == STUB); 2154 ASSERT(0 <= major && major < 256); 2155 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major); 2156 } 2157 2158 2159 bool Code::is_inline_cache_stub() { 2160 Kind kind = this->kind(); 2161 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND; 2162 } 2163 2164 2165 Code::Flags Code::ComputeFlags(Kind kind, 2166 InLoopFlag in_loop, 2167 InlineCacheState ic_state, 2168 PropertyType type, 2169 int argc) { 2170 // Compute the bit mask. 2171 int bits = kind << kFlagsKindShift; 2172 if (in_loop) bits |= kFlagsICInLoopMask; 2173 bits |= ic_state << kFlagsICStateShift; 2174 bits |= type << kFlagsTypeShift; 2175 bits |= argc << kFlagsArgumentsCountShift; 2176 // Cast to flags and validate result before returning it. 2177 Flags result = static_cast<Flags>(bits); 2178 ASSERT(ExtractKindFromFlags(result) == kind); 2179 ASSERT(ExtractICStateFromFlags(result) == ic_state); 2180 ASSERT(ExtractICInLoopFromFlags(result) == in_loop); 2181 ASSERT(ExtractTypeFromFlags(result) == type); 2182 ASSERT(ExtractArgumentsCountFromFlags(result) == argc); 2183 return result; 2184 } 2185 2186 2187 Code::Flags Code::ComputeMonomorphicFlags(Kind kind, 2188 PropertyType type, 2189 InLoopFlag in_loop, 2190 int argc) { 2191 return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc); 2192 } 2193 2194 2195 Code::Kind Code::ExtractKindFromFlags(Flags flags) { 2196 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift; 2197 return static_cast<Kind>(bits); 2198 } 2199 2200 2201 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) { 2202 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift; 2203 return static_cast<InlineCacheState>(bits); 2204 } 2205 2206 2207 InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) { 2208 int bits = (flags & kFlagsICInLoopMask); 2209 return bits != 0 ? IN_LOOP : NOT_IN_LOOP; 2210 } 2211 2212 2213 PropertyType Code::ExtractTypeFromFlags(Flags flags) { 2214 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift; 2215 return static_cast<PropertyType>(bits); 2216 } 2217 2218 2219 int Code::ExtractArgumentsCountFromFlags(Flags flags) { 2220 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift; 2221 } 2222 2223 2224 Code::Flags Code::RemoveTypeFromFlags(Flags flags) { 2225 int bits = flags & ~kFlagsTypeMask; 2226 return static_cast<Flags>(bits); 2227 } 2228 2229 2230 Code* Code::GetCodeFromTargetAddress(Address address) { 2231 HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize); 2232 // GetCodeFromTargetAddress might be called when marking objects during mark 2233 // sweep. reinterpret_cast is therefore used instead of the more appropriate 2234 // Code::cast. Code::cast does not work when the object's map is 2235 // marked. 2236 Code* result = reinterpret_cast<Code*>(code); 2237 return result; 2238 } 2239 2240 2241 Object* Map::prototype() { 2242 return READ_FIELD(this, kPrototypeOffset); 2243 } 2244 2245 2246 void Map::set_prototype(Object* value, WriteBarrierMode mode) { 2247 ASSERT(value->IsNull() || value->IsJSObject()); 2248 WRITE_FIELD(this, kPrototypeOffset, value); 2249 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode); 2250 } 2251 2252 2253 ACCESSORS(Map, instance_descriptors, DescriptorArray, 2254 kInstanceDescriptorsOffset) 2255 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset) 2256 ACCESSORS(Map, constructor, Object, kConstructorOffset) 2257 2258 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset) 2259 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset) 2260 2261 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset) 2262 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset) 2263 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset) 2264 2265 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset) 2266 2267 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset) 2268 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset) 2269 ACCESSORS(AccessorInfo, data, Object, kDataOffset) 2270 ACCESSORS(AccessorInfo, name, Object, kNameOffset) 2271 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset) 2272 ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset) 2273 2274 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset) 2275 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset) 2276 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) 2277 2278 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset) 2279 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset) 2280 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) 2281 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) 2282 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) 2283 ACCESSORS(InterceptorInfo, data, Object, kDataOffset) 2284 2285 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) 2286 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) 2287 2288 ACCESSORS(TemplateInfo, tag, Object, kTagOffset) 2289 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset) 2290 2291 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset) 2292 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset) 2293 ACCESSORS(FunctionTemplateInfo, property_accessors, Object, 2294 kPropertyAccessorsOffset) 2295 ACCESSORS(FunctionTemplateInfo, prototype_template, Object, 2296 kPrototypeTemplateOffset) 2297 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset) 2298 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object, 2299 kNamedPropertyHandlerOffset) 2300 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object, 2301 kIndexedPropertyHandlerOffset) 2302 ACCESSORS(FunctionTemplateInfo, instance_template, Object, 2303 kInstanceTemplateOffset) 2304 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset) 2305 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset) 2306 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object, 2307 kInstanceCallHandlerOffset) 2308 ACCESSORS(FunctionTemplateInfo, access_check_info, Object, 2309 kAccessCheckInfoOffset) 2310 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) 2311 2312 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) 2313 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, 2314 kInternalFieldCountOffset) 2315 2316 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) 2317 ACCESSORS(SignatureInfo, args, Object, kArgsOffset) 2318 2319 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset) 2320 2321 ACCESSORS(Script, source, Object, kSourceOffset) 2322 ACCESSORS(Script, name, Object, kNameOffset) 2323 ACCESSORS(Script, id, Object, kIdOffset) 2324 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset) 2325 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset) 2326 ACCESSORS(Script, data, Object, kDataOffset) 2327 ACCESSORS(Script, context_data, Object, kContextOffset) 2328 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset) 2329 ACCESSORS(Script, type, Smi, kTypeOffset) 2330 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset) 2331 ACCESSORS(Script, line_ends, Object, kLineEndsOffset) 2332 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset) 2333 ACCESSORS(Script, eval_from_instructions_offset, Smi, 2334 kEvalFrominstructionsOffsetOffset) 2335 2336 #ifdef ENABLE_DEBUGGER_SUPPORT 2337 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) 2338 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex) 2339 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex) 2340 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex) 2341 2342 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex) 2343 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex) 2344 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex) 2345 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex) 2346 #endif 2347 2348 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset) 2349 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset) 2350 ACCESSORS(SharedFunctionInfo, instance_class_name, Object, 2351 kInstanceClassNameOffset) 2352 ACCESSORS(SharedFunctionInfo, function_data, Object, 2353 kExternalReferenceDataOffset) 2354 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset) 2355 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset) 2356 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset) 2357 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object, 2358 kThisPropertyAssignmentsOffset) 2359 2360 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype, 2361 kHiddenPrototypeBit) 2362 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit) 2363 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check, 2364 kNeedsAccessCheckBit) 2365 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression, 2366 kIsExpressionBit) 2367 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel, 2368 kIsTopLevelBit) 2369 BOOL_GETTER(SharedFunctionInfo, compiler_hints, 2370 has_only_simple_this_property_assignments, 2371 kHasOnlySimpleThisPropertyAssignments) 2372 BOOL_ACCESSORS(SharedFunctionInfo, 2373 compiler_hints, 2374 try_full_codegen, 2375 kTryFullCodegen) 2376 2377 INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset) 2378 INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count, 2379 kFormalParameterCountOffset) 2380 INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties, 2381 kExpectedNofPropertiesOffset) 2382 INT_ACCESSORS(SharedFunctionInfo, start_position_and_type, 2383 kStartPositionAndTypeOffset) 2384 INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset) 2385 INT_ACCESSORS(SharedFunctionInfo, function_token_position, 2386 kFunctionTokenPositionOffset) 2387 INT_ACCESSORS(SharedFunctionInfo, compiler_hints, 2388 kCompilerHintsOffset) 2389 INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count, 2390 kThisPropertyAssignmentsCountOffset) 2391 2392 2393 bool Script::HasValidSource() { 2394 Object* src = this->source(); 2395 if (!src->IsString()) return true; 2396 String* src_str = String::cast(src); 2397 if (!StringShape(src_str).IsExternal()) return true; 2398 if (src_str->IsAsciiRepresentation()) { 2399 return ExternalAsciiString::cast(src)->resource() != NULL; 2400 } else if (src_str->IsTwoByteRepresentation()) { 2401 return ExternalTwoByteString::cast(src)->resource() != NULL; 2402 } 2403 return true; 2404 } 2405 2406 2407 void SharedFunctionInfo::DontAdaptArguments() { 2408 ASSERT(code()->kind() == Code::BUILTIN); 2409 set_formal_parameter_count(kDontAdaptArgumentsSentinel); 2410 } 2411 2412 2413 int SharedFunctionInfo::start_position() { 2414 return start_position_and_type() >> kStartPositionShift; 2415 } 2416 2417 2418 void SharedFunctionInfo::set_start_position(int start_position) { 2419 set_start_position_and_type((start_position << kStartPositionShift) 2420 | (start_position_and_type() & ~kStartPositionMask)); 2421 } 2422 2423 2424 Code* SharedFunctionInfo::code() { 2425 return Code::cast(READ_FIELD(this, kCodeOffset)); 2426 } 2427 2428 2429 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) { 2430 WRITE_FIELD(this, kCodeOffset, value); 2431 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode); 2432 } 2433 2434 2435 bool SharedFunctionInfo::is_compiled() { 2436 // TODO(1242782): Create a code kind for uncompiled code. 2437 return code()->kind() != Code::STUB; 2438 } 2439 2440 2441 bool JSFunction::IsBoilerplate() { 2442 return map() == Heap::boilerplate_function_map(); 2443 } 2444 2445 2446 bool JSFunction::IsBuiltin() { 2447 return context()->global()->IsJSBuiltinsObject(); 2448 } 2449 2450 2451 Code* JSFunction::code() { 2452 return shared()->code(); 2453 } 2454 2455 2456 void JSFunction::set_code(Code* value) { 2457 shared()->set_code(value); 2458 } 2459 2460 2461 Context* JSFunction::context() { 2462 return Context::cast(READ_FIELD(this, kContextOffset)); 2463 } 2464 2465 2466 Object* JSFunction::unchecked_context() { 2467 return READ_FIELD(this, kContextOffset); 2468 } 2469 2470 2471 void JSFunction::set_context(Object* value) { 2472 ASSERT(value == Heap::undefined_value() || value->IsContext()); 2473 WRITE_FIELD(this, kContextOffset, value); 2474 WRITE_BARRIER(this, kContextOffset); 2475 } 2476 2477 ACCESSORS(JSFunction, prototype_or_initial_map, Object, 2478 kPrototypeOrInitialMapOffset) 2479 2480 2481 Map* JSFunction::initial_map() { 2482 return Map::cast(prototype_or_initial_map()); 2483 } 2484 2485 2486 void JSFunction::set_initial_map(Map* value) { 2487 set_prototype_or_initial_map(value); 2488 } 2489 2490 2491 bool JSFunction::has_initial_map() { 2492 return prototype_or_initial_map()->IsMap(); 2493 } 2494 2495 2496 bool JSFunction::has_instance_prototype() { 2497 return has_initial_map() || !prototype_or_initial_map()->IsTheHole(); 2498 } 2499 2500 2501 bool JSFunction::has_prototype() { 2502 return map()->has_non_instance_prototype() || has_instance_prototype(); 2503 } 2504 2505 2506 Object* JSFunction::instance_prototype() { 2507 ASSERT(has_instance_prototype()); 2508 if (has_initial_map()) return initial_map()->prototype(); 2509 // When there is no initial map and the prototype is a JSObject, the 2510 // initial map field is used for the prototype field. 2511 return prototype_or_initial_map(); 2512 } 2513 2514 2515 Object* JSFunction::prototype() { 2516 ASSERT(has_prototype()); 2517 // If the function's prototype property has been set to a non-JSObject 2518 // value, that value is stored in the constructor field of the map. 2519 if (map()->has_non_instance_prototype()) return map()->constructor(); 2520 return instance_prototype(); 2521 } 2522 2523 2524 bool JSFunction::is_compiled() { 2525 return shared()->is_compiled(); 2526 } 2527 2528 2529 int JSFunction::NumberOfLiterals() { 2530 return literals()->length(); 2531 } 2532 2533 2534 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) { 2535 ASSERT(0 <= id && id < kJSBuiltinsCount); 2536 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize)); 2537 } 2538 2539 2540 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id, 2541 Object* value) { 2542 ASSERT(0 <= id && id < kJSBuiltinsCount); 2543 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value); 2544 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize)); 2545 } 2546 2547 2548 Address Proxy::proxy() { 2549 return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset)); 2550 } 2551 2552 2553 void Proxy::set_proxy(Address value) { 2554 WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value)); 2555 } 2556 2557 2558 void Proxy::ProxyIterateBody(ObjectVisitor* visitor) { 2559 visitor->VisitExternalReference( 2560 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset))); 2561 } 2562 2563 2564 ACCESSORS(JSValue, value, Object, kValueOffset) 2565 2566 2567 JSValue* JSValue::cast(Object* obj) { 2568 ASSERT(obj->IsJSValue()); 2569 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize); 2570 return reinterpret_cast<JSValue*>(obj); 2571 } 2572 2573 2574 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset) 2575 INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset) 2576 INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset) 2577 2578 2579 byte* Code::instruction_start() { 2580 return FIELD_ADDR(this, kHeaderSize); 2581 } 2582 2583 2584 int Code::body_size() { 2585 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment); 2586 } 2587 2588 2589 byte* Code::relocation_start() { 2590 return FIELD_ADDR(this, kHeaderSize + instruction_size()); 2591 } 2592 2593 2594 byte* Code::entry() { 2595 return instruction_start(); 2596 } 2597 2598 2599 bool Code::contains(byte* pc) { 2600 return (instruction_start() <= pc) && 2601 (pc < instruction_start() + instruction_size()); 2602 } 2603 2604 2605 byte* Code::sinfo_start() { 2606 return FIELD_ADDR(this, kHeaderSize + body_size()); 2607 } 2608 2609 2610 ACCESSORS(JSArray, length, Object, kLengthOffset) 2611 2612 2613 ACCESSORS(JSRegExp, data, Object, kDataOffset) 2614 2615 2616 JSRegExp::Type JSRegExp::TypeTag() { 2617 Object* data = this->data(); 2618 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED; 2619 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex)); 2620 return static_cast<JSRegExp::Type>(smi->value()); 2621 } 2622 2623 2624 int JSRegExp::CaptureCount() { 2625 switch (TypeTag()) { 2626 case ATOM: 2627 return 0; 2628 case IRREGEXP: 2629 return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value(); 2630 default: 2631 UNREACHABLE(); 2632 return -1; 2633 } 2634 } 2635 2636 2637 JSRegExp::Flags JSRegExp::GetFlags() { 2638 ASSERT(this->data()->IsFixedArray()); 2639 Object* data = this->data(); 2640 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex)); 2641 return Flags(smi->value()); 2642 } 2643 2644 2645 String* JSRegExp::Pattern() { 2646 ASSERT(this->data()->IsFixedArray()); 2647 Object* data = this->data(); 2648 String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex)); 2649 return pattern; 2650 } 2651 2652 2653 Object* JSRegExp::DataAt(int index) { 2654 ASSERT(TypeTag() != NOT_COMPILED); 2655 return FixedArray::cast(data())->get(index); 2656 } 2657 2658 2659 void JSRegExp::SetDataAt(int index, Object* value) { 2660 ASSERT(TypeTag() != NOT_COMPILED); 2661 ASSERT(index >= kDataIndex); // Only implementation data can be set this way. 2662 FixedArray::cast(data())->set(index, value); 2663 } 2664 2665 2666 JSObject::ElementsKind JSObject::GetElementsKind() { 2667 Array* array = elements(); 2668 if (array->IsFixedArray()) { 2669 // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray. 2670 if (array->map() == Heap::fixed_array_map()) { 2671 return FAST_ELEMENTS; 2672 } 2673 ASSERT(array->IsDictionary()); 2674 return DICTIONARY_ELEMENTS; 2675 } 2676 if (array->IsExternalArray()) { 2677 switch (array->map()->instance_type()) { 2678 case EXTERNAL_BYTE_ARRAY_TYPE: 2679 return EXTERNAL_BYTE_ELEMENTS; 2680 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 2681 return EXTERNAL_UNSIGNED_BYTE_ELEMENTS; 2682 case EXTERNAL_SHORT_ARRAY_TYPE: 2683 return EXTERNAL_SHORT_ELEMENTS; 2684 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 2685 return EXTERNAL_UNSIGNED_SHORT_ELEMENTS; 2686 case EXTERNAL_INT_ARRAY_TYPE: 2687 return EXTERNAL_INT_ELEMENTS; 2688 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 2689 return EXTERNAL_UNSIGNED_INT_ELEMENTS; 2690 default: 2691 ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE); 2692 return EXTERNAL_FLOAT_ELEMENTS; 2693 } 2694 } 2695 ASSERT(array->IsPixelArray()); 2696 return PIXEL_ELEMENTS; 2697 } 2698 2699 2700 bool JSObject::HasFastElements() { 2701 return GetElementsKind() == FAST_ELEMENTS; 2702 } 2703 2704 2705 bool JSObject::HasDictionaryElements() { 2706 return GetElementsKind() == DICTIONARY_ELEMENTS; 2707 } 2708 2709 2710 bool JSObject::HasPixelElements() { 2711 return GetElementsKind() == PIXEL_ELEMENTS; 2712 } 2713 2714 2715 bool JSObject::HasExternalArrayElements() { 2716 return (HasExternalByteElements() || 2717 HasExternalUnsignedByteElements() || 2718 HasExternalShortElements() || 2719 HasExternalUnsignedShortElements() || 2720 HasExternalIntElements() || 2721 HasExternalUnsignedIntElements() || 2722 HasExternalFloatElements()); 2723 } 2724 2725 2726 bool JSObject::HasExternalByteElements() { 2727 return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS; 2728 } 2729 2730 2731 bool JSObject::HasExternalUnsignedByteElements() { 2732 return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS; 2733 } 2734 2735 2736 bool JSObject::HasExternalShortElements() { 2737 return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS; 2738 } 2739 2740 2741 bool JSObject::HasExternalUnsignedShortElements() { 2742 return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS; 2743 } 2744 2745 2746 bool JSObject::HasExternalIntElements() { 2747 return GetElementsKind() == EXTERNAL_INT_ELEMENTS; 2748 } 2749 2750 2751 bool JSObject::HasExternalUnsignedIntElements() { 2752 return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS; 2753 } 2754 2755 2756 bool JSObject::HasExternalFloatElements() { 2757 return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS; 2758 } 2759 2760 2761 bool JSObject::HasNamedInterceptor() { 2762 return map()->has_named_interceptor(); 2763 } 2764 2765 2766 bool JSObject::HasIndexedInterceptor() { 2767 return map()->has_indexed_interceptor(); 2768 } 2769 2770 2771 StringDictionary* JSObject::property_dictionary() { 2772 ASSERT(!HasFastProperties()); 2773 return StringDictionary::cast(properties()); 2774 } 2775 2776 2777 NumberDictionary* JSObject::element_dictionary() { 2778 ASSERT(HasDictionaryElements()); 2779 return NumberDictionary::cast(elements()); 2780 } 2781 2782 2783 bool String::HasHashCode() { 2784 return (hash_field() & kHashComputedMask) != 0; 2785 } 2786 2787 2788 uint32_t String::Hash() { 2789 // Fast case: has hash code already been computed? 2790 uint32_t field = hash_field(); 2791 if (field & kHashComputedMask) return field >> kHashShift; 2792 // Slow case: compute hash code and set it. 2793 return ComputeAndSetHash(); 2794 } 2795 2796 2797 StringHasher::StringHasher(int length) 2798 : length_(length), 2799 raw_running_hash_(0), 2800 array_index_(0), 2801 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), 2802 is_first_char_(true), 2803 is_valid_(true) { } 2804 2805 2806 bool StringHasher::has_trivial_hash() { 2807 return length_ > String::kMaxHashCalcLength; 2808 } 2809 2810 2811 void StringHasher::AddCharacter(uc32 c) { 2812 // Use the Jenkins one-at-a-time hash function to update the hash 2813 // for the given character. 2814 raw_running_hash_ += c; 2815 raw_running_hash_ += (raw_running_hash_ << 10); 2816 raw_running_hash_ ^= (raw_running_hash_ >> 6); 2817 // Incremental array index computation. 2818 if (is_array_index_) { 2819 if (c < '0' || c > '9') { 2820 is_array_index_ = false; 2821 } else { 2822 int d = c - '0'; 2823 if (is_first_char_) { 2824 is_first_char_ = false; 2825 if (c == '0' && length_ > 1) { 2826 is_array_index_ = false; 2827 return; 2828 } 2829 } 2830 if (array_index_ > 429496729U - ((d + 2) >> 3)) { 2831 is_array_index_ = false; 2832 } else { 2833 array_index_ = array_index_ * 10 + d; 2834 } 2835 } 2836 } 2837 } 2838 2839 2840 void StringHasher::AddCharacterNoIndex(uc32 c) { 2841 ASSERT(!is_array_index()); 2842 raw_running_hash_ += c; 2843 raw_running_hash_ += (raw_running_hash_ << 10); 2844 raw_running_hash_ ^= (raw_running_hash_ >> 6); 2845 } 2846 2847 2848 uint32_t StringHasher::GetHash() { 2849 // Get the calculated raw hash value and do some more bit ops to distribute 2850 // the hash further. Ensure that we never return zero as the hash value. 2851 uint32_t result = raw_running_hash_; 2852 result += (result << 3); 2853 result ^= (result >> 11); 2854 result += (result << 15); 2855 if (result == 0) { 2856 result = 27; 2857 } 2858 return result; 2859 } 2860 2861 2862 bool String::AsArrayIndex(uint32_t* index) { 2863 uint32_t field = hash_field(); 2864 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false; 2865 return SlowAsArrayIndex(index); 2866 } 2867 2868 2869 Object* JSObject::GetPrototype() { 2870 return JSObject::cast(this)->map()->prototype(); 2871 } 2872 2873 2874 PropertyAttributes JSObject::GetPropertyAttribute(String* key) { 2875 return GetPropertyAttributeWithReceiver(this, key); 2876 } 2877 2878 // TODO(504): this may be useful in other places too where JSGlobalProxy 2879 // is used. 2880 Object* JSObject::BypassGlobalProxy() { 2881 if (IsJSGlobalProxy()) { 2882 Object* proto = GetPrototype(); 2883 if (proto->IsNull()) return Heap::undefined_value(); 2884 ASSERT(proto->IsJSGlobalObject()); 2885 return proto; 2886 } 2887 return this; 2888 } 2889 2890 2891 bool JSObject::HasHiddenPropertiesObject() { 2892 ASSERT(!IsJSGlobalProxy()); 2893 return GetPropertyAttributePostInterceptor(this, 2894 Heap::hidden_symbol(), 2895 false) != ABSENT; 2896 } 2897 2898 2899 Object* JSObject::GetHiddenPropertiesObject() { 2900 ASSERT(!IsJSGlobalProxy()); 2901 PropertyAttributes attributes; 2902 return GetLocalPropertyPostInterceptor(this, 2903 Heap::hidden_symbol(), 2904 &attributes); 2905 } 2906 2907 2908 Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) { 2909 ASSERT(!IsJSGlobalProxy()); 2910 return SetPropertyPostInterceptor(Heap::hidden_symbol(), 2911 hidden_obj, 2912 DONT_ENUM); 2913 } 2914 2915 2916 bool JSObject::HasElement(uint32_t index) { 2917 return HasElementWithReceiver(this, index); 2918 } 2919 2920 2921 bool AccessorInfo::all_can_read() { 2922 return BooleanBit::get(flag(), kAllCanReadBit); 2923 } 2924 2925 2926 void AccessorInfo::set_all_can_read(bool value) { 2927 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value)); 2928 } 2929 2930 2931 bool AccessorInfo::all_can_write() { 2932 return BooleanBit::get(flag(), kAllCanWriteBit); 2933 } 2934 2935 2936 void AccessorInfo::set_all_can_write(bool value) { 2937 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value)); 2938 } 2939 2940 2941 bool AccessorInfo::prohibits_overwriting() { 2942 return BooleanBit::get(flag(), kProhibitsOverwritingBit); 2943 } 2944 2945 2946 void AccessorInfo::set_prohibits_overwriting(bool value) { 2947 set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value)); 2948 } 2949 2950 2951 PropertyAttributes AccessorInfo::property_attributes() { 2952 return AttributesField::decode(static_cast<uint32_t>(flag()->value())); 2953 } 2954 2955 2956 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) { 2957 ASSERT(AttributesField::is_valid(attributes)); 2958 int rest_value = flag()->value() & ~AttributesField::mask(); 2959 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes))); 2960 } 2961 2962 template<typename Shape, typename Key> 2963 void Dictionary<Shape, Key>::SetEntry(int entry, 2964 Object* key, 2965 Object* value, 2966 PropertyDetails details) { 2967 ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0); 2968 int index = HashTable<Shape, Key>::EntryToIndex(entry); 2969 AssertNoAllocation no_gc; 2970 WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc); 2971 FixedArray::set(index, key, mode); 2972 FixedArray::set(index+1, value, mode); 2973 FixedArray::fast_set(this, index+2, details.AsSmi()); 2974 } 2975 2976 2977 void Map::ClearCodeCache() { 2978 // No write barrier is needed since empty_fixed_array is not in new space. 2979 // Please note this function is used during marking: 2980 // - MarkCompactCollector::MarkUnmarkedObject 2981 ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array())); 2982 WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array()); 2983 } 2984 2985 2986 void JSArray::EnsureSize(int required_size) { 2987 ASSERT(HasFastElements()); 2988 Array* elts = elements(); 2989 const int kArraySizeThatFitsComfortablyInNewSpace = 128; 2990 if (elts->length() < required_size) { 2991 // Doubling in size would be overkill, but leave some slack to avoid 2992 // constantly growing. 2993 Expand(required_size + (required_size >> 3)); 2994 // It's a performance benefit to keep a frequently used array in new-space. 2995 } else if (!Heap::new_space()->Contains(elts) && 2996 required_size < kArraySizeThatFitsComfortablyInNewSpace) { 2997 // Expand will allocate a new backing store in new space even if the size 2998 // we asked for isn't larger than what we had before. 2999 Expand(required_size); 3000 } 3001 } 3002 3003 3004 void JSArray::set_length(Smi* length) { 3005 set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER); 3006 } 3007 3008 3009 void JSArray::SetContent(FixedArray* storage) { 3010 set_length(Smi::FromInt(storage->length())); 3011 set_elements(storage); 3012 } 3013 3014 3015 Object* FixedArray::Copy() { 3016 if (length() == 0) return this; 3017 return Heap::CopyFixedArray(this); 3018 } 3019 3020 3021 #undef CAST_ACCESSOR 3022 #undef INT_ACCESSORS 3023 #undef SMI_ACCESSORS 3024 #undef ACCESSORS 3025 #undef FIELD_ADDR 3026 #undef READ_FIELD 3027 #undef WRITE_FIELD 3028 #undef WRITE_BARRIER 3029 #undef CONDITIONAL_WRITE_BARRIER 3030 #undef READ_MEMADDR_FIELD 3031 #undef WRITE_MEMADDR_FIELD 3032 #undef READ_DOUBLE_FIELD 3033 #undef WRITE_DOUBLE_FIELD 3034 #undef READ_INT_FIELD 3035 #undef WRITE_INT_FIELD 3036 #undef READ_SHORT_FIELD 3037 #undef WRITE_SHORT_FIELD 3038 #undef READ_BYTE_FIELD 3039 #undef WRITE_BYTE_FIELD 3040 3041 3042 } } // namespace v8::internal 3043 3044 #endif // V8_OBJECTS_INL_H_ 3045