objects-inl.h revision 9ac36c9faca11611ada13b4054edbaa0738661d0
1// Copyright 2006-2008 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 "objects.h"
39#include "contexts.h"
40#include "conversions-inl.h"
41#include "heap.h"
42#include "memory.h"
43#include "property.h"
44#include "spaces.h"
45
46namespace v8 {
47namespace internal {
48
49PropertyDetails::PropertyDetails(Smi* smi) {
50  value_ = smi->value();
51}
52
53
54Smi* PropertyDetails::AsSmi() {
55  return Smi::FromInt(value_);
56}
57
58
59PropertyDetails PropertyDetails::AsDeleted() {
60  PropertyDetails d(DONT_ENUM, NORMAL);
61  Smi* smi = Smi::FromInt(AsSmi()->value() | DeletedField::encode(1));
62  return PropertyDetails(smi);
63}
64
65
66#define CAST_ACCESSOR(type)                     \
67  type* type::cast(Object* object) {            \
68    ASSERT(object->Is##type());                 \
69    return reinterpret_cast<type*>(object);     \
70  }
71
72
73#define INT_ACCESSORS(holder, name, offset)                             \
74  int holder::name() { return READ_INT_FIELD(this, offset); }           \
75  void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
76
77
78#define ACCESSORS(holder, name, type, offset)                           \
79  type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
80  void holder::set_##name(type* value, WriteBarrierMode mode) {         \
81    WRITE_FIELD(this, offset, value);                                   \
82    CONDITIONAL_WRITE_BARRIER(this, offset, mode);                      \
83  }
84
85
86
87#define SMI_ACCESSORS(holder, name, offset)             \
88  int holder::name() {                                  \
89    Object* value = READ_FIELD(this, offset);           \
90    return Smi::cast(value)->value();                   \
91  }                                                     \
92  void holder::set_##name(int value) {                  \
93    WRITE_FIELD(this, offset, Smi::FromInt(value));     \
94  }
95
96
97#define BOOL_GETTER(holder, field, name, offset)           \
98  bool holder::name() {                                    \
99    return BooleanBit::get(field(), offset);               \
100  }                                                        \
101
102
103#define BOOL_ACCESSORS(holder, field, name, offset)        \
104  bool holder::name() {                                    \
105    return BooleanBit::get(field(), offset);               \
106  }                                                        \
107  void holder::set_##name(bool value) {                    \
108    set_##field(BooleanBit::set(field(), offset, value));  \
109  }
110
111
112bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
113  // There is a constraint on the object; check.
114  if (!this->IsJSObject()) return false;
115  // Fetch the constructor function of the object.
116  Object* cons_obj = JSObject::cast(this)->map()->constructor();
117  if (!cons_obj->IsJSFunction()) return false;
118  JSFunction* fun = JSFunction::cast(cons_obj);
119  // Iterate through the chain of inheriting function templates to
120  // see if the required one occurs.
121  for (Object* type = fun->shared()->function_data();
122       type->IsFunctionTemplateInfo();
123       type = FunctionTemplateInfo::cast(type)->parent_template()) {
124    if (type == expected) return true;
125  }
126  // Didn't find the required type in the inheritance chain.
127  return false;
128}
129
130
131bool Object::IsSmi() {
132  return HAS_SMI_TAG(this);
133}
134
135
136bool Object::IsHeapObject() {
137  return Internals::HasHeapObjectTag(this);
138}
139
140
141bool Object::IsHeapNumber() {
142  return Object::IsHeapObject()
143    && HeapObject::cast(this)->map()->instance_type() == HEAP_NUMBER_TYPE;
144}
145
146
147bool Object::IsString() {
148  return Object::IsHeapObject()
149    && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
150}
151
152
153bool Object::IsSymbol() {
154  if (!this->IsHeapObject()) return false;
155  uint32_t type = HeapObject::cast(this)->map()->instance_type();
156  // Because the symbol tag is non-zero and no non-string types have the
157  // symbol bit set we can test for symbols with a very simple test
158  // operation.
159  ASSERT(kSymbolTag != 0);
160  ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
161  return (type & kIsSymbolMask) != 0;
162}
163
164
165bool Object::IsConsString() {
166  if (!this->IsHeapObject()) return false;
167  uint32_t type = HeapObject::cast(this)->map()->instance_type();
168  return (type & (kIsNotStringMask | kStringRepresentationMask)) ==
169         (kStringTag | kConsStringTag);
170}
171
172
173bool Object::IsSeqString() {
174  if (!IsString()) return false;
175  return StringShape(String::cast(this)).IsSequential();
176}
177
178
179bool Object::IsSeqAsciiString() {
180  if (!IsString()) return false;
181  return StringShape(String::cast(this)).IsSequential() &&
182         String::cast(this)->IsAsciiRepresentation();
183}
184
185
186bool Object::IsSeqTwoByteString() {
187  if (!IsString()) return false;
188  return StringShape(String::cast(this)).IsSequential() &&
189         String::cast(this)->IsTwoByteRepresentation();
190}
191
192
193bool Object::IsExternalString() {
194  if (!IsString()) return false;
195  return StringShape(String::cast(this)).IsExternal();
196}
197
198
199bool Object::IsExternalAsciiString() {
200  if (!IsString()) return false;
201  return StringShape(String::cast(this)).IsExternal() &&
202         String::cast(this)->IsAsciiRepresentation();
203}
204
205
206bool Object::IsExternalTwoByteString() {
207  if (!IsString()) return false;
208  return StringShape(String::cast(this)).IsExternal() &&
209         String::cast(this)->IsTwoByteRepresentation();
210}
211
212
213StringShape::StringShape(String* str)
214  : type_(str->map()->instance_type()) {
215  set_valid();
216  ASSERT((type_ & kIsNotStringMask) == kStringTag);
217}
218
219
220StringShape::StringShape(Map* map)
221  : type_(map->instance_type()) {
222  set_valid();
223  ASSERT((type_ & kIsNotStringMask) == kStringTag);
224}
225
226
227StringShape::StringShape(InstanceType t)
228  : type_(static_cast<uint32_t>(t)) {
229  set_valid();
230  ASSERT((type_ & kIsNotStringMask) == kStringTag);
231}
232
233
234bool StringShape::IsSymbol() {
235  ASSERT(valid());
236  ASSERT(kSymbolTag != 0);
237  return (type_ & kIsSymbolMask) != 0;
238}
239
240
241bool String::IsAsciiRepresentation() {
242  uint32_t type = map()->instance_type();
243  return (type & kStringEncodingMask) == kAsciiStringTag;
244}
245
246
247bool String::IsTwoByteRepresentation() {
248  uint32_t type = map()->instance_type();
249  return (type & kStringEncodingMask) == kTwoByteStringTag;
250}
251
252
253bool String::HasOnlyAsciiChars() {
254  uint32_t type = map()->instance_type();
255  return (type & kStringEncodingMask) == kAsciiStringTag ||
256         (type & kAsciiDataHintMask) == kAsciiDataHintTag;
257}
258
259
260bool StringShape::IsCons() {
261  return (type_ & kStringRepresentationMask) == kConsStringTag;
262}
263
264
265bool StringShape::IsExternal() {
266  return (type_ & kStringRepresentationMask) == kExternalStringTag;
267}
268
269
270bool StringShape::IsSequential() {
271  return (type_ & kStringRepresentationMask) == kSeqStringTag;
272}
273
274
275StringRepresentationTag StringShape::representation_tag() {
276  uint32_t tag = (type_ & kStringRepresentationMask);
277  return static_cast<StringRepresentationTag>(tag);
278}
279
280
281uint32_t StringShape::full_representation_tag() {
282  return (type_ & (kStringRepresentationMask | kStringEncodingMask));
283}
284
285
286STATIC_CHECK((kStringRepresentationMask | kStringEncodingMask) ==
287             Internals::kFullStringRepresentationMask);
288
289
290bool StringShape::IsSequentialAscii() {
291  return full_representation_tag() == (kSeqStringTag | kAsciiStringTag);
292}
293
294
295bool StringShape::IsSequentialTwoByte() {
296  return full_representation_tag() == (kSeqStringTag | kTwoByteStringTag);
297}
298
299
300bool StringShape::IsExternalAscii() {
301  return full_representation_tag() == (kExternalStringTag | kAsciiStringTag);
302}
303
304
305bool StringShape::IsExternalTwoByte() {
306  return full_representation_tag() == (kExternalStringTag | kTwoByteStringTag);
307}
308
309
310STATIC_CHECK((kExternalStringTag | kTwoByteStringTag) ==
311             Internals::kExternalTwoByteRepresentationTag);
312
313
314uc32 FlatStringReader::Get(int index) {
315  ASSERT(0 <= index && index <= length_);
316  if (is_ascii_) {
317    return static_cast<const byte*>(start_)[index];
318  } else {
319    return static_cast<const uc16*>(start_)[index];
320  }
321}
322
323
324bool Object::IsNumber() {
325  return IsSmi() || IsHeapNumber();
326}
327
328
329bool Object::IsByteArray() {
330  return Object::IsHeapObject()
331    && HeapObject::cast(this)->map()->instance_type() == BYTE_ARRAY_TYPE;
332}
333
334
335bool Object::IsPixelArray() {
336  return Object::IsHeapObject() &&
337      HeapObject::cast(this)->map()->instance_type() == PIXEL_ARRAY_TYPE;
338}
339
340
341bool Object::IsExternalArray() {
342  if (!Object::IsHeapObject())
343    return false;
344  InstanceType instance_type =
345      HeapObject::cast(this)->map()->instance_type();
346  return (instance_type >= FIRST_EXTERNAL_ARRAY_TYPE &&
347          instance_type <= LAST_EXTERNAL_ARRAY_TYPE);
348}
349
350
351bool Object::IsExternalByteArray() {
352  return Object::IsHeapObject() &&
353      HeapObject::cast(this)->map()->instance_type() ==
354      EXTERNAL_BYTE_ARRAY_TYPE;
355}
356
357
358bool Object::IsExternalUnsignedByteArray() {
359  return Object::IsHeapObject() &&
360      HeapObject::cast(this)->map()->instance_type() ==
361      EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE;
362}
363
364
365bool Object::IsExternalShortArray() {
366  return Object::IsHeapObject() &&
367      HeapObject::cast(this)->map()->instance_type() ==
368      EXTERNAL_SHORT_ARRAY_TYPE;
369}
370
371
372bool Object::IsExternalUnsignedShortArray() {
373  return Object::IsHeapObject() &&
374      HeapObject::cast(this)->map()->instance_type() ==
375      EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE;
376}
377
378
379bool Object::IsExternalIntArray() {
380  return Object::IsHeapObject() &&
381      HeapObject::cast(this)->map()->instance_type() ==
382      EXTERNAL_INT_ARRAY_TYPE;
383}
384
385
386bool Object::IsExternalUnsignedIntArray() {
387  return Object::IsHeapObject() &&
388      HeapObject::cast(this)->map()->instance_type() ==
389      EXTERNAL_UNSIGNED_INT_ARRAY_TYPE;
390}
391
392
393bool Object::IsExternalFloatArray() {
394  return Object::IsHeapObject() &&
395      HeapObject::cast(this)->map()->instance_type() ==
396      EXTERNAL_FLOAT_ARRAY_TYPE;
397}
398
399
400bool Object::IsFailure() {
401  return HAS_FAILURE_TAG(this);
402}
403
404
405bool Object::IsRetryAfterGC() {
406  return HAS_FAILURE_TAG(this)
407    && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
408}
409
410
411bool Object::IsOutOfMemoryFailure() {
412  return HAS_FAILURE_TAG(this)
413    && Failure::cast(this)->IsOutOfMemoryException();
414}
415
416
417bool Object::IsException() {
418  return this == Failure::Exception();
419}
420
421
422bool Object::IsJSObject() {
423  return IsHeapObject()
424    && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
425}
426
427
428bool Object::IsJSContextExtensionObject() {
429  return IsHeapObject()
430    && (HeapObject::cast(this)->map()->instance_type() ==
431        JS_CONTEXT_EXTENSION_OBJECT_TYPE);
432}
433
434
435bool Object::IsMap() {
436  return Object::IsHeapObject()
437    && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
438}
439
440
441bool Object::IsFixedArray() {
442  return Object::IsHeapObject()
443    && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
444}
445
446
447bool Object::IsDescriptorArray() {
448  return IsFixedArray();
449}
450
451
452bool Object::IsContext() {
453  return Object::IsHeapObject()
454    && (HeapObject::cast(this)->map() == Heap::context_map() ||
455        HeapObject::cast(this)->map() == Heap::catch_context_map() ||
456        HeapObject::cast(this)->map() == Heap::global_context_map());
457}
458
459
460bool Object::IsCatchContext() {
461  return Object::IsHeapObject()
462    && HeapObject::cast(this)->map() == Heap::catch_context_map();
463}
464
465
466bool Object::IsGlobalContext() {
467  return Object::IsHeapObject()
468    && HeapObject::cast(this)->map() == Heap::global_context_map();
469}
470
471
472bool Object::IsJSFunction() {
473  return Object::IsHeapObject()
474    && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
475}
476
477
478template <> inline bool Is<JSFunction>(Object* obj) {
479  return obj->IsJSFunction();
480}
481
482
483bool Object::IsCode() {
484  return Object::IsHeapObject()
485    && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
486}
487
488
489bool Object::IsOddball() {
490  return Object::IsHeapObject()
491    && HeapObject::cast(this)->map()->instance_type() == ODDBALL_TYPE;
492}
493
494
495bool Object::IsJSGlobalPropertyCell() {
496  return Object::IsHeapObject()
497      && HeapObject::cast(this)->map()->instance_type()
498      == JS_GLOBAL_PROPERTY_CELL_TYPE;
499}
500
501
502bool Object::IsSharedFunctionInfo() {
503  return Object::IsHeapObject() &&
504      (HeapObject::cast(this)->map()->instance_type() ==
505       SHARED_FUNCTION_INFO_TYPE);
506}
507
508
509bool Object::IsJSValue() {
510  return Object::IsHeapObject()
511    && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
512}
513
514
515bool Object::IsStringWrapper() {
516  return IsJSValue() && JSValue::cast(this)->value()->IsString();
517}
518
519
520bool Object::IsProxy() {
521  return Object::IsHeapObject()
522    && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
523}
524
525
526bool Object::IsBoolean() {
527  return IsTrue() || IsFalse();
528}
529
530
531bool Object::IsJSArray() {
532  return Object::IsHeapObject()
533    && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
534}
535
536
537bool Object::IsJSRegExp() {
538  return Object::IsHeapObject()
539    && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
540}
541
542
543template <> inline bool Is<JSArray>(Object* obj) {
544  return obj->IsJSArray();
545}
546
547
548bool Object::IsHashTable() {
549  return Object::IsHeapObject()
550    && HeapObject::cast(this)->map() == Heap::hash_table_map();
551}
552
553
554bool Object::IsDictionary() {
555  return IsHashTable() && this != Heap::symbol_table();
556}
557
558
559bool Object::IsSymbolTable() {
560  return IsHashTable() && this == Heap::raw_unchecked_symbol_table();
561}
562
563
564bool Object::IsJSFunctionResultCache() {
565  if (!IsFixedArray()) return false;
566  FixedArray* self = FixedArray::cast(this);
567  int length = self->length();
568  if (length < JSFunctionResultCache::kEntriesIndex) return false;
569  if ((length - JSFunctionResultCache::kEntriesIndex)
570      % JSFunctionResultCache::kEntrySize != 0) {
571    return false;
572  }
573#ifdef DEBUG
574  reinterpret_cast<JSFunctionResultCache*>(this)->JSFunctionResultCacheVerify();
575#endif
576  return true;
577}
578
579
580bool Object::IsNormalizedMapCache() {
581  if (!IsFixedArray()) return false;
582  if (FixedArray::cast(this)->length() != NormalizedMapCache::kEntries) {
583    return false;
584  }
585#ifdef DEBUG
586  reinterpret_cast<NormalizedMapCache*>(this)->NormalizedMapCacheVerify();
587#endif
588  return true;
589}
590
591
592bool Object::IsCompilationCacheTable() {
593  return IsHashTable();
594}
595
596
597bool Object::IsCodeCacheHashTable() {
598  return IsHashTable();
599}
600
601
602bool Object::IsMapCache() {
603  return IsHashTable();
604}
605
606
607bool Object::IsPrimitive() {
608  return IsOddball() || IsNumber() || IsString();
609}
610
611
612bool Object::IsJSGlobalProxy() {
613  bool result = IsHeapObject() &&
614                (HeapObject::cast(this)->map()->instance_type() ==
615                 JS_GLOBAL_PROXY_TYPE);
616  ASSERT(!result || IsAccessCheckNeeded());
617  return result;
618}
619
620
621bool Object::IsGlobalObject() {
622  if (!IsHeapObject()) return false;
623
624  InstanceType type = HeapObject::cast(this)->map()->instance_type();
625  return type == JS_GLOBAL_OBJECT_TYPE ||
626         type == JS_BUILTINS_OBJECT_TYPE;
627}
628
629
630bool Object::IsJSGlobalObject() {
631  return IsHeapObject() &&
632      (HeapObject::cast(this)->map()->instance_type() ==
633       JS_GLOBAL_OBJECT_TYPE);
634}
635
636
637bool Object::IsJSBuiltinsObject() {
638  return IsHeapObject() &&
639      (HeapObject::cast(this)->map()->instance_type() ==
640       JS_BUILTINS_OBJECT_TYPE);
641}
642
643
644bool Object::IsUndetectableObject() {
645  return IsHeapObject()
646    && HeapObject::cast(this)->map()->is_undetectable();
647}
648
649
650bool Object::IsAccessCheckNeeded() {
651  return IsHeapObject()
652    && HeapObject::cast(this)->map()->is_access_check_needed();
653}
654
655
656bool Object::IsStruct() {
657  if (!IsHeapObject()) return false;
658  switch (HeapObject::cast(this)->map()->instance_type()) {
659#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
660  STRUCT_LIST(MAKE_STRUCT_CASE)
661#undef MAKE_STRUCT_CASE
662    default: return false;
663  }
664}
665
666
667#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
668  bool Object::Is##Name() {                                      \
669    return Object::IsHeapObject()                                \
670      && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
671  }
672  STRUCT_LIST(MAKE_STRUCT_PREDICATE)
673#undef MAKE_STRUCT_PREDICATE
674
675
676bool Object::IsUndefined() {
677  return this == Heap::undefined_value();
678}
679
680
681bool Object::IsTheHole() {
682  return this == Heap::the_hole_value();
683}
684
685
686bool Object::IsNull() {
687  return this == Heap::null_value();
688}
689
690
691bool Object::IsTrue() {
692  return this == Heap::true_value();
693}
694
695
696bool Object::IsFalse() {
697  return this == Heap::false_value();
698}
699
700
701double Object::Number() {
702  ASSERT(IsNumber());
703  return IsSmi()
704    ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
705    : reinterpret_cast<HeapNumber*>(this)->value();
706}
707
708
709
710Object* Object::ToSmi() {
711  if (IsSmi()) return this;
712  if (IsHeapNumber()) {
713    double value = HeapNumber::cast(this)->value();
714    int int_value = FastD2I(value);
715    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
716      return Smi::FromInt(int_value);
717    }
718  }
719  return Failure::Exception();
720}
721
722
723bool Object::HasSpecificClassOf(String* name) {
724  return this->IsJSObject() && (JSObject::cast(this)->class_name() == name);
725}
726
727
728Object* Object::GetElement(uint32_t index) {
729  return GetElementWithReceiver(this, index);
730}
731
732
733Object* Object::GetProperty(String* key) {
734  PropertyAttributes attributes;
735  return GetPropertyWithReceiver(this, key, &attributes);
736}
737
738
739Object* Object::GetProperty(String* key, PropertyAttributes* attributes) {
740  return GetPropertyWithReceiver(this, key, attributes);
741}
742
743
744#define FIELD_ADDR(p, offset) \
745  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
746
747#define READ_FIELD(p, offset) \
748  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))
749
750#define WRITE_FIELD(p, offset, value) \
751  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
752
753
754#define WRITE_BARRIER(object, offset) \
755  Heap::RecordWrite(object->address(), offset);
756
757// CONDITIONAL_WRITE_BARRIER must be issued after the actual
758// write due to the assert validating the written value.
759#define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
760  if (mode == UPDATE_WRITE_BARRIER) { \
761    Heap::RecordWrite(object->address(), offset); \
762  } else { \
763    ASSERT(mode == SKIP_WRITE_BARRIER); \
764    ASSERT(Heap::InNewSpace(object) || \
765           !Heap::InNewSpace(READ_FIELD(object, offset)) || \
766           Page::FromAddress(object->address())->           \
767               IsRegionDirty(object->address() + offset));  \
768  }
769
770#define READ_DOUBLE_FIELD(p, offset) \
771  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))
772
773#define WRITE_DOUBLE_FIELD(p, offset, value) \
774  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)
775
776#define READ_INT_FIELD(p, offset) \
777  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)))
778
779#define WRITE_INT_FIELD(p, offset, value) \
780  (*reinterpret_cast<int*>(FIELD_ADDR(p, offset)) = value)
781
782#define READ_INTPTR_FIELD(p, offset) \
783  (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)))
784
785#define WRITE_INTPTR_FIELD(p, offset, value) \
786  (*reinterpret_cast<intptr_t*>(FIELD_ADDR(p, offset)) = value)
787
788#define READ_UINT32_FIELD(p, offset) \
789  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)))
790
791#define WRITE_UINT32_FIELD(p, offset, value) \
792  (*reinterpret_cast<uint32_t*>(FIELD_ADDR(p, offset)) = value)
793
794#define READ_SHORT_FIELD(p, offset) \
795  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)))
796
797#define WRITE_SHORT_FIELD(p, offset, value) \
798  (*reinterpret_cast<uint16_t*>(FIELD_ADDR(p, offset)) = value)
799
800#define READ_BYTE_FIELD(p, offset) \
801  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))
802
803#define WRITE_BYTE_FIELD(p, offset, value) \
804  (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)
805
806
807Object** HeapObject::RawField(HeapObject* obj, int byte_offset) {
808  return &READ_FIELD(obj, byte_offset);
809}
810
811
812int Smi::value() {
813  return Internals::SmiValue(this);
814}
815
816
817Smi* Smi::FromInt(int value) {
818  ASSERT(Smi::IsValid(value));
819  int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
820  intptr_t tagged_value =
821      (static_cast<intptr_t>(value) << smi_shift_bits) | kSmiTag;
822  return reinterpret_cast<Smi*>(tagged_value);
823}
824
825
826Smi* Smi::FromIntptr(intptr_t value) {
827  ASSERT(Smi::IsValid(value));
828  int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
829  return reinterpret_cast<Smi*>((value << smi_shift_bits) | kSmiTag);
830}
831
832
833Failure::Type Failure::type() const {
834  return static_cast<Type>(value() & kFailureTypeTagMask);
835}
836
837
838bool Failure::IsInternalError() const {
839  return type() == INTERNAL_ERROR;
840}
841
842
843bool Failure::IsOutOfMemoryException() const {
844  return type() == OUT_OF_MEMORY_EXCEPTION;
845}
846
847
848int Failure::requested() const {
849  const int kShiftBits =
850      kFailureTypeTagSize + kSpaceTagSize - kObjectAlignmentBits;
851  STATIC_ASSERT(kShiftBits >= 0);
852  ASSERT(type() == RETRY_AFTER_GC);
853  return static_cast<int>(value() >> kShiftBits);
854}
855
856
857AllocationSpace Failure::allocation_space() const {
858  ASSERT_EQ(RETRY_AFTER_GC, type());
859  return static_cast<AllocationSpace>((value() >> kFailureTypeTagSize)
860                                      & kSpaceTagMask);
861}
862
863
864Failure* Failure::InternalError() {
865  return Construct(INTERNAL_ERROR);
866}
867
868
869Failure* Failure::Exception() {
870  return Construct(EXCEPTION);
871}
872
873
874Failure* Failure::OutOfMemoryException() {
875  return Construct(OUT_OF_MEMORY_EXCEPTION);
876}
877
878
879intptr_t Failure::value() const {
880  return static_cast<intptr_t>(
881      reinterpret_cast<uintptr_t>(this) >> kFailureTagSize);
882}
883
884
885Failure* Failure::RetryAfterGC(int requested_bytes) {
886  // Assert that the space encoding fits in the three bytes allotted for it.
887  ASSERT((LAST_SPACE & ~kSpaceTagMask) == 0);
888  uintptr_t requested =
889      static_cast<uintptr_t>(requested_bytes >> kObjectAlignmentBits);
890  int tag_bits = kSpaceTagSize + kFailureTypeTagSize + kFailureTagSize;
891  if (((requested << tag_bits) >> tag_bits) != requested) {
892    // No room for entire requested size in the bits. Round down to
893    // maximally representable size.
894    requested = static_cast<intptr_t>(
895                    (~static_cast<uintptr_t>(0)) >> (tag_bits + 1));
896  }
897  int value = static_cast<int>(requested << kSpaceTagSize) | NEW_SPACE;
898  return Construct(RETRY_AFTER_GC, value);
899}
900
901
902Failure* Failure::Construct(Type type, intptr_t value) {
903  uintptr_t info =
904      (static_cast<uintptr_t>(value) << kFailureTypeTagSize) | type;
905  ASSERT(((info << kFailureTagSize) >> kFailureTagSize) == info);
906  return reinterpret_cast<Failure*>((info << kFailureTagSize) | kFailureTag);
907}
908
909
910bool Smi::IsValid(intptr_t value) {
911#ifdef DEBUG
912  bool in_range = (value >= kMinValue) && (value <= kMaxValue);
913#endif
914
915#ifdef V8_TARGET_ARCH_X64
916  // To be representable as a long smi, the value must be a 32-bit integer.
917  bool result = (value == static_cast<int32_t>(value));
918#else
919  // To be representable as an tagged small integer, the two
920  // most-significant bits of 'value' must be either 00 or 11 due to
921  // sign-extension. To check this we add 01 to the two
922  // most-significant bits, and check if the most-significant bit is 0
923  //
924  // CAUTION: The original code below:
925  // bool result = ((value + 0x40000000) & 0x80000000) == 0;
926  // may lead to incorrect results according to the C language spec, and
927  // in fact doesn't work correctly with gcc4.1.1 in some cases: The
928  // compiler may produce undefined results in case of signed integer
929  // overflow. The computation must be done w/ unsigned ints.
930  bool result = (static_cast<uintptr_t>(value + 0x40000000U) < 0x80000000U);
931#endif
932  ASSERT(result == in_range);
933  return result;
934}
935
936
937MapWord MapWord::FromMap(Map* map) {
938  return MapWord(reinterpret_cast<uintptr_t>(map));
939}
940
941
942Map* MapWord::ToMap() {
943  return reinterpret_cast<Map*>(value_);
944}
945
946
947bool MapWord::IsForwardingAddress() {
948  return HAS_SMI_TAG(reinterpret_cast<Object*>(value_));
949}
950
951
952MapWord MapWord::FromForwardingAddress(HeapObject* object) {
953  Address raw = reinterpret_cast<Address>(object) - kHeapObjectTag;
954  return MapWord(reinterpret_cast<uintptr_t>(raw));
955}
956
957
958HeapObject* MapWord::ToForwardingAddress() {
959  ASSERT(IsForwardingAddress());
960  return HeapObject::FromAddress(reinterpret_cast<Address>(value_));
961}
962
963
964bool MapWord::IsMarked() {
965  return (value_ & kMarkingMask) == 0;
966}
967
968
969void MapWord::SetMark() {
970  value_ &= ~kMarkingMask;
971}
972
973
974void MapWord::ClearMark() {
975  value_ |= kMarkingMask;
976}
977
978
979bool MapWord::IsOverflowed() {
980  return (value_ & kOverflowMask) != 0;
981}
982
983
984void MapWord::SetOverflow() {
985  value_ |= kOverflowMask;
986}
987
988
989void MapWord::ClearOverflow() {
990  value_ &= ~kOverflowMask;
991}
992
993
994MapWord MapWord::EncodeAddress(Address map_address, int offset) {
995  // Offset is the distance in live bytes from the first live object in the
996  // same page. The offset between two objects in the same page should not
997  // exceed the object area size of a page.
998  ASSERT(0 <= offset && offset < Page::kObjectAreaSize);
999
1000  uintptr_t compact_offset = offset >> kObjectAlignmentBits;
1001  ASSERT(compact_offset < (1 << kForwardingOffsetBits));
1002
1003  Page* map_page = Page::FromAddress(map_address);
1004  ASSERT_MAP_PAGE_INDEX(map_page->mc_page_index);
1005
1006  uintptr_t map_page_offset =
1007      map_page->Offset(map_address) >> kMapAlignmentBits;
1008
1009  uintptr_t encoding =
1010      (compact_offset << kForwardingOffsetShift) |
1011      (map_page_offset << kMapPageOffsetShift) |
1012      (map_page->mc_page_index << kMapPageIndexShift);
1013  return MapWord(encoding);
1014}
1015
1016
1017Address MapWord::DecodeMapAddress(MapSpace* map_space) {
1018  int map_page_index =
1019      static_cast<int>((value_ & kMapPageIndexMask) >> kMapPageIndexShift);
1020  ASSERT_MAP_PAGE_INDEX(map_page_index);
1021
1022  int map_page_offset = static_cast<int>(
1023      ((value_ & kMapPageOffsetMask) >> kMapPageOffsetShift) <<
1024      kMapAlignmentBits);
1025
1026  return (map_space->PageAddress(map_page_index) + map_page_offset);
1027}
1028
1029
1030int MapWord::DecodeOffset() {
1031  // The offset field is represented in the kForwardingOffsetBits
1032  // most-significant bits.
1033  uintptr_t offset = (value_ >> kForwardingOffsetShift) << kObjectAlignmentBits;
1034  ASSERT(offset < static_cast<uintptr_t>(Page::kObjectAreaSize));
1035  return static_cast<int>(offset);
1036}
1037
1038
1039MapWord MapWord::FromEncodedAddress(Address address) {
1040  return MapWord(reinterpret_cast<uintptr_t>(address));
1041}
1042
1043
1044Address MapWord::ToEncodedAddress() {
1045  return reinterpret_cast<Address>(value_);
1046}
1047
1048
1049#ifdef DEBUG
1050void HeapObject::VerifyObjectField(int offset) {
1051  VerifyPointer(READ_FIELD(this, offset));
1052}
1053
1054void HeapObject::VerifySmiField(int offset) {
1055  ASSERT(READ_FIELD(this, offset)->IsSmi());
1056}
1057#endif
1058
1059
1060Map* HeapObject::map() {
1061  return map_word().ToMap();
1062}
1063
1064
1065void HeapObject::set_map(Map* value) {
1066  set_map_word(MapWord::FromMap(value));
1067}
1068
1069
1070MapWord HeapObject::map_word() {
1071  return MapWord(reinterpret_cast<uintptr_t>(READ_FIELD(this, kMapOffset)));
1072}
1073
1074
1075void HeapObject::set_map_word(MapWord map_word) {
1076  // WRITE_FIELD does not invoke write barrier, but there is no need
1077  // here.
1078  WRITE_FIELD(this, kMapOffset, reinterpret_cast<Object*>(map_word.value_));
1079}
1080
1081
1082HeapObject* HeapObject::FromAddress(Address address) {
1083  ASSERT_TAG_ALIGNED(address);
1084  return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
1085}
1086
1087
1088Address HeapObject::address() {
1089  return reinterpret_cast<Address>(this) - kHeapObjectTag;
1090}
1091
1092
1093int HeapObject::Size() {
1094  return SizeFromMap(map());
1095}
1096
1097
1098void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
1099  v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
1100                   reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
1101}
1102
1103
1104void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
1105  v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
1106}
1107
1108
1109bool HeapObject::IsMarked() {
1110  return map_word().IsMarked();
1111}
1112
1113
1114void HeapObject::SetMark() {
1115  ASSERT(!IsMarked());
1116  MapWord first_word = map_word();
1117  first_word.SetMark();
1118  set_map_word(first_word);
1119}
1120
1121
1122void HeapObject::ClearMark() {
1123  ASSERT(IsMarked());
1124  MapWord first_word = map_word();
1125  first_word.ClearMark();
1126  set_map_word(first_word);
1127}
1128
1129
1130bool HeapObject::IsOverflowed() {
1131  return map_word().IsOverflowed();
1132}
1133
1134
1135void HeapObject::SetOverflow() {
1136  MapWord first_word = map_word();
1137  first_word.SetOverflow();
1138  set_map_word(first_word);
1139}
1140
1141
1142void HeapObject::ClearOverflow() {
1143  ASSERT(IsOverflowed());
1144  MapWord first_word = map_word();
1145  first_word.ClearOverflow();
1146  set_map_word(first_word);
1147}
1148
1149
1150double HeapNumber::value() {
1151  return READ_DOUBLE_FIELD(this, kValueOffset);
1152}
1153
1154
1155void HeapNumber::set_value(double value) {
1156  WRITE_DOUBLE_FIELD(this, kValueOffset, value);
1157}
1158
1159
1160int HeapNumber::get_exponent() {
1161  return ((READ_INT_FIELD(this, kExponentOffset) & kExponentMask) >>
1162          kExponentShift) - kExponentBias;
1163}
1164
1165
1166int HeapNumber::get_sign() {
1167  return READ_INT_FIELD(this, kExponentOffset) & kSignMask;
1168}
1169
1170
1171ACCESSORS(JSObject, properties, FixedArray, kPropertiesOffset)
1172
1173
1174HeapObject* JSObject::elements() {
1175  Object* array = READ_FIELD(this, kElementsOffset);
1176  // In the assert below Dictionary is covered under FixedArray.
1177  ASSERT(array->IsFixedArray() || array->IsPixelArray() ||
1178         array->IsExternalArray());
1179  return reinterpret_cast<HeapObject*>(array);
1180}
1181
1182
1183void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
1184  ASSERT(map()->has_fast_elements() ==
1185         (value->map() == Heap::fixed_array_map() ||
1186          value->map() == Heap::fixed_cow_array_map()));
1187  // In the assert below Dictionary is covered under FixedArray.
1188  ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
1189         value->IsExternalArray());
1190  WRITE_FIELD(this, kElementsOffset, value);
1191  CONDITIONAL_WRITE_BARRIER(this, kElementsOffset, mode);
1192}
1193
1194
1195void JSObject::initialize_properties() {
1196  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1197  WRITE_FIELD(this, kPropertiesOffset, Heap::empty_fixed_array());
1198}
1199
1200
1201void JSObject::initialize_elements() {
1202  ASSERT(map()->has_fast_elements());
1203  ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
1204  WRITE_FIELD(this, kElementsOffset, Heap::empty_fixed_array());
1205}
1206
1207
1208Object* JSObject::ResetElements() {
1209  Object* obj = map()->GetFastElementsMap();
1210  if (obj->IsFailure()) return obj;
1211  set_map(Map::cast(obj));
1212  initialize_elements();
1213  return this;
1214}
1215
1216
1217ACCESSORS(Oddball, to_string, String, kToStringOffset)
1218ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
1219
1220
1221Object* JSGlobalPropertyCell::value() {
1222  return READ_FIELD(this, kValueOffset);
1223}
1224
1225
1226void JSGlobalPropertyCell::set_value(Object* val, WriteBarrierMode ignored) {
1227  // The write barrier is not used for global property cells.
1228  ASSERT(!val->IsJSGlobalPropertyCell());
1229  WRITE_FIELD(this, kValueOffset, val);
1230}
1231
1232
1233int JSObject::GetHeaderSize() {
1234  InstanceType type = map()->instance_type();
1235  // Check for the most common kind of JavaScript object before
1236  // falling into the generic switch. This speeds up the internal
1237  // field operations considerably on average.
1238  if (type == JS_OBJECT_TYPE) return JSObject::kHeaderSize;
1239  switch (type) {
1240    case JS_GLOBAL_PROXY_TYPE:
1241      return JSGlobalProxy::kSize;
1242    case JS_GLOBAL_OBJECT_TYPE:
1243      return JSGlobalObject::kSize;
1244    case JS_BUILTINS_OBJECT_TYPE:
1245      return JSBuiltinsObject::kSize;
1246    case JS_FUNCTION_TYPE:
1247      return JSFunction::kSize;
1248    case JS_VALUE_TYPE:
1249      return JSValue::kSize;
1250    case JS_ARRAY_TYPE:
1251      return JSValue::kSize;
1252    case JS_REGEXP_TYPE:
1253      return JSValue::kSize;
1254    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
1255      return JSObject::kHeaderSize;
1256    default:
1257      UNREACHABLE();
1258      return 0;
1259  }
1260}
1261
1262
1263int JSObject::GetInternalFieldCount() {
1264  ASSERT(1 << kPointerSizeLog2 == kPointerSize);
1265  // Make sure to adjust for the number of in-object properties. These
1266  // properties do contribute to the size, but are not internal fields.
1267  return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
1268         map()->inobject_properties();
1269}
1270
1271
1272Object* JSObject::GetInternalField(int index) {
1273  ASSERT(index < GetInternalFieldCount() && index >= 0);
1274  // Internal objects do follow immediately after the header, whereas in-object
1275  // properties are at the end of the object. Therefore there is no need
1276  // to adjust the index here.
1277  return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index));
1278}
1279
1280
1281void JSObject::SetInternalField(int index, Object* value) {
1282  ASSERT(index < GetInternalFieldCount() && index >= 0);
1283  // Internal objects do follow immediately after the header, whereas in-object
1284  // properties are at the end of the object. Therefore there is no need
1285  // to adjust the index here.
1286  int offset = GetHeaderSize() + (kPointerSize * index);
1287  WRITE_FIELD(this, offset, value);
1288  WRITE_BARRIER(this, offset);
1289}
1290
1291
1292// Access fast-case object properties at index. The use of these routines
1293// is needed to correctly distinguish between properties stored in-object and
1294// properties stored in the properties array.
1295Object* JSObject::FastPropertyAt(int index) {
1296  // Adjust for the number of properties stored in the object.
1297  index -= map()->inobject_properties();
1298  if (index < 0) {
1299    int offset = map()->instance_size() + (index * kPointerSize);
1300    return READ_FIELD(this, offset);
1301  } else {
1302    ASSERT(index < properties()->length());
1303    return properties()->get(index);
1304  }
1305}
1306
1307
1308Object* JSObject::FastPropertyAtPut(int index, Object* value) {
1309  // Adjust for the number of properties stored in the object.
1310  index -= map()->inobject_properties();
1311  if (index < 0) {
1312    int offset = map()->instance_size() + (index * kPointerSize);
1313    WRITE_FIELD(this, offset, value);
1314    WRITE_BARRIER(this, offset);
1315  } else {
1316    ASSERT(index < properties()->length());
1317    properties()->set(index, value);
1318  }
1319  return value;
1320}
1321
1322
1323Object* JSObject::InObjectPropertyAt(int index) {
1324  // Adjust for the number of properties stored in the object.
1325  index -= map()->inobject_properties();
1326  ASSERT(index < 0);
1327  int offset = map()->instance_size() + (index * kPointerSize);
1328  return READ_FIELD(this, offset);
1329}
1330
1331
1332Object* JSObject::InObjectPropertyAtPut(int index,
1333                                        Object* value,
1334                                        WriteBarrierMode mode) {
1335  // Adjust for the number of properties stored in the object.
1336  index -= map()->inobject_properties();
1337  ASSERT(index < 0);
1338  int offset = map()->instance_size() + (index * kPointerSize);
1339  WRITE_FIELD(this, offset, value);
1340  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1341  return value;
1342}
1343
1344
1345
1346void JSObject::InitializeBody(int object_size) {
1347  Object* value = Heap::undefined_value();
1348  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1349    WRITE_FIELD(this, offset, value);
1350  }
1351}
1352
1353
1354bool JSObject::HasFastProperties() {
1355  return !properties()->IsDictionary();
1356}
1357
1358
1359int JSObject::MaxFastProperties() {
1360  // Allow extra fast properties if the object has more than
1361  // kMaxFastProperties in-object properties. When this is the case,
1362  // it is very unlikely that the object is being used as a dictionary
1363  // and there is a good chance that allowing more map transitions
1364  // will be worth it.
1365  return Max(map()->inobject_properties(), kMaxFastProperties);
1366}
1367
1368
1369void Struct::InitializeBody(int object_size) {
1370  Object* value = Heap::undefined_value();
1371  for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
1372    WRITE_FIELD(this, offset, value);
1373  }
1374}
1375
1376
1377bool Object::ToArrayIndex(uint32_t* index) {
1378  if (IsSmi()) {
1379    int value = Smi::cast(this)->value();
1380    if (value < 0) return false;
1381    *index = value;
1382    return true;
1383  }
1384  if (IsHeapNumber()) {
1385    double value = HeapNumber::cast(this)->value();
1386    uint32_t uint_value = static_cast<uint32_t>(value);
1387    if (value == static_cast<double>(uint_value)) {
1388      *index = uint_value;
1389      return true;
1390    }
1391  }
1392  return false;
1393}
1394
1395
1396bool Object::IsStringObjectWithCharacterAt(uint32_t index) {
1397  if (!this->IsJSValue()) return false;
1398
1399  JSValue* js_value = JSValue::cast(this);
1400  if (!js_value->value()->IsString()) return false;
1401
1402  String* str = String::cast(js_value->value());
1403  if (index >= (uint32_t)str->length()) return false;
1404
1405  return true;
1406}
1407
1408
1409Object* FixedArray::get(int index) {
1410  ASSERT(index >= 0 && index < this->length());
1411  return READ_FIELD(this, kHeaderSize + index * kPointerSize);
1412}
1413
1414
1415void FixedArray::set(int index, Smi* value) {
1416  ASSERT(map() != Heap::fixed_cow_array_map());
1417  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1418  int offset = kHeaderSize + index * kPointerSize;
1419  WRITE_FIELD(this, offset, value);
1420}
1421
1422
1423void FixedArray::set(int index, Object* value) {
1424  ASSERT(map() != Heap::fixed_cow_array_map());
1425  ASSERT(index >= 0 && index < this->length());
1426  int offset = kHeaderSize + index * kPointerSize;
1427  WRITE_FIELD(this, offset, value);
1428  WRITE_BARRIER(this, offset);
1429}
1430
1431
1432WriteBarrierMode HeapObject::GetWriteBarrierMode(const AssertNoAllocation&) {
1433  if (Heap::InNewSpace(this)) return SKIP_WRITE_BARRIER;
1434  return UPDATE_WRITE_BARRIER;
1435}
1436
1437
1438void FixedArray::set(int index,
1439                     Object* value,
1440                     WriteBarrierMode mode) {
1441  ASSERT(map() != Heap::fixed_cow_array_map());
1442  ASSERT(index >= 0 && index < this->length());
1443  int offset = kHeaderSize + index * kPointerSize;
1444  WRITE_FIELD(this, offset, value);
1445  CONDITIONAL_WRITE_BARRIER(this, offset, mode);
1446}
1447
1448
1449void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
1450  ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
1451  ASSERT(index >= 0 && index < array->length());
1452  ASSERT(!Heap::InNewSpace(value));
1453  WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1454}
1455
1456
1457void FixedArray::set_undefined(int index) {
1458  ASSERT(map() != Heap::fixed_cow_array_map());
1459  ASSERT(index >= 0 && index < this->length());
1460  ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1461  WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1462              Heap::undefined_value());
1463}
1464
1465
1466void FixedArray::set_null(int index) {
1467  ASSERT(map() != Heap::fixed_cow_array_map());
1468  ASSERT(index >= 0 && index < this->length());
1469  ASSERT(!Heap::InNewSpace(Heap::null_value()));
1470  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1471}
1472
1473
1474void FixedArray::set_the_hole(int index) {
1475  ASSERT(map() != Heap::fixed_cow_array_map());
1476  ASSERT(index >= 0 && index < this->length());
1477  ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1478  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1479}
1480
1481
1482void FixedArray::set_unchecked(int index, Smi* value) {
1483  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
1484  int offset = kHeaderSize + index * kPointerSize;
1485  WRITE_FIELD(this, offset, value);
1486}
1487
1488
1489void FixedArray::set_null_unchecked(int index) {
1490  ASSERT(index >= 0 && index < this->length());
1491  ASSERT(!Heap::InNewSpace(Heap::null_value()));
1492  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1493}
1494
1495
1496Object** FixedArray::data_start() {
1497  return HeapObject::RawField(this, kHeaderSize);
1498}
1499
1500
1501bool DescriptorArray::IsEmpty() {
1502  ASSERT(this == Heap::empty_descriptor_array() ||
1503         this->length() > 2);
1504  return this == Heap::empty_descriptor_array();
1505}
1506
1507
1508void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1509  Object* tmp = array->get(first);
1510  fast_set(array, first, array->get(second));
1511  fast_set(array, second, tmp);
1512}
1513
1514
1515int DescriptorArray::Search(String* name) {
1516  SLOW_ASSERT(IsSortedNoDuplicates());
1517
1518  // Check for empty descriptor array.
1519  int nof = number_of_descriptors();
1520  if (nof == 0) return kNotFound;
1521
1522  // Fast case: do linear search for small arrays.
1523  const int kMaxElementsForLinearSearch = 8;
1524  if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1525    return LinearSearch(name, nof);
1526  }
1527
1528  // Slow case: perform binary search.
1529  return BinarySearch(name, 0, nof - 1);
1530}
1531
1532
1533int DescriptorArray::SearchWithCache(String* name) {
1534  int number = DescriptorLookupCache::Lookup(this, name);
1535  if (number == DescriptorLookupCache::kAbsent) {
1536    number = Search(name);
1537    DescriptorLookupCache::Update(this, name, number);
1538  }
1539  return number;
1540}
1541
1542
1543String* DescriptorArray::GetKey(int descriptor_number) {
1544  ASSERT(descriptor_number < number_of_descriptors());
1545  return String::cast(get(ToKeyIndex(descriptor_number)));
1546}
1547
1548
1549Object* DescriptorArray::GetValue(int descriptor_number) {
1550  ASSERT(descriptor_number < number_of_descriptors());
1551  return GetContentArray()->get(ToValueIndex(descriptor_number));
1552}
1553
1554
1555Smi* DescriptorArray::GetDetails(int descriptor_number) {
1556  ASSERT(descriptor_number < number_of_descriptors());
1557  return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1558}
1559
1560
1561PropertyType DescriptorArray::GetType(int descriptor_number) {
1562  ASSERT(descriptor_number < number_of_descriptors());
1563  return PropertyDetails(GetDetails(descriptor_number)).type();
1564}
1565
1566
1567int DescriptorArray::GetFieldIndex(int descriptor_number) {
1568  return Descriptor::IndexFromValue(GetValue(descriptor_number));
1569}
1570
1571
1572JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1573  return JSFunction::cast(GetValue(descriptor_number));
1574}
1575
1576
1577Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1578  ASSERT(GetType(descriptor_number) == CALLBACKS);
1579  return GetValue(descriptor_number);
1580}
1581
1582
1583AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1584  ASSERT(GetType(descriptor_number) == CALLBACKS);
1585  Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1586  return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1587}
1588
1589
1590bool DescriptorArray::IsProperty(int descriptor_number) {
1591  return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1592}
1593
1594
1595bool DescriptorArray::IsTransition(int descriptor_number) {
1596  PropertyType t = GetType(descriptor_number);
1597  return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1598}
1599
1600
1601bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1602  return GetType(descriptor_number) == NULL_DESCRIPTOR;
1603}
1604
1605
1606bool DescriptorArray::IsDontEnum(int descriptor_number) {
1607  return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1608}
1609
1610
1611void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1612  desc->Init(GetKey(descriptor_number),
1613             GetValue(descriptor_number),
1614             GetDetails(descriptor_number));
1615}
1616
1617
1618void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1619  // Range check.
1620  ASSERT(descriptor_number < number_of_descriptors());
1621
1622  // Make sure none of the elements in desc are in new space.
1623  ASSERT(!Heap::InNewSpace(desc->GetKey()));
1624  ASSERT(!Heap::InNewSpace(desc->GetValue()));
1625
1626  fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1627  FixedArray* content_array = GetContentArray();
1628  fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1629  fast_set(content_array, ToDetailsIndex(descriptor_number),
1630           desc->GetDetails().AsSmi());
1631}
1632
1633
1634void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1635  Descriptor desc;
1636  src->Get(src_index, &desc);
1637  Set(index, &desc);
1638}
1639
1640
1641void DescriptorArray::Swap(int first, int second) {
1642  fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1643  FixedArray* content_array = GetContentArray();
1644  fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1645  fast_swap(content_array, ToDetailsIndex(first),  ToDetailsIndex(second));
1646}
1647
1648
1649bool NumberDictionary::requires_slow_elements() {
1650  Object* max_index_object = get(kMaxNumberKeyIndex);
1651  if (!max_index_object->IsSmi()) return false;
1652  return 0 !=
1653      (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1654}
1655
1656uint32_t NumberDictionary::max_number_key() {
1657  ASSERT(!requires_slow_elements());
1658  Object* max_index_object = get(kMaxNumberKeyIndex);
1659  if (!max_index_object->IsSmi()) return 0;
1660  uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1661  return value >> kRequiresSlowElementsTagSize;
1662}
1663
1664void NumberDictionary::set_requires_slow_elements() {
1665  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
1666}
1667
1668
1669// ------------------------------------
1670// Cast operations
1671
1672
1673CAST_ACCESSOR(FixedArray)
1674CAST_ACCESSOR(DescriptorArray)
1675CAST_ACCESSOR(SymbolTable)
1676CAST_ACCESSOR(JSFunctionResultCache)
1677CAST_ACCESSOR(NormalizedMapCache)
1678CAST_ACCESSOR(CompilationCacheTable)
1679CAST_ACCESSOR(CodeCacheHashTable)
1680CAST_ACCESSOR(MapCache)
1681CAST_ACCESSOR(String)
1682CAST_ACCESSOR(SeqString)
1683CAST_ACCESSOR(SeqAsciiString)
1684CAST_ACCESSOR(SeqTwoByteString)
1685CAST_ACCESSOR(ConsString)
1686CAST_ACCESSOR(ExternalString)
1687CAST_ACCESSOR(ExternalAsciiString)
1688CAST_ACCESSOR(ExternalTwoByteString)
1689CAST_ACCESSOR(JSObject)
1690CAST_ACCESSOR(Smi)
1691CAST_ACCESSOR(Failure)
1692CAST_ACCESSOR(HeapObject)
1693CAST_ACCESSOR(HeapNumber)
1694CAST_ACCESSOR(Oddball)
1695CAST_ACCESSOR(JSGlobalPropertyCell)
1696CAST_ACCESSOR(SharedFunctionInfo)
1697CAST_ACCESSOR(Map)
1698CAST_ACCESSOR(JSFunction)
1699CAST_ACCESSOR(GlobalObject)
1700CAST_ACCESSOR(JSGlobalProxy)
1701CAST_ACCESSOR(JSGlobalObject)
1702CAST_ACCESSOR(JSBuiltinsObject)
1703CAST_ACCESSOR(Code)
1704CAST_ACCESSOR(JSArray)
1705CAST_ACCESSOR(JSRegExp)
1706CAST_ACCESSOR(Proxy)
1707CAST_ACCESSOR(ByteArray)
1708CAST_ACCESSOR(PixelArray)
1709CAST_ACCESSOR(ExternalArray)
1710CAST_ACCESSOR(ExternalByteArray)
1711CAST_ACCESSOR(ExternalUnsignedByteArray)
1712CAST_ACCESSOR(ExternalShortArray)
1713CAST_ACCESSOR(ExternalUnsignedShortArray)
1714CAST_ACCESSOR(ExternalIntArray)
1715CAST_ACCESSOR(ExternalUnsignedIntArray)
1716CAST_ACCESSOR(ExternalFloatArray)
1717CAST_ACCESSOR(Struct)
1718
1719
1720#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1721  STRUCT_LIST(MAKE_STRUCT_CAST)
1722#undef MAKE_STRUCT_CAST
1723
1724
1725template <typename Shape, typename Key>
1726HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1727  ASSERT(obj->IsHashTable());
1728  return reinterpret_cast<HashTable*>(obj);
1729}
1730
1731
1732SMI_ACCESSORS(FixedArray, length, kLengthOffset)
1733SMI_ACCESSORS(ByteArray, length, kLengthOffset)
1734
1735INT_ACCESSORS(PixelArray, length, kLengthOffset)
1736INT_ACCESSORS(ExternalArray, length, kLengthOffset)
1737
1738
1739SMI_ACCESSORS(String, length, kLengthOffset)
1740
1741
1742uint32_t String::hash_field() {
1743  return READ_UINT32_FIELD(this, kHashFieldOffset);
1744}
1745
1746
1747void String::set_hash_field(uint32_t value) {
1748  WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1749#if V8_HOST_ARCH_64_BIT
1750  WRITE_UINT32_FIELD(this, kHashFieldOffset + kIntSize, 0);
1751#endif
1752}
1753
1754
1755bool String::Equals(String* other) {
1756  if (other == this) return true;
1757  if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1758    return false;
1759  }
1760  return SlowEquals(other);
1761}
1762
1763
1764Object* String::TryFlatten(PretenureFlag pretenure) {
1765  if (!StringShape(this).IsCons()) return this;
1766  ConsString* cons = ConsString::cast(this);
1767  if (cons->second()->length() == 0) return cons->first();
1768  return SlowTryFlatten(pretenure);
1769}
1770
1771
1772String* String::TryFlattenGetString(PretenureFlag pretenure) {
1773  Object* flat = TryFlatten(pretenure);
1774  return flat->IsFailure() ? this : String::cast(flat);
1775}
1776
1777
1778uint16_t String::Get(int index) {
1779  ASSERT(index >= 0 && index < length());
1780  switch (StringShape(this).full_representation_tag()) {
1781    case kSeqStringTag | kAsciiStringTag:
1782      return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1783    case kSeqStringTag | kTwoByteStringTag:
1784      return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1785    case kConsStringTag | kAsciiStringTag:
1786    case kConsStringTag | kTwoByteStringTag:
1787      return ConsString::cast(this)->ConsStringGet(index);
1788    case kExternalStringTag | kAsciiStringTag:
1789      return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1790    case kExternalStringTag | kTwoByteStringTag:
1791      return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1792    default:
1793      break;
1794  }
1795
1796  UNREACHABLE();
1797  return 0;
1798}
1799
1800
1801void String::Set(int index, uint16_t value) {
1802  ASSERT(index >= 0 && index < length());
1803  ASSERT(StringShape(this).IsSequential());
1804
1805  return this->IsAsciiRepresentation()
1806      ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1807      : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1808}
1809
1810
1811bool String::IsFlat() {
1812  switch (StringShape(this).representation_tag()) {
1813    case kConsStringTag: {
1814      String* second = ConsString::cast(this)->second();
1815      // Only flattened strings have second part empty.
1816      return second->length() == 0;
1817    }
1818    default:
1819      return true;
1820  }
1821}
1822
1823
1824uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1825  ASSERT(index >= 0 && index < length());
1826  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1827}
1828
1829
1830void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1831  ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1832  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1833                   static_cast<byte>(value));
1834}
1835
1836
1837Address SeqAsciiString::GetCharsAddress() {
1838  return FIELD_ADDR(this, kHeaderSize);
1839}
1840
1841
1842char* SeqAsciiString::GetChars() {
1843  return reinterpret_cast<char*>(GetCharsAddress());
1844}
1845
1846
1847Address SeqTwoByteString::GetCharsAddress() {
1848  return FIELD_ADDR(this, kHeaderSize);
1849}
1850
1851
1852uc16* SeqTwoByteString::GetChars() {
1853  return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1854}
1855
1856
1857uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1858  ASSERT(index >= 0 && index < length());
1859  return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1860}
1861
1862
1863void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1864  ASSERT(index >= 0 && index < length());
1865  WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1866}
1867
1868
1869int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1870  return SizeFor(length());
1871}
1872
1873
1874int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1875  return SizeFor(length());
1876}
1877
1878
1879String* ConsString::first() {
1880  return String::cast(READ_FIELD(this, kFirstOffset));
1881}
1882
1883
1884Object* ConsString::unchecked_first() {
1885  return READ_FIELD(this, kFirstOffset);
1886}
1887
1888
1889void ConsString::set_first(String* value, WriteBarrierMode mode) {
1890  WRITE_FIELD(this, kFirstOffset, value);
1891  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1892}
1893
1894
1895String* ConsString::second() {
1896  return String::cast(READ_FIELD(this, kSecondOffset));
1897}
1898
1899
1900Object* ConsString::unchecked_second() {
1901  return READ_FIELD(this, kSecondOffset);
1902}
1903
1904
1905void ConsString::set_second(String* value, WriteBarrierMode mode) {
1906  WRITE_FIELD(this, kSecondOffset, value);
1907  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1908}
1909
1910
1911ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1912  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1913}
1914
1915
1916void ExternalAsciiString::set_resource(
1917    ExternalAsciiString::Resource* resource) {
1918  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1919}
1920
1921
1922ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1923  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1924}
1925
1926
1927void ExternalTwoByteString::set_resource(
1928    ExternalTwoByteString::Resource* resource) {
1929  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1930}
1931
1932
1933void JSFunctionResultCache::MakeZeroSize() {
1934  set(kFingerIndex, Smi::FromInt(kEntriesIndex));
1935  set(kCacheSizeIndex, Smi::FromInt(kEntriesIndex));
1936}
1937
1938
1939void JSFunctionResultCache::Clear() {
1940  int cache_size = Smi::cast(get(kCacheSizeIndex))->value();
1941  Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
1942  MemsetPointer(entries_start, Heap::the_hole_value(), cache_size);
1943  MakeZeroSize();
1944}
1945
1946
1947byte ByteArray::get(int index) {
1948  ASSERT(index >= 0 && index < this->length());
1949  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1950}
1951
1952
1953void ByteArray::set(int index, byte value) {
1954  ASSERT(index >= 0 && index < this->length());
1955  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1956}
1957
1958
1959int ByteArray::get_int(int index) {
1960  ASSERT(index >= 0 && (index * kIntSize) < this->length());
1961  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1962}
1963
1964
1965ByteArray* ByteArray::FromDataStartAddress(Address address) {
1966  ASSERT_TAG_ALIGNED(address);
1967  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1968}
1969
1970
1971Address ByteArray::GetDataStartAddress() {
1972  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1973}
1974
1975
1976uint8_t* PixelArray::external_pointer() {
1977  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1978  return reinterpret_cast<uint8_t*>(ptr);
1979}
1980
1981
1982void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1983  intptr_t ptr = reinterpret_cast<intptr_t>(value);
1984  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1985}
1986
1987
1988uint8_t PixelArray::get(int index) {
1989  ASSERT((index >= 0) && (index < this->length()));
1990  uint8_t* ptr = external_pointer();
1991  return ptr[index];
1992}
1993
1994
1995void PixelArray::set(int index, uint8_t value) {
1996  ASSERT((index >= 0) && (index < this->length()));
1997  uint8_t* ptr = external_pointer();
1998  ptr[index] = value;
1999}
2000
2001
2002void* ExternalArray::external_pointer() {
2003  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
2004  return reinterpret_cast<void*>(ptr);
2005}
2006
2007
2008void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
2009  intptr_t ptr = reinterpret_cast<intptr_t>(value);
2010  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
2011}
2012
2013
2014int8_t ExternalByteArray::get(int index) {
2015  ASSERT((index >= 0) && (index < this->length()));
2016  int8_t* ptr = static_cast<int8_t*>(external_pointer());
2017  return ptr[index];
2018}
2019
2020
2021void ExternalByteArray::set(int index, int8_t value) {
2022  ASSERT((index >= 0) && (index < this->length()));
2023  int8_t* ptr = static_cast<int8_t*>(external_pointer());
2024  ptr[index] = value;
2025}
2026
2027
2028uint8_t ExternalUnsignedByteArray::get(int index) {
2029  ASSERT((index >= 0) && (index < this->length()));
2030  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2031  return ptr[index];
2032}
2033
2034
2035void ExternalUnsignedByteArray::set(int index, uint8_t value) {
2036  ASSERT((index >= 0) && (index < this->length()));
2037  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
2038  ptr[index] = value;
2039}
2040
2041
2042int16_t ExternalShortArray::get(int index) {
2043  ASSERT((index >= 0) && (index < this->length()));
2044  int16_t* ptr = static_cast<int16_t*>(external_pointer());
2045  return ptr[index];
2046}
2047
2048
2049void ExternalShortArray::set(int index, int16_t value) {
2050  ASSERT((index >= 0) && (index < this->length()));
2051  int16_t* ptr = static_cast<int16_t*>(external_pointer());
2052  ptr[index] = value;
2053}
2054
2055
2056uint16_t ExternalUnsignedShortArray::get(int index) {
2057  ASSERT((index >= 0) && (index < this->length()));
2058  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2059  return ptr[index];
2060}
2061
2062
2063void ExternalUnsignedShortArray::set(int index, uint16_t value) {
2064  ASSERT((index >= 0) && (index < this->length()));
2065  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
2066  ptr[index] = value;
2067}
2068
2069
2070int32_t ExternalIntArray::get(int index) {
2071  ASSERT((index >= 0) && (index < this->length()));
2072  int32_t* ptr = static_cast<int32_t*>(external_pointer());
2073  return ptr[index];
2074}
2075
2076
2077void ExternalIntArray::set(int index, int32_t value) {
2078  ASSERT((index >= 0) && (index < this->length()));
2079  int32_t* ptr = static_cast<int32_t*>(external_pointer());
2080  ptr[index] = value;
2081}
2082
2083
2084uint32_t ExternalUnsignedIntArray::get(int index) {
2085  ASSERT((index >= 0) && (index < this->length()));
2086  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2087  return ptr[index];
2088}
2089
2090
2091void ExternalUnsignedIntArray::set(int index, uint32_t value) {
2092  ASSERT((index >= 0) && (index < this->length()));
2093  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
2094  ptr[index] = value;
2095}
2096
2097
2098float ExternalFloatArray::get(int index) {
2099  ASSERT((index >= 0) && (index < this->length()));
2100  float* ptr = static_cast<float*>(external_pointer());
2101  return ptr[index];
2102}
2103
2104
2105void ExternalFloatArray::set(int index, float value) {
2106  ASSERT((index >= 0) && (index < this->length()));
2107  float* ptr = static_cast<float*>(external_pointer());
2108  ptr[index] = value;
2109}
2110
2111
2112int Map::visitor_id() {
2113  return READ_BYTE_FIELD(this, kVisitorIdOffset);
2114}
2115
2116
2117void Map::set_visitor_id(int id) {
2118  ASSERT(0 <= id && id < 256);
2119  WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
2120}
2121
2122
2123int Map::instance_size() {
2124  return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
2125}
2126
2127
2128int Map::inobject_properties() {
2129  return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
2130}
2131
2132
2133int Map::pre_allocated_property_fields() {
2134  return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
2135}
2136
2137
2138int HeapObject::SizeFromMap(Map* map) {
2139  int instance_size = map->instance_size();
2140  if (instance_size != kVariableSizeSentinel) return instance_size;
2141  // We can ignore the "symbol" bit becase it is only set for symbols
2142  // and implies a string type.
2143  int instance_type = static_cast<int>(map->instance_type()) & ~kIsSymbolMask;
2144  // Only inline the most frequent cases.
2145  if (instance_type == FIXED_ARRAY_TYPE) {
2146    return FixedArray::BodyDescriptor::SizeOf(map, this);
2147  }
2148  if (instance_type == ASCII_STRING_TYPE) {
2149    return SeqAsciiString::SizeFor(
2150        reinterpret_cast<SeqAsciiString*>(this)->length());
2151  }
2152  if (instance_type == BYTE_ARRAY_TYPE) {
2153    return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2154  }
2155  if (instance_type == STRING_TYPE) {
2156    return SeqTwoByteString::SizeFor(
2157        reinterpret_cast<SeqTwoByteString*>(this)->length());
2158  }
2159  ASSERT(instance_type == CODE_TYPE);
2160  return reinterpret_cast<Code*>(this)->CodeSize();
2161}
2162
2163
2164void Map::set_instance_size(int value) {
2165  ASSERT_EQ(0, value & (kPointerSize - 1));
2166  value >>= kPointerSizeLog2;
2167  ASSERT(0 <= value && value < 256);
2168  WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2169}
2170
2171
2172void Map::set_inobject_properties(int value) {
2173  ASSERT(0 <= value && value < 256);
2174  WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2175}
2176
2177
2178void Map::set_pre_allocated_property_fields(int value) {
2179  ASSERT(0 <= value && value < 256);
2180  WRITE_BYTE_FIELD(this,
2181                   kPreAllocatedPropertyFieldsOffset,
2182                   static_cast<byte>(value));
2183}
2184
2185
2186InstanceType Map::instance_type() {
2187  return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2188}
2189
2190
2191void Map::set_instance_type(InstanceType value) {
2192  ASSERT(0 <= value && value < 256);
2193  WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2194}
2195
2196
2197int Map::unused_property_fields() {
2198  return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2199}
2200
2201
2202void Map::set_unused_property_fields(int value) {
2203  WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2204}
2205
2206
2207byte Map::bit_field() {
2208  return READ_BYTE_FIELD(this, kBitFieldOffset);
2209}
2210
2211
2212void Map::set_bit_field(byte value) {
2213  WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2214}
2215
2216
2217byte Map::bit_field2() {
2218  return READ_BYTE_FIELD(this, kBitField2Offset);
2219}
2220
2221
2222void Map::set_bit_field2(byte value) {
2223  WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2224}
2225
2226
2227void Map::set_non_instance_prototype(bool value) {
2228  if (value) {
2229    set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2230  } else {
2231    set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2232  }
2233}
2234
2235
2236bool Map::has_non_instance_prototype() {
2237  return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2238}
2239
2240
2241void Map::set_function_with_prototype(bool value) {
2242  if (value) {
2243    set_bit_field2(bit_field2() | (1 << kFunctionWithPrototype));
2244  } else {
2245    set_bit_field2(bit_field2() & ~(1 << kFunctionWithPrototype));
2246  }
2247}
2248
2249
2250bool Map::function_with_prototype() {
2251  return ((1 << kFunctionWithPrototype) & bit_field2()) != 0;
2252}
2253
2254
2255void Map::set_is_access_check_needed(bool access_check_needed) {
2256  if (access_check_needed) {
2257    set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2258  } else {
2259    set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2260  }
2261}
2262
2263
2264bool Map::is_access_check_needed() {
2265  return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2266}
2267
2268
2269void Map::set_is_extensible(bool value) {
2270  if (value) {
2271    set_bit_field2(bit_field2() | (1 << kIsExtensible));
2272  } else {
2273    set_bit_field2(bit_field2() & ~(1 << kIsExtensible));
2274  }
2275}
2276
2277bool Map::is_extensible() {
2278  return ((1 << kIsExtensible) & bit_field2()) != 0;
2279}
2280
2281
2282
2283Code::Flags Code::flags() {
2284  return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2285}
2286
2287
2288void Code::set_flags(Code::Flags flags) {
2289  STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2290  // Make sure that all call stubs have an arguments count.
2291  ASSERT((ExtractKindFromFlags(flags) != CALL_IC &&
2292          ExtractKindFromFlags(flags) != KEYED_CALL_IC) ||
2293         ExtractArgumentsCountFromFlags(flags) >= 0);
2294  WRITE_INT_FIELD(this, kFlagsOffset, flags);
2295}
2296
2297
2298Code::Kind Code::kind() {
2299  return ExtractKindFromFlags(flags());
2300}
2301
2302
2303InLoopFlag Code::ic_in_loop() {
2304  return ExtractICInLoopFromFlags(flags());
2305}
2306
2307
2308InlineCacheState Code::ic_state() {
2309  InlineCacheState result = ExtractICStateFromFlags(flags());
2310  // Only allow uninitialized or debugger states for non-IC code
2311  // objects. This is used in the debugger to determine whether or not
2312  // a call to code object has been replaced with a debug break call.
2313  ASSERT(is_inline_cache_stub() ||
2314         result == UNINITIALIZED ||
2315         result == DEBUG_BREAK ||
2316         result == DEBUG_PREPARE_STEP_IN);
2317  return result;
2318}
2319
2320
2321PropertyType Code::type() {
2322  ASSERT(ic_state() == MONOMORPHIC);
2323  return ExtractTypeFromFlags(flags());
2324}
2325
2326
2327int Code::arguments_count() {
2328  ASSERT(is_call_stub() || is_keyed_call_stub() || kind() == STUB);
2329  return ExtractArgumentsCountFromFlags(flags());
2330}
2331
2332
2333int Code::major_key() {
2334  ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
2335  return READ_BYTE_FIELD(this, kStubMajorKeyOffset);
2336}
2337
2338
2339void Code::set_major_key(int major) {
2340  ASSERT(kind() == STUB || kind() == BINARY_OP_IC);
2341  ASSERT(0 <= major && major < 256);
2342  WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2343}
2344
2345
2346bool Code::is_inline_cache_stub() {
2347  Kind kind = this->kind();
2348  return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2349}
2350
2351
2352Code::Flags Code::ComputeFlags(Kind kind,
2353                               InLoopFlag in_loop,
2354                               InlineCacheState ic_state,
2355                               PropertyType type,
2356                               int argc,
2357                               InlineCacheHolderFlag holder) {
2358  // Compute the bit mask.
2359  int bits = kind << kFlagsKindShift;
2360  if (in_loop) bits |= kFlagsICInLoopMask;
2361  bits |= ic_state << kFlagsICStateShift;
2362  bits |= type << kFlagsTypeShift;
2363  bits |= argc << kFlagsArgumentsCountShift;
2364  if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
2365  // Cast to flags and validate result before returning it.
2366  Flags result = static_cast<Flags>(bits);
2367  ASSERT(ExtractKindFromFlags(result) == kind);
2368  ASSERT(ExtractICStateFromFlags(result) == ic_state);
2369  ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2370  ASSERT(ExtractTypeFromFlags(result) == type);
2371  ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2372  return result;
2373}
2374
2375
2376Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2377                                          PropertyType type,
2378                                          InlineCacheHolderFlag holder,
2379                                          InLoopFlag in_loop,
2380                                          int argc) {
2381  return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
2382}
2383
2384
2385Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2386  int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2387  return static_cast<Kind>(bits);
2388}
2389
2390
2391InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2392  int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2393  return static_cast<InlineCacheState>(bits);
2394}
2395
2396
2397InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2398  int bits = (flags & kFlagsICInLoopMask);
2399  return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2400}
2401
2402
2403PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2404  int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2405  return static_cast<PropertyType>(bits);
2406}
2407
2408
2409int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2410  return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2411}
2412
2413
2414InlineCacheHolderFlag Code::ExtractCacheHolderFromFlags(Flags flags) {
2415  int bits = (flags & kFlagsCacheInPrototypeMapMask);
2416  return bits != 0 ? PROTOTYPE_MAP : OWN_MAP;
2417}
2418
2419
2420Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2421  int bits = flags & ~kFlagsTypeMask;
2422  return static_cast<Flags>(bits);
2423}
2424
2425
2426Code* Code::GetCodeFromTargetAddress(Address address) {
2427  HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2428  // GetCodeFromTargetAddress might be called when marking objects during mark
2429  // sweep. reinterpret_cast is therefore used instead of the more appropriate
2430  // Code::cast. Code::cast does not work when the object's map is
2431  // marked.
2432  Code* result = reinterpret_cast<Code*>(code);
2433  return result;
2434}
2435
2436
2437Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
2438  return HeapObject::
2439      FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
2440}
2441
2442
2443Object* Map::prototype() {
2444  return READ_FIELD(this, kPrototypeOffset);
2445}
2446
2447
2448void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2449  ASSERT(value->IsNull() || value->IsJSObject());
2450  WRITE_FIELD(this, kPrototypeOffset, value);
2451  CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2452}
2453
2454
2455Object* Map::GetFastElementsMap() {
2456  if (has_fast_elements()) return this;
2457  Object* obj = CopyDropTransitions();
2458  if (obj->IsFailure()) return obj;
2459  Map* new_map = Map::cast(obj);
2460  new_map->set_has_fast_elements(true);
2461  Counters::map_slow_to_fast_elements.Increment();
2462  return new_map;
2463}
2464
2465
2466Object* Map::GetSlowElementsMap() {
2467  if (!has_fast_elements()) return this;
2468  Object* obj = CopyDropTransitions();
2469  if (obj->IsFailure()) return obj;
2470  Map* new_map = Map::cast(obj);
2471  new_map->set_has_fast_elements(false);
2472  Counters::map_fast_to_slow_elements.Increment();
2473  return new_map;
2474}
2475
2476
2477ACCESSORS(Map, instance_descriptors, DescriptorArray,
2478          kInstanceDescriptorsOffset)
2479ACCESSORS(Map, code_cache, Object, kCodeCacheOffset)
2480ACCESSORS(Map, constructor, Object, kConstructorOffset)
2481
2482ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2483ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2484
2485ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2486ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2487ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2488
2489ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2490
2491ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2492ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2493ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2494ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2495ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2496ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
2497
2498ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2499ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2500ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2501
2502ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2503ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2504ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2505ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2506ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2507ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2508
2509ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2510ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2511
2512ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2513ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2514
2515ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2516ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2517ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2518          kPropertyAccessorsOffset)
2519ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2520          kPrototypeTemplateOffset)
2521ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2522ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2523          kNamedPropertyHandlerOffset)
2524ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2525          kIndexedPropertyHandlerOffset)
2526ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2527          kInstanceTemplateOffset)
2528ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2529ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2530ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2531          kInstanceCallHandlerOffset)
2532ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2533          kAccessCheckInfoOffset)
2534ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2535
2536ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2537ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2538          kInternalFieldCountOffset)
2539
2540ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2541ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2542
2543ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2544
2545ACCESSORS(Script, source, Object, kSourceOffset)
2546ACCESSORS(Script, name, Object, kNameOffset)
2547ACCESSORS(Script, id, Object, kIdOffset)
2548ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2549ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2550ACCESSORS(Script, data, Object, kDataOffset)
2551ACCESSORS(Script, context_data, Object, kContextOffset)
2552ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2553ACCESSORS(Script, type, Smi, kTypeOffset)
2554ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2555ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2556ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
2557ACCESSORS(Script, eval_from_instructions_offset, Smi,
2558          kEvalFrominstructionsOffsetOffset)
2559
2560#ifdef ENABLE_DEBUGGER_SUPPORT
2561ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2562ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2563ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2564ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2565
2566ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2567ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2568ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2569ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2570#endif
2571
2572ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2573ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2574ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2575          kInstanceClassNameOffset)
2576ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
2577ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2578ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2579ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2580ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2581          kThisPropertyAssignmentsOffset)
2582
2583BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2584               kHiddenPrototypeBit)
2585BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2586BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2587               kNeedsAccessCheckBit)
2588BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2589               kIsExpressionBit)
2590BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2591               kIsTopLevelBit)
2592BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2593            has_only_simple_this_property_assignments,
2594            kHasOnlySimpleThisPropertyAssignments)
2595BOOL_ACCESSORS(SharedFunctionInfo,
2596               compiler_hints,
2597               try_full_codegen,
2598               kTryFullCodegen)
2599BOOL_ACCESSORS(SharedFunctionInfo,
2600               compiler_hints,
2601               allows_lazy_compilation,
2602               kAllowLazyCompilation)
2603
2604
2605#if V8_HOST_ARCH_32_BIT
2606SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2607SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2608              kFormalParameterCountOffset)
2609SMI_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2610              kExpectedNofPropertiesOffset)
2611SMI_ACCESSORS(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2612SMI_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2613              kStartPositionAndTypeOffset)
2614SMI_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2615SMI_ACCESSORS(SharedFunctionInfo, function_token_position,
2616              kFunctionTokenPositionOffset)
2617SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
2618              kCompilerHintsOffset)
2619SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2620              kThisPropertyAssignmentsCountOffset)
2621#else
2622
2623#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset)             \
2624  int holder::name() {                                            \
2625    int value = READ_INT_FIELD(this, offset);                     \
2626    ASSERT(kHeapObjectTag == 1);                                  \
2627    ASSERT((value & kHeapObjectTag) == 0);                        \
2628    return value >> 1;                                            \
2629  }                                                               \
2630  void holder::set_##name(int value) {                            \
2631    ASSERT(kHeapObjectTag == 1);                                  \
2632    ASSERT((value & 0xC0000000) == 0xC0000000 ||                  \
2633           (value & 0xC0000000) == 0x000000000);                  \
2634    WRITE_INT_FIELD(this,                                         \
2635                    offset,                                       \
2636                    (value << 1) & ~kHeapObjectTag);              \
2637  }
2638
2639#define PSEUDO_SMI_ACCESSORS_HI(holder, name, offset) \
2640  INT_ACCESSORS(holder, name, offset)
2641
2642
2643
2644PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, length, kLengthOffset)
2645PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, formal_parameter_count,
2646              kFormalParameterCountOffset)
2647
2648PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, expected_nof_properties,
2649              kExpectedNofPropertiesOffset)
2650PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, num_literals, kNumLiteralsOffset)
2651
2652PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, start_position_and_type,
2653              kStartPositionAndTypeOffset)
2654PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, end_position, kEndPositionOffset)
2655
2656PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, function_token_position,
2657              kFunctionTokenPositionOffset)
2658PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, compiler_hints,
2659              kCompilerHintsOffset)
2660
2661PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, this_property_assignments_count,
2662              kThisPropertyAssignmentsCountOffset)
2663#endif
2664
2665ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
2666ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
2667
2668bool Script::HasValidSource() {
2669  Object* src = this->source();
2670  if (!src->IsString()) return true;
2671  String* src_str = String::cast(src);
2672  if (!StringShape(src_str).IsExternal()) return true;
2673  if (src_str->IsAsciiRepresentation()) {
2674    return ExternalAsciiString::cast(src)->resource() != NULL;
2675  } else if (src_str->IsTwoByteRepresentation()) {
2676    return ExternalTwoByteString::cast(src)->resource() != NULL;
2677  }
2678  return true;
2679}
2680
2681
2682void SharedFunctionInfo::DontAdaptArguments() {
2683  ASSERT(code()->kind() == Code::BUILTIN);
2684  set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2685}
2686
2687
2688int SharedFunctionInfo::start_position() {
2689  return start_position_and_type() >> kStartPositionShift;
2690}
2691
2692
2693void SharedFunctionInfo::set_start_position(int start_position) {
2694  set_start_position_and_type((start_position << kStartPositionShift)
2695    | (start_position_and_type() & ~kStartPositionMask));
2696}
2697
2698
2699Code* SharedFunctionInfo::code() {
2700  return Code::cast(READ_FIELD(this, kCodeOffset));
2701}
2702
2703
2704Code* SharedFunctionInfo::unchecked_code() {
2705  return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
2706}
2707
2708
2709void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2710  WRITE_FIELD(this, kCodeOffset, value);
2711  CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2712}
2713
2714
2715SerializedScopeInfo* SharedFunctionInfo::scope_info() {
2716  return reinterpret_cast<SerializedScopeInfo*>(
2717      READ_FIELD(this, kScopeInfoOffset));
2718}
2719
2720
2721void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
2722                                        WriteBarrierMode mode) {
2723  WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
2724  CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
2725}
2726
2727
2728bool SharedFunctionInfo::is_compiled() {
2729  return code() != Builtins::builtin(Builtins::LazyCompile);
2730}
2731
2732
2733bool SharedFunctionInfo::IsApiFunction() {
2734  return function_data()->IsFunctionTemplateInfo();
2735}
2736
2737
2738FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
2739  ASSERT(IsApiFunction());
2740  return FunctionTemplateInfo::cast(function_data());
2741}
2742
2743
2744bool SharedFunctionInfo::HasCustomCallGenerator() {
2745  return function_data()->IsSmi();
2746}
2747
2748
2749int SharedFunctionInfo::custom_call_generator_id() {
2750  ASSERT(HasCustomCallGenerator());
2751  return Smi::cast(function_data())->value();
2752}
2753
2754
2755int SharedFunctionInfo::code_age() {
2756  return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
2757}
2758
2759
2760void SharedFunctionInfo::set_code_age(int code_age) {
2761  set_compiler_hints(compiler_hints() |
2762                     ((code_age & kCodeAgeMask) << kCodeAgeShift));
2763}
2764
2765
2766bool JSFunction::IsBuiltin() {
2767  return context()->global()->IsJSBuiltinsObject();
2768}
2769
2770
2771Code* JSFunction::code() {
2772  return Code::cast(unchecked_code());
2773}
2774
2775
2776Code* JSFunction::unchecked_code() {
2777  return reinterpret_cast<Code*>(
2778      Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
2779}
2780
2781
2782void JSFunction::set_code(Code* value) {
2783  // Skip the write barrier because code is never in new space.
2784  ASSERT(!Heap::InNewSpace(value));
2785  Address entry = value->entry();
2786  WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
2787}
2788
2789
2790Context* JSFunction::context() {
2791  return Context::cast(READ_FIELD(this, kContextOffset));
2792}
2793
2794
2795Object* JSFunction::unchecked_context() {
2796  return READ_FIELD(this, kContextOffset);
2797}
2798
2799
2800SharedFunctionInfo* JSFunction::unchecked_shared() {
2801  return reinterpret_cast<SharedFunctionInfo*>(
2802      READ_FIELD(this, kSharedFunctionInfoOffset));
2803}
2804
2805
2806void JSFunction::set_context(Object* value) {
2807  ASSERT(value == Heap::undefined_value() || value->IsContext());
2808  WRITE_FIELD(this, kContextOffset, value);
2809  WRITE_BARRIER(this, kContextOffset);
2810}
2811
2812ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2813          kPrototypeOrInitialMapOffset)
2814
2815
2816Map* JSFunction::initial_map() {
2817  return Map::cast(prototype_or_initial_map());
2818}
2819
2820
2821void JSFunction::set_initial_map(Map* value) {
2822  set_prototype_or_initial_map(value);
2823}
2824
2825
2826bool JSFunction::has_initial_map() {
2827  return prototype_or_initial_map()->IsMap();
2828}
2829
2830
2831bool JSFunction::has_instance_prototype() {
2832  return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2833}
2834
2835
2836bool JSFunction::has_prototype() {
2837  return map()->has_non_instance_prototype() || has_instance_prototype();
2838}
2839
2840
2841Object* JSFunction::instance_prototype() {
2842  ASSERT(has_instance_prototype());
2843  if (has_initial_map()) return initial_map()->prototype();
2844  // When there is no initial map and the prototype is a JSObject, the
2845  // initial map field is used for the prototype field.
2846  return prototype_or_initial_map();
2847}
2848
2849
2850Object* JSFunction::prototype() {
2851  ASSERT(has_prototype());
2852  // If the function's prototype property has been set to a non-JSObject
2853  // value, that value is stored in the constructor field of the map.
2854  if (map()->has_non_instance_prototype()) return map()->constructor();
2855  return instance_prototype();
2856}
2857
2858bool JSFunction::should_have_prototype() {
2859  return map()->function_with_prototype();
2860}
2861
2862
2863bool JSFunction::is_compiled() {
2864  return code() != Builtins::builtin(Builtins::LazyCompile);
2865}
2866
2867
2868int JSFunction::NumberOfLiterals() {
2869  return literals()->length();
2870}
2871
2872
2873Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2874  ASSERT(0 <= id && id < kJSBuiltinsCount);
2875  return READ_FIELD(this, OffsetOfFunctionWithId(id));
2876}
2877
2878
2879void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2880                                              Object* value) {
2881  ASSERT(0 <= id && id < kJSBuiltinsCount);
2882  WRITE_FIELD(this, OffsetOfFunctionWithId(id), value);
2883  WRITE_BARRIER(this, OffsetOfFunctionWithId(id));
2884}
2885
2886
2887Code* JSBuiltinsObject::javascript_builtin_code(Builtins::JavaScript id) {
2888  ASSERT(0 <= id && id < kJSBuiltinsCount);
2889  return Code::cast(READ_FIELD(this, OffsetOfCodeWithId(id)));
2890}
2891
2892
2893void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
2894                                                   Code* value) {
2895  ASSERT(0 <= id && id < kJSBuiltinsCount);
2896  WRITE_FIELD(this, OffsetOfCodeWithId(id), value);
2897  ASSERT(!Heap::InNewSpace(value));
2898}
2899
2900
2901Address Proxy::proxy() {
2902  return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2903}
2904
2905
2906void Proxy::set_proxy(Address value) {
2907  WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2908}
2909
2910
2911ACCESSORS(JSValue, value, Object, kValueOffset)
2912
2913
2914JSValue* JSValue::cast(Object* obj) {
2915  ASSERT(obj->IsJSValue());
2916  ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2917  return reinterpret_cast<JSValue*>(obj);
2918}
2919
2920
2921INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2922ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
2923
2924
2925byte* Code::instruction_start()  {
2926  return FIELD_ADDR(this, kHeaderSize);
2927}
2928
2929
2930byte* Code::instruction_end()  {
2931  return instruction_start() + instruction_size();
2932}
2933
2934
2935int Code::body_size() {
2936  return RoundUp(instruction_size(), kObjectAlignment);
2937}
2938
2939
2940ByteArray* Code::unchecked_relocation_info() {
2941  return reinterpret_cast<ByteArray*>(READ_FIELD(this, kRelocationInfoOffset));
2942}
2943
2944
2945byte* Code::relocation_start() {
2946  return unchecked_relocation_info()->GetDataStartAddress();
2947}
2948
2949
2950int Code::relocation_size() {
2951  return unchecked_relocation_info()->length();
2952}
2953
2954
2955byte* Code::entry() {
2956  return instruction_start();
2957}
2958
2959
2960bool Code::contains(byte* pc) {
2961  return (instruction_start() <= pc) &&
2962      (pc <= instruction_start() + instruction_size());
2963}
2964
2965
2966ACCESSORS(JSArray, length, Object, kLengthOffset)
2967
2968
2969ACCESSORS(JSRegExp, data, Object, kDataOffset)
2970
2971
2972JSRegExp::Type JSRegExp::TypeTag() {
2973  Object* data = this->data();
2974  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2975  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2976  return static_cast<JSRegExp::Type>(smi->value());
2977}
2978
2979
2980int JSRegExp::CaptureCount() {
2981  switch (TypeTag()) {
2982    case ATOM:
2983      return 0;
2984    case IRREGEXP:
2985      return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2986    default:
2987      UNREACHABLE();
2988      return -1;
2989  }
2990}
2991
2992
2993JSRegExp::Flags JSRegExp::GetFlags() {
2994  ASSERT(this->data()->IsFixedArray());
2995  Object* data = this->data();
2996  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2997  return Flags(smi->value());
2998}
2999
3000
3001String* JSRegExp::Pattern() {
3002  ASSERT(this->data()->IsFixedArray());
3003  Object* data = this->data();
3004  String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
3005  return pattern;
3006}
3007
3008
3009Object* JSRegExp::DataAt(int index) {
3010  ASSERT(TypeTag() != NOT_COMPILED);
3011  return FixedArray::cast(data())->get(index);
3012}
3013
3014
3015void JSRegExp::SetDataAt(int index, Object* value) {
3016  ASSERT(TypeTag() != NOT_COMPILED);
3017  ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
3018  FixedArray::cast(data())->set(index, value);
3019}
3020
3021
3022JSObject::ElementsKind JSObject::GetElementsKind() {
3023  if (map()->has_fast_elements()) {
3024    ASSERT(elements()->map() == Heap::fixed_array_map() ||
3025           elements()->map() == Heap::fixed_cow_array_map());
3026    return FAST_ELEMENTS;
3027  }
3028  HeapObject* array = elements();
3029  if (array->IsFixedArray()) {
3030    // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
3031    // FixedArray, but FAST_ELEMENTS is already handled above.
3032    ASSERT(array->IsDictionary());
3033    return DICTIONARY_ELEMENTS;
3034  }
3035  if (array->IsExternalArray()) {
3036    switch (array->map()->instance_type()) {
3037      case EXTERNAL_BYTE_ARRAY_TYPE:
3038        return EXTERNAL_BYTE_ELEMENTS;
3039      case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3040        return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3041      case EXTERNAL_SHORT_ARRAY_TYPE:
3042        return EXTERNAL_SHORT_ELEMENTS;
3043      case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3044        return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3045      case EXTERNAL_INT_ARRAY_TYPE:
3046        return EXTERNAL_INT_ELEMENTS;
3047      case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3048        return EXTERNAL_UNSIGNED_INT_ELEMENTS;
3049      default:
3050        ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
3051        return EXTERNAL_FLOAT_ELEMENTS;
3052    }
3053  }
3054  ASSERT(array->IsPixelArray());
3055  return PIXEL_ELEMENTS;
3056}
3057
3058
3059bool JSObject::HasFastElements() {
3060  return GetElementsKind() == FAST_ELEMENTS;
3061}
3062
3063
3064bool JSObject::HasDictionaryElements() {
3065  return GetElementsKind() == DICTIONARY_ELEMENTS;
3066}
3067
3068
3069bool JSObject::HasPixelElements() {
3070  return GetElementsKind() == PIXEL_ELEMENTS;
3071}
3072
3073
3074bool JSObject::HasExternalArrayElements() {
3075  return (HasExternalByteElements() ||
3076          HasExternalUnsignedByteElements() ||
3077          HasExternalShortElements() ||
3078          HasExternalUnsignedShortElements() ||
3079          HasExternalIntElements() ||
3080          HasExternalUnsignedIntElements() ||
3081          HasExternalFloatElements());
3082}
3083
3084
3085bool JSObject::HasExternalByteElements() {
3086  return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
3087}
3088
3089
3090bool JSObject::HasExternalUnsignedByteElements() {
3091  return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3092}
3093
3094
3095bool JSObject::HasExternalShortElements() {
3096  return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
3097}
3098
3099
3100bool JSObject::HasExternalUnsignedShortElements() {
3101  return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3102}
3103
3104
3105bool JSObject::HasExternalIntElements() {
3106  return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
3107}
3108
3109
3110bool JSObject::HasExternalUnsignedIntElements() {
3111  return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
3112}
3113
3114
3115bool JSObject::HasExternalFloatElements() {
3116  return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
3117}
3118
3119
3120bool JSObject::HasNamedInterceptor() {
3121  return map()->has_named_interceptor();
3122}
3123
3124
3125bool JSObject::HasIndexedInterceptor() {
3126  return map()->has_indexed_interceptor();
3127}
3128
3129
3130bool JSObject::AllowsSetElementsLength() {
3131  bool result = elements()->IsFixedArray();
3132  ASSERT(result == (!HasPixelElements() && !HasExternalArrayElements()));
3133  return result;
3134}
3135
3136
3137Object* JSObject::EnsureWritableFastElements() {
3138  ASSERT(HasFastElements());
3139  FixedArray* elems = FixedArray::cast(elements());
3140  if (elems->map() != Heap::fixed_cow_array_map()) return elems;
3141  Object* writable_elems = Heap::CopyFixedArray(elems);
3142  if (writable_elems->IsFailure()) return writable_elems;
3143  FixedArray::cast(writable_elems)->set_map(Heap::fixed_array_map());
3144  set_elements(FixedArray::cast(writable_elems));
3145  Counters::cow_arrays_converted.Increment();
3146  return writable_elems;
3147}
3148
3149
3150StringDictionary* JSObject::property_dictionary() {
3151  ASSERT(!HasFastProperties());
3152  return StringDictionary::cast(properties());
3153}
3154
3155
3156NumberDictionary* JSObject::element_dictionary() {
3157  ASSERT(HasDictionaryElements());
3158  return NumberDictionary::cast(elements());
3159}
3160
3161
3162bool String::IsHashFieldComputed(uint32_t field) {
3163  return (field & kHashNotComputedMask) == 0;
3164}
3165
3166
3167bool String::HasHashCode() {
3168  return IsHashFieldComputed(hash_field());
3169}
3170
3171
3172uint32_t String::Hash() {
3173  // Fast case: has hash code already been computed?
3174  uint32_t field = hash_field();
3175  if (IsHashFieldComputed(field)) return field >> kHashShift;
3176  // Slow case: compute hash code and set it.
3177  return ComputeAndSetHash();
3178}
3179
3180
3181StringHasher::StringHasher(int length)
3182  : length_(length),
3183    raw_running_hash_(0),
3184    array_index_(0),
3185    is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
3186    is_first_char_(true),
3187    is_valid_(true) { }
3188
3189
3190bool StringHasher::has_trivial_hash() {
3191  return length_ > String::kMaxHashCalcLength;
3192}
3193
3194
3195void StringHasher::AddCharacter(uc32 c) {
3196  // Use the Jenkins one-at-a-time hash function to update the hash
3197  // for the given character.
3198  raw_running_hash_ += c;
3199  raw_running_hash_ += (raw_running_hash_ << 10);
3200  raw_running_hash_ ^= (raw_running_hash_ >> 6);
3201  // Incremental array index computation.
3202  if (is_array_index_) {
3203    if (c < '0' || c > '9') {
3204      is_array_index_ = false;
3205    } else {
3206      int d = c - '0';
3207      if (is_first_char_) {
3208        is_first_char_ = false;
3209        if (c == '0' && length_ > 1) {
3210          is_array_index_ = false;
3211          return;
3212        }
3213      }
3214      if (array_index_ > 429496729U - ((d + 2) >> 3)) {
3215        is_array_index_ = false;
3216      } else {
3217        array_index_ = array_index_ * 10 + d;
3218      }
3219    }
3220  }
3221}
3222
3223
3224void StringHasher::AddCharacterNoIndex(uc32 c) {
3225  ASSERT(!is_array_index());
3226  raw_running_hash_ += c;
3227  raw_running_hash_ += (raw_running_hash_ << 10);
3228  raw_running_hash_ ^= (raw_running_hash_ >> 6);
3229}
3230
3231
3232uint32_t StringHasher::GetHash() {
3233  // Get the calculated raw hash value and do some more bit ops to distribute
3234  // the hash further. Ensure that we never return zero as the hash value.
3235  uint32_t result = raw_running_hash_;
3236  result += (result << 3);
3237  result ^= (result >> 11);
3238  result += (result << 15);
3239  if (result == 0) {
3240    result = 27;
3241  }
3242  return result;
3243}
3244
3245
3246bool String::AsArrayIndex(uint32_t* index) {
3247  uint32_t field = hash_field();
3248  if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
3249    return false;
3250  }
3251  return SlowAsArrayIndex(index);
3252}
3253
3254
3255Object* JSObject::GetPrototype() {
3256  return JSObject::cast(this)->map()->prototype();
3257}
3258
3259
3260PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
3261  return GetPropertyAttributeWithReceiver(this, key);
3262}
3263
3264// TODO(504): this may be useful in other places too where JSGlobalProxy
3265// is used.
3266Object* JSObject::BypassGlobalProxy() {
3267  if (IsJSGlobalProxy()) {
3268    Object* proto = GetPrototype();
3269    if (proto->IsNull()) return Heap::undefined_value();
3270    ASSERT(proto->IsJSGlobalObject());
3271    return proto;
3272  }
3273  return this;
3274}
3275
3276
3277bool JSObject::HasHiddenPropertiesObject() {
3278  ASSERT(!IsJSGlobalProxy());
3279  return GetPropertyAttributePostInterceptor(this,
3280                                             Heap::hidden_symbol(),
3281                                             false) != ABSENT;
3282}
3283
3284
3285Object* JSObject::GetHiddenPropertiesObject() {
3286  ASSERT(!IsJSGlobalProxy());
3287  PropertyAttributes attributes;
3288  return GetLocalPropertyPostInterceptor(this,
3289                                         Heap::hidden_symbol(),
3290                                         &attributes);
3291}
3292
3293
3294Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
3295  ASSERT(!IsJSGlobalProxy());
3296  return SetPropertyPostInterceptor(Heap::hidden_symbol(),
3297                                    hidden_obj,
3298                                    DONT_ENUM);
3299}
3300
3301
3302bool JSObject::HasElement(uint32_t index) {
3303  return HasElementWithReceiver(this, index);
3304}
3305
3306
3307bool AccessorInfo::all_can_read() {
3308  return BooleanBit::get(flag(), kAllCanReadBit);
3309}
3310
3311
3312void AccessorInfo::set_all_can_read(bool value) {
3313  set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
3314}
3315
3316
3317bool AccessorInfo::all_can_write() {
3318  return BooleanBit::get(flag(), kAllCanWriteBit);
3319}
3320
3321
3322void AccessorInfo::set_all_can_write(bool value) {
3323  set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
3324}
3325
3326
3327bool AccessorInfo::prohibits_overwriting() {
3328  return BooleanBit::get(flag(), kProhibitsOverwritingBit);
3329}
3330
3331
3332void AccessorInfo::set_prohibits_overwriting(bool value) {
3333  set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
3334}
3335
3336
3337PropertyAttributes AccessorInfo::property_attributes() {
3338  return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
3339}
3340
3341
3342void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
3343  ASSERT(AttributesField::is_valid(attributes));
3344  int rest_value = flag()->value() & ~AttributesField::mask();
3345  set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
3346}
3347
3348template<typename Shape, typename Key>
3349void Dictionary<Shape, Key>::SetEntry(int entry,
3350                                      Object* key,
3351                                      Object* value,
3352                                      PropertyDetails details) {
3353  ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
3354  int index = HashTable<Shape, Key>::EntryToIndex(entry);
3355  AssertNoAllocation no_gc;
3356  WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
3357  FixedArray::set(index, key, mode);
3358  FixedArray::set(index+1, value, mode);
3359  FixedArray::fast_set(this, index+2, details.AsSmi());
3360}
3361
3362
3363void Map::ClearCodeCache() {
3364  // No write barrier is needed since empty_fixed_array is not in new space.
3365  // Please note this function is used during marking:
3366  //  - MarkCompactCollector::MarkUnmarkedObject
3367  ASSERT(!Heap::InNewSpace(Heap::raw_unchecked_empty_fixed_array()));
3368  WRITE_FIELD(this, kCodeCacheOffset, Heap::raw_unchecked_empty_fixed_array());
3369}
3370
3371
3372void JSArray::EnsureSize(int required_size) {
3373  ASSERT(HasFastElements());
3374  FixedArray* elts = FixedArray::cast(elements());
3375  const int kArraySizeThatFitsComfortablyInNewSpace = 128;
3376  if (elts->length() < required_size) {
3377    // Doubling in size would be overkill, but leave some slack to avoid
3378    // constantly growing.
3379    Expand(required_size + (required_size >> 3));
3380    // It's a performance benefit to keep a frequently used array in new-space.
3381  } else if (!Heap::new_space()->Contains(elts) &&
3382             required_size < kArraySizeThatFitsComfortablyInNewSpace) {
3383    // Expand will allocate a new backing store in new space even if the size
3384    // we asked for isn't larger than what we had before.
3385    Expand(required_size);
3386  }
3387}
3388
3389
3390void JSArray::set_length(Smi* length) {
3391  set_length(static_cast<Object*>(length), SKIP_WRITE_BARRIER);
3392}
3393
3394
3395void JSArray::SetContent(FixedArray* storage) {
3396  set_length(Smi::FromInt(storage->length()));
3397  set_elements(storage);
3398}
3399
3400
3401Object* FixedArray::Copy() {
3402  if (length() == 0) return this;
3403  return Heap::CopyFixedArray(this);
3404}
3405
3406
3407int JSObject::BodyDescriptor::SizeOf(Map* map, HeapObject* object) {
3408  return map->instance_size();
3409}
3410
3411
3412void Proxy::ProxyIterateBody(ObjectVisitor* v) {
3413  v->VisitExternalReference(
3414      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3415}
3416
3417
3418template<typename StaticVisitor>
3419void Proxy::ProxyIterateBody() {
3420  StaticVisitor::VisitExternalReference(
3421      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
3422}
3423
3424
3425void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
3426  typedef v8::String::ExternalAsciiStringResource Resource;
3427  v->VisitExternalAsciiString(
3428      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3429}
3430
3431
3432template<typename StaticVisitor>
3433void ExternalAsciiString::ExternalAsciiStringIterateBody() {
3434  typedef v8::String::ExternalAsciiStringResource Resource;
3435  StaticVisitor::VisitExternalAsciiString(
3436      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3437}
3438
3439
3440void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
3441  typedef v8::String::ExternalStringResource Resource;
3442  v->VisitExternalTwoByteString(
3443      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3444}
3445
3446
3447template<typename StaticVisitor>
3448void ExternalTwoByteString::ExternalTwoByteStringIterateBody() {
3449  typedef v8::String::ExternalStringResource Resource;
3450  StaticVisitor::VisitExternalTwoByteString(
3451      reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
3452}
3453
3454#define SLOT_ADDR(obj, offset) \
3455  reinterpret_cast<Object**>((obj)->address() + offset)
3456
3457template<int start_offset, int end_offset, int size>
3458void FixedBodyDescriptor<start_offset, end_offset, size>::IterateBody(
3459    HeapObject* obj,
3460    ObjectVisitor* v) {
3461    v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, end_offset));
3462}
3463
3464
3465template<int start_offset>
3466void FlexibleBodyDescriptor<start_offset>::IterateBody(HeapObject* obj,
3467                                                       int object_size,
3468                                                       ObjectVisitor* v) {
3469  v->VisitPointers(SLOT_ADDR(obj, start_offset), SLOT_ADDR(obj, object_size));
3470}
3471
3472#undef SLOT_ADDR
3473
3474
3475#undef CAST_ACCESSOR
3476#undef INT_ACCESSORS
3477#undef SMI_ACCESSORS
3478#undef ACCESSORS
3479#undef FIELD_ADDR
3480#undef READ_FIELD
3481#undef WRITE_FIELD
3482#undef WRITE_BARRIER
3483#undef CONDITIONAL_WRITE_BARRIER
3484#undef READ_MEMADDR_FIELD
3485#undef WRITE_MEMADDR_FIELD
3486#undef READ_DOUBLE_FIELD
3487#undef WRITE_DOUBLE_FIELD
3488#undef READ_INT_FIELD
3489#undef WRITE_INT_FIELD
3490#undef READ_SHORT_FIELD
3491#undef WRITE_SHORT_FIELD
3492#undef READ_BYTE_FIELD
3493#undef WRITE_BYTE_FIELD
3494
3495
3496} }  // namespace v8::internal
3497
3498#endif  // V8_OBJECTS_INL_H_
3499