00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef V8_OBJECTS_INL_H_
00036 #define V8_OBJECTS_INL_H_
00037
00038 #include "objects.h"
00039 #include "contexts.h"
00040 #include "conversions-inl.h"
00041 #include "property.h"
00042
00043 namespace v8 { namespace internal {
00044
00045 PropertyDetails::PropertyDetails(Smi* smi) {
00046 value_ = smi->value();
00047 }
00048
00049
00050 Smi* PropertyDetails::AsSmi() {
00051 return Smi::FromInt(value_);
00052 }
00053
00054
00055 #define CAST_ACCESSOR(type) \
00056 type* type::cast(Object* object) { \
00057 ASSERT(object->Is##type()); \
00058 return reinterpret_cast<type*>(object); \
00059 }
00060
00061
00062 #define INT_ACCESSORS(holder, name, offset) \
00063 int holder::name() { return READ_INT_FIELD(this, offset); } \
00064 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
00065
00066
00067 #define ACCESSORS(holder, name, type, offset) \
00068 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
00069 void holder::set_##name(type* value, WriteBarrierMode mode) { \
00070 WRITE_FIELD(this, offset, value); \
00071 CONDITIONAL_WRITE_BARRIER(this, offset, mode); \
00072 }
00073
00074
00075
00076 #define SMI_ACCESSORS(holder, name, offset) \
00077 int holder::name() { \
00078 Object* value = READ_FIELD(this, offset); \
00079 return Smi::cast(value)->value(); \
00080 } \
00081 void holder::set_##name(int value) { \
00082 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
00083 }
00084
00085
00086 #define BOOL_ACCESSORS(holder, field, name, offset) \
00087 bool holder::name() { \
00088 return BooleanBit::get(field(), offset); \
00089 } \
00090 void holder::set_##name(bool value) { \
00091 set_##field(BooleanBit::set(field(), offset, value)); \
00092 }
00093
00094
00095 bool Object::IsSmi() {
00096 return HAS_SMI_TAG(this);
00097 }
00098
00099
00100 bool Object::IsHeapObject() {
00101 return HAS_HEAP_OBJECT_TAG(this);
00102 }
00103
00104
00105 bool Object::IsHeapNumber() {
00106 return Object::IsHeapObject()
00107 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
00108 }
00109
00110
00111 bool Object::IsString() {
00112 return Object::IsHeapObject()
00113 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
00114 }
00115
00116
00117 bool Object::IsSeqString() {
00118 return IsString()
00119 && (String::cast(this)->representation_tag() == kSeqStringTag);
00120 }
00121
00122
00123 bool Object::IsSeqAsciiString() {
00124 return IsSeqString()
00125 && String::cast(this)->IsAsciiRepresentation();
00126 }
00127
00128
00129 bool String::IsSeqAsciiString() {
00130 return (this->representation_tag() == kSeqStringTag)
00131 && is_ascii_representation();
00132 }
00133
00134
00135 bool Object::IsSeqTwoByteString() {
00136 return IsSeqString()
00137 && !String::cast(this)->IsAsciiRepresentation();
00138 }
00139
00140
00141 bool Object::IsAsciiStringRepresentation() {
00142 return IsString() && (String::cast(this)->is_ascii_representation());
00143 }
00144
00145
00146 bool Object::IsTwoByteStringRepresentation() {
00147 return IsString() && (!String::cast(this)->is_ascii_representation());
00148 }
00149
00150
00151 bool Object::IsConsString() {
00152 return IsString()
00153 && (String::cast(this)->representation_tag() == kConsStringTag);
00154 }
00155
00156
00157 bool Object::IsSlicedString() {
00158 return IsString()
00159 && (String::cast(this)->representation_tag() == kSlicedStringTag);
00160 }
00161
00162
00163 bool Object::IsExternalString() {
00164 return IsString()
00165 && (String::cast(this)->representation_tag() == kExternalStringTag);
00166 }
00167
00168
00169 bool Object::IsExternalAsciiString() {
00170 return IsExternalString() && (String::cast(this)->is_ascii_representation());
00171 }
00172
00173
00174 bool Object::IsExternalTwoByteString() {
00175 return IsExternalString() && (!String::cast(this)->is_ascii_representation());
00176 }
00177
00178
00179 bool Object::IsShortString() {
00180 return IsString() && (String::cast(this)->size_tag() == kShortStringTag);
00181 }
00182
00183
00184 bool Object::IsMediumString() {
00185 return IsString() && (String::cast(this)->size_tag() == kMediumStringTag);
00186 }
00187
00188
00189 bool Object::IsLongString() {
00190 return IsString() && (String::cast(this)->size_tag() == kLongStringTag);
00191 }
00192
00193
00194 bool Object::IsSymbol() {
00195 return IsString() && (String::cast(this)->is_symbol());
00196 }
00197
00198
00199 bool Object::IsNumber() {
00200 return IsSmi() || IsHeapNumber();
00201 }
00202
00203
00204 bool Object::IsByteArray() {
00205 return Object::IsHeapObject()
00206 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
00207 }
00208
00209
00210 bool Object::IsFailure() {
00211 return HAS_FAILURE_TAG(this);
00212 }
00213
00214
00215 bool Object::IsRetryAfterGC() {
00216 return HAS_FAILURE_TAG(this)
00217 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
00218 }
00219
00220
00221 bool Object::IsOutOfMemoryFailure() {
00222 return HAS_FAILURE_TAG(this)
00223 && Failure::cast(this)->IsOutOfMemoryException();
00224 }
00225
00226
00227 bool Object::IsException() {
00228 return this == Failure::Exception();
00229 }
00230
00231
00232 bool Object::IsJSObject() {
00233 return IsHeapObject()
00234 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
00235 }
00236
00237
00238 bool Object::IsMap() {
00239 return Object::IsHeapObject()
00240 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
00241 }
00242
00243
00244 bool Object::IsFixedArray() {
00245 return Object::IsHeapObject()
00246 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
00247 }
00248
00249
00250 bool Object::IsDescriptorArray() {
00251 return IsFixedArray();
00252 }
00253
00254
00255 bool Object::IsContext() {
00256 return Object::IsHeapObject()
00257 && (HeapObject::cast(this)->map() == Heap::context_map() ||
00258 HeapObject::cast(this)->map() == Heap::global_context_map());
00259 }
00260
00261
00262 bool Object::IsGlobalContext() {
00263 return Object::IsHeapObject()
00264 && HeapObject::cast(this)->map() == Heap::global_context_map();
00265 }
00266
00267
00268 bool Object::IsJSFunction() {
00269 return Object::IsHeapObject()
00270 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
00271 }
00272
00273
00274 template <> inline bool Is<JSFunction>(Object* obj) {
00275 return obj->IsJSFunction();
00276 }
00277
00278
00279 bool Object::IsCode() {
00280 return Object::IsHeapObject()
00281 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
00282 }
00283
00284
00285 bool Object::IsOddball() {
00286 return Object::IsHeapObject()
00287 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
00288 }
00289
00290
00291 bool Object::IsSharedFunctionInfo() {
00292 return Object::IsHeapObject() &&
00293 (HeapObject::cast(this)->map()->instance_type() ==
00294 SHARED_FUNCTION_INFO_TYPE);
00295 }
00296
00297
00298 bool Object::IsJSValue() {
00299 return Object::IsHeapObject()
00300 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
00301 }
00302
00303
00304 bool Object::IsStringWrapper() {
00305 return IsJSValue() && JSValue::cast(this)->value()->IsString();
00306 }
00307
00308
00309 bool Object::IsProxy() {
00310 return Object::IsHeapObject()
00311 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
00312 }
00313
00314
00315 bool Object::IsBoolean() {
00316 return IsTrue() || IsFalse();
00317 }
00318
00319
00320 bool Object::IsJSArray() {
00321 return Object::IsHeapObject()
00322 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
00323 }
00324
00325
00326 bool Object::IsJSRegExp() {
00327 return Object::IsHeapObject()
00328 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
00329 }
00330
00331
00332 template <> inline bool Is<JSArray>(Object* obj) {
00333 return obj->IsJSArray();
00334 }
00335
00336
00337 bool Object::IsHashTable() {
00338 return Object::IsHeapObject()
00339 && HeapObject::cast(this)->map() == Heap::hash_table_map();
00340 }
00341
00342
00343 bool Object::IsDictionary() {
00344 return IsHashTable() && this != Heap::symbol_table();
00345 }
00346
00347
00348 bool Object::IsSymbolTable() {
00349 return IsHashTable() && this == Heap::symbol_table();
00350 }
00351
00352
00353 bool Object::IsCompilationCacheTable() {
00354 return IsHashTable();
00355 }
00356
00357
00358 bool Object::IsMapCache() {
00359 return IsHashTable();
00360 }
00361
00362
00363 bool Object::IsLookupCache() {
00364 return IsHashTable();
00365 }
00366
00367
00368 bool Object::IsPrimitive() {
00369 return IsOddball() || IsNumber() || IsString();
00370 }
00371
00372
00373 bool Object::IsJSGlobalProxy() {
00374 bool result = IsHeapObject() &&
00375 (HeapObject::cast(this)->map()->instance_type() ==
00376 JS_GLOBAL_PROXY_TYPE);
00377 ASSERT(!result || IsAccessCheckNeeded());
00378 return result;
00379 }
00380
00381
00382 bool Object::IsGlobalObject() {
00383 if (!IsHeapObject()) return false;
00384
00385 InstanceType type = HeapObject::cast(this)->map()->instance_type();
00386 return type == JS_GLOBAL_OBJECT_TYPE ||
00387 type == JS_BUILTINS_OBJECT_TYPE;
00388 }
00389
00390
00391 bool Object::IsJSGlobalObject() {
00392 return IsHeapObject() &&
00393 (HeapObject::cast(this)->map()->instance_type() ==
00394 JS_GLOBAL_OBJECT_TYPE);
00395 }
00396
00397
00398 bool Object::IsJSBuiltinsObject() {
00399 return IsHeapObject() &&
00400 (HeapObject::cast(this)->map()->instance_type() ==
00401 JS_BUILTINS_OBJECT_TYPE);
00402 }
00403
00404
00405 bool Object::IsUndetectableObject() {
00406 return IsHeapObject()
00407 && HeapObject::cast(this)->map()->is_undetectable();
00408 }
00409
00410
00411 bool Object::IsAccessCheckNeeded() {
00412 return IsHeapObject()
00413 && HeapObject::cast(this)->map()->is_access_check_needed();
00414 }
00415
00416
00417 bool Object::IsStruct() {
00418 if (!IsHeapObject()) return false;
00419 switch (HeapObject::cast(this)->map()->instance_type()) {
00420 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
00421 STRUCT_LIST(MAKE_STRUCT_CASE)
00422 #undef MAKE_STRUCT_CASE
00423 default: return false;
00424 }
00425 }
00426
00427
00428 #define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
00429 bool Object::Is##Name() { \
00430 return Object::IsHeapObject() \
00431 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
00432 }
00433 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
00434 #undef MAKE_STRUCT_PREDICATE
00435
00436
00437 bool Object::IsUndefined() {
00438 return this == Heap::undefined_value();
00439 }
00440
00441
00442 bool Object::IsTheHole() {
00443 return this == Heap::the_hole_value();
00444 }
00445
00446
00447 bool Object::IsNull() {
00448 return this == Heap::null_value();
00449 }
00450
00451
00452 bool Object::IsTrue() {
00453 return this == Heap::true_value();
00454 }
00455
00456
00457 bool Object::IsFalse() {
00458 return this == Heap::false_value();
00459 }
00460
00461
00462 double Object::Number() {
00463 ASSERT(IsNumber());
00464 return IsSmi()
00465 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
00466 : reinterpret_cast<HeapNumber*>(this)->value();
00467 }
00468
00469
00470
00471 Object* Object::ToSmi() {
00472 if (IsSmi()) return this;
00473 if (IsHeapNumber()) {
00474 double value = HeapNumber::cast(this)->value();
00475 int int_value = FastD2I(value);
00476 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
00477 return Smi::FromInt(int_value);
00478 }
00479 }
00480 return Failure::Exception();
00481 }
00482
00483
00484 bool Object::HasSpecificClassOf(String* name) {
00485 return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
00486 }
00487
00488
00489 Object* Object::GetElement(uint32_t index) {
00490 return GetElementWithReceiver(this, index);
00491 }
00492
00493
00494 Object* Object::GetProperty(String* key) {
00495 PropertyAttributes attributes;
00496 return GetPropertyWithReceiver(this, key, &attributes);
00497 }
00498
00499
00500 Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
00501 return GetPropertyWithReceiver(this, key, attributes);
00502 }
00503
00504
00505 #define FIELD_ADDR(p, offset) \
00506 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
00507
00508 #define READ_FIELD(p, offset) \
00509 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
00510
00511 #define WRITE_FIELD(p, offset, value) \
00512 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
00513
00514
00515 #define WRITE_BARRIER(object, offset) \
00516 Heap::RecordWrite(object->address(), offset);
00517
00518
00519
00520 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
00521 if (mode == UPDATE_WRITE_BARRIER) { \
00522 Heap::RecordWrite(object->address(), offset); \
00523 } else { \
00524 ASSERT(mode == SKIP_WRITE_BARRIER); \
00525 ASSERT(Heap::InNewSpace(object) || \
00526 !Heap::InNewSpace(READ_FIELD(object, offset))); \
00527 }
00528
00529 #define READ_DOUBLE_FIELD(p, offset) \
00530 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
00531
00532 #define WRITE_DOUBLE_FIELD(p, offset, value) \
00533 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
00534
00535 #define READ_INT_FIELD(p, offset) \
00536 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
00537
00538 #define WRITE_INT_FIELD(p, offset, value) \
00539 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
00540
00541 #define READ_UINT32_FIELD(p, offset) \
00542 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
00543
00544 #define WRITE_UINT32_FIELD(p, offset, value) \
00545 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
00546
00547 #define READ_SHORT_FIELD(p, offset) \
00548 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
00549
00550 #define WRITE_SHORT_FIELD(p, offset, value) \
00551 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
00552
00553 #define READ_BYTE_FIELD(p, offset) \
00554 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
00555
00556 #define WRITE_BYTE_FIELD(p, offset, value) \
00557 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
00558
00559
00560 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
00561 return &READ_FIELD(obj, byte_offset);
00562 }
00563
00564
00565 int Smi::value() {
00566 return reinterpret_cast<int>(this) >> kSmiTagSize;
00567 }
00568
00569
00570 Smi* Smi::FromInt(int value) {
00571 ASSERT(Smi::IsValid(value));
00572 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
00573 }
00574
00575
00576 Failure::Type Failure::type() const {
00577 return static_cast<Type>(value() & kFailureTypeTagMask);
00578 }
00579
00580
00581 bool Failure::IsInternalError() const {
00582 return type() == INTERNAL_ERROR;
00583 }
00584
00585
00586 bool Failure::IsOutOfMemoryException() const {
00587 return type() == OUT_OF_MEMORY_EXCEPTION;
00588 }
00589
00590
00591 int Failure::requested() const {
00592 const int kShiftBits =
00593 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
00594 STATIC_ASSERT(kShiftBits >= 0);
00595 ASSERT(type() == RETRY_AFTER_GC);
00596 return value() >> kShiftBits;
00597 }
00598
00599
00600 AllocationSpace Failure::allocation_space() const {
00601 ASSERT_EQ(RETRY_AFTER_GC, type());
00602 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
00603 & kSpaceTagMask);
00604 }
00605
00606
00607 Failure* Failure::InternalError() {
00608 return Construct(INTERNAL_ERROR);
00609 }
00610
00611
00612 Failure* Failure::Exception() {
00613 return Construct(EXCEPTION);
00614 }
00615
00616 Failure* Failure::OutOfMemoryException() {
00617 return Construct(OUT_OF_MEMORY_EXCEPTION);
00618 }
00619
00620
00621 int Failure::value() const {
00622 return reinterpret_cast<int>(this) >> kFailureTagSize;
00623 }
00624
00625
00626 Failure* Failure::RetryAfterGC(int requested_bytes) {
00627 int requested = requested_bytes >> kObjectAlignmentBits;
00628 int value = (requested << kSpaceTagSize) | NEW_SPACE;
00629 ASSERT(value >> kSpaceTagSize == requested);
00630 ASSERT(Smi::IsValid(value));
00631 ASSERT(value == ((value << kFailureTypeTagSize) >> kFailureTypeTagSize));
00632 ASSERT(Smi::IsValid(value << kFailureTypeTagSize));
00633 return Construct(RETRY_AFTER_GC, value);
00634 }
00635
00636
00637 Failure* Failure::Construct(Type type, int value) {
00638 int info = (value << kFailureTypeTagSize) | type;
00639 ASSERT(Smi::IsValid(info));
00640 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
00641 }
00642
00643
00644 bool Smi::IsValid(int value) {
00645 #ifdef DEBUG
00646 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
00647 #endif
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 bool result =
00660 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
00661 ASSERT(result == in_range);
00662 return result;
00663 }
00664
00665
00666 MapWord MapWord::FromMap(Map* map) {
00667 return MapWord(reinterpret_cast<uintptr_t>(map));
00668 }
00669
00670
00671 Map* MapWord::ToMap() {
00672 return reinterpret_cast<Map*>(value_);
00673 }
00674
00675
00676 bool MapWord::IsForwardingAddress() {
00677 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
00678 }
00679
00680
00681 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
00682 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
00683 return MapWord(reinterpret_cast<uintptr_t>(raw));
00684 }
00685
00686
00687 HeapObject* MapWord::ToForwardingAddress() {
00688 ASSERT(IsForwardingAddress());
00689 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
00690 }
00691
00692
00693 bool MapWord::IsMarked() {
00694 return (value_ & kMarkingMask) == 0;
00695 }
00696
00697
00698 void MapWord::SetMark() {
00699 value_ &= ~kMarkingMask;
00700 }
00701
00702
00703 void MapWord::ClearMark() {
00704 value_ |= kMarkingMask;
00705 }
00706
00707
00708 bool MapWord::IsOverflowed() {
00709 return (value_ & kOverflowMask) != 0;
00710 }
00711
00712
00713 void MapWord::SetOverflow() {
00714 value_ |= kOverflowMask;
00715 }
00716
00717
00718 void MapWord::ClearOverflow() {
00719 value_ &= ~kOverflowMask;
00720 }
00721
00722
00723 MapWord MapWord::EncodeAddress(Address map_address, int offset) {
00724
00725
00726
00727 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
00728
00729 int compact_offset = offset >> kObjectAlignmentBits;
00730 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
00731
00732 Page* map_page = Page::FromAddress(map_address);
00733 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
00734
00735 int map_page_offset =
00736 map_page->Offset(map_address) >> kObjectAlignmentBits;
00737
00738 uintptr_t encoding =
00739 (compact_offset << kForwardingOffsetShift) |
00740 (map_page_offset << kMapPageOffsetShift) |
00741 (map_page->mc_page_index << kMapPageIndexShift);
00742 return MapWord(encoding);
00743 }
00744
00745
00746 Address MapWord::DecodeMapAddress(MapSpace* map_space) {
00747 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
00748 ASSERT_MAP_PAGE_INDEX(map_page_index);
00749
00750 int map_page_offset =
00751 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
00752 << kObjectAlignmentBits;
00753
00754 return (map_space->PageAddress(map_page_index) + map_page_offset);
00755 }
00756
00757
00758 int MapWord::DecodeOffset() {
00759
00760
00761 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
00762 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
00763 return offset;
00764 }
00765
00766
00767 MapWord MapWord::FromEncodedAddress(Address address) {
00768 return MapWord(reinterpret_cast<uintptr_t>(address));
00769 }
00770
00771
00772 Address MapWord::ToEncodedAddress() {
00773 return reinterpret_cast<Address>(value_);
00774 }
00775
00776
00777 #ifdef DEBUG
00778 void HeapObject::VerifyObjectField(int offset) {
00779 VerifyPointer(READ_FIELD(this, offset));
00780 }
00781 #endif
00782
00783
00784 Map* HeapObject::map() {
00785 return map_word().ToMap();
00786 }
00787
00788
00789 void HeapObject::set_map(Map* value) {
00790 set_map_word(MapWord::FromMap(value));
00791 }
00792
00793
00794 MapWord HeapObject::map_word() {
00795 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
00796 }
00797
00798
00799 void HeapObject::set_map_word(MapWord map_word) {
00800
00801
00802 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
00803 }
00804
00805
00806 HeapObject* HeapObject::FromAddress(Address address) {
00807 ASSERT_TAG_ALIGNED(address);
00808 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
00809 }
00810
00811
00812 Address HeapObject::address() {
00813 return reinterpret_cast<Address>(this) - kHeapObjectTag;
00814 }
00815
00816
00817 int HeapObject::Size() {
00818 return SizeFromMap(map());
00819 }
00820
00821
00822 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
00823 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
00824 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
00825 }
00826
00827
00828 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
00829 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
00830 }
00831
00832
00833 bool HeapObject::IsMarked() {
00834 return map_word().IsMarked();
00835 }
00836
00837
00838 void HeapObject::SetMark() {
00839 ASSERT(!IsMarked());
00840 MapWord first_word = map_word();
00841 first_word.SetMark();
00842 set_map_word(first_word);
00843 }
00844
00845
00846 void HeapObject::ClearMark() {
00847 ASSERT(IsMarked());
00848 MapWord first_word = map_word();
00849 first_word.ClearMark();
00850 set_map_word(first_word);
00851 }
00852
00853
00854 bool HeapObject::IsOverflowed() {
00855 return map_word().IsOverflowed();
00856 }
00857
00858
00859 void HeapObject::SetOverflow() {
00860 MapWord first_word = map_word();
00861 first_word.SetOverflow();
00862 set_map_word(first_word);
00863 }
00864
00865
00866 void HeapObject::ClearOverflow() {
00867 ASSERT(IsOverflowed());
00868 MapWord first_word = map_word();
00869 first_word.ClearOverflow();
00870 set_map_word(first_word);
00871 }
00872
00873
00874 double HeapNumber::value() {
00875 return READ_DOUBLE_FIELD(this, kValueOffset);
00876 }
00877
00878
00879 void HeapNumber::set_value(double value) {
00880 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
00881 }
00882
00883
00884 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
00885 ACCESSORS(JSObject, elements, FixedArray, kElementsOffset)
00886
00887
00888 void JSObject::initialize_properties() {
00889 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
00890 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
00891 }
00892
00893
00894 void JSObject::initialize_elements() {
00895 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
00896 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
00897 }
00898
00899
00900 ACCESSORS(Oddball, to_string, String, kToStringOffset)
00901 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
00902
00903
00904 int JSObject::GetHeaderSize() {
00905 switch (map()->instance_type()) {
00906 case JS_GLOBAL_PROXY_TYPE:
00907 return JSGlobalProxy::kSize;
00908 case JS_GLOBAL_OBJECT_TYPE:
00909 return JSGlobalObject::kSize;
00910 case JS_BUILTINS_OBJECT_TYPE:
00911 return JSBuiltinsObject::kSize;
00912 case JS_FUNCTION_TYPE:
00913 return JSFunction::kSize;
00914 case JS_VALUE_TYPE:
00915 return JSValue::kSize;
00916 case JS_ARRAY_TYPE:
00917 return JSValue::kSize;
00918 case JS_REGEXP_TYPE:
00919 return JSValue::kSize;
00920 case JS_OBJECT_TYPE:
00921 return JSObject::kHeaderSize;
00922 default:
00923 UNREACHABLE();
00924 return 0;
00925 }
00926 }
00927
00928
00929 int JSObject::GetInternalFieldCount() {
00930 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
00931
00932
00933 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
00934 map()->inobject_properties();
00935 }
00936
00937
00938 Object* JSObject::GetInternalField(int index) {
00939 ASSERT(index < GetInternalFieldCount() && index >= 0);
00940
00941
00942
00943 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
00944 }
00945
00946
00947 void JSObject::SetInternalField(int index, Object* value) {
00948 ASSERT(index < GetInternalFieldCount() && index >= 0);
00949
00950
00951
00952 int offset = GetHeaderSize() + (kPointerSize * index);
00953 WRITE_FIELD(this, offset, value);
00954 WRITE_BARRIER(this, offset);
00955 }
00956
00957
00958
00959
00960
00961 Object* JSObject::FastPropertyAt(int index) {
00962
00963 index -= map()->inobject_properties();
00964 if (index < 0) {
00965 int offset = map()->instance_size() + (index * kPointerSize);
00966 return READ_FIELD(this, offset);
00967 } else {
00968 ASSERT(index < properties()->length());
00969 return properties()->get(index);
00970 }
00971 }
00972
00973
00974 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
00975
00976 index -= map()->inobject_properties();
00977 if (index < 0) {
00978 int offset = map()->instance_size() + (index * kPointerSize);
00979 WRITE_FIELD(this, offset, value);
00980 WRITE_BARRIER(this, offset);
00981 } else {
00982 ASSERT(index < properties()->length());
00983 properties()->set(index, value);
00984 }
00985 return value;
00986 }
00987
00988
00989 Object* JSObject::InObjectPropertyAtPut(int index,
00990 Object* value,
00991 WriteBarrierMode mode) {
00992
00993 index -= map()->inobject_properties();
00994 ASSERT(index < 0);
00995 int offset = map()->instance_size() + (index * kPointerSize);
00996 WRITE_FIELD(this, offset, value);
00997 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
00998 return value;
00999 }
01000
01001
01002
01003 void JSObject::InitializeBody(int object_size) {
01004 Object* value = Heap::undefined_value();
01005 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
01006 WRITE_FIELD(this, offset, value);
01007 }
01008 }
01009
01010
01011 void Struct::InitializeBody(int object_size) {
01012 Object* value = Heap::undefined_value();
01013 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
01014 WRITE_FIELD(this, offset, value);
01015 }
01016 }
01017
01018
01019 bool JSObject::HasFastProperties() {
01020 return !properties()->IsDictionary();
01021 }
01022
01023
01024 bool Array::IndexFromObject(Object* object, uint32_t* index) {
01025 if (object->IsSmi()) {
01026 int value = Smi::cast(object)->value();
01027 if (value < 0) return false;
01028 *index = value;
01029 return true;
01030 }
01031 if (object->IsHeapNumber()) {
01032 double value = HeapNumber::cast(object)->value();
01033 uint32_t uint_value = static_cast<uint32_t>(value);
01034 if (value == static_cast<double>(uint_value)) {
01035 *index = uint_value;
01036 return true;
01037 }
01038 }
01039 return false;
01040 }
01041
01042
01043 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
01044 if (!this->IsJSValue()) return false;
01045
01046 JSValue* js_value = JSValue::cast(this);
01047 if (!js_value->value()->IsString()) return false;
01048
01049 String* str = String::cast(js_value->value());
01050 if (index >= (uint32_t)str->length()) return false;
01051
01052 return true;
01053 }
01054
01055
01056 Object* FixedArray::get(int index) {
01057 ASSERT(index >= 0 && index < this->length());
01058 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
01059 }
01060
01061
01062 void FixedArray::set(int index, Object* value) {
01063 ASSERT(index >= 0 && index < this->length());
01064 int offset = kHeaderSize + index * kPointerSize;
01065 WRITE_FIELD(this, offset, value);
01066 WRITE_BARRIER(this, offset);
01067 }
01068
01069
01070 WriteBarrierMode HeapObject::GetWriteBarrierMode() {
01071 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
01072 return UPDATE_WRITE_BARRIER;
01073 }
01074
01075
01076 void FixedArray::set(int index,
01077 Object* value,
01078 WriteBarrierMode mode) {
01079 ASSERT(index >= 0 && index < this->length());
01080 int offset = kHeaderSize + index * kPointerSize;
01081 WRITE_FIELD(this, offset, value);
01082 CONDITIONAL_WRITE_BARRIER(this, offset, mode);
01083 }
01084
01085
01086 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
01087 ASSERT(index >= 0 && index < array->length());
01088 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
01089 }
01090
01091
01092 void FixedArray::set_undefined(int index) {
01093 ASSERT(index >= 0 && index < this->length());
01094 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
01095 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
01096 Heap::undefined_value());
01097 }
01098
01099
01100 void FixedArray::set_null(int index) {
01101 ASSERT(index >= 0 && index < this->length());
01102 ASSERT(!Heap::InNewSpace(Heap::null_value()));
01103 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
01104 }
01105
01106
01107 void FixedArray::set_the_hole(int index) {
01108 ASSERT(index >= 0 && index < this->length());
01109 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
01110 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
01111 }
01112
01113
01114 bool DescriptorArray::IsEmpty() {
01115 ASSERT(this == Heap::empty_descriptor_array() ||
01116 this->length() > 2);
01117 return this == Heap::empty_descriptor_array();
01118 }
01119
01120
01121 void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
01122 Object* tmp = array->get(first);
01123 fast_set(array, first, array->get(second));
01124 fast_set(array, second, tmp);
01125 }
01126
01127
01128 int DescriptorArray::Search(String* name) {
01129 SLOW_ASSERT(IsSortedNoDuplicates());
01130
01131
01132 int nof = number_of_descriptors();
01133 if (nof == 0) return kNotFound;
01134
01135
01136 const int kMaxElementsForLinearSearch = 8;
01137 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
01138 return LinearSearch(name, nof);
01139 }
01140
01141
01142 return BinarySearch(name, 0, nof - 1);
01143 }
01144
01145
01146
01147 String* DescriptorArray::GetKey(int descriptor_number) {
01148 ASSERT(descriptor_number < number_of_descriptors());
01149 return String::cast(get(ToKeyIndex(descriptor_number)));
01150 }
01151
01152
01153 Object* DescriptorArray::GetValue(int descriptor_number) {
01154 ASSERT(descriptor_number < number_of_descriptors());
01155 return GetContentArray()->get(ToValueIndex(descriptor_number));
01156 }
01157
01158
01159 Smi* DescriptorArray::GetDetails(int descriptor_number) {
01160 ASSERT(descriptor_number < number_of_descriptors());
01161 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
01162 }
01163
01164
01165 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
01166 desc->Init(GetKey(descriptor_number),
01167 GetValue(descriptor_number),
01168 GetDetails(descriptor_number));
01169 }
01170
01171
01172 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
01173
01174 ASSERT(descriptor_number < number_of_descriptors());
01175
01176
01177 ASSERT(!Heap::InNewSpace(desc->GetKey()));
01178 ASSERT(!Heap::InNewSpace(desc->GetValue()));
01179
01180 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
01181 FixedArray* content_array = GetContentArray();
01182 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
01183 fast_set(content_array, ToDetailsIndex(descriptor_number),
01184 desc->GetDetails().AsSmi());
01185 }
01186
01187
01188 void DescriptorArray::Swap(int first, int second) {
01189 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
01190 FixedArray* content_array = GetContentArray();
01191 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
01192 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
01193 }
01194
01195
01196 bool Dictionary::requires_slow_elements() {
01197 Object* max_index_object = get(kMaxNumberKeyIndex);
01198 if (!max_index_object->IsSmi()) return false;
01199 return 0 !=
01200 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
01201 }
01202
01203
01204 uint32_t Dictionary::max_number_key() {
01205 ASSERT(!requires_slow_elements());
01206 Object* max_index_object = get(kMaxNumberKeyIndex);
01207 if (!max_index_object->IsSmi()) return 0;
01208 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
01209 return value >> kRequiresSlowElementsTagSize;
01210 }
01211
01212
01213
01214
01215
01216
01217 CAST_ACCESSOR(FixedArray)
01218 CAST_ACCESSOR(DescriptorArray)
01219 CAST_ACCESSOR(Dictionary)
01220 CAST_ACCESSOR(SymbolTable)
01221 CAST_ACCESSOR(CompilationCacheTable)
01222 CAST_ACCESSOR(MapCache)
01223 CAST_ACCESSOR(LookupCache)
01224 CAST_ACCESSOR(String)
01225 CAST_ACCESSOR(SeqString)
01226 CAST_ACCESSOR(SeqAsciiString)
01227 CAST_ACCESSOR(SeqTwoByteString)
01228 CAST_ACCESSOR(ConsString)
01229 CAST_ACCESSOR(SlicedString)
01230 CAST_ACCESSOR(ExternalString)
01231 CAST_ACCESSOR(ExternalAsciiString)
01232 CAST_ACCESSOR(ExternalTwoByteString)
01233 CAST_ACCESSOR(JSObject)
01234 CAST_ACCESSOR(Smi)
01235 CAST_ACCESSOR(Failure)
01236 CAST_ACCESSOR(HeapObject)
01237 CAST_ACCESSOR(HeapNumber)
01238 CAST_ACCESSOR(Oddball)
01239 CAST_ACCESSOR(SharedFunctionInfo)
01240 CAST_ACCESSOR(Map)
01241 CAST_ACCESSOR(JSFunction)
01242 CAST_ACCESSOR(GlobalObject)
01243 CAST_ACCESSOR(JSGlobalProxy)
01244 CAST_ACCESSOR(JSGlobalObject)
01245 CAST_ACCESSOR(JSBuiltinsObject)
01246 CAST_ACCESSOR(Code)
01247 CAST_ACCESSOR(JSArray)
01248 CAST_ACCESSOR(JSRegExp)
01249 CAST_ACCESSOR(Proxy)
01250 CAST_ACCESSOR(ByteArray)
01251 CAST_ACCESSOR(Struct)
01252
01253
01254 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
01255 STRUCT_LIST(MAKE_STRUCT_CAST)
01256 #undef MAKE_STRUCT_CAST
01257
01258 template <int prefix_size, int elem_size>
01259 HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
01260 Object* obj) {
01261 ASSERT(obj->IsHashTable());
01262 return reinterpret_cast<HashTable*>(obj);
01263 }
01264
01265
01266 INT_ACCESSORS(Array, length, kLengthOffset)
01267
01268
01269 bool String::Equals(String* other) {
01270 if (other == this) return true;
01271 if (IsSymbol() && other->IsSymbol()) return false;
01272 return SlowEquals(other);
01273 }
01274
01275
01276 int String::length() {
01277 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
01278
01279 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
01280 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
01281 ASSERT(kLongStringTag == 0);
01282
01283 return len >> (size_tag() + kLongLengthShift);
01284 }
01285
01286
01287 void String::set_length(int value) {
01288 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
01289 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
01290 ASSERT(kLongStringTag == 0);
01291
01292 WRITE_INT_FIELD(this,
01293 kLengthOffset,
01294 value << (size_tag() + kLongLengthShift));
01295 }
01296
01297
01298 uint32_t String::length_field() {
01299 return READ_UINT32_FIELD(this, kLengthOffset);
01300 }
01301
01302
01303 void String::set_length_field(uint32_t value) {
01304 WRITE_UINT32_FIELD(this, kLengthOffset, value);
01305 }
01306
01307
01308 void String::TryFlatten() {
01309
01310
01311 StringRepresentationTag str_type = representation_tag();
01312 if (str_type != kSeqStringTag && str_type != kExternalStringTag) {
01313 Flatten();
01314 }
01315 }
01316
01317
01318 uint16_t String::Get(int index) {
01319 ASSERT(index >= 0 && index < length());
01320 switch (representation_tag()) {
01321 case kSeqStringTag:
01322 return is_ascii_representation()
01323 ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index)
01324 : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
01325 case kConsStringTag:
01326 return ConsString::cast(this)->ConsStringGet(index);
01327 case kSlicedStringTag:
01328 return SlicedString::cast(this)->SlicedStringGet(index);
01329 case kExternalStringTag:
01330 return is_ascii_representation()
01331 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
01332 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
01333 default:
01334 break;
01335 }
01336
01337 UNREACHABLE();
01338 return 0;
01339 }
01340
01341
01342 void String::Set(int index, uint16_t value) {
01343 ASSERT(index >= 0 && index < length());
01344 ASSERT(IsSeqString());
01345
01346 return is_ascii_representation()
01347 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
01348 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
01349 }
01350
01351
01352 bool String::IsAsciiRepresentation() {
01353 return is_ascii_representation();
01354 }
01355
01356
01357 bool String::StringIsConsString() {
01358 return representation_tag() == kConsStringTag;
01359 }
01360
01361
01362 bool String::StringIsSlicedString() {
01363 return representation_tag() == kSlicedStringTag;
01364 }
01365
01366
01367 uint32_t String::size_tag() {
01368 return map_size_tag(map());
01369 }
01370
01371
01372 uint32_t String::map_size_tag(Map* map) {
01373 return map->instance_type() & kStringSizeMask;
01374 }
01375
01376
01377 bool String::is_symbol() {
01378 return is_symbol_map(map());
01379 }
01380
01381
01382 bool String::is_symbol_map(Map* map) {
01383 return (map->instance_type() & kIsSymbolMask) != 0;
01384 }
01385
01386
01387 bool String::is_ascii_representation() {
01388 return is_ascii_representation_map(map());
01389 }
01390
01391
01392 bool String::is_ascii_representation_map(Map* map) {
01393 return (map->instance_type() & kStringEncodingMask) != 0;
01394 }
01395
01396
01397 int String::full_representation_tag() {
01398 return map()->instance_type() &
01399 (kStringRepresentationMask | kStringEncodingMask);
01400 }
01401
01402
01403 StringRepresentationTag String::representation_tag() {
01404 return map_representation_tag(map());
01405 }
01406
01407
01408 StringRepresentationTag String::map_representation_tag(Map* map) {
01409 uint32_t tag = map->instance_type() & kStringRepresentationMask;
01410 return static_cast<StringRepresentationTag>(tag);
01411 }
01412
01413
01414 bool String::IsFlat() {
01415 switch (this->representation_tag()) {
01416 case kConsStringTag:
01417
01418 return String::cast(ConsString::cast(this)->second())->length() == 0;
01419 case kSlicedStringTag: {
01420 String* slice = String::cast(SlicedString::cast(this)->buffer());
01421 StringRepresentationTag tag = slice->representation_tag();
01422 return tag == kSeqStringTag || tag == kExternalStringTag;
01423 }
01424 default:
01425 return true;
01426 }
01427 }
01428
01429
01430 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
01431 ASSERT(index >= 0 && index < length());
01432 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
01433 }
01434
01435
01436 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
01437 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
01438 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
01439 static_cast<byte>(value));
01440 }
01441
01442
01443 Address SeqAsciiString::GetCharsAddress() {
01444 return FIELD_ADDR(this, kHeaderSize);
01445 }
01446
01447
01448 char* SeqAsciiString::GetChars() {
01449 return reinterpret_cast<char*>(GetCharsAddress());
01450 }
01451
01452
01453 Address SeqTwoByteString::GetCharsAddress() {
01454 return FIELD_ADDR(this, kHeaderSize);
01455 }
01456
01457
01458 uc16* SeqTwoByteString::GetChars() {
01459 return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
01460 }
01461
01462
01463 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
01464 ASSERT(index >= 0 && index < length());
01465 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
01466 }
01467
01468
01469 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
01470 ASSERT(index >= 0 && index < length());
01471 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
01472 }
01473
01474
01475 int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
01476 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
01477
01478 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
01479 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
01480 ASSERT(kLongStringTag == 0);
01481
01482
01483
01484 length >>= map_size_tag(map) + kLongLengthShift;
01485
01486 return SizeFor(length);
01487 }
01488
01489
01490 int SeqAsciiString::SeqAsciiStringSize(Map* map) {
01491 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
01492
01493 ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
01494 ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
01495 ASSERT(kLongStringTag == 0);
01496
01497
01498
01499 length >>= map_size_tag(map) + kLongLengthShift;
01500
01501 return SizeFor(length);
01502 }
01503
01504
01505 Object* ConsString::first() {
01506 return READ_FIELD(this, kFirstOffset);
01507 }
01508
01509
01510 void ConsString::set_first(Object* value, WriteBarrierMode mode) {
01511 WRITE_FIELD(this, kFirstOffset, value);
01512 CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
01513 }
01514
01515
01516 Object* ConsString::second() {
01517 return READ_FIELD(this, kSecondOffset);
01518 }
01519
01520
01521 void ConsString::set_second(Object* value, WriteBarrierMode mode) {
01522 WRITE_FIELD(this, kSecondOffset, value);
01523 CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
01524 }
01525
01526
01527 Object* SlicedString::buffer() {
01528 return READ_FIELD(this, kBufferOffset);
01529 }
01530
01531
01532 void SlicedString::set_buffer(Object* buffer) {
01533 WRITE_FIELD(this, kBufferOffset, buffer);
01534 WRITE_BARRIER(this, kBufferOffset);
01535 }
01536
01537
01538 int SlicedString::start() {
01539 return READ_INT_FIELD(this, kStartOffset);
01540 }
01541
01542
01543 void SlicedString::set_start(int start) {
01544 WRITE_INT_FIELD(this, kStartOffset, start);
01545 }
01546
01547
01548 ExternalAsciiString::Resource* ExternalAsciiString::resource() {
01549 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
01550 }
01551
01552
01553 void ExternalAsciiString::set_resource(
01554 ExternalAsciiString::Resource* resource) {
01555 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
01556 }
01557
01558
01559 ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
01560 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
01561 }
01562
01563
01564 void ExternalTwoByteString::set_resource(
01565 ExternalTwoByteString::Resource* resource) {
01566 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
01567 }
01568
01569
01570 byte ByteArray::get(int index) {
01571 ASSERT(index >= 0 && index < this->length());
01572 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
01573 }
01574
01575
01576 void ByteArray::set(int index, byte value) {
01577 ASSERT(index >= 0 && index < this->length());
01578 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
01579 }
01580
01581
01582 int ByteArray::get_int(int index) {
01583 ASSERT(index >= 0 && (index * kIntSize) < this->length());
01584 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
01585 }
01586
01587
01588 ByteArray* ByteArray::FromDataStartAddress(Address address) {
01589 ASSERT_TAG_ALIGNED(address);
01590 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
01591 }
01592
01593
01594 Address ByteArray::GetDataStartAddress() {
01595 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
01596 }
01597
01598
01599 int Map::instance_size() {
01600 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
01601 }
01602
01603
01604 int Map::inobject_properties() {
01605 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
01606 }
01607
01608
01609 int HeapObject::SizeFromMap(Map* map) {
01610 InstanceType instance_type = map->instance_type();
01611
01612 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
01613 if (instance_type == FIXED_ARRAY_TYPE) {
01614 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
01615 }
01616
01617 return SlowSizeFromMap(map);
01618 }
01619
01620
01621 void Map::set_instance_size(int value) {
01622 ASSERT((value & ~(kPointerSize - 1)) == value);
01623 value >>= kPointerSizeLog2;
01624 ASSERT(0 <= value && value < 256);
01625 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
01626 }
01627
01628
01629 void Map::set_inobject_properties(int value) {
01630 ASSERT(0 <= value && value < 256);
01631 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
01632 }
01633
01634
01635 InstanceType Map::instance_type() {
01636 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
01637 }
01638
01639
01640 void Map::set_instance_type(InstanceType value) {
01641 ASSERT(0 <= value && value < 256);
01642 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
01643 }
01644
01645
01646 int Map::unused_property_fields() {
01647 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
01648 }
01649
01650
01651 void Map::set_unused_property_fields(int value) {
01652 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
01653 }
01654
01655
01656 byte Map::bit_field() {
01657 return READ_BYTE_FIELD(this, kBitFieldOffset);
01658 }
01659
01660
01661 void Map::set_bit_field(byte value) {
01662 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
01663 }
01664
01665
01666 void Map::set_non_instance_prototype(bool value) {
01667 if (value) {
01668 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
01669 } else {
01670 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
01671 }
01672 }
01673
01674
01675 bool Map::has_non_instance_prototype() {
01676 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
01677 }
01678
01679
01680 Code::Flags Code::flags() {
01681 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
01682 }
01683
01684
01685 void Code::set_flags(Code::Flags flags) {
01686
01687 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
01688 ExtractArgumentsCountFromFlags(flags) >= 0);
01689 WRITE_INT_FIELD(this, kFlagsOffset, flags);
01690 }
01691
01692
01693 Code::Kind Code::kind() {
01694 return ExtractKindFromFlags(flags());
01695 }
01696
01697
01698 InlineCacheState Code::ic_state() {
01699 InlineCacheState result = ExtractICStateFromFlags(flags());
01700
01701
01702
01703 ASSERT(is_inline_cache_stub() ||
01704 result == UNINITIALIZED ||
01705 result == DEBUG_BREAK ||
01706 result == DEBUG_PREPARE_STEP_IN);
01707 return result;
01708 }
01709
01710
01711 PropertyType Code::type() {
01712 ASSERT(ic_state() == MONOMORPHIC);
01713 return ExtractTypeFromFlags(flags());
01714 }
01715
01716
01717 int Code::arguments_count() {
01718 ASSERT(is_call_stub() || kind() == STUB);
01719 return ExtractArgumentsCountFromFlags(flags());
01720 }
01721
01722
01723 CodeStub::Major Code::major_key() {
01724 ASSERT(kind() == STUB);
01725 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
01726 kStubMajorKeyOffset));
01727 }
01728
01729
01730 void Code::set_major_key(CodeStub::Major major) {
01731 ASSERT(kind() == STUB);
01732 ASSERT(0 <= major && major < 256);
01733 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
01734 }
01735
01736
01737 bool Code::is_inline_cache_stub() {
01738 Kind kind = this->kind();
01739 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
01740 }
01741
01742
01743 Code::Flags Code::ComputeFlags(Kind kind,
01744 InlineCacheState ic_state,
01745 PropertyType type,
01746 int argc) {
01747
01748 int bits = kind << kFlagsKindShift;
01749 bits |= ic_state << kFlagsICStateShift;
01750 bits |= type << kFlagsTypeShift;
01751 bits |= argc << kFlagsArgumentsCountShift;
01752
01753 Flags result = static_cast<Flags>(bits);
01754 ASSERT(ExtractKindFromFlags(result) == kind);
01755 ASSERT(ExtractICStateFromFlags(result) == ic_state);
01756 ASSERT(ExtractTypeFromFlags(result) == type);
01757 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
01758 return result;
01759 }
01760
01761
01762 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
01763 PropertyType type,
01764 int argc) {
01765 return ComputeFlags(kind, MONOMORPHIC, type, argc);
01766 }
01767
01768
01769 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
01770 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
01771 return static_cast<Kind>(bits);
01772 }
01773
01774
01775 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
01776 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
01777 return static_cast<InlineCacheState>(bits);
01778 }
01779
01780
01781 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
01782 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
01783 return static_cast<PropertyType>(bits);
01784 }
01785
01786
01787 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
01788 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
01789 }
01790
01791
01792 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
01793 int bits = flags & ~kFlagsTypeMask;
01794 return static_cast<Flags>(bits);
01795 }
01796
01797
01798 Object* Map::prototype() {
01799 return READ_FIELD(this, kPrototypeOffset);
01800 }
01801
01802
01803 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
01804 ASSERT(value->IsNull() || value->IsJSObject());
01805 WRITE_FIELD(this, kPrototypeOffset, value);
01806 CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
01807 }
01808
01809
01810 ACCESSORS(Map, instance_descriptors, DescriptorArray,
01811 kInstanceDescriptorsOffset)
01812 ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
01813 ACCESSORS(Map, constructor, Object, kConstructorOffset)
01814
01815 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
01816 ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
01817
01818 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
01819 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
01820 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
01821
01822 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
01823
01824 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
01825 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
01826 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
01827 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
01828 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
01829
01830 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
01831 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
01832 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
01833
01834 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
01835 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
01836 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
01837 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
01838 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
01839 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
01840
01841 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
01842 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
01843
01844 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
01845 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
01846
01847 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
01848 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
01849 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
01850 kPropertyAccessorsOffset)
01851 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
01852 kPrototypeTemplateOffset)
01853 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
01854 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
01855 kNamedPropertyHandlerOffset)
01856 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
01857 kIndexedPropertyHandlerOffset)
01858 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
01859 kInstanceTemplateOffset)
01860 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
01861 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
01862 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
01863 kInstanceCallHandlerOffset)
01864 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
01865 kAccessCheckInfoOffset)
01866 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
01867
01868 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
01869 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
01870 kInternalFieldCountOffset)
01871
01872 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
01873 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
01874
01875 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
01876
01877 ACCESSORS(Script, source, Object, kSourceOffset)
01878 ACCESSORS(Script, name, Object, kNameOffset)
01879 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
01880 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
01881 ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
01882 ACCESSORS(Script, type, Smi, kTypeOffset)
01883
01884 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
01885 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
01886 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
01887 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
01888
01889 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
01890 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
01891 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
01892 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
01893
01894 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
01895 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
01896 kInstanceClassNameOffset)
01897 ACCESSORS(SharedFunctionInfo, function_data, Object,
01898 kExternalReferenceDataOffset)
01899 ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
01900 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
01901 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
01902
01903 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
01904 kHiddenPrototypeBit)
01905 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
01906 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
01907 kNeedsAccessCheckBit)
01908 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
01909 kIsExpressionBit)
01910 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
01911 kIsTopLevelBit)
01912
01913 INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
01914 INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
01915 kFormalParameterCountOffset)
01916 INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
01917 kExpectedNofPropertiesOffset)
01918 INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
01919 kStartPositionAndTypeOffset)
01920 INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
01921 INT_ACCESSORS(SharedFunctionInfo, function_token_position,
01922 kFunctionTokenPositionOffset)
01923
01924
01925 void SharedFunctionInfo::DontAdaptArguments() {
01926 ASSERT(code()->kind() == Code::BUILTIN);
01927 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
01928 }
01929
01930
01931 int SharedFunctionInfo::start_position() {
01932 return start_position_and_type() >> kStartPositionShift;
01933 }
01934
01935
01936 void SharedFunctionInfo::set_start_position(int start_position) {
01937 set_start_position_and_type((start_position << kStartPositionShift)
01938 | (start_position_and_type() & ~kStartPositionMask));
01939 }
01940
01941
01942 Code* SharedFunctionInfo::code() {
01943 return Code::cast(READ_FIELD(this, kCodeOffset));
01944 }
01945
01946
01947 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
01948 WRITE_FIELD(this, kCodeOffset, value);
01949 CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
01950 }
01951
01952
01953 bool SharedFunctionInfo::is_compiled() {
01954
01955 return code()->kind() != Code::STUB;
01956 }
01957
01958
01959 bool JSFunction::IsBoilerplate() {
01960 return map() == Heap::boilerplate_function_map();
01961 }
01962
01963
01964 bool JSFunction::IsLoaded() {
01965 return shared()->lazy_load_data() == Heap::undefined_value();
01966 }
01967
01968
01969 Code* JSFunction::code() {
01970 return shared()->code();
01971 }
01972
01973
01974 void JSFunction::set_code(Code* value) {
01975 shared()->set_code(value);
01976 }
01977
01978
01979 Context* JSFunction::context() {
01980 return Context::cast(READ_FIELD(this, kContextOffset));
01981 }
01982
01983
01984 Object* JSFunction::unchecked_context() {
01985 return READ_FIELD(this, kContextOffset);
01986 }
01987
01988
01989 void JSFunction::set_context(Object* value) {
01990 ASSERT(value == Heap::undefined_value() || value->IsContext());
01991 WRITE_FIELD(this, kContextOffset, value);
01992 WRITE_BARRIER(this, kContextOffset);
01993 }
01994
01995 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
01996 kPrototypeOrInitialMapOffset)
01997
01998
01999 Map* JSFunction::initial_map() {
02000 return Map::cast(prototype_or_initial_map());
02001 }
02002
02003
02004 void JSFunction::set_initial_map(Map* value) {
02005 set_prototype_or_initial_map(value);
02006 }
02007
02008
02009 bool JSFunction::has_initial_map() {
02010 return prototype_or_initial_map()->IsMap();
02011 }
02012
02013
02014 bool JSFunction::has_instance_prototype() {
02015 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
02016 }
02017
02018
02019 bool JSFunction::has_prototype() {
02020 return map()->has_non_instance_prototype() || has_instance_prototype();
02021 }
02022
02023
02024 Object* JSFunction::instance_prototype() {
02025 ASSERT(has_instance_prototype());
02026 if (has_initial_map()) return initial_map()->prototype();
02027
02028
02029 return prototype_or_initial_map();
02030 }
02031
02032
02033 Object* JSFunction::prototype() {
02034 ASSERT(has_prototype());
02035
02036
02037 if (map()->has_non_instance_prototype()) return map()->constructor();
02038 return instance_prototype();
02039 }
02040
02041
02042 bool JSFunction::is_compiled() {
02043 return shared()->is_compiled();
02044 }
02045
02046
02047 int JSFunction::NumberOfLiterals() {
02048 return literals()->length();
02049 }
02050
02051
02052 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
02053 ASSERT(0 <= id && id < kJSBuiltinsCount);
02054 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
02055 }
02056
02057
02058 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
02059 Object* value) {
02060 ASSERT(0 <= id && id < kJSBuiltinsCount);
02061 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
02062 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
02063 }
02064
02065
02066 Address Proxy::proxy() {
02067 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
02068 }
02069
02070
02071 void Proxy::set_proxy(Address value) {
02072 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
02073 }
02074
02075
02076 void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
02077 visitor->VisitExternalReference(
02078 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
02079 }
02080
02081
02082 ACCESSORS(JSValue, value, Object, kValueOffset)
02083
02084
02085 JSValue* JSValue::cast(Object* obj) {
02086 ASSERT(obj->IsJSValue());
02087 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
02088 return reinterpret_cast<JSValue*>(obj);
02089 }
02090
02091
02092 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
02093 INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
02094 INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
02095
02096
02097 Code::ICTargetState Code::ic_flag() {
02098 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
02099 }
02100
02101
02102 void Code::set_ic_flag(ICTargetState value) {
02103 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
02104 }
02105
02106
02107 byte* Code::instruction_start() {
02108 return FIELD_ADDR(this, kHeaderSize);
02109 }
02110
02111
02112 int Code::body_size() {
02113 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
02114 }
02115
02116
02117 byte* Code::relocation_start() {
02118 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
02119 }
02120
02121
02122 byte* Code::entry() {
02123 return instruction_start();
02124 }
02125
02126
02127 bool Code::contains(byte* pc) {
02128 return (instruction_start() <= pc) &&
02129 (pc < instruction_start() + instruction_size());
02130 }
02131
02132
02133 byte* Code::sinfo_start() {
02134 return FIELD_ADDR(this, CodeSize() - sinfo_size());
02135 }
02136
02137
02138 ACCESSORS(JSArray, length, Object, kLengthOffset)
02139
02140
02141 ACCESSORS(JSRegExp, data, Object, kDataOffset)
02142
02143
02144 JSRegExp::Type JSRegExp::TypeTag() {
02145 Object* data = this->data();
02146 if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
02147 Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
02148 return static_cast<JSRegExp::Type>(smi->value());
02149 }
02150
02151
02152 Object* JSRegExp::DataAt(int index) {
02153 ASSERT(TypeTag() != NOT_COMPILED);
02154 return FixedArray::cast(data())->get(index);
02155 }
02156
02157
02158 bool JSObject::HasFastElements() {
02159 return !elements()->IsDictionary();
02160 }
02161
02162
02163 bool JSObject::HasNamedInterceptor() {
02164 return map()->has_named_interceptor();
02165 }
02166
02167
02168 bool JSObject::HasIndexedInterceptor() {
02169 return map()->has_indexed_interceptor();
02170 }
02171
02172
02173 Dictionary* JSObject::property_dictionary() {
02174 ASSERT(!HasFastProperties());
02175 return Dictionary::cast(properties());
02176 }
02177
02178
02179 Dictionary* JSObject::element_dictionary() {
02180 ASSERT(!HasFastElements());
02181 return Dictionary::cast(elements());
02182 }
02183
02184
02185 bool String::HasHashCode() {
02186 return (length_field() & kHashComputedMask) != 0;
02187 }
02188
02189
02190 uint32_t String::Hash() {
02191
02192 uint32_t field = length_field();
02193 if (field & kHashComputedMask) return field >> kHashShift;
02194
02195 return ComputeAndSetHash();
02196 }
02197
02198
02199 StringHasher::StringHasher(int length)
02200 : length_(length),
02201 raw_running_hash_(0),
02202 array_index_(0),
02203 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
02204 is_first_char_(true),
02205 is_valid_(true) { }
02206
02207
02208 bool StringHasher::has_trivial_hash() {
02209 return length_ > String::kMaxMediumStringSize;
02210 }
02211
02212
02213 void StringHasher::AddCharacter(uc32 c) {
02214
02215
02216 raw_running_hash_ += c;
02217 raw_running_hash_ += (raw_running_hash_ << 10);
02218 raw_running_hash_ ^= (raw_running_hash_ >> 6);
02219
02220 if (is_array_index_) {
02221 if (c < '0' || c > '9') {
02222 is_array_index_ = false;
02223 } else {
02224 int d = c - '0';
02225 if (is_first_char_) {
02226 is_first_char_ = false;
02227 if (c == '0' && length_ > 1) {
02228 is_array_index_ = false;
02229 return;
02230 }
02231 }
02232 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
02233 is_array_index_ = false;
02234 } else {
02235 array_index_ = array_index_ * 10 + d;
02236 }
02237 }
02238 }
02239 }
02240
02241
02242 void StringHasher::AddCharacterNoIndex(uc32 c) {
02243 ASSERT(!is_array_index());
02244 raw_running_hash_ += c;
02245 raw_running_hash_ += (raw_running_hash_ << 10);
02246 raw_running_hash_ ^= (raw_running_hash_ >> 6);
02247 }
02248
02249
02250 uint32_t StringHasher::GetHash() {
02251 uint32_t result = raw_running_hash_;
02252 result += (result << 3);
02253 result ^= (result >> 11);
02254 result += (result << 15);
02255 return result;
02256 }
02257
02258
02259 bool String::AsArrayIndex(uint32_t* index) {
02260 uint32_t field = length_field();
02261 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
02262 return SlowAsArrayIndex(index);
02263 }
02264
02265
02266 Object* JSObject::GetPrototype() {
02267 return JSObject::cast(this)->map()->prototype();
02268 }
02269
02270
02271 PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
02272 return GetPropertyAttributeWithReceiver(this, key);
02273 }
02274
02275
02276 bool JSObject::HasElement(uint32_t index) {
02277 return HasElementWithReceiver(this, index);
02278 }
02279
02280
02281 bool AccessorInfo::all_can_read() {
02282 return BooleanBit::get(flag(), kAllCanReadBit);
02283 }
02284
02285
02286 void AccessorInfo::set_all_can_read(bool value) {
02287 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
02288 }
02289
02290
02291 bool AccessorInfo::all_can_write() {
02292 return BooleanBit::get(flag(), kAllCanWriteBit);
02293 }
02294
02295
02296 void AccessorInfo::set_all_can_write(bool value) {
02297 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
02298 }
02299
02300
02301 PropertyAttributes AccessorInfo::property_attributes() {
02302 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
02303 }
02304
02305
02306 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
02307 ASSERT(AttributesField::is_valid(attributes));
02308 int rest_value = flag()->value() & ~AttributesField::mask();
02309 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
02310 }
02311
02312 void Dictionary::SetEntry(int entry,
02313 Object* key,
02314 Object* value,
02315 PropertyDetails details) {
02316 ASSERT(!key->IsString() || details.index() > 0);
02317 int index = EntryToIndex(entry);
02318 WriteBarrierMode mode = GetWriteBarrierMode();
02319 set(index, key, mode);
02320 set(index+1, value, mode);
02321 fast_set(this, index+2, details.AsSmi());
02322 }
02323
02324
02325 void Map::ClearCodeCache() {
02326
02327
02328
02329 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
02330 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
02331 }
02332
02333
02334 void JSArray::SetContent(FixedArray* storage) {
02335 set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
02336 set_elements(storage);
02337 }
02338
02339
02340 Object* FixedArray::Copy() {
02341 if (length() == 0) return this;
02342 return Heap::CopyFixedArray(this);
02343 }
02344
02345
02346 #undef CAST_ACCESSOR
02347 #undef INT_ACCESSORS
02348 #undef SMI_ACCESSORS
02349 #undef ACCESSORS
02350 #undef FIELD_ADDR
02351 #undef READ_FIELD
02352 #undef WRITE_FIELD
02353 #undef WRITE_BARRIER
02354 #undef CONDITIONAL_WRITE_BARRIER
02355 #undef READ_MEMADDR_FIELD
02356 #undef WRITE_MEMADDR_FIELD
02357 #undef READ_DOUBLE_FIELD
02358 #undef WRITE_DOUBLE_FIELD
02359 #undef READ_INT_FIELD
02360 #undef WRITE_INT_FIELD
02361 #undef READ_SHORT_FIELD
02362 #undef WRITE_SHORT_FIELD
02363 #undef READ_BYTE_FIELD
02364 #undef WRITE_BYTE_FIELD
02365
02366
02367 } }
02368
02369 #endif // V8_OBJECTS_INL_H_