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