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