blob: 37919f1f8ab9e4512f2ca874d423f3bc7a61afdb [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright 2006-2008 Google Inc. 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 fuctions 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 { namespace internal {
44
45PropertyDetails::PropertyDetails(Smi* smi) {
46 value_ = smi->value();
47}
48
49
50Smi* PropertyDetails::AsSmi() {
51 return Smi::FromInt(value_);
52}
53
54
55#define CAST_ACCESSOR(type) \
56 type* type::cast(Object* object) { \
57 ASSERT(object->Is##type()); \
58 return reinterpret_cast<type*>(object); \
59 }
60
61
62#define INT_ACCESSORS(holder, name, offset) \
63 int holder::name() { return READ_INT_FIELD(this, offset); } \
64 void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
65
66
67#define ACCESSORS(holder, name, type, offset) \
68 type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
69 void holder::set_##name(type* value) { \
70 WRITE_FIELD(this, offset, value); \
71 WRITE_BARRIER(this, offset); \
72 }
73
74
75#define SMI_ACCESSORS(holder, name, offset) \
76 int holder::name() { \
77 Object* value = READ_FIELD(this, offset); \
78 return Smi::cast(value)->value(); \
79 } \
80 void holder::set_##name(int value) { \
81 WRITE_FIELD(this, offset, Smi::FromInt(value)); \
82 }
83
84
85#define BOOL_ACCESSORS(holder, field, name, offset) \
86 bool holder::name() { \
87 return BooleanBit::get(field(), offset); \
88 } \
89 void holder::set_##name(bool value) { \
90 set_##field(BooleanBit::set(field(), offset, value)); \
91 }
92
93
94bool Object::IsSmi() {
95 return HAS_SMI_TAG(this);
96}
97
98
99bool Object::IsHeapObject() {
100 return HAS_HEAP_OBJECT_TAG(this);
101}
102
103
104bool Object::IsHeapNumber() {
105 return Object::IsHeapObject()
106 && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
107}
108
109
110bool Object::IsString() {
111 return Object::IsHeapObject()
112 && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
113}
114
115
116bool Object::IsSeqString() {
117 return IsString()
118 && (String::cast(this)->representation_tag() == kSeqStringTag);
119}
120
121
122bool Object::IsAsciiString() {
123 return IsString() && (String::cast(this)->is_ascii());
124}
125
126
127bool Object::IsTwoByteString() {
128 return IsString() && (!String::cast(this)->is_ascii());
129}
130
131
132bool Object::IsConsString() {
133 return IsString()
134 && (String::cast(this)->representation_tag() == kConsStringTag);
135}
136
137
138bool Object::IsSlicedString() {
139 return IsString()
140 && (String::cast(this)->representation_tag() == kSlicedStringTag);
141}
142
143
144bool Object::IsExternalString() {
145 return IsString()
146 && (String::cast(this)->representation_tag() == kExternalStringTag);
147}
148
149
150bool Object::IsExternalAsciiString() {
151 return IsExternalString() && (String::cast(this)->is_ascii());
152}
153
154
155bool Object::IsExternalTwoByteString() {
156 return IsExternalString() && (!String::cast(this)->is_ascii());
157}
158
159
160bool Object::IsShortString() {
161 return IsString() && (String::cast(this)->size_tag() == kShortStringTag);
162}
163
164
165bool Object::IsMediumString() {
166 return IsString() && (String::cast(this)->size_tag() == kMediumStringTag);
167}
168
169
170bool Object::IsLongString() {
171 return IsString() && (String::cast(this)->size_tag() == kLongStringTag);
172}
173
174
175bool Object::IsSymbol() {
176 return IsString() && (String::cast(this)->is_symbol());
177}
178
179
180bool Object::IsNumber() {
181 return IsSmi() || IsHeapNumber();
182}
183
184
185bool Object::IsByteArray() {
186 return Object::IsHeapObject()
187 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
188}
189
190
191bool Object::IsFailure() {
192 return HAS_FAILURE_TAG(this);
193}
194
195
196bool Object::IsRetryAfterGC() {
197 return HAS_FAILURE_TAG(this)
198 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
199}
200
201
202bool Object::IsException() {
203 return this == Failure::Exception();
204}
205
206
207bool Object::IsJSObject() {
208 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000209 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210}
211
212
213bool Object::IsMap() {
214 return Object::IsHeapObject()
215 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
216}
217
218
219bool Object::IsFixedArray() {
220 return Object::IsHeapObject()
221 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
222}
223
224
225bool Object::IsDescriptorArray() {
226 return IsFixedArray();
227}
228
229
230bool Object::IsContext() {
231 return Object::IsHeapObject()
232 && (HeapObject::cast(this)->map() == Heap::context_map() ||
233 HeapObject::cast(this)->map() == Heap::global_context_map());
234}
235
236
237bool Object::IsGlobalContext() {
238 return Object::IsHeapObject()
239 && HeapObject::cast(this)->map() == Heap::global_context_map();
240}
241
242
243bool Object::IsJSFunction() {
244 return Object::IsHeapObject()
245 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
246}
247
248
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000249template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250 return obj->IsJSFunction();
251}
252
253
254bool Object::IsCode() {
255 return Object::IsHeapObject()
256 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
257}
258
259
260bool Object::IsOddball() {
261 return Object::IsHeapObject()
262 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
263}
264
265
266bool Object::IsSharedFunctionInfo() {
267 return Object::IsHeapObject() &&
268 (HeapObject::cast(this)->map()->instance_type() ==
269 SHARED_FUNCTION_INFO_TYPE);
270}
271
272
273bool Object::IsJSValue() {
274 return Object::IsHeapObject()
275 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
276}
277
278
279bool Object::IsProxy() {
280 return Object::IsHeapObject()
281 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
282}
283
284
285bool Object::IsBoolean() {
286 return IsTrue() || IsFalse();
287}
288
289
290bool Object::IsJSArray() {
291 return Object::IsHeapObject()
292 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
293}
294
295
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000296template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000297 return obj->IsJSArray();
298}
299
300
301bool Object::IsHashTable() {
302 return Object::IsHeapObject()
303 && HeapObject::cast(this)->map() == Heap::hash_table_map();
304}
305
306
307bool Object::IsDictionary() {
308 return IsHashTable() && this != Heap::symbol_table();
309}
310
311
312bool Object::IsSymbolTable() {
313 return IsHashTable() && this == Heap::symbol_table();
314}
315
316
317bool Object::IsPrimitive() {
318 return IsOddball() || IsNumber() || IsString();
319}
320
321
322bool Object::IsGlobalObject() {
323 return IsHeapObject() &&
324 ((HeapObject::cast(this)->map()->instance_type() ==
325 JS_GLOBAL_OBJECT_TYPE) ||
326 (HeapObject::cast(this)->map()->instance_type() ==
327 JS_BUILTINS_OBJECT_TYPE));
328}
329
330
331bool Object::IsJSGlobalObject() {
332#ifdef DEBUG
333 if (IsHeapObject() &&
334 (HeapObject::cast(this)->map()->instance_type() ==
335 JS_GLOBAL_OBJECT_TYPE)) {
336 ASSERT(IsAccessCheckNeeded());
337 }
338#endif
339 return IsHeapObject() &&
340 (HeapObject::cast(this)->map()->instance_type() ==
341 JS_GLOBAL_OBJECT_TYPE);
342}
343
344
345bool Object::IsJSBuiltinsObject() {
346 return IsHeapObject() &&
347 (HeapObject::cast(this)->map()->instance_type() ==
348 JS_BUILTINS_OBJECT_TYPE);
349}
350
351
352bool Object::IsUndetectableObject() {
353 return IsHeapObject()
354 && HeapObject::cast(this)->map()->is_undetectable();
355}
356
357
358bool Object::IsAccessCheckNeeded() {
359 return IsHeapObject()
360 && HeapObject::cast(this)->map()->needs_access_check();
361}
362
363
364bool Object::IsStruct() {
365 if (!IsHeapObject()) return false;
366 switch (HeapObject::cast(this)->map()->instance_type()) {
367#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
368 STRUCT_LIST(MAKE_STRUCT_CASE)
369#undef MAKE_STRUCT_CASE
370 default: return false;
371 }
372}
373
374
375#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
376 bool Object::Is##Name() { \
377 return Object::IsHeapObject() \
378 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
379 }
380 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
381#undef MAKE_STRUCT_PREDICATE
382
383
384bool Object::IsUndefined() {
385 return this == Heap::undefined_value();
386}
387
388
389bool Object::IsTheHole() {
390 return this == Heap::the_hole_value();
391}
392
393
394bool Object::IsNull() {
395 return this == Heap::null_value();
396}
397
398
399bool Object::IsTrue() {
400 return this == Heap::true_value();
401}
402
403
404bool Object::IsFalse() {
405 return this == Heap::false_value();
406}
407
408
409double Object::Number() {
410 ASSERT(IsNumber());
411 return IsSmi()
412 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
413 : reinterpret_cast<HeapNumber*>(this)->value();
414}
415
416
417
418Object* Object::ToSmi() {
419 if (IsSmi()) return this;
420 if (IsHeapNumber()) {
421 double value = HeapNumber::cast(this)->value();
422 int int_value = FastD2I(value);
423 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
424 return Smi::FromInt(int_value);
425 }
426 }
427 return Failure::Exception();
428}
429
430
431Object* Object::GetElement(uint32_t index) {
432 return GetElementWithReceiver(this, index);
433}
434
435
436Object* Object::GetProperty(String* key) {
437 PropertyAttributes attributes;
438 return GetPropertyWithReceiver(this, key, &attributes);
439}
440
441
442Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
443 return GetPropertyWithReceiver(this, key, attributes);
444}
445
446
447#define FIELD_ADDR(p, offset) \
448 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
449
450#define READ_FIELD(p, offset) \
451 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
452
453#define WRITE_FIELD(p, offset, value) \
454 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
455
456#define WRITE_BARRIER(object, offset) \
457 Heap::RecordWrite(object->address(), offset);
458
459#define READ_DOUBLE_FIELD(p, offset) \
460 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
461
462#define WRITE_DOUBLE_FIELD(p, offset, value) \
463 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
464
465#define READ_INT_FIELD(p, offset) \
466 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
467
468#define WRITE_INT_FIELD(p, offset, value) \
469 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
470
471#define READ_SHORT_FIELD(p, offset) \
472 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
473
474#define WRITE_SHORT_FIELD(p, offset, value) \
475 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
476
477#define READ_BYTE_FIELD(p, offset) \
478 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
479
480#define WRITE_BYTE_FIELD(p, offset, value) \
481 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
482
483
484Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
485 return READ_FIELD(obj, HeapObject::kSize + kPointerSize * index);
486}
487
488
489int Smi::value() {
490 return reinterpret_cast<int>(this) >> kSmiTagSize;
491}
492
493
494Smi* Smi::FromInt(int value) {
495 ASSERT(Smi::IsValid(value));
496 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
497}
498
499
500Failure::Type Failure::type() const {
501 return static_cast<Type>(value() & kFailureTypeTagMask);
502}
503
504
505bool Failure::IsInternalError() const {
506 return type() == INTERNAL_ERROR;
507}
508
509
510bool Failure::IsOutOfMemoryException() const {
511 return type() == OUT_OF_MEMORY_EXCEPTION;
512}
513
514
515int Failure::requested() const {
516 const int kShiftBits =
517 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
518 STATIC_ASSERT(kShiftBits >= 0);
519 ASSERT(type() == RETRY_AFTER_GC);
520 return value() >> kShiftBits;
521}
522
523
524AllocationSpace Failure::allocation_space() const {
525 ASSERT_EQ(RETRY_AFTER_GC, type());
526 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
527 & kSpaceTagMask);
528}
529
530
531Failure* Failure::InternalError() {
532 return Construct(INTERNAL_ERROR);
533}
534
535
536Failure* Failure::Exception() {
537 return Construct(EXCEPTION);
538}
539
540Failure* Failure::OutOfMemoryException() {
541 return Construct(OUT_OF_MEMORY_EXCEPTION);
542}
543
544
545int Failure::value() const {
546 return reinterpret_cast<int>(this) >> kFailureTagSize;
547}
548
549
550Failure* Failure::Construct(Type type, int value) {
551 int info = (value << kFailureTypeTagSize) | type;
552 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
553 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
554}
555
556
557bool Smi::IsValid(int value) {
558#ifdef DEBUG
559 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
560#endif
561 // To be representable as an tagged small integer, the two
562 // most-significant bits of 'value' must be either 00 or 11 due to
563 // sign-extension. To check this we add 01 to the two
564 // most-significant bits, and check if the most-significant bit is 0
565 //
566 // CAUTION: The original code below:
567 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
568 // may lead to incorrect results according to the C language spec, and
569 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
570 // compiler may produce undefined results in case of signed integer
571 // overflow. The computation must be done w/ unsigned ints.
572 bool result =
573 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
574 ASSERT(result == in_range);
575 return result;
576}
577
578
kasper.lund7276f142008-07-30 08:49:36 +0000579MapWord MapWord::FromMap(Map* map) {
580 return MapWord(reinterpret_cast<uintptr_t>(map));
581}
582
583
584Map* MapWord::ToMap() {
585 return reinterpret_cast<Map*>(value_);
586}
587
588
589bool MapWord::IsForwardingAddress() {
590 // This function only works for map words that are heap object pointers.
591 // Since it is a heap object, it has a map. We use that map's instance
592 // type to detect if this map word is not actually a map (ie, it is a
593 // forwarding address during a scavenge collection).
594 return reinterpret_cast<HeapObject*>(value_)->map()->instance_type() !=
595 MAP_TYPE;
596}
597
598
599MapWord MapWord::FromForwardingAddress(HeapObject* object) {
600 return MapWord(reinterpret_cast<uintptr_t>(object));
601}
602
603
604HeapObject* MapWord::ToForwardingAddress() {
605 ASSERT(IsForwardingAddress());
606 return reinterpret_cast<HeapObject*>(value_);
607}
608
609
610bool MapWord::IsMarked() {
611 return (value_ & kMarkingMask) == 0;
612}
613
614
615void MapWord::SetMark() {
616 value_ &= ~kMarkingMask;
617}
618
619
620void MapWord::ClearMark() {
621 value_ |= kMarkingMask;
622}
623
624
625bool MapWord::IsOverflowed() {
626 return (value_ & kOverflowMask) != 0;
627}
628
629
630void MapWord::SetOverflow() {
631 value_ |= kOverflowMask;
632}
633
634
635void MapWord::ClearOverflow() {
636 value_ &= ~kOverflowMask;
637}
638
639
640MapWord MapWord::EncodeAddress(Address map_address, int offset) {
641 // Offset is the distance in live bytes from the first live object in the
642 // same page. The offset between two objects in the same page should not
643 // exceed the object area size of a page.
644 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
645
646 int compact_offset = offset >> kObjectAlignmentBits;
647 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
648
649 Page* map_page = Page::FromAddress(map_address);
650 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
651
652 int map_page_offset =
653 map_page->Offset(map_address) >> kObjectAlignmentBits;
654
655 uintptr_t encoding =
656 (compact_offset << kForwardingOffsetShift) |
657 (map_page_offset << kMapPageOffsetShift) |
658 (map_page->mc_page_index << kMapPageIndexShift);
659 return MapWord(encoding);
660}
661
662
663Address MapWord::DecodeMapAddress(MapSpace* map_space) {
664 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
665 ASSERT_MAP_PAGE_INDEX(map_page_index);
666
667 int map_page_offset =
668 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
669 << kObjectAlignmentBits;
670
671 return (map_space->PageAddress(map_page_index) + map_page_offset);
672}
673
674
675int MapWord::DecodeOffset() {
676 // The offset field is represented in the kForwardingOffsetBits
677 // most-significant bits.
678 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
679 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
680 return offset;
681}
682
683
684MapWord MapWord::FromEncodedAddress(Address address) {
685 return MapWord(reinterpret_cast<uintptr_t>(address));
686}
687
688
689Address MapWord::ToEncodedAddress() {
690 return reinterpret_cast<Address>(value_);
691}
692
693
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000694#ifdef DEBUG
695void HeapObject::VerifyObjectField(int offset) {
696 VerifyPointer(READ_FIELD(this, offset));
697}
698#endif
699
700
701Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000702 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000703}
704
705
706void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000707 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708}
709
710
kasper.lund7276f142008-07-30 08:49:36 +0000711MapWord HeapObject::map_word() {
712 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
713}
714
715
716void HeapObject::set_map_word(MapWord map_word) {
717 // WRITE_FIELD does not update the remembered set, but there is no need
718 // here.
719 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
720}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000721
722
723HeapObject* HeapObject::FromAddress(Address address) {
724 ASSERT_TAG_ALIGNED(address);
725 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
726}
727
728
729Address HeapObject::address() {
730 return reinterpret_cast<Address>(this) - kHeapObjectTag;
731}
732
733
734int HeapObject::Size() {
735 return SizeFromMap(map());
736}
737
738
739void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
740 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
741 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
742}
743
744
745void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
746 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
747}
748
749
750void HeapObject::CopyBody(JSObject* from) {
751 ASSERT(map() == from->map());
752 ASSERT(Size() == from->Size());
753 int object_size = Size();
754 for (int offset = kSize; offset < object_size; offset += kPointerSize) {
755 Object* value = READ_FIELD(from, offset);
756 // Note: WRITE_FIELD does not update the write barrier.
757 WRITE_FIELD(this, offset, value);
758 WRITE_BARRIER(this, offset);
759 }
760}
761
762
kasper.lund7276f142008-07-30 08:49:36 +0000763bool HeapObject::IsMarked() {
764 return map_word().IsMarked();
765}
766
767
768void HeapObject::SetMark() {
769 ASSERT(!IsMarked());
770 MapWord first_word = map_word();
771 first_word.SetMark();
772 set_map_word(first_word);
773}
774
775
776void HeapObject::ClearMark() {
777 ASSERT(IsMarked());
778 MapWord first_word = map_word();
779 first_word.ClearMark();
780 set_map_word(first_word);
781}
782
783
784bool HeapObject::IsOverflowed() {
785 return map_word().IsOverflowed();
786}
787
788
789void HeapObject::SetOverflow() {
790 MapWord first_word = map_word();
791 first_word.SetOverflow();
792 set_map_word(first_word);
793}
794
795
796void HeapObject::ClearOverflow() {
797 ASSERT(IsOverflowed());
798 MapWord first_word = map_word();
799 first_word.ClearOverflow();
800 set_map_word(first_word);
801}
802
803
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000804double HeapNumber::value() {
805 return READ_DOUBLE_FIELD(this, kValueOffset);
806}
807
808
809void HeapNumber::set_value(double value) {
810 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
811}
812
813
814ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
815ACCESSORS(JSObject, elements, HeapObject, kElementsOffset)
816
817
818void JSObject::initialize_properties() {
819 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
820 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
821}
822
823
824void JSObject::initialize_elements() {
825 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
826 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
827}
828
829
830ACCESSORS(Oddball, to_string, String, kToStringOffset)
831ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
832
833
834int JSObject::GetHeaderSize() {
835 switch (map()->instance_type()) {
836 case JS_GLOBAL_OBJECT_TYPE:
837 return JSGlobalObject::kSize;
838 case JS_BUILTINS_OBJECT_TYPE:
839 return JSBuiltinsObject::kSize;
840 case JS_FUNCTION_TYPE:
841 return JSFunction::kSize;
842 case JS_VALUE_TYPE:
843 return JSValue::kSize;
844 case JS_ARRAY_TYPE:
845 return JSValue::kSize;
846 case JS_OBJECT_TYPE:
847 return JSObject::kHeaderSize;
848 default:
849 UNREACHABLE();
850 return 0;
851 }
852}
853
854
855int JSObject::GetInternalFieldCount() {
856 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
857 return (Size() - GetHeaderSize()) >> kPointerSizeLog2;
858}
859
860
861Object* JSObject::GetInternalField(int index) {
862 ASSERT(index < GetInternalFieldCount() && index >= 0);
863 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
864}
865
866
867void JSObject::SetInternalField(int index, Object* value) {
868 ASSERT(index < GetInternalFieldCount() && index >= 0);
869 int offset = GetHeaderSize() + (kPointerSize * index);
870 WRITE_FIELD(this, offset, value);
871 WRITE_BARRIER(this, offset);
872}
873
874
875void JSObject::InitializeBody(int object_size) {
876 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
877 WRITE_FIELD(this, offset, Heap::undefined_value());
878 }
879}
880
881
882void Struct::InitializeBody(int object_size) {
883 for (int offset = kSize; offset < object_size; offset += kPointerSize) {
884 WRITE_FIELD(this, offset, Heap::undefined_value());
885 }
886}
887
888
889bool JSObject::HasFastProperties() {
890 return !properties()->IsDictionary();
891}
892
893
894bool Array::IndexFromObject(Object* object, uint32_t* index) {
895 if (object->IsSmi()) {
896 int value = Smi::cast(object)->value();
897 if (value < 0) return false;
898 *index = value;
899 return true;
900 }
901 if (object->IsHeapNumber()) {
902 double value = HeapNumber::cast(object)->value();
903 uint32_t uint_value = static_cast<uint32_t>(value);
904 if (value == static_cast<double>(uint_value)) {
905 *index = uint_value;
906 return true;
907 }
908 }
909 return false;
910}
911
912
913bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
914 if (!this->IsJSValue()) return false;
915
916 JSValue* js_value = JSValue::cast(this);
917 if (!js_value->value()->IsString()) return false;
918
919 String* str = String::cast(js_value->value());
920 if (index >= (uint32_t)str->length()) return false;
921
922 return true;
923}
924
925
926Object* FixedArray::get(int index) {
927 ASSERT(index >= 0 && index < this->length());
928 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
929}
930
931
932void FixedArray::set(int index, Object* value) {
933 ASSERT(index >= 0 && index < this->length());
934 int offset = kHeaderSize + index * kPointerSize;
935 WRITE_FIELD(this, offset, value);
936 WRITE_BARRIER(this, offset);
937}
938
939
940FixedArray::WriteBarrierMode FixedArray::GetWriteBarrierMode() {
941 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
942 return UPDATE_WRITE_BARRIER;
943}
944
945
946void FixedArray::set(int index,
947 Object* value,
948 FixedArray::WriteBarrierMode mode) {
949 ASSERT(index >= 0 && index < this->length());
950 int offset = kHeaderSize + index * kPointerSize;
951 WRITE_FIELD(this, offset, value);
952 if (mode == UPDATE_WRITE_BARRIER) {
953 WRITE_BARRIER(this, offset);
954 } else {
955 ASSERT(mode == SKIP_WRITE_BARRIER);
956 ASSERT(Heap::InNewSpace(this) || !Heap::InNewSpace(value));
957 }
958}
959
960
961void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
962 ASSERT(index >= 0 && index < array->length());
963 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
964}
965
966
967void FixedArray::set_undefined(int index) {
968 ASSERT(index >= 0 && index < this->length());
969 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
970 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
971 Heap::undefined_value());
972}
973
974
975void FixedArray::set_the_hole(int index) {
976 ASSERT(index >= 0 && index < this->length());
977 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
978 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
979}
980
981
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000982bool DescriptorArray::IsEmpty() {
983 ASSERT(this == Heap::empty_descriptor_array() ||
984 this->length() > 2);
985 return this == Heap::empty_descriptor_array();
986}
987
988
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000989void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
990 Object* tmp = array->get(first);
991 fast_set(array, first, array->get(second));
992 fast_set(array, second, tmp);
993}
994
995
996int DescriptorArray::Search(String* name) {
997 SLOW_ASSERT(IsSortedNoDuplicates());
998
999 // Check for empty descriptor array.
1000 int nof = number_of_descriptors();
1001 if (nof == 0) return kNotFound;
1002
1003 // Fast case: do linear search for small arrays.
1004 const int kMaxElementsForLinearSearch = 8;
1005 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
1006 for (int number = 0; number < nof; number++) {
1007 if (name == GetKey(number)) return number;
1008 }
1009 return kNotFound;
1010 }
1011
1012 // Slow case: perform binary search.
1013 return BinarySearch(name, 0, nof - 1);
1014}
1015
1016
1017
1018String* DescriptorArray::GetKey(int descriptor_number) {
1019 ASSERT(descriptor_number < number_of_descriptors());
1020 return String::cast(get(ToKeyIndex(descriptor_number)));
1021}
1022
1023
1024Object* DescriptorArray::GetValue(int descriptor_number) {
1025 ASSERT(descriptor_number < number_of_descriptors());
1026 return GetContentArray()->get(ToValueIndex(descriptor_number));
1027}
1028
1029
1030Smi* DescriptorArray::GetDetails(int descriptor_number) {
1031 ASSERT(descriptor_number < number_of_descriptors());
1032 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1033}
1034
1035
1036void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1037 desc->Init(GetKey(descriptor_number),
1038 GetValue(descriptor_number),
1039 GetDetails(descriptor_number));
1040}
1041
1042
1043void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1044 // Range check.
1045 ASSERT(descriptor_number < number_of_descriptors());
1046
1047 // Make sure non of the elements in desc are in new space.
1048 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1049 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1050
1051 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1052 FixedArray* content_array = GetContentArray();
1053 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1054 fast_set(content_array, ToDetailsIndex(descriptor_number),
1055 desc->GetDetails().AsSmi());
1056}
1057
1058
1059void DescriptorArray::Swap(int first, int second) {
1060 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1061 FixedArray* content_array = GetContentArray();
1062 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1063 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1064}
1065
1066
1067bool Dictionary::requires_slow_elements() {
1068 Object* max_index_object = get(kPrefixStartIndex);
1069 if (!max_index_object->IsSmi()) return false;
1070 return 0 !=
1071 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1072}
1073
1074
1075uint32_t Dictionary::max_number_key() {
1076 ASSERT(!requires_slow_elements());
1077 Object* max_index_object = get(kPrefixStartIndex);
1078 if (!max_index_object->IsSmi()) return 0;
1079 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1080 return value >> kRequiresSlowElementsTagSize;
1081}
1082
1083
1084// ------------------------------------
1085// Cast operations
1086
1087
1088CAST_ACCESSOR(FixedArray)
1089CAST_ACCESSOR(DescriptorArray)
1090CAST_ACCESSOR(Dictionary)
1091CAST_ACCESSOR(SymbolTable)
1092CAST_ACCESSOR(String)
1093CAST_ACCESSOR(SeqString)
1094CAST_ACCESSOR(AsciiString)
1095CAST_ACCESSOR(TwoByteString)
1096CAST_ACCESSOR(ConsString)
1097CAST_ACCESSOR(SlicedString)
1098CAST_ACCESSOR(ExternalString)
1099CAST_ACCESSOR(ExternalAsciiString)
1100CAST_ACCESSOR(ExternalTwoByteString)
1101CAST_ACCESSOR(JSObject)
1102CAST_ACCESSOR(Smi)
1103CAST_ACCESSOR(Failure)
1104CAST_ACCESSOR(HeapObject)
1105CAST_ACCESSOR(HeapNumber)
1106CAST_ACCESSOR(Oddball)
1107CAST_ACCESSOR(SharedFunctionInfo)
1108CAST_ACCESSOR(Map)
1109CAST_ACCESSOR(JSFunction)
1110CAST_ACCESSOR(JSGlobalObject)
1111CAST_ACCESSOR(JSBuiltinsObject)
1112CAST_ACCESSOR(Code)
1113CAST_ACCESSOR(JSArray)
1114CAST_ACCESSOR(Proxy)
1115CAST_ACCESSOR(ByteArray)
1116CAST_ACCESSOR(Struct)
1117
1118
1119#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1120 STRUCT_LIST(MAKE_STRUCT_CAST)
1121#undef MAKE_STRUCT_CAST
1122
1123template <int prefix_size, int elem_size>
1124HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1125 Object* obj) {
1126 ASSERT(obj->IsHashTable());
1127 return reinterpret_cast<HashTable*>(obj);
1128}
1129
1130
1131INT_ACCESSORS(Array, length, kLengthOffset)
1132
1133
1134bool String::Equals(String* other) {
1135 if (other == this) return true;
1136 if (IsSymbol() && other->IsSymbol()) return false;
1137 return SlowEquals(other);
1138}
1139
1140
1141int String::length() {
1142 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1143
1144 switch (size_tag()) {
1145 case kShortStringTag:
1146 return len >> kShortLengthShift;
1147 case kMediumStringTag:
1148 return len >> kMediumLengthShift;
1149 case kLongStringTag:
1150 return len >> kLongLengthShift;
1151 default:
1152 break;
1153 }
1154 UNREACHABLE();
1155 return 0;
1156}
1157
1158
1159void String::set_length(int value) {
1160 switch (size_tag()) {
1161 case kShortStringTag:
1162 WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
1163 break;
1164 case kMediumStringTag:
1165 WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
1166 break;
1167 case kLongStringTag:
1168 WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
1169 break;
1170 default:
1171 UNREACHABLE();
1172 break;
1173 }
1174}
1175
1176
1177int String::length_field() {
1178 return READ_INT_FIELD(this, kLengthOffset);
1179}
1180
1181
1182void String::set_length_field(int value) {
1183 WRITE_INT_FIELD(this, kLengthOffset, value);
1184}
1185
1186
1187void String::TryFlatten() {
1188 Flatten();
1189}
1190
1191
1192uint16_t String::Get(int index) {
1193 ASSERT(index >= 0 && index < length());
1194 switch (representation_tag()) {
1195 case kSeqStringTag:
1196 return is_ascii()
1197 ? AsciiString::cast(this)->AsciiStringGet(index)
1198 : TwoByteString::cast(this)->TwoByteStringGet(index);
1199 case kConsStringTag:
1200 return ConsString::cast(this)->ConsStringGet(index);
1201 case kSlicedStringTag:
1202 return SlicedString::cast(this)->SlicedStringGet(index);
1203 case kExternalStringTag:
1204 return is_ascii()
1205 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
1206 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1207 default:
1208 break;
1209 }
1210
1211 UNREACHABLE();
1212 return 0;
1213}
1214
1215
1216void String::Set(int index, uint16_t value) {
1217 ASSERT(index >= 0 && index < length());
1218 ASSERT(IsSeqString());
1219
1220 return is_ascii()
1221 ? AsciiString::cast(this)->AsciiStringSet(index, value)
1222 : TwoByteString::cast(this)->TwoByteStringSet(index, value);
1223}
1224
1225
1226bool String::IsAscii() {
1227 return is_ascii();
1228}
1229
1230
1231bool String::StringIsConsString() {
1232 return representation_tag() == kConsStringTag;
1233}
1234
1235
1236bool String::StringIsSlicedString() {
1237 return representation_tag() == kSlicedStringTag;
1238}
1239
1240
1241uint32_t String::size_tag() {
1242 return map_size_tag(map());
1243}
1244
1245
1246uint32_t String::map_size_tag(Map* map) {
1247 return map->instance_type() & kStringSizeMask;
1248}
1249
1250
1251bool String::is_symbol() {
1252 return is_symbol_map(map());
1253}
1254
1255
1256bool String::is_symbol_map(Map* map) {
1257 return (map->instance_type() & kIsSymbolMask) != 0;
1258}
1259
1260
1261bool String::is_ascii() {
1262 return is_ascii_map(map());
1263}
1264
1265
1266bool String::is_ascii_map(Map* map) {
1267 return (map->instance_type() & kStringEncodingMask) != 0;
1268}
1269
1270
1271StringRepresentationTag String::representation_tag() {
1272 return map_representation_tag(map());
1273}
1274
1275
1276StringRepresentationTag String::map_representation_tag(Map* map) {
1277 uint32_t tag = map->instance_type() & kStringRepresentationMask;
1278 return static_cast<StringRepresentationTag>(tag);
1279}
1280
1281
1282bool String::IsFlat() {
1283 String* current = this;
1284 while (true) {
1285 switch (current->representation_tag()) {
1286 case kConsStringTag:
1287 return String::cast(ConsString::cast(current)->second())->length() == 0;
1288 case kSlicedStringTag:
1289 current = String::cast(SlicedString::cast(this)->buffer());
1290 break;
1291 default:
1292 return true;
1293 }
1294 }
1295}
1296
1297
1298uint16_t AsciiString::AsciiStringGet(int index) {
1299 ASSERT(index >= 0 && index < length());
1300 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1301}
1302
1303
1304void AsciiString::AsciiStringSet(int index, uint16_t value) {
1305 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1306 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1307 static_cast<byte>(value));
1308}
1309
1310
1311Address AsciiString::GetCharsAddress() {
1312 return FIELD_ADDR(this, kHeaderSize);
1313}
1314
1315
1316uint16_t TwoByteString::TwoByteStringGet(int index) {
1317 ASSERT(index >= 0 && index < length());
1318 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1319}
1320
1321
1322void TwoByteString::TwoByteStringSet(int index, uint16_t value) {
1323 ASSERT(index >= 0 && index < length());
1324 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1325}
1326
1327
1328int TwoByteString::TwoByteStringSize(Map* map) {
1329 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1330
1331 // Use the map (and not 'this') to compute the size tag, since
1332 // TwoByteStringSize is called during GC when maps are encoded.
1333 switch (map_size_tag(map)) {
1334 case kShortStringTag:
1335 length = length >> kShortLengthShift;
1336 break;
1337 case kMediumStringTag:
1338 length = length >> kMediumLengthShift;
1339 break;
1340 case kLongStringTag:
1341 length = length >> kLongLengthShift;
1342 break;
1343 default:
1344 break;
1345 }
1346 return SizeFor(length);
1347}
1348
1349
1350int AsciiString::AsciiStringSize(Map* map) {
1351 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1352
1353 // Use the map (and not 'this') to compute the size tag, since
1354 // AsciiStringSize is called during GC when maps are encoded.
1355 switch (map_size_tag(map)) {
1356 case kShortStringTag:
1357 length = length >> kShortLengthShift;
1358 break;
1359 case kMediumStringTag:
1360 length = length >> kMediumLengthShift;
1361 break;
1362 case kLongStringTag:
1363 length = length >> kLongLengthShift;
1364 break;
1365 default:
1366 break;
1367 }
1368
1369 return SizeFor(length);
1370}
1371
1372
1373Object* ConsString::first() {
1374 return READ_FIELD(this, kFirstOffset);
1375}
1376
1377
1378void ConsString::set_first(Object* value) {
1379 WRITE_FIELD(this, kFirstOffset, value);
1380 WRITE_BARRIER(this, kFirstOffset);
1381}
1382
1383
1384Object* ConsString::second() {
1385 return READ_FIELD(this, kSecondOffset);
1386}
1387
1388
1389void ConsString::set_second(Object* value) {
1390 WRITE_FIELD(this, kSecondOffset, value);
1391 WRITE_BARRIER(this, kSecondOffset);
1392}
1393
1394
1395Object* SlicedString::buffer() {
1396 return READ_FIELD(this, kBufferOffset);
1397}
1398
1399
1400void SlicedString::set_buffer(Object* buffer) {
1401 WRITE_FIELD(this, kBufferOffset, buffer);
1402 WRITE_BARRIER(this, kBufferOffset);
1403}
1404
1405
1406int SlicedString::start() {
1407 return READ_INT_FIELD(this, kStartOffset);
1408}
1409
1410
1411void SlicedString::set_start(int start) {
1412 WRITE_INT_FIELD(this, kStartOffset, start);
1413}
1414
1415
1416ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1417 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1418}
1419
1420
1421void ExternalAsciiString::set_resource(
1422 ExternalAsciiString::Resource* resource) {
1423 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1424}
1425
1426
1427ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1428 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1429}
1430
1431
1432void ExternalTwoByteString::set_resource(
1433 ExternalTwoByteString::Resource* resource) {
1434 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1435}
1436
1437
1438byte ByteArray::get(int index) {
1439 ASSERT(index >= 0 && index < this->length());
1440 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1441}
1442
1443
1444void ByteArray::set(int index, byte value) {
1445 ASSERT(index >= 0 && index < this->length());
1446 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1447}
1448
1449
1450int ByteArray::get_int(int index) {
1451 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1452 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1453}
1454
1455
1456ByteArray* ByteArray::FromDataStartAddress(Address address) {
1457 ASSERT_TAG_ALIGNED(address);
1458 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1459}
1460
1461
1462Address ByteArray::GetDataStartAddress() {
1463 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1464}
1465
1466
1467int Map::instance_size() {
1468 return READ_BYTE_FIELD(this, kInstanceSizeOffset);
1469}
1470
1471
1472int HeapObject::SizeFromMap(Map* map) {
1473 InstanceType instance_type = map->instance_type();
1474 // Only inline the two most frequent cases.
1475 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1476 if (instance_type == FIXED_ARRAY_TYPE) {
1477 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1478 }
1479 // Otherwise do the general size computation.
1480 return SlowSizeFromMap(map);
1481}
1482
1483
1484void Map::set_instance_size(int value) {
1485 ASSERT(0 <= value && value < 256);
1486 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1487}
1488
1489
1490InstanceType Map::instance_type() {
1491 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1492}
1493
1494
1495void Map::set_instance_type(InstanceType value) {
1496 ASSERT(0 <= value && value < 256);
1497 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1498}
1499
1500
1501int Map::unused_property_fields() {
1502 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1503}
1504
1505
1506void Map::set_unused_property_fields(int value) {
1507 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1508}
1509
1510
1511byte Map::bit_field() {
1512 return READ_BYTE_FIELD(this, kBitFieldOffset);
1513}
1514
1515
1516void Map::set_bit_field(byte value) {
1517 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1518}
1519
1520
1521void Map::set_non_instance_prototype(bool value) {
1522 if (value) {
1523 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1524 } else {
1525 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1526 }
1527}
1528
1529
1530bool Map::has_non_instance_prototype() {
1531 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1532}
1533
1534
1535Code::Flags Code::flags() {
1536 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1537}
1538
1539
1540void Code::set_flags(Code::Flags flags) {
1541 // Make sure that all call stubs have an arguments count.
1542 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1543 ExtractArgumentsCountFromFlags(flags) >= 0);
1544 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1545}
1546
1547
1548Code::Kind Code::kind() {
1549 return ExtractKindFromFlags(flags());
1550}
1551
1552
kasper.lund7276f142008-07-30 08:49:36 +00001553InlineCacheState Code::ic_state() {
1554 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001555 // Only allow uninitialized or debugger states for non-IC code
1556 // objects. This is used in the debugger to determine whether or not
1557 // a call to code object has been replaced with a debug break call.
1558 ASSERT(is_inline_cache_stub() ||
1559 result == UNINITIALIZED ||
1560 result == DEBUG_BREAK ||
1561 result == DEBUG_PREPARE_STEP_IN);
1562 return result;
1563}
1564
1565
1566PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001567 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568 return ExtractTypeFromFlags(flags());
1569}
1570
1571
1572int Code::arguments_count() {
1573 ASSERT(is_call_stub() || kind() == STUB);
1574 return ExtractArgumentsCountFromFlags(flags());
1575}
1576
1577
1578CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001579 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001580 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1581 kStubMajorKeyOffset));
1582}
1583
1584
1585void Code::set_major_key(CodeStub::Major major) {
1586 ASSERT(kind() == STUB);
1587 ASSERT(0 <= major && major < 256);
1588 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001589}
1590
1591
1592bool Code::is_inline_cache_stub() {
1593 Kind kind = this->kind();
1594 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1595}
1596
1597
1598Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001599 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001600 PropertyType type,
1601 int argc) {
1602 // Compute the bit mask.
1603 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001604 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001605 bits |= type << kFlagsTypeShift;
1606 bits |= argc << kFlagsArgumentsCountShift;
1607 // Cast to flags and validate result before returning it.
1608 Flags result = static_cast<Flags>(bits);
1609 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001610 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611 ASSERT(ExtractTypeFromFlags(result) == type);
1612 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1613 return result;
1614}
1615
1616
1617Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1618 PropertyType type,
1619 int argc) {
1620 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1621}
1622
1623
1624Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1625 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1626 return static_cast<Kind>(bits);
1627}
1628
1629
kasper.lund7276f142008-07-30 08:49:36 +00001630InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1631 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001632 return static_cast<InlineCacheState>(bits);
1633}
1634
1635
1636PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1637 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1638 return static_cast<PropertyType>(bits);
1639}
1640
1641
1642int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1643 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1644}
1645
1646
1647Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1648 int bits = flags & ~kFlagsTypeMask;
1649 return static_cast<Flags>(bits);
1650}
1651
1652
1653Object* Map::prototype() {
1654 return READ_FIELD(this, kPrototypeOffset);
1655}
1656
1657
1658void Map::set_prototype(Object* value) {
1659 ASSERT(value->IsNull() || value->IsJSObject());
1660 WRITE_FIELD(this, kPrototypeOffset, value);
1661 WRITE_BARRIER(this, kPrototypeOffset);
1662}
1663
1664
1665ACCESSORS(Map, instance_descriptors, DescriptorArray,
1666 kInstanceDescriptorsOffset)
1667ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1668ACCESSORS(Map, constructor, Object, kConstructorOffset)
1669
1670ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1671ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1672
1673ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1674ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
1675
1676ACCESSORS(JSGlobalObject, security_token, Object, kSecurityTokenOffset)
1677
1678ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1679ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1680ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1681ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1682ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1683
1684ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1685ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1686ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1687
1688ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1689ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1690ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1691ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1692ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1693ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1694
1695ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1696ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1697
1698ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1699ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1700
1701ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1702ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001703ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1704 kPropertyAccessorsOffset)
1705ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1706 kPrototypeTemplateOffset)
1707ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1708ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1709 kNamedPropertyHandlerOffset)
1710ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1711 kIndexedPropertyHandlerOffset)
1712ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1713 kInstanceTemplateOffset)
1714ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1715ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001716ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1717 kInstanceCallHandlerOffset)
1718ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1719 kAccessCheckInfoOffset)
1720ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1721
1722ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001723ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1724 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001725
1726ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1727ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1728
1729ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1730
1731ACCESSORS(Script, source, Object, kSourceOffset)
1732ACCESSORS(Script, name, Object, kNameOffset)
1733ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1734ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1735ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1736ACCESSORS(Script, type, Smi, kTypeOffset)
1737
1738ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1739ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1740ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1741ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1742
1743ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1744ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1745ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1746ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1747
1748ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1749ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1750 kInstanceClassNameOffset)
1751ACCESSORS(SharedFunctionInfo, function_data, Object,
1752 kExternalReferenceDataOffset)
1753ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1754ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1755ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1756
1757BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1758 kHiddenPrototypeBit)
1759BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1760BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1761 kNeedsAccessCheckBit)
1762BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1763 kIsExpressionBit)
1764BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1765 kIsTopLevelBit)
1766
1767INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1768INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1769 kFormalParameterCountOffset)
1770INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1771 kExpectedNofPropertiesOffset)
1772INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1773 kStartPositionAndTypeOffset)
1774INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1775INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1776 kFunctionTokenPositionOffset)
1777
1778
1779int SharedFunctionInfo::start_position() {
1780 return start_position_and_type() >> kStartPositionShift;
1781}
1782
1783
1784void SharedFunctionInfo::set_start_position(int start_position) {
1785 set_start_position_and_type((start_position << kStartPositionShift)
1786 | (start_position_and_type() & ~kStartPositionMask));
1787}
1788
1789
1790Code* SharedFunctionInfo::code() {
1791 return Code::cast(READ_FIELD(this, kCodeOffset));
1792}
1793
1794
1795void SharedFunctionInfo::set_code(Code* value) {
1796 WRITE_FIELD(this, kCodeOffset, value);
1797 WRITE_BARRIER(this, kCodeOffset);
1798}
1799
1800
1801bool SharedFunctionInfo::is_compiled() {
1802 // TODO(1242782): Create a code kind for uncompiled code.
1803 return code()->kind() != Code::STUB;
1804}
1805
1806
1807bool JSFunction::IsBoilerplate() {
1808 return map() == Heap::boilerplate_function_map();
1809}
1810
1811
1812bool JSFunction::IsLoaded() {
1813 return shared()->lazy_load_data() == Heap::undefined_value();
1814}
1815
1816
1817Code* JSFunction::code() {
1818 return shared()->code();
1819}
1820
1821
1822void JSFunction::set_code(Code* value) {
1823 shared()->set_code(value);
1824}
1825
1826
1827Context* JSFunction::context() {
1828 return Context::cast(READ_FIELD(this, kContextOffset));
1829}
1830
1831
1832Object* JSFunction::unchecked_context() {
1833 return READ_FIELD(this, kContextOffset);
1834}
1835
1836
1837void JSFunction::set_context(Object* value) {
1838 ASSERT(value == Heap::undefined_value() || value->IsContext());
1839 WRITE_FIELD(this, kContextOffset, value);
1840 WRITE_BARRIER(this, kContextOffset);
1841}
1842
1843ACCESSORS(JSFunction, prototype_or_initial_map, Object,
1844 kPrototypeOrInitialMapOffset)
1845
1846
1847Map* JSFunction::initial_map() {
1848 return Map::cast(prototype_or_initial_map());
1849}
1850
1851
1852void JSFunction::set_initial_map(Map* value) {
1853 set_prototype_or_initial_map(value);
1854}
1855
1856
1857bool JSFunction::has_initial_map() {
1858 return prototype_or_initial_map()->IsMap();
1859}
1860
1861
1862bool JSFunction::has_instance_prototype() {
1863 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
1864}
1865
1866
1867bool JSFunction::has_prototype() {
1868 return map()->has_non_instance_prototype() || has_instance_prototype();
1869}
1870
1871
1872Object* JSFunction::instance_prototype() {
1873 ASSERT(has_instance_prototype());
1874 if (has_initial_map()) return initial_map()->prototype();
1875 // When there is no initial map and the prototype is a JSObject, the
1876 // initial map field is used for the prototype field.
1877 return prototype_or_initial_map();
1878}
1879
1880
1881Object* JSFunction::prototype() {
1882 ASSERT(has_prototype());
1883 // If the function's prototype property has been set to a non-JSObject
1884 // value, that value is stored in the constructor field of the map.
1885 if (map()->has_non_instance_prototype()) return map()->constructor();
1886 return instance_prototype();
1887}
1888
1889
1890bool JSFunction::is_compiled() {
1891 return shared()->is_compiled();
1892}
1893
1894
1895Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
1896 ASSERT(0 <= id && id < kJSBuiltinsCount);
1897 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
1898}
1899
1900
1901void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
1902 Object* value) {
1903 ASSERT(0 <= id && id < kJSBuiltinsCount);
1904 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
1905 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
1906}
1907
1908
1909Address Proxy::proxy() {
1910 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
1911}
1912
1913
1914void Proxy::set_proxy(Address value) {
1915 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
1916}
1917
1918
1919void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
1920 visitor->VisitExternalReference(
1921 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
1922}
1923
1924
1925ACCESSORS(JSValue, value, Object, kValueOffset)
1926
1927
1928JSValue* JSValue::cast(Object* obj) {
1929 ASSERT(obj->IsJSValue());
1930 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
1931 return reinterpret_cast<JSValue*>(obj);
1932}
1933
1934
1935INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
1936INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
1937INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
1938
1939
1940Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00001941 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001942}
1943
1944
1945void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00001946 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001947}
1948
1949
1950byte* Code::instruction_start() {
1951 return FIELD_ADDR(this, kHeaderSize);
1952}
1953
1954
1955int Code::body_size() {
1956 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
1957}
1958
1959
1960byte* Code::relocation_start() {
1961 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
1962}
1963
1964
1965byte* Code::entry() {
1966 return instruction_start();
1967}
1968
1969
1970bool Code::contains(byte* pc) {
1971 return (instruction_start() <= pc) &&
1972 (pc < instruction_start() + instruction_size());
1973}
1974
1975
1976byte* Code::sinfo_start() {
1977 return FIELD_ADDR(this, CodeSize() - sinfo_size());
1978}
1979
1980
1981ACCESSORS(JSArray, length, Object, kLengthOffset)
1982
1983
1984bool JSObject::HasFastElements() {
1985 return !elements()->IsDictionary();
1986}
1987
1988
1989bool JSObject::HasNamedInterceptor() {
1990 return map()->has_named_interceptor();
1991}
1992
1993
1994bool JSObject::HasIndexedInterceptor() {
1995 return map()->has_indexed_interceptor();
1996}
1997
1998
1999Dictionary* JSObject::property_dictionary() {
2000 ASSERT(!HasFastProperties());
2001 return Dictionary::cast(properties());
2002}
2003
2004
2005Dictionary* JSObject::element_dictionary() {
2006 ASSERT(!HasFastElements());
2007 return Dictionary::cast(elements());
2008}
2009
2010
2011bool String::HasHashCode() {
2012 return (length_field() & kHashComputedMask) != 0;
2013}
2014
2015
2016uint32_t String::Hash() {
2017 // Fast case: has hash code already been computed?
2018 int hash = length_field();
2019 if (hash & kHashComputedMask) return hash;
2020 // Slow case: compute hash code and set it..
2021 return ComputeAndSetHash();
2022}
2023
2024
2025bool String::AsArrayIndex(uint32_t* index) {
2026 int hash = length_field();
2027 if ((hash & kHashComputedMask) && !(hash & kIsArrayIndexMask)) return false;
2028 return SlowAsArrayIndex(index);
2029}
2030
2031
2032Object* JSObject::GetPrototype() {
2033 return JSObject::cast(this)->map()->prototype();
2034}
2035
2036
2037PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2038 return GetPropertyAttributeWithReceiver(this, key);
2039}
2040
2041
2042bool JSObject::HasElement(uint32_t index) {
2043 return HasElementWithReceiver(this, index);
2044}
2045
2046
2047bool AccessorInfo::all_can_read() {
2048 return BooleanBit::get(flag(), kAllCanReadBit);
2049}
2050
2051
2052void AccessorInfo::set_all_can_read(bool value) {
2053 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2054}
2055
2056
2057bool AccessorInfo::all_can_write() {
2058 return BooleanBit::get(flag(), kAllCanWriteBit);
2059}
2060
2061
2062void AccessorInfo::set_all_can_write(bool value) {
2063 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2064}
2065
2066
2067PropertyAttributes AccessorInfo::property_attributes() {
2068 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2069}
2070
2071
2072void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2073 ASSERT(AttributesField::is_valid(attributes));
2074 int rest_value = flag()->value() & ~AttributesField::mask();
2075 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2076}
2077
2078void Dictionary::SetEntry(int entry,
2079 Object* key,
2080 Object* value,
2081 PropertyDetails details) {
2082 ASSERT(!key->IsString() || details.index() > 0);
2083 int index = EntryToIndex(entry);
2084 WriteBarrierMode mode = GetWriteBarrierMode();
2085 set(index, key, mode);
2086 set(index+1, value, mode);
2087 fast_set(this, index+2, details.AsSmi());
2088}
2089
2090
2091void Map::ClearCodeCache() {
2092 // No write barrier is needed since empty_fixed_array is not in new space.
2093 // Please note this function is used during marking:
2094 // - MarkCompactCollector::MarkUnmarkedObject
2095 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2096 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2097}
2098
2099
2100#undef CAST_ACCESSOR
2101#undef INT_ACCESSORS
2102#undef SMI_ACCESSORS
2103#undef ACCESSORS
2104#undef FIELD_ADDR
2105#undef READ_FIELD
2106#undef WRITE_FIELD
2107#undef WRITE_BARRIER
2108#undef READ_MEMADDR_FIELD
2109#undef WRITE_MEMADDR_FIELD
2110#undef READ_DOUBLE_FIELD
2111#undef WRITE_DOUBLE_FIELD
2112#undef READ_INT_FIELD
2113#undef WRITE_INT_FIELD
2114#undef READ_SHORT_FIELD
2115#undef WRITE_SHORT_FIELD
2116#undef READ_BYTE_FIELD
2117#undef WRITE_BYTE_FIELD
2118
2119
2120} } // namespace v8::internal
2121
2122#endif // V8_OBJECTS_INL_H_