[V8] Generalize external object resources
[profile/ivi/qtjsbackend.git] / src / 3rdparty / v8 / src / objects-inl.h
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // Review notes:
29 //
30 // - The use of macros in these inline functions may seem superfluous
31 // but it is absolutely needed to make sure gcc generates optimal
32 // code. gcc is not happy when attempting to inline too deep.
33 //
34
35 #ifndef V8_OBJECTS_INL_H_
36 #define V8_OBJECTS_INL_H_
37
38 #include "elements.h"
39 #include "objects.h"
40 #include "contexts.h"
41 #include "conversions-inl.h"
42 #include "heap.h"
43 #include "isolate.h"
44 #include "property.h"
45 #include "spaces.h"
46 #include "store-buffer.h"
47 #include "v8memory.h"
48
49 #include "incremental-marking.h"
50
51 namespace v8 {
52 namespace internal {
53
54 PropertyDetails::PropertyDetails(Smi* smi) {
55   value_ = smi->value();
56 }
57
58
59 Smi* PropertyDetails::AsSmi() {
60   return Smi::FromInt(value_);
61 }
62
63
64 PropertyDetails PropertyDetails::AsDeleted() {
65   Smi* smi = Smi::FromInt(value_ | DeletedField::encode(1));
66   return PropertyDetails(smi);
67 }
68
69
70 #define TYPE_CHECKER(type, instancetype)                                \
71   bool Object::Is##type() {                                             \
72   return Object::IsHeapObject() &&                                      \
73       HeapObject::cast(this)->map()->instance_type() == instancetype;   \
74   }
75
76
77 #define CAST_ACCESSOR(type)                     \
78   type* type::cast(Object* object) {            \
79     ASSERT(object->Is##type());                 \
80     return reinterpret_cast<type*>(object);     \
81   }
82
83
84 #define INT_ACCESSORS(holder, name, offset)                             \
85   int holder::name() { return READ_INT_FIELD(this, offset); }           \
86   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
87
88
89 #define ACCESSORS(holder, name, type, offset)                           \
90   type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
91   void holder::set_##name(type* value, WriteBarrierMode mode) {         \
92     WRITE_FIELD(this, offset, value);                                   \
93     CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);    \
94   }
95
96
97 #define SMI_ACCESSORS(holder, name, offset)             \
98   int holder::name() {                                  \
99     Object* value = READ_FIELD(this, offset);           \
100     return Smi::cast(value)->value();                   \
101   }                                                     \
102   void holder::set_##name(int value) {                  \
103     WRITE_FIELD(this, offset, Smi::FromInt(value));     \
104   }
105
106
107 #define BOOL_GETTER(holder, field, name, offset)           \
108   bool holder::name() {                                    \
109     return BooleanBit::get(field(), offset);               \
110   }                                                        \
111
112
113 #define BOOL_ACCESSORS(holder, field, name, offset)        \
114   bool holder::name() {                                    \
115     return BooleanBit::get(field(), offset);               \
116   }                                                        \
117   void holder::set_##name(bool value) {                    \
118     set_##field(BooleanBit::set(field(), offset, value));  \
119   }
120
121
122 bool Object::IsFixedArrayBase() {
123   return IsFixedArray() || IsFixedDoubleArray();
124 }
125
126
127 bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
128   // There is a constraint on the object; check.
129   if (!this->IsJSObject()) return false;
130   // Fetch the constructor function of the object.
131   Object* cons_obj = JSObject::cast(this)->map()->constructor();
132   if (!cons_obj->IsJSFunction()) return false;
133   JSFunction* fun = JSFunction::cast(cons_obj);
134   // Iterate through the chain of inheriting function templates to
135   // see if the required one occurs.
136   for (Object* type = fun->shared()->function_data();
137        type->IsFunctionTemplateInfo();
138        type = FunctionTemplateInfo::cast(type)->parent_template()) {
139     if (type == expected) return true;
140   }
141   // Didn't find the required type in the inheritance chain.
142   return false;
143 }
144
145
146 bool Object::IsSmi() {
147   return HAS_SMI_TAG(this);
148 }
149
150
151 bool Object::IsHeapObject() {
152   return Internals::HasHeapObjectTag(this);
153 }
154
155
156 bool Object::NonFailureIsHeapObject() {
157   ASSERT(!this->IsFailure());
158   return (reinterpret_cast<intptr_t>(this) & kSmiTagMask) != 0;
159 }
160
161
162 TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
163
164
165 bool Object::IsString() {
166   return Object::IsHeapObject()
167     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
168 }
169
170
171 bool Object::IsSpecObject() {
172   return Object::IsHeapObject()
173     && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
174 }
175
176
177 bool Object::IsSpecFunction() {
178   if (!Object::IsHeapObject()) return false;
179   InstanceType type = HeapObject::cast(this)->map()->instance_type();
180   return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
181 }
182
183
184 bool Object::IsSymbol() {
185   if (!this->IsHeapObject()) return false;
186   uint32_t type = HeapObject::cast(this)->map()->instance_type();
187   // Because the symbol tag is non-zero and no non-string types have the
188   // symbol bit set we can test for symbols with a very simple test
189   // operation.
190   STATIC_ASSERT(kSymbolTag != 0);
191   ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
192   return (type & kIsSymbolMask) != 0;
193 }
194
195
196 bool Object::IsConsString() {
197   if (!IsString()) return false;
198   return StringShape(String::cast(this)).IsCons();
199 }
200
201
202 bool Object::IsSlicedString() {
203   if (!IsString()) return false;
204   return StringShape(String::cast(this)).IsSliced();
205 }
206
207
208 bool Object::IsSeqString() {
209   if (!IsString()) return false;
210   return StringShape(String::cast(this)).IsSequential();
211 }
212
213
214 bool Object::IsSeqAsciiString() {
215   if (!IsString()) return false;
216   return StringShape(String::cast(this)).IsSequential() &&
217          String::cast(this)->IsAsciiRepresentation();
218 }
219
220
221 bool Object::IsSeqTwoByteString() {
222   if (!IsString()) return false;
223   return StringShape(String::cast(this)).IsSequential() &&
224          String::cast(this)->IsTwoByteRepresentation();
225 }
226
227
228 bool Object::IsExternalString() {
229   if (!IsString()) return false;
230   return StringShape(String::cast(this)).IsExternal();
231 }
232
233
234 bool Object::IsExternalAsciiString() {
235   if (!IsString()) return false;
236   return StringShape(String::cast(this)).IsExternal() &&
237          String::cast(this)->IsAsciiRepresentation();
238 }
239
240
241 bool Object::IsExternalTwoByteString() {
242   if (!IsString()) return false;
243   return StringShape(String::cast(this)).IsExternal() &&
244          String::cast(this)->IsTwoByteRepresentation();
245 }
246
247 bool Object::HasValidElements() {
248   // Dictionary is covered under FixedArray.
249   return IsFixedArray() || IsFixedDoubleArray() || IsExternalArray();
250 }
251
252 StringShape::StringShape(String* str)
253   : type_(str->map()->instance_type()) {
254   set_valid();
255   ASSERT((type_ & kIsNotStringMask) == kStringTag);
256 }
257
258
259 StringShape::StringShape(Map* map)
260   : type_(map->instance_type()) {
261   set_valid();
262   ASSERT((type_ & kIsNotStringMask) == kStringTag);
263 }
264
265
266 StringShape::StringShape(InstanceType t)
267   : type_(static_cast<uint32_t>(t)) {
268   set_valid();
269   ASSERT((type_ & kIsNotStringMask) == kStringTag);
270 }
271
272
273 bool StringShape::IsSymbol() {
274   ASSERT(valid());
275   STATIC_ASSERT(kSymbolTag != 0);
276   return (type_ & kIsSymbolMask) != 0;
277 }
278
279
280 bool String::IsAsciiRepresentation() {
281   uint32_t type = map()->instance_type();
282   return (type & kStringEncodingMask) == kAsciiStringTag;
283 }
284
285
286 bool String::IsTwoByteRepresentation() {
287   uint32_t type = map()->instance_type();
288   return (type & kStringEncodingMask) == kTwoByteStringTag;
289 }
290
291
292 bool String::IsAsciiRepresentationUnderneath() {
293   uint32_t type = map()->instance_type();
294   STATIC_ASSERT(kIsIndirectStringTag != 0);
295   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
296   ASSERT(IsFlat());
297   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
298     case kAsciiStringTag:
299       return true;
300     case kTwoByteStringTag:
301       return false;
302     default:  // Cons or sliced string.  Need to go deeper.
303       return GetUnderlying()->IsAsciiRepresentation();
304   }
305 }
306
307
308 bool String::IsTwoByteRepresentationUnderneath() {
309   uint32_t type = map()->instance_type();
310   STATIC_ASSERT(kIsIndirectStringTag != 0);
311   STATIC_ASSERT((kIsIndirectStringMask & kStringEncodingMask) == 0);
312   ASSERT(IsFlat());
313   switch (type & (kIsIndirectStringMask | kStringEncodingMask)) {
314     case kAsciiStringTag:
315       return false;
316     case kTwoByteStringTag:
317       return true;
318     default:  // Cons or sliced string.  Need to go deeper.
319       return GetUnderlying()->IsTwoByteRepresentation();
320   }
321 }
322
323
324 bool String::HasOnlyAsciiChars() {
325   uint32_t type = map()->instance_type();
326   return (type & kStringEncodingMask) == kAsciiStringTag ||
327          (type & kAsciiDataHintMask) == kAsciiDataHintTag;
328 }
329
330
331 bool StringShape::IsCons() {
332   return (type_ & kStringRepresentationMask) == kConsStringTag;
333 }
334
335
336 bool StringShape::IsSliced() {
337   return (type_ & kStringRepresentationMask) == kSlicedStringTag;
338 }
339
340
341 bool StringShape::IsIndirect() {
342   return (type_ & kIsIndirectStringMask) == kIsIndirectStringTag;
343 }
344
345
346 bool StringShape::IsExternal() {
347   return (type_ & kStringRepresentationMask) == kExternalStringTag;
348 }
349
350
351 bool StringShape::IsSequential() {
352   return (type_ & kStringRepresentationMask) == kSeqStringTag;
353 }
354
355
356 StringRepresentationTag StringShape::representation_tag() {
357   uint32_t tag = (type_ & kStringRepresentationMask);
358   return static_cast<StringRepresentationTag>(tag);
359 }
360
361
362 uint32_t StringShape::encoding_tag() {
363   return type_ & kStringEncodingMask;
364 }
365
366
367 uint32_t StringShape::full_representation_tag() {
368   return (type_ & (kStringRepresentationMask | kStringEncodingMask));
369 }
370
371
372 STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
373              Internals::kFullStringRepresentationMask);
374
375
376 bool StringShape::IsSequentialAscii() {
377   return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
378 }
379
380
381 bool StringShape::IsSequentialTwoByte() {
382   return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
383 }
384
385
386 bool StringShape::IsExternalAscii() {
387   return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
388 }
389
390
391 bool StringShape::IsExternalTwoByte() {
392   return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
393 }
394
395
396 STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
397              Internals::kExternalTwoByteRepresentationTag);
398
399
400 uc32 FlatStringReader::Get(int index) {
401   ASSERT(0 <= index && index <= length_);
402   if (is_ascii_) {
403     return static_cast<const byte*>(start_)[index];
404   } else {
405     return static_cast<const uc16*>(start_)[index];
406   }
407 }
408
409
410 bool Object::IsNumber() {
411   return IsSmi() || IsHeapNumber();
412 }
413
414
415 TYPE_CHECKER(ByteArray, BYTE_ARRAY_TYPE)
416 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
417
418
419 bool Object::IsFiller() {
420   if (!Object::IsHeapObject()) return false;
421   InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
422   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
423 }
424
425
426 TYPE_CHECKER(ExternalPixelArray, EXTERNAL_PIXEL_ARRAY_TYPE)
427
428
429 bool Object::IsExternalArray() {
430   if (!Object::IsHeapObject())
431     return false;
432   InstanceType instance_type =
433       HeapObject::cast(this)->map()->instance_type();
434   return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
435           instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
436 }
437
438
439 TYPE_CHECKER(ExternalByteArray, EXTERNAL_BYTE_ARRAY_TYPE)
440 TYPE_CHECKER(ExternalUnsignedByteArray, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
441 TYPE_CHECKER(ExternalShortArray, EXTERNAL_SHORT_ARRAY_TYPE)
442 TYPE_CHECKER(ExternalUnsignedShortArray, EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
443 TYPE_CHECKER(ExternalIntArray, EXTERNAL_INT_ARRAY_TYPE)
444 TYPE_CHECKER(ExternalUnsignedIntArray, EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
445 TYPE_CHECKER(ExternalFloatArray, EXTERNAL_FLOAT_ARRAY_TYPE)
446 TYPE_CHECKER(ExternalDoubleArray, EXTERNAL_DOUBLE_ARRAY_TYPE)
447
448
449 bool MaybeObject::IsFailure() {
450   return HAS_FAILURE_TAG(this);
451 }
452
453
454 bool MaybeObject::IsRetryAfterGC() {
455   return HAS_FAILURE_TAG(this)
456     && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
457 }
458
459
460 bool MaybeObject::IsOutOfMemory() {
461   return HAS_FAILURE_TAG(this)
462       && Failure::cast(this)->IsOutOfMemoryException();
463 }
464
465
466 bool MaybeObject::IsException() {
467   return this == Failure::Exception();
468 }
469
470
471 bool MaybeObject::IsTheHole() {
472   return !IsFailure() && ToObjectUnchecked()->IsTheHole();
473 }
474
475
476 Failure* Failure::cast(MaybeObject* obj) {
477   ASSERT(HAS_FAILURE_TAG(obj));
478   return reinterpret_cast<Failure*>(obj);
479 }
480
481
482 bool Object::IsJSReceiver() {
483   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
484   return IsHeapObject() &&
485       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
486 }
487
488
489 bool Object::IsJSObject() {
490   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
491   return IsHeapObject() &&
492       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
493 }
494
495
496 bool Object::IsJSProxy() {
497   if (!Object::IsHeapObject()) return false;
498   InstanceType type = HeapObject::cast(this)->map()->instance_type();
499   return FIRST_JS_PROXY_TYPE <= type && type <= LAST_JS_PROXY_TYPE;
500 }
501
502
503 TYPE_CHECKER(JSFunctionProxy, JS_FUNCTION_PROXY_TYPE)
504 TYPE_CHECKER(JSSet, JS_SET_TYPE)
505 TYPE_CHECKER(JSMap, JS_MAP_TYPE)
506 TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
507 TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
508 TYPE_CHECKER(Map, MAP_TYPE)
509 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
510 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
511
512
513 bool Object::IsDescriptorArray() {
514   return IsFixedArray();
515 }
516
517
518 bool Object::IsDeoptimizationInputData() {
519   // Must be a fixed array.
520   if (!IsFixedArray()) return false;
521
522   // There's no sure way to detect the difference between a fixed array and
523   // a deoptimization data array.  Since this is used for asserts we can
524   // check that the length is zero or else the fixed size plus a multiple of
525   // the entry size.
526   int length = FixedArray::cast(this)->length();
527   if (length == 0) return true;
528
529   length -= DeoptimizationInputData::kFirstDeoptEntryIndex;
530   return length >= 0 &&
531       length % DeoptimizationInputData::kDeoptEntrySize == 0;
532 }
533
534
535 bool Object::IsDeoptimizationOutputData() {
536   if (!IsFixedArray()) return false;
537   // There's actually no way to see the difference between a fixed array and
538   // a deoptimization data array.  Since this is used for asserts we can check
539   // that the length is plausible though.
540   if (FixedArray::cast(this)->length() % 2 != 0) return false;
541   return true;
542 }
543
544
545 bool Object::IsContext() {
546   if (Object::IsHeapObject()) {
547     Map* map = HeapObject::cast(this)->map();
548     Heap* heap = map->GetHeap();
549     return (map == heap->function_context_map() ||
550             map == heap->catch_context_map() ||
551             map == heap->with_context_map() ||
552             map == heap->global_context_map() ||
553             map == heap->block_context_map());
554   }
555   return false;
556 }
557
558
559 bool Object::IsGlobalContext() {
560   return Object::IsHeapObject() &&
561       HeapObject::cast(this)->map() ==
562       HeapObject::cast(this)->GetHeap()->global_context_map();
563 }
564
565
566 bool Object::IsSerializedScopeInfo() {
567   return Object::IsHeapObject() &&
568       HeapObject::cast(this)->map() ==
569       HeapObject::cast(this)->GetHeap()->serialized_scope_info_map();
570 }
571
572
573 TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
574
575
576 template <> inline bool Is<JSFunction>(Object* obj) {
577   return obj->IsJSFunction();
578 }
579
580
581 TYPE_CHECKER(Code, CODE_TYPE)
582 TYPE_CHECKER(Oddball, ODDBALL_TYPE)
583 TYPE_CHECKER(JSGlobalPropertyCell, JS_GLOBAL_PROPERTY_CELL_TYPE)
584 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
585 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
586 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
587
588
589 bool Object::IsStringWrapper() {
590   return IsJSValue() && JSValue::cast(this)->value()->IsString();
591 }
592
593
594 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
595
596
597 bool Object::IsBoolean() {
598   return IsOddball() &&
599       ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
600 }
601
602
603 TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
604 TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
605
606
607 template <> inline bool Is<JSArray>(Object* obj) {
608   return obj->IsJSArray();
609 }
610
611
612 bool Object::IsHashTable() {
613   return Object::IsHeapObject() &&
614       HeapObject::cast(this)->map() ==
615       HeapObject::cast(this)->GetHeap()->hash_table_map();
616 }
617
618
619 bool Object::IsDictionary() {
620   return IsHashTable() &&
621       this != HeapObject::cast(this)->GetHeap()->symbol_table();
622 }
623
624
625 bool Object::IsSymbolTable() {
626   return IsHashTable() && this ==
627          HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
628 }
629
630
631 bool Object::IsJSFunctionResultCache() {
632   if (!IsFixedArray()) return false;
633   FixedArray* self = FixedArray::cast(this);
634   int length = self->length();
635   if (length < JSFunctionResultCache::kEntriesIndex) return false;
636   if ((length - JSFunctionResultCache::kEntriesIndex)
637       % JSFunctionResultCache::kEntrySize != 0) {
638     return false;
639   }
640 #ifdef DEBUG
641   if (FLAG_verify_heap) {
642     reinterpret_cast<JSFunctionResultCache*>(this)->
643         JSFunctionResultCacheVerify();
644   }
645 #endif
646   return true;
647 }
648
649
650 bool Object::IsNormalizedMapCache() {
651   if (!IsFixedArray()) return false;
652   if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
653     return false;
654   }
655 #ifdef DEBUG
656   if (FLAG_verify_heap) {
657     reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
658   }
659 #endif
660   return true;
661 }
662
663
664 bool Object::IsCompilationCacheTable() {
665   return IsHashTable();
666 }
667
668
669 bool Object::IsCodeCacheHashTable() {
670   return IsHashTable();
671 }
672
673
674 bool Object::IsPolymorphicCodeCacheHashTable() {
675   return IsHashTable();
676 }
677
678
679 bool Object::IsMapCache() {
680   return IsHashTable();
681 }
682
683
684 bool Object::IsPrimitive() {
685   return IsOddball() || IsNumber() || IsString();
686 }
687
688
689 bool Object::IsJSGlobalProxy() {
690   bool result = IsHeapObject() &&
691                 (HeapObject::cast(this)->map()->instance_type() ==
692                  JS_GLOBAL_PROXY_TYPE);
693   ASSERT(!result || IsAccessCheckNeeded());
694   return result;
695 }
696
697
698 bool Object::IsGlobalObject() {
699   if (!IsHeapObject()) return false;
700
701   InstanceType type = HeapObject::cast(this)->map()->instance_type();
702   return type == JS_GLOBAL_OBJECT_TYPE ||
703          type == JS_BUILTINS_OBJECT_TYPE;
704 }
705
706
707 TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
708 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
709
710
711 bool Object::IsUndetectableObject() {
712   return IsHeapObject()
713     && HeapObject::cast(this)->map()->is_undetectable();
714 }
715
716
717 bool Object::IsAccessCheckNeeded() {
718   return IsHeapObject()
719     && HeapObject::cast(this)->map()->is_access_check_needed();
720 }
721
722
723 bool Object::IsStruct() {
724   if (!IsHeapObject()) return false;
725   switch (HeapObject::cast(this)->map()->instance_type()) {
726 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
727   STRUCT_LIST(MAKE_STRUCT_CASE)
728 #undef MAKE_STRUCT_CASE
729     default: return false;
730   }
731 }
732
733
734 #define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
735   bool Object::Is##Name() {                                      \
736     return Object::IsHeapObject()                                \
737       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
738   }
739   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
740 #undef MAKE_STRUCT_PREDICATE
741
742
743 bool Object::IsUndefined() {
744   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
745 }
746
747
748 bool Object::IsNull() {
749   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
750 }
751
752
753 bool Object::IsTheHole() {
754   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
755 }
756
757
758 bool Object::IsTrue() {
759   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
760 }
761
762
763 bool Object::IsFalse() {
764   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
765 }
766
767
768 bool Object::IsArgumentsMarker() {
769   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
770 }
771
772
773 double Object::Number() {
774   ASSERT(IsNumber());
775   return IsSmi()
776     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
777     : reinterpret_cast<HeapNumber*>(this)->value();
778 }
779
780
781 MaybeObject* Object::ToSmi() {
782   if (IsSmi()) return this;
783   if (IsHeapNumber()) {
784     double value = HeapNumber::cast(this)->value();
785     int int_value = FastD2I(value);
786     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
787       return Smi::FromInt(int_value);
788     }
789   }
790   return Failure::Exception();
791 }
792
793
794 bool Object::HasSpecificClassOf(String* name) {
795   return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
796 }
797
798
799 MaybeObject* Object::GetElement(uint32_t index) {
800   // GetElement can trigger a getter which can cause allocation.
801   // This was not always the case. This ASSERT is here to catch
802   // leftover incorrect uses.
803   ASSERT(HEAP->IsAllocationAllowed());
804   return GetElementWithReceiver(this, index);
805 }
806
807
808 Object* Object::GetElementNoExceptionThrown(uint32_t index) {
809   MaybeObject* maybe = GetElementWithReceiver(this, index);
810   ASSERT(!maybe->IsFailure());
811   Object* result = NULL;  // Initialization to please compiler.
812   maybe->ToObject(&result);
813   return result;
814 }
815
816
817 MaybeObject* Object::GetProperty(String* key) {
818   PropertyAttributes attributes;
819   return GetPropertyWithReceiver(this, key, &attributes);
820 }
821
822
823 MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
824   return GetPropertyWithReceiver(this, key, attributes);
825 }
826
827
828 #define FIELD_ADDR(p, offset) \
829   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
830
831 #define READ_FIELD(p, offset) \
832   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
833
834 #define WRITE_FIELD(p, offset, value) \
835   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
836
837 #define WRITE_BARRIER(heap, object, offset, value)                      \
838   heap->incremental_marking()->RecordWrite(                             \
839       object, HeapObject::RawField(object, offset), value);             \
840   if (heap->InNewSpace(value)) {                                        \
841     heap->RecordWrite(object->address(), offset);                       \
842   }
843
844 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
845   if (mode == UPDATE_WRITE_BARRIER) {                                   \
846     heap->incremental_marking()->RecordWrite(                           \
847       object, HeapObject::RawField(object, offset), value);             \
848     if (heap->InNewSpace(value)) {                                      \
849       heap->RecordWrite(object->address(), offset);                     \
850     }                                                                   \
851   }
852
853 #ifndef V8_TARGET_ARCH_MIPS
854   #define READ_DOUBLE_FIELD(p, offset) \
855     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
856 #else  // V8_TARGET_ARCH_MIPS
857   // Prevent gcc from using load-double (mips ldc1) on (possibly)
858   // non-64-bit aligned HeapNumber::value.
859   static inline double read_double_field(void* p, int offset) {
860     union conversion {
861       double d;
862       uint32_t u[2];
863     } c;
864     c.u[0] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)));
865     c.u[1] = (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4)));
866     return c.d;
867   }
868   #define READ_DOUBLE_FIELD(p, offset) read_double_field(p, offset)
869 #endif  // V8_TARGET_ARCH_MIPS
870
871 #ifndef V8_TARGET_ARCH_MIPS
872   #define WRITE_DOUBLE_FIELD(p, offset, value) \
873     (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
874 #else  // V8_TARGET_ARCH_MIPS
875   // Prevent gcc from using store-double (mips sdc1) on (possibly)
876   // non-64-bit aligned HeapNumber::value.
877   static inline void write_double_field(void* p, int offset,
878                                         double value) {
879     union conversion {
880       double d;
881       uint32_t u[2];
882     } c;
883     c.d = value;
884     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset))) = c.u[0];
885     (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset + 4))) = c.u[1];
886   }
887   #define WRITE_DOUBLE_FIELD(p, offset, value) \
888     write_double_field(p, offset, value)
889 #endif  // V8_TARGET_ARCH_MIPS
890
891
892 #define READ_INT_FIELD(p, offset) \
893   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
894
895 #define WRITE_INT_FIELD(p, offset, value) \
896   (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
897
898 #define READ_INTPTR_FIELD(p, offset) \
899   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
900
901 #define WRITE_INTPTR_FIELD(p, offset, value) \
902   (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
903
904 #define READ_UINT32_FIELD(p, offset) \
905   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
906
907 #define WRITE_UINT32_FIELD(p, offset, value) \
908   (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
909
910 #define READ_SHORT_FIELD(p, offset) \
911   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
912
913 #define WRITE_SHORT_FIELD(p, offset, value) \
914   (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
915
916 #define READ_BYTE_FIELD(p, offset) \
917   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
918
919 #define WRITE_BYTE_FIELD(p, offset, value) \
920   (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
921
922
923 Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
924   return &READ_FIELD(obj, byte_offset);
925 }
926
927
928 int Smi::value() {
929   return Internals::SmiValue(this);
930 }
931
932
933 Smi* Smi::FromInt(int value) {
934   ASSERT(Smi::IsValid(value));
935   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
936   intptr_t tagged_value =
937       (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
938   return reinterpret_cast<Smi*>(tagged_value);
939 }
940
941
942 Smi* Smi::FromIntptr(intptr_t value) {
943   ASSERT(Smi::IsValid(value));
944   int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
945   return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
946 }
947
948
949 Failure::Type Failure::type() const {
950   return static_cast<Type>(value() & kFailureTypeTagMask);
951 }
952
953
954 bool Failure::IsInternalError() const {
955   return type() == INTERNAL_ERROR;
956 }
957
958
959 bool Failure::IsOutOfMemoryException() const {
960   return type() == OUT_OF_MEMORY_EXCEPTION;
961 }
962
963
964 AllocationSpace Failure::allocation_space() const {
965   ASSERT_EQ(RETRY_AFTER_GC, type());
966   return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
967                                       & kSpaceTagMask);
968 }
969
970
971 Failure* Failure::InternalError() {
972   return Construct(INTERNAL_ERROR);
973 }
974
975
976 Failure* Failure::Exception() {
977   return Construct(EXCEPTION);
978 }
979
980
981 Failure* Failure::OutOfMemoryException() {
982   return Construct(OUT_OF_MEMORY_EXCEPTION);
983 }
984
985
986 intptr_t Failure::value() const {
987   return static_cast<intptr_t>(
988       reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
989 }
990
991
992 Failure* Failure::RetryAfterGC() {
993   return RetryAfterGC(NEW_SPACE);
994 }
995
996
997 Failure* Failure::RetryAfterGC(AllocationSpace space) {
998   ASSERT((space & ~kSpaceTagMask) == 0);
999   return Construct(RETRY_AFTER_GC, space);
1000 }
1001
1002
1003 Failure* Failure::Construct(Type type, intptr_t value) {
1004   uintptr_t info =
1005       (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
1006   ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
1007   return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
1008 }
1009
1010
1011 bool Smi::IsValid(intptr_t value) {
1012 #ifdef DEBUG
1013   bool in_range = (value >= kMinValue) && (value <= kMaxValue);
1014 #endif
1015
1016 #ifdef V8_TARGET_ARCH_X64
1017   // To be representable as a long smi, the value must be a 32-bit integer.
1018   bool result = (value == static_cast<int32_t>(value));
1019 #else
1020   // To be representable as an tagged small integer, the two
1021   // most-significant bits of 'value' must be either 00 or 11 due to
1022   // sign-extension. To check this we add 01 to the two
1023   // most-significant bits, and check if the most-significant bit is 0
1024   //
1025   // CAUTION: The original code below:
1026   // bool result = ((value + 0x40000000) & 0x80000000) == 0;
1027   // may lead to incorrect results according to the C language spec, and
1028   // in fact doesn't work correctly with gcc4.1.1 in some cases: The
1029   // compiler may produce undefined results in case of signed integer
1030   // overflow. The computation must be done w/ unsigned ints.
1031   bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
1032 #endif
1033   ASSERT(result == in_range);
1034   return result;
1035 }
1036
1037
1038 MapWord MapWord::FromMap(Map* map) {
1039   return MapWord(reinterpret_cast<uintptr_t>(map));
1040 }
1041
1042
1043 Map* MapWord::ToMap() {
1044   return reinterpret_cast<Map*>(value_);
1045 }
1046
1047
1048 bool MapWord::IsForwardingAddress() {
1049   return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
1050 }
1051
1052
1053 MapWord MapWord::FromForwardingAddress(HeapObject* object) {
1054   Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
1055   return MapWord(reinterpret_cast<uintptr_t>(raw));
1056 }
1057
1058
1059 HeapObject* MapWord::ToForwardingAddress() {
1060   ASSERT(IsForwardingAddress());
1061   return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
1062 }
1063
1064
1065 #ifdef DEBUG
1066 void HeapObject::VerifyObjectField(int offset) {
1067   VerifyPointer(READ_FIELD(this, offset));
1068 }
1069
1070 void HeapObject::VerifySmiField(int offset) {
1071   ASSERT(READ_FIELD(this, offset)->IsSmi());
1072 }
1073 #endif
1074
1075
1076 Heap* HeapObject::GetHeap() {
1077   Heap* heap =
1078       MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();
1079   ASSERT(heap != NULL);
1080   ASSERT(heap->isolate() == Isolate::Current());
1081   return heap;
1082 }
1083
1084
1085 Isolate* HeapObject::GetIsolate() {
1086   return GetHeap()->isolate();
1087 }
1088
1089
1090 Map* HeapObject::map() {
1091   return map_word().ToMap();
1092 }
1093
1094
1095 void HeapObject::set_map(Map* value) {
1096   set_map_word(MapWord::FromMap(value));
1097   if (value != NULL) {
1098     // TODO(1600) We are passing NULL as a slot because maps can never be on
1099     // evacuation candidate.
1100     value->GetHeap()->incremental_marking()->RecordWrite(this, NULL, value);
1101   }
1102 }
1103
1104
1105 // Unsafe accessor omitting write barrier.
1106 void HeapObject::set_map_unsafe(Map* value) {
1107   set_map_word(MapWord::FromMap(value));
1108 }
1109
1110
1111 MapWord HeapObject::map_word() {
1112   return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1113 }
1114
1115
1116 void HeapObject::set_map_word(MapWord map_word) {
1117   // WRITE_FIELD does not invoke write barrier, but there is no need
1118   // here.
1119   WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1120 }
1121
1122
1123 HeapObject* HeapObject::FromAddress(Address address) {
1124   ASSERT_TAG_ALIGNED(address);
1125   return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1126 }
1127
1128
1129 Address HeapObject::address() {
1130   return reinterpret_cast<Address>(this) - kHeapObjectTag;
1131 }
1132
1133
1134 int HeapObject::Size() {
1135   return SizeFromMap(map());
1136 }
1137
1138
1139 void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1140   v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1141                    reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1142 }
1143
1144
1145 void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1146   v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1147 }
1148
1149
1150 double HeapNumber::value() {
1151   return READ_DOUBLE_FIELD(this, kValueOffset);
1152 }
1153
1154
1155 void HeapNumber::set_value(double value) {
1156   WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1157 }
1158
1159
1160 int HeapNumber::get_exponent() {
1161   return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1162           kExponentShift) - kExponentBias;
1163 }
1164
1165
1166 int HeapNumber::get_sign() {
1167   return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1168 }
1169
1170
1171 ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1172
1173
1174 FixedArrayBase* JSObject::elements() {
1175   Object* array = READ_FIELD(this, kElementsOffset);
1176   return static_cast<FixedArrayBase*>(array);
1177 }
1178
1179 void JSObject::ValidateSmiOnlyElements() {
1180 #if DEBUG
1181   if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1182     Heap* heap = GetHeap();
1183     // Don't use elements, since integrity checks will fail if there
1184     // are filler pointers in the array.
1185     FixedArray* fixed_array =
1186         reinterpret_cast<FixedArray*>(READ_FIELD(this, kElementsOffset));
1187     Map* map = fixed_array->map();
1188     // Arrays that have been shifted in place can't be verified.
1189     if (map != heap->raw_unchecked_one_pointer_filler_map() &&
1190         map != heap->raw_unchecked_two_pointer_filler_map() &&
1191         map != heap->free_space_map()) {
1192       for (int i = 0; i < fixed_array->length(); i++) {
1193         Object* current = fixed_array->get(i);
1194         ASSERT(current->IsSmi() || current == heap->the_hole_value());
1195       }
1196     }
1197   }
1198 #endif
1199 }
1200
1201
1202 MaybeObject* JSObject::EnsureCanContainNonSmiElements() {
1203 #if DEBUG
1204   ValidateSmiOnlyElements();
1205 #endif
1206   if ((map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS)) {
1207     Object* obj;
1208     MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
1209     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1210     set_map(Map::cast(obj));
1211   }
1212   return this;
1213 }
1214
1215
1216 MaybeObject* JSObject::EnsureCanContainElements(Object** objects,
1217                                                 uint32_t count) {
1218   if (map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS) {
1219     for (uint32_t i = 0; i < count; ++i) {
1220       Object* current = *objects++;
1221       if (!current->IsSmi() && current != GetHeap()->the_hole_value()) {
1222         return EnsureCanContainNonSmiElements();
1223       }
1224     }
1225   }
1226   return this;
1227 }
1228
1229
1230 MaybeObject* JSObject::EnsureCanContainElements(FixedArray* elements) {
1231   Object** objects = reinterpret_cast<Object**>(
1232       FIELD_ADDR(elements, elements->OffsetOfElementAt(0)));
1233   return EnsureCanContainElements(objects, elements->length());
1234 }
1235
1236
1237 void JSObject::set_elements(FixedArrayBase* value, WriteBarrierMode mode) {
1238   ASSERT((map()->has_fast_elements() ||
1239           map()->has_fast_smi_only_elements()) ==
1240          (value->map() == GetHeap()->fixed_array_map() ||
1241           value->map() == GetHeap()->fixed_cow_array_map()));
1242   ASSERT(map()->has_fast_double_elements() ==
1243          value->IsFixedDoubleArray());
1244   ASSERT(value->HasValidElements());
1245 #ifdef DEBUG
1246   ValidateSmiOnlyElements();
1247 #endif
1248   WRITE_FIELD(this, kElementsOffset, value);
1249   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kElementsOffset, value, mode);
1250 }
1251
1252
1253 void JSObject::initialize_properties() {
1254   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1255   WRITE_FIELD(this, kPropertiesOffset, GetHeap()->empty_fixed_array());
1256 }
1257
1258
1259 void JSObject::initialize_elements() {
1260   ASSERT(map()->has_fast_elements() || map()->has_fast_smi_only_elements());
1261   ASSERT(!GetHeap()->InNewSpace(GetHeap()->empty_fixed_array()));
1262   WRITE_FIELD(this, kElementsOffset, GetHeap()->empty_fixed_array());
1263 }
1264
1265
1266 MaybeObject* JSObject::ResetElements() {
1267   Object* obj;
1268   ElementsKind elements_kind = FLAG_smi_only_arrays
1269       ? FAST_SMI_ONLY_ELEMENTS
1270       : FAST_ELEMENTS;
1271   MaybeObject* maybe_obj = GetElementsTransitionMap(elements_kind);
1272   if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1273   set_map(Map::cast(obj));
1274   initialize_elements();
1275   return this;
1276 }
1277
1278
1279 ACCESSORS(Oddball, to_string, String, kToStringOffset)
1280 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1281
1282
1283 byte Oddball::kind() {
1284   return Smi::cast(READ_FIELD(this, kKindOffset))->value();
1285 }
1286
1287
1288 void Oddball::set_kind(byte value) {
1289   WRITE_FIELD(this, kKindOffset, Smi::FromInt(value));
1290 }
1291
1292
1293 Object* JSGlobalPropertyCell::value() {
1294   return READ_FIELD(this, kValueOffset);
1295 }
1296
1297
1298 void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1299   // The write barrier is not used for global property cells.
1300   ASSERT(!val->IsJSGlobalPropertyCell());
1301   WRITE_FIELD(this, kValueOffset, val);
1302   GetHeap()->incremental_marking()->RecordWrite(
1303       this, HeapObject::RawField(this, kValueOffset), val);
1304 }
1305
1306
1307 int JSObject::GetHeaderSize() {
1308   InstanceType type = map()->instance_type();
1309   // Check for the most common kind of JavaScript object before
1310   // falling into the generic switch. This speeds up the internal
1311   // field operations considerably on average.
1312   if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1313   switch (type) {
1314     case JS_GLOBAL_PROXY_TYPE:
1315       return JSGlobalProxy::kSize;
1316     case JS_GLOBAL_OBJECT_TYPE:
1317       return JSGlobalObject::kSize;
1318     case JS_BUILTINS_OBJECT_TYPE:
1319       return JSBuiltinsObject::kSize;
1320     case JS_FUNCTION_TYPE:
1321       return JSFunction::kSize;
1322     case JS_VALUE_TYPE:
1323       return JSValue::kSize;
1324     case JS_ARRAY_TYPE:
1325       return JSValue::kSize;
1326     case JS_WEAK_MAP_TYPE:
1327       return JSWeakMap::kSize;
1328     case JS_REGEXP_TYPE:
1329       return JSValue::kSize;
1330     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1331       return JSObject::kHeaderSize;
1332     case JS_MESSAGE_OBJECT_TYPE:
1333       return JSMessageObject::kSize;
1334     default:
1335       UNREACHABLE();
1336       return 0;
1337   }
1338 }
1339
1340
1341 int JSObject::GetInternalFieldCount() {
1342   ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1343   // Make sure to adjust for the number of in-object properties. These
1344   // properties do contribute to the size, but are not internal fields.
1345   return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1346          map()->inobject_properties() - (map()->has_external_resource()?1:0);
1347 }
1348
1349
1350 int JSObject::GetInternalFieldOffset(int index) {
1351   ASSERT(index < GetInternalFieldCount() && index >= 0);
1352   return GetHeaderSize() + (kPointerSize * index);
1353 }
1354
1355
1356 Object* JSObject::GetInternalField(int index) {
1357   ASSERT(index < GetInternalFieldCount() && index >= 0);
1358   // Internal objects do follow immediately after the header, whereas in-object
1359   // properties are at the end of the object. Therefore there is no need
1360   // to adjust the index here.
1361   return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1362 }
1363
1364
1365 void JSObject::SetInternalField(int index, Object* value) {
1366   ASSERT(index < GetInternalFieldCount() && index >= 0);
1367   // Internal objects do follow immediately after the header, whereas in-object
1368   // properties are at the end of the object. Therefore there is no need
1369   // to adjust the index here.
1370   int offset = GetHeaderSize() + (kPointerSize * index);
1371   WRITE_FIELD(this, offset, value);
1372   WRITE_BARRIER(GetHeap(), this, offset, value);
1373 }
1374
1375
1376 void JSObject::SetExternalResourceObject(Object *value) {
1377   ASSERT(map()->has_external_resource());
1378   int offset = GetHeaderSize() + kPointerSize * GetInternalFieldCount();
1379   WRITE_FIELD(this, offset, value);
1380   WRITE_BARRIER(GetHeap(), this, offset, value);
1381 }
1382
1383
1384 Object *JSObject::GetExternalResourceObject() { 
1385   if (map()->has_external_resource()) {
1386     return READ_FIELD(this, GetHeaderSize() + kPointerSize * GetInternalFieldCount());
1387   } else {
1388     return GetHeap()->undefined_value();
1389   }
1390 }
1391
1392
1393 // Access fast-case object properties at index. The use of these routines
1394 // is needed to correctly distinguish between properties stored in-object and
1395 // properties stored in the properties array.
1396 Object* JSObject::FastPropertyAt(int index) {
1397   // Adjust for the number of properties stored in the object.
1398   index -= map()->inobject_properties();
1399   if (index < 0) {
1400     int offset = map()->instance_size() + (index * kPointerSize);
1401     return READ_FIELD(this, offset);
1402   } else {
1403     ASSERT(index < properties()->length());
1404     return properties()->get(index);
1405   }
1406 }
1407
1408
1409 Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1410   // Adjust for the number of properties stored in the object.
1411   index -= map()->inobject_properties();
1412   if (index < 0) {
1413     int offset = map()->instance_size() + (index * kPointerSize);
1414     WRITE_FIELD(this, offset, value);
1415     WRITE_BARRIER(GetHeap(), this, offset, value);
1416   } else {
1417     ASSERT(index < properties()->length());
1418     properties()->set(index, value);
1419   }
1420   return value;
1421 }
1422
1423
1424 int JSObject::GetInObjectPropertyOffset(int index) {
1425   // Adjust for the number of properties stored in the object.
1426   index -= map()->inobject_properties();
1427   ASSERT(index < 0);
1428   return map()->instance_size() + (index * kPointerSize);
1429 }
1430
1431
1432 Object* JSObject::InObjectPropertyAt(int index) {
1433   // Adjust for the number of properties stored in the object.
1434   index -= map()->inobject_properties();
1435   ASSERT(index < 0);
1436   int offset = map()->instance_size() + (index * kPointerSize);
1437   return READ_FIELD(this, offset);
1438 }
1439
1440
1441 Object* JSObject::InObjectPropertyAtPut(int index,
1442                                         Object* value,
1443                                         WriteBarrierMode mode) {
1444   // Adjust for the number of properties stored in the object.
1445   index -= map()->inobject_properties();
1446   ASSERT(index < 0);
1447   int offset = map()->instance_size() + (index * kPointerSize);
1448   WRITE_FIELD(this, offset, value);
1449   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1450   return value;
1451 }
1452
1453
1454
1455 void JSObject::InitializeBody(Map* map,
1456                               Object* pre_allocated_value,
1457                               Object* filler_value) {
1458   ASSERT(!filler_value->IsHeapObject() ||
1459          !GetHeap()->InNewSpace(filler_value));
1460   ASSERT(!pre_allocated_value->IsHeapObject() ||
1461          !GetHeap()->InNewSpace(pre_allocated_value));
1462   int size = map->instance_size();
1463   int offset = kHeaderSize;
1464   if (filler_value != pre_allocated_value) {
1465     int pre_allocated = map->pre_allocated_property_fields();
1466     ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
1467     for (int i = 0; i < pre_allocated; i++) {
1468       WRITE_FIELD(this, offset, pre_allocated_value);
1469       offset += kPointerSize;
1470     }
1471   }
1472   while (offset < size) {
1473     WRITE_FIELD(this, offset, filler_value);
1474     offset += kPointerSize;
1475   }
1476 }
1477
1478
1479 bool JSObject::HasFastProperties() {
1480   return !properties()->IsDictionary();
1481 }
1482
1483
1484 int JSObject::MaxFastProperties() {
1485   // Allow extra fast properties if the object has more than
1486   // kMaxFastProperties in-object properties. When this is the case,
1487   // it is very unlikely that the object is being used as a dictionary
1488   // and there is a good chance that allowing more map transitions
1489   // will be worth it.
1490   return Max(map()->inobject_properties(), kMaxFastProperties);
1491 }
1492
1493
1494 void Struct::InitializeBody(int object_size) {
1495   Object* value = GetHeap()->undefined_value();
1496   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1497     WRITE_FIELD(this, offset, value);
1498   }
1499 }
1500
1501
1502 bool Object::ToArrayIndex(uint32_t* index) {
1503   if (IsSmi()) {
1504     int value = Smi::cast(this)->value();
1505     if (value < 0) return false;
1506     *index = value;
1507     return true;
1508   }
1509   if (IsHeapNumber()) {
1510     double value = HeapNumber::cast(this)->value();
1511     uint32_t uint_value = static_cast<uint32_t>(value);
1512     if (value == static_cast<double>(uint_value)) {
1513       *index = uint_value;
1514       return true;
1515     }
1516   }
1517   return false;
1518 }
1519
1520
1521 bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1522   if (!this->IsJSValue()) return false;
1523
1524   JSValue* js_value = JSValue::cast(this);
1525   if (!js_value->value()->IsString()) return false;
1526
1527   String* str = String::cast(js_value->value());
1528   if (index >= (uint32_t)str->length()) return false;
1529
1530   return true;
1531 }
1532
1533
1534 FixedArrayBase* FixedArrayBase::cast(Object* object) {
1535   ASSERT(object->IsFixedArray() || object->IsFixedDoubleArray());
1536   return reinterpret_cast<FixedArrayBase*>(object);
1537 }
1538
1539
1540 Object* FixedArray::get(int index) {
1541   ASSERT(index >= 0 && index < this->length());
1542   return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1543 }
1544
1545
1546 void FixedArray::set(int index, Smi* value) {
1547   ASSERT(map() != HEAP->fixed_cow_array_map());
1548   ASSERT(index >= 0 && index < this->length());
1549   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1550   int offset = kHeaderSize + index * kPointerSize;
1551   WRITE_FIELD(this, offset, value);
1552 }
1553
1554
1555 void FixedArray::set(int index, Object* value) {
1556   ASSERT(map() != HEAP->fixed_cow_array_map());
1557   ASSERT(index >= 0 && index < this->length());
1558   int offset = kHeaderSize + index * kPointerSize;
1559   WRITE_FIELD(this, offset, value);
1560   WRITE_BARRIER(GetHeap(), this, offset, value);
1561 }
1562
1563
1564 inline bool FixedDoubleArray::is_the_hole_nan(double value) {
1565   return BitCast<uint64_t, double>(value) == kHoleNanInt64;
1566 }
1567
1568
1569 inline double FixedDoubleArray::hole_nan_as_double() {
1570   return BitCast<double, uint64_t>(kHoleNanInt64);
1571 }
1572
1573
1574 inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
1575   ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
1576   ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
1577   return OS::nan_value();
1578 }
1579
1580
1581 double FixedDoubleArray::get_scalar(int index) {
1582   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1583          map() != HEAP->fixed_array_map());
1584   ASSERT(index >= 0 && index < this->length());
1585   double result = READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
1586   ASSERT(!is_the_hole_nan(result));
1587   return result;
1588 }
1589
1590
1591 MaybeObject* FixedDoubleArray::get(int index) {
1592   if (is_the_hole(index)) {
1593     return GetHeap()->the_hole_value();
1594   } else {
1595     return GetHeap()->NumberFromDouble(get_scalar(index));
1596   }
1597 }
1598
1599
1600 void FixedDoubleArray::set(int index, double value) {
1601   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1602          map() != HEAP->fixed_array_map());
1603   int offset = kHeaderSize + index * kDoubleSize;
1604   if (isnan(value)) value = canonical_not_the_hole_nan_as_double();
1605   WRITE_DOUBLE_FIELD(this, offset, value);
1606 }
1607
1608
1609 void FixedDoubleArray::set_the_hole(int index) {
1610   ASSERT(map() != HEAP->fixed_cow_array_map() &&
1611          map() != HEAP->fixed_array_map());
1612   int offset = kHeaderSize + index * kDoubleSize;
1613   WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1614 }
1615
1616
1617 bool FixedDoubleArray::is_the_hole(int index) {
1618   int offset = kHeaderSize + index * kDoubleSize;
1619   return is_the_hole_nan(READ_DOUBLE_FIELD(this, offset));
1620 }
1621
1622
1623 void FixedDoubleArray::Initialize(FixedDoubleArray* from) {
1624   int old_length = from->length();
1625   ASSERT(old_length < length());
1626   if (old_length * kDoubleSize >= OS::kMinComplexMemCopy) {
1627     OS::MemCopy(FIELD_ADDR(this, kHeaderSize),
1628                 FIELD_ADDR(from, kHeaderSize),
1629                 old_length * kDoubleSize);
1630   } else {
1631     for (int i = 0; i < old_length; ++i) {
1632       if (from->is_the_hole(i)) {
1633         set_the_hole(i);
1634       } else {
1635         set(i, from->get_scalar(i));
1636       }
1637     }
1638   }
1639   int offset = kHeaderSize + old_length * kDoubleSize;
1640   for (int current = from->length(); current < length(); ++current) {
1641     WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1642     offset += kDoubleSize;
1643   }
1644 }
1645
1646
1647 void FixedDoubleArray::Initialize(FixedArray* from) {
1648   int old_length = from->length();
1649   ASSERT(old_length <= length());
1650   for (int i = 0; i < old_length; i++) {
1651     Object* hole_or_object = from->get(i);
1652     if (hole_or_object->IsTheHole()) {
1653       set_the_hole(i);
1654     } else {
1655       set(i, hole_or_object->Number());
1656     }
1657   }
1658   int offset = kHeaderSize + old_length * kDoubleSize;
1659   for (int current = from->length(); current < length(); ++current) {
1660     WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1661     offset += kDoubleSize;
1662   }
1663 }
1664
1665
1666 void FixedDoubleArray::Initialize(NumberDictionary* from) {
1667   int offset = kHeaderSize;
1668   for (int current = 0; current < length(); ++current) {
1669     WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double());
1670     offset += kDoubleSize;
1671   }
1672   for (int i = 0; i < from->Capacity(); i++) {
1673     Object* key = from->KeyAt(i);
1674     if (key->IsNumber()) {
1675       uint32_t entry = static_cast<uint32_t>(key->Number());
1676       set(entry, from->ValueAt(i)->Number());
1677     }
1678   }
1679 }
1680
1681
1682 WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1683   Heap* heap = GetHeap();
1684   if (heap->incremental_marking()->IsMarking()) return UPDATE_WRITE_BARRIER;
1685   if (heap->InNewSpace(this)) return SKIP_WRITE_BARRIER;
1686   return UPDATE_WRITE_BARRIER;
1687 }
1688
1689
1690 void FixedArray::set(int index,
1691                      Object* value,
1692                      WriteBarrierMode mode) {
1693   ASSERT(map() != HEAP->fixed_cow_array_map());
1694   ASSERT(index >= 0 && index < this->length());
1695   int offset = kHeaderSize + index * kPointerSize;
1696   WRITE_FIELD(this, offset, value);
1697   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);
1698 }
1699
1700
1701 void FixedArray::NoWriteBarrierSet(FixedArray* array,
1702                                    int index,
1703                                    Object* value) {
1704   ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
1705   ASSERT(index >= 0 && index < array->length());
1706   ASSERT(!HEAP->InNewSpace(value));
1707   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1708 }
1709
1710
1711 void FixedArray::set_undefined(int index) {
1712   ASSERT(map() != HEAP->fixed_cow_array_map());
1713   set_undefined(GetHeap(), index);
1714 }
1715
1716
1717 void FixedArray::set_undefined(Heap* heap, int index) {
1718   ASSERT(index >= 0 && index < this->length());
1719   ASSERT(!heap->InNewSpace(heap->undefined_value()));
1720   WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1721               heap->undefined_value());
1722 }
1723
1724
1725 void FixedArray::set_null(int index) {
1726   set_null(GetHeap(), index);
1727 }
1728
1729
1730 void FixedArray::set_null(Heap* heap, int index) {
1731   ASSERT(index >= 0 && index < this->length());
1732   ASSERT(!heap->InNewSpace(heap->null_value()));
1733   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1734 }
1735
1736
1737 void FixedArray::set_the_hole(int index) {
1738   ASSERT(map() != HEAP->fixed_cow_array_map());
1739   ASSERT(index >= 0 && index < this->length());
1740   ASSERT(!HEAP->InNewSpace(HEAP->the_hole_value()));
1741   WRITE_FIELD(this,
1742               kHeaderSize + index * kPointerSize,
1743               GetHeap()->the_hole_value());
1744 }
1745
1746
1747 void FixedArray::set_unchecked(int index, Smi* value) {
1748   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1749   int offset = kHeaderSize + index * kPointerSize;
1750   WRITE_FIELD(this, offset, value);
1751 }
1752
1753
1754 void FixedArray::set_unchecked(Heap* heap,
1755                                int index,
1756                                Object* value,
1757                                WriteBarrierMode mode) {
1758   int offset = kHeaderSize + index * kPointerSize;
1759   WRITE_FIELD(this, offset, value);
1760   CONDITIONAL_WRITE_BARRIER(heap, this, offset, value, mode);
1761 }
1762
1763
1764 void FixedArray::set_null_unchecked(Heap* heap, int index) {
1765   ASSERT(index >= 0 && index < this->length());
1766   ASSERT(!HEAP->InNewSpace(heap->null_value()));
1767   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, heap->null_value());
1768 }
1769
1770
1771 Object** FixedArray::data_start() {
1772   return HeapObject::RawField(this, kHeaderSize);
1773 }
1774
1775
1776 bool DescriptorArray::IsEmpty() {
1777   ASSERT(this->IsSmi() ||
1778          this->length() > kFirstIndex ||
1779          this == HEAP->empty_descriptor_array());
1780   return this->IsSmi() || length() <= kFirstIndex;
1781 }
1782
1783
1784 int DescriptorArray::bit_field3_storage() {
1785   Object* storage = READ_FIELD(this, kBitField3StorageOffset);
1786   return Smi::cast(storage)->value();
1787 }
1788
1789 void DescriptorArray::set_bit_field3_storage(int value) {
1790   ASSERT(!IsEmpty());
1791   WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value));
1792 }
1793
1794
1795 void DescriptorArray::NoWriteBarrierSwap(FixedArray* array,
1796                                          int first,
1797                                          int second) {
1798   Object* tmp = array->get(first);
1799   NoWriteBarrierSet(array, first, array->get(second));
1800   NoWriteBarrierSet(array, second, tmp);
1801 }
1802
1803
1804 int DescriptorArray::Search(String* name) {
1805   SLOW_ASSERT(IsSortedNoDuplicates());
1806
1807   // Check for empty descriptor array.
1808   int nof = number_of_descriptors();
1809   if (nof == 0) return kNotFound;
1810
1811   // Fast case: do linear search for small arrays.
1812   const int kMaxElementsForLinearSearch = 8;
1813   if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1814     return LinearSearch(name, nof);
1815   }
1816
1817   // Slow case: perform binary search.
1818   return BinarySearch(name, 0, nof - 1);
1819 }
1820
1821
1822 int DescriptorArray::SearchWithCache(String* name) {
1823   int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name);
1824   if (number == DescriptorLookupCache::kAbsent) {
1825     number = Search(name);
1826     GetIsolate()->descriptor_lookup_cache()->Update(this, name, number);
1827   }
1828   return number;
1829 }
1830
1831
1832 String* DescriptorArray::GetKey(int descriptor_number) {
1833   ASSERT(descriptor_number < number_of_descriptors());
1834   return String::cast(get(ToKeyIndex(descriptor_number)));
1835 }
1836
1837
1838 Object* DescriptorArray::GetValue(int descriptor_number) {
1839   ASSERT(descriptor_number < number_of_descriptors());
1840   return GetContentArray()->get(ToValueIndex(descriptor_number));
1841 }
1842
1843
1844 Smi* DescriptorArray::GetDetails(int descriptor_number) {
1845   ASSERT(descriptor_number < number_of_descriptors());
1846   return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1847 }
1848
1849
1850 PropertyType DescriptorArray::GetType(int descriptor_number) {
1851   ASSERT(descriptor_number < number_of_descriptors());
1852   return PropertyDetails(GetDetails(descriptor_number)).type();
1853 }
1854
1855
1856 int DescriptorArray::GetFieldIndex(int descriptor_number) {
1857   return Descriptor::IndexFromValue(GetValue(descriptor_number));
1858 }
1859
1860
1861 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1862   return JSFunction::cast(GetValue(descriptor_number));
1863 }
1864
1865
1866 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1867   ASSERT(GetType(descriptor_number) == CALLBACKS);
1868   return GetValue(descriptor_number);
1869 }
1870
1871
1872 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1873   ASSERT(GetType(descriptor_number) == CALLBACKS);
1874   Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number));
1875   return reinterpret_cast<AccessorDescriptor*>(p->foreign_address());
1876 }
1877
1878
1879 bool DescriptorArray::IsProperty(int descriptor_number) {
1880   return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1881 }
1882
1883
1884 bool DescriptorArray::IsTransition(int descriptor_number) {
1885   PropertyType t = GetType(descriptor_number);
1886   return t == MAP_TRANSITION || t == CONSTANT_TRANSITION ||
1887       t == ELEMENTS_TRANSITION;
1888 }
1889
1890
1891 bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1892   return GetType(descriptor_number) == NULL_DESCRIPTOR;
1893 }
1894
1895
1896 bool DescriptorArray::IsDontEnum(int descriptor_number) {
1897   return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1898 }
1899
1900
1901 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1902   desc->Init(GetKey(descriptor_number),
1903              GetValue(descriptor_number),
1904              PropertyDetails(GetDetails(descriptor_number)));
1905 }
1906
1907
1908 void DescriptorArray::Set(int descriptor_number,
1909                           Descriptor* desc,
1910                           const WhitenessWitness&) {
1911   // Range check.
1912   ASSERT(descriptor_number < number_of_descriptors());
1913
1914   // Make sure none of the elements in desc are in new space.
1915   ASSERT(!HEAP->InNewSpace(desc->GetKey()));
1916   ASSERT(!HEAP->InNewSpace(desc->GetValue()));
1917
1918   NoWriteBarrierSet(this,
1919                     ToKeyIndex(descriptor_number),
1920                     desc->GetKey());
1921   FixedArray* content_array = GetContentArray();
1922   NoWriteBarrierSet(content_array,
1923                     ToValueIndex(descriptor_number),
1924                     desc->GetValue());
1925   NoWriteBarrierSet(content_array,
1926                     ToDetailsIndex(descriptor_number),
1927                     desc->GetDetails().AsSmi());
1928 }
1929
1930
1931 void DescriptorArray::CopyFrom(int index,
1932                                DescriptorArray* src,
1933                                int src_index,
1934                                const WhitenessWitness& witness) {
1935   Descriptor desc;
1936   src->Get(src_index, &desc);
1937   Set(index, &desc, witness);
1938 }
1939
1940
1941 void DescriptorArray::NoWriteBarrierSwapDescriptors(int first, int second) {
1942   NoWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
1943   FixedArray* content_array = GetContentArray();
1944   NoWriteBarrierSwap(content_array,
1945                      ToValueIndex(first),
1946                      ToValueIndex(second));
1947   NoWriteBarrierSwap(content_array,
1948                      ToDetailsIndex(first),
1949                      ToDetailsIndex(second));
1950 }
1951
1952
1953 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
1954     : marking_(array->GetHeap()->incremental_marking()) {
1955   marking_->EnterNoMarkingScope();
1956   if (array->number_of_descriptors() > 0) {
1957     ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT);
1958     ASSERT(Marking::Color(array->GetContentArray()) == Marking::WHITE_OBJECT);
1959   }
1960 }
1961
1962
1963 DescriptorArray::WhitenessWitness::~WhitenessWitness() {
1964   marking_->LeaveNoMarkingScope();
1965 }
1966
1967
1968 template<typename Shape, typename Key>
1969 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) {
1970   const int kMinCapacity = 32;
1971   int capacity = RoundUpToPowerOf2(at_least_space_for * 2);
1972   if (capacity < kMinCapacity) {
1973     capacity = kMinCapacity;  // Guarantee min capacity.
1974   }
1975   return capacity;
1976 }
1977
1978
1979 template<typename Shape, typename Key>
1980 int HashTable<Shape, Key>::FindEntry(Key key) {
1981   return FindEntry(GetIsolate(), key);
1982 }
1983
1984
1985 // Find entry for key otherwise return kNotFound.
1986 template<typename Shape, typename Key>
1987 int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
1988   uint32_t capacity = Capacity();
1989   uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
1990   uint32_t count = 1;
1991   // EnsureCapacity will guarantee the hash table is never full.
1992   while (true) {
1993     Object* element = KeyAt(entry);
1994     if (element == isolate->heap()->undefined_value()) break;  // Empty entry.
1995     if (element != isolate->heap()->null_value() &&
1996         Shape::IsMatch(key, element)) return entry;
1997     entry = NextProbe(entry, count++, capacity);
1998   }
1999   return kNotFound;
2000 }
2001
2002
2003 bool NumberDictionary::requires_slow_elements() {
2004   Object* max_index_object = get(kMaxNumberKeyIndex);
2005   if (!max_index_object->IsSmi()) return false;
2006   return 0 !=
2007       (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
2008 }
2009
2010 uint32_t NumberDictionary::max_number_key() {
2011   ASSERT(!requires_slow_elements());
2012   Object* max_index_object = get(kMaxNumberKeyIndex);
2013   if (!max_index_object->IsSmi()) return 0;
2014   uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
2015   return value >> kRequiresSlowElementsTagSize;
2016 }
2017
2018 void NumberDictionary::set_requires_slow_elements() {
2019   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
2020 }
2021
2022
2023 // ------------------------------------
2024 // Cast operations
2025
2026
2027 CAST_ACCESSOR(FixedArray)
2028 CAST_ACCESSOR(FixedDoubleArray)
2029 CAST_ACCESSOR(DescriptorArray)
2030 CAST_ACCESSOR(DeoptimizationInputData)
2031 CAST_ACCESSOR(DeoptimizationOutputData)
2032 CAST_ACCESSOR(SymbolTable)
2033 CAST_ACCESSOR(JSFunctionResultCache)
2034 CAST_ACCESSOR(NormalizedMapCache)
2035 CAST_ACCESSOR(CompilationCacheTable)
2036 CAST_ACCESSOR(CodeCacheHashTable)
2037 CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
2038 CAST_ACCESSOR(MapCache)
2039 CAST_ACCESSOR(String)
2040 CAST_ACCESSOR(SeqString)
2041 CAST_ACCESSOR(SeqAsciiString)
2042 CAST_ACCESSOR(SeqTwoByteString)
2043 CAST_ACCESSOR(SlicedString)
2044 CAST_ACCESSOR(ConsString)
2045 CAST_ACCESSOR(ExternalString)
2046 CAST_ACCESSOR(ExternalAsciiString)
2047 CAST_ACCESSOR(ExternalTwoByteString)
2048 CAST_ACCESSOR(JSReceiver)
2049 CAST_ACCESSOR(JSObject)
2050 CAST_ACCESSOR(Smi)
2051 CAST_ACCESSOR(HeapObject)
2052 CAST_ACCESSOR(HeapNumber)
2053 CAST_ACCESSOR(Oddball)
2054 CAST_ACCESSOR(JSGlobalPropertyCell)
2055 CAST_ACCESSOR(SharedFunctionInfo)
2056 CAST_ACCESSOR(Map)
2057 CAST_ACCESSOR(JSFunction)
2058 CAST_ACCESSOR(GlobalObject)
2059 CAST_ACCESSOR(JSGlobalProxy)
2060 CAST_ACCESSOR(JSGlobalObject)
2061 CAST_ACCESSOR(JSBuiltinsObject)
2062 CAST_ACCESSOR(Code)
2063 CAST_ACCESSOR(JSArray)
2064 CAST_ACCESSOR(JSRegExp)
2065 CAST_ACCESSOR(JSProxy)
2066 CAST_ACCESSOR(JSFunctionProxy)
2067 CAST_ACCESSOR(JSSet)
2068 CAST_ACCESSOR(JSMap)
2069 CAST_ACCESSOR(JSWeakMap)
2070 CAST_ACCESSOR(Foreign)
2071 CAST_ACCESSOR(ByteArray)
2072 CAST_ACCESSOR(FreeSpace)
2073 CAST_ACCESSOR(ExternalArray)
2074 CAST_ACCESSOR(ExternalByteArray)
2075 CAST_ACCESSOR(ExternalUnsignedByteArray)
2076 CAST_ACCESSOR(ExternalShortArray)
2077 CAST_ACCESSOR(ExternalUnsignedShortArray)
2078 CAST_ACCESSOR(ExternalIntArray)
2079 CAST_ACCESSOR(ExternalUnsignedIntArray)
2080 CAST_ACCESSOR(ExternalFloatArray)
2081 CAST_ACCESSOR(ExternalDoubleArray)
2082 CAST_ACCESSOR(ExternalPixelArray)
2083 CAST_ACCESSOR(Struct)
2084
2085
2086 #define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
2087   STRUCT_LIST(MAKE_STRUCT_CAST)
2088 #undef MAKE_STRUCT_CAST
2089
2090
2091 template <typename Shape, typename Key>
2092 HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
2093   ASSERT(obj->IsHashTable());
2094   return reinterpret_cast<HashTable*>(obj);
2095 }
2096
2097
2098 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
2099 SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
2100
2101 SMI_ACCESSORS(String, length, kLengthOffset)
2102 SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset)
2103
2104
2105 uint32_t String::hash_field() {
2106   return READ_UINT32_FIELD(this, kHashFieldOffset);
2107 }
2108
2109
2110 void String::set_hash_field(uint32_t value) {
2111   WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
2112 #if V8_HOST_ARCH_64_BIT
2113   WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
2114 #endif
2115 }
2116
2117
2118 bool String::Equals(String* other) {
2119   if (other == this) return true;
2120   if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
2121     return false;
2122   }
2123   return SlowEquals(other);
2124 }
2125
2126
2127 MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
2128   if (!StringShape(this).IsCons()) return this;
2129   ConsString* cons = ConsString::cast(this);
2130   if (cons->IsFlat()) return cons->first();
2131   return SlowTryFlatten(pretenure);
2132 }
2133
2134
2135 String* String::TryFlattenGetString(PretenureFlag pretenure) {
2136   MaybeObject* flat = TryFlatten(pretenure);
2137   Object* successfully_flattened;
2138   if (!flat->ToObject(&successfully_flattened)) return this;
2139   return String::cast(successfully_flattened);
2140 }
2141
2142
2143 uint16_t String::Get(int index) {
2144   ASSERT(index >= 0 && index < length());
2145   switch (StringShape(this).full_representation_tag()) {
2146     case kSeqStringTag | kAsciiStringTag:
2147       return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
2148     case kSeqStringTag | kTwoByteStringTag:
2149       return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
2150     case kConsStringTag | kAsciiStringTag:
2151     case kConsStringTag | kTwoByteStringTag:
2152       return ConsString::cast(this)->ConsStringGet(index);
2153     case kExternalStringTag | kAsciiStringTag:
2154       return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
2155     case kExternalStringTag | kTwoByteStringTag:
2156       return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
2157     case kSlicedStringTag | kAsciiStringTag:
2158     case kSlicedStringTag | kTwoByteStringTag:
2159       return SlicedString::cast(this)->SlicedStringGet(index);
2160     default:
2161       break;
2162   }
2163
2164   UNREACHABLE();
2165   return 0;
2166 }
2167
2168
2169 void String::Set(int index, uint16_t value) {
2170   ASSERT(index >= 0 && index < length());
2171   ASSERT(StringShape(this).IsSequential());
2172
2173   return this->IsAsciiRepresentation()
2174       ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
2175       : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
2176 }
2177
2178
2179 bool String::IsFlat() {
2180   if (!StringShape(this).IsCons()) return true;
2181   return ConsString::cast(this)->second()->length() == 0;
2182 }
2183
2184
2185 String* String::GetUnderlying() {
2186   // Giving direct access to underlying string only makes sense if the
2187   // wrapping string is already flattened.
2188   ASSERT(this->IsFlat());
2189   ASSERT(StringShape(this).IsIndirect());
2190   STATIC_ASSERT(ConsString::kFirstOffset == SlicedString::kParentOffset);
2191   const int kUnderlyingOffset = SlicedString::kParentOffset;
2192   return String::cast(READ_FIELD(this, kUnderlyingOffset));
2193 }
2194
2195
2196 uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
2197   ASSERT(index >= 0 && index < length());
2198   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2199 }
2200
2201
2202 void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
2203   ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
2204   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
2205                    static_cast<byte>(value));
2206 }
2207
2208
2209 Address SeqAsciiString::GetCharsAddress() {
2210   return FIELD_ADDR(this, kHeaderSize);
2211 }
2212
2213
2214 char* SeqAsciiString::GetChars() {
2215   return reinterpret_cast<char*>(GetCharsAddress());
2216 }
2217
2218
2219 Address SeqTwoByteString::GetCharsAddress() {
2220   return FIELD_ADDR(this, kHeaderSize);
2221 }
2222
2223
2224 uc16* SeqTwoByteString::GetChars() {
2225   return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
2226 }
2227
2228
2229 uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
2230   ASSERT(index >= 0 && index < length());
2231   return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
2232 }
2233
2234
2235 void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
2236   ASSERT(index >= 0 && index < length());
2237   WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
2238 }
2239
2240
2241 int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
2242   return SizeFor(length());
2243 }
2244
2245
2246 int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
2247   return SizeFor(length());
2248 }
2249
2250
2251 String* SlicedString::parent() {
2252   return String::cast(READ_FIELD(this, kParentOffset));
2253 }
2254
2255
2256 void SlicedString::set_parent(String* parent) {
2257   ASSERT(parent->IsSeqString() || parent->IsExternalString());
2258   WRITE_FIELD(this, kParentOffset, parent);
2259 }
2260
2261
2262 SMI_ACCESSORS(SlicedString, offset, kOffsetOffset)
2263
2264
2265 String* ConsString::first() {
2266   return String::cast(READ_FIELD(this, kFirstOffset));
2267 }
2268
2269
2270 Object* ConsString::unchecked_first() {
2271   return READ_FIELD(this, kFirstOffset);
2272 }
2273
2274
2275 void ConsString::set_first(String* value, WriteBarrierMode mode) {
2276   WRITE_FIELD(this, kFirstOffset, value);
2277   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kFirstOffset, value, mode);
2278 }
2279
2280
2281 String* ConsString::second() {
2282   return String::cast(READ_FIELD(this, kSecondOffset));
2283 }
2284
2285
2286 Object* ConsString::unchecked_second() {
2287   return READ_FIELD(this, kSecondOffset);
2288 }
2289
2290
2291 void ConsString::set_second(String* value, WriteBarrierMode mode) {
2292   WRITE_FIELD(this, kSecondOffset, value);
2293   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kSecondOffset, value, mode);
2294 }
2295
2296
2297 const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
2298   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2299 }
2300
2301
2302 void ExternalAsciiString::set_resource(
2303     const ExternalAsciiString::Resource* resource) {
2304   *reinterpret_cast<const Resource**>(
2305       FIELD_ADDR(this, kResourceOffset)) = resource;
2306 }
2307
2308
2309 const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
2310   return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
2311 }
2312
2313
2314 void ExternalTwoByteString::set_resource(
2315     const ExternalTwoByteString::Resource* resource) {
2316   *reinterpret_cast<const Resource**>(
2317       FIELD_ADDR(this, kResourceOffset)) = resource;
2318 }
2319
2320
2321 void JSFunctionResultCache::MakeZeroSize() {
2322   set_finger_index(kEntriesIndex);
2323   set_size(kEntriesIndex);
2324 }
2325
2326
2327 void JSFunctionResultCache::Clear() {
2328   int cache_size = size();
2329   Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
2330   MemsetPointer(entries_start,
2331                 GetHeap()->the_hole_value(),
2332                 cache_size - kEntriesIndex);
2333   MakeZeroSize();
2334 }
2335
2336
2337 int JSFunctionResultCache::size() {
2338   return Smi::cast(get(kCacheSizeIndex))->value();
2339 }
2340
2341
2342 void JSFunctionResultCache::set_size(int size) {
2343   set(kCacheSizeIndex, Smi::FromInt(size));
2344 }
2345
2346
2347 int JSFunctionResultCache::finger_index() {
2348   return Smi::cast(get(kFingerIndex))->value();
2349 }
2350
2351
2352 void JSFunctionResultCache::set_finger_index(int finger_index) {
2353   set(kFingerIndex, Smi::FromInt(finger_index));
2354 }
2355
2356
2357 byte ByteArray::get(int index) {
2358   ASSERT(index >= 0 && index < this->length());
2359   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
2360 }
2361
2362
2363 void ByteArray::set(int index, byte value) {
2364   ASSERT(index >= 0 && index < this->length());
2365   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
2366 }
2367
2368
2369 int ByteArray::get_int(int index) {
2370   ASSERT(index >= 0 && (index * kIntSize) < this->length());
2371   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
2372 }
2373
2374
2375 ByteArray* ByteArray::FromDataStartAddress(Address address) {
2376   ASSERT_TAG_ALIGNED(address);
2377   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
2378 }
2379
2380
2381 Address ByteArray::GetDataStartAddress() {
2382   return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
2383 }
2384
2385
2386 uint8_t* ExternalPixelArray::external_pixel_pointer() {
2387   return reinterpret_cast<uint8_t*>(external_pointer());
2388 }
2389
2390
2391 uint8_t ExternalPixelArray::get_scalar(int index) {
2392   ASSERT((index >= 0) && (index < this->length()));
2393   uint8_t* ptr = external_pixel_pointer();
2394   return ptr[index];
2395 }
2396
2397
2398 MaybeObject* ExternalPixelArray::get(int index) {
2399   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2400 }
2401
2402
2403 void ExternalPixelArray::set(int index, uint8_t value) {
2404   ASSERT((index >= 0) && (index < this->length()));
2405   uint8_t* ptr = external_pixel_pointer();
2406   ptr[index] = value;
2407 }
2408
2409
2410 void* ExternalArray::external_pointer() {
2411   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2412   return reinterpret_cast<void*>(ptr);
2413 }
2414
2415
2416 void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2417   intptr_t ptr = reinterpret_cast<intptr_t>(value);
2418   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2419 }
2420
2421
2422 int8_t ExternalByteArray::get_scalar(int index) {
2423   ASSERT((index >= 0) && (index < this->length()));
2424   int8_t* ptr = static_cast<int8_t*>(external_pointer());
2425   return ptr[index];
2426 }
2427
2428
2429 MaybeObject* ExternalByteArray::get(int index) {
2430   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2431 }
2432
2433
2434 void ExternalByteArray::set(int index, int8_t value) {
2435   ASSERT((index >= 0) && (index < this->length()));
2436   int8_t* ptr = static_cast<int8_t*>(external_pointer());
2437   ptr[index] = value;
2438 }
2439
2440
2441 uint8_t ExternalUnsignedByteArray::get_scalar(int index) {
2442   ASSERT((index >= 0) && (index < this->length()));
2443   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2444   return ptr[index];
2445 }
2446
2447
2448 MaybeObject* ExternalUnsignedByteArray::get(int index) {
2449   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2450 }
2451
2452
2453 void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2454   ASSERT((index >= 0) && (index < this->length()));
2455   uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2456   ptr[index] = value;
2457 }
2458
2459
2460 int16_t ExternalShortArray::get_scalar(int index) {
2461   ASSERT((index >= 0) && (index < this->length()));
2462   int16_t* ptr = static_cast<int16_t*>(external_pointer());
2463   return ptr[index];
2464 }
2465
2466
2467 MaybeObject* ExternalShortArray::get(int index) {
2468   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2469 }
2470
2471
2472 void ExternalShortArray::set(int index, int16_t value) {
2473   ASSERT((index >= 0) && (index < this->length()));
2474   int16_t* ptr = static_cast<int16_t*>(external_pointer());
2475   ptr[index] = value;
2476 }
2477
2478
2479 uint16_t ExternalUnsignedShortArray::get_scalar(int index) {
2480   ASSERT((index >= 0) && (index < this->length()));
2481   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2482   return ptr[index];
2483 }
2484
2485
2486 MaybeObject* ExternalUnsignedShortArray::get(int index) {
2487   return Smi::FromInt(static_cast<int>(get_scalar(index)));
2488 }
2489
2490
2491 void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2492   ASSERT((index >= 0) && (index < this->length()));
2493   uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2494   ptr[index] = value;
2495 }
2496
2497
2498 int32_t ExternalIntArray::get_scalar(int index) {
2499   ASSERT((index >= 0) && (index < this->length()));
2500   int32_t* ptr = static_cast<int32_t*>(external_pointer());
2501   return ptr[index];
2502 }
2503
2504
2505 MaybeObject* ExternalIntArray::get(int index) {
2506     return GetHeap()->NumberFromInt32(get_scalar(index));
2507 }
2508
2509
2510 void ExternalIntArray::set(int index, int32_t value) {
2511   ASSERT((index >= 0) && (index < this->length()));
2512   int32_t* ptr = static_cast<int32_t*>(external_pointer());
2513   ptr[index] = value;
2514 }
2515
2516
2517 uint32_t ExternalUnsignedIntArray::get_scalar(int index) {
2518   ASSERT((index >= 0) && (index < this->length()));
2519   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2520   return ptr[index];
2521 }
2522
2523
2524 MaybeObject* ExternalUnsignedIntArray::get(int index) {
2525     return GetHeap()->NumberFromUint32(get_scalar(index));
2526 }
2527
2528
2529 void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2530   ASSERT((index >= 0) && (index < this->length()));
2531   uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2532   ptr[index] = value;
2533 }
2534
2535
2536 float ExternalFloatArray::get_scalar(int index) {
2537   ASSERT((index >= 0) && (index < this->length()));
2538   float* ptr = static_cast<float*>(external_pointer());
2539   return ptr[index];
2540 }
2541
2542
2543 MaybeObject* ExternalFloatArray::get(int index) {
2544     return GetHeap()->NumberFromDouble(get_scalar(index));
2545 }
2546
2547
2548 void ExternalFloatArray::set(int index, float value) {
2549   ASSERT((index >= 0) && (index < this->length()));
2550   float* ptr = static_cast<float*>(external_pointer());
2551   ptr[index] = value;
2552 }
2553
2554
2555 double ExternalDoubleArray::get_scalar(int index) {
2556   ASSERT((index >= 0) && (index < this->length()));
2557   double* ptr = static_cast<double*>(external_pointer());
2558   return ptr[index];
2559 }
2560
2561
2562 MaybeObject* ExternalDoubleArray::get(int index) {
2563     return GetHeap()->NumberFromDouble(get_scalar(index));
2564 }
2565
2566
2567 void ExternalDoubleArray::set(int index, double value) {
2568   ASSERT((index >= 0) && (index < this->length()));
2569   double* ptr = static_cast<double*>(external_pointer());
2570   ptr[index] = value;
2571 }
2572
2573
2574 int Map::visitor_id() {
2575   return READ_BYTE_FIELD(this, kVisitorIdOffset);
2576 }
2577
2578
2579 void Map::set_visitor_id(int id) {
2580   ASSERT(0 <= id && id < 256);
2581   WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2582 }
2583
2584
2585 int Map::instance_size() {
2586   return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2587 }
2588
2589
2590 int Map::inobject_properties() {
2591   return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2592 }
2593
2594
2595 int Map::pre_allocated_property_fields() {
2596   return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2597 }
2598
2599
2600 int HeapObject::SizeFromMap(Map* map) {
2601   int instance_size = map->instance_size();
2602   if (instance_size != kVariableSizeSentinel) return instance_size;
2603   // We can ignore the "symbol" bit becase it is only set for symbols
2604   // and implies a string type.
2605   int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2606   // Only inline the most frequent cases.
2607   if (instance_type == FIXED_ARRAY_TYPE) {
2608     return FixedArray::BodyDescriptor::SizeOf(map, this);
2609   }
2610   if (instance_type == ASCII_STRING_TYPE) {
2611     return SeqAsciiString::SizeFor(
2612         reinterpret_cast<SeqAsciiString*>(this)->length());
2613   }
2614   if (instance_type == BYTE_ARRAY_TYPE) {
2615     return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2616   }
2617   if (instance_type == FREE_SPACE_TYPE) {
2618     return reinterpret_cast<FreeSpace*>(this)->size();
2619   }
2620   if (instance_type == STRING_TYPE) {
2621     return SeqTwoByteString::SizeFor(
2622         reinterpret_cast<SeqTwoByteString*>(this)->length());
2623   }
2624   if (instance_type == FIXED_DOUBLE_ARRAY_TYPE) {
2625     return FixedDoubleArray::SizeFor(
2626         reinterpret_cast<FixedDoubleArray*>(this)->length());
2627   }
2628   ASSERT(instance_type == CODE_TYPE);
2629   return reinterpret_cast<Code*>(this)->CodeSize();
2630 }
2631
2632
2633 void Map::set_instance_size(int value) {
2634   ASSERT_EQ(0, value & (kPointerSize - 1));
2635   value >>= kPointerSizeLog2;
2636   ASSERT(0 <= value && value < 256);
2637   WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2638 }
2639
2640
2641 void Map::set_inobject_properties(int value) {
2642   ASSERT(0 <= value && value < 256);
2643   WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2644 }
2645
2646
2647 void Map::set_pre_allocated_property_fields(int value) {
2648   ASSERT(0 <= value && value < 256);
2649   WRITE_BYTE_FIELD(this,
2650                    kPreAllocatedPropertyFieldsOffset,
2651                    static_cast<byte>(value));
2652 }
2653
2654
2655 InstanceType Map::instance_type() {
2656   return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2657 }
2658
2659
2660 void Map::set_instance_type(InstanceType value) {
2661   WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2662 }
2663
2664
2665 int Map::unused_property_fields() {
2666   return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2667 }
2668
2669
2670 void Map::set_unused_property_fields(int value) {
2671   WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2672 }
2673
2674
2675 byte Map::bit_field() {
2676   return READ_BYTE_FIELD(this, kBitFieldOffset);
2677 }
2678
2679
2680 void Map::set_bit_field(byte value) {
2681   WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2682 }
2683
2684
2685 byte Map::bit_field2() {
2686   return READ_BYTE_FIELD(this, kBitField2Offset);
2687 }
2688
2689
2690 void Map::set_bit_field2(byte value) {
2691   WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2692 }
2693
2694
2695 void Map::set_non_instance_prototype(bool value) {
2696   if (value) {
2697     set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2698   } else {
2699     set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2700   }
2701 }
2702
2703
2704 bool Map::has_non_instance_prototype() {
2705   return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2706 }
2707
2708
2709 void Map::set_function_with_prototype(bool value) {
2710   if (value) {
2711     set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2712   } else {
2713     set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2714   }
2715 }
2716
2717
2718 bool Map::function_with_prototype() {
2719   return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2720 }
2721
2722
2723 void Map::set_is_access_check_needed(bool access_check_needed) {
2724   if (access_check_needed) {
2725     set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2726   } else {
2727     set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2728   }
2729 }
2730
2731
2732 bool Map::is_access_check_needed() {
2733   return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2734 }
2735
2736
2737 void Map::set_is_extensible(bool value) {
2738   if (value) {
2739     set_bit_field2(bit_field2() | (1 << kIsExtensible));
2740   } else {
2741     set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2742   }
2743 }
2744
2745 bool Map::is_extensible() {
2746   return ((1 << kIsExtensible) & bit_field2()) != 0;
2747 }
2748
2749
2750 void Map::set_attached_to_shared_function_info(bool value) {
2751   if (value) {
2752     set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
2753   } else {
2754     set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
2755   }
2756 }
2757
2758 bool Map::attached_to_shared_function_info() {
2759   return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
2760 }
2761
2762
2763 void Map::set_is_shared(bool value) {
2764   if (value) {
2765     set_bit_field3(bit_field3() | (1 << kIsShared));
2766   } else {
2767     set_bit_field3(bit_field3() & ~(1 << kIsShared));
2768   }
2769 }
2770
2771 bool Map::is_shared() {
2772   return ((1 << kIsShared) & bit_field3()) != 0;
2773 }
2774  
2775 void Map::set_has_external_resource(bool value) {
2776   if (value) {
2777     set_bit_field(bit_field() | (1 << kHasExternalResource));
2778   } else {
2779     set_bit_field(bit_field() & ~(1 << kHasExternalResource));
2780   }
2781 }
2782
2783 bool Map::has_external_resource()
2784 {
2785     return ((1 << kHasExternalResource) & bit_field()) != 0;
2786 }
2787  
2788
2789 void Map::set_named_interceptor_is_fallback(bool value)
2790 {
2791   if (value) {
2792     set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback));
2793   } else {
2794     set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback));
2795   }
2796 }
2797
2798 bool Map::named_interceptor_is_fallback()
2799 {
2800   return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0;
2801 }
2802
2803
2804 JSFunction* Map::unchecked_constructor() {
2805   return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
2806 }
2807
2808
2809 Code::Flags Code::flags() {
2810   return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2811 }
2812
2813
2814 void Code::set_flags(Code::Flags flags) {
2815   STATIC_ASSERT(Code::NUMBER_OF_KINDS <= KindField::kMax + 1);
2816   // Make sure that all call stubs have an arguments count.
2817   ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2818           ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2819          ExtractArgumentsCountFromFlags(flags) >= 0);
2820   WRITE_INT_FIELD(this, kFlagsOffset, flags);
2821 }
2822
2823
2824 Code::Kind Code::kind() {
2825   return ExtractKindFromFlags(flags());
2826 }
2827
2828
2829 InlineCacheState Code::ic_state() {
2830   InlineCacheState result = ExtractICStateFromFlags(flags());
2831   // Only allow uninitialized or debugger states for non-IC code
2832   // objects. This is used in the debugger to determine whether or not
2833   // a call to code object has been replaced with a debug break call.
2834   ASSERT(is_inline_cache_stub() ||
2835          result == UNINITIALIZED ||
2836          result == DEBUG_BREAK ||
2837          result == DEBUG_PREPARE_STEP_IN);
2838   return result;
2839 }
2840
2841
2842 Code::ExtraICState Code::extra_ic_state() {
2843   ASSERT(is_inline_cache_stub());
2844   return ExtractExtraICStateFromFlags(flags());
2845 }
2846
2847
2848 PropertyType Code::type() {
2849   return ExtractTypeFromFlags(flags());
2850 }
2851
2852
2853 int Code::arguments_count() {
2854   ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2855   return ExtractArgumentsCountFromFlags(flags());
2856 }
2857
2858
2859 int Code::major_key() {
2860   ASSERT(kind() == STUB ||
2861          kind() == UNARY_OP_IC ||
2862          kind() == BINARY_OP_IC ||
2863          kind() == COMPARE_IC ||
2864          kind() == TO_BOOLEAN_IC);
2865   return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2866 }
2867
2868
2869 void Code::set_major_key(int major) {
2870   ASSERT(kind() == STUB ||
2871          kind() == UNARY_OP_IC ||
2872          kind() == BINARY_OP_IC ||
2873          kind() == COMPARE_IC ||
2874          kind() == TO_BOOLEAN_IC);
2875   ASSERT(0 <= major && major < 256);
2876   WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2877 }
2878
2879
2880 bool Code::is_pregenerated() {
2881   return kind() == STUB && IsPregeneratedField::decode(flags());
2882 }
2883
2884
2885 void Code::set_is_pregenerated(bool value) {
2886   ASSERT(kind() == STUB);
2887   Flags f = flags();
2888   f = static_cast<Flags>(IsPregeneratedField::update(f, value));
2889   set_flags(f);
2890 }
2891
2892
2893 bool Code::optimizable() {
2894   ASSERT(kind() == FUNCTION);
2895   return READ_BYTE_FIELD(this, kOptimizableOffset) == 1;
2896 }
2897
2898
2899 void Code::set_optimizable(bool value) {
2900   ASSERT(kind() == FUNCTION);
2901   WRITE_BYTE_FIELD(this, kOptimizableOffset, value ? 1 : 0);
2902 }
2903
2904
2905 bool Code::has_deoptimization_support() {
2906   ASSERT(kind() == FUNCTION);
2907   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2908   return FullCodeFlagsHasDeoptimizationSupportField::decode(flags);
2909 }
2910
2911
2912 void Code::set_has_deoptimization_support(bool value) {
2913   ASSERT(kind() == FUNCTION);
2914   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2915   flags = FullCodeFlagsHasDeoptimizationSupportField::update(flags, value);
2916   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2917 }
2918
2919
2920 bool Code::has_debug_break_slots() {
2921   ASSERT(kind() == FUNCTION);
2922   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2923   return FullCodeFlagsHasDebugBreakSlotsField::decode(flags);
2924 }
2925
2926
2927 void Code::set_has_debug_break_slots(bool value) {
2928   ASSERT(kind() == FUNCTION);
2929   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2930   flags = FullCodeFlagsHasDebugBreakSlotsField::update(flags, value);
2931   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2932 }
2933
2934
2935 bool Code::is_compiled_optimizable() {
2936   ASSERT(kind() == FUNCTION);
2937   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2938   return FullCodeFlagsIsCompiledOptimizable::decode(flags);
2939 }
2940
2941
2942 void Code::set_compiled_optimizable(bool value) {
2943   ASSERT(kind() == FUNCTION);
2944   byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
2945   flags = FullCodeFlagsIsCompiledOptimizable::update(flags, value);
2946   WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
2947 }
2948
2949
2950 int Code::allow_osr_at_loop_nesting_level() {
2951   ASSERT(kind() == FUNCTION);
2952   return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
2953 }
2954
2955
2956 void Code::set_allow_osr_at_loop_nesting_level(int level) {
2957   ASSERT(kind() == FUNCTION);
2958   ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
2959   WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
2960 }
2961
2962
2963 unsigned Code::stack_slots() {
2964   ASSERT(kind() == OPTIMIZED_FUNCTION);
2965   return READ_UINT32_FIELD(this, kStackSlotsOffset);
2966 }
2967
2968
2969 void Code::set_stack_slots(unsigned slots) {
2970   ASSERT(kind() == OPTIMIZED_FUNCTION);
2971   WRITE_UINT32_FIELD(this, kStackSlotsOffset, slots);
2972 }
2973
2974
2975 unsigned Code::safepoint_table_offset() {
2976   ASSERT(kind() == OPTIMIZED_FUNCTION);
2977   return READ_UINT32_FIELD(this, kSafepointTableOffsetOffset);
2978 }
2979
2980
2981 void Code::set_safepoint_table_offset(unsigned offset) {
2982   ASSERT(kind() == OPTIMIZED_FUNCTION);
2983   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2984   WRITE_UINT32_FIELD(this, kSafepointTableOffsetOffset, offset);
2985 }
2986
2987
2988 unsigned Code::stack_check_table_offset() {
2989   ASSERT(kind() == FUNCTION);
2990   return READ_UINT32_FIELD(this, kStackCheckTableOffsetOffset);
2991 }
2992
2993
2994 void Code::set_stack_check_table_offset(unsigned offset) {
2995   ASSERT(kind() == FUNCTION);
2996   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
2997   WRITE_UINT32_FIELD(this, kStackCheckTableOffsetOffset, offset);
2998 }
2999
3000
3001 CheckType Code::check_type() {
3002   ASSERT(is_call_stub() || is_keyed_call_stub());
3003   byte type = READ_BYTE_FIELD(this, kCheckTypeOffset);
3004   return static_cast<CheckType>(type);
3005 }
3006
3007
3008 void Code::set_check_type(CheckType value) {
3009   ASSERT(is_call_stub() || is_keyed_call_stub());
3010   WRITE_BYTE_FIELD(this, kCheckTypeOffset, value);
3011 }
3012
3013
3014 byte Code::unary_op_type() {
3015   ASSERT(is_unary_op_stub());
3016   return READ_BYTE_FIELD(this, kUnaryOpTypeOffset);
3017 }
3018
3019
3020 void Code::set_unary_op_type(byte value) {
3021   ASSERT(is_unary_op_stub());
3022   WRITE_BYTE_FIELD(this, kUnaryOpTypeOffset, value);
3023 }
3024
3025
3026 byte Code::binary_op_type() {
3027   ASSERT(is_binary_op_stub());
3028   return READ_BYTE_FIELD(this, kBinaryOpTypeOffset);
3029 }
3030
3031
3032 void Code::set_binary_op_type(byte value) {
3033   ASSERT(is_binary_op_stub());
3034   WRITE_BYTE_FIELD(this, kBinaryOpTypeOffset, value);
3035 }
3036
3037
3038 byte Code::binary_op_result_type() {
3039   ASSERT(is_binary_op_stub());
3040   return READ_BYTE_FIELD(this, kBinaryOpReturnTypeOffset);
3041 }
3042
3043
3044 void Code::set_binary_op_result_type(byte value) {
3045   ASSERT(is_binary_op_stub());
3046   WRITE_BYTE_FIELD(this, kBinaryOpReturnTypeOffset, value);
3047 }
3048
3049
3050 byte Code::compare_state() {
3051   ASSERT(is_compare_ic_stub());
3052   return READ_BYTE_FIELD(this, kCompareStateOffset);
3053 }
3054
3055
3056 void Code::set_compare_state(byte value) {
3057   ASSERT(is_compare_ic_stub());
3058   WRITE_BYTE_FIELD(this, kCompareStateOffset, value);
3059 }
3060
3061
3062 byte Code::to_boolean_state() {
3063   ASSERT(is_to_boolean_ic_stub());
3064   return READ_BYTE_FIELD(this, kToBooleanTypeOffset);
3065 }
3066
3067
3068 void Code::set_to_boolean_state(byte value) {
3069   ASSERT(is_to_boolean_ic_stub());
3070   WRITE_BYTE_FIELD(this, kToBooleanTypeOffset, value);
3071 }
3072
3073
3074 bool Code::has_function_cache() {
3075   ASSERT(kind() == STUB);
3076   return READ_BYTE_FIELD(this, kHasFunctionCacheOffset) != 0;
3077 }
3078
3079
3080 void Code::set_has_function_cache(bool flag) {
3081   ASSERT(kind() == STUB);
3082   WRITE_BYTE_FIELD(this, kHasFunctionCacheOffset, flag);
3083 }
3084
3085
3086 bool Code::is_inline_cache_stub() {
3087   Kind kind = this->kind();
3088   return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
3089 }
3090
3091
3092 Code::Flags Code::ComputeFlags(Kind kind,
3093                                InlineCacheState ic_state,
3094                                ExtraICState extra_ic_state,
3095                                PropertyType type,
3096                                int argc,
3097                                InlineCacheHolderFlag holder) {
3098   // Extra IC state is only allowed for call IC stubs or for store IC
3099   // stubs.
3100   ASSERT(extra_ic_state == kNoExtraICState ||
3101          kind == CALL_IC ||
3102          kind == STORE_IC ||
3103          kind == KEYED_STORE_IC);
3104   // Compute the bit mask.
3105   int bits = KindField::encode(kind)
3106       | ICStateField::encode(ic_state)
3107       | TypeField::encode(type)
3108       | ExtraICStateField::encode(extra_ic_state)
3109       | (argc << kArgumentsCountShift)
3110       | CacheHolderField::encode(holder);
3111   return static_cast<Flags>(bits);
3112 }
3113
3114
3115 Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
3116                                           PropertyType type,
3117                                           ExtraICState extra_ic_state,
3118                                           InlineCacheHolderFlag holder,
3119                                           int argc) {
3120   return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
3121 }
3122
3123
3124 Code::Kind Code::ExtractKindFromFlags(Flags flags) {
3125   return KindField::decode(flags);
3126 }
3127
3128
3129 InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
3130   return ICStateField::decode(flags);
3131 }
3132
3133
3134 Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
3135   return ExtraICStateField::decode(flags);
3136 }
3137
3138
3139 PropertyType Code::ExtractTypeFromFlags(Flags flags) {
3140   return TypeField::decode(flags);
3141 }
3142
3143
3144 int Code::ExtractArgumentsCountFromFlags(Flags flags) {
3145   return (flags & kArgumentsCountMask) >> kArgumentsCountShift;
3146 }
3147
3148
3149 InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
3150   return CacheHolderField::decode(flags);
3151 }
3152
3153
3154 Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
3155   int bits = flags & ~TypeField::kMask;
3156   return static_cast<Flags>(bits);
3157 }
3158
3159
3160 Code* Code::GetCodeFromTargetAddress(Address address) {
3161   HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
3162   // GetCodeFromTargetAddress might be called when marking objects during mark
3163   // sweep. reinterpret_cast is therefore used instead of the more appropriate
3164   // Code::cast. Code::cast does not work when the object's map is
3165   // marked.
3166   Code* result = reinterpret_cast<Code*>(code);
3167   return result;
3168 }
3169
3170
3171 Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
3172   return HeapObject::
3173       FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
3174 }
3175
3176
3177 Object* Map::prototype() {
3178   return READ_FIELD(this, kPrototypeOffset);
3179 }
3180
3181
3182 void Map::set_prototype(Object* value, WriteBarrierMode mode) {
3183   ASSERT(value->IsNull() || value->IsJSReceiver());
3184   WRITE_FIELD(this, kPrototypeOffset, value);
3185   CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kPrototypeOffset, value, mode);
3186 }
3187
3188
3189 DescriptorArray* Map::instance_descriptors() {
3190   Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset);
3191   if (object->IsSmi()) {
3192     return HEAP->empty_descriptor_array();
3193   } else {
3194     return DescriptorArray::cast(object);
3195   }
3196 }
3197
3198
3199 void Map::init_instance_descriptors() {
3200   WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0));
3201 }
3202
3203
3204 void Map::clear_instance_descriptors() {
3205   Object* object = READ_FIELD(this,
3206                               kInstanceDescriptorsOrBitField3Offset);
3207   if (!object->IsSmi()) {
3208     WRITE_FIELD(
3209         this,
3210         kInstanceDescriptorsOrBitField3Offset,
3211         Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage()));
3212   }
3213 }
3214
3215
3216 void Map::set_instance_descriptors(DescriptorArray* value,
3217                                    WriteBarrierMode mode) {
3218   Object* object = READ_FIELD(this,
3219                               kInstanceDescriptorsOrBitField3Offset);
3220   Heap* heap = GetHeap();
3221   if (value == heap->empty_descriptor_array()) {
3222     clear_instance_descriptors();
3223     return;
3224   } else {
3225     if (object->IsSmi()) {
3226       value->set_bit_field3_storage(Smi::cast(object)->value());
3227     } else {
3228       value->set_bit_field3_storage(
3229           DescriptorArray::cast(object)->bit_field3_storage());
3230     }
3231   }
3232   ASSERT(!is_shared());
3233   WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value);
3234   CONDITIONAL_WRITE_BARRIER(
3235       heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode);
3236 }
3237
3238
3239 int Map::bit_field3() {
3240   Object* object = READ_FIELD(this,
3241                               kInstanceDescriptorsOrBitField3Offset);
3242   if (object->IsSmi()) {
3243     return Smi::cast(object)->value();
3244   } else {
3245     return DescriptorArray::cast(object)->bit_field3_storage();
3246   }
3247 }
3248
3249
3250 void Map::set_bit_field3(int value) {
3251   ASSERT(Smi::IsValid(value));
3252   Object* object = READ_FIELD(this,
3253                               kInstanceDescriptorsOrBitField3Offset);
3254   if (object->IsSmi()) {
3255     WRITE_FIELD(this,
3256                 kInstanceDescriptorsOrBitField3Offset,
3257                 Smi::FromInt(value));
3258   } else {
3259     DescriptorArray::cast(object)->set_bit_field3_storage(value);
3260   }
3261 }
3262
3263
3264 FixedArray* Map::unchecked_prototype_transitions() {
3265   return reinterpret_cast<FixedArray*>(
3266       READ_FIELD(this, kPrototypeTransitionsOffset));
3267 }
3268
3269
3270 ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
3271 ACCESSORS(Map, prototype_transitions, FixedArray, kPrototypeTransitionsOffset)
3272 ACCESSORS(Map, constructor, Object, kConstructorOffset)
3273
3274 ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
3275 ACCESSORS(JSFunction, literals_or_bindings, FixedArray, kLiteralsOffset)
3276 ACCESSORS(JSFunction,
3277           next_function_link,
3278           Object,
3279           kNextFunctionLinkOffset)
3280
3281 ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
3282 ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
3283 ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
3284
3285 ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
3286
3287 ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
3288 ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
3289 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
3290 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
3291 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
3292
3293 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
3294 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
3295 ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
3296
3297 ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
3298 ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
3299 ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
3300 ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
3301 ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
3302 ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
3303 ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset)
3304
3305 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
3306 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
3307
3308 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
3309 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
3310
3311 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
3312 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
3313 ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
3314           kPropertyAccessorsOffset)
3315 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
3316           kPrototypeTemplateOffset)
3317 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
3318 ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
3319           kNamedPropertyHandlerOffset)
3320 ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
3321           kIndexedPropertyHandlerOffset)
3322 ACCESSORS(FunctionTemplateInfo, instance_template, Object,
3323           kInstanceTemplateOffset)
3324 ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
3325 ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
3326 ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
3327           kInstanceCallHandlerOffset)
3328 ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
3329           kAccessCheckInfoOffset)
3330 ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
3331
3332 ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
3333 ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
3334           kInternalFieldCountOffset)
3335 ACCESSORS(ObjectTemplateInfo, has_external_resource, Object,
3336           kHasExternalResourceOffset)
3337
3338 ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
3339 ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
3340
3341 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
3342
3343 ACCESSORS(Script, source, Object, kSourceOffset)
3344 ACCESSORS(Script, name, Object, kNameOffset)
3345 ACCESSORS(Script, id, Object, kIdOffset)
3346 ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
3347 ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
3348 ACCESSORS(Script, data, Object, kDataOffset)
3349 ACCESSORS(Script, context_data, Object, kContextOffset)
3350 ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
3351 ACCESSORS(Script, type, Smi, kTypeOffset)
3352 ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
3353 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
3354 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
3355 ACCESSORS(Script, eval_from_instructions_offset, Smi,
3356           kEvalFrominstructionsOffsetOffset)
3357
3358 #ifdef ENABLE_DEBUGGER_SUPPORT
3359 ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
3360 ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
3361 ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
3362 ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
3363
3364 ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
3365 ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
3366 ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
3367 ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
3368 #endif
3369
3370 ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
3371 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
3372 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
3373 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
3374           kInstanceClassNameOffset)
3375 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
3376 ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
3377 ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
3378 ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
3379 ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
3380           kThisPropertyAssignmentsOffset)
3381
3382 BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
3383                kHiddenPrototypeBit)
3384 BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
3385 BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
3386                kNeedsAccessCheckBit)
3387 BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
3388                kReadOnlyPrototypeBit)
3389 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
3390                kIsExpressionBit)
3391 BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
3392                kIsTopLevelBit)
3393 BOOL_GETTER(SharedFunctionInfo,
3394             compiler_hints,
3395             has_only_simple_this_property_assignments,
3396             kHasOnlySimpleThisPropertyAssignments)
3397 BOOL_ACCESSORS(SharedFunctionInfo,
3398                compiler_hints,
3399                allows_lazy_compilation,
3400                kAllowLazyCompilation)
3401 BOOL_ACCESSORS(SharedFunctionInfo,
3402                compiler_hints,
3403                uses_arguments,
3404                kUsesArguments)
3405 BOOL_ACCESSORS(SharedFunctionInfo,
3406                compiler_hints,
3407                has_duplicate_parameters,
3408                kHasDuplicateParameters)
3409
3410
3411 #if V8_HOST_ARCH_32_BIT
3412 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
3413 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
3414               kFormalParameterCountOffset)
3415 SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
3416               kExpectedNofPropertiesOffset)
3417 SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3418 SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
3419               kStartPositionAndTypeOffset)
3420 SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
3421 SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
3422               kFunctionTokenPositionOffset)
3423 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
3424               kCompilerHintsOffset)
3425 SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
3426               kThisPropertyAssignmentsCountOffset)
3427 SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
3428 #else
3429
3430 #define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
3431   STATIC_ASSERT(holder::offset % kPointerSize == 0);              \
3432   int holder::name() {                                            \
3433     int value = READ_INT_FIELD(this, offset);                     \
3434     ASSERT(kHeapObjectTag == 1);                                  \
3435     ASSERT((value & kHeapObjectTag) == 0);                        \
3436     return value >> 1;                                            \
3437   }                                                               \
3438   void holder::set_##name(int value) {                            \
3439     ASSERT(kHeapObjectTag == 1);                                  \
3440     ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
3441            (value & 0xC0000000) == 0x000000000);                  \
3442     WRITE_INT_FIELD(this,                                         \
3443                     offset,                                       \
3444                     (value << 1) & ~kHeapObjectTag);              \
3445   }
3446
3447 #define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset)             \
3448   STATIC_ASSERT(holder::offset % kPointerSize == kIntSize);       \
3449   INT_ACCESSORS(holder, name, offset)
3450
3451
3452 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
3453 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3454                         formal_parameter_count,
3455                         kFormalParameterCountOffset)
3456
3457 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3458                         expected_nof_properties,
3459                         kExpectedNofPropertiesOffset)
3460 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
3461
3462 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, end_position, kEndPositionOffset)
3463 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3464                         start_position_and_type,
3465                         kStartPositionAndTypeOffset)
3466
3467 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3468                         function_token_position,
3469                         kFunctionTokenPositionOffset)
3470 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
3471                         compiler_hints,
3472                         kCompilerHintsOffset)
3473
3474 PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
3475                         this_property_assignments_count,
3476                         kThisPropertyAssignmentsCountOffset)
3477 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
3478 #endif
3479
3480
3481 int SharedFunctionInfo::construction_count() {
3482   return READ_BYTE_FIELD(this, kConstructionCountOffset);
3483 }
3484
3485
3486 void SharedFunctionInfo::set_construction_count(int value) {
3487   ASSERT(0 <= value && value < 256);
3488   WRITE_BYTE_FIELD(this, kConstructionCountOffset, static_cast<byte>(value));
3489 }
3490
3491
3492 BOOL_ACCESSORS(SharedFunctionInfo,
3493                compiler_hints,
3494                live_objects_may_exist,
3495                kLiveObjectsMayExist)
3496
3497
3498 bool SharedFunctionInfo::IsInobjectSlackTrackingInProgress() {
3499   return initial_map() != HEAP->undefined_value();
3500 }
3501
3502
3503 BOOL_GETTER(SharedFunctionInfo,
3504             compiler_hints,
3505             optimization_disabled,
3506             kOptimizationDisabled)
3507
3508
3509 void SharedFunctionInfo::set_optimization_disabled(bool disable) {
3510   set_compiler_hints(BooleanBit::set(compiler_hints(),
3511                                      kOptimizationDisabled,
3512                                      disable));
3513   // If disabling optimizations we reflect that in the code object so
3514   // it will not be counted as optimizable code.
3515   if ((code()->kind() == Code::FUNCTION) && disable) {
3516     code()->set_optimizable(false);
3517   }
3518 }
3519
3520
3521 StrictModeFlag SharedFunctionInfo::strict_mode_flag() {
3522   return BooleanBit::get(compiler_hints(), kStrictModeFunction)
3523       ? kStrictMode : kNonStrictMode;
3524 }
3525
3526
3527 void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
3528   ASSERT(strict_mode_flag == kStrictMode ||
3529          strict_mode_flag == kNonStrictMode);
3530   bool value = strict_mode_flag == kStrictMode;
3531   set_compiler_hints(
3532       BooleanBit::set(compiler_hints(), kStrictModeFunction, value));
3533 }
3534
3535
3536 BOOL_GETTER(SharedFunctionInfo, compiler_hints, strict_mode,
3537             kStrictModeFunction)
3538 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
3539 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
3540                name_should_print_as_anonymous,
3541                kNameShouldPrintAsAnonymous)
3542 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
3543 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
3544
3545 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
3546 ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
3547
3548 ACCESSORS(PolymorphicCodeCache, cache, Object, kCacheOffset)
3549
3550 bool Script::HasValidSource() {
3551   Object* src = this->source();
3552   if (!src->IsString()) return true;
3553   String* src_str = String::cast(src);
3554   if (!StringShape(src_str).IsExternal()) return true;
3555   if (src_str->IsAsciiRepresentation()) {
3556     return ExternalAsciiString::cast(src)->resource() != NULL;
3557   } else if (src_str->IsTwoByteRepresentation()) {
3558     return ExternalTwoByteString::cast(src)->resource() != NULL;
3559   }
3560   return true;
3561 }
3562
3563
3564 void SharedFunctionInfo::DontAdaptArguments() {
3565   ASSERT(code()->kind() == Code::BUILTIN);
3566   set_formal_parameter_count(kDontAdaptArgumentsSentinel);
3567 }
3568
3569
3570 int SharedFunctionInfo::start_position() {
3571   return start_position_and_type() >> kStartPositionShift;
3572 }
3573
3574
3575 void SharedFunctionInfo::set_start_position(int start_position) {
3576   set_start_position_and_type((start_position << kStartPositionShift)
3577     | (start_position_and_type() & ~kStartPositionMask));
3578 }
3579
3580
3581 Code* SharedFunctionInfo::code() {
3582   return Code::cast(READ_FIELD(this, kCodeOffset));
3583 }
3584
3585
3586 Code* SharedFunctionInfo::unchecked_code() {
3587   return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
3588 }
3589
3590
3591 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
3592   WRITE_FIELD(this, kCodeOffset, value);
3593   CONDITIONAL_WRITE_BARRIER(value->GetHeap(), this, kCodeOffset, value, mode);
3594 }
3595
3596
3597 SerializedScopeInfo* SharedFunctionInfo::scope_info() {
3598   return reinterpret_cast<SerializedScopeInfo*>(
3599       READ_FIELD(this, kScopeInfoOffset));
3600 }
3601
3602
3603 void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
3604                                         WriteBarrierMode mode) {
3605   WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
3606   CONDITIONAL_WRITE_BARRIER(GetHeap(),
3607                             this,
3608                             kScopeInfoOffset,
3609                             reinterpret_cast<Object*>(value),
3610                             mode);
3611 }
3612
3613
3614 Smi* SharedFunctionInfo::deopt_counter() {
3615   return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
3616 }
3617
3618
3619 void SharedFunctionInfo::set_deopt_counter(Smi* value) {
3620   WRITE_FIELD(this, kDeoptCounterOffset, value);
3621 }
3622
3623
3624 bool SharedFunctionInfo::is_compiled() {
3625   return code() !=
3626       Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);
3627 }
3628
3629
3630 bool SharedFunctionInfo::IsApiFunction() {
3631   return function_data()->IsFunctionTemplateInfo();
3632 }
3633
3634
3635 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
3636   ASSERT(IsApiFunction());
3637   return FunctionTemplateInfo::cast(function_data());
3638 }
3639
3640
3641 bool SharedFunctionInfo::HasBuiltinFunctionId() {
3642   return function_data()->IsSmi();
3643 }
3644
3645
3646 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
3647   ASSERT(HasBuiltinFunctionId());
3648   return static_cast<BuiltinFunctionId>(Smi::cast(function_data())->value());
3649 }
3650
3651
3652 int SharedFunctionInfo::code_age() {
3653   return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
3654 }
3655
3656
3657 void SharedFunctionInfo::set_code_age(int code_age) {
3658   set_compiler_hints(compiler_hints() |
3659                      ((code_age & kCodeAgeMask) << kCodeAgeShift));
3660 }
3661
3662
3663 bool SharedFunctionInfo::has_deoptimization_support() {
3664   Code* code = this->code();
3665   return code->kind() == Code::FUNCTION && code->has_deoptimization_support();
3666 }
3667
3668
3669 bool JSFunction::IsBuiltin() {
3670   return context()->global()->IsJSBuiltinsObject();
3671 }
3672
3673
3674 bool JSFunction::NeedsArgumentsAdaption() {
3675   return shared()->formal_parameter_count() !=
3676       SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3677 }
3678
3679
3680 bool JSFunction::IsOptimized() {
3681   return code()->kind() == Code::OPTIMIZED_FUNCTION;
3682 }
3683
3684
3685 bool JSFunction::IsOptimizable() {
3686   return code()->kind() == Code::FUNCTION && code()->optimizable();
3687 }
3688
3689
3690 bool JSFunction::IsMarkedForLazyRecompilation() {
3691   return code() == GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile);
3692 }
3693
3694
3695 Code* JSFunction::code() {
3696   return Code::cast(unchecked_code());
3697 }
3698
3699
3700 Code* JSFunction::unchecked_code() {
3701   return reinterpret_cast<Code*>(
3702       Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
3703 }
3704
3705
3706 void JSFunction::set_code(Code* value) {
3707   ASSERT(!HEAP->InNewSpace(value));
3708   Address entry = value->entry();
3709   WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
3710   GetHeap()->incremental_marking()->RecordWriteOfCodeEntry(
3711       this,
3712       HeapObject::RawField(this, kCodeEntryOffset),
3713       value);
3714 }
3715
3716
3717 void JSFunction::ReplaceCode(Code* code) {
3718   bool was_optimized = IsOptimized();
3719   bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
3720
3721   set_code(code);
3722
3723   // Add/remove the function from the list of optimized functions for this
3724   // context based on the state change.
3725   if (!was_optimized && is_optimized) {
3726     context()->global_context()->AddOptimizedFunction(this);
3727   }
3728   if (was_optimized && !is_optimized) {
3729     context()->global_context()->RemoveOptimizedFunction(this);
3730   }
3731 }
3732
3733
3734 Context* JSFunction::context() {
3735   return Context::cast(READ_FIELD(this, kContextOffset));
3736 }
3737
3738
3739 Object* JSFunction::unchecked_context() {
3740   return READ_FIELD(this, kContextOffset);
3741 }
3742
3743
3744 SharedFunctionInfo* JSFunction::unchecked_shared() {
3745   return reinterpret_cast<SharedFunctionInfo*>(
3746       READ_FIELD(this, kSharedFunctionInfoOffset));
3747 }
3748
3749
3750 void JSFunction::set_context(Object* value) {
3751   ASSERT(value->IsUndefined() || value->IsContext());
3752   WRITE_FIELD(this, kContextOffset, value);
3753   WRITE_BARRIER(GetHeap(), this, kContextOffset, value);
3754 }
3755
3756 ACCESSORS(JSFunction, prototype_or_initial_map, Object,
3757           kPrototypeOrInitialMapOffset)
3758
3759
3760 Map* JSFunction::initial_map() {
3761   return Map::cast(prototype_or_initial_map());
3762 }
3763
3764
3765 void JSFunction::set_initial_map(Map* value) {
3766   set_prototype_or_initial_map(value);
3767 }
3768
3769
3770 bool JSFunction::has_initial_map() {
3771   return prototype_or_initial_map()->IsMap();
3772 }
3773
3774
3775 bool JSFunction::has_instance_prototype() {
3776   return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
3777 }
3778
3779
3780 bool JSFunction::has_prototype() {
3781   return map()->has_non_instance_prototype() || has_instance_prototype();
3782 }
3783
3784
3785 Object* JSFunction::instance_prototype() {
3786   ASSERT(has_instance_prototype());
3787   if (has_initial_map()) return initial_map()->prototype();
3788   // When there is no initial map and the prototype is a JSObject, the
3789   // initial map field is used for the prototype field.
3790   return prototype_or_initial_map();
3791 }
3792
3793
3794 Object* JSFunction::prototype() {
3795   ASSERT(has_prototype());
3796   // If the function's prototype property has been set to a non-JSObject
3797   // value, that value is stored in the constructor field of the map.
3798   if (map()->has_non_instance_prototype()) return map()->constructor();
3799   return instance_prototype();
3800 }
3801
3802 bool JSFunction::should_have_prototype() {
3803   return map()->function_with_prototype();
3804 }
3805
3806
3807 bool JSFunction::is_compiled() {
3808   return code() != GetIsolate()->builtins()->builtin(Builtins::kLazyCompile);
3809 }
3810
3811
3812 FixedArray* JSFunction::literals() {
3813   ASSERT(!shared()->bound());
3814   return literals_or_bindings();
3815 }
3816
3817
3818 void JSFunction::set_literals(FixedArray* literals) {
3819   ASSERT(!shared()->bound());
3820   set_literals_or_bindings(literals);
3821 }
3822
3823
3824 FixedArray* JSFunction::function_bindings() {
3825   ASSERT(shared()->bound());
3826   return literals_or_bindings();
3827 }
3828
3829
3830 void JSFunction::set_function_bindings(FixedArray* bindings) {
3831   ASSERT(shared()->bound());
3832   // Bound function literal may be initialized to the empty fixed array
3833   // before the bindings are set.
3834   ASSERT(bindings == GetHeap()->empty_fixed_array() ||
3835          bindings->map() == GetHeap()->fixed_cow_array_map());
3836   set_literals_or_bindings(bindings);
3837 }
3838
3839
3840 int JSFunction::NumberOfLiterals() {
3841   ASSERT(!shared()->bound());
3842   return literals()->length();
3843 }
3844
3845
3846 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
3847   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
3848   return READ_FIELD(this, OffsetOfFunctionWithId(id));
3849 }
3850
3851
3852 void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
3853                                               Object* value) {
3854   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
3855   WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
3856   WRITE_BARRIER(GetHeap(), this, OffsetOfFunctionWithId(id), value);
3857 }
3858
3859
3860 Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
3861   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
3862   return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
3863 }
3864
3865
3866 void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
3867                                                    Code* value) {
3868   ASSERT(id < kJSBuiltinsCount);  // id is unsigned.
3869   WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
3870   ASSERT(!HEAP->InNewSpace(value));
3871 }
3872
3873
3874 ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
3875 ACCESSORS(JSProxy, hash, Object, kHashOffset)
3876 ACCESSORS(JSFunctionProxy, call_trap, Object, kCallTrapOffset)
3877 ACCESSORS(JSFunctionProxy, construct_trap, Object, kConstructTrapOffset)
3878
3879
3880 void JSProxy::InitializeBody(int object_size, Object* value) {
3881   ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
3882   for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
3883     WRITE_FIELD(this, offset, value);
3884   }
3885 }
3886
3887
3888 ACCESSORS(JSSet, table, Object, kTableOffset)
3889 ACCESSORS(JSMap, table, Object, kTableOffset)
3890 ACCESSORS(JSWeakMap, table, Object, kTableOffset)
3891 ACCESSORS(JSWeakMap, next, Object, kNextOffset)
3892
3893
3894 ObjectHashTable* JSWeakMap::unchecked_table() {
3895   return reinterpret_cast<ObjectHashTable*>(READ_FIELD(this, kTableOffset));
3896 }
3897
3898
3899 Address Foreign::foreign_address() {
3900   return AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignAddressOffset));
3901 }
3902
3903
3904 void Foreign::set_foreign_address(Address value) {
3905   WRITE_INTPTR_FIELD(this, kForeignAddressOffset, OffsetFrom(value));
3906 }
3907
3908
3909 ACCESSORS(JSValue, value, Object, kValueOffset)
3910
3911
3912 JSValue* JSValue::cast(Object* obj) {
3913   ASSERT(obj->IsJSValue());
3914   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
3915   return reinterpret_cast<JSValue*>(obj);
3916 }
3917
3918
3919 ACCESSORS(JSMessageObject, type, String, kTypeOffset)
3920 ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
3921 ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
3922 ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
3923 ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
3924 SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
3925 SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
3926
3927
3928 JSMessageObject* JSMessageObject::cast(Object* obj) {
3929   ASSERT(obj->IsJSMessageObject());
3930   ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
3931   return reinterpret_cast<JSMessageObject*>(obj);
3932 }
3933
3934
3935 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
3936 ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
3937 ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
3938 ACCESSORS(Code, next_code_flushing_candidate,
3939           Object, kNextCodeFlushingCandidateOffset)
3940
3941
3942 byte* Code::instruction_start()  {
3943   return FIELD_ADDR(this, kHeaderSize);
3944 }
3945
3946
3947 byte* Code::instruction_end()  {
3948   return instruction_start() + instruction_size();
3949 }
3950
3951
3952 int Code::body_size() {
3953   return RoundUp(instruction_size(), kObjectAlignment);
3954 }
3955
3956
3957 FixedArray* Code::unchecked_deoptimization_data() {
3958   return reinterpret_cast<FixedArray*>(
3959       READ_FIELD(this, kDeoptimizationDataOffset));
3960 }
3961
3962
3963 ByteArray* Code::unchecked_relocation_info() {
3964   return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
3965 }
3966
3967
3968 byte* Code::relocation_start() {
3969   return unchecked_relocation_info()->GetDataStartAddress();
3970 }
3971
3972
3973 int Code::relocation_size() {
3974   return unchecked_relocation_info()->length();
3975 }
3976
3977
3978 byte* Code::entry() {
3979   return instruction_start();
3980 }
3981
3982
3983 bool Code::contains(byte* inner_pointer) {
3984   return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
3985 }
3986
3987
3988 ACCESSORS(JSArray, length, Object, kLengthOffset)
3989
3990
3991 ACCESSORS(JSRegExp, data, Object, kDataOffset)
3992
3993
3994 JSRegExp::Type JSRegExp::TypeTag() {
3995   Object* data = this->data();
3996   if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
3997   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
3998   return static_cast<JSRegExp::Type>(smi->value());
3999 }
4000
4001
4002 JSRegExp::Type JSRegExp::TypeTagUnchecked() {
4003   Smi* smi = Smi::cast(DataAtUnchecked(kTagIndex));
4004   return static_cast<JSRegExp::Type>(smi->value());
4005 }
4006
4007
4008 int JSRegExp::CaptureCount() {
4009   switch (TypeTag()) {
4010     case ATOM:
4011       return 0;
4012     case IRREGEXP:
4013       return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
4014     default:
4015       UNREACHABLE();
4016       return -1;
4017   }
4018 }
4019
4020
4021 JSRegExp::Flags JSRegExp::GetFlags() {
4022   ASSERT(this->data()->IsFixedArray());
4023   Object* data = this->data();
4024   Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
4025   return Flags(smi->value());
4026 }
4027
4028
4029 String* JSRegExp::Pattern() {
4030   ASSERT(this->data()->IsFixedArray());
4031   Object* data = this->data();
4032   String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
4033   return pattern;
4034 }
4035
4036
4037 Object* JSRegExp::DataAt(int index) {
4038   ASSERT(TypeTag() != NOT_COMPILED);
4039   return FixedArray::cast(data())->get(index);
4040 }
4041
4042
4043 Object* JSRegExp::DataAtUnchecked(int index) {
4044   FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4045   int offset = FixedArray::kHeaderSize + index * kPointerSize;
4046   return READ_FIELD(fa, offset);
4047 }
4048
4049
4050 void JSRegExp::SetDataAt(int index, Object* value) {
4051   ASSERT(TypeTag() != NOT_COMPILED);
4052   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
4053   FixedArray::cast(data())->set(index, value);
4054 }
4055
4056
4057 void JSRegExp::SetDataAtUnchecked(int index, Object* value, Heap* heap) {
4058   ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
4059   FixedArray* fa = reinterpret_cast<FixedArray*>(data());
4060   if (value->IsSmi()) {
4061     fa->set_unchecked(index, Smi::cast(value));
4062   } else {
4063     // We only do this during GC, so we don't need to notify the write barrier.
4064     fa->set_unchecked(heap, index, value, SKIP_WRITE_BARRIER);
4065   }
4066 }
4067
4068
4069 ElementsKind JSObject::GetElementsKind() {
4070   ElementsKind kind = map()->elements_kind();
4071 #if DEBUG
4072   FixedArrayBase* fixed_array =
4073       reinterpret_cast<FixedArrayBase*>(READ_FIELD(this, kElementsOffset));
4074   Map* map = fixed_array->map();
4075     ASSERT(((kind == FAST_ELEMENTS || kind == FAST_SMI_ONLY_ELEMENTS) &&
4076             (map == GetHeap()->fixed_array_map() ||
4077              map == GetHeap()->fixed_cow_array_map())) ||
4078            (kind == FAST_DOUBLE_ELEMENTS &&
4079             fixed_array->IsFixedDoubleArray()) ||
4080            (kind == DICTIONARY_ELEMENTS &&
4081             fixed_array->IsFixedArray() &&
4082             fixed_array->IsDictionary()) ||
4083            (kind > DICTIONARY_ELEMENTS));
4084     ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
4085            (elements()->IsFixedArray() && elements()->length() >= 2));
4086 #endif
4087   return kind;
4088 }
4089
4090
4091 ElementsAccessor* JSObject::GetElementsAccessor() {
4092   return ElementsAccessor::ForKind(GetElementsKind());
4093 }
4094
4095
4096 bool JSObject::HasFastElements() {
4097   return GetElementsKind() == FAST_ELEMENTS;
4098 }
4099
4100
4101 bool JSObject::HasFastSmiOnlyElements() {
4102   return GetElementsKind() == FAST_SMI_ONLY_ELEMENTS;
4103 }
4104
4105
4106 bool JSObject::HasFastTypeElements() {
4107   ElementsKind elements_kind = GetElementsKind();
4108   return elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4109       elements_kind == FAST_ELEMENTS;
4110 }
4111
4112
4113 bool JSObject::HasFastDoubleElements() {
4114   return GetElementsKind() == FAST_DOUBLE_ELEMENTS;
4115 }
4116
4117
4118 bool JSObject::HasDictionaryElements() {
4119   return GetElementsKind() == DICTIONARY_ELEMENTS;
4120 }
4121
4122
4123 bool JSObject::HasNonStrictArgumentsElements() {
4124   return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
4125 }
4126
4127
4128 bool JSObject::HasExternalArrayElements() {
4129   HeapObject* array = elements();
4130   ASSERT(array != NULL);
4131   return array->IsExternalArray();
4132 }
4133
4134
4135 #define EXTERNAL_ELEMENTS_CHECK(name, type)          \
4136 bool JSObject::HasExternal##name##Elements() {       \
4137   HeapObject* array = elements();                    \
4138   ASSERT(array != NULL);                             \
4139   if (!array->IsHeapObject())                        \
4140     return false;                                    \
4141   return array->map()->instance_type() == type;      \
4142 }
4143
4144
4145 EXTERNAL_ELEMENTS_CHECK(Byte, EXTERNAL_BYTE_ARRAY_TYPE)
4146 EXTERNAL_ELEMENTS_CHECK(UnsignedByte, EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE)
4147 EXTERNAL_ELEMENTS_CHECK(Short, EXTERNAL_SHORT_ARRAY_TYPE)
4148 EXTERNAL_ELEMENTS_CHECK(UnsignedShort,
4149                         EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE)
4150 EXTERNAL_ELEMENTS_CHECK(Int, EXTERNAL_INT_ARRAY_TYPE)
4151 EXTERNAL_ELEMENTS_CHECK(UnsignedInt,
4152                         EXTERNAL_UNSIGNED_INT_ARRAY_TYPE)
4153 EXTERNAL_ELEMENTS_CHECK(Float,
4154                         EXTERNAL_FLOAT_ARRAY_TYPE)
4155 EXTERNAL_ELEMENTS_CHECK(Double,
4156                         EXTERNAL_DOUBLE_ARRAY_TYPE)
4157 EXTERNAL_ELEMENTS_CHECK(Pixel, EXTERNAL_PIXEL_ARRAY_TYPE)
4158
4159
4160 bool JSObject::HasNamedInterceptor() {
4161   return map()->has_named_interceptor();
4162 }
4163
4164
4165 bool JSObject::HasIndexedInterceptor() {
4166   return map()->has_indexed_interceptor();
4167 }
4168
4169
4170 bool JSObject::AllowsSetElementsLength() {
4171   bool result = elements()->IsFixedArray() ||
4172       elements()->IsFixedDoubleArray();
4173   ASSERT(result == !HasExternalArrayElements());
4174   return result;
4175 }
4176
4177
4178 MaybeObject* JSObject::EnsureWritableFastElements() {
4179   ASSERT(HasFastTypeElements());
4180   FixedArray* elems = FixedArray::cast(elements());
4181   Isolate* isolate = GetIsolate();
4182   if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
4183   Object* writable_elems;
4184   { MaybeObject* maybe_writable_elems = isolate->heap()->CopyFixedArrayWithMap(
4185       elems, isolate->heap()->fixed_array_map());
4186     if (!maybe_writable_elems->ToObject(&writable_elems)) {
4187       return maybe_writable_elems;
4188     }
4189   }
4190   set_elements(FixedArray::cast(writable_elems));
4191   isolate->counters()->cow_arrays_converted()->Increment();
4192   return writable_elems;
4193 }
4194
4195
4196 StringDictionary* JSObject::property_dictionary() {
4197   ASSERT(!HasFastProperties());
4198   return StringDictionary::cast(properties());
4199 }
4200
4201
4202 NumberDictionary* JSObject::element_dictionary() {
4203   ASSERT(HasDictionaryElements());
4204   return NumberDictionary::cast(elements());
4205 }
4206
4207
4208 bool String::IsHashFieldComputed(uint32_t field) {
4209   return (field & kHashNotComputedMask) == 0;
4210 }
4211
4212
4213 bool String::HasHashCode() {
4214   return IsHashFieldComputed(hash_field());
4215 }
4216
4217
4218 uint32_t String::Hash() {
4219   // Fast case: has hash code already been computed?
4220   uint32_t field = hash_field();
4221   if (IsHashFieldComputed(field)) return field >> kHashShift;
4222   // Slow case: compute hash code and set it.
4223   return ComputeAndSetHash();
4224 }
4225
4226
4227 StringHasher::StringHasher(int length)
4228   : length_(length),
4229     raw_running_hash_(0),
4230     array_index_(0),
4231     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
4232     is_first_char_(true),
4233     is_valid_(true) { }
4234
4235
4236 bool StringHasher::has_trivial_hash() {
4237   return length_ > String::kMaxHashCalcLength;
4238 }
4239
4240
4241 void StringHasher::AddCharacter(uc32 c) {
4242   // Use the Jenkins one-at-a-time hash function to update the hash
4243   // for the given character.
4244   raw_running_hash_ += c;
4245   raw_running_hash_ += (raw_running_hash_ << 10);
4246   raw_running_hash_ ^= (raw_running_hash_ >> 6);
4247   // Incremental array index computation.
4248   if (is_array_index_) {
4249     if (c < '0' || c > '9') {
4250       is_array_index_ = false;
4251     } else {
4252       int d = c - '0';
4253       if (is_first_char_) {
4254         is_first_char_ = false;
4255         if (c == '0' && length_ > 1) {
4256           is_array_index_ = false;
4257           return;
4258         }
4259       }
4260       if (array_index_ > 429496729U - ((d + 2) >> 3)) {
4261         is_array_index_ = false;
4262       } else {
4263         array_index_ = array_index_ * 10 + d;
4264       }
4265     }
4266   }
4267 }
4268
4269
4270 void StringHasher::AddCharacterNoIndex(uc32 c) {
4271   ASSERT(!is_array_index());
4272   raw_running_hash_ += c;
4273   raw_running_hash_ += (raw_running_hash_ << 10);
4274   raw_running_hash_ ^= (raw_running_hash_ >> 6);
4275 }
4276
4277
4278 uint32_t StringHasher::GetHash() {
4279   // Get the calculated raw hash value and do some more bit ops to distribute
4280   // the hash further. Ensure that we never return zero as the hash value.
4281   uint32_t result = raw_running_hash_;
4282   result += (result << 3);
4283   result ^= (result >> 11);
4284   result += (result << 15);
4285   if (result == 0) {
4286     result = 27;
4287   }
4288   return result;
4289 }
4290
4291
4292 template <typename schar>
4293 uint32_t HashSequentialString(const schar* chars, int length) {
4294   StringHasher hasher(length);
4295   if (!hasher.has_trivial_hash()) {
4296     int i;
4297     for (i = 0; hasher.is_array_index() && (i < length); i++) {
4298       hasher.AddCharacter(chars[i]);
4299     }
4300     for (; i < length; i++) {
4301       hasher.AddCharacterNoIndex(chars[i]);
4302     }
4303   }
4304   return hasher.GetHashField();
4305 }
4306
4307
4308 bool String::AsArrayIndex(uint32_t* index) {
4309   uint32_t field = hash_field();
4310   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
4311     return false;
4312   }
4313   return SlowAsArrayIndex(index);
4314 }
4315
4316
4317 Object* JSReceiver::GetPrototype() {
4318   return HeapObject::cast(this)->map()->prototype();
4319 }
4320
4321
4322 bool JSReceiver::HasProperty(String* name) {
4323   if (IsJSProxy()) {
4324     return JSProxy::cast(this)->HasPropertyWithHandler(name);
4325   }
4326   return GetPropertyAttribute(name) != ABSENT;
4327 }
4328
4329
4330 bool JSReceiver::HasLocalProperty(String* name) {
4331   if (IsJSProxy()) {
4332     return JSProxy::cast(this)->HasPropertyWithHandler(name);
4333   }
4334   return GetLocalPropertyAttribute(name) != ABSENT;
4335 }
4336
4337
4338 PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
4339   return GetPropertyAttributeWithReceiver(this, key);
4340 }
4341
4342 // TODO(504): this may be useful in other places too where JSGlobalProxy
4343 // is used.
4344 Object* JSObject::BypassGlobalProxy() {
4345   if (IsJSGlobalProxy()) {
4346     Object* proto = GetPrototype();
4347     if (proto->IsNull()) return GetHeap()->undefined_value();
4348     ASSERT(proto->IsJSGlobalObject());
4349     return proto;
4350   }
4351   return this;
4352 }
4353
4354
4355 MaybeObject* JSReceiver::GetIdentityHash(CreationFlag flag) {
4356   return IsJSProxy()
4357       ? JSProxy::cast(this)->GetIdentityHash(flag)
4358       : JSObject::cast(this)->GetIdentityHash(flag);
4359 }
4360
4361
4362 bool JSReceiver::HasElement(uint32_t index) {
4363   if (IsJSProxy()) {
4364     return JSProxy::cast(this)->HasElementWithHandler(index);
4365   }
4366   return JSObject::cast(this)->HasElementWithReceiver(this, index);
4367 }
4368
4369
4370 bool AccessorInfo::all_can_read() {
4371   return BooleanBit::get(flag(), kAllCanReadBit);
4372 }
4373
4374
4375 void AccessorInfo::set_all_can_read(bool value) {
4376   set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
4377 }
4378
4379
4380 bool AccessorInfo::all_can_write() {
4381   return BooleanBit::get(flag(), kAllCanWriteBit);
4382 }
4383
4384
4385 void AccessorInfo::set_all_can_write(bool value) {
4386   set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
4387 }
4388
4389
4390 bool AccessorInfo::prohibits_overwriting() {
4391   return BooleanBit::get(flag(), kProhibitsOverwritingBit);
4392 }
4393
4394
4395 void AccessorInfo::set_prohibits_overwriting(bool value) {
4396   set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
4397 }
4398
4399
4400 PropertyAttributes AccessorInfo::property_attributes() {
4401   return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
4402 }
4403
4404
4405 void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
4406   set_flag(Smi::FromInt(AttributesField::update(flag()->value(), attributes)));
4407 }
4408
4409
4410 template<typename Shape, typename Key>
4411 void Dictionary<Shape, Key>::SetEntry(int entry,
4412                                       Object* key,
4413                                       Object* value) {
4414   SetEntry(entry, key, value, PropertyDetails(Smi::FromInt(0)));
4415 }
4416
4417
4418 template<typename Shape, typename Key>
4419 void Dictionary<Shape, Key>::SetEntry(int entry,
4420                                       Object* key,
4421                                       Object* value,
4422                                       PropertyDetails details) {
4423   ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
4424   int index = HashTable<Shape, Key>::EntryToIndex(entry);
4425   AssertNoAllocation no_gc;
4426   WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
4427   FixedArray::set(index, key, mode);
4428   FixedArray::set(index+1, value, mode);
4429   FixedArray::set(index+2, details.AsSmi());
4430 }
4431
4432
4433 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
4434   ASSERT(other->IsNumber());
4435   return key == static_cast<uint32_t>(other->Number());
4436 }
4437
4438
4439 uint32_t NumberDictionaryShape::Hash(uint32_t key) {
4440   return ComputeIntegerHash(key);
4441 }
4442
4443
4444 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
4445   ASSERT(other->IsNumber());
4446   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
4447 }
4448
4449
4450 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
4451   return Isolate::Current()->heap()->NumberFromUint32(key);
4452 }
4453
4454
4455 bool StringDictionaryShape::IsMatch(String* key, Object* other) {
4456   // We know that all entries in a hash table had their hash keys created.
4457   // Use that knowledge to have fast failure.
4458   if (key->Hash() != String::cast(other)->Hash()) return false;
4459   return key->Equals(String::cast(other));
4460 }
4461
4462
4463 uint32_t StringDictionaryShape::Hash(String* key) {
4464   return key->Hash();
4465 }
4466
4467
4468 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
4469   return String::cast(other)->Hash();
4470 }
4471
4472
4473 MaybeObject* StringDictionaryShape::AsObject(String* key) {
4474   return key;
4475 }
4476
4477
4478 template <int entrysize>
4479 bool ObjectHashTableShape<entrysize>::IsMatch(Object* key, Object* other) {
4480   return key->SameValue(other);
4481 }
4482
4483
4484 template <int entrysize>
4485 uint32_t ObjectHashTableShape<entrysize>::Hash(Object* key) {
4486   ASSERT(!key->IsUndefined() && !key->IsNull());
4487   MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
4488   return Smi::cast(maybe_hash->ToObjectChecked())->value();
4489 }
4490
4491
4492 template <int entrysize>
4493 uint32_t ObjectHashTableShape<entrysize>::HashForObject(Object* key,
4494                                                         Object* other) {
4495   ASSERT(!other->IsUndefined() && !other->IsNull());
4496   MaybeObject* maybe_hash = other->GetHash(OMIT_CREATION);
4497   return Smi::cast(maybe_hash->ToObjectChecked())->value();
4498 }
4499
4500
4501 template <int entrysize>
4502 MaybeObject* ObjectHashTableShape<entrysize>::AsObject(Object* key) {
4503   return key;
4504 }
4505
4506
4507 void ObjectHashTable::RemoveEntry(int entry) {
4508   RemoveEntry(entry, GetHeap());
4509 }
4510
4511
4512 void Map::ClearCodeCache(Heap* heap) {
4513   // No write barrier is needed since empty_fixed_array is not in new space.
4514   // Please note this function is used during marking:
4515   //  - MarkCompactCollector::MarkUnmarkedObject
4516   ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
4517   WRITE_FIELD(this, kCodeCacheOffset, heap->raw_unchecked_empty_fixed_array());
4518 }
4519
4520
4521 void JSArray::EnsureSize(int required_size) {
4522   ASSERT(HasFastTypeElements());
4523   FixedArray* elts = FixedArray::cast(elements());
4524   const int kArraySizeThatFitsComfortablyInNewSpace = 128;
4525   if (elts->length() < required_size) {
4526     // Doubling in size would be overkill, but leave some slack to avoid
4527     // constantly growing.
4528     Expand(required_size + (required_size >> 3));
4529     // It's a performance benefit to keep a frequently used array in new-space.
4530   } else if (!GetHeap()->new_space()->Contains(elts) &&
4531              required_size < kArraySizeThatFitsComfortablyInNewSpace) {
4532     // Expand will allocate a new backing store in new space even if the size
4533     // we asked for isn't larger than what we had before.
4534     Expand(required_size);
4535   }
4536 }
4537
4538
4539 void JSArray::set_length(Smi* length) {
4540   // Don't need a write barrier for a Smi.
4541   set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
4542 }
4543
4544
4545 MaybeObject* JSArray::SetContent(FixedArray* storage) {
4546   MaybeObject* maybe_object = EnsureCanContainElements(storage);
4547   if (maybe_object->IsFailure()) return maybe_object;
4548   set_length(Smi::FromInt(storage->length()));
4549   set_elements(storage);
4550   return this;
4551 }
4552
4553
4554 MaybeObject* FixedArray::Copy() {
4555   if (length() == 0) return this;
4556   return GetHeap()->CopyFixedArray(this);
4557 }
4558
4559
4560 MaybeObject* FixedDoubleArray::Copy() {
4561   if (length() == 0) return this;
4562   return GetHeap()->CopyFixedDoubleArray(this);
4563 }
4564
4565
4566 Relocatable::Relocatable(Isolate* isolate) {
4567   ASSERT(isolate == Isolate::Current());
4568   isolate_ = isolate;
4569   prev_ = isolate->relocatable_top();
4570   isolate->set_relocatable_top(this);
4571 }
4572
4573
4574 Relocatable::~Relocatable() {
4575   ASSERT(isolate_ == Isolate::Current());
4576   ASSERT_EQ(isolate_->relocatable_top(), this);
4577   isolate_->set_relocatable_top(prev_);
4578 }
4579
4580
4581 int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
4582   return map->instance_size();
4583 }
4584
4585
4586 void Foreign::ForeignIterateBody(ObjectVisitor* v) {
4587   v->VisitExternalReference(
4588       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4589 }
4590
4591
4592 template<typename StaticVisitor>
4593 void Foreign::ForeignIterateBody() {
4594   StaticVisitor::VisitExternalReference(
4595       reinterpret_cast<Address*>(FIELD_ADDR(this, kForeignAddressOffset)));
4596 }
4597
4598
4599 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
4600   typedef v8::String::ExternalAsciiStringResource Resource;
4601   v->VisitExternalAsciiString(
4602       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4603 }
4604
4605
4606 template<typename StaticVisitor>
4607 void ExternalAsciiString::ExternalAsciiStringIterateBody() {
4608   typedef v8::String::ExternalAsciiStringResource Resource;
4609   StaticVisitor::VisitExternalAsciiString(
4610       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4611 }
4612
4613
4614 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
4615   typedef v8::String::ExternalStringResource Resource;
4616   v->VisitExternalTwoByteString(
4617       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4618 }
4619
4620
4621 template<typename StaticVisitor>
4622 void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
4623   typedef v8::String::ExternalStringResource Resource;
4624   StaticVisitor::VisitExternalTwoByteString(
4625       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
4626 }
4627
4628 #define SLOT_ADDR(obj, offset) \
4629   reinterpret_cast<Object**>((obj)->address() + offset)
4630
4631 template<int start_offset, int end_offset, int size>
4632 void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
4633     HeapObject* obj,
4634     ObjectVisitor* v) {
4635     v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
4636 }
4637
4638
4639 template<int start_offset>
4640 void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
4641                                                        int object_size,
4642                                                        ObjectVisitor* v) {
4643   v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
4644 }
4645
4646 #undef SLOT_ADDR
4647
4648
4649 #undef CAST_ACCESSOR
4650 #undef INT_ACCESSORS
4651 #undef SMI_ACCESSORS
4652 #undef ACCESSORS
4653 #undef FIELD_ADDR
4654 #undef READ_FIELD
4655 #undef WRITE_FIELD
4656 #undef WRITE_BARRIER
4657 #undef CONDITIONAL_WRITE_BARRIER
4658 #undef READ_MEMADDR_FIELD
4659 #undef WRITE_MEMADDR_FIELD
4660 #undef READ_DOUBLE_FIELD
4661 #undef WRITE_DOUBLE_FIELD
4662 #undef READ_INT_FIELD
4663 #undef WRITE_INT_FIELD
4664 #undef READ_SHORT_FIELD
4665 #undef WRITE_SHORT_FIELD
4666 #undef READ_BYTE_FIELD
4667 #undef WRITE_BYTE_FIELD
4668
4669
4670 } }  // namespace v8::internal
4671
4672 #endif  // V8_OBJECTS_INL_H_