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