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