Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / v8 / src / objects-inl.h
1 // Copyright 2012 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 "elements.h"
39 #include "objects.h"
40 #include "contexts.h"
41 #include "conversions-inl.h"
42 #include "heap.h"
43 #include "isolate.h"
44 #include "heap-inl.h"
45 #include "property.h"
46 #include "spaces.h"
47 #include "store-buffer.h"
48 #include "v8memory.h"
49 #include "factory.h"
50 #include "incremental-marking.h"
51 #include "transitions-inl.h"
52 #include "objects-visiting.h"
53
54 namespace v8 {
55 namespace internal {
56
57 PropertyDetails::PropertyDetails(Smi* smi) {
58   value_ = smi->value();
59 }
60
61
62 Smi* PropertyDetails::AsSmi() {
63   // Ensure the upper 2 bits have the same value by sign extending it. This is
64   // necessary to be able to use the 31st bit of the property details.
65   int value = value_ << 1;
66   return Smi::FromInt(value >> 1);
67 }
68
69
70 PropertyDetails PropertyDetails::AsDeleted() {
71   Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
72   return PropertyDetails(smi);
73 }
74
75
76 #define TYPE_CHECKER(type, instancetype)                                \
77   bool Object::Is##type() {                                             \
78   return Object::IsHeapObject() &&                                      \
79       HeapObject::cast(this)->map()->instance_type() == instancetype;   \
80   }
81
82
83 #define CAST_ACCESSOR(type)                     \
84   type* type::cast(Object* object) {            \
85     SLOW_ASSERT(object->Is##type());            \
86     return reinterpret_cast<type*>(object);     \
87   }
88
89
90 #define FIXED_TYPED_ARRAY_CAST_ACCESSOR(type)   \
91   template<>                                    \
92   type* type::cast(Object* object) {            \
93     SLOW_ASSERT(object->Is##type());            \
94     return reinterpret_cast<type*>(object);     \
95   }
96
97 #define INT_ACCESSORS(holder, name, offset)                             \
98   int holder::name() { return READ_INT_FIELD(this, offset); }           \
99   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
100
101
102 #define ACCESSORS(holder, name, type, offset)                           \
103   type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
104   void holder::set_##name(type* value, WriteBarrierMode mode) {         \
105     WRITE_FIELD(this, offset, value);                                   \
106     CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);    \
107   }
108
109
110 // Getter that returns a tagged Smi and setter that writes a tagged Smi.
111 #define ACCESSORS_TO_SMI(holder, name, offset)                          \
112   Smi* holder::name() { return Smi::cast(READ_FIELD(this, offset)); }   \
113   void holder::set_##name(Smi* value, WriteBarrierMode mode) {          \
114     WRITE_FIELD(this, offset, value);                                   \
115   }
116
117
118 // Getter that returns a Smi as an int and writes an int as a Smi.
119 #define SMI_ACCESSORS(holder, name, offset)             \
120   int holder::name() {                                  \
121     Object* value = READ_FIELD(this, offset);           \
122     return Smi::cast(value)->value();                   \
123   }                                                     \
124   void holder::set_##name(int value) {                  \
125     WRITE_FIELD(this, offset, Smi::FromInt(value));     \
126   }
127
128
129 #define BOOL_GETTER(holder, field, name, offset)           \
130   bool holder::name() {                                    \
131     return BooleanBit::get(field(), offset);               \
132   }                                                        \
133
134
135 #define BOOL_ACCESSORS(holder, field, name, offset)        \
136   bool holder::name() {                                    \
137     return BooleanBit::get(field(), offset);               \
138   }                                                        \
139   void holder::set_##name(bool value) {                    \
140     set_##field(BooleanBit::set(field(), offset, value));  \
141   }
142
143
144 bool Object::IsFixedArrayBase() {
145   return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
146          IsFixedTypedArrayBase() || IsExternalArray();
147 }
148
149
150 // External objects are not extensible, so the map check is enough.
151 bool Object::IsExternal() {
152   return Object::IsHeapObject() &&
153       HeapObject::cast(this)->map() ==
154       HeapObject::cast(this)->GetHeap()->external_map();
155 }
156
157
158 bool Object::IsAccessorInfo() {
159   return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
160 }
161
162
163 bool Object::IsSmi() {
164   return HAS_SMI_TAG(this);
165 }
166
167
168 bool Object::IsHeapObject() {
169   return Internals::HasHeapObjectTag(this);
170 }
171
172
173 bool Object::NonFailureIsHeapObject() {
174   ASSERT(!this->IsFailure());
175   return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
176 }
177
178
179 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
180 TYPE_CHECKER(Symbol, SYMBOL_TYPE)
181
182
183 bool Object::IsString() {
184   return Object::IsHeapObject()
185     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
186 }
187
188
189 bool Object::IsName() {
190   return IsString() || IsSymbol();
191 }
192
193
194 bool Object::IsUniqueName() {
195   return IsInternalizedString() || IsSymbol();
196 }
197
198
199 bool Object::IsSpecObject() {
200   return Object::IsHeapObject()
201     && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
202 }
203
204
205 bool Object::IsSpecFunction() {
206   if (!Object::IsHeapObject()) return false;
207   InstanceType type = HeapObject::cast(this)->map()->instance_type();
208   return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
209 }
210
211
212 bool Object::IsInternalizedString() {
213   if (!this->IsHeapObject()) return false;
214   uint32_t type = HeapObject::cast(this)->map()->instance_type();
215   STATIC_ASSERT(kNotInternalizedTag != 0);
216   return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
217       (kStringTag | kInternalizedTag);
218 }
219
220
221 bool Object::IsConsString() {
222   if (!IsString()) return false;
223   return StringShape(String::cast(this)).IsCons();
224 }
225
226
227 bool Object::IsSlicedString() {
228   if (!IsString()) return false;
229   return StringShape(String::cast(this)).IsSliced();
230 }
231
232
233 bool Object::IsSeqString() {
234   if (!IsString()) return false;
235   return StringShape(String::cast(this)).IsSequential();
236 }
237
238
239 bool Object::IsSeqOneByteString() {
240   if (!IsString()) return false;
241   return StringShape(String::cast(this)).IsSequential() &&
242          String::cast(this)->IsOneByteRepresentation();
243 }
244
245
246 bool Object::IsSeqTwoByteString() {
247   if (!IsString()) return false;
248   return StringShape(String::cast(this)).IsSequential() &&
249          String::cast(this)->IsTwoByteRepresentation();
250 }
251
252
253 bool Object::IsExternalString() {
254   if (!IsString()) return false;
255   return StringShape(String::cast(this)).IsExternal();
256 }
257
258
259 bool Object::IsExternalAsciiString() {
260   if (!IsString()) return false;
261   return StringShape(String::cast(this)).IsExternal() &&
262          String::cast(this)->IsOneByteRepresentation();
263 }
264
265
266 bool Object::IsExternalTwoByteString() {
267   if (!IsString()) return false;
268   return StringShape(String::cast(this)).IsExternal() &&
269          String::cast(this)->IsTwoByteRepresentation();
270 }
271
272 bool Object::HasValidElements() {
273   // Dictionary is covered under FixedArray.
274   return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray() ||
275          IsFixedTypedArrayBase();
276 }
277
278
279 MaybeObject* Object::AllocateNewStorageFor(Heap* heap,
280                                            Representation representation) {
281   if (FLAG_track_fields && representation.IsSmi() && IsUninitialized()) {
282     return Smi::FromInt(0);
283   }
284   if (!FLAG_track_double_fields) return this;
285   if (!representation.IsDouble()) return this;
286   if (IsUninitialized()) {
287     return heap->AllocateHeapNumber(0);
288   }
289   return heap->AllocateHeapNumber(Number());
290 }
291
292
293 StringShape::StringShape(String* str)
294   : type_(str->map()->instance_type()) {
295   set_valid();
296   ASSERT((type_ & kIsNotStringMask) == kStringTag);
297 }
298
299
300 StringShape::StringShape(Map* map)
301   : type_(map->instance_type()) {
302   set_valid();
303   ASSERT((type_ & kIsNotStringMask) == kStringTag);
304 }
305
306
307 StringShape::StringShape(InstanceType t)
308   : type_(static_cast<uint32_t>(t)) {
309   set_valid();
310   ASSERT((type_ & kIsNotStringMask) == kStringTag);
311 }
312
313
314 bool StringShape::IsInternalized() {
315   ASSERT(valid());
316   STATIC_ASSERT(kNotInternalizedTag != 0);
317   return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
318       (kStringTag | kInternalizedTag);
319 }
320
321
322 bool String::IsOneByteRepresentation() {
323   uint32_t type = map()->instance_type();
324   return (type & kStringEncodingMask) == kOneByteStringTag;
325 }
326
327
328 bool String::IsTwoByteRepresentation() {
329   uint32_t type = map()->instance_type();
330   return (type & kStringEncodingMask) == kTwoByteStringTag;
331 }
332
333
334 bool String::IsOneByteRepresentationUnderneath() {
335   uint32_t type = map()->instance_type();
336   STATIC_ASSERT(kIsIndirectStringTag != 0);
337   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
338   ASSERT(IsFlat());
339   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
340     case kOneByteStringTag:
341       return true;
342     case kTwoByteStringTag:
343       return false;
344     default:  // Cons or sliced string.  Need to go deeper.
345       return GetUnderlying()->IsOneByteRepresentation();
346   }
347 }
348
349
350 bool String::IsTwoByteRepresentationUnderneath() {
351   uint32_t type = map()->instance_type();
352   STATIC_ASSERT(kIsIndirectStringTag != 0);
353   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
354   ASSERT(IsFlat());
355   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
356     case kOneByteStringTag:
357       return false;
358     case kTwoByteStringTag:
359       return true;
360     default:  // Cons or sliced string.  Need to go deeper.
361       return GetUnderlying()->IsTwoByteRepresentation();
362   }
363 }
364
365
366 bool String::HasOnlyOneByteChars() {
367   uint32_t type = map()->instance_type();
368   return (type & kOneByteDataHintMask) == kOneByteDataHintTag ||
369          IsOneByteRepresentation();
370 }
371
372
373 bool StringShape::IsCons() {
374   return (type_ & kStringRepresentationMask) == kConsStringTag;
375 }
376
377
378 bool StringShape::IsSliced() {
379   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
380 }
381
382
383 bool StringShape::IsIndirect() {
384   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
385 }
386
387
388 bool StringShape::IsExternal() {
389   return (type_ & kStringRepresentationMask) == kExternalStringTag;
390 }
391
392
393 bool StringShape::IsSequential() {
394   return (type_ & kStringRepresentationMask) == kSeqStringTag;
395 }
396
397
398 StringRepresentationTag StringShape::representation_tag() {
399   uint32_t tag = (type_ & kStringRepresentationMask);
400   return static_cast<StringRepresentationTag>(tag);
401 }
402
403
404 uint32_t StringShape::encoding_tag() {
405   return type_ & kStringEncodingMask;
406 }
407
408
409 uint32_t StringShape::full_representation_tag() {
410   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
411 }
412
413
414 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
415              Internals::kFullStringRepresentationMask);
416
417 STATIC_CHECK(static_cast<uint32_t>(kStringEncodingMask) ==
418              Internals::kStringEncodingMask);
419
420
421 bool StringShape::IsSequentialAscii() {
422   return full_representation_tag() == (kSeqStringTag | kOneByteStringTag);
423 }
424
425
426 bool StringShape::IsSequentialTwoByte() {
427   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
428 }
429
430
431 bool StringShape::IsExternalAscii() {
432   return full_representation_tag() == (kExternalStringTag | kOneByteStringTag);
433 }
434
435
436 STATIC_CHECK((kExternalStringTag | kOneByteStringTag) ==
437              Internals::kExternalAsciiRepresentationTag);
438
439 STATIC_CHECK(v8::String::ASCII_ENCODING == kOneByteStringTag);
440
441
442 bool StringShape::IsExternalTwoByte() {
443   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
444 }
445
446
447 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
448              Internals::kExternalTwoByteRepresentationTag);
449
450 STATIC_CHECK(v8::String::TWO_BYTE_ENCODING == kTwoByteStringTag);
451
452 uc32 FlatStringReader::Get(int index) {
453   ASSERT(0 <= index && index <= length_);
454   if (is_ascii_) {
455     return static_cast<const byte*>(start_)[index];
456   } else {
457     return static_cast<const uc16*>(start_)[index];
458   }
459 }
460
461
462 template <typename Char>
463 class SequentialStringKey : public HashTableKey {
464  public:
465   explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
466       : string_(string), hash_field_(0), seed_(seed) { }
467
468   virtual uint32_t Hash() {
469     hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
470                                                            string_.length(),
471                                                            seed_);
472
473     uint32_t result = hash_field_ >> String::kHashShift;
474     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
475     return result;
476   }
477
478
479   virtual uint32_t HashForObject(Object* other) {
480     return String::cast(other)->Hash();
481   }
482
483   Vector<const Char> string_;
484   uint32_t hash_field_;
485   uint32_t seed_;
486 };
487
488
489 class OneByteStringKey : public SequentialStringKey<uint8_t> {
490  public:
491   OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
492       : SequentialStringKey<uint8_t>(str, seed) { }
493
494   virtual bool IsMatch(Object* string) {
495     return String::cast(string)->IsOneByteEqualTo(string_);
496   }
497
498   virtual MaybeObject* AsObject(Heap* heap);
499 };
500
501
502 class SubStringOneByteStringKey : public HashTableKey {
503  public:
504   explicit SubStringOneByteStringKey(Handle<SeqOneByteString> string,
505                                      int from,
506                                      int length)
507       : string_(string), from_(from), length_(length) { }
508
509   virtual uint32_t Hash() {
510     ASSERT(length_ >= 0);
511     ASSERT(from_ + length_ <= string_->length());
512     uint8_t* chars = string_->GetChars() + from_;
513     hash_field_ = StringHasher::HashSequentialString(
514         chars, length_, string_->GetHeap()->HashSeed());
515     uint32_t result = hash_field_ >> String::kHashShift;
516     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
517     return result;
518   }
519
520
521   virtual uint32_t HashForObject(Object* other) {
522     return String::cast(other)->Hash();
523   }
524
525   virtual bool IsMatch(Object* string) {
526     Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
527     return String::cast(string)->IsOneByteEqualTo(chars);
528   }
529
530   virtual MaybeObject* AsObject(Heap* heap);
531
532  private:
533   Handle<SeqOneByteString> string_;
534   int from_;
535   int length_;
536   uint32_t hash_field_;
537 };
538
539
540 class TwoByteStringKey : public SequentialStringKey<uc16> {
541  public:
542   explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
543       : SequentialStringKey<uc16>(str, seed) { }
544
545   virtual bool IsMatch(Object* string) {
546     return String::cast(string)->IsTwoByteEqualTo(string_);
547   }
548
549   virtual MaybeObject* AsObject(Heap* heap);
550 };
551
552
553 // Utf8StringKey carries a vector of chars as key.
554 class Utf8StringKey : public HashTableKey {
555  public:
556   explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
557       : string_(string), hash_field_(0), seed_(seed) { }
558
559   virtual bool IsMatch(Object* string) {
560     return String::cast(string)->IsUtf8EqualTo(string_);
561   }
562
563   virtual uint32_t Hash() {
564     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
565     hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
566     uint32_t result = hash_field_ >> String::kHashShift;
567     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
568     return result;
569   }
570
571   virtual uint32_t HashForObject(Object* other) {
572     return String::cast(other)->Hash();
573   }
574
575   virtual MaybeObject* AsObject(Heap* heap) {
576     if (hash_field_ == 0) Hash();
577     return heap->AllocateInternalizedStringFromUtf8(string_,
578                                                     chars_,
579                                                     hash_field_);
580   }
581
582   Vector<const char> string_;
583   uint32_t hash_field_;
584   int chars_;  // Caches the number of characters when computing the hash code.
585   uint32_t seed_;
586 };
587
588
589 bool Object::IsNumber() {
590   return IsSmi() || IsHeapNumber();
591 }
592
593
594 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
595 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
596
597
598 bool Object::IsFiller() {
599   if (!Object::IsHeapObject()) return false;
600   InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
601   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
602 }
603
604
605 bool Object::IsExternalArray() {
606   if (!Object::IsHeapObject())
607     return false;
608   InstanceType instance_type =
609       HeapObject::cast(this)->map()->instance_type();
610   return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
611           instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
612 }
613
614
615 #define TYPED_ARRAY_TYPE_CHECKER(Type, type, TYPE, ctype, size)               \
616   TYPE_CHECKER(External##Type##Array, EXTERNAL_##TYPE##_ARRAY_TYPE)           \
617   TYPE_CHECKER(Fixed##Type##Array, FIXED_##TYPE##_ARRAY_TYPE)
618
619 TYPED_ARRAYS(TYPED_ARRAY_TYPE_CHECKER)
620 #undef TYPED_ARRAY_TYPE_CHECKER
621
622
623 bool Object::IsFixedTypedArrayBase() {
624   if (!Object::IsHeapObject()) return false;
625
626   InstanceType instance_type =
627       HeapObject::cast(this)->map()->instance_type();
628   return (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
629           instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE);
630 }
631
632
633 bool MaybeObject::IsFailure() {
634   return HAS_FAILURE_TAG(this);
635 }
636
637
638 bool MaybeObject::IsRetryAfterGC() {
639   return HAS_FAILURE_TAG(this)
640     && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
641 }
642
643
644 bool MaybeObject::IsOutOfMemory() {
645   return HAS_FAILURE_TAG(this)
646       && Failure::cast(this)->IsOutOfMemoryException();
647 }
648
649
650 bool MaybeObject::IsException() {
651   return this == Failure::Exception();
652 }
653
654
655 bool MaybeObject::IsTheHole() {
656   return !IsFailure() && ToObjectUnchecked()->IsTheHole();
657 }
658
659
660 bool MaybeObject::IsUninitialized() {
661   return !IsFailure() && ToObjectUnchecked()->IsUninitialized();
662 }
663
664
665 Failure* Failure::cast(MaybeObject* obj) {
666   ASSERT(HAS_FAILURE_TAG(obj));
667   return reinterpret_cast<Failure*>(obj);
668 }
669
670
671 bool Object::IsJSReceiver() {
672   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
673   return IsHeapObject() &&
674       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
675 }
676
677
678 bool Object::IsJSObject() {
679   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
680   return IsHeapObject() &&
681       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
682 }
683
684
685 bool Object::IsJSProxy() {
686   if (!Object::IsHeapObject()) return false;
687   InstanceType type = HeapObject::cast(this)->map()->instance_type();
688   return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
689 }
690
691
692 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
693 TYPE_CHECKER(JSSet, JS_SET_TYPE)
694 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
695 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
696 TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
697 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
698 TYPE_CHECKER(Map, MAP_TYPE)
699 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
700 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
701 TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
702
703
704 bool Object::IsJSWeakCollection() {
705   return IsJSWeakMap() || IsJSWeakSet();
706 }
707
708
709 bool Object::IsDescriptorArray() {
710   return IsFixedArray();
711 }
712
713
714 bool Object::IsTransitionArray() {
715   return IsFixedArray();
716 }
717
718
719 bool Object::IsDeoptimizationInputData() {
720   // Must be a fixed array.
721   if (!IsFixedArray()) return false;
722
723   // There's no sure way to detect the difference between a fixed array and
724   // a deoptimization data array.  Since this is used for asserts we can
725   // check that the length is zero or else the fixed size plus a multiple of
726   // the entry size.
727   int length = FixedArray::cast(this)->length();
728   if (length == 0) return true;
729
730   length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
731   return length >= 0 &&
732       length % DeoptimizationInputData::kDeoptEntrySize == 0;
733 }
734
735
736 bool Object::IsDeoptimizationOutputData() {
737   if (!IsFixedArray()) return false;
738   // There's actually no way to see the difference between a fixed array and
739   // a deoptimization data array.  Since this is used for asserts we can check
740   // that the length is plausible though.
741   if (FixedArray::cast(this)->length() % 2 != 0) return false;
742   return true;
743 }
744
745
746 bool Object::IsDependentCode() {
747   if (!IsFixedArray()) return false;
748   // There's actually no way to see the difference between a fixed array and
749   // a dependent codes array.
750   return true;
751 }
752
753
754 bool Object::IsTypeFeedbackCells() {
755   if (!IsFixedArray()) return false;
756   // There's actually no way to see the difference between a fixed array and
757   // a cache cells array.  Since this is used for asserts we can check that
758   // the length is plausible though.
759   if (FixedArray::cast(this)->length() % 2 != 0) return false;
760   return true;
761 }
762
763
764 bool Object::IsContext() {
765   if (!Object::IsHeapObject()) return false;
766   Map* map = HeapObject::cast(this)->map();
767   Heap* heap = map->GetHeap();
768   return (map == heap->function_context_map() ||
769       map == heap->catch_context_map() ||
770       map == heap->with_context_map() ||
771       map == heap->native_context_map() ||
772       map == heap->block_context_map() ||
773       map == heap->module_context_map() ||
774       map == heap->global_context_map());
775 }
776
777
778 bool Object::IsNativeContext() {
779   return Object::IsHeapObject() &&
780       HeapObject::cast(this)->map() ==
781       HeapObject::cast(this)->GetHeap()->native_context_map();
782 }
783
784
785 bool Object::IsScopeInfo() {
786   return Object::IsHeapObject() &&
787       HeapObject::cast(this)->map() ==
788       HeapObject::cast(this)->GetHeap()->scope_info_map();
789 }
790
791
792 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
793
794
795 template <> inline bool Is<JSFunction>(Object* obj) {
796   return obj->IsJSFunction();
797 }
798
799
800 TYPE_CHECKER(Code, CODE_TYPE)
801 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
802 TYPE_CHECKER(Cell, CELL_TYPE)
803 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
804 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
805 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
806 TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
807 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
808 TYPE_CHECKER(JSDate, JS_DATE_TYPE)
809 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
810
811
812 bool Object::IsStringWrapper() {
813   return IsJSValue() && JSValue::cast(this)->value()->IsString();
814 }
815
816
817 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
818
819
820 bool Object::IsBoolean() {
821   return IsOddball() &&
822       ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
823 }
824
825
826 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
827 TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
828 TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
829 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
830
831
832 bool Object::IsJSArrayBufferView() {
833   return IsJSDataView() || IsJSTypedArray();
834 }
835
836
837 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
838
839
840 template <> inline bool Is<JSArray>(Object* obj) {
841   return obj->IsJSArray();
842 }
843
844
845 bool Object::IsHashTable() {
846   return Object::IsHeapObject() &&
847       HeapObject::cast(this)->map() ==
848       HeapObject::cast(this)->GetHeap()->hash_table_map();
849 }
850
851
852 bool Object::IsDictionary() {
853   return IsHashTable() &&
854       this != HeapObject::cast(this)->GetHeap()->string_table();
855 }
856
857
858 bool Object::IsStringTable() {
859   return IsHashTable() &&
860       this == HeapObject::cast(this)->GetHeap()->raw_unchecked_string_table();
861 }
862
863
864 bool Object::IsJSFunctionResultCache() {
865   if (!IsFixedArray()) return false;
866   FixedArray* self = FixedArray::cast(this);
867   int length = self->length();
868   if (length < JSFunctionResultCache::kEntriesIndex) return false;
869   if ((length - JSFunctionResultCache::kEntriesIndex)
870       % JSFunctionResultCache::kEntrySize != 0) {
871     return false;
872   }
873 #ifdef VERIFY_HEAP
874   if (FLAG_verify_heap) {
875     reinterpret_cast<JSFunctionResultCache*>(this)->
876         JSFunctionResultCacheVerify();
877   }
878 #endif
879   return true;
880 }
881
882
883 bool Object::IsNormalizedMapCache() {
884   if (!IsFixedArray()) return false;
885   if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
886     return false;
887   }
888 #ifdef VERIFY_HEAP
889   if (FLAG_verify_heap) {
890     reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
891   }
892 #endif
893   return true;
894 }
895
896
897 bool Object::IsCompilationCacheTable() {
898   return IsHashTable();
899 }
900
901
902 bool Object::IsCodeCacheHashTable() {
903   return IsHashTable();
904 }
905
906
907 bool Object::IsPolymorphicCodeCacheHashTable() {
908   return IsHashTable();
909 }
910
911
912 bool Object::IsMapCache() {
913   return IsHashTable();
914 }
915
916
917 bool Object::IsObjectHashTable() {
918   return IsHashTable();
919 }
920
921
922 bool Object::IsPrimitive() {
923   return IsOddball() || IsNumber() || IsString();
924 }
925
926
927 bool Object::IsJSGlobalProxy() {
928   bool result = IsHeapObject() &&
929                 (HeapObject::cast(this)->map()->instance_type() ==
930                  JS_GLOBAL_PROXY_TYPE);
931   ASSERT(!result || IsAccessCheckNeeded());
932   return result;
933 }
934
935
936 bool Object::IsGlobalObject() {
937   if (!IsHeapObject()) return false;
938
939   InstanceType type = HeapObject::cast(this)->map()->instance_type();
940   return type == JS_GLOBAL_OBJECT_TYPE ||
941          type == JS_BUILTINS_OBJECT_TYPE;
942 }
943
944
945 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
946 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
947
948
949 bool Object::IsUndetectableObject() {
950   return IsHeapObject()
951     && HeapObject::cast(this)->map()->is_undetectable();
952 }
953
954
955 bool Object::IsAccessCheckNeeded() {
956   return IsHeapObject()
957     && HeapObject::cast(this)->map()->is_access_check_needed();
958 }
959
960
961 bool Object::IsStruct() {
962   if (!IsHeapObject()) return false;
963   switch (HeapObject::cast(this)->map()->instance_type()) {
964 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
965   STRUCT_LIST(MAKE_STRUCT_CASE)
966 #undef MAKE_STRUCT_CASE
967     default: return false;
968   }
969 }
970
971
972 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
973   bool Object::Is##Name() {                                      \
974     return Object::IsHeapObject()                                \
975       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
976   }
977   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
978 #undef MAKE_STRUCT_PREDICATE
979
980
981 bool Object::IsUndefined() {
982   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
983 }
984
985
986 bool Object::IsNull() {
987   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
988 }
989
990
991 bool Object::IsTheHole() {
992   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
993 }
994
995
996 bool Object::IsUninitialized() {
997   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
998 }
999
1000
1001 bool Object::IsTrue() {
1002   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
1003 }
1004
1005
1006 bool Object::IsFalse() {
1007   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
1008 }
1009
1010
1011 bool Object::IsArgumentsMarker() {
1012   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
1013 }
1014
1015
1016 double Object::Number() {
1017   ASSERT(IsNumber());
1018   return IsSmi()
1019     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
1020     : reinterpret_cast<HeapNumber*>(this)->value();
1021 }
1022
1023
1024 bool Object::IsNaN() {
1025   return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
1026 }
1027
1028
1029 MaybeObject* Object::ToSmi() {
1030   if (IsSmi()) return this;
1031   if (IsHeapNumber()) {
1032     double value = HeapNumber::cast(this)->value();
1033     int int_value = FastD2I(value);
1034     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
1035       return Smi::FromInt(int_value);
1036     }
1037   }
1038   return Failure::Exception();
1039 }
1040
1041
1042 bool Object::HasSpecificClassOf(String* name) {
1043   return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
1044 }
1045
1046
1047 MaybeObject* Object::GetElement(Isolate* isolate, uint32_t index) {
1048   // GetElement can trigger a getter which can cause allocation.
1049   // This was not always the case. This ASSERT is here to catch
1050   // leftover incorrect uses.
1051   ASSERT(AllowHeapAllocation::IsAllowed());
1052   return GetElementWithReceiver(isolate, this, index);
1053 }
1054
1055
1056 Object* Object::GetElementNoExceptionThrown(Isolate* isolate, uint32_t index) {
1057   MaybeObject* maybe = GetElementWithReceiver(isolate, this, index);
1058   ASSERT(!maybe->IsFailure());
1059   Object* result = NULL;  // Initialization to please compiler.
1060   maybe->ToObject(&result);
1061   return result;
1062 }
1063
1064
1065 MaybeObject* Object::GetProperty(Name* key) {
1066   PropertyAttributes attributes;
1067   return GetPropertyWithReceiver(this, key, &attributes);
1068 }
1069
1070
1071 MaybeObject* Object::GetProperty(Name* key, PropertyAttributes* attributes) {
1072   return GetPropertyWithReceiver(this, key, attributes);
1073 }
1074
1075
1076 #define FIELD_ADDR(p, offset) \
1077   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
1078
1079 #define READ_FIELD(p, offset) \
1080   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
1081
1082 #define WRITE_FIELD(p, offset, value) \
1083   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
1084
1085 #define WRITE_BARRIER(heap, object, offset, value)                      \
1086   heap->incremental_marking()->RecordWrite(                             \
1087       object, HeapObject::RawField(object, offset), value);             \
1088   if (heap->InNewSpace(value)) {                                        \
1089     heap->RecordWrite(object->address(), offset);                       \
1090   }
1091
1092 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
1093   if (mode == UPDATE_WRITE_BARRIER) {                                   \
1094     heap->incremental_marking()->RecordWrite(                           \
1095       object, HeapObject::RawField(object, offset), value);             \
1096     if (heap->InNewSpace(value)) {                                      \
1097       heap->RecordWrite(object->address(), offset);                     \
1098     }                                                                   \
1099   }
1100
1101 #ifndef V8_TARGET_ARCH_MIPS
1102   #define READ_DOUBLE_FIELD(p, offset) \
1103     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
1104 #else  // V8_TARGET_ARCH_MIPS
1105   // Prevent gcc from using load-double (mips ldc1) on (possibly)
1106   // non-64-bit aligned HeapNumber::value.
1107   static inline double read_double_field(void* p, int offset) {
1108     union conversion {
1109       double d;
1110       uint32_t u[2];
1111     } c;
1112     c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
1113     c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
1114     return c.d;
1115   }
1116   #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
1117 #endif  // V8_TARGET_ARCH_MIPS
1118
1119 #ifndef V8_TARGET_ARCH_MIPS
1120   #define WRITE_DOUBLE_FIELD(p, offset, value) \
1121     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
1122 #else  // V8_TARGET_ARCH_MIPS
1123   // Prevent gcc from using store-double (mips sdc1) on (possibly)
1124   // non-64-bit aligned HeapNumber::value.
1125   static inline void write_double_field(void* p, int offset,
1126                                         double value) {
1127     union conversion {
1128       double d;
1129       uint32_t u[2];
1130     } c;
1131     c.d = value;
1132     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
1133     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
1134   }
1135   #define WRITE_DOUBLE_FIELD(p, offset, value) \
1136     write_double_field(p, offset, value)
1137 #endif  // V8_TARGET_ARCH_MIPS
1138
1139
1140 #define READ_INT_FIELD(p, offset) \
1141   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
1142
1143 #define WRITE_INT_FIELD(p, offset, value) \
1144   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
1145
1146 #define READ_INTPTR_FIELD(p, offset) \
1147   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
1148
1149 #define WRITE_INTPTR_FIELD(p, offset, value) \
1150   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
1151
1152 #define READ_UINT32_FIELD(p, offset) \
1153   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
1154
1155 #define WRITE_UINT32_FIELD(p, offset, value) \
1156   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
1157
1158 #define READ_INT32_FIELD(p, offset) \
1159   (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)))
1160
1161 #define WRITE_INT32_FIELD(p, offset, value) \
1162   (*reinterpret_cast<int32_t*>(FIELD_ADDR(p, offset)) = value)
1163
1164 #define READ_INT64_FIELD(p, offset) \
1165   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)))
1166
1167 #define WRITE_INT64_FIELD(p, offset, value) \
1168   (*reinterpret_cast<int64_t*>(FIELD_ADDR(p, offset)) = value)
1169
1170 #define READ_SHORT_FIELD(p, offset) \
1171   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
1172
1173 #define WRITE_SHORT_FIELD(p, offset, value) \
1174   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
1175
1176 #define READ_BYTE_FIELD(p, offset) \
1177   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
1178
1179 #define WRITE_BYTE_FIELD(p, offset, value) \
1180   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
1181
1182
1183 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
1184   return &READ_FIELD(obj, byte_offset);
1185 }
1186
1187
1188 int Smi::value() {
1189   return Internals::SmiValue(this);
1190 }
1191
1192
1193 Smi* Smi::FromInt(int value) {
1194   ASSERT(Smi::IsValid(value));
1195   return reinterpret_cast<Smi*>(Internals::IntToSmi(value));
1196 }
1197
1198
1199 Smi* Smi::FromIntptr(intptr_t value) {
1200   ASSERT(Smi::IsValid(value));
1201   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
1202   return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
1203 }
1204
1205
1206 Failure::Type Failure::type() const {
1207   return static_cast<Type>(value() & kFailureTypeTagMask);
1208 }
1209
1210
1211 bool Failure::IsInternalError() const {
1212   return type() == INTERNAL_ERROR;
1213 }
1214
1215
1216 bool Failure::IsOutOfMemoryException() const {
1217   return type() == OUT_OF_MEMORY_EXCEPTION;
1218 }
1219
1220
1221 AllocationSpace Failure::allocation_space() const {
1222   ASSERT_EQ(RETRY_AFTER_GC, type());
1223   return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
1224                                       & kSpaceTagMask);
1225 }
1226
1227
1228 Failure* Failure::InternalError() {
1229   return Construct(INTERNAL_ERROR);
1230 }
1231
1232
1233 Failure* Failure::Exception() {
1234   return Construct(EXCEPTION);
1235 }
1236
1237
1238 Failure* Failure::OutOfMemoryException(intptr_t value) {
1239   return Construct(OUT_OF_MEMORY_EXCEPTION, value);
1240 }
1241
1242
1243 intptr_t Failure::value() const {
1244   return static_cast<intptr_t>(
1245       reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
1246 }
1247
1248
1249 Failure* Failure::RetryAfterGC() {
1250   return RetryAfterGC(NEW_SPACE);
1251 }
1252
1253
1254 Failure* Failure::RetryAfterGC(AllocationSpace space) {
1255   ASSERT((space & ~kSpaceTagMask) == 0);
1256   return Construct(RETRY_AFTER_GC, space);
1257 }
1258
1259
1260 Failure* Failure::Construct(Type type, intptr_t value) {
1261   uintptr_t info =
1262       (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1263   ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1264   // Fill the unused bits with a pattern that's easy to recognize in crash
1265   // dumps.
1266   static const int kFailureMagicPattern = 0x0BAD0000;
1267   return reinterpret_cast<Failure*>(
1268       (info << kFailureTagSize) | kFailureTag | kFailureMagicPattern);
1269 }
1270
1271
1272 bool Smi::IsValid(intptr_t value) {
1273   bool result = Internals::IsValidSmi(value);
1274   ASSERT_EQ(result, value >= kMinValue && value <= kMaxValue);
1275   return result;
1276 }
1277
1278
1279 MapWord MapWord::FromMap(Map* map) {
1280   return MapWord(reinterpret_cast<uintptr_t>(map));
1281 }
1282
1283
1284 Map* MapWord::ToMap() {
1285   return reinterpret_cast<Map*>(value_);
1286 }
1287
1288
1289 bool MapWord::IsForwardingAddress() {
1290   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1291 }
1292
1293
1294 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1295   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1296   return MapWord(reinterpret_cast<uintptr_t>(raw));
1297 }
1298
1299
1300 HeapObject* MapWord::ToForwardingAddress() {
1301   ASSERT(IsForwardingAddress());
1302   return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1303 }
1304
1305
1306 #ifdef VERIFY_HEAP
1307 void HeapObject::VerifyObjectField(int offset) {
1308   VerifyPointer(READ_FIELD(this, offset));
1309 }
1310
1311 void HeapObject::VerifySmiField(int offset) {
1312   CHECK(READ_FIELD(this, offset)->IsSmi());
1313 }
1314 #endif
1315
1316
1317 Heap* HeapObject::GetHeap() {
1318   Heap* heap =
1319       MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1320   SLOW_ASSERT(heap != NULL);
1321   return heap;
1322 }
1323
1324
1325 Isolate* HeapObject::GetIsolate() {
1326   return GetHeap()->isolate();
1327 }
1328
1329
1330 Map* HeapObject::map() {
1331   return map_word().ToMap();
1332 }
1333
1334
1335 void HeapObject::set_map(Map* value) {
1336   set_map_word(MapWord::FromMap(value));
1337   if (value != NULL) {
1338     // TODO(1600) We are passing NULL as a slot because maps can never be on
1339     // evacuation candidate.
1340     value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1341   }
1342 }
1343
1344
1345 // Unsafe accessor omitting write barrier.
1346 void HeapObject::set_map_no_write_barrier(Map* value) {
1347   set_map_word(MapWord::FromMap(value));
1348 }
1349
1350
1351 MapWord HeapObject::map_word() {
1352   return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1353 }
1354
1355
1356 void HeapObject::set_map_word(MapWord map_word) {
1357   // WRITE_FIELD does not invoke write barrier, but there is no need
1358   // here.
1359   WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1360 }
1361
1362
1363 HeapObject* HeapObject::FromAddress(Address address) {
1364   ASSERT_TAG_ALIGNED(address);
1365   return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1366 }
1367
1368
1369 Address HeapObject::address() {
1370   return reinterpret_cast<Address>(this) - kHeapObjectTag;
1371 }
1372
1373
1374 int HeapObject::Size() {
1375   return SizeFromMap(map());
1376 }
1377
1378
1379 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1380   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1381                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1382 }
1383
1384
1385 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1386   v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1387 }
1388
1389
1390 double HeapNumber::value() {
1391   return READ_DOUBLE_FIELD(this, kValueOffset);
1392 }
1393
1394
1395 void HeapNumber::set_value(double value) {
1396   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1397 }
1398
1399
1400 int HeapNumber::get_exponent() {
1401   return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1402           kExponentShift) - kExponentBias;
1403 }
1404
1405
1406 int HeapNumber::get_sign() {
1407   return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1408 }
1409
1410
1411 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1412
1413
1414 Object** FixedArray::GetFirstElementAddress() {
1415   return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
1416 }
1417
1418
1419 bool FixedArray::ContainsOnlySmisOrHoles() {
1420   Object* the_hole = GetHeap()->the_hole_value();
1421   Object** current = GetFirstElementAddress();
1422   for (int i = 0; i < length(); ++i) {
1423     Object* candidate = *current++;
1424     if (!candidate->IsSmi() && candidate != the_hole) return false;
1425   }
1426   return true;
1427 }
1428
1429
1430 FixedArrayBase* JSObject::elements() {
1431   Object* array = READ_FIELD(this, kElementsOffset);
1432   return static_cast<FixedArrayBase*>(array);
1433 }
1434
1435
1436 void JSObject::ValidateElements() {
1437 #ifdef ENABLE_SLOW_ASSERTS
1438   if (FLAG_enable_slow_asserts) {
1439     ElementsAccessor* accessor = GetElementsAccessor();
1440     accessor->Validate(this);
1441   }
1442 #endif
1443 }
1444
1445
1446 void AllocationSite::Initialize() {
1447   set_transition_info(Smi::FromInt(0));
1448   SetElementsKind(GetInitialFastElementsKind());
1449   set_nested_site(Smi::FromInt(0));
1450   set_pretenure_data(Smi::FromInt(0));
1451   set_pretenure_create_count(Smi::FromInt(0));
1452   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
1453                      SKIP_WRITE_BARRIER);
1454 }
1455
1456
1457 void AllocationSite::MarkZombie() {
1458   ASSERT(!IsZombie());
1459   Initialize();
1460   set_pretenure_decision(kZombie);
1461 }
1462
1463
1464 // Heuristic: We only need to create allocation site info if the boilerplate
1465 // elements kind is the initial elements kind.
1466 AllocationSiteMode AllocationSite::GetMode(
1467     ElementsKind boilerplate_elements_kind) {
1468   if (IsFastSmiElementsKind(boilerplate_elements_kind)) {
1469     return TRACK_ALLOCATION_SITE;
1470   }
1471
1472   return DONT_TRACK_ALLOCATION_SITE;
1473 }
1474
1475
1476 AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
1477                                            ElementsKind to) {
1478   if (IsFastSmiElementsKind(from) &&
1479       IsMoreGeneralElementsKindTransition(from, to)) {
1480     return TRACK_ALLOCATION_SITE;
1481   }
1482
1483   return DONT_TRACK_ALLOCATION_SITE;
1484 }
1485
1486
1487 inline bool AllocationSite::CanTrack(InstanceType type) {
1488   if (FLAG_allocation_site_pretenuring) {
1489     return type == JS_ARRAY_TYPE ||
1490         type == JS_OBJECT_TYPE ||
1491         type < FIRST_NONSTRING_TYPE;
1492   }
1493   return type == JS_ARRAY_TYPE;
1494 }
1495
1496
1497 inline DependentCode::DependencyGroup AllocationSite::ToDependencyGroup(
1498     Reason reason) {
1499   switch (reason) {
1500     case TENURING:
1501       return DependentCode::kAllocationSiteTenuringChangedGroup;
1502       break;
1503     case TRANSITIONS:
1504       return DependentCode::kAllocationSiteTransitionChangedGroup;
1505       break;
1506   }
1507   UNREACHABLE();
1508   return DependentCode::kAllocationSiteTransitionChangedGroup;
1509 }
1510
1511
1512 inline void AllocationSite::set_memento_found_count(int count) {
1513   int value = pretenure_data()->value();
1514   // Verify that we can count more mementos than we can possibly find in one
1515   // new space collection.
1516   ASSERT((GetHeap()->MaxSemiSpaceSize() /
1517           (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
1518            AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
1519   ASSERT(count < MementoFoundCountBits::kMax);
1520   set_pretenure_data(
1521       Smi::FromInt(MementoFoundCountBits::update(value, count)),
1522       SKIP_WRITE_BARRIER);
1523 }
1524
1525 inline bool AllocationSite::IncrementMementoFoundCount() {
1526   if (IsZombie()) return false;
1527
1528   int value = memento_found_count();
1529   set_memento_found_count(value + 1);
1530   return value == 0;
1531 }
1532
1533
1534 inline void AllocationSite::IncrementMementoCreateCount() {
1535   ASSERT(FLAG_allocation_site_pretenuring);
1536   int value = memento_create_count();
1537   set_memento_create_count(value + 1);
1538 }
1539
1540
1541 inline bool AllocationSite::DigestPretenuringFeedback() {
1542   bool decision_changed = false;
1543   int create_count = memento_create_count();
1544   if (create_count >= kPretenureMinimumCreated) {
1545     int found_count = memento_found_count();
1546     double ratio = static_cast<double>(found_count) / create_count;
1547     if (FLAG_trace_track_allocation_sites) {
1548       PrintF("AllocationSite: %p (created, found, ratio) (%d, %d, %f)\n",
1549              static_cast<void*>(this), create_count, found_count, ratio);
1550     }
1551     int current_mode = GetPretenureMode();
1552     PretenureDecision result = ratio >= kPretenureRatio
1553         ? kTenure
1554         : kDontTenure;
1555     set_pretenure_decision(result);
1556     if (current_mode != GetPretenureMode()) {
1557       decision_changed = true;
1558       dependent_code()->MarkCodeForDeoptimization(
1559           GetIsolate(),
1560           DependentCode::kAllocationSiteTenuringChangedGroup);
1561     }
1562   }
1563
1564   // Clear feedback calculation fields until the next gc.
1565   set_memento_found_count(0);
1566   set_memento_create_count(0);
1567   return decision_changed;
1568 }
1569
1570
1571 void JSObject::EnsureCanContainHeapObjectElements(Handle<JSObject> object) {
1572   object->ValidateElements();
1573   ElementsKind elements_kind = object->map()->elements_kind();
1574   if (!IsFastObjectElementsKind(elements_kind)) {
1575     if (IsFastHoleyElementsKind(elements_kind)) {
1576       TransitionElementsKind(object, FAST_HOLEY_ELEMENTS);
1577     } else {
1578       TransitionElementsKind(object, FAST_ELEMENTS);
1579     }
1580   }
1581 }
1582
1583
1584 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1585                                                 uint32_t count,
1586                                                 EnsureElementsMode mode) {
1587   ElementsKind current_kind = map()->elements_kind();
1588   ElementsKind target_kind = current_kind;
1589   ASSERT(mode != ALLOW_COPIED_DOUBLE_ELEMENTS);
1590   bool is_holey = IsFastHoleyElementsKind(current_kind);
1591   if (current_kind == FAST_HOLEY_ELEMENTS) return this;
1592   Heap* heap = GetHeap();
1593   Object* the_hole = heap->the_hole_value();
1594   for (uint32_t i = 0; i < count; ++i) {
1595     Object* current = *objects++;
1596     if (current == the_hole) {
1597       is_holey = true;
1598       target_kind = GetHoleyElementsKind(target_kind);
1599     } else if (!current->IsSmi()) {
1600       if (mode == ALLOW_CONVERTED_DOUBLE_ELEMENTS && current->IsNumber()) {
1601         if (IsFastSmiElementsKind(target_kind)) {
1602           if (is_holey) {
1603             target_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
1604           } else {
1605             target_kind = FAST_DOUBLE_ELEMENTS;
1606           }
1607         }
1608       } else if (is_holey) {
1609         target_kind = FAST_HOLEY_ELEMENTS;
1610         break;
1611       } else {
1612         target_kind = FAST_ELEMENTS;
1613       }
1614     }
1615   }
1616
1617   if (target_kind != current_kind) {
1618     return TransitionElementsKind(target_kind);
1619   }
1620   return this;
1621 }
1622
1623
1624 MaybeObject* JSObject::EnsureCanContainElements(FixedArrayBase* elements,
1625                                                 uint32_t length,
1626                                                 EnsureElementsMode mode) {
1627   if (elements->map() != GetHeap()->fixed_double_array_map()) {
1628     ASSERT(elements->map() == GetHeap()->fixed_array_map() ||
1629            elements->map() == GetHeap()->fixed_cow_array_map());
1630     if (mode == ALLOW_COPIED_DOUBLE_ELEMENTS) {
1631       mode = DONT_ALLOW_DOUBLE_ELEMENTS;
1632     }
1633     Object** objects = FixedArray::cast(elements)->GetFirstElementAddress();
1634     return EnsureCanContainElements(objects, length, mode);
1635   }
1636
1637   ASSERT(mode == ALLOW_COPIED_DOUBLE_ELEMENTS);
1638   if (GetElementsKind() == FAST_HOLEY_SMI_ELEMENTS) {
1639     return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS);
1640   } else if (GetElementsKind() == FAST_SMI_ELEMENTS) {
1641     FixedDoubleArray* double_array = FixedDoubleArray::cast(elements);
1642     for (uint32_t i = 0; i < length; ++i) {
1643       if (double_array->is_the_hole(i)) {
1644         return TransitionElementsKind(FAST_HOLEY_DOUBLE_ELEMENTS);
1645       }
1646     }
1647     return TransitionElementsKind(FAST_DOUBLE_ELEMENTS);
1648   }
1649
1650   return this;
1651 }
1652
1653
1654 MaybeObject* JSObject::GetElementsTransitionMap(Isolate* isolate,
1655                                                 ElementsKind to_kind) {
1656   Map* current_map = map();
1657   ElementsKind from_kind = current_map->elements_kind();
1658   if (from_kind == to_kind) return current_map;
1659
1660   Context* native_context = isolate->context()->native_context();
1661   Object* maybe_array_maps = native_context->js_array_maps();
1662   if (maybe_array_maps->IsFixedArray()) {
1663     FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
1664     if (array_maps->get(from_kind) == current_map) {
1665       Object* maybe_transitioned_map = array_maps->get(to_kind);
1666       if (maybe_transitioned_map->IsMap()) {
1667         return Map::cast(maybe_transitioned_map);
1668       }
1669     }
1670   }
1671
1672   return GetElementsTransitionMapSlow(to_kind);
1673 }
1674
1675
1676 void JSObject::set_map_and_elements(Map* new_map,
1677                                     FixedArrayBase* value,
1678                                     WriteBarrierMode mode) {
1679   ASSERT(value->HasValidElements());
1680   if (new_map != NULL) {
1681     if (mode == UPDATE_WRITE_BARRIER) {
1682       set_map(new_map);
1683     } else {
1684       ASSERT(mode == SKIP_WRITE_BARRIER);
1685       set_map_no_write_barrier(new_map);
1686     }
1687   }
1688   ASSERT((map()->has_fast_smi_or_object_elements() ||
1689           (value == GetHeap()->empty_fixed_array())) ==
1690          (value->map() == GetHeap()->fixed_array_map() ||
1691           value->map() == GetHeap()->fixed_cow_array_map()));
1692   ASSERT((value == GetHeap()->empty_fixed_array()) ||
1693          (map()->has_fast_double_elements() == value->IsFixedDoubleArray()));
1694   WRITE_FIELD(this, kElementsOffset, value);
1695   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1696 }
1697
1698
1699 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1700   set_map_and_elements(NULL, value, mode);
1701 }
1702
1703
1704 void JSObject::initialize_properties() {
1705   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1706   WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1707 }
1708
1709
1710 void JSObject::initialize_elements() {
1711   if (map()->has_fast_smi_or_object_elements() ||
1712       map()->has_fast_double_elements()) {
1713     ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1714     WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1715   } else if (map()->has_external_array_elements()) {
1716     ExternalArray* empty_array = GetHeap()->EmptyExternalArrayForMap(map());
1717     ASSERT(!GetHeap()->InNewSpace(empty_array));
1718     WRITE_FIELD(this, kElementsOffset, empty_array);
1719   } else {
1720     UNREACHABLE();
1721   }
1722 }
1723
1724
1725 MaybeObject* JSObject::ResetElements() {
1726   if (map()->is_observed()) {
1727     // Maintain invariant that observed elements are always in dictionary mode.
1728     SeededNumberDictionary* dictionary;
1729     MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0);
1730     if (!maybe->To(&dictionary)) return maybe;
1731     if (map() == GetHeap()->non_strict_arguments_elements_map()) {
1732       FixedArray::cast(elements())->set(1, dictionary);
1733     } else {
1734       set_elements(dictionary);
1735     }
1736     return this;
1737   }
1738
1739   ElementsKind elements_kind = GetInitialFastElementsKind();
1740   if (!FLAG_smi_only_arrays) {
1741     elements_kind = FastSmiToObjectElementsKind(elements_kind);
1742   }
1743   MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
1744   Map* map;
1745   if (!maybe->To(&map)) return maybe;
1746   set_map(map);
1747   initialize_elements();
1748
1749   return this;
1750 }
1751
1752
1753 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) {
1754   DisallowHeapAllocation no_gc;
1755   if (!map->HasTransitionArray()) return Handle<String>::null();
1756   TransitionArray* transitions = map->transitions();
1757   if (!transitions->IsSimpleTransition()) return Handle<String>::null();
1758   int transition = TransitionArray::kSimpleTransitionIndex;
1759   PropertyDetails details = transitions->GetTargetDetails(transition);
1760   Name* name = transitions->GetKey(transition);
1761   if (details.type() != FIELD) return Handle<String>::null();
1762   if (details.attributes() != NONE) return Handle<String>::null();
1763   if (!name->IsString()) return Handle<String>::null();
1764   return Handle<String>(String::cast(name));
1765 }
1766
1767
1768 Handle<Map> JSObject::ExpectedTransitionTarget(Handle<Map> map) {
1769   ASSERT(!ExpectedTransitionKey(map).is_null());
1770   return Handle<Map>(map->transitions()->GetTarget(
1771       TransitionArray::kSimpleTransitionIndex));
1772 }
1773
1774
1775 Handle<Map> JSObject::FindTransitionToField(Handle<Map> map, Handle<Name> key) {
1776   DisallowHeapAllocation no_allocation;
1777   if (!map->HasTransitionArray()) return Handle<Map>::null();
1778   TransitionArray* transitions = map->transitions();
1779   int transition = transitions->Search(*key);
1780   if (transition == TransitionArray::kNotFound) return Handle<Map>::null();
1781   PropertyDetails target_details = transitions->GetTargetDetails(transition);
1782   if (target_details.type() != FIELD) return Handle<Map>::null();
1783   if (target_details.attributes() != NONE) return Handle<Map>::null();
1784   return Handle<Map>(transitions->GetTarget(transition));
1785 }
1786
1787
1788 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1789 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1790
1791
1792 byte Oddball::kind() {
1793   return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1794 }
1795
1796
1797 void Oddball::set_kind(byte value) {
1798   WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1799 }
1800
1801
1802 Object* Cell::value() {
1803   return READ_FIELD(this, kValueOffset);
1804 }
1805
1806
1807 void Cell::set_value(Object* val, WriteBarrierMode ignored) {
1808   // The write barrier is not used for global property cells.
1809   ASSERT(!val->IsPropertyCell() && !val->IsCell());
1810   WRITE_FIELD(this, kValueOffset, val);
1811 }
1812
1813 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
1814
1815 Object* PropertyCell::type_raw() {
1816   return READ_FIELD(this, kTypeOffset);
1817 }
1818
1819
1820 void PropertyCell::set_type_raw(Object* val, WriteBarrierMode ignored) {
1821   WRITE_FIELD(this, kTypeOffset, val);
1822 }
1823
1824
1825 int JSObject::GetHeaderSize() {
1826   InstanceType type = map()->instance_type();
1827   // Check for the most common kind of JavaScript object before
1828   // falling into the generic switch. This speeds up the internal
1829   // field operations considerably on average.
1830   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1831   switch (type) {
1832     case JS_GENERATOR_OBJECT_TYPE:
1833       return JSGeneratorObject::kSize;
1834     case JS_MODULE_TYPE:
1835       return JSModule::kSize;
1836     case JS_GLOBAL_PROXY_TYPE:
1837       return JSGlobalProxy::kSize;
1838     case JS_GLOBAL_OBJECT_TYPE:
1839       return JSGlobalObject::kSize;
1840     case JS_BUILTINS_OBJECT_TYPE:
1841       return JSBuiltinsObject::kSize;
1842     case JS_FUNCTION_TYPE:
1843       return JSFunction::kSize;
1844     case JS_VALUE_TYPE:
1845       return JSValue::kSize;
1846     case JS_DATE_TYPE:
1847       return JSDate::kSize;
1848     case JS_ARRAY_TYPE:
1849       return JSArray::kSize;
1850     case JS_ARRAY_BUFFER_TYPE:
1851       return JSArrayBuffer::kSize;
1852     case JS_TYPED_ARRAY_TYPE:
1853       return JSTypedArray::kSize;
1854     case JS_DATA_VIEW_TYPE:
1855       return JSDataView::kSize;
1856     case JS_SET_TYPE:
1857       return JSSet::kSize;
1858     case JS_MAP_TYPE:
1859       return JSMap::kSize;
1860     case JS_WEAK_MAP_TYPE:
1861       return JSWeakMap::kSize;
1862     case JS_WEAK_SET_TYPE:
1863       return JSWeakSet::kSize;
1864     case JS_REGEXP_TYPE:
1865       return JSRegExp::kSize;
1866     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1867       return JSObject::kHeaderSize;
1868     case JS_MESSAGE_OBJECT_TYPE:
1869       return JSMessageObject::kSize;
1870     default:
1871       // TODO(jkummerow): Re-enable this. Blink currently hits this
1872       // from its CustomElementConstructorBuilder.
1873       // UNREACHABLE();
1874       return 0;
1875   }
1876 }
1877
1878
1879 int JSObject::GetInternalFieldCount() {
1880   ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1881   // Make sure to adjust for the number of in-object properties. These
1882   // properties do contribute to the size, but are not internal fields.
1883   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1884          map()->inobject_properties();
1885 }
1886
1887
1888 int JSObject::GetInternalFieldOffset(int index) {
1889   ASSERT(index < GetInternalFieldCount() && index >= 0);
1890   return GetHeaderSize() + (kPointerSize * index);
1891 }
1892
1893
1894 Object* JSObject::GetInternalField(int index) {
1895   ASSERT(index < GetInternalFieldCount() && index >= 0);
1896   // Internal objects do follow immediately after the header, whereas in-object
1897   // properties are at the end of the object. Therefore there is no need
1898   // to adjust the index here.
1899   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1900 }
1901
1902
1903 void JSObject::SetInternalField(int index, Object* value) {
1904   ASSERT(index < GetInternalFieldCount() && index >= 0);
1905   // Internal objects do follow immediately after the header, whereas in-object
1906   // properties are at the end of the object. Therefore there is no need
1907   // to adjust the index here.
1908   int offset = GetHeaderSize() + (kPointerSize * index);
1909   WRITE_FIELD(this, offset, value);
1910   WRITE_BARRIER(GetHeap(), this, offset, value);
1911 }
1912
1913
1914 void JSObject::SetInternalField(int index, Smi* value) {
1915   ASSERT(index < GetInternalFieldCount() && index >= 0);
1916   // Internal objects do follow immediately after the header, whereas in-object
1917   // properties are at the end of the object. Therefore there is no need
1918   // to adjust the index here.
1919   int offset = GetHeaderSize() + (kPointerSize * index);
1920   WRITE_FIELD(this, offset, value);
1921 }
1922
1923
1924 MaybeObject* JSObject::FastPropertyAt(Representation representation,
1925                                       int index) {
1926   Object* raw_value = RawFastPropertyAt(index);
1927   return raw_value->AllocateNewStorageFor(GetHeap(), representation);
1928 }
1929
1930
1931 // Access fast-case object properties at index. The use of these routines
1932 // is needed to correctly distinguish between properties stored in-object and
1933 // properties stored in the properties array.
1934 Object* JSObject::RawFastPropertyAt(int index) {
1935   // Adjust for the number of properties stored in the object.
1936   index -= map()->inobject_properties();
1937   if (index < 0) {
1938     int offset = map()->instance_size() + (index * kPointerSize);
1939     return READ_FIELD(this, offset);
1940   } else {
1941     ASSERT(index < properties()->length());
1942     return properties()->get(index);
1943   }
1944 }
1945
1946
1947 void JSObject::FastPropertyAtPut(int index, Object* value) {
1948   // Adjust for the number of properties stored in the object.
1949   index -= map()->inobject_properties();
1950   if (index < 0) {
1951     int offset = map()->instance_size() + (index * kPointerSize);
1952     WRITE_FIELD(this, offset, value);
1953     WRITE_BARRIER(GetHeap(), this, offset, value);
1954   } else {
1955     ASSERT(index < properties()->length());
1956     properties()->set(index, value);
1957   }
1958 }
1959
1960
1961 int JSObject::GetInObjectPropertyOffset(int index) {
1962   // Adjust for the number of properties stored in the object.
1963   index -= map()->inobject_properties();
1964   ASSERT(index < 0);
1965   return map()->instance_size() + (index * kPointerSize);
1966 }
1967
1968
1969 Object* JSObject::InObjectPropertyAt(int index) {
1970   // Adjust for the number of properties stored in the object.
1971   index -= map()->inobject_properties();
1972   ASSERT(index < 0);
1973   int offset = map()->instance_size() + (index * kPointerSize);
1974   return READ_FIELD(this, offset);
1975 }
1976
1977
1978 Object* JSObject::InObjectPropertyAtPut(int index,
1979                                         Object* value,
1980                                         WriteBarrierMode mode) {
1981   // Adjust for the number of properties stored in the object.
1982   index -= map()->inobject_properties();
1983   ASSERT(index < 0);
1984   int offset = map()->instance_size() + (index * kPointerSize);
1985   WRITE_FIELD(this, offset, value);
1986   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1987   return value;
1988 }
1989
1990
1991
1992 void JSObject::InitializeBody(Map* map,
1993                               Object* pre_allocated_value,
1994                               Object* filler_value) {
1995   ASSERT(!filler_value->IsHeapObject() ||
1996          !GetHeap()->InNewSpace(filler_value));
1997   ASSERT(!pre_allocated_value->IsHeapObject() ||
1998          !GetHeap()->InNewSpace(pre_allocated_value));
1999   int size = map->instance_size();
2000   int offset = kHeaderSize;
2001   if (filler_value != pre_allocated_value) {
2002     int pre_allocated = map->pre_allocated_property_fields();
2003     ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
2004     for (int i = 0; i < pre_allocated; i++) {
2005       WRITE_FIELD(this, offset, pre_allocated_value);
2006       offset += kPointerSize;
2007     }
2008   }
2009   while (offset < size) {
2010     WRITE_FIELD(this, offset, filler_value);
2011     offset += kPointerSize;
2012   }
2013 }
2014
2015
2016 bool JSObject::HasFastProperties() {
2017   ASSERT(properties()->IsDictionary() == map()->is_dictionary_map());
2018   return !properties()->IsDictionary();
2019 }
2020
2021
2022 bool JSObject::TooManyFastProperties(StoreFromKeyed store_mode) {
2023   // Allow extra fast properties if the object has more than
2024   // kFastPropertiesSoftLimit in-object properties. When this is the case, it is
2025   // very unlikely that the object is being used as a dictionary and there is a
2026   // good chance that allowing more map transitions will be worth it.
2027   Map* map = this->map();
2028   if (map->unused_property_fields() != 0) return false;
2029
2030   int inobject = map->inobject_properties();
2031
2032   int limit;
2033   if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
2034     limit = Max(inobject, kMaxFastProperties);
2035   } else {
2036     limit = Max(inobject, kFastPropertiesSoftLimit);
2037   }
2038   return properties()->length() > limit;
2039 }
2040
2041
2042 void Struct::InitializeBody(int object_size) {
2043   Object* value = GetHeap()->undefined_value();
2044   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
2045     WRITE_FIELD(this, offset, value);
2046   }
2047 }
2048
2049
2050 bool Object::ToArrayIndex(uint32_t* index) {
2051   if (IsSmi()) {
2052     int value = Smi::cast(this)->value();
2053     if (value < 0) return false;
2054     *index = value;
2055     return true;
2056   }
2057   if (IsHeapNumber()) {
2058     double value = HeapNumber::cast(this)->value();
2059     uint32_t uint_value = static_cast<uint32_t>(value);
2060     if (value == static_cast<double>(uint_value)) {
2061       *index = uint_value;
2062       return true;
2063     }
2064   }
2065   return false;
2066 }
2067
2068
2069 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
2070   if (!this->IsJSValue()) return false;
2071
2072   JSValue* js_value = JSValue::cast(this);
2073   if (!js_value->value()->IsString()) return false;
2074
2075   String* str = String::cast(js_value->value());
2076   if (index >= static_cast<uint32_t>(str->length())) return false;
2077
2078   return true;
2079 }
2080
2081
2082
2083 void Object::VerifyApiCallResultType() {
2084 #if ENABLE_EXTRA_CHECKS
2085   if (!(IsSmi() ||
2086         IsString() ||
2087         IsSpecObject() ||
2088         IsHeapNumber() ||
2089         IsUndefined() ||
2090         IsTrue() ||
2091         IsFalse() ||
2092         IsNull())) {
2093     FATAL("API call returned invalid object");
2094   }
2095 #endif  // ENABLE_EXTRA_CHECKS
2096 }
2097
2098
2099 FixedArrayBase* FixedArrayBase::cast(Object* object) {
2100   ASSERT(object->IsFixedArrayBase());
2101   return reinterpret_cast<FixedArrayBase*>(object);
2102 }
2103
2104
2105 Object* FixedArray::get(int index) {
2106   SLOW_ASSERT(index >= 0 && index < this->length());
2107   return READ_FIELD(this, kHeaderSize + index * kPointerSize);
2108 }
2109
2110
2111 bool FixedArray::is_the_hole(int index) {
2112   return get(index) == GetHeap()->the_hole_value();
2113 }
2114
2115
2116 void FixedArray::set(int index, Smi* value) {
2117   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2118   ASSERT(index >= 0 && index < this->length());
2119   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
2120   int offset = kHeaderSize + index * kPointerSize;
2121   WRITE_FIELD(this, offset, value);
2122 }
2123
2124
2125 void FixedArray::set(int index, Object* value) {
2126   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2127   ASSERT(index >= 0 && index < this->length());
2128   int offset = kHeaderSize + index * kPointerSize;
2129   WRITE_FIELD(this, offset, value);
2130   WRITE_BARRIER(GetHeap(), this, offset, value);
2131 }
2132
2133
2134 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
2135   return BitCast<uint64_t, double>(value) == kHoleNanInt64;
2136 }
2137
2138
2139 inline double FixedDoubleArray::hole_nan_as_double() {
2140   return BitCast<double, uint64_t>(kHoleNanInt64);
2141 }
2142
2143
2144 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
2145   ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
2146   ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
2147   return OS::nan_value();
2148 }
2149
2150
2151 double FixedDoubleArray::get_scalar(int index) {
2152   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2153          map() != GetHeap()->fixed_array_map());
2154   ASSERT(index >= 0 && index < this->length());
2155   double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
2156   ASSERT(!is_the_hole_nan(result));
2157   return result;
2158 }
2159
2160 int64_t FixedDoubleArray::get_representation(int index) {
2161   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2162          map() != GetHeap()->fixed_array_map());
2163   ASSERT(index >= 0 && index < this->length());
2164   return READ_INT64_FIELD(this, kHeaderSize + index * kDoubleSize);
2165 }
2166
2167 MaybeObject* FixedDoubleArray::get(int index) {
2168   if (is_the_hole(index)) {
2169     return GetHeap()->the_hole_value();
2170   } else {
2171     return GetHeap()->NumberFromDouble(get_scalar(index));
2172   }
2173 }
2174
2175
2176 void FixedDoubleArray::set(int index, double value) {
2177   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2178          map() != GetHeap()->fixed_array_map());
2179   int offset = kHeaderSize + index * kDoubleSize;
2180   if (std::isnan(value)) value = canonical_not_the_hole_nan_as_double();
2181   WRITE_DOUBLE_FIELD(this, offset, value);
2182 }
2183
2184
2185 void FixedDoubleArray::set_the_hole(int index) {
2186   ASSERT(map() != GetHeap()->fixed_cow_array_map() &&
2187          map() != GetHeap()->fixed_array_map());
2188   int offset = kHeaderSize + index * kDoubleSize;
2189   WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
2190 }
2191
2192
2193 bool FixedDoubleArray::is_the_hole(int index) {
2194   int offset = kHeaderSize + index * kDoubleSize;
2195   return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
2196 }
2197
2198
2199 SMI_ACCESSORS(ConstantPoolArray, first_ptr_index, kFirstPointerIndexOffset)
2200 SMI_ACCESSORS(ConstantPoolArray, first_int32_index, kFirstInt32IndexOffset)
2201
2202
2203 int ConstantPoolArray::first_int64_index() {
2204   return 0;
2205 }
2206
2207
2208 int ConstantPoolArray::count_of_int64_entries() {
2209   return first_ptr_index();
2210 }
2211
2212
2213 int ConstantPoolArray::count_of_ptr_entries() {
2214   return first_int32_index() - first_ptr_index();
2215 }
2216
2217
2218 int ConstantPoolArray::count_of_int32_entries() {
2219   return length() - first_int32_index();
2220 }
2221
2222
2223 void ConstantPoolArray::SetEntryCounts(int number_of_int64_entries,
2224                                        int number_of_ptr_entries,
2225                                        int number_of_int32_entries) {
2226   set_first_ptr_index(number_of_int64_entries);
2227   set_first_int32_index(number_of_int64_entries + number_of_ptr_entries);
2228   set_length(number_of_int64_entries + number_of_ptr_entries +
2229              number_of_int32_entries);
2230 }
2231
2232
2233 int64_t ConstantPoolArray::get_int64_entry(int index) {
2234   ASSERT(map() == GetHeap()->constant_pool_array_map());
2235   ASSERT(index >= 0 && index < first_ptr_index());
2236   return READ_INT64_FIELD(this, OffsetOfElementAt(index));
2237 }
2238
2239 double ConstantPoolArray::get_int64_entry_as_double(int index) {
2240   STATIC_ASSERT(kDoubleSize == kInt64Size);
2241   ASSERT(map() == GetHeap()->constant_pool_array_map());
2242   ASSERT(index >= 0 && index < first_ptr_index());
2243   return READ_DOUBLE_FIELD(this, OffsetOfElementAt(index));
2244 }
2245
2246
2247 Object* ConstantPoolArray::get_ptr_entry(int index) {
2248   ASSERT(map() == GetHeap()->constant_pool_array_map());
2249   ASSERT(index >= first_ptr_index() && index < first_int32_index());
2250   return READ_FIELD(this, OffsetOfElementAt(index));
2251 }
2252
2253
2254 int32_t ConstantPoolArray::get_int32_entry(int index) {
2255   ASSERT(map() == GetHeap()->constant_pool_array_map());
2256   ASSERT(index >= first_int32_index() && index < length());
2257   return READ_INT32_FIELD(this, OffsetOfElementAt(index));
2258 }
2259
2260
2261 void ConstantPoolArray::set(int index, Object* value) {
2262   ASSERT(map() == GetHeap()->constant_pool_array_map());
2263   ASSERT(index >= first_ptr_index() && index < first_int32_index());
2264   WRITE_FIELD(this, OffsetOfElementAt(index), value);
2265   WRITE_BARRIER(GetHeap(), this, OffsetOfElementAt(index), value);
2266 }
2267
2268
2269 void ConstantPoolArray::set(int index, int64_t value) {
2270   ASSERT(map() == GetHeap()->constant_pool_array_map());
2271   ASSERT(index >= first_int64_index() && index < first_ptr_index());
2272   WRITE_INT64_FIELD(this, OffsetOfElementAt(index), value);
2273 }
2274
2275
2276 void ConstantPoolArray::set(int index, double value) {
2277   STATIC_ASSERT(kDoubleSize == kInt64Size);
2278   ASSERT(map() == GetHeap()->constant_pool_array_map());
2279   ASSERT(index >= first_int64_index() && index < first_ptr_index());
2280   WRITE_DOUBLE_FIELD(this, OffsetOfElementAt(index), value);
2281 }
2282
2283
2284 void ConstantPoolArray::set(int index, int32_t value) {
2285   ASSERT(map() == GetHeap()->constant_pool_array_map());
2286   ASSERT(index >= this->first_int32_index() && index < length());
2287   WRITE_INT32_FIELD(this, OffsetOfElementAt(index), value);
2288 }
2289
2290
2291 WriteBarrierMode HeapObject::GetWriteBarrierMode(
2292     const DisallowHeapAllocation& promise) {
2293   Heap* heap = GetHeap();
2294   if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
2295   if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
2296   return UPDATE_WRITE_BARRIER;
2297 }
2298
2299
2300 void FixedArray::set(int index,
2301                      Object* value,
2302                      WriteBarrierMode mode) {
2303   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2304   ASSERT(index >= 0 && index < this->length());
2305   int offset = kHeaderSize + index * kPointerSize;
2306   WRITE_FIELD(this, offset, value);
2307   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
2308 }
2309
2310
2311 void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
2312                                               int index,
2313                                               Object* value) {
2314   ASSERT(array->map() != array->GetHeap()->fixed_cow_array_map());
2315   ASSERT(index >= 0 && index < array->length());
2316   int offset = kHeaderSize + index * kPointerSize;
2317   WRITE_FIELD(array, offset, value);
2318   Heap* heap = array->GetHeap();
2319   if (heap->InNewSpace(value)) {
2320     heap->RecordWrite(array->address(), offset);
2321   }
2322 }
2323
2324
2325 void FixedArray::NoWriteBarrierSet(FixedArray* array,
2326                                    int index,
2327                                    Object* value) {
2328   ASSERT(array->map() != array->GetHeap()->fixed_cow_array_map());
2329   ASSERT(index >= 0 && index < array->length());
2330   ASSERT(!array->GetHeap()->InNewSpace(value));
2331   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
2332 }
2333
2334
2335 void FixedArray::set_undefined(int index) {
2336   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2337   ASSERT(index >= 0 && index < this->length());
2338   ASSERT(!GetHeap()->InNewSpace(GetHeap()->undefined_value()));
2339   WRITE_FIELD(this,
2340               kHeaderSize + index * kPointerSize,
2341               GetHeap()->undefined_value());
2342 }
2343
2344
2345 void FixedArray::set_null(int index) {
2346   ASSERT(index >= 0 && index < this->length());
2347   ASSERT(!GetHeap()->InNewSpace(GetHeap()->null_value()));
2348   WRITE_FIELD(this,
2349               kHeaderSize + index * kPointerSize,
2350               GetHeap()->null_value());
2351 }
2352
2353
2354 void FixedArray::set_the_hole(int index) {
2355   ASSERT(map() != GetHeap()->fixed_cow_array_map());
2356   ASSERT(index >= 0 && index < this->length());
2357   ASSERT(!GetHeap()->InNewSpace(GetHeap()->the_hole_value()));
2358   WRITE_FIELD(this,
2359               kHeaderSize + index * kPointerSize,
2360               GetHeap()->the_hole_value());
2361 }
2362
2363
2364 double* FixedDoubleArray::data_start() {
2365   return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
2366 }
2367
2368
2369 Object** FixedArray::data_start() {
2370   return HeapObject::RawField(this, kHeaderSize);
2371 }
2372
2373
2374 bool DescriptorArray::IsEmpty() {
2375   ASSERT(length() >= kFirstIndex ||
2376          this == GetHeap()->empty_descriptor_array());
2377   return length() < kFirstIndex;
2378 }
2379
2380
2381 void DescriptorArray::SetNumberOfDescriptors(int number_of_descriptors) {
2382   WRITE_FIELD(
2383       this, kDescriptorLengthOffset, Smi::FromInt(number_of_descriptors));
2384 }
2385
2386
2387 // Perform a binary search in a fixed array. Low and high are entry indices. If
2388 // there are three entries in this array it should be called with low=0 and
2389 // high=2.
2390 template<SearchMode search_mode, typename T>
2391 int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
2392   uint32_t hash = name->Hash();
2393   int limit = high;
2394
2395   ASSERT(low <= high);
2396
2397   while (low != high) {
2398     int mid = (low + high) / 2;
2399     Name* mid_name = array->GetSortedKey(mid);
2400     uint32_t mid_hash = mid_name->Hash();
2401
2402     if (mid_hash >= hash) {
2403       high = mid;
2404     } else {
2405       low = mid + 1;
2406     }
2407   }
2408
2409   for (; low <= limit; ++low) {
2410     int sort_index = array->GetSortedKeyIndex(low);
2411     Name* entry = array->GetKey(sort_index);
2412     if (entry->Hash() != hash) break;
2413     if (entry->Equals(name)) {
2414       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
2415         return sort_index;
2416       }
2417       return T::kNotFound;
2418     }
2419   }
2420
2421   return T::kNotFound;
2422 }
2423
2424
2425 // Perform a linear search in this fixed array. len is the number of entry
2426 // indices that are valid.
2427 template<SearchMode search_mode, typename T>
2428 int LinearSearch(T* array, Name* name, int len, int valid_entries) {
2429   uint32_t hash = name->Hash();
2430   if (search_mode == ALL_ENTRIES) {
2431     for (int number = 0; number < len; number++) {
2432       int sorted_index = array->GetSortedKeyIndex(number);
2433       Name* entry = array->GetKey(sorted_index);
2434       uint32_t current_hash = entry->Hash();
2435       if (current_hash > hash) break;
2436       if (current_hash == hash && entry->Equals(name)) return sorted_index;
2437     }
2438   } else {
2439     ASSERT(len >= valid_entries);
2440     for (int number = 0; number < valid_entries; number++) {
2441       Name* entry = array->GetKey(number);
2442       uint32_t current_hash = entry->Hash();
2443       if (current_hash == hash && entry->Equals(name)) return number;
2444     }
2445   }
2446   return T::kNotFound;
2447 }
2448
2449
2450 template<SearchMode search_mode, typename T>
2451 int Search(T* array, Name* name, int valid_entries) {
2452   if (search_mode == VALID_ENTRIES) {
2453     SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
2454   } else {
2455     SLOW_ASSERT(array->IsSortedNoDuplicates());
2456   }
2457
2458   int nof = array->number_of_entries();
2459   if (nof == 0) return T::kNotFound;
2460
2461   // Fast case: do linear search for small arrays.
2462   const int kMaxElementsForLinearSearch = 8;
2463   if ((search_mode == ALL_ENTRIES &&
2464        nof <= kMaxElementsForLinearSearch) ||
2465       (search_mode == VALID_ENTRIES &&
2466        valid_entries <= (kMaxElementsForLinearSearch * 3))) {
2467     return LinearSearch<search_mode>(array, name, nof, valid_entries);
2468   }
2469
2470   // Slow case: perform binary search.
2471   return BinarySearch<search_mode>(array, name, 0, nof - 1, valid_entries);
2472 }
2473
2474
2475 int DescriptorArray::Search(Name* name, int valid_descriptors) {
2476   return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
2477 }
2478
2479
2480 int DescriptorArray::SearchWithCache(Name* name, Map* map) {
2481   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
2482   if (number_of_own_descriptors == 0) return kNotFound;
2483
2484   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
2485   int number = cache->Lookup(map, name);
2486
2487   if (number == DescriptorLookupCache::kAbsent) {
2488     number = Search(name, number_of_own_descriptors);
2489     cache->Update(map, name, number);
2490   }
2491
2492   return number;
2493 }
2494
2495
2496 void Map::LookupDescriptor(JSObject* holder,
2497                            Name* name,
2498                            LookupResult* result) {
2499   DescriptorArray* descriptors = this->instance_descriptors();
2500   int number = descriptors->SearchWithCache(name, this);
2501   if (number == DescriptorArray::kNotFound) return result->NotFound();
2502   result->DescriptorResult(holder, descriptors->GetDetails(number), number);
2503 }
2504
2505
2506 void Map::LookupTransition(JSObject* holder,
2507                            Name* name,
2508                            LookupResult* result) {
2509   if (HasTransitionArray()) {
2510     TransitionArray* transition_array = transitions();
2511     int number = transition_array->Search(name);
2512     if (number != TransitionArray::kNotFound) {
2513       return result->TransitionResult(holder, number);
2514     }
2515   }
2516   result->NotFound();
2517 }
2518
2519
2520 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
2521   ASSERT(descriptor_number < number_of_descriptors());
2522   return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
2523 }
2524
2525
2526 Object** DescriptorArray::GetDescriptorStartSlot(int descriptor_number) {
2527   return GetKeySlot(descriptor_number);
2528 }
2529
2530
2531 Object** DescriptorArray::GetDescriptorEndSlot(int descriptor_number) {
2532   return GetValueSlot(descriptor_number - 1) + 1;
2533 }
2534
2535
2536 Name* DescriptorArray::GetKey(int descriptor_number) {
2537   ASSERT(descriptor_number < number_of_descriptors());
2538   return Name::cast(get(ToKeyIndex(descriptor_number)));
2539 }
2540
2541
2542 int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
2543   return GetDetails(descriptor_number).pointer();
2544 }
2545
2546
2547 Name* DescriptorArray::GetSortedKey(int descriptor_number) {
2548   return GetKey(GetSortedKeyIndex(descriptor_number));
2549 }
2550
2551
2552 void DescriptorArray::SetSortedKey(int descriptor_index, int pointer) {
2553   PropertyDetails details = GetDetails(descriptor_index);
2554   set(ToDetailsIndex(descriptor_index), details.set_pointer(pointer).AsSmi());
2555 }
2556
2557
2558 void DescriptorArray::SetRepresentation(int descriptor_index,
2559                                         Representation representation) {
2560   ASSERT(!representation.IsNone());
2561   PropertyDetails details = GetDetails(descriptor_index);
2562   set(ToDetailsIndex(descriptor_index),
2563       details.CopyWithRepresentation(representation).AsSmi());
2564 }
2565
2566
2567 void DescriptorArray::InitializeRepresentations(Representation representation) {
2568   int length = number_of_descriptors();
2569   for (int i = 0; i < length; i++) {
2570     SetRepresentation(i, representation);
2571   }
2572 }
2573
2574
2575 Object** DescriptorArray::GetValueSlot(int descriptor_number) {
2576   ASSERT(descriptor_number < number_of_descriptors());
2577   return RawFieldOfElementAt(ToValueIndex(descriptor_number));
2578 }
2579
2580
2581 Object* DescriptorArray::GetValue(int descriptor_number) {
2582   ASSERT(descriptor_number < number_of_descriptors());
2583   return get(ToValueIndex(descriptor_number));
2584 }
2585
2586
2587 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) {
2588   ASSERT(descriptor_number < number_of_descriptors());
2589   Object* details = get(ToDetailsIndex(descriptor_number));
2590   return PropertyDetails(Smi::cast(details));
2591 }
2592
2593
2594 PropertyType DescriptorArray::GetType(int descriptor_number) {
2595   return GetDetails(descriptor_number).type();
2596 }
2597
2598
2599 int DescriptorArray::GetFieldIndex(int descriptor_number) {
2600   ASSERT(GetDetails(descriptor_number).type() == FIELD);
2601   return GetDetails(descriptor_number).field_index();
2602 }
2603
2604
2605 Object* DescriptorArray::GetConstant(int descriptor_number) {
2606   return GetValue(descriptor_number);
2607 }
2608
2609
2610 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
2611   ASSERT(GetType(descriptor_number) == CALLBACKS);
2612   return GetValue(descriptor_number);
2613 }
2614
2615
2616 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
2617   ASSERT(GetType(descriptor_number) == CALLBACKS);
2618   Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
2619   return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
2620 }
2621
2622
2623 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
2624   desc->Init(GetKey(descriptor_number),
2625              GetValue(descriptor_number),
2626              GetDetails(descriptor_number));
2627 }
2628
2629
2630 void DescriptorArray::Set(int descriptor_number,
2631                           Descriptor* desc,
2632                           const WhitenessWitness&) {
2633   // Range check.
2634   ASSERT(descriptor_number < number_of_descriptors());
2635
2636   NoIncrementalWriteBarrierSet(this,
2637                                ToKeyIndex(descriptor_number),
2638                                desc->GetKey());
2639   NoIncrementalWriteBarrierSet(this,
2640                                ToValueIndex(descriptor_number),
2641                                desc->GetValue());
2642   NoIncrementalWriteBarrierSet(this,
2643                                ToDetailsIndex(descriptor_number),
2644                                desc->GetDetails().AsSmi());
2645 }
2646
2647
2648 void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
2649   // Range check.
2650   ASSERT(descriptor_number < number_of_descriptors());
2651
2652   set(ToKeyIndex(descriptor_number), desc->GetKey());
2653   set(ToValueIndex(descriptor_number), desc->GetValue());
2654   set(ToDetailsIndex(descriptor_number), desc->GetDetails().AsSmi());
2655 }
2656
2657
2658 void DescriptorArray::Append(Descriptor* desc,
2659                              const WhitenessWitness& witness) {
2660   int descriptor_number = number_of_descriptors();
2661   SetNumberOfDescriptors(descriptor_number + 1);
2662   Set(descriptor_number, desc, witness);
2663
2664   uint32_t hash = desc->GetKey()->Hash();
2665
2666   int insertion;
2667
2668   for (insertion = descriptor_number; insertion > 0; --insertion) {
2669     Name* key = GetSortedKey(insertion - 1);
2670     if (key->Hash() <= hash) break;
2671     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
2672   }
2673
2674   SetSortedKey(insertion, descriptor_number);
2675 }
2676
2677
2678 void DescriptorArray::Append(Descriptor* desc) {
2679   int descriptor_number = number_of_descriptors();
2680   SetNumberOfDescriptors(descriptor_number + 1);
2681   Set(descriptor_number, desc);
2682
2683   uint32_t hash = desc->GetKey()->Hash();
2684
2685   int insertion;
2686
2687   for (insertion = descriptor_number; insertion > 0; --insertion) {
2688     Name* key = GetSortedKey(insertion - 1);
2689     if (key->Hash() <= hash) break;
2690     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
2691   }
2692
2693   SetSortedKey(insertion, descriptor_number);
2694 }
2695
2696
2697 void DescriptorArray::SwapSortedKeys(int first, int second) {
2698   int first_key = GetSortedKeyIndex(first);
2699   SetSortedKey(first, GetSortedKeyIndex(second));
2700   SetSortedKey(second, first_key);
2701 }
2702
2703
2704 DescriptorArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
2705     : marking_(array->GetHeap()->incremental_marking()) {
2706   marking_->EnterNoMarkingScope();
2707   ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
2708 }
2709
2710
2711 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
2712   marking_->LeaveNoMarkingScope();
2713 }
2714
2715
2716 template<typename Shape, typename Key>
2717 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
2718   const int kMinCapacity = 32;
2719   int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
2720   if (capacity < kMinCapacity) {
2721     capacity = kMinCapacity;  // Guarantee min capacity.
2722   }
2723   return capacity;
2724 }
2725
2726
2727 template<typename Shape, typename Key>
2728 int HashTable<Shape, Key>::FindEntry(Key key) {
2729   return FindEntry(GetIsolate(), key);
2730 }
2731
2732
2733 // Find entry for key otherwise return kNotFound.
2734 template<typename Shape, typename Key>
2735 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
2736   uint32_t capacity = Capacity();
2737   uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity);
2738   uint32_t count = 1;
2739   // EnsureCapacity will guarantee the hash table is never full.
2740   while (true) {
2741     Object* element = KeyAt(entry);
2742     // Empty entry. Uses raw unchecked accessors because it is called by the
2743     // string table during bootstrapping.
2744     if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
2745     if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
2746         Shape::IsMatch(key, element)) return entry;
2747     entry = NextProbe(entry, count++, capacity);
2748   }
2749   return kNotFound;
2750 }
2751
2752
2753 bool SeededNumberDictionary::requires_slow_elements() {
2754   Object* max_index_object = get(kMaxNumberKeyIndex);
2755   if (!max_index_object->IsSmi()) return false;
2756   return 0 !=
2757       (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2758 }
2759
2760 uint32_t SeededNumberDictionary::max_number_key() {
2761   ASSERT(!requires_slow_elements());
2762   Object* max_index_object = get(kMaxNumberKeyIndex);
2763   if (!max_index_object->IsSmi()) return 0;
2764   uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2765   return value >> kRequiresSlowElementsTagSize;
2766 }
2767
2768 void SeededNumberDictionary::set_requires_slow_elements() {
2769   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2770 }
2771
2772
2773 // ------------------------------------
2774 // Cast operations
2775
2776
2777 CAST_ACCESSOR(FixedArray)
2778 CAST_ACCESSOR(FixedDoubleArray)
2779 CAST_ACCESSOR(FixedTypedArrayBase)
2780 CAST_ACCESSOR(ConstantPoolArray)
2781 CAST_ACCESSOR(DescriptorArray)
2782 CAST_ACCESSOR(DeoptimizationInputData)
2783 CAST_ACCESSOR(DeoptimizationOutputData)
2784 CAST_ACCESSOR(DependentCode)
2785 CAST_ACCESSOR(TypeFeedbackCells)
2786 CAST_ACCESSOR(StringTable)
2787 CAST_ACCESSOR(JSFunctionResultCache)
2788 CAST_ACCESSOR(NormalizedMapCache)
2789 CAST_ACCESSOR(ScopeInfo)
2790 CAST_ACCESSOR(CompilationCacheTable)
2791 CAST_ACCESSOR(CodeCacheHashTable)
2792 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2793 CAST_ACCESSOR(MapCache)
2794 CAST_ACCESSOR(String)
2795 CAST_ACCESSOR(SeqString)
2796 CAST_ACCESSOR(SeqOneByteString)
2797 CAST_ACCESSOR(SeqTwoByteString)
2798 CAST_ACCESSOR(SlicedString)
2799 CAST_ACCESSOR(ConsString)
2800 CAST_ACCESSOR(ExternalString)
2801 CAST_ACCESSOR(ExternalAsciiString)
2802 CAST_ACCESSOR(ExternalTwoByteString)
2803 CAST_ACCESSOR(Symbol)
2804 CAST_ACCESSOR(Name)
2805 CAST_ACCESSOR(JSReceiver)
2806 CAST_ACCESSOR(JSObject)
2807 CAST_ACCESSOR(Smi)
2808 CAST_ACCESSOR(HeapObject)
2809 CAST_ACCESSOR(HeapNumber)
2810 CAST_ACCESSOR(Oddball)
2811 CAST_ACCESSOR(Cell)
2812 CAST_ACCESSOR(PropertyCell)
2813 CAST_ACCESSOR(SharedFunctionInfo)
2814 CAST_ACCESSOR(Map)
2815 CAST_ACCESSOR(JSFunction)
2816 CAST_ACCESSOR(GlobalObject)
2817 CAST_ACCESSOR(JSGlobalProxy)
2818 CAST_ACCESSOR(JSGlobalObject)
2819 CAST_ACCESSOR(JSBuiltinsObject)
2820 CAST_ACCESSOR(Code)
2821 CAST_ACCESSOR(JSArray)
2822 CAST_ACCESSOR(JSArrayBuffer)
2823 CAST_ACCESSOR(JSArrayBufferView)
2824 CAST_ACCESSOR(JSTypedArray)
2825 CAST_ACCESSOR(JSDataView)
2826 CAST_ACCESSOR(JSRegExp)
2827 CAST_ACCESSOR(JSProxy)
2828 CAST_ACCESSOR(JSFunctionProxy)
2829 CAST_ACCESSOR(JSSet)
2830 CAST_ACCESSOR(JSMap)
2831 CAST_ACCESSOR(JSWeakMap)
2832 CAST_ACCESSOR(JSWeakSet)
2833 CAST_ACCESSOR(Foreign)
2834 CAST_ACCESSOR(ByteArray)
2835 CAST_ACCESSOR(FreeSpace)
2836 CAST_ACCESSOR(ExternalArray)
2837 CAST_ACCESSOR(ExternalInt8Array)
2838 CAST_ACCESSOR(ExternalUint8Array)
2839 CAST_ACCESSOR(ExternalInt16Array)
2840 CAST_ACCESSOR(ExternalUint16Array)
2841 CAST_ACCESSOR(ExternalInt32Array)
2842 CAST_ACCESSOR(ExternalUint32Array)
2843 CAST_ACCESSOR(ExternalFloat32Array)
2844 CAST_ACCESSOR(ExternalFloat64Array)
2845 CAST_ACCESSOR(ExternalUint8ClampedArray)
2846 CAST_ACCESSOR(Struct)
2847 CAST_ACCESSOR(AccessorInfo)
2848
2849 template <class Traits>
2850 FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
2851   SLOW_ASSERT(object->IsHeapObject() &&
2852       HeapObject::cast(object)->map()->instance_type() ==
2853           Traits::kInstanceType);
2854   return reinterpret_cast<FixedTypedArray<Traits>*>(object);
2855 }
2856
2857
2858 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2859   STRUCT_LIST(MAKE_STRUCT_CAST)
2860 #undef MAKE_STRUCT_CAST
2861
2862
2863 template <typename Shape, typename Key>
2864 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2865   ASSERT(obj->IsHashTable());
2866   return reinterpret_cast<HashTable*>(obj);
2867 }
2868
2869
2870 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2871 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2872
2873 SMI_ACCESSORS(String, length, kLengthOffset)
2874
2875
2876 uint32_t Name::hash_field() {
2877   return READ_UINT32_FIELD(this, kHashFieldOffset);
2878 }
2879
2880
2881 void Name::set_hash_field(uint32_t value) {
2882   WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2883 #if V8_HOST_ARCH_64_BIT
2884   WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2885 #endif
2886 }
2887
2888
2889 bool Name::Equals(Name* other) {
2890   if (other == this) return true;
2891   if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
2892       this->IsSymbol() || other->IsSymbol()) {
2893     return false;
2894   }
2895   return String::cast(this)->SlowEquals(String::cast(other));
2896 }
2897
2898
2899 ACCESSORS(Symbol, name, Object, kNameOffset)
2900 ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
2901 BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
2902
2903
2904 bool String::Equals(String* other) {
2905   if (other == this) return true;
2906   if (this->IsInternalizedString() && other->IsInternalizedString()) {
2907     return false;
2908   }
2909   return SlowEquals(other);
2910 }
2911
2912
2913 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2914   if (!StringShape(this).IsCons()) return this;
2915   ConsString* cons = ConsString::cast(this);
2916   if (cons->IsFlat()) return cons->first();
2917   return SlowTryFlatten(pretenure);
2918 }
2919
2920
2921 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2922   MaybeObject* flat = TryFlatten(pretenure);
2923   Object* successfully_flattened;
2924   if (!flat->ToObject(&successfully_flattened)) return this;
2925   return String::cast(successfully_flattened);
2926 }
2927
2928
2929 uint16_t String::Get(int index) {
2930   ASSERT(index >= 0 && index < length());
2931   switch (StringShape(this).full_representation_tag()) {
2932     case kSeqStringTag | kOneByteStringTag:
2933       return SeqOneByteString::cast(this)->SeqOneByteStringGet(index);
2934     case kSeqStringTag | kTwoByteStringTag:
2935       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2936     case kConsStringTag | kOneByteStringTag:
2937     case kConsStringTag | kTwoByteStringTag:
2938       return ConsString::cast(this)->ConsStringGet(index);
2939     case kExternalStringTag | kOneByteStringTag:
2940       return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2941     case kExternalStringTag | kTwoByteStringTag:
2942       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2943     case kSlicedStringTag | kOneByteStringTag:
2944     case kSlicedStringTag | kTwoByteStringTag:
2945       return SlicedString::cast(this)->SlicedStringGet(index);
2946     default:
2947       break;
2948   }
2949
2950   UNREACHABLE();
2951   return 0;
2952 }
2953
2954
2955 void String::Set(int index, uint16_t value) {
2956   ASSERT(index >= 0 && index < length());
2957   ASSERT(StringShape(this).IsSequential());
2958
2959   return this->IsOneByteRepresentation()
2960       ? SeqOneByteString::cast(this)->SeqOneByteStringSet(index, value)
2961       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2962 }
2963
2964
2965 bool String::IsFlat() {
2966   if (!StringShape(this).IsCons()) return true;
2967   return ConsString::cast(this)->second()->length() == 0;
2968 }
2969
2970
2971 String* String::GetUnderlying() {
2972   // Giving direct access to underlying string only makes sense if the
2973   // wrapping string is already flattened.
2974   ASSERT(this->IsFlat());
2975   ASSERT(StringShape(this).IsIndirect());
2976   STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2977   const int kUnderlyingOffset = SlicedString::kParentOffset;
2978   return String::cast(READ_FIELD(this, kUnderlyingOffset));
2979 }
2980
2981
2982 template<class Visitor, class ConsOp>
2983 void String::Visit(
2984     String* string,
2985     unsigned offset,
2986     Visitor& visitor,
2987     ConsOp& cons_op,
2988     int32_t type,
2989     unsigned length) {
2990   ASSERT(length == static_cast<unsigned>(string->length()));
2991   ASSERT(offset <= length);
2992   unsigned slice_offset = offset;
2993   while (true) {
2994     ASSERT(type == string->map()->instance_type());
2995
2996     switch (type & (kStringRepresentationMask | kStringEncodingMask)) {
2997       case kSeqStringTag | kOneByteStringTag:
2998         visitor.VisitOneByteString(
2999             SeqOneByteString::cast(string)->GetChars() + slice_offset,
3000             length - offset);
3001         return;
3002
3003       case kSeqStringTag | kTwoByteStringTag:
3004         visitor.VisitTwoByteString(
3005             SeqTwoByteString::cast(string)->GetChars() + slice_offset,
3006             length - offset);
3007         return;
3008
3009       case kExternalStringTag | kOneByteStringTag:
3010         visitor.VisitOneByteString(
3011             ExternalAsciiString::cast(string)->GetChars() + slice_offset,
3012             length - offset);
3013         return;
3014
3015       case kExternalStringTag | kTwoByteStringTag:
3016         visitor.VisitTwoByteString(
3017             ExternalTwoByteString::cast(string)->GetChars() + slice_offset,
3018             length - offset);
3019         return;
3020
3021       case kSlicedStringTag | kOneByteStringTag:
3022       case kSlicedStringTag | kTwoByteStringTag: {
3023         SlicedString* slicedString = SlicedString::cast(string);
3024         slice_offset += slicedString->offset();
3025         string = slicedString->parent();
3026         type = string->map()->instance_type();
3027         continue;
3028       }
3029
3030       case kConsStringTag | kOneByteStringTag:
3031       case kConsStringTag | kTwoByteStringTag:
3032         string = cons_op.Operate(string, &offset, &type, &length);
3033         if (string == NULL) return;
3034         slice_offset = offset;
3035         ASSERT(length == static_cast<unsigned>(string->length()));
3036         continue;
3037
3038       default:
3039         UNREACHABLE();
3040         return;
3041     }
3042   }
3043 }
3044
3045
3046 // TODO(dcarney): Remove this class after conversion to VisitFlat.
3047 class ConsStringCaptureOp {
3048  public:
3049   inline ConsStringCaptureOp() : cons_string_(NULL) {}
3050   inline String* Operate(String* string, unsigned*, int32_t*, unsigned*) {
3051     cons_string_ = ConsString::cast(string);
3052     return NULL;
3053   }
3054   ConsString* cons_string_;
3055 };
3056
3057
3058 template<class Visitor>
3059 ConsString* String::VisitFlat(Visitor* visitor,
3060                               String* string,
3061                               int offset,
3062                               int length,
3063                               int32_t type) {
3064   ASSERT(length >= 0 && length == string->length());
3065   ASSERT(offset >= 0 && offset <= length);
3066   ConsStringCaptureOp op;
3067   Visit(string, offset, *visitor, op, type, static_cast<unsigned>(length));
3068   return op.cons_string_;
3069 }
3070
3071
3072 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
3073   ASSERT(index >= 0 && index < length());
3074   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3075 }
3076
3077
3078 void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
3079   ASSERT(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
3080   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
3081                    static_cast<byte>(value));
3082 }
3083
3084
3085 Address SeqOneByteString::GetCharsAddress() {
3086   return FIELD_ADDR(this, kHeaderSize);
3087 }
3088
3089
3090 uint8_t* SeqOneByteString::GetChars() {
3091   return reinterpret_cast<uint8_t*>(GetCharsAddress());
3092 }
3093
3094
3095 Address SeqTwoByteString::GetCharsAddress() {
3096   return FIELD_ADDR(this, kHeaderSize);
3097 }
3098
3099
3100 uc16* SeqTwoByteString::GetChars() {
3101   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
3102 }
3103
3104
3105 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
3106   ASSERT(index >= 0 && index < length());
3107   return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
3108 }
3109
3110
3111 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
3112   ASSERT(index >= 0 && index < length());
3113   WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
3114 }
3115
3116
3117 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
3118   return SizeFor(length());
3119 }
3120
3121
3122 int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
3123   return SizeFor(length());
3124 }
3125
3126
3127 String* SlicedString::parent() {
3128   return String::cast(READ_FIELD(this, kParentOffset));
3129 }
3130
3131
3132 void SlicedString::set_parent(String* parent, WriteBarrierMode mode) {
3133   ASSERT(parent->IsSeqString() || parent->IsExternalString());
3134   WRITE_FIELD(this, kParentOffset, parent);
3135   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kParentOffset, parent, mode);
3136 }
3137
3138
3139 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
3140
3141
3142 String* ConsString::first() {
3143   return String::cast(READ_FIELD(this, kFirstOffset));
3144 }
3145
3146
3147 Object* ConsString::unchecked_first() {
3148   return READ_FIELD(this, kFirstOffset);
3149 }
3150
3151
3152 void ConsString::set_first(String* value, WriteBarrierMode mode) {
3153   WRITE_FIELD(this, kFirstOffset, value);
3154   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
3155 }
3156
3157
3158 String* ConsString::second() {
3159   return String::cast(READ_FIELD(this, kSecondOffset));
3160 }
3161
3162
3163 Object* ConsString::unchecked_second() {
3164   return READ_FIELD(this, kSecondOffset);
3165 }
3166
3167
3168 void ConsString::set_second(String* value, WriteBarrierMode mode) {
3169   WRITE_FIELD(this, kSecondOffset, value);
3170   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
3171 }
3172
3173
3174 bool ExternalString::is_short() {
3175   InstanceType type = map()->instance_type();
3176   return (type & kShortExternalStringMask) == kShortExternalStringTag;
3177 }
3178
3179
3180 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
3181   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3182 }
3183
3184
3185 void ExternalAsciiString::update_data_cache() {
3186   if (is_short()) return;
3187   const char** data_field =
3188       reinterpret_cast<const char**>(FIELD_ADDR(this, kResourceDataOffset));
3189   *data_field = resource()->data();
3190 }
3191
3192
3193 void ExternalAsciiString::set_resource(
3194     const ExternalAsciiString::Resource* resource) {
3195   *reinterpret_cast<const Resource**>(
3196       FIELD_ADDR(this, kResourceOffset)) = resource;
3197   if (resource != NULL) update_data_cache();
3198 }
3199
3200
3201 const uint8_t* ExternalAsciiString::GetChars() {
3202   return reinterpret_cast<const uint8_t*>(resource()->data());
3203 }
3204
3205
3206 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
3207   ASSERT(index >= 0 && index < length());
3208   return GetChars()[index];
3209 }
3210
3211
3212 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
3213   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
3214 }
3215
3216
3217 void ExternalTwoByteString::update_data_cache() {
3218   if (is_short()) return;
3219   const uint16_t** data_field =
3220       reinterpret_cast<const uint16_t**>(FIELD_ADDR(this, kResourceDataOffset));
3221   *data_field = resource()->data();
3222 }
3223
3224
3225 void ExternalTwoByteString::set_resource(
3226     const ExternalTwoByteString::Resource* resource) {
3227   *reinterpret_cast<const Resource**>(
3228       FIELD_ADDR(this, kResourceOffset)) = resource;
3229   if (resource != NULL) update_data_cache();
3230 }
3231
3232
3233 const uint16_t* ExternalTwoByteString::GetChars() {
3234   return resource()->data();
3235 }
3236
3237
3238 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
3239   ASSERT(index >= 0 && index < length());
3240   return GetChars()[index];
3241 }
3242
3243
3244 const uint16_t* ExternalTwoByteString::ExternalTwoByteStringGetData(
3245       unsigned start) {
3246   return GetChars() + start;
3247 }
3248
3249
3250 String* ConsStringNullOp::Operate(String*, unsigned*, int32_t*, unsigned*) {
3251   return NULL;
3252 }
3253
3254
3255 unsigned ConsStringIteratorOp::OffsetForDepth(unsigned depth) {
3256   return depth & kDepthMask;
3257 }
3258
3259
3260 void ConsStringIteratorOp::PushLeft(ConsString* string) {
3261   frames_[depth_++ & kDepthMask] = string;
3262 }
3263
3264
3265 void ConsStringIteratorOp::PushRight(ConsString* string) {
3266   // Inplace update.
3267   frames_[(depth_-1) & kDepthMask] = string;
3268 }
3269
3270
3271 void ConsStringIteratorOp::AdjustMaximumDepth() {
3272   if (depth_ > maximum_depth_) maximum_depth_ = depth_;
3273 }
3274
3275
3276 void ConsStringIteratorOp::Pop() {
3277   ASSERT(depth_ > 0);
3278   ASSERT(depth_ <= maximum_depth_);
3279   depth_--;
3280 }
3281
3282
3283 bool ConsStringIteratorOp::HasMore() {
3284   return depth_ != 0;
3285 }
3286
3287
3288 void ConsStringIteratorOp::Reset() {
3289   depth_ = 0;
3290 }
3291
3292
3293 String* ConsStringIteratorOp::ContinueOperation(int32_t* type_out,
3294                                                 unsigned* length_out) {
3295   bool blew_stack = false;
3296   String* string = NextLeaf(&blew_stack, type_out, length_out);
3297   // String found.
3298   if (string != NULL) {
3299     // Verify output.
3300     ASSERT(*length_out == static_cast<unsigned>(string->length()));
3301     ASSERT(*type_out == string->map()->instance_type());
3302     return string;
3303   }
3304   // Traversal complete.
3305   if (!blew_stack) return NULL;
3306   // Restart search from root.
3307   unsigned offset_out;
3308   string = Search(&offset_out, type_out, length_out);
3309   // Verify output.
3310   ASSERT(string == NULL || offset_out == 0);
3311   ASSERT(string == NULL ||
3312          *length_out == static_cast<unsigned>(string->length()));
3313   ASSERT(string == NULL || *type_out == string->map()->instance_type());
3314   return string;
3315 }
3316
3317
3318 uint16_t StringCharacterStream::GetNext() {
3319   ASSERT(buffer8_ != NULL && end_ != NULL);
3320   // Advance cursor if needed.
3321   // TODO(dcarney): Ensure uses of the api call HasMore first and avoid this.
3322   if (buffer8_ == end_) HasMore();
3323   ASSERT(buffer8_ < end_);
3324   return is_one_byte_ ? *buffer8_++ : *buffer16_++;
3325 }
3326
3327
3328 StringCharacterStream::StringCharacterStream(String* string,
3329                                              ConsStringIteratorOp* op,
3330                                              unsigned offset)
3331   : is_one_byte_(false),
3332     op_(op) {
3333   Reset(string, offset);
3334 }
3335
3336
3337 void StringCharacterStream::Reset(String* string, unsigned offset) {
3338   op_->Reset();
3339   buffer8_ = NULL;
3340   end_ = NULL;
3341   int32_t type = string->map()->instance_type();
3342   unsigned length = string->length();
3343   String::Visit(string, offset, *this, *op_, type, length);
3344 }
3345
3346
3347 bool StringCharacterStream::HasMore() {
3348   if (buffer8_ != end_) return true;
3349   if (!op_->HasMore()) return false;
3350   unsigned length;
3351   int32_t type;
3352   String* string = op_->ContinueOperation(&type, &length);
3353   if (string == NULL) return false;
3354   ASSERT(!string->IsConsString());
3355   ASSERT(string->length() != 0);
3356   ConsStringNullOp null_op;
3357   String::Visit(string, 0, *this, null_op, type, length);
3358   ASSERT(buffer8_ != end_);
3359   return true;
3360 }
3361
3362
3363 void StringCharacterStream::VisitOneByteString(
3364     const uint8_t* chars, unsigned length) {
3365   is_one_byte_ = true;
3366   buffer8_ = chars;
3367   end_ = chars + length;
3368 }
3369
3370
3371 void StringCharacterStream::VisitTwoByteString(
3372     const uint16_t* chars, unsigned length) {
3373   is_one_byte_ = false;
3374   buffer16_ = chars;
3375   end_ = reinterpret_cast<const uint8_t*>(chars + length);
3376 }
3377
3378
3379 void JSFunctionResultCache::MakeZeroSize() {
3380   set_finger_index(kEntriesIndex);
3381   set_size(kEntriesIndex);
3382 }
3383
3384
3385 void JSFunctionResultCache::Clear() {
3386   int cache_size = size();
3387   Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
3388   MemsetPointer(entries_start,
3389                 GetHeap()->the_hole_value(),
3390                 cache_size - kEntriesIndex);
3391   MakeZeroSize();
3392 }
3393
3394
3395 int JSFunctionResultCache::size() {
3396   return Smi::cast(get(kCacheSizeIndex))->value();
3397 }
3398
3399
3400 void JSFunctionResultCache::set_size(int size) {
3401   set(kCacheSizeIndex, Smi::FromInt(size));
3402 }
3403
3404
3405 int JSFunctionResultCache::finger_index() {
3406   return Smi::cast(get(kFingerIndex))->value();
3407 }
3408
3409
3410 void JSFunctionResultCache::set_finger_index(int finger_index) {
3411   set(kFingerIndex, Smi::FromInt(finger_index));
3412 }
3413
3414
3415 byte ByteArray::get(int index) {
3416   ASSERT(index >= 0 && index < this->length());
3417   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
3418 }
3419
3420
3421 void ByteArray::set(int index, byte value) {
3422   ASSERT(index >= 0 && index < this->length());
3423   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
3424 }
3425
3426
3427 int ByteArray::get_int(int index) {
3428   ASSERT(index >= 0 && (index * kIntSize) < this->length());
3429   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
3430 }
3431
3432
3433 ByteArray* ByteArray::FromDataStartAddress(Address address) {
3434   ASSERT_TAG_ALIGNED(address);
3435   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
3436 }
3437
3438
3439 Address ByteArray::GetDataStartAddress() {
3440   return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
3441 }
3442
3443
3444 uint8_t* ExternalUint8ClampedArray::external_uint8_clamped_pointer() {
3445   return reinterpret_cast<uint8_t*>(external_pointer());
3446 }
3447
3448
3449 uint8_t ExternalUint8ClampedArray::get_scalar(int index) {
3450   ASSERT((index >= 0) && (index < this->length()));
3451   uint8_t* ptr = external_uint8_clamped_pointer();
3452   return ptr[index];
3453 }
3454
3455
3456 MaybeObject* ExternalUint8ClampedArray::get(int index) {
3457   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3458 }
3459
3460
3461 void ExternalUint8ClampedArray::set(int index, uint8_t value) {
3462   ASSERT((index >= 0) && (index < this->length()));
3463   uint8_t* ptr = external_uint8_clamped_pointer();
3464   ptr[index] = value;
3465 }
3466
3467
3468 void* ExternalArray::external_pointer() {
3469   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
3470   return reinterpret_cast<void*>(ptr);
3471 }
3472
3473
3474 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
3475   intptr_t ptr = reinterpret_cast<intptr_t>(value);
3476   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
3477 }
3478
3479
3480 int8_t ExternalInt8Array::get_scalar(int index) {
3481   ASSERT((index >= 0) && (index < this->length()));
3482   int8_t* ptr = static_cast<int8_t*>(external_pointer());
3483   return ptr[index];
3484 }
3485
3486
3487 MaybeObject* ExternalInt8Array::get(int index) {
3488   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3489 }
3490
3491
3492 void ExternalInt8Array::set(int index, int8_t value) {
3493   ASSERT((index >= 0) && (index < this->length()));
3494   int8_t* ptr = static_cast<int8_t*>(external_pointer());
3495   ptr[index] = value;
3496 }
3497
3498
3499 uint8_t ExternalUint8Array::get_scalar(int index) {
3500   ASSERT((index >= 0) && (index < this->length()));
3501   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3502   return ptr[index];
3503 }
3504
3505
3506 MaybeObject* ExternalUint8Array::get(int index) {
3507   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3508 }
3509
3510
3511 void ExternalUint8Array::set(int index, uint8_t value) {
3512   ASSERT((index >= 0) && (index < this->length()));
3513   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
3514   ptr[index] = value;
3515 }
3516
3517
3518 int16_t ExternalInt16Array::get_scalar(int index) {
3519   ASSERT((index >= 0) && (index < this->length()));
3520   int16_t* ptr = static_cast<int16_t*>(external_pointer());
3521   return ptr[index];
3522 }
3523
3524
3525 MaybeObject* ExternalInt16Array::get(int index) {
3526   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3527 }
3528
3529
3530 void ExternalInt16Array::set(int index, int16_t value) {
3531   ASSERT((index >= 0) && (index < this->length()));
3532   int16_t* ptr = static_cast<int16_t*>(external_pointer());
3533   ptr[index] = value;
3534 }
3535
3536
3537 uint16_t ExternalUint16Array::get_scalar(int index) {
3538   ASSERT((index >= 0) && (index < this->length()));
3539   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3540   return ptr[index];
3541 }
3542
3543
3544 MaybeObject* ExternalUint16Array::get(int index) {
3545   return Smi::FromInt(static_cast<int>(get_scalar(index)));
3546 }
3547
3548
3549 void ExternalUint16Array::set(int index, uint16_t value) {
3550   ASSERT((index >= 0) && (index < this->length()));
3551   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
3552   ptr[index] = value;
3553 }
3554
3555
3556 int32_t ExternalInt32Array::get_scalar(int index) {
3557   ASSERT((index >= 0) && (index < this->length()));
3558   int32_t* ptr = static_cast<int32_t*>(external_pointer());
3559   return ptr[index];
3560 }
3561
3562
3563 MaybeObject* ExternalInt32Array::get(int index) {
3564     return GetHeap()->NumberFromInt32(get_scalar(index));
3565 }
3566
3567
3568 void ExternalInt32Array::set(int index, int32_t value) {
3569   ASSERT((index >= 0) && (index < this->length()));
3570   int32_t* ptr = static_cast<int32_t*>(external_pointer());
3571   ptr[index] = value;
3572 }
3573
3574
3575 uint32_t ExternalUint32Array::get_scalar(int index) {
3576   ASSERT((index >= 0) && (index < this->length()));
3577   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3578   return ptr[index];
3579 }
3580
3581
3582 MaybeObject* ExternalUint32Array::get(int index) {
3583     return GetHeap()->NumberFromUint32(get_scalar(index));
3584 }
3585
3586
3587 void ExternalUint32Array::set(int index, uint32_t value) {
3588   ASSERT((index >= 0) && (index < this->length()));
3589   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
3590   ptr[index] = value;
3591 }
3592
3593
3594 float ExternalFloat32Array::get_scalar(int index) {
3595   ASSERT((index >= 0) && (index < this->length()));
3596   float* ptr = static_cast<float*>(external_pointer());
3597   return ptr[index];
3598 }
3599
3600
3601 MaybeObject* ExternalFloat32Array::get(int index) {
3602     return GetHeap()->NumberFromDouble(get_scalar(index));
3603 }
3604
3605
3606 void ExternalFloat32Array::set(int index, float value) {
3607   ASSERT((index >= 0) && (index < this->length()));
3608   float* ptr = static_cast<float*>(external_pointer());
3609   ptr[index] = value;
3610 }
3611
3612
3613 double ExternalFloat64Array::get_scalar(int index) {
3614   ASSERT((index >= 0) && (index < this->length()));
3615   double* ptr = static_cast<double*>(external_pointer());
3616   return ptr[index];
3617 }
3618
3619
3620 MaybeObject* ExternalFloat64Array::get(int index) {
3621     return GetHeap()->NumberFromDouble(get_scalar(index));
3622 }
3623
3624
3625 void ExternalFloat64Array::set(int index, double value) {
3626   ASSERT((index >= 0) && (index < this->length()));
3627   double* ptr = static_cast<double*>(external_pointer());
3628   ptr[index] = value;
3629 }
3630
3631
3632 int FixedTypedArrayBase::size() {
3633   InstanceType instance_type = map()->instance_type();
3634   int element_size;
3635   switch (instance_type) {
3636     case FIXED_UINT8_ARRAY_TYPE:
3637     case FIXED_INT8_ARRAY_TYPE:
3638     case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
3639       element_size = 1;
3640       break;
3641     case FIXED_UINT16_ARRAY_TYPE:
3642     case FIXED_INT16_ARRAY_TYPE:
3643       element_size = 2;
3644       break;
3645     case FIXED_UINT32_ARRAY_TYPE:
3646     case FIXED_INT32_ARRAY_TYPE:
3647     case FIXED_FLOAT32_ARRAY_TYPE:
3648       element_size = 4;
3649       break;
3650     case FIXED_FLOAT64_ARRAY_TYPE:
3651       element_size = 8;
3652       break;
3653     default:
3654       UNREACHABLE();
3655       return 0;
3656   }
3657   return OBJECT_POINTER_ALIGN(kDataOffset + length() * element_size);
3658 }
3659
3660
3661 template <class Traits>
3662 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
3663   ASSERT((index >= 0) && (index < this->length()));
3664   ElementType* ptr = reinterpret_cast<ElementType*>(
3665       FIELD_ADDR(this, kDataOffset));
3666   return ptr[index];
3667 }
3668
3669 template <class Traits>
3670 void FixedTypedArray<Traits>::set(int index, ElementType value) {
3671   ASSERT((index >= 0) && (index < this->length()));
3672   ElementType* ptr = reinterpret_cast<ElementType*>(
3673       FIELD_ADDR(this, kDataOffset));
3674   ptr[index] = value;
3675 }
3676
3677
3678 template <class Traits>
3679 MaybeObject* FixedTypedArray<Traits>::get(int index) {
3680   return Traits::ToObject(GetHeap(), get_scalar(index));
3681 }
3682
3683 template <class Traits>
3684 MaybeObject* FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
3685   ElementType cast_value = Traits::defaultValue();
3686   if (index < static_cast<uint32_t>(length())) {
3687     if (value->IsSmi()) {
3688       int int_value = Smi::cast(value)->value();
3689       cast_value = static_cast<ElementType>(int_value);
3690     } else if (value->IsHeapNumber()) {
3691       double double_value = HeapNumber::cast(value)->value();
3692       cast_value = static_cast<ElementType>(DoubleToInt32(double_value));
3693     } else {
3694       // Clamp undefined to the default value. All other types have been
3695       // converted to a number type further up in the call chain.
3696       ASSERT(value->IsUndefined());
3697     }
3698     set(index, cast_value);
3699   }
3700   return Traits::ToObject(GetHeap(), cast_value);
3701 }
3702
3703 template <class Traits>
3704 Handle<Object> FixedTypedArray<Traits>::SetValue(
3705     Handle<FixedTypedArray<Traits> > array,
3706     uint32_t index,
3707     Handle<Object> value) {
3708   CALL_HEAP_FUNCTION(array->GetIsolate(),
3709                      array->SetValue(index, *value),
3710                      Object);
3711 }
3712
3713
3714 MaybeObject* Uint8ArrayTraits::ToObject(Heap*, uint8_t scalar) {
3715   return Smi::FromInt(scalar);
3716 }
3717
3718
3719 MaybeObject* Uint8ClampedArrayTraits::ToObject(Heap*, uint8_t scalar) {
3720   return Smi::FromInt(scalar);
3721 }
3722
3723
3724 MaybeObject* Int8ArrayTraits::ToObject(Heap*, int8_t scalar) {
3725   return Smi::FromInt(scalar);
3726 }
3727
3728
3729 MaybeObject* Uint16ArrayTraits::ToObject(Heap*, uint16_t scalar) {
3730   return Smi::FromInt(scalar);
3731 }
3732
3733
3734 MaybeObject* Int16ArrayTraits::ToObject(Heap*, int16_t scalar) {
3735   return Smi::FromInt(scalar);
3736 }
3737
3738
3739 MaybeObject* Uint32ArrayTraits::ToObject(Heap* heap, uint32_t scalar) {
3740   return heap->NumberFromUint32(scalar);
3741 }
3742
3743
3744 MaybeObject* Int32ArrayTraits::ToObject(Heap* heap, int32_t scalar) {
3745   return heap->NumberFromInt32(scalar);
3746 }
3747
3748
3749 MaybeObject* Float32ArrayTraits::ToObject(Heap* heap, float scalar) {
3750   return heap->NumberFromDouble(scalar);
3751 }
3752
3753
3754 MaybeObject* Float64ArrayTraits::ToObject(Heap* heap, double scalar) {
3755   return heap->NumberFromDouble(scalar);
3756 }
3757
3758
3759 int Map::visitor_id() {
3760   return READ_BYTE_FIELD(this, kVisitorIdOffset);
3761 }
3762
3763
3764 void Map::set_visitor_id(int id) {
3765   ASSERT(0 <= id && id < 256);
3766   WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
3767 }
3768
3769
3770 int Map::instance_size() {
3771   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
3772 }
3773
3774
3775 int Map::inobject_properties() {
3776   return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
3777 }
3778
3779
3780 int Map::pre_allocated_property_fields() {
3781   return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
3782 }
3783
3784
3785 int HeapObject::SizeFromMap(Map* map) {
3786   int instance_size = map->instance_size();
3787   if (instance_size != kVariableSizeSentinel) return instance_size;
3788   // Only inline the most frequent cases.
3789   int instance_type = static_cast<int>(map->instance_type());
3790   if (instance_type == FIXED_ARRAY_TYPE) {
3791     return FixedArray::BodyDescriptor::SizeOf(map, this);
3792   }
3793   if (instance_type == ASCII_STRING_TYPE ||
3794       instance_type == ASCII_INTERNALIZED_STRING_TYPE) {
3795     return SeqOneByteString::SizeFor(
3796         reinterpret_cast<SeqOneByteString*>(this)->length());
3797   }
3798   if (instance_type == BYTE_ARRAY_TYPE) {
3799     return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
3800   }
3801   if (instance_type == FREE_SPACE_TYPE) {
3802     return reinterpret_cast<FreeSpace*>(this)->size();
3803   }
3804   if (instance_type == STRING_TYPE ||
3805       instance_type == INTERNALIZED_STRING_TYPE) {
3806     return SeqTwoByteString::SizeFor(
3807         reinterpret_cast<SeqTwoByteString*>(this)->length());
3808   }
3809   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
3810     return FixedDoubleArray::SizeFor(
3811         reinterpret_cast<FixedDoubleArray*>(this)->length());
3812   }
3813   if (instance_type == CONSTANT_POOL_ARRAY_TYPE) {
3814     return ConstantPoolArray::SizeFor(
3815         reinterpret_cast<ConstantPoolArray*>(this)->count_of_int64_entries(),
3816         reinterpret_cast<ConstantPoolArray*>(this)->count_of_ptr_entries(),
3817         reinterpret_cast<ConstantPoolArray*>(this)->count_of_int32_entries());
3818   }
3819   if (instance_type >= FIRST_FIXED_TYPED_ARRAY_TYPE &&
3820       instance_type <= LAST_FIXED_TYPED_ARRAY_TYPE) {
3821     return reinterpret_cast<FixedTypedArrayBase*>(this)->size();
3822   }
3823   ASSERT(instance_type == CODE_TYPE);
3824   return reinterpret_cast<Code*>(this)->CodeSize();
3825 }
3826
3827
3828 void Map::set_instance_size(int value) {
3829   ASSERT_EQ(0, value & (kPointerSize - 1));
3830   value >>= kPointerSizeLog2;
3831   ASSERT(0 <= value && value < 256);
3832   WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
3833 }
3834
3835
3836 void Map::set_inobject_properties(int value) {
3837   ASSERT(0 <= value && value < 256);
3838   WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
3839 }
3840
3841
3842 void Map::set_pre_allocated_property_fields(int value) {
3843   ASSERT(0 <= value && value < 256);
3844   WRITE_BYTE_FIELD(this,
3845                    kPreAllocatedPropertyFieldsOffset,
3846                    static_cast<byte>(value));
3847 }
3848
3849
3850 InstanceType Map::instance_type() {
3851   return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
3852 }
3853
3854
3855 void Map::set_instance_type(InstanceType value) {
3856   WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
3857 }
3858
3859
3860 int Map::unused_property_fields() {
3861   return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
3862 }
3863
3864
3865 void Map::set_unused_property_fields(int value) {
3866   WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
3867 }
3868
3869
3870 byte Map::bit_field() {
3871   return READ_BYTE_FIELD(this, kBitFieldOffset);
3872 }
3873
3874
3875 void Map::set_bit_field(byte value) {
3876   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
3877 }
3878
3879
3880 byte Map::bit_field2() {
3881   return READ_BYTE_FIELD(this, kBitField2Offset);
3882 }
3883
3884
3885 void Map::set_bit_field2(byte value) {
3886   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
3887 }
3888
3889
3890 void Map::set_non_instance_prototype(bool value) {
3891   if (value) {
3892     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
3893   } else {
3894     set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
3895   }
3896 }
3897
3898
3899 bool Map::has_non_instance_prototype() {
3900   return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
3901 }
3902
3903
3904 void Map::set_function_with_prototype(bool value) {
3905   set_bit_field3(FunctionWithPrototype::update(bit_field3(), value));
3906 }
3907
3908
3909 bool Map::function_with_prototype() {
3910   return FunctionWithPrototype::decode(bit_field3());
3911 }
3912
3913
3914 void Map::set_is_access_check_needed(bool access_check_needed) {
3915   if (access_check_needed) {
3916     set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
3917   } else {
3918     set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
3919   }
3920 }
3921
3922
3923 bool Map::is_access_check_needed() {
3924   return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
3925 }
3926
3927
3928 void Map::set_is_extensible(bool value) {
3929   if (value) {
3930     set_bit_field2(bit_field2() | (1 << kIsExtensible));
3931   } else {
3932     set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
3933   }
3934 }
3935
3936 bool Map::is_extensible() {
3937   return ((1 << kIsExtensible) & bit_field2()) != 0;
3938 }
3939
3940
3941 void Map::set_attached_to_shared_function_info(bool value) {
3942   if (value) {
3943     set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
3944   } else {
3945     set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
3946   }
3947 }
3948
3949 bool Map::attached_to_shared_function_info() {
3950   return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
3951 }
3952
3953
3954 void Map::set_is_shared(bool value) {
3955   set_bit_field3(IsShared::update(bit_field3(), value));
3956 }
3957
3958
3959 bool Map::is_shared() {
3960   return IsShared::decode(bit_field3());
3961 }
3962
3963
3964 void Map::set_dictionary_map(bool value) {
3965   if (value) mark_unstable();
3966   set_bit_field3(DictionaryMap::update(bit_field3(), value));
3967 }
3968
3969
3970 bool Map::is_dictionary_map() {
3971   return DictionaryMap::decode(bit_field3());
3972 }
3973
3974
3975 Code::Flags Code::flags() {
3976   return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
3977 }
3978
3979
3980 void Map::set_owns_descriptors(bool is_shared) {
3981   set_bit_field3(OwnsDescriptors::update(bit_field3(), is_shared));
3982 }
3983
3984
3985 bool Map::owns_descriptors() {
3986   return OwnsDescriptors::decode(bit_field3());
3987 }
3988
3989
3990 void Map::set_has_instance_call_handler() {
3991   set_bit_field3(HasInstanceCallHandler::update(bit_field3(), true));
3992 }
3993
3994
3995 bool Map::has_instance_call_handler() {
3996   return HasInstanceCallHandler::decode(bit_field3());
3997 }
3998
3999
4000 void Map::deprecate() {
4001   set_bit_field3(Deprecated::update(bit_field3(), true));
4002 }
4003
4004
4005 bool Map::is_deprecated() {
4006   if (!FLAG_track_fields) return false;
4007   return Deprecated::decode(bit_field3());
4008 }
4009
4010
4011 void Map::set_migration_target(bool value) {
4012   set_bit_field3(IsMigrationTarget::update(bit_field3(), value));
4013 }
4014
4015
4016 bool Map::is_migration_target() {
4017   if (!FLAG_track_fields) return false;
4018   return IsMigrationTarget::decode(bit_field3());
4019 }
4020
4021
4022 void Map::freeze() {
4023   set_bit_field3(IsFrozen::update(bit_field3(), true));
4024 }
4025
4026
4027 bool Map::is_frozen() {
4028   return IsFrozen::decode(bit_field3());
4029 }
4030
4031
4032 void Map::mark_unstable() {
4033   set_bit_field3(IsUnstable::update(bit_field3(), true));
4034 }
4035
4036
4037 bool Map::is_stable() {
4038   return !IsUnstable::decode(bit_field3());
4039 }
4040
4041
4042 bool Map::has_code_cache() {
4043   return code_cache() != GetIsolate()->heap()->empty_fixed_array();
4044 }
4045
4046
4047 bool Map::CanBeDeprecated() {
4048   int descriptor = LastAdded();
4049   for (int i = 0; i <= descriptor; i++) {
4050     PropertyDetails details = instance_descriptors()->GetDetails(i);
4051     if (FLAG_track_fields && details.representation().IsNone()) {
4052       return true;
4053     }
4054     if (FLAG_track_fields && details.representation().IsSmi()) {
4055       return true;
4056     }
4057     if (FLAG_track_double_fields && details.representation().IsDouble()) {
4058       return true;
4059     }
4060     if (FLAG_track_heap_object_fields &&
4061         details.representation().IsHeapObject()) {
4062       return true;
4063     }
4064     if (FLAG_track_fields && details.type() == CONSTANT) {
4065       return true;
4066     }
4067   }
4068   return false;
4069 }
4070
4071
4072 void Map::NotifyLeafMapLayoutChange() {
4073   if (is_stable()) {
4074     mark_unstable();
4075     dependent_code()->DeoptimizeDependentCodeGroup(
4076         GetIsolate(),
4077         DependentCode::kPrototypeCheckGroup);
4078   }
4079 }
4080
4081
4082 bool Map::CanOmitMapChecks() {
4083   return is_stable() && FLAG_omit_map_checks_for_leaf_maps;
4084 }
4085
4086
4087 int DependentCode::number_of_entries(DependencyGroup group) {
4088   if (length() == 0) return 0;
4089   return Smi::cast(get(group))->value();
4090 }
4091
4092
4093 void DependentCode::set_number_of_entries(DependencyGroup group, int value) {
4094   set(group, Smi::FromInt(value));
4095 }
4096
4097
4098 bool DependentCode::is_code_at(int i) {
4099   return get(kCodesStartIndex + i)->IsCode();
4100 }
4101
4102 Code* DependentCode::code_at(int i) {
4103   return Code::cast(get(kCodesStartIndex + i));
4104 }
4105
4106
4107 CompilationInfo* DependentCode::compilation_info_at(int i) {
4108   return reinterpret_cast<CompilationInfo*>(
4109       Foreign::cast(get(kCodesStartIndex + i))->foreign_address());
4110 }
4111
4112
4113 void DependentCode::set_object_at(int i, Object* object) {
4114   set(kCodesStartIndex + i, object);
4115 }
4116
4117
4118 Object* DependentCode::object_at(int i) {
4119   return get(kCodesStartIndex + i);
4120 }
4121
4122
4123 Object** DependentCode::slot_at(int i) {
4124   return RawFieldOfElementAt(kCodesStartIndex + i);
4125 }
4126
4127
4128 void DependentCode::clear_at(int i) {
4129   set_undefined(kCodesStartIndex + i);
4130 }
4131
4132
4133 void DependentCode::copy(int from, int to) {
4134   set(kCodesStartIndex + to, get(kCodesStartIndex + from));
4135 }
4136
4137
4138 void DependentCode::ExtendGroup(DependencyGroup group) {
4139   GroupStartIndexes starts(this);
4140   for (int g = kGroupCount - 1; g > group; g--) {
4141     if (starts.at(g) < starts.at(g + 1)) {
4142       copy(starts.at(g), starts.at(g + 1));
4143     }
4144   }
4145 }
4146
4147
4148 void Code::set_flags(Code::Flags flags) {
4149   STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
4150   // Make sure that all call stubs have an arguments count.
4151   ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
4152           ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
4153          ExtractArgumentsCountFromFlags(flags) >= 0);
4154   WRITE_INT_FIELD(this, kFlagsOffset, flags);
4155 }
4156
4157
4158 Code::Kind Code::kind() {
4159   return ExtractKindFromFlags(flags());
4160 }
4161
4162
4163 InlineCacheState Code::ic_state() {
4164   InlineCacheState result = ExtractICStateFromFlags(flags());
4165   // Only allow uninitialized or debugger states for non-IC code
4166   // objects. This is used in the debugger to determine whether or not
4167   // a call to code object has been replaced with a debug break call.
4168   ASSERT(is_inline_cache_stub() ||
4169          result == UNINITIALIZED ||
4170          result == DEBUG_STUB);
4171   return result;
4172 }
4173
4174
4175 ExtraICState Code::extra_ic_state() {
4176   ASSERT((is_inline_cache_stub() && !needs_extended_extra_ic_state(kind()))
4177          || ic_state() == DEBUG_STUB);
4178   return ExtractExtraICStateFromFlags(flags());
4179 }
4180
4181
4182 ExtraICState Code::extended_extra_ic_state() {
4183   ASSERT(is_inline_cache_stub() || ic_state() == DEBUG_STUB);
4184   ASSERT(needs_extended_extra_ic_state(kind()));
4185   return ExtractExtendedExtraICStateFromFlags(flags());
4186 }
4187
4188
4189 Code::StubType Code::type() {
4190   return ExtractTypeFromFlags(flags());
4191 }
4192
4193
4194 int Code::arguments_count() {
4195   ASSERT(is_call_stub() || is_keyed_call_stub() ||
4196          kind() == STUB || is_handler());
4197   return ExtractArgumentsCountFromFlags(flags());
4198 }
4199
4200
4201 // For initialization.
4202 void Code::set_raw_kind_specific_flags1(int value) {
4203   WRITE_INT_FIELD(this, kKindSpecificFlags1Offset, value);
4204 }
4205
4206
4207 void Code::set_raw_kind_specific_flags2(int value) {
4208   WRITE_INT_FIELD(this, kKindSpecificFlags2Offset, value);
4209 }
4210
4211
4212 inline bool Code::is_crankshafted() {
4213   return IsCrankshaftedField::decode(
4214       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4215 }
4216
4217
4218 inline void Code::set_is_crankshafted(bool value) {
4219   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4220   int updated = IsCrankshaftedField::update(previous, value);
4221   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4222 }
4223
4224
4225 int Code::major_key() {
4226   ASSERT(has_major_key());
4227   return StubMajorKeyField::decode(
4228       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4229 }
4230
4231
4232 void Code::set_major_key(int major) {
4233   ASSERT(has_major_key());
4234   ASSERT(0 <= major && major < 256);
4235   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4236   int updated = StubMajorKeyField::update(previous, major);
4237   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4238 }
4239
4240
4241 bool Code::has_major_key() {
4242   return kind() == STUB ||
4243       kind() == HANDLER ||
4244       kind() == BINARY_OP_IC ||
4245       kind() == COMPARE_IC ||
4246       kind() == COMPARE_NIL_IC ||
4247       kind() == LOAD_IC ||
4248       kind() == KEYED_LOAD_IC ||
4249       kind() == STORE_IC ||
4250       kind() == KEYED_STORE_IC ||
4251       kind() == KEYED_CALL_IC ||
4252       kind() == TO_BOOLEAN_IC;
4253 }
4254
4255
4256 bool Code::optimizable() {
4257   ASSERT_EQ(FUNCTION, kind());
4258   return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
4259 }
4260
4261
4262 void Code::set_optimizable(bool value) {
4263   ASSERT_EQ(FUNCTION, kind());
4264   WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
4265 }
4266
4267
4268 bool Code::has_deoptimization_support() {
4269   ASSERT_EQ(FUNCTION, kind());
4270   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4271   return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
4272 }
4273
4274
4275 void Code::set_has_deoptimization_support(bool value) {
4276   ASSERT_EQ(FUNCTION, kind());
4277   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4278   flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
4279   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4280 }
4281
4282
4283 bool Code::has_debug_break_slots() {
4284   ASSERT_EQ(FUNCTION, kind());
4285   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4286   return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
4287 }
4288
4289
4290 void Code::set_has_debug_break_slots(bool value) {
4291   ASSERT_EQ(FUNCTION, kind());
4292   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4293   flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
4294   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4295 }
4296
4297
4298 bool Code::is_compiled_optimizable() {
4299   ASSERT_EQ(FUNCTION, kind());
4300   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4301   return FullCodeFlagsIsCompiledOptimizable::decode(flags);
4302 }
4303
4304
4305 void Code::set_compiled_optimizable(bool value) {
4306   ASSERT_EQ(FUNCTION, kind());
4307   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
4308   flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
4309   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
4310 }
4311
4312
4313 int Code::allow_osr_at_loop_nesting_level() {
4314   ASSERT_EQ(FUNCTION, kind());
4315   return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
4316 }
4317
4318
4319 void Code::set_allow_osr_at_loop_nesting_level(int level) {
4320   ASSERT_EQ(FUNCTION, kind());
4321   ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
4322   WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
4323 }
4324
4325
4326 int Code::profiler_ticks() {
4327   ASSERT_EQ(FUNCTION, kind());
4328   return READ_BYTE_FIELD(this, kProfilerTicksOffset);
4329 }
4330
4331
4332 void Code::set_profiler_ticks(int ticks) {
4333   ASSERT_EQ(FUNCTION, kind());
4334   ASSERT(ticks < 256);
4335   WRITE_BYTE_FIELD(this, kProfilerTicksOffset, ticks);
4336 }
4337
4338
4339 unsigned Code::stack_slots() {
4340   ASSERT(is_crankshafted());
4341   return StackSlotsField::decode(
4342       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4343 }
4344
4345
4346 void Code::set_stack_slots(unsigned slots) {
4347   CHECK(slots <= (1 << kStackSlotsBitCount));
4348   ASSERT(is_crankshafted());
4349   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4350   int updated = StackSlotsField::update(previous, slots);
4351   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4352 }
4353
4354
4355 unsigned Code::safepoint_table_offset() {
4356   ASSERT(is_crankshafted());
4357   return SafepointTableOffsetField::decode(
4358       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4359 }
4360
4361
4362 void Code::set_safepoint_table_offset(unsigned offset) {
4363   CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
4364   ASSERT(is_crankshafted());
4365   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4366   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4367   int updated = SafepointTableOffsetField::update(previous, offset);
4368   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4369 }
4370
4371
4372 unsigned Code::back_edge_table_offset() {
4373   ASSERT_EQ(FUNCTION, kind());
4374   return BackEdgeTableOffsetField::decode(
4375       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4376 }
4377
4378
4379 void Code::set_back_edge_table_offset(unsigned offset) {
4380   ASSERT_EQ(FUNCTION, kind());
4381   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
4382   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4383   int updated = BackEdgeTableOffsetField::update(previous, offset);
4384   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4385 }
4386
4387
4388 bool Code::back_edges_patched_for_osr() {
4389   ASSERT_EQ(FUNCTION, kind());
4390   return BackEdgesPatchedForOSRField::decode(
4391       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
4392 }
4393
4394
4395 void Code::set_back_edges_patched_for_osr(bool value) {
4396   ASSERT_EQ(FUNCTION, kind());
4397   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
4398   int updated = BackEdgesPatchedForOSRField::update(previous, value);
4399   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
4400 }
4401
4402
4403
4404 CheckType Code::check_type() {
4405   ASSERT(is_call_stub() || is_keyed_call_stub());
4406   byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
4407   return static_cast<CheckType>(type);
4408 }
4409
4410
4411 void Code::set_check_type(CheckType value) {
4412   ASSERT(is_call_stub() || is_keyed_call_stub());
4413   WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
4414 }
4415
4416
4417 byte Code::to_boolean_state() {
4418   return extended_extra_ic_state();
4419 }
4420
4421
4422 bool Code::has_function_cache() {
4423   ASSERT(kind() == STUB);
4424   return HasFunctionCacheField::decode(
4425       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4426 }
4427
4428
4429 void Code::set_has_function_cache(bool flag) {
4430   ASSERT(kind() == STUB);
4431   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4432   int updated = HasFunctionCacheField::update(previous, flag);
4433   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4434 }
4435
4436
4437 bool Code::marked_for_deoptimization() {
4438   ASSERT(kind() == OPTIMIZED_FUNCTION);
4439   return MarkedForDeoptimizationField::decode(
4440       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
4441 }
4442
4443
4444 void Code::set_marked_for_deoptimization(bool flag) {
4445   ASSERT(kind() == OPTIMIZED_FUNCTION);
4446   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
4447   int updated = MarkedForDeoptimizationField::update(previous, flag);
4448   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
4449 }
4450
4451
4452 bool Code::is_inline_cache_stub() {
4453   Kind kind = this->kind();
4454   switch (kind) {
4455 #define CASE(name) case name: return true;
4456     IC_KIND_LIST(CASE)
4457 #undef CASE
4458     default: return false;
4459   }
4460 }
4461
4462
4463 bool Code::is_keyed_stub() {
4464   return is_keyed_load_stub() || is_keyed_store_stub() || is_keyed_call_stub();
4465 }
4466
4467
4468 bool Code::is_debug_stub() {
4469   return ic_state() == DEBUG_STUB;
4470 }
4471
4472
4473 ConstantPoolArray* Code::constant_pool() {
4474   return ConstantPoolArray::cast(READ_FIELD(this, kConstantPoolOffset));
4475 }
4476
4477
4478 void Code::set_constant_pool(Object* value) {
4479   ASSERT(value->IsConstantPoolArray());
4480   WRITE_FIELD(this, kConstantPoolOffset, value);
4481   WRITE_BARRIER(GetHeap(), this, kConstantPoolOffset, value);
4482 }
4483
4484
4485 Code::Flags Code::ComputeFlags(Kind kind,
4486                                InlineCacheState ic_state,
4487                                ExtraICState extra_ic_state,
4488                                StubType type,
4489                                int argc,
4490                                InlineCacheHolderFlag holder) {
4491   ASSERT(argc <= Code::kMaxArguments);
4492   // Since the extended extra ic state overlaps with the argument count
4493   // for CALL_ICs, do so checks to make sure that they don't interfere.
4494   ASSERT((kind != Code::CALL_IC &&
4495           kind != Code::KEYED_CALL_IC) ||
4496          (ExtraICStateField::encode(extra_ic_state) | true));
4497   // Compute the bit mask.
4498   unsigned int bits = KindField::encode(kind)
4499       | ICStateField::encode(ic_state)
4500       | TypeField::encode(type)
4501       | ExtendedExtraICStateField::encode(extra_ic_state)
4502       | CacheHolderField::encode(holder);
4503   if (!Code::needs_extended_extra_ic_state(kind)) {
4504     bits |= (argc << kArgumentsCountShift);
4505   }
4506   return static_cast<Flags>(bits);
4507 }
4508
4509
4510 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
4511                                           ExtraICState extra_ic_state,
4512                                           InlineCacheHolderFlag holder,
4513                                           StubType type,
4514                                           int argc) {
4515   return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
4516 }
4517
4518
4519 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
4520   return KindField::decode(flags);
4521 }
4522
4523
4524 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
4525   return ICStateField::decode(flags);
4526 }
4527
4528
4529 ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
4530   return ExtraICStateField::decode(flags);
4531 }
4532
4533
4534 ExtraICState Code::ExtractExtendedExtraICStateFromFlags(
4535     Flags flags) {
4536   return ExtendedExtraICStateField::decode(flags);
4537 }
4538
4539
4540 Code::StubType Code::ExtractTypeFromFlags(Flags flags) {
4541   return TypeField::decode(flags);
4542 }
4543
4544
4545 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
4546   return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
4547 }
4548
4549
4550 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
4551   return CacheHolderField::decode(flags);
4552 }
4553
4554
4555 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
4556   int bits = flags & ~TypeField::kMask;
4557   return static_cast<Flags>(bits);
4558 }
4559
4560
4561 Code* Code::GetCodeFromTargetAddress(Address address) {
4562   HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
4563   // GetCodeFromTargetAddress might be called when marking objects during mark
4564   // sweep. reinterpret_cast is therefore used instead of the more appropriate
4565   // Code::cast. Code::cast does not work when the object's map is
4566   // marked.
4567   Code* result = reinterpret_cast<Code*>(code);
4568   return result;
4569 }
4570
4571
4572 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
4573   return HeapObject::
4574       FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
4575 }
4576
4577
4578 Object* Map::prototype() {
4579   return READ_FIELD(this, kPrototypeOffset);
4580 }
4581
4582
4583 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
4584   ASSERT(value->IsNull() || value->IsJSReceiver());
4585   WRITE_FIELD(this, kPrototypeOffset, value);
4586   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
4587 }
4588
4589
4590 // If the descriptor is using the empty transition array, install a new empty
4591 // transition array that will have place for an element transition.
4592 static MaybeObject* EnsureHasTransitionArray(Map* map) {
4593   TransitionArray* transitions;
4594   MaybeObject* maybe_transitions;
4595   if (!map->HasTransitionArray()) {
4596     maybe_transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
4597     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4598     transitions->set_back_pointer_storage(map->GetBackPointer());
4599   } else if (!map->transitions()->IsFullTransitionArray()) {
4600     maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
4601     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4602   } else {
4603     return map;
4604   }
4605   map->set_transitions(transitions);
4606   return transitions;
4607 }
4608
4609
4610 void Map::InitializeDescriptors(DescriptorArray* descriptors) {
4611   int len = descriptors->number_of_descriptors();
4612   set_instance_descriptors(descriptors);
4613   SetNumberOfOwnDescriptors(len);
4614 }
4615
4616
4617 ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
4618
4619
4620 void Map::set_bit_field3(uint32_t bits) {
4621   // Ensure the upper 2 bits have the same value by sign extending it. This is
4622   // necessary to be able to use the 31st bit.
4623   int value = bits << 1;
4624   WRITE_FIELD(this, kBitField3Offset, Smi::FromInt(value >> 1));
4625 }
4626
4627
4628 uint32_t Map::bit_field3() {
4629   Object* value = READ_FIELD(this, kBitField3Offset);
4630   return Smi::cast(value)->value();
4631 }
4632
4633
4634 void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
4635   Object* back_pointer = GetBackPointer();
4636
4637   if (Heap::ShouldZapGarbage() && HasTransitionArray()) {
4638     ZapTransitions();
4639   }
4640
4641   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, back_pointer);
4642   CONDITIONAL_WRITE_BARRIER(
4643       heap, this, kTransitionsOrBackPointerOffset, back_pointer, mode);
4644 }
4645
4646
4647 void Map::AppendDescriptor(Descriptor* desc,
4648                            const DescriptorArray::WhitenessWitness& witness) {
4649   DescriptorArray* descriptors = instance_descriptors();
4650   int number_of_own_descriptors = NumberOfOwnDescriptors();
4651   ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
4652   descriptors->Append(desc, witness);
4653   SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
4654 }
4655
4656
4657 Object* Map::GetBackPointer() {
4658   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4659   if (object->IsDescriptorArray()) {
4660     return TransitionArray::cast(object)->back_pointer_storage();
4661   } else {
4662     ASSERT(object->IsMap() || object->IsUndefined());
4663     return object;
4664   }
4665 }
4666
4667
4668 bool Map::HasElementsTransition() {
4669   return HasTransitionArray() && transitions()->HasElementsTransition();
4670 }
4671
4672
4673 bool Map::HasTransitionArray() {
4674   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4675   return object->IsTransitionArray();
4676 }
4677
4678
4679 Map* Map::elements_transition_map() {
4680   int index = transitions()->Search(GetHeap()->elements_transition_symbol());
4681   return transitions()->GetTarget(index);
4682 }
4683
4684
4685 bool Map::CanHaveMoreTransitions() {
4686   if (!HasTransitionArray()) return true;
4687   return FixedArray::SizeFor(transitions()->length() +
4688                              TransitionArray::kTransitionSize)
4689       <= Page::kMaxRegularHeapObjectSize;
4690 }
4691
4692
4693 MaybeObject* Map::AddTransition(Name* key,
4694                                 Map* target,
4695                                 SimpleTransitionFlag flag) {
4696   if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
4697   return TransitionArray::NewWith(flag, key, target, GetBackPointer());
4698 }
4699
4700
4701 void Map::SetTransition(int transition_index, Map* target) {
4702   transitions()->SetTarget(transition_index, target);
4703 }
4704
4705
4706 Map* Map::GetTransition(int transition_index) {
4707   return transitions()->GetTarget(transition_index);
4708 }
4709
4710
4711 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) {
4712   TransitionArray* transitions;
4713   MaybeObject* maybe_transitions = AddTransition(
4714       GetHeap()->elements_transition_symbol(),
4715       transitioned_map,
4716       FULL_TRANSITION);
4717   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4718   set_transitions(transitions);
4719   return transitions;
4720 }
4721
4722
4723 FixedArray* Map::GetPrototypeTransitions() {
4724   if (!HasTransitionArray()) return GetHeap()->empty_fixed_array();
4725   if (!transitions()->HasPrototypeTransitions()) {
4726     return GetHeap()->empty_fixed_array();
4727   }
4728   return transitions()->GetPrototypeTransitions();
4729 }
4730
4731
4732 MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
4733   MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
4734   if (allow_prototype->IsFailure()) return allow_prototype;
4735   int old_number_of_transitions = NumberOfProtoTransitions();
4736 #ifdef DEBUG
4737   if (HasPrototypeTransitions()) {
4738     ASSERT(GetPrototypeTransitions() != proto_transitions);
4739     ZapPrototypeTransitions();
4740   }
4741 #endif
4742   transitions()->SetPrototypeTransitions(proto_transitions);
4743   SetNumberOfProtoTransitions(old_number_of_transitions);
4744   return this;
4745 }
4746
4747
4748 bool Map::HasPrototypeTransitions() {
4749   return HasTransitionArray() && transitions()->HasPrototypeTransitions();
4750 }
4751
4752
4753 TransitionArray* Map::transitions() {
4754   ASSERT(HasTransitionArray());
4755   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4756   return TransitionArray::cast(object);
4757 }
4758
4759
4760 void Map::set_transitions(TransitionArray* transition_array,
4761                           WriteBarrierMode mode) {
4762   // Transition arrays are not shared. When one is replaced, it should not
4763   // keep referenced objects alive, so we zap it.
4764   // When there is another reference to the array somewhere (e.g. a handle),
4765   // not zapping turns from a waste of memory into a source of crashes.
4766   if (HasTransitionArray()) {
4767 #ifdef DEBUG
4768     for (int i = 0; i < transitions()->number_of_transitions(); i++) {
4769       Map* target = transitions()->GetTarget(i);
4770       if (target->instance_descriptors() == instance_descriptors()) {
4771         Name* key = transitions()->GetKey(i);
4772         int new_target_index = transition_array->Search(key);
4773         ASSERT(new_target_index != TransitionArray::kNotFound);
4774         ASSERT(transition_array->GetTarget(new_target_index) == target);
4775       }
4776     }
4777 #endif
4778     ASSERT(transitions() != transition_array);
4779     ZapTransitions();
4780   }
4781
4782   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, transition_array);
4783   CONDITIONAL_WRITE_BARRIER(
4784       GetHeap(), this, kTransitionsOrBackPointerOffset, transition_array, mode);
4785 }
4786
4787
4788 void Map::init_back_pointer(Object* undefined) {
4789   ASSERT(undefined->IsUndefined());
4790   WRITE_FIELD(this, kTransitionsOrBackPointerOffset, undefined);
4791 }
4792
4793
4794 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) {
4795   ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE);
4796   ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) ||
4797          (value->IsMap() && GetBackPointer()->IsUndefined()));
4798   Object* object = READ_FIELD(this, kTransitionsOrBackPointerOffset);
4799   if (object->IsTransitionArray()) {
4800     TransitionArray::cast(object)->set_back_pointer_storage(value);
4801   } else {
4802     WRITE_FIELD(this, kTransitionsOrBackPointerOffset, value);
4803     CONDITIONAL_WRITE_BARRIER(
4804         GetHeap(), this, kTransitionsOrBackPointerOffset, value, mode);
4805   }
4806 }
4807
4808
4809 // Can either be Smi (no transitions), normal transition array, or a transition
4810 // array with the header overwritten as a Smi (thus iterating).
4811 TransitionArray* Map::unchecked_transition_array() {
4812   Object* object = *HeapObject::RawField(this,
4813                                          Map::kTransitionsOrBackPointerOffset);
4814   TransitionArray* transition_array = static_cast<TransitionArray*>(object);
4815   return transition_array;
4816 }
4817
4818
4819 HeapObject* Map::UncheckedPrototypeTransitions() {
4820   ASSERT(HasTransitionArray());
4821   ASSERT(unchecked_transition_array()->HasPrototypeTransitions());
4822   return unchecked_transition_array()->UncheckedPrototypeTransitions();
4823 }
4824
4825
4826 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
4827 ACCESSORS(Map, dependent_code, DependentCode, kDependentCodeOffset)
4828 ACCESSORS(Map, constructor, Object, kConstructorOffset)
4829
4830 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
4831 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
4832 ACCESSORS(JSFunction, next_function_link, Object, kNextFunctionLinkOffset)
4833
4834 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
4835 ACCESSORS(GlobalObject, native_context, Context, kNativeContextOffset)
4836 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
4837 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
4838
4839 ACCESSORS(JSGlobalProxy, native_context, Object, kNativeContextOffset)
4840
4841 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
4842 ACCESSORS_TO_SMI(AccessorInfo, flag, kFlagOffset)
4843 ACCESSORS(AccessorInfo, expected_receiver_type, Object,
4844           kExpectedReceiverTypeOffset)
4845
4846 ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
4847           kSerializedDataOffset)
4848
4849 ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
4850           kDescriptorOffset)
4851
4852 ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
4853 ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
4854 ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
4855
4856 ACCESSORS(Box, value, Object, kValueOffset)
4857
4858 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
4859 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
4860 ACCESSORS_TO_SMI(AccessorPair, access_flags, kAccessFlagsOffset)
4861
4862 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
4863 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
4864 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
4865
4866 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
4867 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
4868 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
4869 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
4870 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
4871 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
4872
4873 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
4874 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
4875
4876 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
4877 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
4878 ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
4879
4880 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
4881 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
4882 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
4883           kPrototypeTemplateOffset)
4884 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
4885 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
4886           kNamedPropertyHandlerOffset)
4887 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
4888           kIndexedPropertyHandlerOffset)
4889 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
4890           kInstanceTemplateOffset)
4891 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
4892 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
4893 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
4894           kInstanceCallHandlerOffset)
4895 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
4896           kAccessCheckInfoOffset)
4897 ACCESSORS_TO_SMI(FunctionTemplateInfo, flag, kFlagOffset)
4898
4899 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
4900 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
4901           kInternalFieldCountOffset)
4902
4903 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
4904 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
4905
4906 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
4907
4908 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
4909 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
4910 ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
4911 ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
4912                  kPretenureCreateCountOffset)
4913 ACCESSORS(AllocationSite, dependent_code, DependentCode,
4914           kDependentCodeOffset)
4915 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
4916 ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
4917
4918 ACCESSORS(Script, source, Object, kSourceOffset)
4919 ACCESSORS(Script, name, Object, kNameOffset)
4920 ACCESSORS(Script, id, Smi, kIdOffset)
4921 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
4922 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
4923 ACCESSORS(Script, data, Object, kDataOffset)
4924 ACCESSORS(Script, context_data, Object, kContextOffset)
4925 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
4926 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
4927 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
4928 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
4929 ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
4930                  kEvalFrominstructionsOffsetOffset)
4931 ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
4932 BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
4933
4934 Script::CompilationType Script::compilation_type() {
4935   return BooleanBit::get(flags(), kCompilationTypeBit) ?
4936       COMPILATION_TYPE_EVAL : COMPILATION_TYPE_HOST;
4937 }
4938 void Script::set_compilation_type(CompilationType type) {
4939   set_flags(BooleanBit::set(flags(), kCompilationTypeBit,
4940       type == COMPILATION_TYPE_EVAL));
4941 }
4942 Script::CompilationState Script::compilation_state() {
4943   return BooleanBit::get(flags(), kCompilationStateBit) ?
4944       COMPILATION_STATE_COMPILED : COMPILATION_STATE_INITIAL;
4945 }
4946 void Script::set_compilation_state(CompilationState state) {
4947   set_flags(BooleanBit::set(flags(), kCompilationStateBit,
4948       state == COMPILATION_STATE_COMPILED));
4949 }
4950
4951
4952 #ifdef ENABLE_DEBUGGER_SUPPORT
4953 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
4954 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
4955 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
4956 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
4957
4958 ACCESSORS_TO_SMI(BreakPointInfo, code_position, kCodePositionIndex)
4959 ACCESSORS_TO_SMI(BreakPointInfo, source_position, kSourcePositionIndex)
4960 ACCESSORS_TO_SMI(BreakPointInfo, statement_position, kStatementPositionIndex)
4961 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
4962 #endif
4963
4964 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
4965 ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
4966                  kOptimizedCodeMapOffset)
4967 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
4968 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
4969 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
4970           kInstanceClassNameOffset)
4971 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
4972 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
4973 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
4974 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
4975 SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
4976
4977
4978 SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
4979 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
4980                kHiddenPrototypeBit)
4981 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
4982 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
4983                kNeedsAccessCheckBit)
4984 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
4985                kReadOnlyPrototypeBit)
4986 BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
4987                kRemovePrototypeBit)
4988 BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
4989                kDoNotCacheBit)
4990 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
4991                kIsExpressionBit)
4992 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
4993                kIsTopLevelBit)
4994
4995 BOOL_ACCESSORS(SharedFunctionInfo,
4996                compiler_hints,
4997                allows_lazy_compilation,
4998                kAllowLazyCompilation)
4999 BOOL_ACCESSORS(SharedFunctionInfo,
5000                compiler_hints,
5001                allows_lazy_compilation_without_context,
5002                kAllowLazyCompilationWithoutContext)
5003 BOOL_ACCESSORS(SharedFunctionInfo,
5004                compiler_hints,
5005                uses_arguments,
5006                kUsesArguments)
5007 BOOL_ACCESSORS(SharedFunctionInfo,
5008                compiler_hints,
5009                has_duplicate_parameters,
5010                kHasDuplicateParameters)
5011
5012
5013 #if V8_HOST_ARCH_32_BIT
5014 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
5015 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
5016               kFormalParameterCountOffset)
5017 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
5018               kExpectedNofPropertiesOffset)
5019 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5020 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
5021               kStartPositionAndTypeOffset)
5022 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
5023 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
5024               kFunctionTokenPositionOffset)
5025 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
5026               kCompilerHintsOffset)
5027 SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
5028               kOptCountAndBailoutReasonOffset)
5029 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
5030
5031 #else
5032
5033 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
5034   STATIC_ASSERT(holder::offset % kPointerSize == 0);              \
5035   int holder::name() {                                            \
5036     int value = READ_INT_FIELD(this, offset);                     \
5037     ASSERT(kHeapObjectTag == 1);                                  \
5038     ASSERT((value & kHeapObjectTag) == 0);                        \
5039     return value >> 1;                                            \
5040   }                                                               \
5041   void holder::set_##name(int value) {                            \
5042     ASSERT(kHeapObjectTag == 1);                                  \
5043     ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
5044            (value & 0xC0000000) == 0x000000000);                  \
5045     WRITE_INT_FIELD(this,                                         \
5046                     offset,                                       \
5047                     (value << 1) & ~kHeapObjectTag);              \
5048   }
5049
5050 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)             \
5051   STATIC_ASSERT(holder::offset % kPointerSize == kIntSize);       \
5052   INT_ACCESSORS(holder, name, offset)
5053
5054
5055 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
5056 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5057                         formal_parameter_count,
5058                         kFormalParameterCountOffset)
5059
5060 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5061                         expected_nof_properties,
5062                         kExpectedNofPropertiesOffset)
5063 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
5064
5065 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
5066 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5067                         start_position_and_type,
5068                         kStartPositionAndTypeOffset)
5069
5070 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5071                         function_token_position,
5072                         kFunctionTokenPositionOffset)
5073 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
5074                         compiler_hints,
5075                         kCompilerHintsOffset)
5076
5077 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
5078                         opt_count_and_bailout_reason,
5079                         kOptCountAndBailoutReasonOffset)
5080
5081 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
5082
5083 #endif
5084
5085
5086 int SharedFunctionInfo::construction_count() {
5087   return READ_BYTE_FIELD(this, kConstructionCountOffset);
5088 }
5089
5090
5091 void SharedFunctionInfo::set_construction_count(int value) {
5092   ASSERT(0 <= value && value < 256);
5093   WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
5094 }
5095
5096
5097 BOOL_ACCESSORS(SharedFunctionInfo,
5098                compiler_hints,
5099                live_objects_may_exist,
5100                kLiveObjectsMayExist)
5101
5102
5103 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
5104   return initial_map() != GetHeap()->undefined_value();
5105 }
5106
5107
5108 BOOL_GETTER(SharedFunctionInfo,
5109             compiler_hints,
5110             optimization_disabled,
5111             kOptimizationDisabled)
5112
5113
5114 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
5115   set_compiler_hints(BooleanBit::set(compiler_hints(),
5116                                      kOptimizationDisabled,
5117                                      disable));
5118   // If disabling optimizations we reflect that in the code object so
5119   // it will not be counted as optimizable code.
5120   if ((code()->kind() == Code::FUNCTION) && disable) {
5121     code()->set_optimizable(false);
5122   }
5123 }
5124
5125
5126 int SharedFunctionInfo::profiler_ticks() {
5127   if (code()->kind() != Code::FUNCTION) return 0;
5128   return code()->profiler_ticks();
5129 }
5130
5131
5132 LanguageMode SharedFunctionInfo::language_mode() {
5133   int hints = compiler_hints();
5134   if (BooleanBit::get(hints, kExtendedModeFunction)) {
5135     ASSERT(BooleanBit::get(hints, kStrictModeFunction));
5136     return EXTENDED_MODE;
5137   }
5138   return BooleanBit::get(hints, kStrictModeFunction)
5139       ? STRICT_MODE : CLASSIC_MODE;
5140 }
5141
5142
5143 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
5144   // We only allow language mode transitions that go set the same language mode
5145   // again or go up in the chain:
5146   //   CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
5147   ASSERT(this->language_mode() == CLASSIC_MODE ||
5148          this->language_mode() == language_mode ||
5149          language_mode == EXTENDED_MODE);
5150   int hints = compiler_hints();
5151   hints = BooleanBit::set(
5152       hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
5153   hints = BooleanBit::set(
5154       hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
5155   set_compiler_hints(hints);
5156 }
5157
5158
5159 bool SharedFunctionInfo::is_classic_mode() {
5160   return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
5161 }
5162
5163 BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
5164             kExtendedModeFunction)
5165 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
5166 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
5167                kInlineBuiltin)
5168 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
5169                name_should_print_as_anonymous,
5170                kNameShouldPrintAsAnonymous)
5171 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
5172 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
5173 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
5174 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_optimize,
5175                kDontOptimize)
5176 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
5177 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
5178 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
5179 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
5180
5181 void SharedFunctionInfo::BeforeVisitingPointers() {
5182   if (IsInobjectSlackTrackingInProgress()) DetachInitialMap();
5183 }
5184
5185
5186 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
5187 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
5188
5189 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
5190
5191 bool Script::HasValidSource() {
5192   Object* src = this->source();
5193   if (!src->IsString()) return true;
5194   String* src_str = String::cast(src);
5195   if (!StringShape(src_str).IsExternal()) return true;
5196   if (src_str->IsOneByteRepresentation()) {
5197     return ExternalAsciiString::cast(src)->resource() != NULL;
5198   } else if (src_str->IsTwoByteRepresentation()) {
5199     return ExternalTwoByteString::cast(src)->resource() != NULL;
5200   }
5201   return true;
5202 }
5203
5204
5205 void SharedFunctionInfo::DontAdaptArguments() {
5206   ASSERT(code()->kind() == Code::BUILTIN);
5207   set_formal_parameter_count(kDontAdaptArgumentsSentinel);
5208 }
5209
5210
5211 int SharedFunctionInfo::start_position() {
5212   return start_position_and_type() >> kStartPositionShift;
5213 }
5214
5215
5216 void SharedFunctionInfo::set_start_position(int start_position) {
5217   set_start_position_and_type((start_position << kStartPositionShift)
5218     | (start_position_and_type() & ~kStartPositionMask));
5219 }
5220
5221
5222 Code* SharedFunctionInfo::code() {
5223   return Code::cast(READ_FIELD(this, kCodeOffset));
5224 }
5225
5226
5227 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
5228   ASSERT(value->kind() != Code::OPTIMIZED_FUNCTION);
5229   WRITE_FIELD(this, kCodeOffset, value);
5230   CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
5231 }
5232
5233
5234 void SharedFunctionInfo::ReplaceCode(Code* value) {
5235   // If the GC metadata field is already used then the function was
5236   // enqueued as a code flushing candidate and we remove it now.
5237   if (code()->gc_metadata() != NULL) {
5238     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
5239     flusher->EvictCandidate(this);
5240   }
5241
5242   ASSERT(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
5243   set_code(value);
5244 }
5245
5246
5247 ScopeInfo* SharedFunctionInfo::scope_info() {
5248   return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
5249 }
5250
5251
5252 void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
5253                                         WriteBarrierMode mode) {
5254   WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
5255   CONDITIONAL_WRITE_BARRIER(GetHeap(),
5256                             this,
5257                             kScopeInfoOffset,
5258                             reinterpret_cast<Object*>(value),
5259                             mode);
5260 }
5261
5262
5263 bool SharedFunctionInfo::is_compiled() {
5264   return code() !=
5265       GetIsolate()->builtins()->builtin(Builtins::kCompileUnoptimized);
5266 }
5267
5268
5269 bool SharedFunctionInfo::IsApiFunction() {
5270   return function_data()->IsFunctionTemplateInfo();
5271 }
5272
5273
5274 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
5275   ASSERT(IsApiFunction());
5276   return FunctionTemplateInfo::cast(function_data());
5277 }
5278
5279
5280 bool SharedFunctionInfo::HasBuiltinFunctionId() {
5281   return function_data()->IsSmi();
5282 }
5283
5284
5285 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
5286   ASSERT(HasBuiltinFunctionId());
5287   return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
5288 }
5289
5290
5291 int SharedFunctionInfo::ic_age() {
5292   return ICAgeBits::decode(counters());
5293 }
5294
5295
5296 void SharedFunctionInfo::set_ic_age(int ic_age) {
5297   set_counters(ICAgeBits::update(counters(), ic_age));
5298 }
5299
5300
5301 int SharedFunctionInfo::deopt_count() {
5302   return DeoptCountBits::decode(counters());
5303 }
5304
5305
5306 void SharedFunctionInfo::set_deopt_count(int deopt_count) {
5307   set_counters(DeoptCountBits::update(counters(), deopt_count));
5308 }
5309
5310
5311 void SharedFunctionInfo::increment_deopt_count() {
5312   int value = counters();
5313   int deopt_count = DeoptCountBits::decode(value);
5314   deopt_count = (deopt_count + 1) & DeoptCountBits::kMax;
5315   set_counters(DeoptCountBits::update(value, deopt_count));
5316 }
5317
5318
5319 int SharedFunctionInfo::opt_reenable_tries() {
5320   return OptReenableTriesBits::decode(counters());
5321 }
5322
5323
5324 void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
5325   set_counters(OptReenableTriesBits::update(counters(), tries));
5326 }
5327
5328
5329 int SharedFunctionInfo::opt_count() {
5330   return OptCountBits::decode(opt_count_and_bailout_reason());
5331 }
5332
5333
5334 void SharedFunctionInfo::set_opt_count(int opt_count) {
5335   set_opt_count_and_bailout_reason(
5336       OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
5337 }
5338
5339
5340 BailoutReason SharedFunctionInfo::DisableOptimizationReason() {
5341   BailoutReason reason = static_cast<BailoutReason>(
5342       DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
5343   return reason;
5344 }
5345
5346
5347 bool SharedFunctionInfo::has_deoptimization_support() {
5348   Code* code = this->code();
5349   return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
5350 }
5351
5352
5353 void SharedFunctionInfo::TryReenableOptimization() {
5354   int tries = opt_reenable_tries();
5355   set_opt_reenable_tries((tries + 1) & OptReenableTriesBits::kMax);
5356   // We reenable optimization whenever the number of tries is a large
5357   // enough power of 2.
5358   if (tries >= 16 && (((tries - 1) & tries) == 0)) {
5359     set_optimization_disabled(false);
5360     set_opt_count(0);
5361     set_deopt_count(0);
5362     code()->set_optimizable(true);
5363   }
5364 }
5365
5366
5367 bool JSFunction::IsBuiltin() {
5368   return context()->global_object()->IsJSBuiltinsObject();
5369 }
5370
5371
5372 bool JSFunction::NeedsArgumentsAdaption() {
5373   return shared()->formal_parameter_count() !=
5374       SharedFunctionInfo::kDontAdaptArgumentsSentinel;
5375 }
5376
5377
5378 bool JSFunction::IsOptimized() {
5379   return code()->kind() == Code::OPTIMIZED_FUNCTION;
5380 }
5381
5382
5383 bool JSFunction::IsOptimizable() {
5384   return code()->kind() == Code::FUNCTION && code()->optimizable();
5385 }
5386
5387
5388 bool JSFunction::IsMarkedForOptimization() {
5389   return code() == GetIsolate()->builtins()->builtin(
5390       Builtins::kCompileOptimized);
5391 }
5392
5393
5394 bool JSFunction::IsMarkedForConcurrentOptimization() {
5395   return code() == GetIsolate()->builtins()->builtin(
5396       Builtins::kCompileOptimizedConcurrent);
5397 }
5398
5399
5400 bool JSFunction::IsInOptimizationQueue() {
5401   return code() == GetIsolate()->builtins()->builtin(
5402       Builtins::kInOptimizationQueue);
5403 }
5404
5405
5406 Code* JSFunction::code() {
5407   return Code::cast(
5408       Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
5409 }
5410
5411
5412 void JSFunction::set_code(Code* value) {
5413   ASSERT(!GetHeap()->InNewSpace(value));
5414   Address entry = value->entry();
5415   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5416   GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
5417       this,
5418       HeapObject::RawField(this, kCodeEntryOffset),
5419       value);
5420 }
5421
5422
5423 void JSFunction::set_code_no_write_barrier(Code* value) {
5424   ASSERT(!GetHeap()->InNewSpace(value));
5425   Address entry = value->entry();
5426   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
5427 }
5428
5429
5430 void JSFunction::ReplaceCode(Code* code) {
5431   bool was_optimized = IsOptimized();
5432   bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
5433
5434   if (was_optimized && is_optimized) {
5435     shared()->EvictFromOptimizedCodeMap(
5436       this->code(), "Replacing with another optimized code");
5437   }
5438
5439   set_code(code);
5440
5441   // Add/remove the function from the list of optimized functions for this
5442   // context based on the state change.
5443   if (!was_optimized && is_optimized) {
5444     context()->native_context()->AddOptimizedFunction(this);
5445   }
5446   if (was_optimized && !is_optimized) {
5447     // TODO(titzer): linear in the number of optimized functions; fix!
5448     context()->native_context()->RemoveOptimizedFunction(this);
5449   }
5450 }
5451
5452
5453 Context* JSFunction::context() {
5454   return Context::cast(READ_FIELD(this, kContextOffset));
5455 }
5456
5457
5458 void JSFunction::set_context(Object* value) {
5459   ASSERT(value->IsUndefined() || value->IsContext());
5460   WRITE_FIELD(this, kContextOffset, value);
5461   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
5462 }
5463
5464 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
5465           kPrototypeOrInitialMapOffset)
5466
5467
5468 Map* JSFunction::initial_map() {
5469   return Map::cast(prototype_or_initial_map());
5470 }
5471
5472
5473 void JSFunction::set_initial_map(Map* value) {
5474   set_prototype_or_initial_map(value);
5475 }
5476
5477
5478 bool JSFunction::has_initial_map() {
5479   return prototype_or_initial_map()->IsMap();
5480 }
5481
5482
5483 bool JSFunction::has_instance_prototype() {
5484   return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
5485 }
5486
5487
5488 bool JSFunction::has_prototype() {
5489   return map()->has_non_instance_prototype() || has_instance_prototype();
5490 }
5491
5492
5493 Object* JSFunction::instance_prototype() {
5494   ASSERT(has_instance_prototype());
5495   if (has_initial_map()) return initial_map()->prototype();
5496   // When there is no initial map and the prototype is a JSObject, the
5497   // initial map field is used for the prototype field.
5498   return prototype_or_initial_map();
5499 }
5500
5501
5502 Object* JSFunction::prototype() {
5503   ASSERT(has_prototype());
5504   // If the function's prototype property has been set to a non-JSObject
5505   // value, that value is stored in the constructor field of the map.
5506   if (map()->has_non_instance_prototype()) return map()->constructor();
5507   return instance_prototype();
5508 }
5509
5510
5511 bool JSFunction::should_have_prototype() {
5512   return map()->function_with_prototype();
5513 }
5514
5515
5516 bool JSFunction::is_compiled() {
5517   return code() !=
5518       GetIsolate()->builtins()->builtin(Builtins::kCompileUnoptimized);
5519 }
5520
5521
5522 FixedArray* JSFunction::literals() {
5523   ASSERT(!shared()->bound());
5524   return literals_or_bindings();
5525 }
5526
5527
5528 void JSFunction::set_literals(FixedArray* literals) {
5529   ASSERT(!shared()->bound());
5530   set_literals_or_bindings(literals);
5531 }
5532
5533
5534 FixedArray* JSFunction::function_bindings() {
5535   ASSERT(shared()->bound());
5536   return literals_or_bindings();
5537 }
5538
5539
5540 void JSFunction::set_function_bindings(FixedArray* bindings) {
5541   ASSERT(shared()->bound());
5542   // Bound function literal may be initialized to the empty fixed array
5543   // before the bindings are set.
5544   ASSERT(bindings == GetHeap()->empty_fixed_array() ||
5545          bindings->map() == GetHeap()->fixed_cow_array_map());
5546   set_literals_or_bindings(bindings);
5547 }
5548
5549
5550 int JSFunction::NumberOfLiterals() {
5551   ASSERT(!shared()->bound());
5552   return literals()->length();
5553 }
5554
5555
5556 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
5557   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5558   return READ_FIELD(this, OffsetOfFunctionWithId(id));
5559 }
5560
5561
5562 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
5563                                               Object* value) {
5564   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5565   WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
5566   WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
5567 }
5568
5569
5570 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
5571   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5572   return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
5573 }
5574
5575
5576 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
5577                                                    Code* value) {
5578   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
5579   WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
5580   ASSERT(!GetHeap()->InNewSpace(value));
5581 }
5582
5583
5584 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
5585 ACCESSORS(JSProxy, hash, Object, kHashOffset)
5586 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
5587 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
5588
5589
5590 void JSProxy::InitializeBody(int object_size, Object* value) {
5591   ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
5592   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
5593     WRITE_FIELD(this, offset, value);
5594   }
5595 }
5596
5597
5598 ACCESSORS(JSSet, table, Object, kTableOffset)
5599 ACCESSORS(JSMap, table, Object, kTableOffset)
5600 ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
5601 ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
5602
5603
5604 Address Foreign::foreign_address() {
5605   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
5606 }
5607
5608
5609 void Foreign::set_foreign_address(Address value) {
5610   WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
5611 }
5612
5613
5614 ACCESSORS(JSGeneratorObject, function, JSFunction, kFunctionOffset)
5615 ACCESSORS(JSGeneratorObject, context, Context, kContextOffset)
5616 ACCESSORS(JSGeneratorObject, receiver, Object, kReceiverOffset)
5617 SMI_ACCESSORS(JSGeneratorObject, continuation, kContinuationOffset)
5618 ACCESSORS(JSGeneratorObject, operand_stack, FixedArray, kOperandStackOffset)
5619 SMI_ACCESSORS(JSGeneratorObject, stack_handler_index, kStackHandlerIndexOffset)
5620
5621
5622 JSGeneratorObject* JSGeneratorObject::cast(Object* obj) {
5623   ASSERT(obj->IsJSGeneratorObject());
5624   ASSERT(HeapObject::cast(obj)->Size() == JSGeneratorObject::kSize);
5625   return reinterpret_cast<JSGeneratorObject*>(obj);
5626 }
5627
5628
5629 ACCESSORS(JSModule, context, Object, kContextOffset)
5630 ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
5631
5632
5633 JSModule* JSModule::cast(Object* obj) {
5634   ASSERT(obj->IsJSModule());
5635   ASSERT(HeapObject::cast(obj)->Size() == JSModule::kSize);
5636   return reinterpret_cast<JSModule*>(obj);
5637 }
5638
5639
5640 ACCESSORS(JSValue, value, Object, kValueOffset)
5641
5642
5643 JSValue* JSValue::cast(Object* obj) {
5644   ASSERT(obj->IsJSValue());
5645   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
5646   return reinterpret_cast<JSValue*>(obj);
5647 }
5648
5649
5650 ACCESSORS(JSDate, value, Object, kValueOffset)
5651 ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
5652 ACCESSORS(JSDate, year, Object, kYearOffset)
5653 ACCESSORS(JSDate, month, Object, kMonthOffset)
5654 ACCESSORS(JSDate, day, Object, kDayOffset)
5655 ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
5656 ACCESSORS(JSDate, hour, Object, kHourOffset)
5657 ACCESSORS(JSDate, min, Object, kMinOffset)
5658 ACCESSORS(JSDate, sec, Object, kSecOffset)
5659
5660
5661 JSDate* JSDate::cast(Object* obj) {
5662   ASSERT(obj->IsJSDate());
5663   ASSERT(HeapObject::cast(obj)->Size() == JSDate::kSize);
5664   return reinterpret_cast<JSDate*>(obj);
5665 }
5666
5667
5668 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
5669 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
5670 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
5671 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
5672 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
5673 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
5674 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
5675
5676
5677 JSMessageObject* JSMessageObject::cast(Object* obj) {
5678   ASSERT(obj->IsJSMessageObject());
5679   ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
5680   return reinterpret_cast<JSMessageObject*>(obj);
5681 }
5682
5683
5684 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
5685 INT_ACCESSORS(Code, prologue_offset, kPrologueOffset)
5686 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
5687 ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
5688 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
5689 ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
5690
5691
5692 void Code::WipeOutHeader() {
5693   WRITE_FIELD(this, kRelocationInfoOffset, NULL);
5694   WRITE_FIELD(this, kHandlerTableOffset, NULL);
5695   WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
5696   // Do not wipe out e.g. a minor key.
5697   if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
5698     WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
5699   }
5700 }
5701
5702
5703 Object* Code::type_feedback_info() {
5704   ASSERT(kind() == FUNCTION);
5705   return raw_type_feedback_info();
5706 }
5707
5708
5709 void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
5710   ASSERT(kind() == FUNCTION);
5711   set_raw_type_feedback_info(value, mode);
5712   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
5713                             value, mode);
5714 }
5715
5716
5717 Object* Code::next_code_link() {
5718   CHECK(kind() == OPTIMIZED_FUNCTION);
5719   return raw_type_feedback_info();
5720 }
5721
5722
5723 void Code::set_next_code_link(Object* value, WriteBarrierMode mode) {
5724   CHECK(kind() == OPTIMIZED_FUNCTION);
5725   set_raw_type_feedback_info(value);
5726   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kTypeFeedbackInfoOffset,
5727                             value, mode);
5728 }
5729
5730
5731 int Code::stub_info() {
5732   ASSERT(kind() == COMPARE_IC || kind() == COMPARE_NIL_IC ||
5733          kind() == BINARY_OP_IC || kind() == LOAD_IC);
5734   return Smi::cast(raw_type_feedback_info())->value();
5735 }
5736
5737
5738 void Code::set_stub_info(int value) {
5739   ASSERT(kind() == COMPARE_IC ||
5740          kind() == COMPARE_NIL_IC ||
5741          kind() == BINARY_OP_IC ||
5742          kind() == STUB ||
5743          kind() == LOAD_IC ||
5744          kind() == KEYED_LOAD_IC ||
5745          kind() == STORE_IC ||
5746          kind() == KEYED_STORE_IC);
5747   set_raw_type_feedback_info(Smi::FromInt(value));
5748 }
5749
5750
5751 ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
5752 INT_ACCESSORS(Code, ic_age, kICAgeOffset)
5753
5754
5755 byte* Code::instruction_start()  {
5756   return FIELD_ADDR(this, kHeaderSize);
5757 }
5758
5759
5760 byte* Code::instruction_end()  {
5761   return instruction_start() + instruction_size();
5762 }
5763
5764
5765 int Code::body_size() {
5766   return RoundUp(instruction_size(), kObjectAlignment);
5767 }
5768
5769
5770 ByteArray* Code::unchecked_relocation_info() {
5771   return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
5772 }
5773
5774
5775 byte* Code::relocation_start() {
5776   return unchecked_relocation_info()->GetDataStartAddress();
5777 }
5778
5779
5780 int Code::relocation_size() {
5781   return unchecked_relocation_info()->length();
5782 }
5783
5784
5785 byte* Code::entry() {
5786   return instruction_start();
5787 }
5788
5789
5790 bool Code::contains(byte* inner_pointer) {
5791   return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
5792 }
5793
5794
5795 ACCESSORS(JSArray, length, Object, kLengthOffset)
5796
5797
5798 void* JSArrayBuffer::backing_store() {
5799   intptr_t ptr = READ_INTPTR_FIELD(this, kBackingStoreOffset);
5800   return reinterpret_cast<void*>(ptr);
5801 }
5802
5803
5804 void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
5805   intptr_t ptr = reinterpret_cast<intptr_t>(value);
5806   WRITE_INTPTR_FIELD(this, kBackingStoreOffset, ptr);
5807 }
5808
5809
5810 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
5811 ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
5812
5813
5814 bool JSArrayBuffer::is_external() {
5815   return BooleanBit::get(flag(), kIsExternalBit);
5816 }
5817
5818
5819 void JSArrayBuffer::set_is_external(bool value) {
5820   set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
5821 }
5822
5823
5824 bool JSArrayBuffer::should_be_freed() {
5825   return BooleanBit::get(flag(), kShouldBeFreed);
5826 }
5827
5828
5829 void JSArrayBuffer::set_should_be_freed(bool value) {
5830   set_flag(BooleanBit::set(flag(), kShouldBeFreed, value));
5831 }
5832
5833
5834 ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset)
5835 ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset)
5836
5837
5838 ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset)
5839 ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset)
5840 ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset)
5841 ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset)
5842 ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
5843
5844 ACCESSORS(JSRegExp, data, Object, kDataOffset)
5845
5846
5847 JSRegExp::Type JSRegExp::TypeTag() {
5848   Object* data = this->data();
5849   if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
5850   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
5851   return static_cast<JSRegExp::Type>(smi->value());
5852 }
5853
5854
5855 int JSRegExp::CaptureCount() {
5856   switch (TypeTag()) {
5857     case ATOM:
5858       return 0;
5859     case IRREGEXP:
5860       return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
5861     default:
5862       UNREACHABLE();
5863       return -1;
5864   }
5865 }
5866
5867
5868 JSRegExp::Flags JSRegExp::GetFlags() {
5869   ASSERT(this->data()->IsFixedArray());
5870   Object* data = this->data();
5871   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
5872   return Flags(smi->value());
5873 }
5874
5875
5876 String* JSRegExp::Pattern() {
5877   ASSERT(this->data()->IsFixedArray());
5878   Object* data = this->data();
5879   String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
5880   return pattern;
5881 }
5882
5883
5884 Object* JSRegExp::DataAt(int index) {
5885   ASSERT(TypeTag() != NOT_COMPILED);
5886   return FixedArray::cast(data())->get(index);
5887 }
5888
5889
5890 void JSRegExp::SetDataAt(int index, Object* value) {
5891   ASSERT(TypeTag() != NOT_COMPILED);
5892   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
5893   FixedArray::cast(data())->set(index, value);
5894 }
5895
5896
5897 ElementsKind JSObject::GetElementsKind() {
5898   ElementsKind kind = map()->elements_kind();
5899 #if DEBUG
5900   FixedArrayBase* fixed_array =
5901       reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
5902
5903   // If a GC was caused while constructing this object, the elements
5904   // pointer may point to a one pointer filler map.
5905   if (ElementsAreSafeToExamine()) {
5906     Map* map = fixed_array->map();
5907     ASSERT((IsFastSmiOrObjectElementsKind(kind) &&
5908             (map == GetHeap()->fixed_array_map() ||
5909              map == GetHeap()->fixed_cow_array_map())) ||
5910            (IsFastDoubleElementsKind(kind) &&
5911             (fixed_array->IsFixedDoubleArray() ||
5912              fixed_array == GetHeap()->empty_fixed_array())) ||
5913            (kind == DICTIONARY_ELEMENTS &&
5914             fixed_array->IsFixedArray() &&
5915             fixed_array->IsDictionary()) ||
5916            (kind > DICTIONARY_ELEMENTS));
5917     ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
5918            (elements()->IsFixedArray() && elements()->length() >= 2));
5919   }
5920 #endif
5921   return kind;
5922 }
5923
5924
5925 ElementsAccessor* JSObject::GetElementsAccessor() {
5926   return ElementsAccessor::ForKind(GetElementsKind());
5927 }
5928
5929
5930 bool JSObject::HasFastObjectElements() {
5931   return IsFastObjectElementsKind(GetElementsKind());
5932 }
5933
5934
5935 bool JSObject::HasFastSmiElements() {
5936   return IsFastSmiElementsKind(GetElementsKind());
5937 }
5938
5939
5940 bool JSObject::HasFastSmiOrObjectElements() {
5941   return IsFastSmiOrObjectElementsKind(GetElementsKind());
5942 }
5943
5944
5945 bool JSObject::HasFastDoubleElements() {
5946   return IsFastDoubleElementsKind(GetElementsKind());
5947 }
5948
5949
5950 bool JSObject::HasFastHoleyElements() {
5951   return IsFastHoleyElementsKind(GetElementsKind());
5952 }
5953
5954
5955 bool JSObject::HasFastElements() {
5956   return IsFastElementsKind(GetElementsKind());
5957 }
5958
5959
5960 bool JSObject::HasDictionaryElements() {
5961   return GetElementsKind() == DICTIONARY_ELEMENTS;
5962 }
5963
5964
5965 bool JSObject::HasNonStrictArgumentsElements() {
5966   return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
5967 }
5968
5969
5970 bool JSObject::HasExternalArrayElements() {
5971   HeapObject* array = elements();
5972   ASSERT(array != NULL);
5973   return array->IsExternalArray();
5974 }
5975
5976
5977 #define EXTERNAL_ELEMENTS_CHECK(Type, type, TYPE, ctype, size)          \
5978 bool JSObject::HasExternal##Type##Elements() {                          \
5979   HeapObject* array = elements();                                       \
5980   ASSERT(array != NULL);                                                \
5981   if (!array->IsHeapObject())                                           \
5982     return false;                                                       \
5983   return array->map()->instance_type() == EXTERNAL_##TYPE##_ARRAY_TYPE; \
5984 }
5985
5986 TYPED_ARRAYS(EXTERNAL_ELEMENTS_CHECK)
5987
5988 #undef EXTERNAL_ELEMENTS_CHECK
5989
5990
5991 bool JSObject::HasFixedTypedArrayElements() {
5992   HeapObject* array = elements();
5993   ASSERT(array != NULL);
5994   return array->IsFixedTypedArrayBase();
5995 }
5996
5997
5998 bool JSObject::HasNamedInterceptor() {
5999   return map()->has_named_interceptor();
6000 }
6001
6002
6003 bool JSObject::HasIndexedInterceptor() {
6004   return map()->has_indexed_interceptor();
6005 }
6006
6007
6008 MaybeObject* JSObject::EnsureWritableFastElements() {
6009   ASSERT(HasFastSmiOrObjectElements());
6010   FixedArray* elems = FixedArray::cast(elements());
6011   Isolate* isolate = GetIsolate();
6012   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
6013   Object* writable_elems;
6014   { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
6015       elems, isolate->heap()->fixed_array_map());
6016     if (!maybe_writable_elems->ToObject(&writable_elems)) {
6017       return maybe_writable_elems;
6018     }
6019   }
6020   set_elements(FixedArray::cast(writable_elems));
6021   isolate->counters()->cow_arrays_converted()->Increment();
6022   return writable_elems;
6023 }
6024
6025
6026 NameDictionary* JSObject::property_dictionary() {
6027   ASSERT(!HasFastProperties());
6028   return NameDictionary::cast(properties());
6029 }
6030
6031
6032 SeededNumberDictionary* JSObject::element_dictionary() {
6033   ASSERT(HasDictionaryElements());
6034   return SeededNumberDictionary::cast(elements());
6035 }
6036
6037
6038 bool Name::IsHashFieldComputed(uint32_t field) {
6039   return (field & kHashNotComputedMask) == 0;
6040 }
6041
6042
6043 bool Name::HasHashCode() {
6044   return IsHashFieldComputed(hash_field());
6045 }
6046
6047
6048 uint32_t Name::Hash() {
6049   // Fast case: has hash code already been computed?
6050   uint32_t field = hash_field();
6051   if (IsHashFieldComputed(field)) return field >> kHashShift;
6052   // Slow case: compute hash code and set it. Has to be a string.
6053   return String::cast(this)->ComputeAndSetHash();
6054 }
6055
6056
6057 StringHasher::StringHasher(int length, uint32_t seed)
6058   : length_(length),
6059     raw_running_hash_(seed),
6060     array_index_(0),
6061     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
6062     is_first_char_(true) {
6063   ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0);
6064 }
6065
6066
6067 bool StringHasher::has_trivial_hash() {
6068   return length_ > String::kMaxHashCalcLength;
6069 }
6070
6071
6072 uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
6073   running_hash += c;
6074   running_hash += (running_hash << 10);
6075   running_hash ^= (running_hash >> 6);
6076   return running_hash;
6077 }
6078
6079
6080 uint32_t StringHasher::GetHashCore(uint32_t running_hash) {
6081   running_hash += (running_hash << 3);
6082   running_hash ^= (running_hash >> 11);
6083   running_hash += (running_hash << 15);
6084   if ((running_hash & String::kHashBitMask) == 0) {
6085     return kZeroHash;
6086   }
6087   return running_hash;
6088 }
6089
6090
6091 void StringHasher::AddCharacter(uint16_t c) {
6092   // Use the Jenkins one-at-a-time hash function to update the hash
6093   // for the given character.
6094   raw_running_hash_ = AddCharacterCore(raw_running_hash_, c);
6095 }
6096
6097
6098 bool StringHasher::UpdateIndex(uint16_t c) {
6099   ASSERT(is_array_index_);
6100   if (c < '0' || c > '9') {
6101     is_array_index_ = false;
6102     return false;
6103   }
6104   int d = c - '0';
6105   if (is_first_char_) {
6106     is_first_char_ = false;
6107     if (c == '0' && length_ > 1) {
6108       is_array_index_ = false;
6109       return false;
6110     }
6111   }
6112   if (array_index_ > 429496729U - ((d + 2) >> 3)) {
6113     is_array_index_ = false;
6114     return false;
6115   }
6116   array_index_ = array_index_ * 10 + d;
6117   return true;
6118 }
6119
6120
6121 template<typename Char>
6122 inline void StringHasher::AddCharacters(const Char* chars, int length) {
6123   ASSERT(sizeof(Char) == 1 || sizeof(Char) == 2);
6124   int i = 0;
6125   if (is_array_index_) {
6126     for (; i < length; i++) {
6127       AddCharacter(chars[i]);
6128       if (!UpdateIndex(chars[i])) {
6129         i++;
6130         break;
6131       }
6132     }
6133   }
6134   for (; i < length; i++) {
6135     ASSERT(!is_array_index_);
6136     AddCharacter(chars[i]);
6137   }
6138 }
6139
6140
6141 template <typename schar>
6142 uint32_t StringHasher::HashSequentialString(const schar* chars,
6143                                             int length,
6144                                             uint32_t seed) {
6145   StringHasher hasher(length, seed);
6146   if (!hasher.has_trivial_hash()) hasher.AddCharacters(chars, length);
6147   return hasher.GetHashField();
6148 }
6149
6150
6151 bool Name::AsArrayIndex(uint32_t* index) {
6152   return IsString() && String::cast(this)->AsArrayIndex(index);
6153 }
6154
6155
6156 bool String::AsArrayIndex(uint32_t* index) {
6157   uint32_t field = hash_field();
6158   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
6159     return false;
6160   }
6161   return SlowAsArrayIndex(index);
6162 }
6163
6164
6165 Object* JSReceiver::GetPrototype() {
6166   return map()->prototype();
6167 }
6168
6169
6170 Object* JSReceiver::GetConstructor() {
6171   return map()->constructor();
6172 }
6173
6174
6175 bool JSReceiver::HasProperty(Handle<JSReceiver> object,
6176                              Handle<Name> name) {
6177   if (object->IsJSProxy()) {
6178     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6179     return JSProxy::HasPropertyWithHandler(proxy, name);
6180   }
6181   return object->GetPropertyAttribute(*name) != ABSENT;
6182 }
6183
6184
6185 bool JSReceiver::HasLocalProperty(Handle<JSReceiver> object,
6186                                   Handle<Name> name) {
6187   if (object->IsJSProxy()) {
6188     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6189     return JSProxy::HasPropertyWithHandler(proxy, name);
6190   }
6191   return object->GetLocalPropertyAttribute(*name) != ABSENT;
6192 }
6193
6194
6195 PropertyAttributes JSReceiver::GetPropertyAttribute(Name* key) {
6196   uint32_t index;
6197   if (IsJSObject() && key->AsArrayIndex(&index)) {
6198     return GetElementAttribute(index);
6199   }
6200   return GetPropertyAttributeWithReceiver(this, key);
6201 }
6202
6203
6204 PropertyAttributes JSReceiver::GetElementAttribute(uint32_t index) {
6205   if (IsJSProxy()) {
6206     return JSProxy::cast(this)->GetElementAttributeWithHandler(this, index);
6207   }
6208   return JSObject::cast(this)->GetElementAttributeWithReceiver(
6209       this, index, true);
6210 }
6211
6212
6213 bool JSGlobalObject::IsDetached() {
6214   return JSGlobalProxy::cast(global_receiver())->IsDetachedFrom(this);
6215 }
6216
6217
6218 bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) {
6219   return GetPrototype() != global;
6220 }
6221
6222
6223 Handle<Object> JSReceiver::GetOrCreateIdentityHash(Handle<JSReceiver> object) {
6224   return object->IsJSProxy()
6225       ? JSProxy::GetOrCreateIdentityHash(Handle<JSProxy>::cast(object))
6226       : JSObject::GetOrCreateIdentityHash(Handle<JSObject>::cast(object));
6227 }
6228
6229
6230 Object* JSReceiver::GetIdentityHash() {
6231   return IsJSProxy()
6232       ? JSProxy::cast(this)->GetIdentityHash()
6233       : JSObject::cast(this)->GetIdentityHash();
6234 }
6235
6236
6237 bool JSReceiver::HasElement(Handle<JSReceiver> object, uint32_t index) {
6238   if (object->IsJSProxy()) {
6239     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6240     return JSProxy::HasElementWithHandler(proxy, index);
6241   }
6242   return Handle<JSObject>::cast(object)->GetElementAttributeWithReceiver(
6243       *object, index, true) != ABSENT;
6244 }
6245
6246
6247 bool JSReceiver::HasLocalElement(Handle<JSReceiver> object, uint32_t index) {
6248   if (object->IsJSProxy()) {
6249     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
6250     return JSProxy::HasElementWithHandler(proxy, index);
6251   }
6252   return Handle<JSObject>::cast(object)->GetElementAttributeWithReceiver(
6253       *object, index, false) != ABSENT;
6254 }
6255
6256
6257 PropertyAttributes JSReceiver::GetLocalElementAttribute(uint32_t index) {
6258   if (IsJSProxy()) {
6259     return JSProxy::cast(this)->GetElementAttributeWithHandler(this, index);
6260   }
6261   return JSObject::cast(this)->GetElementAttributeWithReceiver(
6262       this, index, false);
6263 }
6264
6265
6266 bool AccessorInfo::all_can_read() {
6267   return BooleanBit::get(flag(), kAllCanReadBit);
6268 }
6269
6270
6271 void AccessorInfo::set_all_can_read(bool value) {
6272   set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
6273 }
6274
6275
6276 bool AccessorInfo::all_can_write() {
6277   return BooleanBit::get(flag(), kAllCanWriteBit);
6278 }
6279
6280
6281 void AccessorInfo::set_all_can_write(bool value) {
6282   set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
6283 }
6284
6285
6286 bool AccessorInfo::prohibits_overwriting() {
6287   return BooleanBit::get(flag(), kProhibitsOverwritingBit);
6288 }
6289
6290
6291 void AccessorInfo::set_prohibits_overwriting(bool value) {
6292   set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
6293 }
6294
6295
6296 PropertyAttributes AccessorInfo::property_attributes() {
6297   return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
6298 }
6299
6300
6301 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
6302   set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
6303 }
6304
6305
6306 bool AccessorInfo::IsCompatibleReceiver(Object* receiver) {
6307   Object* function_template = expected_receiver_type();
6308   if (!function_template->IsFunctionTemplateInfo()) return true;
6309   return FunctionTemplateInfo::cast(function_template)->IsTemplateFor(receiver);
6310 }
6311
6312
6313 void AccessorPair::set_access_flags(v8::AccessControl access_control) {
6314   int current = access_flags()->value();
6315   current = BooleanBit::set(current,
6316                             kProhibitsOverwritingBit,
6317                             access_control & PROHIBITS_OVERWRITING);
6318   current = BooleanBit::set(current,
6319                             kAllCanReadBit,
6320                             access_control & ALL_CAN_READ);
6321   current = BooleanBit::set(current,
6322                             kAllCanWriteBit,
6323                             access_control & ALL_CAN_WRITE);
6324   set_access_flags(Smi::FromInt(current));
6325 }
6326
6327
6328 bool AccessorPair::all_can_read() {
6329   return BooleanBit::get(access_flags(), kAllCanReadBit);
6330 }
6331
6332
6333 bool AccessorPair::all_can_write() {
6334   return BooleanBit::get(access_flags(), kAllCanWriteBit);
6335 }
6336
6337
6338 bool AccessorPair::prohibits_overwriting() {
6339   return BooleanBit::get(access_flags(), kProhibitsOverwritingBit);
6340 }
6341
6342
6343 template<typename Shape, typename Key>
6344 void Dictionary<Shape, Key>::SetEntry(int entry,
6345                                       Object* key,
6346                                       Object* value) {
6347   SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
6348 }
6349
6350
6351 template<typename Shape, typename Key>
6352 void Dictionary<Shape, Key>::SetEntry(int entry,
6353                                       Object* key,
6354                                       Object* value,
6355                                       PropertyDetails details) {
6356   ASSERT(!key->IsName() ||
6357          details.IsDeleted() ||
6358          details.dictionary_index() > 0);
6359   int index = HashTable<Shape, Key>::EntryToIndex(entry);
6360   DisallowHeapAllocation no_gc;
6361   WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
6362   FixedArray::set(index, key, mode);
6363   FixedArray::set(index+1, value, mode);
6364   FixedArray::set(index+2, details.AsSmi());
6365 }
6366
6367
6368 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
6369   ASSERT(other->IsNumber());
6370   return key == static_cast<uint32_t>(other->Number());
6371 }
6372
6373
6374 uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) {
6375   return ComputeIntegerHash(key, 0);
6376 }
6377
6378
6379 uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
6380                                                       Object* other) {
6381   ASSERT(other->IsNumber());
6382   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0);
6383 }
6384
6385 uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
6386   return ComputeIntegerHash(key, seed);
6387 }
6388
6389 uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key,
6390                                                           uint32_t seed,
6391                                                           Object* other) {
6392   ASSERT(other->IsNumber());
6393   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed);
6394 }
6395
6396 MaybeObject* NumberDictionaryShape::AsObject(Heap* heap, uint32_t key) {
6397   return heap->NumberFromUint32(key);
6398 }
6399
6400
6401 bool NameDictionaryShape::IsMatch(Name* key, Object* other) {
6402   // We know that all entries in a hash table had their hash keys created.
6403   // Use that knowledge to have fast failure.
6404   if (key->Hash() != Name::cast(other)->Hash()) return false;
6405   return key->Equals(Name::cast(other));
6406 }
6407
6408
6409 uint32_t NameDictionaryShape::Hash(Name* key) {
6410   return key->Hash();
6411 }
6412
6413
6414 uint32_t NameDictionaryShape::HashForObject(Name* key, Object* other) {
6415   return Name::cast(other)->Hash();
6416 }
6417
6418
6419 MaybeObject* NameDictionaryShape::AsObject(Heap* heap, Name* key) {
6420   ASSERT(key->IsUniqueName());
6421   return key;
6422 }
6423
6424
6425 template <int entrysize>
6426 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
6427   return key->SameValue(other);
6428 }
6429
6430
6431 template <int entrysize>
6432 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
6433   return Smi::cast(key->GetHash())->value();
6434 }
6435
6436
6437 template <int entrysize>
6438 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
6439                                                         Object* other) {
6440   return Smi::cast(other->GetHash())->value();
6441 }
6442
6443
6444 template <int entrysize>
6445 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Heap* heap,
6446                                                        Object* key) {
6447   return key;
6448 }
6449
6450
6451 template <int entrysize>
6452 bool WeakHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
6453   return key->SameValue(other);
6454 }
6455
6456
6457 template <int entrysize>
6458 uint32_t WeakHashTableShape<entrysize>::Hash(Object* key) {
6459   intptr_t hash = reinterpret_cast<intptr_t>(key);
6460   return (uint32_t)(hash & 0xFFFFFFFF);
6461 }
6462
6463
6464 template <int entrysize>
6465 uint32_t WeakHashTableShape<entrysize>::HashForObject(Object* key,
6466                                                       Object* other) {
6467   intptr_t hash = reinterpret_cast<intptr_t>(other);
6468   return (uint32_t)(hash & 0xFFFFFFFF);
6469 }
6470
6471
6472 template <int entrysize>
6473 MaybeObject* WeakHashTableShape<entrysize>::AsObject(Heap* heap,
6474                                                     Object* key) {
6475   return key;
6476 }
6477
6478
6479 void Map::ClearCodeCache(Heap* heap) {
6480   // No write barrier is needed since empty_fixed_array is not in new space.
6481   // Please note this function is used during marking:
6482   //  - MarkCompactCollector::MarkUnmarkedObject
6483   //  - IncrementalMarking::Step
6484   ASSERT(!heap->InNewSpace(heap->empty_fixed_array()));
6485   WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
6486 }
6487
6488
6489 void JSArray::EnsureSize(int required_size) {
6490   ASSERT(HasFastSmiOrObjectElements());
6491   FixedArray* elts = FixedArray::cast(elements());
6492   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
6493   if (elts->length() < required_size) {
6494     // Doubling in size would be overkill, but leave some slack to avoid
6495     // constantly growing.
6496     Expand(required_size + (required_size >> 3));
6497     // It's a performance benefit to keep a frequently used array in new-space.
6498   } else if (!GetHeap()->new_space()->Contains(elts) &&
6499              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
6500     // Expand will allocate a new backing store in new space even if the size
6501     // we asked for isn't larger than what we had before.
6502     Expand(required_size);
6503   }
6504 }
6505
6506
6507 void JSArray::set_length(Smi* length) {
6508   // Don't need a write barrier for a Smi.
6509   set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
6510 }
6511
6512
6513 bool JSArray::AllowsSetElementsLength() {
6514   bool result = elements()->IsFixedArray() || elements()->IsFixedDoubleArray();
6515   ASSERT(result == !HasExternalArrayElements());
6516   return result;
6517 }
6518
6519
6520 MaybeObject* JSArray::SetContent(FixedArrayBase* storage) {
6521   MaybeObject* maybe_result = EnsureCanContainElements(
6522       storage, storage->length(), ALLOW_COPIED_DOUBLE_ELEMENTS);
6523   if (maybe_result->IsFailure()) return maybe_result;
6524   ASSERT((storage->map() == GetHeap()->fixed_double_array_map() &&
6525           IsFastDoubleElementsKind(GetElementsKind())) ||
6526          ((storage->map() != GetHeap()->fixed_double_array_map()) &&
6527           (IsFastObjectElementsKind(GetElementsKind()) ||
6528            (IsFastSmiElementsKind(GetElementsKind()) &&
6529             FixedArray::cast(storage)->ContainsOnlySmisOrHoles()))));
6530   set_elements(storage);
6531   set_length(Smi::FromInt(storage->length()));
6532   return this;
6533 }
6534
6535
6536 MaybeObject* FixedArray::Copy() {
6537   if (length() == 0) return this;
6538   return GetHeap()->CopyFixedArray(this);
6539 }
6540
6541
6542 MaybeObject* FixedDoubleArray::Copy() {
6543   if (length() == 0) return this;
6544   return GetHeap()->CopyFixedDoubleArray(this);
6545 }
6546
6547
6548 MaybeObject* ConstantPoolArray::Copy() {
6549   if (length() == 0) return this;
6550   return GetHeap()->CopyConstantPoolArray(this);
6551 }
6552
6553
6554 void TypeFeedbackCells::SetAstId(int index, TypeFeedbackId id) {
6555   set(1 + index * 2, Smi::FromInt(id.ToInt()));
6556 }
6557
6558
6559 TypeFeedbackId TypeFeedbackCells::AstId(int index) {
6560   return TypeFeedbackId(Smi::cast(get(1 + index * 2))->value());
6561 }
6562
6563
6564 void TypeFeedbackCells::SetCell(int index, Cell* cell) {
6565   set(index * 2, cell);
6566 }
6567
6568
6569 Cell* TypeFeedbackCells::GetCell(int index) {
6570   return Cell::cast(get(index * 2));
6571 }
6572
6573
6574 Handle<Object> TypeFeedbackCells::UninitializedSentinel(Isolate* isolate) {
6575   return isolate->factory()->the_hole_value();
6576 }
6577
6578
6579 Handle<Object> TypeFeedbackCells::MegamorphicSentinel(Isolate* isolate) {
6580   return isolate->factory()->undefined_value();
6581 }
6582
6583
6584 Handle<Object> TypeFeedbackCells::MonomorphicArraySentinel(Isolate* isolate,
6585     ElementsKind elements_kind) {
6586   return Handle<Object>(Smi::FromInt(static_cast<int>(elements_kind)), isolate);
6587 }
6588
6589
6590 Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
6591   return heap->the_hole_value();
6592 }
6593
6594
6595 int TypeFeedbackInfo::ic_total_count() {
6596   int current = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6597   return ICTotalCountField::decode(current);
6598 }
6599
6600
6601 void TypeFeedbackInfo::set_ic_total_count(int count) {
6602   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6603   value = ICTotalCountField::update(value,
6604                                     ICTotalCountField::decode(count));
6605   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
6606 }
6607
6608
6609 int TypeFeedbackInfo::ic_with_type_info_count() {
6610   int current = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6611   return ICsWithTypeInfoCountField::decode(current);
6612 }
6613
6614
6615 void TypeFeedbackInfo::change_ic_with_type_info_count(int delta) {
6616   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6617   int new_count = ICsWithTypeInfoCountField::decode(value) + delta;
6618   // We can get negative count here when the type-feedback info is
6619   // shared between two code objects. The can only happen when
6620   // the debugger made a shallow copy of code object (see Heap::CopyCode).
6621   // Since we do not optimize when the debugger is active, we can skip
6622   // this counter update.
6623   if (new_count >= 0) {
6624     new_count &= ICsWithTypeInfoCountField::kMask;
6625     value = ICsWithTypeInfoCountField::update(value, new_count);
6626     WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
6627   }
6628 }
6629
6630
6631 void TypeFeedbackInfo::initialize_storage() {
6632   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(0));
6633   WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(0));
6634 }
6635
6636
6637 void TypeFeedbackInfo::change_own_type_change_checksum() {
6638   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6639   int checksum = OwnTypeChangeChecksum::decode(value);
6640   checksum = (checksum + 1) % (1 << kTypeChangeChecksumBits);
6641   value = OwnTypeChangeChecksum::update(value, checksum);
6642   // Ensure packed bit field is in Smi range.
6643   if (value > Smi::kMaxValue) value |= Smi::kMinValue;
6644   if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
6645   WRITE_FIELD(this, kStorage1Offset, Smi::FromInt(value));
6646 }
6647
6648
6649 void TypeFeedbackInfo::set_inlined_type_change_checksum(int checksum) {
6650   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6651   int mask = (1 << kTypeChangeChecksumBits) - 1;
6652   value = InlinedTypeChangeChecksum::update(value, checksum & mask);
6653   // Ensure packed bit field is in Smi range.
6654   if (value > Smi::kMaxValue) value |= Smi::kMinValue;
6655   if (value < Smi::kMinValue) value &= ~Smi::kMinValue;
6656   WRITE_FIELD(this, kStorage2Offset, Smi::FromInt(value));
6657 }
6658
6659
6660 int TypeFeedbackInfo::own_type_change_checksum() {
6661   int value = Smi::cast(READ_FIELD(this, kStorage1Offset))->value();
6662   return OwnTypeChangeChecksum::decode(value);
6663 }
6664
6665
6666 bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
6667   int value = Smi::cast(READ_FIELD(this, kStorage2Offset))->value();
6668   int mask = (1 << kTypeChangeChecksumBits) - 1;
6669   return InlinedTypeChangeChecksum::decode(value) == (checksum & mask);
6670 }
6671
6672
6673 ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
6674           kTypeFeedbackCellsOffset)
6675
6676
6677 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
6678
6679
6680 Relocatable::Relocatable(Isolate* isolate) {
6681   isolate_ = isolate;
6682   prev_ = isolate->relocatable_top();
6683   isolate->set_relocatable_top(this);
6684 }
6685
6686
6687 Relocatable::~Relocatable() {
6688   ASSERT_EQ(isolate_->relocatable_top(), this);
6689   isolate_->set_relocatable_top(prev_);
6690 }
6691
6692
6693 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
6694   return map->instance_size();
6695 }
6696
6697
6698 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
6699   v->VisitExternalReference(
6700       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
6701 }
6702
6703
6704 template<typename StaticVisitor>
6705 void Foreign::ForeignIterateBody() {
6706   StaticVisitor::VisitExternalReference(
6707       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
6708 }
6709
6710
6711 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
6712   typedef v8::String::ExternalAsciiStringResource Resource;
6713   v->VisitExternalAsciiString(
6714       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6715 }
6716
6717
6718 template<typename StaticVisitor>
6719 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
6720   typedef v8::String::ExternalAsciiStringResource Resource;
6721   StaticVisitor::VisitExternalAsciiString(
6722       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6723 }
6724
6725
6726 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
6727   typedef v8::String::ExternalStringResource Resource;
6728   v->VisitExternalTwoByteString(
6729       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6730 }
6731
6732
6733 template<typename StaticVisitor>
6734 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
6735   typedef v8::String::ExternalStringResource Resource;
6736   StaticVisitor::VisitExternalTwoByteString(
6737       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
6738 }
6739
6740
6741 template<int start_offset, int end_offset, int size>
6742 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
6743     HeapObject* obj,
6744     ObjectVisitor* v) {
6745     v->VisitPointers(HeapObject::RawField(obj, start_offset),
6746                      HeapObject::RawField(obj, end_offset));
6747 }
6748
6749
6750 template<int start_offset>
6751 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
6752                                                        int object_size,
6753                                                        ObjectVisitor* v) {
6754   v->VisitPointers(HeapObject::RawField(obj, start_offset),
6755                    HeapObject::RawField(obj, object_size));
6756 }
6757
6758
6759 #undef TYPE_CHECKER
6760 #undef CAST_ACCESSOR
6761 #undef INT_ACCESSORS
6762 #undef ACCESSORS
6763 #undef ACCESSORS_TO_SMI
6764 #undef SMI_ACCESSORS
6765 #undef BOOL_GETTER
6766 #undef BOOL_ACCESSORS
6767 #undef FIELD_ADDR
6768 #undef READ_FIELD
6769 #undef WRITE_FIELD
6770 #undef WRITE_BARRIER
6771 #undef CONDITIONAL_WRITE_BARRIER
6772 #undef READ_DOUBLE_FIELD
6773 #undef WRITE_DOUBLE_FIELD
6774 #undef READ_INT_FIELD
6775 #undef WRITE_INT_FIELD
6776 #undef READ_INTPTR_FIELD
6777 #undef WRITE_INTPTR_FIELD
6778 #undef READ_UINT32_FIELD
6779 #undef WRITE_UINT32_FIELD
6780 #undef READ_SHORT_FIELD
6781 #undef WRITE_SHORT_FIELD
6782 #undef READ_BYTE_FIELD
6783 #undef WRITE_BYTE_FIELD
6784
6785 } }  // namespace v8::internal
6786
6787 #endif  // V8_OBJECTS_INL_H_