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