blob: ed84ce4c6e0481002414f9ecffe8a98f8c6e8445 [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()
209 && HeapObject::cast(this)->map()->instance_type() >= JS_OBJECT_TYPE;
210}
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
249template <> static inline bool Is<JSFunction>(Object* obj) {
250 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
296template <> static inline bool Is<JSArray>(Object* obj) {
297 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
982void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
983 Object* tmp = array->get(first);
984 fast_set(array, first, array->get(second));
985 fast_set(array, second, tmp);
986}
987
988
989int DescriptorArray::Search(String* name) {
990 SLOW_ASSERT(IsSortedNoDuplicates());
991
992 // Check for empty descriptor array.
993 int nof = number_of_descriptors();
994 if (nof == 0) return kNotFound;
995
996 // Fast case: do linear search for small arrays.
997 const int kMaxElementsForLinearSearch = 8;
998 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
999 for (int number = 0; number < nof; number++) {
1000 if (name == GetKey(number)) return number;
1001 }
1002 return kNotFound;
1003 }
1004
1005 // Slow case: perform binary search.
1006 return BinarySearch(name, 0, nof - 1);
1007}
1008
1009
1010
1011String* DescriptorArray::GetKey(int descriptor_number) {
1012 ASSERT(descriptor_number < number_of_descriptors());
1013 return String::cast(get(ToKeyIndex(descriptor_number)));
1014}
1015
1016
1017Object* DescriptorArray::GetValue(int descriptor_number) {
1018 ASSERT(descriptor_number < number_of_descriptors());
1019 return GetContentArray()->get(ToValueIndex(descriptor_number));
1020}
1021
1022
1023Smi* DescriptorArray::GetDetails(int descriptor_number) {
1024 ASSERT(descriptor_number < number_of_descriptors());
1025 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1026}
1027
1028
1029void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1030 desc->Init(GetKey(descriptor_number),
1031 GetValue(descriptor_number),
1032 GetDetails(descriptor_number));
1033}
1034
1035
1036void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1037 // Range check.
1038 ASSERT(descriptor_number < number_of_descriptors());
1039
1040 // Make sure non of the elements in desc are in new space.
1041 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1042 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1043
1044 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1045 FixedArray* content_array = GetContentArray();
1046 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1047 fast_set(content_array, ToDetailsIndex(descriptor_number),
1048 desc->GetDetails().AsSmi());
1049}
1050
1051
1052void DescriptorArray::Swap(int first, int second) {
1053 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1054 FixedArray* content_array = GetContentArray();
1055 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1056 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1057}
1058
1059
1060bool Dictionary::requires_slow_elements() {
1061 Object* max_index_object = get(kPrefixStartIndex);
1062 if (!max_index_object->IsSmi()) return false;
1063 return 0 !=
1064 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1065}
1066
1067
1068uint32_t Dictionary::max_number_key() {
1069 ASSERT(!requires_slow_elements());
1070 Object* max_index_object = get(kPrefixStartIndex);
1071 if (!max_index_object->IsSmi()) return 0;
1072 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1073 return value >> kRequiresSlowElementsTagSize;
1074}
1075
1076
1077// ------------------------------------
1078// Cast operations
1079
1080
1081CAST_ACCESSOR(FixedArray)
1082CAST_ACCESSOR(DescriptorArray)
1083CAST_ACCESSOR(Dictionary)
1084CAST_ACCESSOR(SymbolTable)
1085CAST_ACCESSOR(String)
1086CAST_ACCESSOR(SeqString)
1087CAST_ACCESSOR(AsciiString)
1088CAST_ACCESSOR(TwoByteString)
1089CAST_ACCESSOR(ConsString)
1090CAST_ACCESSOR(SlicedString)
1091CAST_ACCESSOR(ExternalString)
1092CAST_ACCESSOR(ExternalAsciiString)
1093CAST_ACCESSOR(ExternalTwoByteString)
1094CAST_ACCESSOR(JSObject)
1095CAST_ACCESSOR(Smi)
1096CAST_ACCESSOR(Failure)
1097CAST_ACCESSOR(HeapObject)
1098CAST_ACCESSOR(HeapNumber)
1099CAST_ACCESSOR(Oddball)
1100CAST_ACCESSOR(SharedFunctionInfo)
1101CAST_ACCESSOR(Map)
1102CAST_ACCESSOR(JSFunction)
1103CAST_ACCESSOR(JSGlobalObject)
1104CAST_ACCESSOR(JSBuiltinsObject)
1105CAST_ACCESSOR(Code)
1106CAST_ACCESSOR(JSArray)
1107CAST_ACCESSOR(Proxy)
1108CAST_ACCESSOR(ByteArray)
1109CAST_ACCESSOR(Struct)
1110
1111
1112#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1113 STRUCT_LIST(MAKE_STRUCT_CAST)
1114#undef MAKE_STRUCT_CAST
1115
1116template <int prefix_size, int elem_size>
1117HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1118 Object* obj) {
1119 ASSERT(obj->IsHashTable());
1120 return reinterpret_cast<HashTable*>(obj);
1121}
1122
1123
1124INT_ACCESSORS(Array, length, kLengthOffset)
1125
1126
1127bool String::Equals(String* other) {
1128 if (other == this) return true;
1129 if (IsSymbol() && other->IsSymbol()) return false;
1130 return SlowEquals(other);
1131}
1132
1133
1134int String::length() {
1135 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1136
1137 switch (size_tag()) {
1138 case kShortStringTag:
1139 return len >> kShortLengthShift;
1140 case kMediumStringTag:
1141 return len >> kMediumLengthShift;
1142 case kLongStringTag:
1143 return len >> kLongLengthShift;
1144 default:
1145 break;
1146 }
1147 UNREACHABLE();
1148 return 0;
1149}
1150
1151
1152void String::set_length(int value) {
1153 switch (size_tag()) {
1154 case kShortStringTag:
1155 WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
1156 break;
1157 case kMediumStringTag:
1158 WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
1159 break;
1160 case kLongStringTag:
1161 WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
1162 break;
1163 default:
1164 UNREACHABLE();
1165 break;
1166 }
1167}
1168
1169
1170int String::length_field() {
1171 return READ_INT_FIELD(this, kLengthOffset);
1172}
1173
1174
1175void String::set_length_field(int value) {
1176 WRITE_INT_FIELD(this, kLengthOffset, value);
1177}
1178
1179
1180void String::TryFlatten() {
1181 Flatten();
1182}
1183
1184
1185uint16_t String::Get(int index) {
1186 ASSERT(index >= 0 && index < length());
1187 switch (representation_tag()) {
1188 case kSeqStringTag:
1189 return is_ascii()
1190 ? AsciiString::cast(this)->AsciiStringGet(index)
1191 : TwoByteString::cast(this)->TwoByteStringGet(index);
1192 case kConsStringTag:
1193 return ConsString::cast(this)->ConsStringGet(index);
1194 case kSlicedStringTag:
1195 return SlicedString::cast(this)->SlicedStringGet(index);
1196 case kExternalStringTag:
1197 return is_ascii()
1198 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
1199 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1200 default:
1201 break;
1202 }
1203
1204 UNREACHABLE();
1205 return 0;
1206}
1207
1208
1209void String::Set(int index, uint16_t value) {
1210 ASSERT(index >= 0 && index < length());
1211 ASSERT(IsSeqString());
1212
1213 return is_ascii()
1214 ? AsciiString::cast(this)->AsciiStringSet(index, value)
1215 : TwoByteString::cast(this)->TwoByteStringSet(index, value);
1216}
1217
1218
1219bool String::IsAscii() {
1220 return is_ascii();
1221}
1222
1223
1224bool String::StringIsConsString() {
1225 return representation_tag() == kConsStringTag;
1226}
1227
1228
1229bool String::StringIsSlicedString() {
1230 return representation_tag() == kSlicedStringTag;
1231}
1232
1233
1234uint32_t String::size_tag() {
1235 return map_size_tag(map());
1236}
1237
1238
1239uint32_t String::map_size_tag(Map* map) {
1240 return map->instance_type() & kStringSizeMask;
1241}
1242
1243
1244bool String::is_symbol() {
1245 return is_symbol_map(map());
1246}
1247
1248
1249bool String::is_symbol_map(Map* map) {
1250 return (map->instance_type() & kIsSymbolMask) != 0;
1251}
1252
1253
1254bool String::is_ascii() {
1255 return is_ascii_map(map());
1256}
1257
1258
1259bool String::is_ascii_map(Map* map) {
1260 return (map->instance_type() & kStringEncodingMask) != 0;
1261}
1262
1263
1264StringRepresentationTag String::representation_tag() {
1265 return map_representation_tag(map());
1266}
1267
1268
1269StringRepresentationTag String::map_representation_tag(Map* map) {
1270 uint32_t tag = map->instance_type() & kStringRepresentationMask;
1271 return static_cast<StringRepresentationTag>(tag);
1272}
1273
1274
1275bool String::IsFlat() {
1276 String* current = this;
1277 while (true) {
1278 switch (current->representation_tag()) {
1279 case kConsStringTag:
1280 return String::cast(ConsString::cast(current)->second())->length() == 0;
1281 case kSlicedStringTag:
1282 current = String::cast(SlicedString::cast(this)->buffer());
1283 break;
1284 default:
1285 return true;
1286 }
1287 }
1288}
1289
1290
1291uint16_t AsciiString::AsciiStringGet(int index) {
1292 ASSERT(index >= 0 && index < length());
1293 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1294}
1295
1296
1297void AsciiString::AsciiStringSet(int index, uint16_t value) {
1298 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1299 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1300 static_cast<byte>(value));
1301}
1302
1303
1304Address AsciiString::GetCharsAddress() {
1305 return FIELD_ADDR(this, kHeaderSize);
1306}
1307
1308
1309uint16_t TwoByteString::TwoByteStringGet(int index) {
1310 ASSERT(index >= 0 && index < length());
1311 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1312}
1313
1314
1315void TwoByteString::TwoByteStringSet(int index, uint16_t value) {
1316 ASSERT(index >= 0 && index < length());
1317 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1318}
1319
1320
1321int TwoByteString::TwoByteStringSize(Map* map) {
1322 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1323
1324 // Use the map (and not 'this') to compute the size tag, since
1325 // TwoByteStringSize is called during GC when maps are encoded.
1326 switch (map_size_tag(map)) {
1327 case kShortStringTag:
1328 length = length >> kShortLengthShift;
1329 break;
1330 case kMediumStringTag:
1331 length = length >> kMediumLengthShift;
1332 break;
1333 case kLongStringTag:
1334 length = length >> kLongLengthShift;
1335 break;
1336 default:
1337 break;
1338 }
1339 return SizeFor(length);
1340}
1341
1342
1343int AsciiString::AsciiStringSize(Map* map) {
1344 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1345
1346 // Use the map (and not 'this') to compute the size tag, since
1347 // AsciiStringSize is called during GC when maps are encoded.
1348 switch (map_size_tag(map)) {
1349 case kShortStringTag:
1350 length = length >> kShortLengthShift;
1351 break;
1352 case kMediumStringTag:
1353 length = length >> kMediumLengthShift;
1354 break;
1355 case kLongStringTag:
1356 length = length >> kLongLengthShift;
1357 break;
1358 default:
1359 break;
1360 }
1361
1362 return SizeFor(length);
1363}
1364
1365
1366Object* ConsString::first() {
1367 return READ_FIELD(this, kFirstOffset);
1368}
1369
1370
1371void ConsString::set_first(Object* value) {
1372 WRITE_FIELD(this, kFirstOffset, value);
1373 WRITE_BARRIER(this, kFirstOffset);
1374}
1375
1376
1377Object* ConsString::second() {
1378 return READ_FIELD(this, kSecondOffset);
1379}
1380
1381
1382void ConsString::set_second(Object* value) {
1383 WRITE_FIELD(this, kSecondOffset, value);
1384 WRITE_BARRIER(this, kSecondOffset);
1385}
1386
1387
1388Object* SlicedString::buffer() {
1389 return READ_FIELD(this, kBufferOffset);
1390}
1391
1392
1393void SlicedString::set_buffer(Object* buffer) {
1394 WRITE_FIELD(this, kBufferOffset, buffer);
1395 WRITE_BARRIER(this, kBufferOffset);
1396}
1397
1398
1399int SlicedString::start() {
1400 return READ_INT_FIELD(this, kStartOffset);
1401}
1402
1403
1404void SlicedString::set_start(int start) {
1405 WRITE_INT_FIELD(this, kStartOffset, start);
1406}
1407
1408
1409ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1410 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1411}
1412
1413
1414void ExternalAsciiString::set_resource(
1415 ExternalAsciiString::Resource* resource) {
1416 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1417}
1418
1419
1420ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1421 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1422}
1423
1424
1425void ExternalTwoByteString::set_resource(
1426 ExternalTwoByteString::Resource* resource) {
1427 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1428}
1429
1430
1431byte ByteArray::get(int index) {
1432 ASSERT(index >= 0 && index < this->length());
1433 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1434}
1435
1436
1437void ByteArray::set(int index, byte value) {
1438 ASSERT(index >= 0 && index < this->length());
1439 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1440}
1441
1442
1443int ByteArray::get_int(int index) {
1444 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1445 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1446}
1447
1448
1449ByteArray* ByteArray::FromDataStartAddress(Address address) {
1450 ASSERT_TAG_ALIGNED(address);
1451 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1452}
1453
1454
1455Address ByteArray::GetDataStartAddress() {
1456 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1457}
1458
1459
1460int Map::instance_size() {
1461 return READ_BYTE_FIELD(this, kInstanceSizeOffset);
1462}
1463
1464
1465int HeapObject::SizeFromMap(Map* map) {
1466 InstanceType instance_type = map->instance_type();
1467 // Only inline the two most frequent cases.
1468 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1469 if (instance_type == FIXED_ARRAY_TYPE) {
1470 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1471 }
1472 // Otherwise do the general size computation.
1473 return SlowSizeFromMap(map);
1474}
1475
1476
1477void Map::set_instance_size(int value) {
1478 ASSERT(0 <= value && value < 256);
1479 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1480}
1481
1482
1483InstanceType Map::instance_type() {
1484 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1485}
1486
1487
1488void Map::set_instance_type(InstanceType value) {
1489 ASSERT(0 <= value && value < 256);
1490 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1491}
1492
1493
1494int Map::unused_property_fields() {
1495 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1496}
1497
1498
1499void Map::set_unused_property_fields(int value) {
1500 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1501}
1502
1503
1504byte Map::bit_field() {
1505 return READ_BYTE_FIELD(this, kBitFieldOffset);
1506}
1507
1508
1509void Map::set_bit_field(byte value) {
1510 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1511}
1512
1513
1514void Map::set_non_instance_prototype(bool value) {
1515 if (value) {
1516 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1517 } else {
1518 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1519 }
1520}
1521
1522
1523bool Map::has_non_instance_prototype() {
1524 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1525}
1526
1527
1528Code::Flags Code::flags() {
1529 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1530}
1531
1532
1533void Code::set_flags(Code::Flags flags) {
1534 // Make sure that all call stubs have an arguments count.
1535 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1536 ExtractArgumentsCountFromFlags(flags) >= 0);
1537 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1538}
1539
1540
1541Code::Kind Code::kind() {
1542 return ExtractKindFromFlags(flags());
1543}
1544
1545
kasper.lund7276f142008-07-30 08:49:36 +00001546InlineCacheState Code::ic_state() {
1547 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001548 // Only allow uninitialized or debugger states for non-IC code
1549 // objects. This is used in the debugger to determine whether or not
1550 // a call to code object has been replaced with a debug break call.
1551 ASSERT(is_inline_cache_stub() ||
1552 result == UNINITIALIZED ||
1553 result == DEBUG_BREAK ||
1554 result == DEBUG_PREPARE_STEP_IN);
1555 return result;
1556}
1557
1558
1559PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001560 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001561 return ExtractTypeFromFlags(flags());
1562}
1563
1564
1565int Code::arguments_count() {
1566 ASSERT(is_call_stub() || kind() == STUB);
1567 return ExtractArgumentsCountFromFlags(flags());
1568}
1569
1570
1571CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001572 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001573 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1574 kStubMajorKeyOffset));
1575}
1576
1577
1578void Code::set_major_key(CodeStub::Major major) {
1579 ASSERT(kind() == STUB);
1580 ASSERT(0 <= major && major < 256);
1581 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001582}
1583
1584
1585bool Code::is_inline_cache_stub() {
1586 Kind kind = this->kind();
1587 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1588}
1589
1590
1591Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001592 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001593 PropertyType type,
1594 int argc) {
1595 // Compute the bit mask.
1596 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001597 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598 bits |= type << kFlagsTypeShift;
1599 bits |= argc << kFlagsArgumentsCountShift;
1600 // Cast to flags and validate result before returning it.
1601 Flags result = static_cast<Flags>(bits);
1602 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001603 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001604 ASSERT(ExtractTypeFromFlags(result) == type);
1605 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1606 return result;
1607}
1608
1609
1610Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1611 PropertyType type,
1612 int argc) {
1613 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1614}
1615
1616
1617Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1618 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1619 return static_cast<Kind>(bits);
1620}
1621
1622
kasper.lund7276f142008-07-30 08:49:36 +00001623InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1624 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001625 return static_cast<InlineCacheState>(bits);
1626}
1627
1628
1629PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1630 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1631 return static_cast<PropertyType>(bits);
1632}
1633
1634
1635int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1636 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1637}
1638
1639
1640Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1641 int bits = flags & ~kFlagsTypeMask;
1642 return static_cast<Flags>(bits);
1643}
1644
1645
1646Object* Map::prototype() {
1647 return READ_FIELD(this, kPrototypeOffset);
1648}
1649
1650
1651void Map::set_prototype(Object* value) {
1652 ASSERT(value->IsNull() || value->IsJSObject());
1653 WRITE_FIELD(this, kPrototypeOffset, value);
1654 WRITE_BARRIER(this, kPrototypeOffset);
1655}
1656
1657
1658ACCESSORS(Map, instance_descriptors, DescriptorArray,
1659 kInstanceDescriptorsOffset)
1660ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1661ACCESSORS(Map, constructor, Object, kConstructorOffset)
1662
1663ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1664ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1665
1666ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1667ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
1668
1669ACCESSORS(JSGlobalObject, security_token, Object, kSecurityTokenOffset)
1670
1671ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1672ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1673ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1674ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1675ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1676
1677ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1678ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1679ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1680
1681ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1682ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1683ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1684ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1685ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1686ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1687
1688ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1689ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1690
1691ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1692ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1693
1694ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1695ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001696ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1697 kPropertyAccessorsOffset)
1698ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1699 kPrototypeTemplateOffset)
1700ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1701ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1702 kNamedPropertyHandlerOffset)
1703ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1704 kIndexedPropertyHandlerOffset)
1705ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1706 kInstanceTemplateOffset)
1707ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1708ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
1709ACCESSORS(FunctionTemplateInfo, lookup_callback, Object, kLookupCallbackOffset)
1710ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1711 kInstanceCallHandlerOffset)
1712ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1713 kAccessCheckInfoOffset)
1714ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1715
1716ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001717ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1718 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001719
1720ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1721ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1722
1723ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1724
1725ACCESSORS(Script, source, Object, kSourceOffset)
1726ACCESSORS(Script, name, Object, kNameOffset)
1727ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1728ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1729ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1730ACCESSORS(Script, type, Smi, kTypeOffset)
1731
1732ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1733ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1734ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1735ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1736
1737ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1738ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1739ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1740ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1741
1742ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1743ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1744 kInstanceClassNameOffset)
1745ACCESSORS(SharedFunctionInfo, function_data, Object,
1746 kExternalReferenceDataOffset)
1747ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1748ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1749ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1750
1751BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1752 kHiddenPrototypeBit)
1753BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1754BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1755 kNeedsAccessCheckBit)
1756BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1757 kIsExpressionBit)
1758BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1759 kIsTopLevelBit)
1760
1761INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1762INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1763 kFormalParameterCountOffset)
1764INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1765 kExpectedNofPropertiesOffset)
1766INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1767 kStartPositionAndTypeOffset)
1768INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1769INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1770 kFunctionTokenPositionOffset)
1771
1772
1773int SharedFunctionInfo::start_position() {
1774 return start_position_and_type() >> kStartPositionShift;
1775}
1776
1777
1778void SharedFunctionInfo::set_start_position(int start_position) {
1779 set_start_position_and_type((start_position << kStartPositionShift)
1780 | (start_position_and_type() & ~kStartPositionMask));
1781}
1782
1783
1784Code* SharedFunctionInfo::code() {
1785 return Code::cast(READ_FIELD(this, kCodeOffset));
1786}
1787
1788
1789void SharedFunctionInfo::set_code(Code* value) {
1790 WRITE_FIELD(this, kCodeOffset, value);
1791 WRITE_BARRIER(this, kCodeOffset);
1792}
1793
1794
1795bool SharedFunctionInfo::is_compiled() {
1796 // TODO(1242782): Create a code kind for uncompiled code.
1797 return code()->kind() != Code::STUB;
1798}
1799
1800
1801bool JSFunction::IsBoilerplate() {
1802 return map() == Heap::boilerplate_function_map();
1803}
1804
1805
1806bool JSFunction::IsLoaded() {
1807 return shared()->lazy_load_data() == Heap::undefined_value();
1808}
1809
1810
1811Code* JSFunction::code() {
1812 return shared()->code();
1813}
1814
1815
1816void JSFunction::set_code(Code* value) {
1817 shared()->set_code(value);
1818}
1819
1820
1821Context* JSFunction::context() {
1822 return Context::cast(READ_FIELD(this, kContextOffset));
1823}
1824
1825
1826Object* JSFunction::unchecked_context() {
1827 return READ_FIELD(this, kContextOffset);
1828}
1829
1830
1831void JSFunction::set_context(Object* value) {
1832 ASSERT(value == Heap::undefined_value() || value->IsContext());
1833 WRITE_FIELD(this, kContextOffset, value);
1834 WRITE_BARRIER(this, kContextOffset);
1835}
1836
1837ACCESSORS(JSFunction, prototype_or_initial_map, Object,
1838 kPrototypeOrInitialMapOffset)
1839
1840
1841Map* JSFunction::initial_map() {
1842 return Map::cast(prototype_or_initial_map());
1843}
1844
1845
1846void JSFunction::set_initial_map(Map* value) {
1847 set_prototype_or_initial_map(value);
1848}
1849
1850
1851bool JSFunction::has_initial_map() {
1852 return prototype_or_initial_map()->IsMap();
1853}
1854
1855
1856bool JSFunction::has_instance_prototype() {
1857 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
1858}
1859
1860
1861bool JSFunction::has_prototype() {
1862 return map()->has_non_instance_prototype() || has_instance_prototype();
1863}
1864
1865
1866Object* JSFunction::instance_prototype() {
1867 ASSERT(has_instance_prototype());
1868 if (has_initial_map()) return initial_map()->prototype();
1869 // When there is no initial map and the prototype is a JSObject, the
1870 // initial map field is used for the prototype field.
1871 return prototype_or_initial_map();
1872}
1873
1874
1875Object* JSFunction::prototype() {
1876 ASSERT(has_prototype());
1877 // If the function's prototype property has been set to a non-JSObject
1878 // value, that value is stored in the constructor field of the map.
1879 if (map()->has_non_instance_prototype()) return map()->constructor();
1880 return instance_prototype();
1881}
1882
1883
1884bool JSFunction::is_compiled() {
1885 return shared()->is_compiled();
1886}
1887
1888
1889Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
1890 ASSERT(0 <= id && id < kJSBuiltinsCount);
1891 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
1892}
1893
1894
1895void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
1896 Object* value) {
1897 ASSERT(0 <= id && id < kJSBuiltinsCount);
1898 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
1899 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
1900}
1901
1902
1903Address Proxy::proxy() {
1904 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
1905}
1906
1907
1908void Proxy::set_proxy(Address value) {
1909 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
1910}
1911
1912
1913void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
1914 visitor->VisitExternalReference(
1915 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
1916}
1917
1918
1919ACCESSORS(JSValue, value, Object, kValueOffset)
1920
1921
1922JSValue* JSValue::cast(Object* obj) {
1923 ASSERT(obj->IsJSValue());
1924 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
1925 return reinterpret_cast<JSValue*>(obj);
1926}
1927
1928
1929INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
1930INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
1931INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
1932
1933
1934Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00001935 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001936}
1937
1938
1939void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00001940 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001941}
1942
1943
1944byte* Code::instruction_start() {
1945 return FIELD_ADDR(this, kHeaderSize);
1946}
1947
1948
1949int Code::body_size() {
1950 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
1951}
1952
1953
1954byte* Code::relocation_start() {
1955 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
1956}
1957
1958
1959byte* Code::entry() {
1960 return instruction_start();
1961}
1962
1963
1964bool Code::contains(byte* pc) {
1965 return (instruction_start() <= pc) &&
1966 (pc < instruction_start() + instruction_size());
1967}
1968
1969
1970byte* Code::sinfo_start() {
1971 return FIELD_ADDR(this, CodeSize() - sinfo_size());
1972}
1973
1974
1975ACCESSORS(JSArray, length, Object, kLengthOffset)
1976
1977
1978bool JSObject::HasFastElements() {
1979 return !elements()->IsDictionary();
1980}
1981
1982
1983bool JSObject::HasNamedInterceptor() {
1984 return map()->has_named_interceptor();
1985}
1986
1987
1988bool JSObject::HasIndexedInterceptor() {
1989 return map()->has_indexed_interceptor();
1990}
1991
1992
1993Dictionary* JSObject::property_dictionary() {
1994 ASSERT(!HasFastProperties());
1995 return Dictionary::cast(properties());
1996}
1997
1998
1999Dictionary* JSObject::element_dictionary() {
2000 ASSERT(!HasFastElements());
2001 return Dictionary::cast(elements());
2002}
2003
2004
2005bool String::HasHashCode() {
2006 return (length_field() & kHashComputedMask) != 0;
2007}
2008
2009
2010uint32_t String::Hash() {
2011 // Fast case: has hash code already been computed?
2012 int hash = length_field();
2013 if (hash & kHashComputedMask) return hash;
2014 // Slow case: compute hash code and set it..
2015 return ComputeAndSetHash();
2016}
2017
2018
2019bool String::AsArrayIndex(uint32_t* index) {
2020 int hash = length_field();
2021 if ((hash & kHashComputedMask) && !(hash & kIsArrayIndexMask)) return false;
2022 return SlowAsArrayIndex(index);
2023}
2024
2025
2026Object* JSObject::GetPrototype() {
2027 return JSObject::cast(this)->map()->prototype();
2028}
2029
2030
2031PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2032 return GetPropertyAttributeWithReceiver(this, key);
2033}
2034
2035
2036bool JSObject::HasElement(uint32_t index) {
2037 return HasElementWithReceiver(this, index);
2038}
2039
2040
2041bool AccessorInfo::all_can_read() {
2042 return BooleanBit::get(flag(), kAllCanReadBit);
2043}
2044
2045
2046void AccessorInfo::set_all_can_read(bool value) {
2047 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2048}
2049
2050
2051bool AccessorInfo::all_can_write() {
2052 return BooleanBit::get(flag(), kAllCanWriteBit);
2053}
2054
2055
2056void AccessorInfo::set_all_can_write(bool value) {
2057 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2058}
2059
2060
2061PropertyAttributes AccessorInfo::property_attributes() {
2062 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2063}
2064
2065
2066void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2067 ASSERT(AttributesField::is_valid(attributes));
2068 int rest_value = flag()->value() & ~AttributesField::mask();
2069 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2070}
2071
2072void Dictionary::SetEntry(int entry,
2073 Object* key,
2074 Object* value,
2075 PropertyDetails details) {
2076 ASSERT(!key->IsString() || details.index() > 0);
2077 int index = EntryToIndex(entry);
2078 WriteBarrierMode mode = GetWriteBarrierMode();
2079 set(index, key, mode);
2080 set(index+1, value, mode);
2081 fast_set(this, index+2, details.AsSmi());
2082}
2083
2084
2085void Map::ClearCodeCache() {
2086 // No write barrier is needed since empty_fixed_array is not in new space.
2087 // Please note this function is used during marking:
2088 // - MarkCompactCollector::MarkUnmarkedObject
2089 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2090 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2091}
2092
2093
2094#undef CAST_ACCESSOR
2095#undef INT_ACCESSORS
2096#undef SMI_ACCESSORS
2097#undef ACCESSORS
2098#undef FIELD_ADDR
2099#undef READ_FIELD
2100#undef WRITE_FIELD
2101#undef WRITE_BARRIER
2102#undef READ_MEMADDR_FIELD
2103#undef WRITE_MEMADDR_FIELD
2104#undef READ_DOUBLE_FIELD
2105#undef WRITE_DOUBLE_FIELD
2106#undef READ_INT_FIELD
2107#undef WRITE_INT_FIELD
2108#undef READ_SHORT_FIELD
2109#undef WRITE_SHORT_FIELD
2110#undef READ_BYTE_FIELD
2111#undef WRITE_BYTE_FIELD
2112
2113
2114} } // namespace v8::internal
2115
2116#endif // V8_OBJECTS_INL_H_