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