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