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