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