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