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