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