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