objects-inl.h revision f87a203d89e1bbb6708282e0b64dbd13d59b723d
1// Copyright 2006-2008 the V8 project authors. 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 functions 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 "heap.h"
42#include "memory.h"
43#include "property.h"
44#include "spaces.h"
45
46namespace v8 {
47namespace internal {
48
49PropertyDetails::PropertyDetails(Smi* smi) {
50  value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55  return Smi::FromInt(value_);
56}
57
58
59PropertyDetails PropertyDetails::AsDeleted() {
60  PropertyDetails d(DONT_ENUM, NORMAL);
61  Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
62  return PropertyDetails(smi);
63}
64
65
66#define CAST_ACCESSOR(type)                     \
67  type* type::cast(Object* object) {            \
68    ASSERT(object->Is##type());                 \
69    return reinterpret_cast<type*>(object);     \
70  }
71
72
73#define INT_ACCESSORS(holder, name, offset)                             \
74  int holder::name() { return READ_INT_FIELD(this, offset); }           \
75  void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset)                           \
79  type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
80  void holder::set_##name(type* value, WriteBarrierMode mode) {         \
81    WRITE_FIELD(this, offset, value);                                   \
82    CONDITIONAL_WRITE_BARRIER(this, offset, mode);                      \
83  }
84
85
86#define SMI_ACCESSORS(holder, name, offset)             \
87  int holder::name() {                                  \
88    Object* value = READ_FIELD(this, offset);           \
89    return Smi::cast(value)->value();                   \
90  }                                                     \
91  void holder::set_##name(int value) {                  \
92    WRITE_FIELD(this, offset, Smi::FromInt(value));     \
93  }
94
95
96#define BOOL_GETTER(holder, field, name, offset)           \
97  bool holder::name() {                                    \
98    return BooleanBit::get(field(), offset);               \
99  }                                                        \
100
101
102#define BOOL_ACCESSORS(holder, field, name, offset)        \
103  bool holder::name() {                                    \
104    return BooleanBit::get(field(), offset);               \
105  }                                                        \
106  void holder::set_##name(bool value) {                    \
107    set_##field(BooleanBit::set(field(), offset, value));  \
108  }
109
110
111bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
112  // There is a constraint on the object; check.
113  if (!this->IsJSObject()) return false;
114  // Fetch the constructor function of the object.
115  Object* cons_obj = JSObject::cast(this)->map()->constructor();
116  if (!cons_obj->IsJSFunction()) return false;
117  JSFunction* fun = JSFunction::cast(cons_obj);
118  // Iterate through the chain of inheriting function templates to
119  // see if the required one occurs.
120  for (Object* type = fun->shared()->function_data();
121       type->IsFunctionTemplateInfo();
122       type = FunctionTemplateInfo::cast(type)->parent_template()) {
123    if (type == expected) return true;
124  }
125  // Didn't find the required type in the inheritance chain.
126  return false;
127}
128
129
130bool Object::IsSmi() {
131  return HAS_SMI_TAG(this);
132}
133
134
135bool Object::IsHeapObject() {
136  return Internals::HasHeapObjectTag(this);
137}
138
139
140bool Object::IsHeapNumber() {
141  return Object::IsHeapObject()
142    && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
143}
144
145
146bool Object::IsString() {
147  return Object::IsHeapObject()
148    && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
149}
150
151
152bool Object::IsSymbol() {
153  if (!this->IsHeapObject()) return false;
154  uint32_t type = HeapObject::cast(this)->map()->instance_type();
155  // Because the symbol tag is non-zero and no non-string types have the
156  // symbol bit set we can test for symbols with a very simple test
157  // operation.
158  ASSERT(kSymbolTag != 0);
159  ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
160  return (type & kIsSymbolMask) != 0;
161}
162
163
164bool Object::IsConsString() {
165  if (!this->IsHeapObject()) return false;
166  uint32_t type = HeapObject::cast(this)->map()->instance_type();
167  return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
168         (kStringTag | kConsStringTag);
169}
170
171
172bool Object::IsSeqString() {
173  if (!IsString()) return false;
174  return StringShape(String::cast(this)).IsSequential();
175}
176
177
178bool Object::IsSeqAsciiString() {
179  if (!IsString()) return false;
180  return StringShape(String::cast(this)).IsSequential() &&
181         String::cast(this)->IsAsciiRepresentation();
182}
183
184
185bool Object::IsSeqTwoByteString() {
186  if (!IsString()) return false;
187  return StringShape(String::cast(this)).IsSequential() &&
188         String::cast(this)->IsTwoByteRepresentation();
189}
190
191
192bool Object::IsExternalString() {
193  if (!IsString()) return false;
194  return StringShape(String::cast(this)).IsExternal();
195}
196
197
198bool Object::IsExternalAsciiString() {
199  if (!IsString()) return false;
200  return StringShape(String::cast(this)).IsExternal() &&
201         String::cast(this)->IsAsciiRepresentation();
202}
203
204
205bool Object::IsExternalTwoByteString() {
206  if (!IsString()) return false;
207  return StringShape(String::cast(this)).IsExternal() &&
208         String::cast(this)->IsTwoByteRepresentation();
209}
210
211
212StringShape::StringShape(String* str)
213  : type_(str->map()->instance_type()) {
214  set_valid();
215  ASSERT((type_ & kIsNotStringMask) == kStringTag);
216}
217
218
219StringShape::StringShape(Map* map)
220  : type_(map->instance_type()) {
221  set_valid();
222  ASSERT((type_ & kIsNotStringMask) == kStringTag);
223}
224
225
226StringShape::StringShape(InstanceType t)
227  : type_(static_cast<uint32_t>(t)) {
228  set_valid();
229  ASSERT((type_ & kIsNotStringMask) == kStringTag);
230}
231
232
233bool StringShape::IsSymbol() {
234  ASSERT(valid());
235  ASSERT(kSymbolTag != 0);
236  return (type_ & kIsSymbolMask) != 0;
237}
238
239
240bool String::IsAsciiRepresentation() {
241  uint32_t type = map()->instance_type();
242  return (type & kStringEncodingMask) == kAsciiStringTag;
243}
244
245
246bool String::IsTwoByteRepresentation() {
247  uint32_t type = map()->instance_type();
248  return (type & kStringEncodingMask) == kTwoByteStringTag;
249}
250
251
252bool String::HasOnlyAsciiChars() {
253  uint32_t type = map()->instance_type();
254  return (type & kStringEncodingMask) == kAsciiStringTag ||
255         (type & kAsciiDataHintMask) == kAsciiDataHintTag;
256}
257
258
259bool StringShape::IsCons() {
260  return (type_ & kStringRepresentationMask) == kConsStringTag;
261}
262
263
264bool StringShape::IsExternal() {
265  return (type_ & kStringRepresentationMask) == kExternalStringTag;
266}
267
268
269bool StringShape::IsSequential() {
270  return (type_ & kStringRepresentationMask) == kSeqStringTag;
271}
272
273
274StringRepresentationTag StringShape::representation_tag() {
275  uint32_t tag = (type_ & kStringRepresentationMask);
276  return static_cast<StringRepresentationTag>(tag);
277}
278
279
280uint32_t StringShape::full_representation_tag() {
281  return (type_ & (kStringRepresentationMask | kStringEncodingMask));
282}
283
284
285STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
286             Internals::kFullStringRepresentationMask);
287
288
289bool StringShape::IsSequentialAscii() {
290  return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
291}
292
293
294bool StringShape::IsSequentialTwoByte() {
295  return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
296}
297
298
299bool StringShape::IsExternalAscii() {
300  return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
301}
302
303
304bool StringShape::IsExternalTwoByte() {
305  return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
306}
307
308
309STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
310             Internals::kExternalTwoByteRepresentationTag);
311
312
313uc32 FlatStringReader::Get(int index) {
314  ASSERT(0 <= index && index <= length_);
315  if (is_ascii_) {
316    return static_cast<const byte*>(start_)[index];
317  } else {
318    return static_cast<const uc16*>(start_)[index];
319  }
320}
321
322
323bool Object::IsNumber() {
324  return IsSmi() || IsHeapNumber();
325}
326
327
328bool Object::IsByteArray() {
329  return Object::IsHeapObject()
330    && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
331}
332
333
334bool Object::IsPixelArray() {
335  return Object::IsHeapObject() &&
336      HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
337}
338
339
340bool Object::IsExternalArray() {
341  if (!Object::IsHeapObject())
342    return false;
343  InstanceType instance_type =
344      HeapObject::cast(this)->map()->instance_type();
345  return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
346          instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
347}
348
349
350bool Object::IsExternalByteArray() {
351  return Object::IsHeapObject() &&
352      HeapObject::cast(this)->map()->instance_type() ==
353      EXTERNAL_BYTE_ARRAY_TYPE;
354}
355
356
357bool Object::IsExternalUnsignedByteArray() {
358  return Object::IsHeapObject() &&
359      HeapObject::cast(this)->map()->instance_type() ==
360      EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
361}
362
363
364bool Object::IsExternalShortArray() {
365  return Object::IsHeapObject() &&
366      HeapObject::cast(this)->map()->instance_type() ==
367      EXTERNAL_SHORT_ARRAY_TYPE;
368}
369
370
371bool Object::IsExternalUnsignedShortArray() {
372  return Object::IsHeapObject() &&
373      HeapObject::cast(this)->map()->instance_type() ==
374      EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
375}
376
377
378bool Object::IsExternalIntArray() {
379  return Object::IsHeapObject() &&
380      HeapObject::cast(this)->map()->instance_type() ==
381      EXTERNAL_INT_ARRAY_TYPE;
382}
383
384
385bool Object::IsExternalUnsignedIntArray() {
386  return Object::IsHeapObject() &&
387      HeapObject::cast(this)->map()->instance_type() ==
388      EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
389}
390
391
392bool Object::IsExternalFloatArray() {
393  return Object::IsHeapObject() &&
394      HeapObject::cast(this)->map()->instance_type() ==
395      EXTERNAL_FLOAT_ARRAY_TYPE;
396}
397
398
399bool Object::IsFailure() {
400  return HAS_FAILURE_TAG(this);
401}
402
403
404bool Object::IsRetryAfterGC() {
405  return HAS_FAILURE_TAG(this)
406    && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
407}
408
409
410bool Object::IsOutOfMemoryFailure() {
411  return HAS_FAILURE_TAG(this)
412    && Failure::cast(this)->IsOutOfMemoryException();
413}
414
415
416bool Object::IsException() {
417  return this == Failure::Exception();
418}
419
420
421bool Object::IsJSObject() {
422  return IsHeapObject()
423    && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
424}
425
426
427bool Object::IsJSContextExtensionObject() {
428  return IsHeapObject()
429    && (HeapObject::cast(this)->map()->instance_type() ==
430        JS_CONTEXT_EXTENSION_OBJECT_TYPE);
431}
432
433
434bool Object::IsMap() {
435  return Object::IsHeapObject()
436    && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
437}
438
439
440bool Object::IsFixedArray() {
441  return Object::IsHeapObject()
442    && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
443}
444
445
446bool Object::IsDescriptorArray() {
447  return IsFixedArray();
448}
449
450
451bool Object::IsContext() {
452  return Object::IsHeapObject()
453    && (HeapObject::cast(this)->map() == Heap::context_map() ||
454        HeapObject::cast(this)->map() == Heap::catch_context_map() ||
455        HeapObject::cast(this)->map() == Heap::global_context_map());
456}
457
458
459bool Object::IsCatchContext() {
460  return Object::IsHeapObject()
461    && HeapObject::cast(this)->map() == Heap::catch_context_map();
462}
463
464
465bool Object::IsGlobalContext() {
466  return Object::IsHeapObject()
467    && HeapObject::cast(this)->map() == Heap::global_context_map();
468}
469
470
471bool Object::IsJSFunction() {
472  return Object::IsHeapObject()
473    && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
474}
475
476
477template <> inline bool Is<JSFunction>(Object* obj) {
478  return obj->IsJSFunction();
479}
480
481
482bool Object::IsCode() {
483  return Object::IsHeapObject()
484    && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
485}
486
487
488bool Object::IsOddball() {
489  return Object::IsHeapObject()
490    && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
491}
492
493
494bool Object::IsJSGlobalPropertyCell() {
495  return Object::IsHeapObject()
496      && HeapObject::cast(this)->map()->instance_type()
497      == JS_GLOBAL_PROPERTY_CELL_TYPE;
498}
499
500
501bool Object::IsSharedFunctionInfo() {
502  return Object::IsHeapObject() &&
503      (HeapObject::cast(this)->map()->instance_type() ==
504       SHARED_FUNCTION_INFO_TYPE);
505}
506
507
508bool Object::IsJSValue() {
509  return Object::IsHeapObject()
510    && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
511}
512
513
514bool Object::IsStringWrapper() {
515  return IsJSValue() && JSValue::cast(this)->value()->IsString();
516}
517
518
519bool Object::IsProxy() {
520  return Object::IsHeapObject()
521    && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
522}
523
524
525bool Object::IsBoolean() {
526  return IsTrue() || IsFalse();
527}
528
529
530bool Object::IsJSArray() {
531  return Object::IsHeapObject()
532    && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
533}
534
535
536bool Object::IsJSRegExp() {
537  return Object::IsHeapObject()
538    && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
539}
540
541
542template <> inline bool Is<JSArray>(Object* obj) {
543  return obj->IsJSArray();
544}
545
546
547bool Object::IsHashTable() {
548  return Object::IsHeapObject()
549    && HeapObject::cast(this)->map() == Heap::hash_table_map();
550}
551
552
553bool Object::IsDictionary() {
554  return IsHashTable() && this != Heap::symbol_table();
555}
556
557
558bool Object::IsSymbolTable() {
559  return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
560}
561
562
563bool Object::IsJSFunctionResultCache() {
564  if (!IsFixedArray()) return false;
565  FixedArray* self = FixedArray::cast(this);
566  int length = self->length();
567  if (length < JSFunctionResultCache::kEntriesIndex) return false;
568  if ((length - JSFunctionResultCache::kEntriesIndex)
569      % JSFunctionResultCache::kEntrySize != 0) {
570    return false;
571  }
572#ifdef DEBUG
573  reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
574#endif
575  return true;
576}
577
578
579bool Object::IsNormalizedMapCache() {
580  if (!IsFixedArray()) return false;
581  if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
582    return false;
583  }
584#ifdef DEBUG
585  reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
586#endif
587  return true;
588}
589
590
591bool Object::IsCompilationCacheTable() {
592  return IsHashTable();
593}
594
595
596bool Object::IsCodeCacheHashTable() {
597  return IsHashTable();
598}
599
600
601bool Object::IsMapCache() {
602  return IsHashTable();
603}
604
605
606bool Object::IsPrimitive() {
607  return IsOddball() || IsNumber() || IsString();
608}
609
610
611bool Object::IsJSGlobalProxy() {
612  bool result = IsHeapObject() &&
613                (HeapObject::cast(this)->map()->instance_type() ==
614                 JS_GLOBAL_PROXY_TYPE);
615  ASSERT(!result || IsAccessCheckNeeded());
616  return result;
617}
618
619
620bool Object::IsGlobalObject() {
621  if (!IsHeapObject()) return false;
622
623  InstanceType type = HeapObject::cast(this)->map()->instance_type();
624  return type == JS_GLOBAL_OBJECT_TYPE ||
625         type == JS_BUILTINS_OBJECT_TYPE;
626}
627
628
629bool Object::IsJSGlobalObject() {
630  return IsHeapObject() &&
631      (HeapObject::cast(this)->map()->instance_type() ==
632       JS_GLOBAL_OBJECT_TYPE);
633}
634
635
636bool Object::IsJSBuiltinsObject() {
637  return IsHeapObject() &&
638      (HeapObject::cast(this)->map()->instance_type() ==
639       JS_BUILTINS_OBJECT_TYPE);
640}
641
642
643bool Object::IsUndetectableObject() {
644  return IsHeapObject()
645    && HeapObject::cast(this)->map()->is_undetectable();
646}
647
648
649bool Object::IsAccessCheckNeeded() {
650  return IsHeapObject()
651    && HeapObject::cast(this)->map()->is_access_check_needed();
652}
653
654
655bool Object::IsStruct() {
656  if (!IsHeapObject()) return false;
657  switch (HeapObject::cast(this)->map()->instance_type()) {
658#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
659  STRUCT_LIST(MAKE_STRUCT_CASE)
660#undef MAKE_STRUCT_CASE
661    default: return false;
662  }
663}
664
665
666#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
667  bool Object::Is##Name() {                                      \
668    return Object::IsHeapObject()                                \
669      && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
670  }
671  STRUCT_LIST(MAKE_STRUCT_PREDICATE)
672#undef MAKE_STRUCT_PREDICATE
673
674
675bool Object::IsUndefined() {
676  return this == Heap::undefined_value();
677}
678
679
680bool Object::IsTheHole() {
681  return this == Heap::the_hole_value();
682}
683
684
685bool Object::IsNull() {
686  return this == Heap::null_value();
687}
688
689
690bool Object::IsTrue() {
691  return this == Heap::true_value();
692}
693
694
695bool Object::IsFalse() {
696  return this == Heap::false_value();
697}
698
699
700double Object::Number() {
701  ASSERT(IsNumber());
702  return IsSmi()
703    ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
704    : reinterpret_cast<HeapNumber*>(this)->value();
705}
706
707
708
709Object* Object::ToSmi() {
710  if (IsSmi()) return this;
711  if (IsHeapNumber()) {
712    double value = HeapNumber::cast(this)->value();
713    int int_value = FastD2I(value);
714    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
715      return Smi::FromInt(int_value);
716    }
717  }
718  return Failure::Exception();
719}
720
721
722bool Object::HasSpecificClassOf(String* name) {
723  return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
724}
725
726
727Object* Object::GetElement(uint32_t index) {
728  return GetElementWithReceiver(this, index);
729}
730
731
732Object* Object::GetProperty(String* key) {
733  PropertyAttributes attributes;
734  return GetPropertyWithReceiver(this, key, &attributes);
735}
736
737
738Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
739  return GetPropertyWithReceiver(this, key, attributes);
740}
741
742
743#define FIELD_ADDR(p, offset) \
744  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
745
746#define READ_FIELD(p, offset) \
747  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
748
749#define WRITE_FIELD(p, offset, value) \
750  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
751
752
753#define WRITE_BARRIER(object, offset) \
754  Heap::RecordWrite(object->address(), offset);
755
756// CONDITIONAL_WRITE_BARRIER must be issued after the actual
757// write due to the assert validating the written value.
758#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
759  if (mode == UPDATE_WRITE_BARRIER) { \
760    Heap::RecordWrite(object->address(), offset); \
761  } else { \
762    ASSERT(mode == SKIP_WRITE_BARRIER); \
763    ASSERT(Heap::InNewSpace(object) || \
764           !Heap::InNewSpace(READ_FIELD(object, offset)) || \
765           Page::FromAddress(object->address())->           \
766               IsRegionDirty(object->address() + offset));  \
767  }
768
769#define READ_DOUBLE_FIELD(p, offset) \
770  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
771
772#define WRITE_DOUBLE_FIELD(p, offset, value) \
773  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
774
775#define READ_INT_FIELD(p, offset) \
776  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
777
778#define WRITE_INT_FIELD(p, offset, value) \
779  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
780
781#define READ_INTPTR_FIELD(p, offset) \
782  (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
783
784#define WRITE_INTPTR_FIELD(p, offset, value) \
785  (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
786
787#define READ_UINT32_FIELD(p, offset) \
788  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
789
790#define WRITE_UINT32_FIELD(p, offset, value) \
791  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
792
793#define READ_SHORT_FIELD(p, offset) \
794  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
795
796#define WRITE_SHORT_FIELD(p, offset, value) \
797  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
798
799#define READ_BYTE_FIELD(p, offset) \
800  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
801
802#define WRITE_BYTE_FIELD(p, offset, value) \
803  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
804
805
806Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
807  return &READ_FIELD(obj, byte_offset);
808}
809
810
811int Smi::value() {
812  return Internals::SmiValue(this);
813}
814
815
816Smi* Smi::FromInt(int value) {
817  ASSERT(Smi::IsValid(value));
818  int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
819  intptr_t tagged_value =
820      (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
821  return reinterpret_cast<Smi*>(tagged_value);
822}
823
824
825Smi* Smi::FromIntptr(intptr_t value) {
826  ASSERT(Smi::IsValid(value));
827  int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
828  return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
829}
830
831
832Failure::Type Failure::type() const {
833  return static_cast<Type>(value() & kFailureTypeTagMask);
834}
835
836
837bool Failure::IsInternalError() const {
838  return type() == INTERNAL_ERROR;
839}
840
841
842bool Failure::IsOutOfMemoryException() const {
843  return type() == OUT_OF_MEMORY_EXCEPTION;
844}
845
846
847AllocationSpace Failure::allocation_space() const {
848  ASSERT_EQ(RETRY_AFTER_GC, type());
849  return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
850                                      & kSpaceTagMask);
851}
852
853
854Failure* Failure::InternalError() {
855  return Construct(INTERNAL_ERROR);
856}
857
858
859Failure* Failure::Exception() {
860  return Construct(EXCEPTION);
861}
862
863
864Failure* Failure::OutOfMemoryException() {
865  return Construct(OUT_OF_MEMORY_EXCEPTION);
866}
867
868
869intptr_t Failure::value() const {
870  return static_cast<intptr_t>(
871      reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
872}
873
874
875Failure* Failure::RetryAfterGC() {
876  return RetryAfterGC(NEW_SPACE);
877}
878
879
880Failure* Failure::RetryAfterGC(AllocationSpace space) {
881  ASSERT((space & ~kSpaceTagMask) == 0);
882  return Construct(RETRY_AFTER_GC, space);
883}
884
885
886Failure* Failure::Construct(Type type, intptr_t value) {
887  uintptr_t info =
888      (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
889  ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
890  return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
891}
892
893
894bool Smi::IsValid(intptr_t value) {
895#ifdef DEBUG
896  bool in_range = (value >= kMinValue) && (value <= kMaxValue);
897#endif
898
899#ifdef V8_TARGET_ARCH_X64
900  // To be representable as a long smi, the value must be a 32-bit integer.
901  bool result = (value == static_cast<int32_t>(value));
902#else
903  // To be representable as an tagged small integer, the two
904  // most-significant bits of 'value' must be either 00 or 11 due to
905  // sign-extension. To check this we add 01 to the two
906  // most-significant bits, and check if the most-significant bit is 0
907  //
908  // CAUTION: The original code below:
909  // bool result = ((value + 0x40000000) & 0x80000000) == 0;
910  // may lead to incorrect results according to the C language spec, and
911  // in fact doesn't work correctly with gcc4.1.1 in some cases: The
912  // compiler may produce undefined results in case of signed integer
913  // overflow. The computation must be done w/ unsigned ints.
914  bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
915#endif
916  ASSERT(result == in_range);
917  return result;
918}
919
920
921MapWord MapWord::FromMap(Map* map) {
922  return MapWord(reinterpret_cast<uintptr_t>(map));
923}
924
925
926Map* MapWord::ToMap() {
927  return reinterpret_cast<Map*>(value_);
928}
929
930
931bool MapWord::IsForwardingAddress() {
932  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
933}
934
935
936MapWord MapWord::FromForwardingAddress(HeapObject* object) {
937  Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
938  return MapWord(reinterpret_cast<uintptr_t>(raw));
939}
940
941
942HeapObject* MapWord::ToForwardingAddress() {
943  ASSERT(IsForwardingAddress());
944  return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
945}
946
947
948bool MapWord::IsMarked() {
949  return (value_ & kMarkingMask) == 0;
950}
951
952
953void MapWord::SetMark() {
954  value_ &= ~kMarkingMask;
955}
956
957
958void MapWord::ClearMark() {
959  value_ |= kMarkingMask;
960}
961
962
963bool MapWord::IsOverflowed() {
964  return (value_ & kOverflowMask) != 0;
965}
966
967
968void MapWord::SetOverflow() {
969  value_ |= kOverflowMask;
970}
971
972
973void MapWord::ClearOverflow() {
974  value_ &= ~kOverflowMask;
975}
976
977
978MapWord MapWord::EncodeAddress(Address map_address, int offset) {
979  // Offset is the distance in live bytes from the first live object in the
980  // same page. The offset between two objects in the same page should not
981  // exceed the object area size of a page.
982  ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
983
984  uintptr_t compact_offset = offset >> kObjectAlignmentBits;
985  ASSERT(compact_offset < (1 << kForwardingOffsetBits));
986
987  Page* map_page = Page::FromAddress(map_address);
988  ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
989
990  uintptr_t map_page_offset =
991      map_page->Offset(map_address) >> kMapAlignmentBits;
992
993  uintptr_t encoding =
994      (compact_offset << kForwardingOffsetShift) |
995      (map_page_offset << kMapPageOffsetShift) |
996      (map_page->mc_page_index << kMapPageIndexShift);
997  return MapWord(encoding);
998}
999
1000
1001Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1002  int map_page_index =
1003      static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1004  ASSERT_MAP_PAGE_INDEX(map_page_index);
1005
1006  int map_page_offset = static_cast<int>(
1007      ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1008      kMapAlignmentBits);
1009
1010  return (map_space->PageAddress(map_page_index) + map_page_offset);
1011}
1012
1013
1014int MapWord::DecodeOffset() {
1015  // The offset field is represented in the kForwardingOffsetBits
1016  // most-significant bits.
1017  uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1018  ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1019  return static_cast<int>(offset);
1020}
1021
1022
1023MapWord MapWord::FromEncodedAddress(Address address) {
1024  return MapWord(reinterpret_cast<uintptr_t>(address));
1025}
1026
1027
1028Address MapWord::ToEncodedAddress() {
1029  return reinterpret_cast<Address>(value_);
1030}
1031
1032
1033#ifdef DEBUG
1034void HeapObject::VerifyObjectField(int offset) {
1035  VerifyPointer(READ_FIELD(this, offset));
1036}
1037
1038void HeapObject::VerifySmiField(int offset) {
1039  ASSERT(READ_FIELD(this, offset)->IsSmi());
1040}
1041#endif
1042
1043
1044Map* HeapObject::map() {
1045  return map_word().ToMap();
1046}
1047
1048
1049void HeapObject::set_map(Map* value) {
1050  set_map_word(MapWord::FromMap(value));
1051}
1052
1053
1054MapWord HeapObject::map_word() {
1055  return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1056}
1057
1058
1059void HeapObject::set_map_word(MapWord map_word) {
1060  // WRITE_FIELD does not invoke write barrier, but there is no need
1061  // here.
1062  WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1063}
1064
1065
1066HeapObject* HeapObject::FromAddress(Address address) {
1067  ASSERT_TAG_ALIGNED(address);
1068  return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1069}
1070
1071
1072Address HeapObject::address() {
1073  return reinterpret_cast<Address>(this) - kHeapObjectTag;
1074}
1075
1076
1077int HeapObject::Size() {
1078  return SizeFromMap(map());
1079}
1080
1081
1082void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1083  v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1084                   reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1085}
1086
1087
1088void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1089  v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1090}
1091
1092
1093bool HeapObject::IsMarked() {
1094  return map_word().IsMarked();
1095}
1096
1097
1098void HeapObject::SetMark() {
1099  ASSERT(!IsMarked());
1100  MapWord first_word = map_word();
1101  first_word.SetMark();
1102  set_map_word(first_word);
1103}
1104
1105
1106void HeapObject::ClearMark() {
1107  ASSERT(IsMarked());
1108  MapWord first_word = map_word();
1109  first_word.ClearMark();
1110  set_map_word(first_word);
1111}
1112
1113
1114bool HeapObject::IsOverflowed() {
1115  return map_word().IsOverflowed();
1116}
1117
1118
1119void HeapObject::SetOverflow() {
1120  MapWord first_word = map_word();
1121  first_word.SetOverflow();
1122  set_map_word(first_word);
1123}
1124
1125
1126void HeapObject::ClearOverflow() {
1127  ASSERT(IsOverflowed());
1128  MapWord first_word = map_word();
1129  first_word.ClearOverflow();
1130  set_map_word(first_word);
1131}
1132
1133
1134double HeapNumber::value() {
1135  return READ_DOUBLE_FIELD(this, kValueOffset);
1136}
1137
1138
1139void HeapNumber::set_value(double value) {
1140  WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1141}
1142
1143
1144int HeapNumber::get_exponent() {
1145  return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1146          kExponentShift) - kExponentBias;
1147}
1148
1149
1150int HeapNumber::get_sign() {
1151  return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1152}
1153
1154
1155ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1156
1157
1158HeapObject* JSObject::elements() {
1159  Object* array = READ_FIELD(this, kElementsOffset);
1160  // In the assert below Dictionary is covered under FixedArray.
1161  ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1162         array->IsExternalArray());
1163  return reinterpret_cast<HeapObject*>(array);
1164}
1165
1166
1167void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
1168  ASSERT(map()->has_fast_elements() ==
1169         (value->map() == Heap::fixed_array_map() ||
1170          value->map() == Heap::fixed_cow_array_map()));
1171  // In the assert below Dictionary is covered under FixedArray.
1172  ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1173         value->IsExternalArray());
1174  WRITE_FIELD(this, kElementsOffset, value);
1175  CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1176}
1177
1178
1179void JSObject::initialize_properties() {
1180  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1181  WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1182}
1183
1184
1185void JSObject::initialize_elements() {
1186  ASSERT(map()->has_fast_elements());
1187  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1188  WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1189}
1190
1191
1192Object* JSObject::ResetElements() {
1193  Object* obj = map()->GetFastElementsMap();
1194  if (obj->IsFailure()) return obj;
1195  set_map(Map::cast(obj));
1196  initialize_elements();
1197  return this;
1198}
1199
1200
1201ACCESSORS(Oddball, to_string, String, kToStringOffset)
1202ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1203
1204
1205Object* JSGlobalPropertyCell::value() {
1206  return READ_FIELD(this, kValueOffset);
1207}
1208
1209
1210void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1211  // The write barrier is not used for global property cells.
1212  ASSERT(!val->IsJSGlobalPropertyCell());
1213  WRITE_FIELD(this, kValueOffset, val);
1214}
1215
1216
1217int JSObject::GetHeaderSize() {
1218  InstanceType type = map()->instance_type();
1219  // Check for the most common kind of JavaScript object before
1220  // falling into the generic switch. This speeds up the internal
1221  // field operations considerably on average.
1222  if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1223  switch (type) {
1224    case JS_GLOBAL_PROXY_TYPE:
1225      return JSGlobalProxy::kSize;
1226    case JS_GLOBAL_OBJECT_TYPE:
1227      return JSGlobalObject::kSize;
1228    case JS_BUILTINS_OBJECT_TYPE:
1229      return JSBuiltinsObject::kSize;
1230    case JS_FUNCTION_TYPE:
1231      return JSFunction::kSize;
1232    case JS_VALUE_TYPE:
1233      return JSValue::kSize;
1234    case JS_ARRAY_TYPE:
1235      return JSValue::kSize;
1236    case JS_REGEXP_TYPE:
1237      return JSValue::kSize;
1238    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1239      return JSObject::kHeaderSize;
1240    default:
1241      UNREACHABLE();
1242      return 0;
1243  }
1244}
1245
1246
1247int JSObject::GetInternalFieldCount() {
1248  ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1249  // Make sure to adjust for the number of in-object properties. These
1250  // properties do contribute to the size, but are not internal fields.
1251  return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1252         map()->inobject_properties();
1253}
1254
1255
1256Object* JSObject::GetInternalField(int index) {
1257  ASSERT(index < GetInternalFieldCount() && index >= 0);
1258  // Internal objects do follow immediately after the header, whereas in-object
1259  // properties are at the end of the object. Therefore there is no need
1260  // to adjust the index here.
1261  return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1262}
1263
1264
1265void JSObject::SetInternalField(int index, Object* value) {
1266  ASSERT(index < GetInternalFieldCount() && index >= 0);
1267  // Internal objects do follow immediately after the header, whereas in-object
1268  // properties are at the end of the object. Therefore there is no need
1269  // to adjust the index here.
1270  int offset = GetHeaderSize() + (kPointerSize * index);
1271  WRITE_FIELD(this, offset, value);
1272  WRITE_BARRIER(this, offset);
1273}
1274
1275
1276// Access fast-case object properties at index. The use of these routines
1277// is needed to correctly distinguish between properties stored in-object and
1278// properties stored in the properties array.
1279Object* JSObject::FastPropertyAt(int index) {
1280  // Adjust for the number of properties stored in the object.
1281  index -= map()->inobject_properties();
1282  if (index < 0) {
1283    int offset = map()->instance_size() + (index * kPointerSize);
1284    return READ_FIELD(this, offset);
1285  } else {
1286    ASSERT(index < properties()->length());
1287    return properties()->get(index);
1288  }
1289}
1290
1291
1292Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1293  // Adjust for the number of properties stored in the object.
1294  index -= map()->inobject_properties();
1295  if (index < 0) {
1296    int offset = map()->instance_size() + (index * kPointerSize);
1297    WRITE_FIELD(this, offset, value);
1298    WRITE_BARRIER(this, offset);
1299  } else {
1300    ASSERT(index < properties()->length());
1301    properties()->set(index, value);
1302  }
1303  return value;
1304}
1305
1306
1307Object* JSObject::InObjectPropertyAt(int index) {
1308  // Adjust for the number of properties stored in the object.
1309  index -= map()->inobject_properties();
1310  ASSERT(index < 0);
1311  int offset = map()->instance_size() + (index * kPointerSize);
1312  return READ_FIELD(this, offset);
1313}
1314
1315
1316Object* JSObject::InObjectPropertyAtPut(int index,
1317                                        Object* value,
1318                                        WriteBarrierMode mode) {
1319  // Adjust for the number of properties stored in the object.
1320  index -= map()->inobject_properties();
1321  ASSERT(index < 0);
1322  int offset = map()->instance_size() + (index * kPointerSize);
1323  WRITE_FIELD(this, offset, value);
1324  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1325  return value;
1326}
1327
1328
1329
1330void JSObject::InitializeBody(int object_size, Object* value) {
1331  ASSERT(!value->IsHeapObject() || !Heap::InNewSpace(value));
1332  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1333    WRITE_FIELD(this, offset, value);
1334  }
1335}
1336
1337
1338bool JSObject::HasFastProperties() {
1339  return !properties()->IsDictionary();
1340}
1341
1342
1343int JSObject::MaxFastProperties() {
1344  // Allow extra fast properties if the object has more than
1345  // kMaxFastProperties in-object properties. When this is the case,
1346  // it is very unlikely that the object is being used as a dictionary
1347  // and there is a good chance that allowing more map transitions
1348  // will be worth it.
1349  return Max(map()->inobject_properties(), kMaxFastProperties);
1350}
1351
1352
1353void Struct::InitializeBody(int object_size) {
1354  Object* value = Heap::undefined_value();
1355  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1356    WRITE_FIELD(this, offset, value);
1357  }
1358}
1359
1360
1361bool Object::ToArrayIndex(uint32_t* index) {
1362  if (IsSmi()) {
1363    int value = Smi::cast(this)->value();
1364    if (value < 0) return false;
1365    *index = value;
1366    return true;
1367  }
1368  if (IsHeapNumber()) {
1369    double value = HeapNumber::cast(this)->value();
1370    uint32_t uint_value = static_cast<uint32_t>(value);
1371    if (value == static_cast<double>(uint_value)) {
1372      *index = uint_value;
1373      return true;
1374    }
1375  }
1376  return false;
1377}
1378
1379
1380bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1381  if (!this->IsJSValue()) return false;
1382
1383  JSValue* js_value = JSValue::cast(this);
1384  if (!js_value->value()->IsString()) return false;
1385
1386  String* str = String::cast(js_value->value());
1387  if (index >= (uint32_t)str->length()) return false;
1388
1389  return true;
1390}
1391
1392
1393Object* FixedArray::get(int index) {
1394  ASSERT(index >= 0 && index < this->length());
1395  return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1396}
1397
1398
1399void FixedArray::set(int index, Smi* value) {
1400  ASSERT(map() != Heap::fixed_cow_array_map());
1401  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1402  int offset = kHeaderSize + index * kPointerSize;
1403  WRITE_FIELD(this, offset, value);
1404}
1405
1406
1407void FixedArray::set(int index, Object* value) {
1408  ASSERT(map() != Heap::fixed_cow_array_map());
1409  ASSERT(index >= 0 && index < this->length());
1410  int offset = kHeaderSize + index * kPointerSize;
1411  WRITE_FIELD(this, offset, value);
1412  WRITE_BARRIER(this, offset);
1413}
1414
1415
1416WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1417  if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1418  return UPDATE_WRITE_BARRIER;
1419}
1420
1421
1422void FixedArray::set(int index,
1423                     Object* value,
1424                     WriteBarrierMode mode) {
1425  ASSERT(map() != Heap::fixed_cow_array_map());
1426  ASSERT(index >= 0 && index < this->length());
1427  int offset = kHeaderSize + index * kPointerSize;
1428  WRITE_FIELD(this, offset, value);
1429  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1430}
1431
1432
1433void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1434  ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
1435  ASSERT(index >= 0 && index < array->length());
1436  ASSERT(!Heap::InNewSpace(value));
1437  WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1438}
1439
1440
1441void FixedArray::set_undefined(int index) {
1442  ASSERT(map() != Heap::fixed_cow_array_map());
1443  ASSERT(index >= 0 && index < this->length());
1444  ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1445  WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1446              Heap::undefined_value());
1447}
1448
1449
1450void FixedArray::set_null(int index) {
1451  ASSERT(map() != Heap::fixed_cow_array_map());
1452  ASSERT(index >= 0 && index < this->length());
1453  ASSERT(!Heap::InNewSpace(Heap::null_value()));
1454  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1455}
1456
1457
1458void FixedArray::set_the_hole(int index) {
1459  ASSERT(map() != Heap::fixed_cow_array_map());
1460  ASSERT(index >= 0 && index < this->length());
1461  ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1462  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1463}
1464
1465
1466void FixedArray::set_unchecked(int index, Smi* value) {
1467  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1468  int offset = kHeaderSize + index * kPointerSize;
1469  WRITE_FIELD(this, offset, value);
1470}
1471
1472
1473void FixedArray::set_unchecked(int index,
1474                               Object* value,
1475                               WriteBarrierMode mode) {
1476  int offset = kHeaderSize + index * kPointerSize;
1477  WRITE_FIELD(this, offset, value);
1478  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1479}
1480
1481
1482void FixedArray::set_null_unchecked(int index) {
1483  ASSERT(index >= 0 && index < this->length());
1484  ASSERT(!Heap::InNewSpace(Heap::null_value()));
1485  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1486}
1487
1488
1489Object** FixedArray::data_start() {
1490  return HeapObject::RawField(this, kHeaderSize);
1491}
1492
1493
1494bool DescriptorArray::IsEmpty() {
1495  ASSERT(this == Heap::empty_descriptor_array() ||
1496         this->length() > 2);
1497  return this == Heap::empty_descriptor_array();
1498}
1499
1500
1501void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1502  Object* tmp = array->get(first);
1503  fast_set(array, first, array->get(second));
1504  fast_set(array, second, tmp);
1505}
1506
1507
1508int DescriptorArray::Search(String* name) {
1509  SLOW_ASSERT(IsSortedNoDuplicates());
1510
1511  // Check for empty descriptor array.
1512  int nof = number_of_descriptors();
1513  if (nof == 0) return kNotFound;
1514
1515  // Fast case: do linear search for small arrays.
1516  const int kMaxElementsForLinearSearch = 8;
1517  if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1518    return LinearSearch(name, nof);
1519  }
1520
1521  // Slow case: perform binary search.
1522  return BinarySearch(name, 0, nof - 1);
1523}
1524
1525
1526int DescriptorArray::SearchWithCache(String* name) {
1527  int number = DescriptorLookupCache::Lookup(this, name);
1528  if (number == DescriptorLookupCache::kAbsent) {
1529    number = Search(name);
1530    DescriptorLookupCache::Update(this, name, number);
1531  }
1532  return number;
1533}
1534
1535
1536String* DescriptorArray::GetKey(int descriptor_number) {
1537  ASSERT(descriptor_number < number_of_descriptors());
1538  return String::cast(get(ToKeyIndex(descriptor_number)));
1539}
1540
1541
1542Object* DescriptorArray::GetValue(int descriptor_number) {
1543  ASSERT(descriptor_number < number_of_descriptors());
1544  return GetContentArray()->get(ToValueIndex(descriptor_number));
1545}
1546
1547
1548Smi* DescriptorArray::GetDetails(int descriptor_number) {
1549  ASSERT(descriptor_number < number_of_descriptors());
1550  return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1551}
1552
1553
1554PropertyType DescriptorArray::GetType(int descriptor_number) {
1555  ASSERT(descriptor_number < number_of_descriptors());
1556  return PropertyDetails(GetDetails(descriptor_number)).type();
1557}
1558
1559
1560int DescriptorArray::GetFieldIndex(int descriptor_number) {
1561  return Descriptor::IndexFromValue(GetValue(descriptor_number));
1562}
1563
1564
1565JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1566  return JSFunction::cast(GetValue(descriptor_number));
1567}
1568
1569
1570Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1571  ASSERT(GetType(descriptor_number) == CALLBACKS);
1572  return GetValue(descriptor_number);
1573}
1574
1575
1576AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1577  ASSERT(GetType(descriptor_number) == CALLBACKS);
1578  Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1579  return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1580}
1581
1582
1583bool DescriptorArray::IsProperty(int descriptor_number) {
1584  return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1585}
1586
1587
1588bool DescriptorArray::IsTransition(int descriptor_number) {
1589  PropertyType t = GetType(descriptor_number);
1590  return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1591}
1592
1593
1594bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1595  return GetType(descriptor_number) == NULL_DESCRIPTOR;
1596}
1597
1598
1599bool DescriptorArray::IsDontEnum(int descriptor_number) {
1600  return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1601}
1602
1603
1604void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1605  desc->Init(GetKey(descriptor_number),
1606             GetValue(descriptor_number),
1607             GetDetails(descriptor_number));
1608}
1609
1610
1611void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1612  // Range check.
1613  ASSERT(descriptor_number < number_of_descriptors());
1614
1615  // Make sure none of the elements in desc are in new space.
1616  ASSERT(!Heap::InNewSpace(desc->GetKey()));
1617  ASSERT(!Heap::InNewSpace(desc->GetValue()));
1618
1619  fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1620  FixedArray* content_array = GetContentArray();
1621  fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1622  fast_set(content_array, ToDetailsIndex(descriptor_number),
1623           desc->GetDetails().AsSmi());
1624}
1625
1626
1627void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1628  Descriptor desc;
1629  src->Get(src_index, &desc);
1630  Set(index, &desc);
1631}
1632
1633
1634void DescriptorArray::Swap(int first, int second) {
1635  fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1636  FixedArray* content_array = GetContentArray();
1637  fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1638  fast_swap(content_array, ToDetailsIndex(first),  ToDetailsIndex(second));
1639}
1640
1641
1642bool NumberDictionary::requires_slow_elements() {
1643  Object* max_index_object = get(kMaxNumberKeyIndex);
1644  if (!max_index_object->IsSmi()) return false;
1645  return 0 !=
1646      (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1647}
1648
1649uint32_t NumberDictionary::max_number_key() {
1650  ASSERT(!requires_slow_elements());
1651  Object* max_index_object = get(kMaxNumberKeyIndex);
1652  if (!max_index_object->IsSmi()) return 0;
1653  uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1654  return value >> kRequiresSlowElementsTagSize;
1655}
1656
1657void NumberDictionary::set_requires_slow_elements() {
1658  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
1659}
1660
1661
1662// ------------------------------------
1663// Cast operations
1664
1665
1666CAST_ACCESSOR(FixedArray)
1667CAST_ACCESSOR(DescriptorArray)
1668CAST_ACCESSOR(SymbolTable)
1669CAST_ACCESSOR(JSFunctionResultCache)
1670CAST_ACCESSOR(NormalizedMapCache)
1671CAST_ACCESSOR(CompilationCacheTable)
1672CAST_ACCESSOR(CodeCacheHashTable)
1673CAST_ACCESSOR(MapCache)
1674CAST_ACCESSOR(String)
1675CAST_ACCESSOR(SeqString)
1676CAST_ACCESSOR(SeqAsciiString)
1677CAST_ACCESSOR(SeqTwoByteString)
1678CAST_ACCESSOR(ConsString)
1679CAST_ACCESSOR(ExternalString)
1680CAST_ACCESSOR(ExternalAsciiString)
1681CAST_ACCESSOR(ExternalTwoByteString)
1682CAST_ACCESSOR(JSObject)
1683CAST_ACCESSOR(Smi)
1684CAST_ACCESSOR(Failure)
1685CAST_ACCESSOR(HeapObject)
1686CAST_ACCESSOR(HeapNumber)
1687CAST_ACCESSOR(Oddball)
1688CAST_ACCESSOR(JSGlobalPropertyCell)
1689CAST_ACCESSOR(SharedFunctionInfo)
1690CAST_ACCESSOR(Map)
1691CAST_ACCESSOR(JSFunction)
1692CAST_ACCESSOR(GlobalObject)
1693CAST_ACCESSOR(JSGlobalProxy)
1694CAST_ACCESSOR(JSGlobalObject)
1695CAST_ACCESSOR(JSBuiltinsObject)
1696CAST_ACCESSOR(Code)
1697CAST_ACCESSOR(JSArray)
1698CAST_ACCESSOR(JSRegExp)
1699CAST_ACCESSOR(Proxy)
1700CAST_ACCESSOR(ByteArray)
1701CAST_ACCESSOR(PixelArray)
1702CAST_ACCESSOR(ExternalArray)
1703CAST_ACCESSOR(ExternalByteArray)
1704CAST_ACCESSOR(ExternalUnsignedByteArray)
1705CAST_ACCESSOR(ExternalShortArray)
1706CAST_ACCESSOR(ExternalUnsignedShortArray)
1707CAST_ACCESSOR(ExternalIntArray)
1708CAST_ACCESSOR(ExternalUnsignedIntArray)
1709CAST_ACCESSOR(ExternalFloatArray)
1710CAST_ACCESSOR(Struct)
1711
1712
1713#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1714  STRUCT_LIST(MAKE_STRUCT_CAST)
1715#undef MAKE_STRUCT_CAST
1716
1717
1718template <typename Shape, typename Key>
1719HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1720  ASSERT(obj->IsHashTable());
1721  return reinterpret_cast<HashTable*>(obj);
1722}
1723
1724
1725SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1726SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1727
1728INT_ACCESSORS(PixelArray, length, kLengthOffset)
1729INT_ACCESSORS(ExternalArray, length, kLengthOffset)
1730
1731
1732SMI_ACCESSORS(String, length, kLengthOffset)
1733
1734
1735uint32_t String::hash_field() {
1736  return READ_UINT32_FIELD(this, kHashFieldOffset);
1737}
1738
1739
1740void String::set_hash_field(uint32_t value) {
1741  WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1742#if V8_HOST_ARCH_64_BIT
1743  WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1744#endif
1745}
1746
1747
1748bool String::Equals(String* other) {
1749  if (other == this) return true;
1750  if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1751    return false;
1752  }
1753  return SlowEquals(other);
1754}
1755
1756
1757Object* String::TryFlatten(PretenureFlag pretenure) {
1758  if (!StringShape(this).IsCons()) return this;
1759  ConsString* cons = ConsString::cast(this);
1760  if (cons->second()->length() == 0) return cons->first();
1761  return SlowTryFlatten(pretenure);
1762}
1763
1764
1765String* String::TryFlattenGetString(PretenureFlag pretenure) {
1766  Object* flat = TryFlatten(pretenure);
1767  return flat->IsFailure() ? this : String::cast(flat);
1768}
1769
1770
1771uint16_t String::Get(int index) {
1772  ASSERT(index >= 0 && index < length());
1773  switch (StringShape(this).full_representation_tag()) {
1774    case kSeqStringTag | kAsciiStringTag:
1775      return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1776    case kSeqStringTag | kTwoByteStringTag:
1777      return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1778    case kConsStringTag | kAsciiStringTag:
1779    case kConsStringTag | kTwoByteStringTag:
1780      return ConsString::cast(this)->ConsStringGet(index);
1781    case kExternalStringTag | kAsciiStringTag:
1782      return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1783    case kExternalStringTag | kTwoByteStringTag:
1784      return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1785    default:
1786      break;
1787  }
1788
1789  UNREACHABLE();
1790  return 0;
1791}
1792
1793
1794void String::Set(int index, uint16_t value) {
1795  ASSERT(index >= 0 && index < length());
1796  ASSERT(StringShape(this).IsSequential());
1797
1798  return this->IsAsciiRepresentation()
1799      ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1800      : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1801}
1802
1803
1804bool String::IsFlat() {
1805  switch (StringShape(this).representation_tag()) {
1806    case kConsStringTag: {
1807      String* second = ConsString::cast(this)->second();
1808      // Only flattened strings have second part empty.
1809      return second->length() == 0;
1810    }
1811    default:
1812      return true;
1813  }
1814}
1815
1816
1817uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1818  ASSERT(index >= 0 && index < length());
1819  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1820}
1821
1822
1823void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1824  ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1825  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1826                   static_cast<byte>(value));
1827}
1828
1829
1830Address SeqAsciiString::GetCharsAddress() {
1831  return FIELD_ADDR(this, kHeaderSize);
1832}
1833
1834
1835char* SeqAsciiString::GetChars() {
1836  return reinterpret_cast<char*>(GetCharsAddress());
1837}
1838
1839
1840Address SeqTwoByteString::GetCharsAddress() {
1841  return FIELD_ADDR(this, kHeaderSize);
1842}
1843
1844
1845uc16* SeqTwoByteString::GetChars() {
1846  return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1847}
1848
1849
1850uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1851  ASSERT(index >= 0 && index < length());
1852  return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1853}
1854
1855
1856void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1857  ASSERT(index >= 0 && index < length());
1858  WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1859}
1860
1861
1862int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1863  return SizeFor(length());
1864}
1865
1866
1867int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1868  return SizeFor(length());
1869}
1870
1871
1872String* ConsString::first() {
1873  return String::cast(READ_FIELD(this, kFirstOffset));
1874}
1875
1876
1877Object* ConsString::unchecked_first() {
1878  return READ_FIELD(this, kFirstOffset);
1879}
1880
1881
1882void ConsString::set_first(String* value, WriteBarrierMode mode) {
1883  WRITE_FIELD(this, kFirstOffset, value);
1884  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1885}
1886
1887
1888String* ConsString::second() {
1889  return String::cast(READ_FIELD(this, kSecondOffset));
1890}
1891
1892
1893Object* ConsString::unchecked_second() {
1894  return READ_FIELD(this, kSecondOffset);
1895}
1896
1897
1898void ConsString::set_second(String* value, WriteBarrierMode mode) {
1899  WRITE_FIELD(this, kSecondOffset, value);
1900  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1901}
1902
1903
1904ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1905  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1906}
1907
1908
1909void ExternalAsciiString::set_resource(
1910    ExternalAsciiString::Resource* resource) {
1911  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1912}
1913
1914
1915ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1916  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1917}
1918
1919
1920void ExternalTwoByteString::set_resource(
1921    ExternalTwoByteString::Resource* resource) {
1922  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1923}
1924
1925
1926void JSFunctionResultCache::MakeZeroSize() {
1927  set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1928  set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1929}
1930
1931
1932void JSFunctionResultCache::Clear() {
1933  int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1934  Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1935  MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1936  MakeZeroSize();
1937}
1938
1939
1940byte ByteArray::get(int index) {
1941  ASSERT(index >= 0 && index < this->length());
1942  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1943}
1944
1945
1946void ByteArray::set(int index, byte value) {
1947  ASSERT(index >= 0 && index < this->length());
1948  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1949}
1950
1951
1952int ByteArray::get_int(int index) {
1953  ASSERT(index >= 0 && (index * kIntSize) < this->length());
1954  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1955}
1956
1957
1958ByteArray* ByteArray::FromDataStartAddress(Address address) {
1959  ASSERT_TAG_ALIGNED(address);
1960  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1961}
1962
1963
1964Address ByteArray::GetDataStartAddress() {
1965  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1966}
1967
1968
1969uint8_t* PixelArray::external_pointer() {
1970  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1971  return reinterpret_cast<uint8_t*>(ptr);
1972}
1973
1974
1975void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1976  intptr_t ptr = reinterpret_cast<intptr_t>(value);
1977  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1978}
1979
1980
1981uint8_t PixelArray::get(int index) {
1982  ASSERT((index >= 0) && (index < this->length()));
1983  uint8_t* ptr = external_pointer();
1984  return ptr[index];
1985}
1986
1987
1988void PixelArray::set(int index, uint8_t value) {
1989  ASSERT((index >= 0) && (index < this->length()));
1990  uint8_t* ptr = external_pointer();
1991  ptr[index] = value;
1992}
1993
1994
1995void* ExternalArray::external_pointer() {
1996  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1997  return reinterpret_cast<void*>(ptr);
1998}
1999
2000
2001void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2002  intptr_t ptr = reinterpret_cast<intptr_t>(value);
2003  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2004}
2005
2006
2007int8_t ExternalByteArray::get(int index) {
2008  ASSERT((index >= 0) && (index < this->length()));
2009  int8_t* ptr = static_cast<int8_t*>(external_pointer());
2010  return ptr[index];
2011}
2012
2013
2014void ExternalByteArray::set(int index, int8_t value) {
2015  ASSERT((index >= 0) && (index < this->length()));
2016  int8_t* ptr = static_cast<int8_t*>(external_pointer());
2017  ptr[index] = value;
2018}
2019
2020
2021uint8_t ExternalUnsignedByteArray::get(int index) {
2022  ASSERT((index >= 0) && (index < this->length()));
2023  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2024  return ptr[index];
2025}
2026
2027
2028void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2029  ASSERT((index >= 0) && (index < this->length()));
2030  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2031  ptr[index] = value;
2032}
2033
2034
2035int16_t ExternalShortArray::get(int index) {
2036  ASSERT((index >= 0) && (index < this->length()));
2037  int16_t* ptr = static_cast<int16_t*>(external_pointer());
2038  return ptr[index];
2039}
2040
2041
2042void ExternalShortArray::set(int index, int16_t value) {
2043  ASSERT((index >= 0) && (index < this->length()));
2044  int16_t* ptr = static_cast<int16_t*>(external_pointer());
2045  ptr[index] = value;
2046}
2047
2048
2049uint16_t ExternalUnsignedShortArray::get(int index) {
2050  ASSERT((index >= 0) && (index < this->length()));
2051  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2052  return ptr[index];
2053}
2054
2055
2056void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2057  ASSERT((index >= 0) && (index < this->length()));
2058  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2059  ptr[index] = value;
2060}
2061
2062
2063int32_t ExternalIntArray::get(int index) {
2064  ASSERT((index >= 0) && (index < this->length()));
2065  int32_t* ptr = static_cast<int32_t*>(external_pointer());
2066  return ptr[index];
2067}
2068
2069
2070void ExternalIntArray::set(int index, int32_t value) {
2071  ASSERT((index >= 0) && (index < this->length()));
2072  int32_t* ptr = static_cast<int32_t*>(external_pointer());
2073  ptr[index] = value;
2074}
2075
2076
2077uint32_t ExternalUnsignedIntArray::get(int index) {
2078  ASSERT((index >= 0) && (index < this->length()));
2079  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2080  return ptr[index];
2081}
2082
2083
2084void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2085  ASSERT((index >= 0) && (index < this->length()));
2086  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2087  ptr[index] = value;
2088}
2089
2090
2091float ExternalFloatArray::get(int index) {
2092  ASSERT((index >= 0) && (index < this->length()));
2093  float* ptr = static_cast<float*>(external_pointer());
2094  return ptr[index];
2095}
2096
2097
2098void ExternalFloatArray::set(int index, float value) {
2099  ASSERT((index >= 0) && (index < this->length()));
2100  float* ptr = static_cast<float*>(external_pointer());
2101  ptr[index] = value;
2102}
2103
2104
2105int Map::visitor_id() {
2106  return READ_BYTE_FIELD(this, kVisitorIdOffset);
2107}
2108
2109
2110void Map::set_visitor_id(int id) {
2111  ASSERT(0 <= id && id < 256);
2112  WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2113}
2114
2115
2116int Map::instance_size() {
2117  return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2118}
2119
2120
2121int Map::inobject_properties() {
2122  return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2123}
2124
2125
2126int Map::pre_allocated_property_fields() {
2127  return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2128}
2129
2130
2131int HeapObject::SizeFromMap(Map* map) {
2132  int instance_size = map->instance_size();
2133  if (instance_size != kVariableSizeSentinel) return instance_size;
2134  // We can ignore the "symbol" bit becase it is only set for symbols
2135  // and implies a string type.
2136  int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2137  // Only inline the most frequent cases.
2138  if (instance_type == FIXED_ARRAY_TYPE) {
2139    return FixedArray::BodyDescriptor::SizeOf(map, this);
2140  }
2141  if (instance_type == ASCII_STRING_TYPE) {
2142    return SeqAsciiString::SizeFor(
2143        reinterpret_cast<SeqAsciiString*>(this)->length());
2144  }
2145  if (instance_type == BYTE_ARRAY_TYPE) {
2146    return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2147  }
2148  if (instance_type == STRING_TYPE) {
2149    return SeqTwoByteString::SizeFor(
2150        reinterpret_cast<SeqTwoByteString*>(this)->length());
2151  }
2152  ASSERT(instance_type == CODE_TYPE);
2153  return reinterpret_cast<Code*>(this)->CodeSize();
2154}
2155
2156
2157void Map::set_instance_size(int value) {
2158  ASSERT_EQ(0, value & (kPointerSize - 1));
2159  value >>= kPointerSizeLog2;
2160  ASSERT(0 <= value && value < 256);
2161  WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2162}
2163
2164
2165void Map::set_inobject_properties(int value) {
2166  ASSERT(0 <= value && value < 256);
2167  WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2168}
2169
2170
2171void Map::set_pre_allocated_property_fields(int value) {
2172  ASSERT(0 <= value && value < 256);
2173  WRITE_BYTE_FIELD(this,
2174                   kPreAllocatedPropertyFieldsOffset,
2175                   static_cast<byte>(value));
2176}
2177
2178
2179InstanceType Map::instance_type() {
2180  return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2181}
2182
2183
2184void Map::set_instance_type(InstanceType value) {
2185  ASSERT(0 <= value && value < 256);
2186  WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2187}
2188
2189
2190int Map::unused_property_fields() {
2191  return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2192}
2193
2194
2195void Map::set_unused_property_fields(int value) {
2196  WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2197}
2198
2199
2200byte Map::bit_field() {
2201  return READ_BYTE_FIELD(this, kBitFieldOffset);
2202}
2203
2204
2205void Map::set_bit_field(byte value) {
2206  WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2207}
2208
2209
2210byte Map::bit_field2() {
2211  return READ_BYTE_FIELD(this, kBitField2Offset);
2212}
2213
2214
2215void Map::set_bit_field2(byte value) {
2216  WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2217}
2218
2219
2220void Map::set_non_instance_prototype(bool value) {
2221  if (value) {
2222    set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2223  } else {
2224    set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2225  }
2226}
2227
2228
2229bool Map::has_non_instance_prototype() {
2230  return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2231}
2232
2233
2234void Map::set_function_with_prototype(bool value) {
2235  if (value) {
2236    set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2237  } else {
2238    set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2239  }
2240}
2241
2242
2243bool Map::function_with_prototype() {
2244  return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2245}
2246
2247
2248void Map::set_is_access_check_needed(bool access_check_needed) {
2249  if (access_check_needed) {
2250    set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2251  } else {
2252    set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2253  }
2254}
2255
2256
2257bool Map::is_access_check_needed() {
2258  return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2259}
2260
2261
2262void Map::set_is_extensible(bool value) {
2263  if (value) {
2264    set_bit_field2(bit_field2() | (1 << kIsExtensible));
2265  } else {
2266    set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2267  }
2268}
2269
2270bool Map::is_extensible() {
2271  return ((1 << kIsExtensible) & bit_field2()) != 0;
2272}
2273
2274
2275void Map::set_attached_to_shared_function_info(bool value) {
2276  if (value) {
2277    set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2278  } else {
2279    set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2280  }
2281}
2282
2283bool Map::attached_to_shared_function_info() {
2284  return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2285}
2286
2287
2288void Map::set_is_shared(bool value) {
2289  if (value) {
2290    set_bit_field2(bit_field2() | (1 << kIsShared));
2291  } else {
2292    set_bit_field2(bit_field2() & ~(1 << kIsShared));
2293  }
2294}
2295
2296bool Map::is_shared() {
2297  return ((1 << kIsShared) & bit_field2()) != 0;
2298}
2299
2300
2301JSFunction* Map::unchecked_constructor() {
2302  return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2303}
2304
2305
2306Code::Flags Code::flags() {
2307  return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2308}
2309
2310
2311void Code::set_flags(Code::Flags flags) {
2312  STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2313  // Make sure that all call stubs have an arguments count.
2314  ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2315          ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2316         ExtractArgumentsCountFromFlags(flags) >= 0);
2317  WRITE_INT_FIELD(this, kFlagsOffset, flags);
2318}
2319
2320
2321Code::Kind Code::kind() {
2322  return ExtractKindFromFlags(flags());
2323}
2324
2325
2326InLoopFlag Code::ic_in_loop() {
2327  return ExtractICInLoopFromFlags(flags());
2328}
2329
2330
2331InlineCacheState Code::ic_state() {
2332  InlineCacheState result = ExtractICStateFromFlags(flags());
2333  // Only allow uninitialized or debugger states for non-IC code
2334  // objects. This is used in the debugger to determine whether or not
2335  // a call to code object has been replaced with a debug break call.
2336  ASSERT(is_inline_cache_stub() ||
2337         result == UNINITIALIZED ||
2338         result == DEBUG_BREAK ||
2339         result == DEBUG_PREPARE_STEP_IN);
2340  return result;
2341}
2342
2343
2344PropertyType Code::type() {
2345  ASSERT(ic_state() == MONOMORPHIC);
2346  return ExtractTypeFromFlags(flags());
2347}
2348
2349
2350int Code::arguments_count() {
2351  ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2352  return ExtractArgumentsCountFromFlags(flags());
2353}
2354
2355
2356int Code::major_key() {
2357  ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
2358  return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2359}
2360
2361
2362void Code::set_major_key(int major) {
2363  ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
2364  ASSERT(0 <= major && major < 256);
2365  WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2366}
2367
2368
2369bool Code::is_inline_cache_stub() {
2370  Kind kind = this->kind();
2371  return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2372}
2373
2374
2375Code::Flags Code::ComputeFlags(Kind kind,
2376                               InLoopFlag in_loop,
2377                               InlineCacheState ic_state,
2378                               PropertyType type,
2379                               int argc,
2380                               InlineCacheHolderFlag holder) {
2381  // Compute the bit mask.
2382  int bits = kind << kFlagsKindShift;
2383  if (in_loop) bits |= kFlagsICInLoopMask;
2384  bits |= ic_state << kFlagsICStateShift;
2385  bits |= type << kFlagsTypeShift;
2386  bits |= argc << kFlagsArgumentsCountShift;
2387  if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
2388  // Cast to flags and validate result before returning it.
2389  Flags result = static_cast<Flags>(bits);
2390  ASSERT(ExtractKindFromFlags(result) == kind);
2391  ASSERT(ExtractICStateFromFlags(result) == ic_state);
2392  ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2393  ASSERT(ExtractTypeFromFlags(result) == type);
2394  ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2395  return result;
2396}
2397
2398
2399Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2400                                          PropertyType type,
2401                                          InlineCacheHolderFlag holder,
2402                                          InLoopFlag in_loop,
2403                                          int argc) {
2404  return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
2405}
2406
2407
2408Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2409  int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2410  return static_cast<Kind>(bits);
2411}
2412
2413
2414InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2415  int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2416  return static_cast<InlineCacheState>(bits);
2417}
2418
2419
2420InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2421  int bits = (flags & kFlagsICInLoopMask);
2422  return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2423}
2424
2425
2426PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2427  int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2428  return static_cast<PropertyType>(bits);
2429}
2430
2431
2432int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2433  return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2434}
2435
2436
2437InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2438  int bits = (flags & kFlagsCacheInPrototypeMapMask);
2439  return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2440}
2441
2442
2443Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2444  int bits = flags & ~kFlagsTypeMask;
2445  return static_cast<Flags>(bits);
2446}
2447
2448
2449Code* Code::GetCodeFromTargetAddress(Address address) {
2450  HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2451  // GetCodeFromTargetAddress might be called when marking objects during mark
2452  // sweep. reinterpret_cast is therefore used instead of the more appropriate
2453  // Code::cast. Code::cast does not work when the object's map is
2454  // marked.
2455  Code* result = reinterpret_cast<Code*>(code);
2456  return result;
2457}
2458
2459
2460Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2461  return HeapObject::
2462      FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2463}
2464
2465
2466Object* Map::prototype() {
2467  return READ_FIELD(this, kPrototypeOffset);
2468}
2469
2470
2471void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2472  ASSERT(value->IsNull() || value->IsJSObject());
2473  WRITE_FIELD(this, kPrototypeOffset, value);
2474  CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2475}
2476
2477
2478Object* Map::GetFastElementsMap() {
2479  if (has_fast_elements()) return this;
2480  Object* obj = CopyDropTransitions();
2481  if (obj->IsFailure()) return obj;
2482  Map* new_map = Map::cast(obj);
2483  new_map->set_has_fast_elements(true);
2484  Counters::map_slow_to_fast_elements.Increment();
2485  return new_map;
2486}
2487
2488
2489Object* Map::GetSlowElementsMap() {
2490  if (!has_fast_elements()) return this;
2491  Object* obj = CopyDropTransitions();
2492  if (obj->IsFailure()) return obj;
2493  Map* new_map = Map::cast(obj);
2494  new_map->set_has_fast_elements(false);
2495  Counters::map_fast_to_slow_elements.Increment();
2496  return new_map;
2497}
2498
2499
2500ACCESSORS(Map, instance_descriptors, DescriptorArray,
2501          kInstanceDescriptorsOffset)
2502ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
2503ACCESSORS(Map, constructor, Object, kConstructorOffset)
2504
2505ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2506ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2507
2508ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2509ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2510ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2511
2512ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2513
2514ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2515ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2516ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2517ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2518ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2519ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
2520
2521ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2522ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2523ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2524
2525ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2526ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2527ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2528ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2529ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2530ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2531
2532ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2533ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2534
2535ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2536ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2537
2538ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2539ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2540ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2541          kPropertyAccessorsOffset)
2542ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2543          kPrototypeTemplateOffset)
2544ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2545ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2546          kNamedPropertyHandlerOffset)
2547ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2548          kIndexedPropertyHandlerOffset)
2549ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2550          kInstanceTemplateOffset)
2551ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2552ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2553ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2554          kInstanceCallHandlerOffset)
2555ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2556          kAccessCheckInfoOffset)
2557ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2558
2559ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2560ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2561          kInternalFieldCountOffset)
2562
2563ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2564ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2565
2566ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2567
2568ACCESSORS(Script, source, Object, kSourceOffset)
2569ACCESSORS(Script, name, Object, kNameOffset)
2570ACCESSORS(Script, id, Object, kIdOffset)
2571ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2572ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2573ACCESSORS(Script, data, Object, kDataOffset)
2574ACCESSORS(Script, context_data, Object, kContextOffset)
2575ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2576ACCESSORS(Script, type, Smi, kTypeOffset)
2577ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2578ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2579ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
2580ACCESSORS(Script, eval_from_instructions_offset, Smi,
2581          kEvalFrominstructionsOffsetOffset)
2582
2583#ifdef ENABLE_DEBUGGER_SUPPORT
2584ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2585ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2586ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2587ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2588
2589ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2590ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2591ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2592ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2593#endif
2594
2595ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2596ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2597ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
2598ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2599          kInstanceClassNameOffset)
2600ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
2601ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2602ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2603ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2604ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2605          kThisPropertyAssignmentsOffset)
2606
2607BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2608               kHiddenPrototypeBit)
2609BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2610BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2611               kNeedsAccessCheckBit)
2612BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2613               kIsExpressionBit)
2614BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2615               kIsTopLevelBit)
2616BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2617            has_only_simple_this_property_assignments,
2618            kHasOnlySimpleThisPropertyAssignments)
2619BOOL_ACCESSORS(SharedFunctionInfo,
2620               compiler_hints,
2621               try_full_codegen,
2622               kTryFullCodegen)
2623BOOL_ACCESSORS(SharedFunctionInfo,
2624               compiler_hints,
2625               allows_lazy_compilation,
2626               kAllowLazyCompilation)
2627
2628
2629#if V8_HOST_ARCH_32_BIT
2630SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2631SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2632              kFormalParameterCountOffset)
2633SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2634              kExpectedNofPropertiesOffset)
2635SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2636SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2637              kStartPositionAndTypeOffset)
2638SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2639SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
2640              kFunctionTokenPositionOffset)
2641SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
2642              kCompilerHintsOffset)
2643SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2644              kThisPropertyAssignmentsCountOffset)
2645#else
2646
2647#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
2648  int holder::name() {                                            \
2649    int value = READ_INT_FIELD(this, offset);                     \
2650    ASSERT(kHeapObjectTag == 1);                                  \
2651    ASSERT((value & kHeapObjectTag) == 0);                        \
2652    return value >> 1;                                            \
2653  }                                                               \
2654  void holder::set_##name(int value) {                            \
2655    ASSERT(kHeapObjectTag == 1);                                  \
2656    ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
2657           (value & 0xC0000000) == 0x000000000);                  \
2658    WRITE_INT_FIELD(this,                                         \
2659                    offset,                                       \
2660                    (value << 1) & ~kHeapObjectTag);              \
2661  }
2662
2663#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2664  INT_ACCESSORS(holder, name, offset)
2665
2666
2667
2668PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2669PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2670              kFormalParameterCountOffset)
2671
2672PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2673              kExpectedNofPropertiesOffset)
2674PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2675
2676PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2677              kStartPositionAndTypeOffset)
2678PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2679
2680PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2681              kFunctionTokenPositionOffset)
2682PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2683              kCompilerHintsOffset)
2684
2685PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2686              kThisPropertyAssignmentsCountOffset)
2687#endif
2688
2689
2690int SharedFunctionInfo::construction_count() {
2691  return READ_BYTE_FIELD(this, kConstructionCountOffset);
2692}
2693
2694
2695void SharedFunctionInfo::set_construction_count(int value) {
2696  ASSERT(0 <= value && value < 256);
2697  WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
2698}
2699
2700
2701bool SharedFunctionInfo::live_objects_may_exist() {
2702  return (compiler_hints() & (1 << kLiveObjectsMayExist)) != 0;
2703}
2704
2705
2706void SharedFunctionInfo::set_live_objects_may_exist(bool value) {
2707  if (value) {
2708    set_compiler_hints(compiler_hints() | (1 << kLiveObjectsMayExist));
2709  } else {
2710    set_compiler_hints(compiler_hints() & ~(1 << kLiveObjectsMayExist));
2711  }
2712}
2713
2714
2715bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
2716  return initial_map() != Heap::undefined_value();
2717}
2718
2719
2720ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2721ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2722
2723bool Script::HasValidSource() {
2724  Object* src = this->source();
2725  if (!src->IsString()) return true;
2726  String* src_str = String::cast(src);
2727  if (!StringShape(src_str).IsExternal()) return true;
2728  if (src_str->IsAsciiRepresentation()) {
2729    return ExternalAsciiString::cast(src)->resource() != NULL;
2730  } else if (src_str->IsTwoByteRepresentation()) {
2731    return ExternalTwoByteString::cast(src)->resource() != NULL;
2732  }
2733  return true;
2734}
2735
2736
2737void SharedFunctionInfo::DontAdaptArguments() {
2738  ASSERT(code()->kind() == Code::BUILTIN);
2739  set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2740}
2741
2742
2743int SharedFunctionInfo::start_position() {
2744  return start_position_and_type() >> kStartPositionShift;
2745}
2746
2747
2748void SharedFunctionInfo::set_start_position(int start_position) {
2749  set_start_position_and_type((start_position << kStartPositionShift)
2750    | (start_position_and_type() & ~kStartPositionMask));
2751}
2752
2753
2754Code* SharedFunctionInfo::code() {
2755  return Code::cast(READ_FIELD(this, kCodeOffset));
2756}
2757
2758
2759Code* SharedFunctionInfo::unchecked_code() {
2760  return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2761}
2762
2763
2764void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2765  WRITE_FIELD(this, kCodeOffset, value);
2766  CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2767}
2768
2769
2770SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2771  return reinterpret_cast<SerializedScopeInfo*>(
2772      READ_FIELD(this, kScopeInfoOffset));
2773}
2774
2775
2776void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2777                                        WriteBarrierMode mode) {
2778  WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2779  CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2780}
2781
2782
2783bool SharedFunctionInfo::is_compiled() {
2784  return code() != Builtins::builtin(Builtins::LazyCompile);
2785}
2786
2787
2788bool SharedFunctionInfo::IsApiFunction() {
2789  return function_data()->IsFunctionTemplateInfo();
2790}
2791
2792
2793FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2794  ASSERT(IsApiFunction());
2795  return FunctionTemplateInfo::cast(function_data());
2796}
2797
2798
2799bool SharedFunctionInfo::HasCustomCallGenerator() {
2800  return function_data()->IsSmi();
2801}
2802
2803
2804int SharedFunctionInfo::custom_call_generator_id() {
2805  ASSERT(HasCustomCallGenerator());
2806  return Smi::cast(function_data())->value();
2807}
2808
2809
2810int SharedFunctionInfo::code_age() {
2811  return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
2812}
2813
2814
2815void SharedFunctionInfo::set_code_age(int code_age) {
2816  set_compiler_hints(compiler_hints() |
2817                     ((code_age & kCodeAgeMask) << kCodeAgeShift));
2818}
2819
2820
2821bool JSFunction::IsBuiltin() {
2822  return context()->global()->IsJSBuiltinsObject();
2823}
2824
2825
2826Code* JSFunction::code() {
2827  return Code::cast(unchecked_code());
2828}
2829
2830
2831Code* JSFunction::unchecked_code() {
2832  return reinterpret_cast<Code*>(
2833      Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
2834}
2835
2836
2837void JSFunction::set_code(Code* value) {
2838  // Skip the write barrier because code is never in new space.
2839  ASSERT(!Heap::InNewSpace(value));
2840  Address entry = value->entry();
2841  WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
2842}
2843
2844
2845Context* JSFunction::context() {
2846  return Context::cast(READ_FIELD(this, kContextOffset));
2847}
2848
2849
2850Object* JSFunction::unchecked_context() {
2851  return READ_FIELD(this, kContextOffset);
2852}
2853
2854
2855SharedFunctionInfo* JSFunction::unchecked_shared() {
2856  return reinterpret_cast<SharedFunctionInfo*>(
2857      READ_FIELD(this, kSharedFunctionInfoOffset));
2858}
2859
2860
2861void JSFunction::set_context(Object* value) {
2862  ASSERT(value == Heap::undefined_value() || value->IsContext());
2863  WRITE_FIELD(this, kContextOffset, value);
2864  WRITE_BARRIER(this, kContextOffset);
2865}
2866
2867ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2868          kPrototypeOrInitialMapOffset)
2869
2870
2871Map* JSFunction::initial_map() {
2872  return Map::cast(prototype_or_initial_map());
2873}
2874
2875
2876void JSFunction::set_initial_map(Map* value) {
2877  set_prototype_or_initial_map(value);
2878}
2879
2880
2881bool JSFunction::has_initial_map() {
2882  return prototype_or_initial_map()->IsMap();
2883}
2884
2885
2886bool JSFunction::has_instance_prototype() {
2887  return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2888}
2889
2890
2891bool JSFunction::has_prototype() {
2892  return map()->has_non_instance_prototype() || has_instance_prototype();
2893}
2894
2895
2896Object* JSFunction::instance_prototype() {
2897  ASSERT(has_instance_prototype());
2898  if (has_initial_map()) return initial_map()->prototype();
2899  // When there is no initial map and the prototype is a JSObject, the
2900  // initial map field is used for the prototype field.
2901  return prototype_or_initial_map();
2902}
2903
2904
2905Object* JSFunction::prototype() {
2906  ASSERT(has_prototype());
2907  // If the function's prototype property has been set to a non-JSObject
2908  // value, that value is stored in the constructor field of the map.
2909  if (map()->has_non_instance_prototype()) return map()->constructor();
2910  return instance_prototype();
2911}
2912
2913bool JSFunction::should_have_prototype() {
2914  return map()->function_with_prototype();
2915}
2916
2917
2918bool JSFunction::is_compiled() {
2919  return code() != Builtins::builtin(Builtins::LazyCompile);
2920}
2921
2922
2923int JSFunction::NumberOfLiterals() {
2924  return literals()->length();
2925}
2926
2927
2928Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2929  ASSERT(0 <= id && id < kJSBuiltinsCount);
2930  return READ_FIELD(this, OffsetOfFunctionWithId(id));
2931}
2932
2933
2934void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2935                                              Object* value) {
2936  ASSERT(0 <= id && id < kJSBuiltinsCount);
2937  WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2938  WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2939}
2940
2941
2942Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2943  ASSERT(0 <= id && id < kJSBuiltinsCount);
2944  return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2945}
2946
2947
2948void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2949                                                   Code* value) {
2950  ASSERT(0 <= id && id < kJSBuiltinsCount);
2951  WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2952  ASSERT(!Heap::InNewSpace(value));
2953}
2954
2955
2956Address Proxy::proxy() {
2957  return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2958}
2959
2960
2961void Proxy::set_proxy(Address value) {
2962  WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2963}
2964
2965
2966ACCESSORS(JSValue, value, Object, kValueOffset)
2967
2968
2969JSValue* JSValue::cast(Object* obj) {
2970  ASSERT(obj->IsJSValue());
2971  ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2972  return reinterpret_cast<JSValue*>(obj);
2973}
2974
2975
2976INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2977ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
2978
2979
2980byte* Code::instruction_start()  {
2981  return FIELD_ADDR(this, kHeaderSize);
2982}
2983
2984
2985byte* Code::instruction_end()  {
2986  return instruction_start() + instruction_size();
2987}
2988
2989
2990int Code::body_size() {
2991  return RoundUp(instruction_size(), kObjectAlignment);
2992}
2993
2994
2995ByteArray* Code::unchecked_relocation_info() {
2996  return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
2997}
2998
2999
3000byte* Code::relocation_start() {
3001  return unchecked_relocation_info()->GetDataStartAddress();
3002}
3003
3004
3005int Code::relocation_size() {
3006  return unchecked_relocation_info()->length();
3007}
3008
3009
3010byte* Code::entry() {
3011  return instruction_start();
3012}
3013
3014
3015bool Code::contains(byte* pc) {
3016  return (instruction_start() <= pc) &&
3017      (pc <= instruction_start() + instruction_size());
3018}
3019
3020
3021ACCESSORS(JSArray, length, Object, kLengthOffset)
3022
3023
3024ACCESSORS(JSRegExp, data, Object, kDataOffset)
3025
3026
3027JSRegExp::Type JSRegExp::TypeTag() {
3028  Object* data = this->data();
3029  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3030  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3031  return static_cast<JSRegExp::Type>(smi->value());
3032}
3033
3034
3035int JSRegExp::CaptureCount() {
3036  switch (TypeTag()) {
3037    case ATOM:
3038      return 0;
3039    case IRREGEXP:
3040      return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
3041    default:
3042      UNREACHABLE();
3043      return -1;
3044  }
3045}
3046
3047
3048JSRegExp::Flags JSRegExp::GetFlags() {
3049  ASSERT(this->data()->IsFixedArray());
3050  Object* data = this->data();
3051  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
3052  return Flags(smi->value());
3053}
3054
3055
3056String* JSRegExp::Pattern() {
3057  ASSERT(this->data()->IsFixedArray());
3058  Object* data = this->data();
3059  String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3060  return pattern;
3061}
3062
3063
3064Object* JSRegExp::DataAt(int index) {
3065  ASSERT(TypeTag() != NOT_COMPILED);
3066  return FixedArray::cast(data())->get(index);
3067}
3068
3069
3070void JSRegExp::SetDataAt(int index, Object* value) {
3071  ASSERT(TypeTag() != NOT_COMPILED);
3072  ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
3073  FixedArray::cast(data())->set(index, value);
3074}
3075
3076
3077JSObject::ElementsKind JSObject::GetElementsKind() {
3078  if (map()->has_fast_elements()) {
3079    ASSERT(elements()->map() == Heap::fixed_array_map() ||
3080           elements()->map() == Heap::fixed_cow_array_map());
3081    return FAST_ELEMENTS;
3082  }
3083  HeapObject* array = elements();
3084  if (array->IsFixedArray()) {
3085    // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3086    // FixedArray, but FAST_ELEMENTS is already handled above.
3087    ASSERT(array->IsDictionary());
3088    return DICTIONARY_ELEMENTS;
3089  }
3090  if (array->IsExternalArray()) {
3091    switch (array->map()->instance_type()) {
3092      case EXTERNAL_BYTE_ARRAY_TYPE:
3093        return EXTERNAL_BYTE_ELEMENTS;
3094      case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3095        return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3096      case EXTERNAL_SHORT_ARRAY_TYPE:
3097        return EXTERNAL_SHORT_ELEMENTS;
3098      case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3099        return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3100      case EXTERNAL_INT_ARRAY_TYPE:
3101        return EXTERNAL_INT_ELEMENTS;
3102      case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3103        return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3104      default:
3105        ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3106        return EXTERNAL_FLOAT_ELEMENTS;
3107    }
3108  }
3109  ASSERT(array->IsPixelArray());
3110  return PIXEL_ELEMENTS;
3111}
3112
3113
3114bool JSObject::HasFastElements() {
3115  return GetElementsKind() == FAST_ELEMENTS;
3116}
3117
3118
3119bool JSObject::HasDictionaryElements() {
3120  return GetElementsKind() == DICTIONARY_ELEMENTS;
3121}
3122
3123
3124bool JSObject::HasPixelElements() {
3125  return GetElementsKind() == PIXEL_ELEMENTS;
3126}
3127
3128
3129bool JSObject::HasExternalArrayElements() {
3130  return (HasExternalByteElements() ||
3131          HasExternalUnsignedByteElements() ||
3132          HasExternalShortElements() ||
3133          HasExternalUnsignedShortElements() ||
3134          HasExternalIntElements() ||
3135          HasExternalUnsignedIntElements() ||
3136          HasExternalFloatElements());
3137}
3138
3139
3140bool JSObject::HasExternalByteElements() {
3141  return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3142}
3143
3144
3145bool JSObject::HasExternalUnsignedByteElements() {
3146  return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3147}
3148
3149
3150bool JSObject::HasExternalShortElements() {
3151  return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3152}
3153
3154
3155bool JSObject::HasExternalUnsignedShortElements() {
3156  return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3157}
3158
3159
3160bool JSObject::HasExternalIntElements() {
3161  return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3162}
3163
3164
3165bool JSObject::HasExternalUnsignedIntElements() {
3166  return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3167}
3168
3169
3170bool JSObject::HasExternalFloatElements() {
3171  return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3172}
3173
3174
3175bool JSObject::HasNamedInterceptor() {
3176  return map()->has_named_interceptor();
3177}
3178
3179
3180bool JSObject::HasIndexedInterceptor() {
3181  return map()->has_indexed_interceptor();
3182}
3183
3184
3185bool JSObject::AllowsSetElementsLength() {
3186  bool result = elements()->IsFixedArray();
3187  ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3188  return result;
3189}
3190
3191
3192Object* JSObject::EnsureWritableFastElements() {
3193  ASSERT(HasFastElements());
3194  FixedArray* elems = FixedArray::cast(elements());
3195  if (elems->map() != Heap::fixed_cow_array_map()) return elems;
3196  Object* writable_elems = Heap::CopyFixedArrayWithMap(elems,
3197                                                       Heap::fixed_array_map());
3198  if (writable_elems->IsFailure()) return writable_elems;
3199  set_elements(FixedArray::cast(writable_elems));
3200  Counters::cow_arrays_converted.Increment();
3201  return writable_elems;
3202}
3203
3204
3205StringDictionary* JSObject::property_dictionary() {
3206  ASSERT(!HasFastProperties());
3207  return StringDictionary::cast(properties());
3208}
3209
3210
3211NumberDictionary* JSObject::element_dictionary() {
3212  ASSERT(HasDictionaryElements());
3213  return NumberDictionary::cast(elements());
3214}
3215
3216
3217bool String::IsHashFieldComputed(uint32_t field) {
3218  return (field & kHashNotComputedMask) == 0;
3219}
3220
3221
3222bool String::HasHashCode() {
3223  return IsHashFieldComputed(hash_field());
3224}
3225
3226
3227uint32_t String::Hash() {
3228  // Fast case: has hash code already been computed?
3229  uint32_t field = hash_field();
3230  if (IsHashFieldComputed(field)) return field >> kHashShift;
3231  // Slow case: compute hash code and set it.
3232  return ComputeAndSetHash();
3233}
3234
3235
3236StringHasher::StringHasher(int length)
3237  : length_(length),
3238    raw_running_hash_(0),
3239    array_index_(0),
3240    is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3241    is_first_char_(true),
3242    is_valid_(true) { }
3243
3244
3245bool StringHasher::has_trivial_hash() {
3246  return length_ > String::kMaxHashCalcLength;
3247}
3248
3249
3250void StringHasher::AddCharacter(uc32 c) {
3251  // Use the Jenkins one-at-a-time hash function to update the hash
3252  // for the given character.
3253  raw_running_hash_ += c;
3254  raw_running_hash_ += (raw_running_hash_ << 10);
3255  raw_running_hash_ ^= (raw_running_hash_ >> 6);
3256  // Incremental array index computation.
3257  if (is_array_index_) {
3258    if (c < '0' || c > '9') {
3259      is_array_index_ = false;
3260    } else {
3261      int d = c - '0';
3262      if (is_first_char_) {
3263        is_first_char_ = false;
3264        if (c == '0' && length_ > 1) {
3265          is_array_index_ = false;
3266          return;
3267        }
3268      }
3269      if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3270        is_array_index_ = false;
3271      } else {
3272        array_index_ = array_index_ * 10 + d;
3273      }
3274    }
3275  }
3276}
3277
3278
3279void StringHasher::AddCharacterNoIndex(uc32 c) {
3280  ASSERT(!is_array_index());
3281  raw_running_hash_ += c;
3282  raw_running_hash_ += (raw_running_hash_ << 10);
3283  raw_running_hash_ ^= (raw_running_hash_ >> 6);
3284}
3285
3286
3287uint32_t StringHasher::GetHash() {
3288  // Get the calculated raw hash value and do some more bit ops to distribute
3289  // the hash further. Ensure that we never return zero as the hash value.
3290  uint32_t result = raw_running_hash_;
3291  result += (result << 3);
3292  result ^= (result >> 11);
3293  result += (result << 15);
3294  if (result == 0) {
3295    result = 27;
3296  }
3297  return result;
3298}
3299
3300
3301bool String::AsArrayIndex(uint32_t* index) {
3302  uint32_t field = hash_field();
3303  if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3304    return false;
3305  }
3306  return SlowAsArrayIndex(index);
3307}
3308
3309
3310Object* JSObject::GetPrototype() {
3311  return JSObject::cast(this)->map()->prototype();
3312}
3313
3314
3315PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3316  return GetPropertyAttributeWithReceiver(this, key);
3317}
3318
3319// TODO(504): this may be useful in other places too where JSGlobalProxy
3320// is used.
3321Object* JSObject::BypassGlobalProxy() {
3322  if (IsJSGlobalProxy()) {
3323    Object* proto = GetPrototype();
3324    if (proto->IsNull()) return Heap::undefined_value();
3325    ASSERT(proto->IsJSGlobalObject());
3326    return proto;
3327  }
3328  return this;
3329}
3330
3331
3332bool JSObject::HasHiddenPropertiesObject() {
3333  ASSERT(!IsJSGlobalProxy());
3334  return GetPropertyAttributePostInterceptor(this,
3335                                             Heap::hidden_symbol(),
3336                                             false) != ABSENT;
3337}
3338
3339
3340Object* JSObject::GetHiddenPropertiesObject() {
3341  ASSERT(!IsJSGlobalProxy());
3342  PropertyAttributes attributes;
3343  return GetLocalPropertyPostInterceptor(this,
3344                                         Heap::hidden_symbol(),
3345                                         &attributes);
3346}
3347
3348
3349Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3350  ASSERT(!IsJSGlobalProxy());
3351  return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3352                                    hidden_obj,
3353                                    DONT_ENUM);
3354}
3355
3356
3357bool JSObject::HasElement(uint32_t index) {
3358  return HasElementWithReceiver(this, index);
3359}
3360
3361
3362bool AccessorInfo::all_can_read() {
3363  return BooleanBit::get(flag(), kAllCanReadBit);
3364}
3365
3366
3367void AccessorInfo::set_all_can_read(bool value) {
3368  set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3369}
3370
3371
3372bool AccessorInfo::all_can_write() {
3373  return BooleanBit::get(flag(), kAllCanWriteBit);
3374}
3375
3376
3377void AccessorInfo::set_all_can_write(bool value) {
3378  set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3379}
3380
3381
3382bool AccessorInfo::prohibits_overwriting() {
3383  return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3384}
3385
3386
3387void AccessorInfo::set_prohibits_overwriting(bool value) {
3388  set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3389}
3390
3391
3392PropertyAttributes AccessorInfo::property_attributes() {
3393  return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3394}
3395
3396
3397void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3398  ASSERT(AttributesField::is_valid(attributes));
3399  int rest_value = flag()->value() & ~AttributesField::mask();
3400  set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3401}
3402
3403template<typename Shape, typename Key>
3404void Dictionary<Shape, Key>::SetEntry(int entry,
3405                                      Object* key,
3406                                      Object* value,
3407                                      PropertyDetails details) {
3408  ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3409  int index = HashTable<Shape, Key>::EntryToIndex(entry);
3410  AssertNoAllocation no_gc;
3411  WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
3412  FixedArray::set(index, key, mode);
3413  FixedArray::set(index+1, value, mode);
3414  FixedArray::fast_set(this, index+2, details.AsSmi());
3415}
3416
3417
3418void Map::ClearCodeCache() {
3419  // No write barrier is needed since empty_fixed_array is not in new space.
3420  // Please note this function is used during marking:
3421  //  - MarkCompactCollector::MarkUnmarkedObject
3422  ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3423  WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3424}
3425
3426
3427void JSArray::EnsureSize(int required_size) {
3428  ASSERT(HasFastElements());
3429  FixedArray* elts = FixedArray::cast(elements());
3430  const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3431  if (elts->length() < required_size) {
3432    // Doubling in size would be overkill, but leave some slack to avoid
3433    // constantly growing.
3434    Expand(required_size + (required_size >> 3));
3435    // It's a performance benefit to keep a frequently used array in new-space.
3436  } else if (!Heap::new_space()->Contains(elts) &&
3437             required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3438    // Expand will allocate a new backing store in new space even if the size
3439    // we asked for isn't larger than what we had before.
3440    Expand(required_size);
3441  }
3442}
3443
3444
3445void JSArray::set_length(Smi* length) {
3446  set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3447}
3448
3449
3450void JSArray::SetContent(FixedArray* storage) {
3451  set_length(Smi::FromInt(storage->length()));
3452  set_elements(storage);
3453}
3454
3455
3456Object* FixedArray::Copy() {
3457  if (length() == 0) return this;
3458  return Heap::CopyFixedArray(this);
3459}
3460
3461
3462int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3463  return map->instance_size();
3464}
3465
3466
3467void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3468  v->VisitExternalReference(
3469      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3470}
3471
3472
3473template<typename StaticVisitor>
3474void Proxy::ProxyIterateBody() {
3475  StaticVisitor::VisitExternalReference(
3476      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3477}
3478
3479
3480void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3481  typedef v8::String::ExternalAsciiStringResource Resource;
3482  v->VisitExternalAsciiString(
3483      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3484}
3485
3486
3487template<typename StaticVisitor>
3488void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3489  typedef v8::String::ExternalAsciiStringResource Resource;
3490  StaticVisitor::VisitExternalAsciiString(
3491      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3492}
3493
3494
3495void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3496  typedef v8::String::ExternalStringResource Resource;
3497  v->VisitExternalTwoByteString(
3498      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3499}
3500
3501
3502template<typename StaticVisitor>
3503void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3504  typedef v8::String::ExternalStringResource Resource;
3505  StaticVisitor::VisitExternalTwoByteString(
3506      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3507}
3508
3509#define SLOT_ADDR(obj, offset) \
3510  reinterpret_cast<Object**>((obj)->address() + offset)
3511
3512template<int start_offset, int end_offset, int size>
3513void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3514    HeapObject* obj,
3515    ObjectVisitor* v) {
3516    v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3517}
3518
3519
3520template<int start_offset>
3521void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3522                                                       int object_size,
3523                                                       ObjectVisitor* v) {
3524  v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3525}
3526
3527#undef SLOT_ADDR
3528
3529
3530#undef CAST_ACCESSOR
3531#undef INT_ACCESSORS
3532#undef SMI_ACCESSORS
3533#undef ACCESSORS
3534#undef FIELD_ADDR
3535#undef READ_FIELD
3536#undef WRITE_FIELD
3537#undef WRITE_BARRIER
3538#undef CONDITIONAL_WRITE_BARRIER
3539#undef READ_MEMADDR_FIELD
3540#undef WRITE_MEMADDR_FIELD
3541#undef READ_DOUBLE_FIELD
3542#undef WRITE_DOUBLE_FIELD
3543#undef READ_INT_FIELD
3544#undef WRITE_INT_FIELD
3545#undef READ_SHORT_FIELD
3546#undef WRITE_SHORT_FIELD
3547#undef READ_BYTE_FIELD
3548#undef WRITE_BYTE_FIELD
3549
3550
3551} }  // namespace v8::internal
3552
3553#endif  // V8_OBJECTS_INL_H_
3554