blob: ce2da12ad2d68e54a545c1656e18c474914636ee [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
ager@chromium.org7c537e22008-10-16 08:43:32 +0000122bool Object::IsSeqAsciiString() {
123 return IsSeqString()
124 && String::cast(this)->IsAsciiRepresentation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000125}
126
127
ager@chromium.org7c537e22008-10-16 08:43:32 +0000128bool Object::IsSeqTwoByteString() {
129 return IsSeqString()
130 && !String::cast(this)->IsAsciiRepresentation();
131}
132
133
134bool Object::IsAsciiStringRepresentation() {
135 return IsString() && (String::cast(this)->is_ascii_representation());
136}
137
138
139bool Object::IsTwoByteStringRepresentation() {
140 return IsString() && (!String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141}
142
143
144bool Object::IsConsString() {
145 return IsString()
146 && (String::cast(this)->representation_tag() == kConsStringTag);
147}
148
149
150bool Object::IsSlicedString() {
151 return IsString()
152 && (String::cast(this)->representation_tag() == kSlicedStringTag);
153}
154
155
156bool Object::IsExternalString() {
157 return IsString()
158 && (String::cast(this)->representation_tag() == kExternalStringTag);
159}
160
161
162bool Object::IsExternalAsciiString() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000163 return IsExternalString() && (String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164}
165
166
167bool Object::IsExternalTwoByteString() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000168 return IsExternalString() && (!String::cast(this)->is_ascii_representation());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169}
170
171
172bool Object::IsShortString() {
173 return IsString() && (String::cast(this)->size_tag() == kShortStringTag);
174}
175
176
177bool Object::IsMediumString() {
178 return IsString() && (String::cast(this)->size_tag() == kMediumStringTag);
179}
180
181
182bool Object::IsLongString() {
183 return IsString() && (String::cast(this)->size_tag() == kLongStringTag);
184}
185
186
187bool Object::IsSymbol() {
188 return IsString() && (String::cast(this)->is_symbol());
189}
190
191
192bool Object::IsNumber() {
193 return IsSmi() || IsHeapNumber();
194}
195
196
197bool Object::IsByteArray() {
198 return Object::IsHeapObject()
199 && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
200}
201
202
203bool Object::IsFailure() {
204 return HAS_FAILURE_TAG(this);
205}
206
207
208bool Object::IsRetryAfterGC() {
209 return HAS_FAILURE_TAG(this)
210 && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
211}
212
213
ager@chromium.org7c537e22008-10-16 08:43:32 +0000214bool Object::IsOutOfMemoryFailure() {
215 return HAS_FAILURE_TAG(this)
216 && Failure::cast(this)->IsOutOfMemoryException();
217}
218
219
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220bool Object::IsException() {
221 return this == Failure::Exception();
222}
223
224
225bool Object::IsJSObject() {
226 return IsHeapObject()
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000227 && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228}
229
230
231bool Object::IsMap() {
232 return Object::IsHeapObject()
233 && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
234}
235
236
237bool Object::IsFixedArray() {
238 return Object::IsHeapObject()
239 && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
240}
241
242
243bool Object::IsDescriptorArray() {
244 return IsFixedArray();
245}
246
247
248bool Object::IsContext() {
249 return Object::IsHeapObject()
250 && (HeapObject::cast(this)->map() == Heap::context_map() ||
251 HeapObject::cast(this)->map() == Heap::global_context_map());
252}
253
254
255bool Object::IsGlobalContext() {
256 return Object::IsHeapObject()
257 && HeapObject::cast(this)->map() == Heap::global_context_map();
258}
259
260
261bool Object::IsJSFunction() {
262 return Object::IsHeapObject()
263 && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
264}
265
266
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000267template <> inline bool Is<JSFunction>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000268 return obj->IsJSFunction();
269}
270
271
272bool Object::IsCode() {
273 return Object::IsHeapObject()
274 && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
275}
276
277
278bool Object::IsOddball() {
279 return Object::IsHeapObject()
280 && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
281}
282
283
284bool Object::IsSharedFunctionInfo() {
285 return Object::IsHeapObject() &&
286 (HeapObject::cast(this)->map()->instance_type() ==
287 SHARED_FUNCTION_INFO_TYPE);
288}
289
290
291bool Object::IsJSValue() {
292 return Object::IsHeapObject()
293 && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
294}
295
296
297bool Object::IsProxy() {
298 return Object::IsHeapObject()
299 && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
300}
301
302
303bool Object::IsBoolean() {
304 return IsTrue() || IsFalse();
305}
306
307
308bool Object::IsJSArray() {
309 return Object::IsHeapObject()
310 && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
311}
312
313
ager@chromium.org236ad962008-09-25 09:45:57 +0000314bool Object::IsJSRegExp() {
315 return Object::IsHeapObject()
316 && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
317}
318
319
ager@chromium.orgc27e4e72008-09-04 13:52:27 +0000320template <> inline bool Is<JSArray>(Object* obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321 return obj->IsJSArray();
322}
323
324
325bool Object::IsHashTable() {
326 return Object::IsHeapObject()
327 && HeapObject::cast(this)->map() == Heap::hash_table_map();
328}
329
330
331bool Object::IsDictionary() {
332 return IsHashTable() && this != Heap::symbol_table();
333}
334
335
336bool Object::IsSymbolTable() {
337 return IsHashTable() && this == Heap::symbol_table();
338}
339
340
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000341bool Object::IsCompilationCacheTable() {
342 return IsHashTable();
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000343}
344
345
ager@chromium.org236ad962008-09-25 09:45:57 +0000346bool Object::IsMapCache() {
347 return IsHashTable();
348}
349
350
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351bool Object::IsPrimitive() {
352 return IsOddball() || IsNumber() || IsString();
353}
354
355
356bool Object::IsGlobalObject() {
357 return IsHeapObject() &&
358 ((HeapObject::cast(this)->map()->instance_type() ==
359 JS_GLOBAL_OBJECT_TYPE) ||
360 (HeapObject::cast(this)->map()->instance_type() ==
361 JS_BUILTINS_OBJECT_TYPE));
362}
363
364
365bool Object::IsJSGlobalObject() {
366#ifdef DEBUG
367 if (IsHeapObject() &&
368 (HeapObject::cast(this)->map()->instance_type() ==
369 JS_GLOBAL_OBJECT_TYPE)) {
370 ASSERT(IsAccessCheckNeeded());
371 }
372#endif
373 return IsHeapObject() &&
374 (HeapObject::cast(this)->map()->instance_type() ==
375 JS_GLOBAL_OBJECT_TYPE);
376}
377
378
379bool Object::IsJSBuiltinsObject() {
380 return IsHeapObject() &&
381 (HeapObject::cast(this)->map()->instance_type() ==
382 JS_BUILTINS_OBJECT_TYPE);
383}
384
385
386bool Object::IsUndetectableObject() {
387 return IsHeapObject()
388 && HeapObject::cast(this)->map()->is_undetectable();
389}
390
391
392bool Object::IsAccessCheckNeeded() {
393 return IsHeapObject()
394 && HeapObject::cast(this)->map()->needs_access_check();
395}
396
397
398bool Object::IsStruct() {
399 if (!IsHeapObject()) return false;
400 switch (HeapObject::cast(this)->map()->instance_type()) {
401#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
402 STRUCT_LIST(MAKE_STRUCT_CASE)
403#undef MAKE_STRUCT_CASE
404 default: return false;
405 }
406}
407
408
409#define MAKE_STRUCT_PREDICATE(NAME, Name, name) \
410 bool Object::Is##Name() { \
411 return Object::IsHeapObject() \
412 && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
413 }
414 STRUCT_LIST(MAKE_STRUCT_PREDICATE)
415#undef MAKE_STRUCT_PREDICATE
416
417
418bool Object::IsUndefined() {
419 return this == Heap::undefined_value();
420}
421
422
423bool Object::IsTheHole() {
424 return this == Heap::the_hole_value();
425}
426
427
428bool Object::IsNull() {
429 return this == Heap::null_value();
430}
431
432
433bool Object::IsTrue() {
434 return this == Heap::true_value();
435}
436
437
438bool Object::IsFalse() {
439 return this == Heap::false_value();
440}
441
442
443double Object::Number() {
444 ASSERT(IsNumber());
445 return IsSmi()
446 ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
447 : reinterpret_cast<HeapNumber*>(this)->value();
448}
449
450
451
452Object* Object::ToSmi() {
453 if (IsSmi()) return this;
454 if (IsHeapNumber()) {
455 double value = HeapNumber::cast(this)->value();
456 int int_value = FastD2I(value);
457 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
458 return Smi::FromInt(int_value);
459 }
460 }
461 return Failure::Exception();
462}
463
464
465Object* Object::GetElement(uint32_t index) {
466 return GetElementWithReceiver(this, index);
467}
468
469
470Object* Object::GetProperty(String* key) {
471 PropertyAttributes attributes;
472 return GetPropertyWithReceiver(this, key, &attributes);
473}
474
475
476Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
477 return GetPropertyWithReceiver(this, key, attributes);
478}
479
480
481#define FIELD_ADDR(p, offset) \
482 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
483
484#define READ_FIELD(p, offset) \
485 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
486
487#define WRITE_FIELD(p, offset, value) \
488 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
489
490#define WRITE_BARRIER(object, offset) \
491 Heap::RecordWrite(object->address(), offset);
492
493#define READ_DOUBLE_FIELD(p, offset) \
494 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
495
496#define WRITE_DOUBLE_FIELD(p, offset, value) \
497 (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
498
499#define READ_INT_FIELD(p, offset) \
500 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
501
502#define WRITE_INT_FIELD(p, offset, value) \
503 (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
504
ager@chromium.org7c537e22008-10-16 08:43:32 +0000505#define READ_UINT32_FIELD(p, offset) \
506 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
507
508#define WRITE_UINT32_FIELD(p, offset, value) \
509 (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
510
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511#define READ_SHORT_FIELD(p, offset) \
512 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
513
514#define WRITE_SHORT_FIELD(p, offset, value) \
515 (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
516
517#define READ_BYTE_FIELD(p, offset) \
518 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
519
520#define WRITE_BYTE_FIELD(p, offset, value) \
521 (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
522
523
524Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000525 return READ_FIELD(obj, HeapObject::kHeaderSize + kPointerSize * index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000526}
527
528
529int Smi::value() {
530 return reinterpret_cast<int>(this) >> kSmiTagSize;
531}
532
533
534Smi* Smi::FromInt(int value) {
535 ASSERT(Smi::IsValid(value));
536 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
537}
538
539
540Failure::Type Failure::type() const {
541 return static_cast<Type>(value() & kFailureTypeTagMask);
542}
543
544
545bool Failure::IsInternalError() const {
546 return type() == INTERNAL_ERROR;
547}
548
549
550bool Failure::IsOutOfMemoryException() const {
551 return type() == OUT_OF_MEMORY_EXCEPTION;
552}
553
554
555int Failure::requested() const {
556 const int kShiftBits =
557 kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
558 STATIC_ASSERT(kShiftBits >= 0);
559 ASSERT(type() == RETRY_AFTER_GC);
560 return value() >> kShiftBits;
561}
562
563
564AllocationSpace Failure::allocation_space() const {
565 ASSERT_EQ(RETRY_AFTER_GC, type());
566 return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
567 & kSpaceTagMask);
568}
569
570
571Failure* Failure::InternalError() {
572 return Construct(INTERNAL_ERROR);
573}
574
575
576Failure* Failure::Exception() {
577 return Construct(EXCEPTION);
578}
579
580Failure* Failure::OutOfMemoryException() {
581 return Construct(OUT_OF_MEMORY_EXCEPTION);
582}
583
584
585int Failure::value() const {
586 return reinterpret_cast<int>(this) >> kFailureTagSize;
587}
588
589
590Failure* Failure::Construct(Type type, int value) {
591 int info = (value << kFailureTypeTagSize) | type;
592 ASSERT(Smi::IsValid(info)); // Same validation check as in Smi
593 return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
594}
595
596
597bool Smi::IsValid(int value) {
598#ifdef DEBUG
599 bool in_range = (value >= kMinValue) && (value <= kMaxValue);
600#endif
601 // To be representable as an tagged small integer, the two
602 // most-significant bits of 'value' must be either 00 or 11 due to
603 // sign-extension. To check this we add 01 to the two
604 // most-significant bits, and check if the most-significant bit is 0
605 //
606 // CAUTION: The original code below:
607 // bool result = ((value + 0x40000000) & 0x80000000) == 0;
608 // may lead to incorrect results according to the C language spec, and
609 // in fact doesn't work correctly with gcc4.1.1 in some cases: The
610 // compiler may produce undefined results in case of signed integer
611 // overflow. The computation must be done w/ unsigned ints.
612 bool result =
613 ((static_cast<unsigned int>(value) + 0x40000000U) & 0x80000000U) == 0;
614 ASSERT(result == in_range);
615 return result;
616}
617
618
kasper.lund7276f142008-07-30 08:49:36 +0000619MapWord MapWord::FromMap(Map* map) {
620 return MapWord(reinterpret_cast<uintptr_t>(map));
621}
622
623
624Map* MapWord::ToMap() {
625 return reinterpret_cast<Map*>(value_);
626}
627
628
629bool MapWord::IsForwardingAddress() {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000630 return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000631}
632
633
634MapWord MapWord::FromForwardingAddress(HeapObject* object) {
ager@chromium.org7c537e22008-10-16 08:43:32 +0000635 Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
636 return MapWord(reinterpret_cast<uintptr_t>(raw));
kasper.lund7276f142008-07-30 08:49:36 +0000637}
638
639
640HeapObject* MapWord::ToForwardingAddress() {
641 ASSERT(IsForwardingAddress());
ager@chromium.org7c537e22008-10-16 08:43:32 +0000642 return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
kasper.lund7276f142008-07-30 08:49:36 +0000643}
644
645
646bool MapWord::IsMarked() {
647 return (value_ & kMarkingMask) == 0;
648}
649
650
651void MapWord::SetMark() {
652 value_ &= ~kMarkingMask;
653}
654
655
656void MapWord::ClearMark() {
657 value_ |= kMarkingMask;
658}
659
660
661bool MapWord::IsOverflowed() {
662 return (value_ & kOverflowMask) != 0;
663}
664
665
666void MapWord::SetOverflow() {
667 value_ |= kOverflowMask;
668}
669
670
671void MapWord::ClearOverflow() {
672 value_ &= ~kOverflowMask;
673}
674
675
676MapWord MapWord::EncodeAddress(Address map_address, int offset) {
677 // Offset is the distance in live bytes from the first live object in the
678 // same page. The offset between two objects in the same page should not
679 // exceed the object area size of a page.
680 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
681
682 int compact_offset = offset >> kObjectAlignmentBits;
683 ASSERT(compact_offset < (1 << kForwardingOffsetBits));
684
685 Page* map_page = Page::FromAddress(map_address);
686 ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
687
688 int map_page_offset =
689 map_page->Offset(map_address) >> kObjectAlignmentBits;
690
691 uintptr_t encoding =
692 (compact_offset << kForwardingOffsetShift) |
693 (map_page_offset << kMapPageOffsetShift) |
694 (map_page->mc_page_index << kMapPageIndexShift);
695 return MapWord(encoding);
696}
697
698
699Address MapWord::DecodeMapAddress(MapSpace* map_space) {
700 int map_page_index = (value_ & kMapPageIndexMask) >> kMapPageIndexShift;
701 ASSERT_MAP_PAGE_INDEX(map_page_index);
702
703 int map_page_offset =
704 ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift)
705 << kObjectAlignmentBits;
706
707 return (map_space->PageAddress(map_page_index) + map_page_offset);
708}
709
710
711int MapWord::DecodeOffset() {
712 // The offset field is represented in the kForwardingOffsetBits
713 // most-significant bits.
714 int offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
715 ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
716 return offset;
717}
718
719
720MapWord MapWord::FromEncodedAddress(Address address) {
721 return MapWord(reinterpret_cast<uintptr_t>(address));
722}
723
724
725Address MapWord::ToEncodedAddress() {
726 return reinterpret_cast<Address>(value_);
727}
728
729
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000730#ifdef DEBUG
731void HeapObject::VerifyObjectField(int offset) {
732 VerifyPointer(READ_FIELD(this, offset));
733}
734#endif
735
736
737Map* HeapObject::map() {
kasper.lund7276f142008-07-30 08:49:36 +0000738 return map_word().ToMap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739}
740
741
742void HeapObject::set_map(Map* value) {
kasper.lund7276f142008-07-30 08:49:36 +0000743 set_map_word(MapWord::FromMap(value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000744}
745
746
kasper.lund7276f142008-07-30 08:49:36 +0000747MapWord HeapObject::map_word() {
748 return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
749}
750
751
752void HeapObject::set_map_word(MapWord map_word) {
753 // WRITE_FIELD does not update the remembered set, but there is no need
754 // here.
755 WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
756}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757
758
759HeapObject* HeapObject::FromAddress(Address address) {
760 ASSERT_TAG_ALIGNED(address);
761 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
762}
763
764
765Address HeapObject::address() {
766 return reinterpret_cast<Address>(this) - kHeapObjectTag;
767}
768
769
770int HeapObject::Size() {
771 return SizeFromMap(map());
772}
773
774
775void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
776 v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
777 reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
778}
779
780
781void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
782 v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
783}
784
785
786void HeapObject::CopyBody(JSObject* from) {
787 ASSERT(map() == from->map());
788 ASSERT(Size() == from->Size());
789 int object_size = Size();
ager@chromium.org236ad962008-09-25 09:45:57 +0000790 for (int offset = kHeaderSize;
791 offset < object_size;
792 offset += kPointerSize) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793 Object* value = READ_FIELD(from, offset);
794 // Note: WRITE_FIELD does not update the write barrier.
795 WRITE_FIELD(this, offset, value);
796 WRITE_BARRIER(this, offset);
797 }
798}
799
800
kasper.lund7276f142008-07-30 08:49:36 +0000801bool HeapObject::IsMarked() {
802 return map_word().IsMarked();
803}
804
805
806void HeapObject::SetMark() {
807 ASSERT(!IsMarked());
808 MapWord first_word = map_word();
809 first_word.SetMark();
810 set_map_word(first_word);
811}
812
813
814void HeapObject::ClearMark() {
815 ASSERT(IsMarked());
816 MapWord first_word = map_word();
817 first_word.ClearMark();
818 set_map_word(first_word);
819}
820
821
822bool HeapObject::IsOverflowed() {
823 return map_word().IsOverflowed();
824}
825
826
827void HeapObject::SetOverflow() {
828 MapWord first_word = map_word();
829 first_word.SetOverflow();
830 set_map_word(first_word);
831}
832
833
834void HeapObject::ClearOverflow() {
835 ASSERT(IsOverflowed());
836 MapWord first_word = map_word();
837 first_word.ClearOverflow();
838 set_map_word(first_word);
839}
840
841
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000842double HeapNumber::value() {
843 return READ_DOUBLE_FIELD(this, kValueOffset);
844}
845
846
847void HeapNumber::set_value(double value) {
848 WRITE_DOUBLE_FIELD(this, kValueOffset, value);
849}
850
851
852ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
853ACCESSORS(JSObject, elements, HeapObject, kElementsOffset)
854
855
856void JSObject::initialize_properties() {
857 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
858 WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
859}
860
861
862void JSObject::initialize_elements() {
863 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
864 WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
865}
866
867
868ACCESSORS(Oddball, to_string, String, kToStringOffset)
869ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
870
871
872int JSObject::GetHeaderSize() {
873 switch (map()->instance_type()) {
874 case JS_GLOBAL_OBJECT_TYPE:
875 return JSGlobalObject::kSize;
876 case JS_BUILTINS_OBJECT_TYPE:
877 return JSBuiltinsObject::kSize;
878 case JS_FUNCTION_TYPE:
879 return JSFunction::kSize;
880 case JS_VALUE_TYPE:
881 return JSValue::kSize;
882 case JS_ARRAY_TYPE:
883 return JSValue::kSize;
ager@chromium.org236ad962008-09-25 09:45:57 +0000884 case JS_REGEXP_TYPE:
885 return JSValue::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000886 case JS_OBJECT_TYPE:
887 return JSObject::kHeaderSize;
888 default:
889 UNREACHABLE();
890 return 0;
891 }
892}
893
894
895int JSObject::GetInternalFieldCount() {
896 ASSERT(1 << kPointerSizeLog2 == kPointerSize);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000897 // Make sure to adjust for the number of in-object properties. These
898 // properties do contribute to the size, but are not internal fields.
899 return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
900 map()->inobject_properties();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000901}
902
903
904Object* JSObject::GetInternalField(int index) {
905 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000906 // Internal objects do follow immediately after the header, whereas in-object
907 // properties are at the end of the object. Therefore there is no need
908 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000909 return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
910}
911
912
913void JSObject::SetInternalField(int index, Object* value) {
914 ASSERT(index < GetInternalFieldCount() && index >= 0);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000915 // Internal objects do follow immediately after the header, whereas in-object
916 // properties are at the end of the object. Therefore there is no need
917 // to adjust the index here.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000918 int offset = GetHeaderSize() + (kPointerSize * index);
919 WRITE_FIELD(this, offset, value);
920 WRITE_BARRIER(this, offset);
921}
922
923
ager@chromium.org7c537e22008-10-16 08:43:32 +0000924// Access fast-case object properties at index. The use of these routines
925// is needed to correctly distinguish between properties stored in-object and
926// properties stored in the properties array.
927inline Object* JSObject::FastPropertyAt(int index) {
928 // Adjust for the number of properties stored in the object.
929 index -= map()->inobject_properties();
930 if (index < 0) {
931 int offset = map()->instance_size() + (index * kPointerSize);
932 return READ_FIELD(this, offset);
933 } else {
934 ASSERT(index < properties()->length());
935 return properties()->get(index);
936 }
937}
938
939
940inline Object* JSObject::FastPropertyAtPut(int index, Object* value) {
941 // Adjust for the number of properties stored in the object.
942 index -= map()->inobject_properties();
943 if (index < 0) {
944 int offset = map()->instance_size() + (index * kPointerSize);
945 WRITE_FIELD(this, offset, value);
946 WRITE_BARRIER(this, offset);
947 } else {
948 ASSERT(index < properties()->length());
949 properties()->set(index, value);
950 }
951 return value;
952}
953
954
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000955void JSObject::InitializeBody(int object_size) {
956 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
957 WRITE_FIELD(this, offset, Heap::undefined_value());
958 }
959}
960
961
962void Struct::InitializeBody(int object_size) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000963 for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000964 WRITE_FIELD(this, offset, Heap::undefined_value());
965 }
966}
967
968
969bool JSObject::HasFastProperties() {
970 return !properties()->IsDictionary();
971}
972
973
974bool Array::IndexFromObject(Object* object, uint32_t* index) {
975 if (object->IsSmi()) {
976 int value = Smi::cast(object)->value();
977 if (value < 0) return false;
978 *index = value;
979 return true;
980 }
981 if (object->IsHeapNumber()) {
982 double value = HeapNumber::cast(object)->value();
983 uint32_t uint_value = static_cast<uint32_t>(value);
984 if (value == static_cast<double>(uint_value)) {
985 *index = uint_value;
986 return true;
987 }
988 }
989 return false;
990}
991
992
993bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
994 if (!this->IsJSValue()) return false;
995
996 JSValue* js_value = JSValue::cast(this);
997 if (!js_value->value()->IsString()) return false;
998
999 String* str = String::cast(js_value->value());
1000 if (index >= (uint32_t)str->length()) return false;
1001
1002 return true;
1003}
1004
1005
1006Object* FixedArray::get(int index) {
1007 ASSERT(index >= 0 && index < this->length());
1008 return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1009}
1010
1011
1012void FixedArray::set(int index, Object* value) {
1013 ASSERT(index >= 0 && index < this->length());
1014 int offset = kHeaderSize + index * kPointerSize;
1015 WRITE_FIELD(this, offset, value);
1016 WRITE_BARRIER(this, offset);
1017}
1018
1019
1020FixedArray::WriteBarrierMode FixedArray::GetWriteBarrierMode() {
1021 if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1022 return UPDATE_WRITE_BARRIER;
1023}
1024
1025
1026void FixedArray::set(int index,
1027 Object* value,
1028 FixedArray::WriteBarrierMode mode) {
1029 ASSERT(index >= 0 && index < this->length());
1030 int offset = kHeaderSize + index * kPointerSize;
1031 WRITE_FIELD(this, offset, value);
1032 if (mode == UPDATE_WRITE_BARRIER) {
1033 WRITE_BARRIER(this, offset);
1034 } else {
1035 ASSERT(mode == SKIP_WRITE_BARRIER);
1036 ASSERT(Heap::InNewSpace(this) || !Heap::InNewSpace(value));
1037 }
1038}
1039
1040
1041void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1042 ASSERT(index >= 0 && index < array->length());
1043 WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1044}
1045
1046
1047void FixedArray::set_undefined(int index) {
1048 ASSERT(index >= 0 && index < this->length());
1049 ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1050 WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1051 Heap::undefined_value());
1052}
1053
1054
ager@chromium.org236ad962008-09-25 09:45:57 +00001055void FixedArray::set_null(int index) {
1056 ASSERT(index >= 0 && index < this->length());
1057 ASSERT(!Heap::InNewSpace(Heap::null_value()));
1058 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1059}
1060
1061
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001062void FixedArray::set_the_hole(int index) {
1063 ASSERT(index >= 0 && index < this->length());
1064 ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1065 WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1066}
1067
1068
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001069bool DescriptorArray::IsEmpty() {
1070 ASSERT(this == Heap::empty_descriptor_array() ||
1071 this->length() > 2);
1072 return this == Heap::empty_descriptor_array();
1073}
1074
1075
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001076void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1077 Object* tmp = array->get(first);
1078 fast_set(array, first, array->get(second));
1079 fast_set(array, second, tmp);
1080}
1081
1082
1083int DescriptorArray::Search(String* name) {
1084 SLOW_ASSERT(IsSortedNoDuplicates());
1085
1086 // Check for empty descriptor array.
1087 int nof = number_of_descriptors();
1088 if (nof == 0) return kNotFound;
1089
1090 // Fast case: do linear search for small arrays.
1091 const int kMaxElementsForLinearSearch = 8;
1092 if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
1093 for (int number = 0; number < nof; number++) {
1094 if (name == GetKey(number)) return number;
1095 }
1096 return kNotFound;
1097 }
1098
1099 // Slow case: perform binary search.
1100 return BinarySearch(name, 0, nof - 1);
1101}
1102
1103
1104
1105String* DescriptorArray::GetKey(int descriptor_number) {
1106 ASSERT(descriptor_number < number_of_descriptors());
1107 return String::cast(get(ToKeyIndex(descriptor_number)));
1108}
1109
1110
1111Object* DescriptorArray::GetValue(int descriptor_number) {
1112 ASSERT(descriptor_number < number_of_descriptors());
1113 return GetContentArray()->get(ToValueIndex(descriptor_number));
1114}
1115
1116
1117Smi* DescriptorArray::GetDetails(int descriptor_number) {
1118 ASSERT(descriptor_number < number_of_descriptors());
1119 return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1120}
1121
1122
1123void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1124 desc->Init(GetKey(descriptor_number),
1125 GetValue(descriptor_number),
1126 GetDetails(descriptor_number));
1127}
1128
1129
1130void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1131 // Range check.
1132 ASSERT(descriptor_number < number_of_descriptors());
1133
1134 // Make sure non of the elements in desc are in new space.
1135 ASSERT(!Heap::InNewSpace(desc->GetKey()));
1136 ASSERT(!Heap::InNewSpace(desc->GetValue()));
1137
1138 fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1139 FixedArray* content_array = GetContentArray();
1140 fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1141 fast_set(content_array, ToDetailsIndex(descriptor_number),
1142 desc->GetDetails().AsSmi());
1143}
1144
1145
1146void DescriptorArray::Swap(int first, int second) {
1147 fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1148 FixedArray* content_array = GetContentArray();
1149 fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1150 fast_swap(content_array, ToDetailsIndex(first), ToDetailsIndex(second));
1151}
1152
1153
1154bool Dictionary::requires_slow_elements() {
1155 Object* max_index_object = get(kPrefixStartIndex);
1156 if (!max_index_object->IsSmi()) return false;
1157 return 0 !=
1158 (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1159}
1160
1161
1162uint32_t Dictionary::max_number_key() {
1163 ASSERT(!requires_slow_elements());
1164 Object* max_index_object = get(kPrefixStartIndex);
1165 if (!max_index_object->IsSmi()) return 0;
1166 uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1167 return value >> kRequiresSlowElementsTagSize;
1168}
1169
1170
1171// ------------------------------------
1172// Cast operations
1173
1174
1175CAST_ACCESSOR(FixedArray)
1176CAST_ACCESSOR(DescriptorArray)
1177CAST_ACCESSOR(Dictionary)
1178CAST_ACCESSOR(SymbolTable)
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001179CAST_ACCESSOR(CompilationCacheTable)
ager@chromium.org236ad962008-09-25 09:45:57 +00001180CAST_ACCESSOR(MapCache)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001181CAST_ACCESSOR(String)
1182CAST_ACCESSOR(SeqString)
ager@chromium.org7c537e22008-10-16 08:43:32 +00001183CAST_ACCESSOR(SeqAsciiString)
1184CAST_ACCESSOR(SeqTwoByteString)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001185CAST_ACCESSOR(ConsString)
1186CAST_ACCESSOR(SlicedString)
1187CAST_ACCESSOR(ExternalString)
1188CAST_ACCESSOR(ExternalAsciiString)
1189CAST_ACCESSOR(ExternalTwoByteString)
1190CAST_ACCESSOR(JSObject)
1191CAST_ACCESSOR(Smi)
1192CAST_ACCESSOR(Failure)
1193CAST_ACCESSOR(HeapObject)
1194CAST_ACCESSOR(HeapNumber)
1195CAST_ACCESSOR(Oddball)
1196CAST_ACCESSOR(SharedFunctionInfo)
1197CAST_ACCESSOR(Map)
1198CAST_ACCESSOR(JSFunction)
1199CAST_ACCESSOR(JSGlobalObject)
1200CAST_ACCESSOR(JSBuiltinsObject)
1201CAST_ACCESSOR(Code)
1202CAST_ACCESSOR(JSArray)
ager@chromium.org236ad962008-09-25 09:45:57 +00001203CAST_ACCESSOR(JSRegExp)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001204CAST_ACCESSOR(Proxy)
1205CAST_ACCESSOR(ByteArray)
1206CAST_ACCESSOR(Struct)
1207
1208
1209#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1210 STRUCT_LIST(MAKE_STRUCT_CAST)
1211#undef MAKE_STRUCT_CAST
1212
1213template <int prefix_size, int elem_size>
1214HashTable<prefix_size, elem_size>* HashTable<prefix_size, elem_size>::cast(
1215 Object* obj) {
1216 ASSERT(obj->IsHashTable());
1217 return reinterpret_cast<HashTable*>(obj);
1218}
1219
1220
1221INT_ACCESSORS(Array, length, kLengthOffset)
1222
1223
1224bool String::Equals(String* other) {
1225 if (other == this) return true;
1226 if (IsSymbol() && other->IsSymbol()) return false;
1227 return SlowEquals(other);
1228}
1229
1230
1231int String::length() {
1232 uint32_t len = READ_INT_FIELD(this, kLengthOffset);
1233
1234 switch (size_tag()) {
1235 case kShortStringTag:
1236 return len >> kShortLengthShift;
1237 case kMediumStringTag:
1238 return len >> kMediumLengthShift;
1239 case kLongStringTag:
1240 return len >> kLongLengthShift;
1241 default:
1242 break;
1243 }
1244 UNREACHABLE();
1245 return 0;
1246}
1247
1248
1249void String::set_length(int value) {
1250 switch (size_tag()) {
1251 case kShortStringTag:
1252 WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
1253 break;
1254 case kMediumStringTag:
1255 WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
1256 break;
1257 case kLongStringTag:
1258 WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
1259 break;
1260 default:
1261 UNREACHABLE();
1262 break;
1263 }
1264}
1265
1266
ager@chromium.org7c537e22008-10-16 08:43:32 +00001267uint32_t String::length_field() {
1268 return READ_UINT32_FIELD(this, kLengthOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001269}
1270
1271
ager@chromium.org7c537e22008-10-16 08:43:32 +00001272void String::set_length_field(uint32_t value) {
1273 WRITE_UINT32_FIELD(this, kLengthOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001274}
1275
1276
1277void String::TryFlatten() {
ager@chromium.org236ad962008-09-25 09:45:57 +00001278 // We don't need to flatten strings that are already flat. Since this code
1279 // is inlined, it can be helpful in the flat case to not call out to Flatten.
1280 StringRepresentationTag str_type = representation_tag();
1281 if (str_type != kSeqStringTag && str_type != kExternalStringTag) {
1282 Flatten();
1283 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284}
1285
1286
1287uint16_t String::Get(int index) {
1288 ASSERT(index >= 0 && index < length());
1289 switch (representation_tag()) {
1290 case kSeqStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001291 return is_ascii_representation()
1292 ? SeqAsciiString::cast(this)->SeqAsciiStringGet(index)
1293 : SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294 case kConsStringTag:
1295 return ConsString::cast(this)->ConsStringGet(index);
1296 case kSlicedStringTag:
1297 return SlicedString::cast(this)->SlicedStringGet(index);
1298 case kExternalStringTag:
ager@chromium.org7c537e22008-10-16 08:43:32 +00001299 return is_ascii_representation()
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 ? ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index)
1301 : ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1302 default:
1303 break;
1304 }
1305
1306 UNREACHABLE();
1307 return 0;
1308}
1309
1310
1311void String::Set(int index, uint16_t value) {
1312 ASSERT(index >= 0 && index < length());
1313 ASSERT(IsSeqString());
1314
ager@chromium.org7c537e22008-10-16 08:43:32 +00001315 return is_ascii_representation()
1316 ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1317 : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001318}
1319
1320
ager@chromium.org7c537e22008-10-16 08:43:32 +00001321bool String::IsAsciiRepresentation() {
1322 return is_ascii_representation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001323}
1324
1325
1326bool String::StringIsConsString() {
1327 return representation_tag() == kConsStringTag;
1328}
1329
1330
1331bool String::StringIsSlicedString() {
1332 return representation_tag() == kSlicedStringTag;
1333}
1334
1335
1336uint32_t String::size_tag() {
1337 return map_size_tag(map());
1338}
1339
1340
1341uint32_t String::map_size_tag(Map* map) {
1342 return map->instance_type() & kStringSizeMask;
1343}
1344
1345
1346bool String::is_symbol() {
1347 return is_symbol_map(map());
1348}
1349
1350
1351bool String::is_symbol_map(Map* map) {
1352 return (map->instance_type() & kIsSymbolMask) != 0;
1353}
1354
1355
ager@chromium.org7c537e22008-10-16 08:43:32 +00001356bool String::is_ascii_representation() {
1357 return is_ascii_representation_map(map());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001358}
1359
1360
ager@chromium.org7c537e22008-10-16 08:43:32 +00001361bool String::is_ascii_representation_map(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001362 return (map->instance_type() & kStringEncodingMask) != 0;
1363}
1364
1365
1366StringRepresentationTag String::representation_tag() {
1367 return map_representation_tag(map());
1368}
1369
1370
1371StringRepresentationTag String::map_representation_tag(Map* map) {
1372 uint32_t tag = map->instance_type() & kStringRepresentationMask;
1373 return static_cast<StringRepresentationTag>(tag);
1374}
1375
1376
1377bool String::IsFlat() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001378 switch (this->representation_tag()) {
1379 case kConsStringTag:
1380 // Only flattened strings have second part empty.
1381 return String::cast(ConsString::cast(this)->second())->length() == 0;
1382 case kSlicedStringTag: {
1383 String* slice = String::cast(SlicedString::cast(this)->buffer());
1384 StringRepresentationTag tag = slice->representation_tag();
1385 return tag == kSeqStringTag || tag == kExternalStringTag;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001386 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001387 default:
1388 return true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389 }
1390}
1391
1392
ager@chromium.org7c537e22008-10-16 08:43:32 +00001393uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001394 ASSERT(index >= 0 && index < length());
1395 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1396}
1397
1398
ager@chromium.org7c537e22008-10-16 08:43:32 +00001399void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001400 ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1401 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1402 static_cast<byte>(value));
1403}
1404
1405
ager@chromium.org7c537e22008-10-16 08:43:32 +00001406Address SeqAsciiString::GetCharsAddress() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001407 return FIELD_ADDR(this, kHeaderSize);
1408}
1409
1410
ager@chromium.org7c537e22008-10-16 08:43:32 +00001411Address SeqTwoByteString::GetCharsAddress() {
1412 return FIELD_ADDR(this, kHeaderSize);
1413}
1414
1415
1416uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001417 ASSERT(index >= 0 && index < length());
1418 return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1419}
1420
1421
ager@chromium.org7c537e22008-10-16 08:43:32 +00001422void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001423 ASSERT(index >= 0 && index < length());
1424 WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1425}
1426
1427
ager@chromium.org7c537e22008-10-16 08:43:32 +00001428int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001429 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1430
1431 // Use the map (and not 'this') to compute the size tag, since
1432 // TwoByteStringSize is called during GC when maps are encoded.
1433 switch (map_size_tag(map)) {
1434 case kShortStringTag:
1435 length = length >> kShortLengthShift;
1436 break;
1437 case kMediumStringTag:
1438 length = length >> kMediumLengthShift;
1439 break;
1440 case kLongStringTag:
1441 length = length >> kLongLengthShift;
1442 break;
1443 default:
1444 break;
1445 }
1446 return SizeFor(length);
1447}
1448
1449
ager@chromium.org7c537e22008-10-16 08:43:32 +00001450int SeqAsciiString::SeqAsciiStringSize(Map* map) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001451 uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1452
1453 // Use the map (and not 'this') to compute the size tag, since
1454 // AsciiStringSize is called during GC when maps are encoded.
1455 switch (map_size_tag(map)) {
1456 case kShortStringTag:
1457 length = length >> kShortLengthShift;
1458 break;
1459 case kMediumStringTag:
1460 length = length >> kMediumLengthShift;
1461 break;
1462 case kLongStringTag:
1463 length = length >> kLongLengthShift;
1464 break;
1465 default:
1466 break;
1467 }
1468
1469 return SizeFor(length);
1470}
1471
1472
1473Object* ConsString::first() {
1474 return READ_FIELD(this, kFirstOffset);
1475}
1476
1477
1478void ConsString::set_first(Object* value) {
1479 WRITE_FIELD(this, kFirstOffset, value);
1480 WRITE_BARRIER(this, kFirstOffset);
1481}
1482
1483
1484Object* ConsString::second() {
1485 return READ_FIELD(this, kSecondOffset);
1486}
1487
1488
1489void ConsString::set_second(Object* value) {
1490 WRITE_FIELD(this, kSecondOffset, value);
1491 WRITE_BARRIER(this, kSecondOffset);
1492}
1493
1494
1495Object* SlicedString::buffer() {
1496 return READ_FIELD(this, kBufferOffset);
1497}
1498
1499
1500void SlicedString::set_buffer(Object* buffer) {
1501 WRITE_FIELD(this, kBufferOffset, buffer);
1502 WRITE_BARRIER(this, kBufferOffset);
1503}
1504
1505
1506int SlicedString::start() {
1507 return READ_INT_FIELD(this, kStartOffset);
1508}
1509
1510
1511void SlicedString::set_start(int start) {
1512 WRITE_INT_FIELD(this, kStartOffset, start);
1513}
1514
1515
1516ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1517 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1518}
1519
1520
1521void ExternalAsciiString::set_resource(
1522 ExternalAsciiString::Resource* resource) {
1523 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1524}
1525
1526
1527ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1528 return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1529}
1530
1531
1532void ExternalTwoByteString::set_resource(
1533 ExternalTwoByteString::Resource* resource) {
1534 *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1535}
1536
1537
1538byte ByteArray::get(int index) {
1539 ASSERT(index >= 0 && index < this->length());
1540 return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1541}
1542
1543
1544void ByteArray::set(int index, byte value) {
1545 ASSERT(index >= 0 && index < this->length());
1546 WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1547}
1548
1549
1550int ByteArray::get_int(int index) {
1551 ASSERT(index >= 0 && (index * kIntSize) < this->length());
1552 return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1553}
1554
1555
1556ByteArray* ByteArray::FromDataStartAddress(Address address) {
1557 ASSERT_TAG_ALIGNED(address);
1558 return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1559}
1560
1561
1562Address ByteArray::GetDataStartAddress() {
1563 return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1564}
1565
1566
1567int Map::instance_size() {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001568 return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1569}
1570
1571
1572int Map::inobject_properties() {
1573 return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001574}
1575
1576
1577int HeapObject::SizeFromMap(Map* map) {
1578 InstanceType instance_type = map->instance_type();
1579 // Only inline the two most frequent cases.
1580 if (instance_type == JS_OBJECT_TYPE) return map->instance_size();
1581 if (instance_type == FIXED_ARRAY_TYPE) {
1582 return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1583 }
1584 // Otherwise do the general size computation.
1585 return SlowSizeFromMap(map);
1586}
1587
1588
1589void Map::set_instance_size(int value) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00001590 ASSERT((value & ~(kPointerSize - 1)) == value);
1591 value >>= kPointerSizeLog2;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001592 ASSERT(0 <= value && value < 256);
1593 WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
1594}
1595
1596
ager@chromium.org7c537e22008-10-16 08:43:32 +00001597void Map::set_inobject_properties(int value) {
1598 ASSERT(0 <= value && value < 256);
1599 WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
1600}
1601
1602
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001603InstanceType Map::instance_type() {
1604 return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
1605}
1606
1607
1608void Map::set_instance_type(InstanceType value) {
1609 ASSERT(0 <= value && value < 256);
1610 WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
1611}
1612
1613
1614int Map::unused_property_fields() {
1615 return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
1616}
1617
1618
1619void Map::set_unused_property_fields(int value) {
1620 WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
1621}
1622
1623
1624byte Map::bit_field() {
1625 return READ_BYTE_FIELD(this, kBitFieldOffset);
1626}
1627
1628
1629void Map::set_bit_field(byte value) {
1630 WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
1631}
1632
1633
1634void Map::set_non_instance_prototype(bool value) {
1635 if (value) {
1636 set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
1637 } else {
1638 set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
1639 }
1640}
1641
1642
1643bool Map::has_non_instance_prototype() {
1644 return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
1645}
1646
1647
1648Code::Flags Code::flags() {
1649 return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
1650}
1651
1652
1653void Code::set_flags(Code::Flags flags) {
1654 // Make sure that all call stubs have an arguments count.
1655 ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
1656 ExtractArgumentsCountFromFlags(flags) >= 0);
1657 WRITE_INT_FIELD(this, kFlagsOffset, flags);
1658}
1659
1660
1661Code::Kind Code::kind() {
1662 return ExtractKindFromFlags(flags());
1663}
1664
1665
kasper.lund7276f142008-07-30 08:49:36 +00001666InlineCacheState Code::ic_state() {
1667 InlineCacheState result = ExtractICStateFromFlags(flags());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001668 // Only allow uninitialized or debugger states for non-IC code
1669 // objects. This is used in the debugger to determine whether or not
1670 // a call to code object has been replaced with a debug break call.
1671 ASSERT(is_inline_cache_stub() ||
1672 result == UNINITIALIZED ||
1673 result == DEBUG_BREAK ||
1674 result == DEBUG_PREPARE_STEP_IN);
1675 return result;
1676}
1677
1678
1679PropertyType Code::type() {
kasper.lund7276f142008-07-30 08:49:36 +00001680 ASSERT(ic_state() == MONOMORPHIC);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001681 return ExtractTypeFromFlags(flags());
1682}
1683
1684
1685int Code::arguments_count() {
1686 ASSERT(is_call_stub() || kind() == STUB);
1687 return ExtractArgumentsCountFromFlags(flags());
1688}
1689
1690
1691CodeStub::Major Code::major_key() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001692 ASSERT(kind() == STUB);
kasper.lund7276f142008-07-30 08:49:36 +00001693 return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
1694 kStubMajorKeyOffset));
1695}
1696
1697
1698void Code::set_major_key(CodeStub::Major major) {
1699 ASSERT(kind() == STUB);
1700 ASSERT(0 <= major && major < 256);
1701 WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001702}
1703
1704
1705bool Code::is_inline_cache_stub() {
1706 Kind kind = this->kind();
1707 return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
1708}
1709
1710
1711Code::Flags Code::ComputeFlags(Kind kind,
kasper.lund7276f142008-07-30 08:49:36 +00001712 InlineCacheState ic_state,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001713 PropertyType type,
1714 int argc) {
1715 // Compute the bit mask.
1716 int bits = kind << kFlagsKindShift;
kasper.lund7276f142008-07-30 08:49:36 +00001717 bits |= ic_state << kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001718 bits |= type << kFlagsTypeShift;
1719 bits |= argc << kFlagsArgumentsCountShift;
1720 // Cast to flags and validate result before returning it.
1721 Flags result = static_cast<Flags>(bits);
1722 ASSERT(ExtractKindFromFlags(result) == kind);
kasper.lund7276f142008-07-30 08:49:36 +00001723 ASSERT(ExtractICStateFromFlags(result) == ic_state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001724 ASSERT(ExtractTypeFromFlags(result) == type);
1725 ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
1726 return result;
1727}
1728
1729
1730Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
1731 PropertyType type,
1732 int argc) {
1733 return ComputeFlags(kind, MONOMORPHIC, type, argc);
1734}
1735
1736
1737Code::Kind Code::ExtractKindFromFlags(Flags flags) {
1738 int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
1739 return static_cast<Kind>(bits);
1740}
1741
1742
kasper.lund7276f142008-07-30 08:49:36 +00001743InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
1744 int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001745 return static_cast<InlineCacheState>(bits);
1746}
1747
1748
1749PropertyType Code::ExtractTypeFromFlags(Flags flags) {
1750 int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
1751 return static_cast<PropertyType>(bits);
1752}
1753
1754
1755int Code::ExtractArgumentsCountFromFlags(Flags flags) {
1756 return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
1757}
1758
1759
1760Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
1761 int bits = flags & ~kFlagsTypeMask;
1762 return static_cast<Flags>(bits);
1763}
1764
1765
1766Object* Map::prototype() {
1767 return READ_FIELD(this, kPrototypeOffset);
1768}
1769
1770
1771void Map::set_prototype(Object* value) {
1772 ASSERT(value->IsNull() || value->IsJSObject());
1773 WRITE_FIELD(this, kPrototypeOffset, value);
1774 WRITE_BARRIER(this, kPrototypeOffset);
1775}
1776
1777
1778ACCESSORS(Map, instance_descriptors, DescriptorArray,
1779 kInstanceDescriptorsOffset)
1780ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
1781ACCESSORS(Map, constructor, Object, kConstructorOffset)
1782
1783ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
1784ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
1785
1786ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
1787ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
1788
1789ACCESSORS(JSGlobalObject, security_token, Object, kSecurityTokenOffset)
1790
1791ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
1792ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
1793ACCESSORS(AccessorInfo, data, Object, kDataOffset)
1794ACCESSORS(AccessorInfo, name, Object, kNameOffset)
1795ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
1796
1797ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
1798ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
1799ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
1800
1801ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
1802ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
1803ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
1804ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
1805ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
1806ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
1807
1808ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
1809ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
1810
1811ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
1812ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
1813
1814ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
1815ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001816ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
1817 kPropertyAccessorsOffset)
1818ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
1819 kPrototypeTemplateOffset)
1820ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
1821ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
1822 kNamedPropertyHandlerOffset)
1823ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
1824 kIndexedPropertyHandlerOffset)
1825ACCESSORS(FunctionTemplateInfo, instance_template, Object,
1826 kInstanceTemplateOffset)
1827ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
1828ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001829ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
1830 kInstanceCallHandlerOffset)
1831ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
1832 kAccessCheckInfoOffset)
1833ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
1834
1835ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
kasper.lund212ac232008-07-16 07:07:30 +00001836ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
1837 kInternalFieldCountOffset)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001838
1839ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
1840ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
1841
1842ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
1843
1844ACCESSORS(Script, source, Object, kSourceOffset)
1845ACCESSORS(Script, name, Object, kNameOffset)
1846ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
1847ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
1848ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
1849ACCESSORS(Script, type, Smi, kTypeOffset)
1850
1851ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
1852ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
1853ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
1854ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
1855
1856ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
1857ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
1858ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
1859ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
1860
1861ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
1862ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
1863 kInstanceClassNameOffset)
1864ACCESSORS(SharedFunctionInfo, function_data, Object,
1865 kExternalReferenceDataOffset)
1866ACCESSORS(SharedFunctionInfo, lazy_load_data, Object, kLazyLoadDataOffset)
1867ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
1868ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
1869
1870BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
1871 kHiddenPrototypeBit)
1872BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
1873BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
1874 kNeedsAccessCheckBit)
1875BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
1876 kIsExpressionBit)
1877BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
1878 kIsTopLevelBit)
1879
1880INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
1881INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
1882 kFormalParameterCountOffset)
1883INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
1884 kExpectedNofPropertiesOffset)
1885INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
1886 kStartPositionAndTypeOffset)
1887INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
1888INT_ACCESSORS(SharedFunctionInfo, function_token_position,
1889 kFunctionTokenPositionOffset)
1890
1891
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00001892void SharedFunctionInfo::DontAdaptArguments() {
1893 ASSERT(code()->kind() == Code::BUILTIN);
1894 set_formal_parameter_count(kDontAdaptArgumentsSentinel);
1895}
1896
1897
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001898int SharedFunctionInfo::start_position() {
1899 return start_position_and_type() >> kStartPositionShift;
1900}
1901
1902
1903void SharedFunctionInfo::set_start_position(int start_position) {
1904 set_start_position_and_type((start_position << kStartPositionShift)
1905 | (start_position_and_type() & ~kStartPositionMask));
1906}
1907
1908
1909Code* SharedFunctionInfo::code() {
1910 return Code::cast(READ_FIELD(this, kCodeOffset));
1911}
1912
1913
1914void SharedFunctionInfo::set_code(Code* value) {
1915 WRITE_FIELD(this, kCodeOffset, value);
1916 WRITE_BARRIER(this, kCodeOffset);
1917}
1918
1919
1920bool SharedFunctionInfo::is_compiled() {
1921 // TODO(1242782): Create a code kind for uncompiled code.
1922 return code()->kind() != Code::STUB;
1923}
1924
1925
1926bool JSFunction::IsBoilerplate() {
1927 return map() == Heap::boilerplate_function_map();
1928}
1929
1930
1931bool JSFunction::IsLoaded() {
1932 return shared()->lazy_load_data() == Heap::undefined_value();
1933}
1934
1935
1936Code* JSFunction::code() {
1937 return shared()->code();
1938}
1939
1940
1941void JSFunction::set_code(Code* value) {
1942 shared()->set_code(value);
1943}
1944
1945
1946Context* JSFunction::context() {
1947 return Context::cast(READ_FIELD(this, kContextOffset));
1948}
1949
1950
1951Object* JSFunction::unchecked_context() {
1952 return READ_FIELD(this, kContextOffset);
1953}
1954
1955
1956void JSFunction::set_context(Object* value) {
1957 ASSERT(value == Heap::undefined_value() || value->IsContext());
1958 WRITE_FIELD(this, kContextOffset, value);
1959 WRITE_BARRIER(this, kContextOffset);
1960}
1961
1962ACCESSORS(JSFunction, prototype_or_initial_map, Object,
1963 kPrototypeOrInitialMapOffset)
1964
1965
1966Map* JSFunction::initial_map() {
1967 return Map::cast(prototype_or_initial_map());
1968}
1969
1970
1971void JSFunction::set_initial_map(Map* value) {
1972 set_prototype_or_initial_map(value);
1973}
1974
1975
1976bool JSFunction::has_initial_map() {
1977 return prototype_or_initial_map()->IsMap();
1978}
1979
1980
1981bool JSFunction::has_instance_prototype() {
1982 return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
1983}
1984
1985
1986bool JSFunction::has_prototype() {
1987 return map()->has_non_instance_prototype() || has_instance_prototype();
1988}
1989
1990
1991Object* JSFunction::instance_prototype() {
1992 ASSERT(has_instance_prototype());
1993 if (has_initial_map()) return initial_map()->prototype();
1994 // When there is no initial map and the prototype is a JSObject, the
1995 // initial map field is used for the prototype field.
1996 return prototype_or_initial_map();
1997}
1998
1999
2000Object* JSFunction::prototype() {
2001 ASSERT(has_prototype());
2002 // If the function's prototype property has been set to a non-JSObject
2003 // value, that value is stored in the constructor field of the map.
2004 if (map()->has_non_instance_prototype()) return map()->constructor();
2005 return instance_prototype();
2006}
2007
2008
2009bool JSFunction::is_compiled() {
2010 return shared()->is_compiled();
2011}
2012
2013
2014Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2015 ASSERT(0 <= id && id < kJSBuiltinsCount);
2016 return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2017}
2018
2019
2020void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2021 Object* value) {
2022 ASSERT(0 <= id && id < kJSBuiltinsCount);
2023 WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2024 WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2025}
2026
2027
2028Address Proxy::proxy() {
2029 return AddressFrom<Address>(READ_INT_FIELD(this, kProxyOffset));
2030}
2031
2032
2033void Proxy::set_proxy(Address value) {
2034 WRITE_INT_FIELD(this, kProxyOffset, OffsetFrom(value));
2035}
2036
2037
2038void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2039 visitor->VisitExternalReference(
2040 reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2041}
2042
2043
2044ACCESSORS(JSValue, value, Object, kValueOffset)
2045
2046
2047JSValue* JSValue::cast(Object* obj) {
2048 ASSERT(obj->IsJSValue());
2049 ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2050 return reinterpret_cast<JSValue*>(obj);
2051}
2052
2053
2054INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2055INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2056INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2057
2058
2059Code::ICTargetState Code::ic_flag() {
kasper.lund7276f142008-07-30 08:49:36 +00002060 return static_cast<ICTargetState>(READ_BYTE_FIELD(this, kICFlagOffset));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002061}
2062
2063
2064void Code::set_ic_flag(ICTargetState value) {
kasper.lund7276f142008-07-30 08:49:36 +00002065 WRITE_BYTE_FIELD(this, kICFlagOffset, value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002066}
2067
2068
2069byte* Code::instruction_start() {
2070 return FIELD_ADDR(this, kHeaderSize);
2071}
2072
2073
2074int Code::body_size() {
2075 return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2076}
2077
2078
2079byte* Code::relocation_start() {
2080 return FIELD_ADDR(this, CodeSize() - sinfo_size() - relocation_size());
2081}
2082
2083
2084byte* Code::entry() {
2085 return instruction_start();
2086}
2087
2088
2089bool Code::contains(byte* pc) {
2090 return (instruction_start() <= pc) &&
2091 (pc < instruction_start() + instruction_size());
2092}
2093
2094
2095byte* Code::sinfo_start() {
2096 return FIELD_ADDR(this, CodeSize() - sinfo_size());
2097}
2098
2099
2100ACCESSORS(JSArray, length, Object, kLengthOffset)
2101
2102
ager@chromium.org236ad962008-09-25 09:45:57 +00002103ACCESSORS(JSRegExp, data, Object, kDataOffset)
2104ACCESSORS(JSRegExp, type, Object, kTypeOffset)
2105
2106
2107JSRegExp::Type JSRegExp::type_tag() {
2108 return static_cast<JSRegExp::Type>(Smi::cast(type())->value());
2109}
2110
2111
2112void JSRegExp::set_type_tag(JSRegExp::Type value) {
2113 set_type(Smi::FromInt(value));
2114}
2115
2116
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002117bool JSObject::HasFastElements() {
2118 return !elements()->IsDictionary();
2119}
2120
2121
2122bool JSObject::HasNamedInterceptor() {
2123 return map()->has_named_interceptor();
2124}
2125
2126
2127bool JSObject::HasIndexedInterceptor() {
2128 return map()->has_indexed_interceptor();
2129}
2130
2131
2132Dictionary* JSObject::property_dictionary() {
2133 ASSERT(!HasFastProperties());
2134 return Dictionary::cast(properties());
2135}
2136
2137
2138Dictionary* JSObject::element_dictionary() {
2139 ASSERT(!HasFastElements());
2140 return Dictionary::cast(elements());
2141}
2142
2143
2144bool String::HasHashCode() {
2145 return (length_field() & kHashComputedMask) != 0;
2146}
2147
2148
2149uint32_t String::Hash() {
2150 // Fast case: has hash code already been computed?
ager@chromium.org7c537e22008-10-16 08:43:32 +00002151 uint32_t field = length_field();
2152 if (field & kHashComputedMask) return field >> kHashShift;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002153 // Slow case: compute hash code and set it..
2154 return ComputeAndSetHash();
2155}
2156
2157
ager@chromium.org7c537e22008-10-16 08:43:32 +00002158StringHasher::StringHasher(int length)
2159 : length_(length),
2160 raw_running_hash_(0),
2161 array_index_(0),
2162 is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2163 is_first_char_(true),
2164 is_valid_(true) { }
2165
2166
2167bool StringHasher::has_trivial_hash() {
2168 return length_ > String::kMaxMediumStringSize;
2169}
2170
2171
2172void StringHasher::AddCharacter(uc32 c) {
2173 // Note: the Jenkins one-at-a-time hash function
2174 raw_running_hash_ += c;
2175 raw_running_hash_ += (raw_running_hash_ << 10);
2176 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2177 // Incremental array index computation
2178 if (is_array_index_) {
2179 if (c < '0' || c > '9') {
2180 is_array_index_ = false;
2181 } else {
2182 int d = c - '0';
2183 if (is_first_char_) {
2184 is_first_char_ = false;
2185 if (c == '0' && length_ > 1) {
2186 is_array_index_ = false;
2187 return;
2188 }
2189 }
2190 if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2191 is_array_index_ = false;
2192 } else {
2193 array_index_ = array_index_ * 10 + d;
2194 }
2195 }
2196 }
2197}
2198
2199
2200void StringHasher::AddCharacterNoIndex(uc32 c) {
2201 ASSERT(!is_array_index());
2202 raw_running_hash_ += c;
2203 raw_running_hash_ += (raw_running_hash_ << 10);
2204 raw_running_hash_ ^= (raw_running_hash_ >> 6);
2205}
2206
2207
2208uint32_t StringHasher::GetHash() {
2209 uint32_t result = raw_running_hash_;
2210 result += (result << 3);
2211 result ^= (result >> 11);
2212 result += (result << 15);
2213 return result;
2214}
2215
2216
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002217bool String::AsArrayIndex(uint32_t* index) {
ager@chromium.org7c537e22008-10-16 08:43:32 +00002218 uint32_t field = length_field();
2219 if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002220 return SlowAsArrayIndex(index);
2221}
2222
2223
2224Object* JSObject::GetPrototype() {
2225 return JSObject::cast(this)->map()->prototype();
2226}
2227
2228
2229PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2230 return GetPropertyAttributeWithReceiver(this, key);
2231}
2232
2233
2234bool JSObject::HasElement(uint32_t index) {
2235 return HasElementWithReceiver(this, index);
2236}
2237
2238
2239bool AccessorInfo::all_can_read() {
2240 return BooleanBit::get(flag(), kAllCanReadBit);
2241}
2242
2243
2244void AccessorInfo::set_all_can_read(bool value) {
2245 set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2246}
2247
2248
2249bool AccessorInfo::all_can_write() {
2250 return BooleanBit::get(flag(), kAllCanWriteBit);
2251}
2252
2253
2254void AccessorInfo::set_all_can_write(bool value) {
2255 set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2256}
2257
2258
2259PropertyAttributes AccessorInfo::property_attributes() {
2260 return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2261}
2262
2263
2264void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2265 ASSERT(AttributesField::is_valid(attributes));
2266 int rest_value = flag()->value() & ~AttributesField::mask();
2267 set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2268}
2269
2270void Dictionary::SetEntry(int entry,
2271 Object* key,
2272 Object* value,
2273 PropertyDetails details) {
2274 ASSERT(!key->IsString() || details.index() > 0);
2275 int index = EntryToIndex(entry);
2276 WriteBarrierMode mode = GetWriteBarrierMode();
2277 set(index, key, mode);
2278 set(index+1, value, mode);
2279 fast_set(this, index+2, details.AsSmi());
2280}
2281
2282
2283void Map::ClearCodeCache() {
2284 // No write barrier is needed since empty_fixed_array is not in new space.
2285 // Please note this function is used during marking:
2286 // - MarkCompactCollector::MarkUnmarkedObject
2287 ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
2288 WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
2289}
2290
2291
ager@chromium.org7c537e22008-10-16 08:43:32 +00002292void JSArray::SetContent(FixedArray* storage) {
2293 set_length(Smi::FromInt(storage->length()));
2294 set_elements(storage);
2295}
2296
2297
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002298#undef CAST_ACCESSOR
2299#undef INT_ACCESSORS
2300#undef SMI_ACCESSORS
2301#undef ACCESSORS
2302#undef FIELD_ADDR
2303#undef READ_FIELD
2304#undef WRITE_FIELD
2305#undef WRITE_BARRIER
2306#undef READ_MEMADDR_FIELD
2307#undef WRITE_MEMADDR_FIELD
2308#undef READ_DOUBLE_FIELD
2309#undef WRITE_DOUBLE_FIELD
2310#undef READ_INT_FIELD
2311#undef WRITE_INT_FIELD
2312#undef READ_SHORT_FIELD
2313#undef WRITE_SHORT_FIELD
2314#undef READ_BYTE_FIELD
2315#undef WRITE_BYTE_FIELD
2316
2317
2318} } // namespace v8::internal
2319
2320#endif // V8_OBJECTS_INL_H_