objects-inl.h revision e46be819fca9468a0cd4e74859ce0f778eb8ca60
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() {
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  WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
1371}
1372
1373
1374void FixedArray::set_undefined(int index) {
1375  ASSERT(index >= 0 && index < this->length());
1376  ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
1377  WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
1378              Heap::undefined_value());
1379}
1380
1381
1382void FixedArray::set_null(int index) {
1383  ASSERT(index >= 0 && index < this->length());
1384  ASSERT(!Heap::InNewSpace(Heap::null_value()));
1385  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
1386}
1387
1388
1389void FixedArray::set_the_hole(int index) {
1390  ASSERT(index >= 0 && index < this->length());
1391  ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
1392  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
1393}
1394
1395
1396bool DescriptorArray::IsEmpty() {
1397  ASSERT(this == Heap::empty_descriptor_array() ||
1398         this->length() > 2);
1399  return this == Heap::empty_descriptor_array();
1400}
1401
1402
1403void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
1404  Object* tmp = array->get(first);
1405  fast_set(array, first, array->get(second));
1406  fast_set(array, second, tmp);
1407}
1408
1409
1410int DescriptorArray::Search(String* name) {
1411  SLOW_ASSERT(IsSortedNoDuplicates());
1412
1413  // Check for empty descriptor array.
1414  int nof = number_of_descriptors();
1415  if (nof == 0) return kNotFound;
1416
1417  // Fast case: do linear search for small arrays.
1418  const int kMaxElementsForLinearSearch = 8;
1419  if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) {
1420    return LinearSearch(name, nof);
1421  }
1422
1423  // Slow case: perform binary search.
1424  return BinarySearch(name, 0, nof - 1);
1425}
1426
1427
1428String* DescriptorArray::GetKey(int descriptor_number) {
1429  ASSERT(descriptor_number < number_of_descriptors());
1430  return String::cast(get(ToKeyIndex(descriptor_number)));
1431}
1432
1433
1434Object* DescriptorArray::GetValue(int descriptor_number) {
1435  ASSERT(descriptor_number < number_of_descriptors());
1436  return GetContentArray()->get(ToValueIndex(descriptor_number));
1437}
1438
1439
1440Smi* DescriptorArray::GetDetails(int descriptor_number) {
1441  ASSERT(descriptor_number < number_of_descriptors());
1442  return Smi::cast(GetContentArray()->get(ToDetailsIndex(descriptor_number)));
1443}
1444
1445
1446PropertyType DescriptorArray::GetType(int descriptor_number) {
1447  ASSERT(descriptor_number < number_of_descriptors());
1448  return PropertyDetails(GetDetails(descriptor_number)).type();
1449}
1450
1451
1452int DescriptorArray::GetFieldIndex(int descriptor_number) {
1453  return Descriptor::IndexFromValue(GetValue(descriptor_number));
1454}
1455
1456
1457JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
1458  return JSFunction::cast(GetValue(descriptor_number));
1459}
1460
1461
1462Object* DescriptorArray::GetCallbacksObject(int descriptor_number) {
1463  ASSERT(GetType(descriptor_number) == CALLBACKS);
1464  return GetValue(descriptor_number);
1465}
1466
1467
1468AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) {
1469  ASSERT(GetType(descriptor_number) == CALLBACKS);
1470  Proxy* p = Proxy::cast(GetCallbacksObject(descriptor_number));
1471  return reinterpret_cast<AccessorDescriptor*>(p->proxy());
1472}
1473
1474
1475bool DescriptorArray::IsProperty(int descriptor_number) {
1476  return GetType(descriptor_number) < FIRST_PHANTOM_PROPERTY_TYPE;
1477}
1478
1479
1480bool DescriptorArray::IsTransition(int descriptor_number) {
1481  PropertyType t = GetType(descriptor_number);
1482  return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
1483}
1484
1485
1486bool DescriptorArray::IsNullDescriptor(int descriptor_number) {
1487  return GetType(descriptor_number) == NULL_DESCRIPTOR;
1488}
1489
1490
1491bool DescriptorArray::IsDontEnum(int descriptor_number) {
1492  return PropertyDetails(GetDetails(descriptor_number)).IsDontEnum();
1493}
1494
1495
1496void DescriptorArray::Get(int descriptor_number, Descriptor* desc) {
1497  desc->Init(GetKey(descriptor_number),
1498             GetValue(descriptor_number),
1499             GetDetails(descriptor_number));
1500}
1501
1502
1503void DescriptorArray::Set(int descriptor_number, Descriptor* desc) {
1504  // Range check.
1505  ASSERT(descriptor_number < number_of_descriptors());
1506
1507  // Make sure none of the elements in desc are in new space.
1508  ASSERT(!Heap::InNewSpace(desc->GetKey()));
1509  ASSERT(!Heap::InNewSpace(desc->GetValue()));
1510
1511  fast_set(this, ToKeyIndex(descriptor_number), desc->GetKey());
1512  FixedArray* content_array = GetContentArray();
1513  fast_set(content_array, ToValueIndex(descriptor_number), desc->GetValue());
1514  fast_set(content_array, ToDetailsIndex(descriptor_number),
1515           desc->GetDetails().AsSmi());
1516}
1517
1518
1519void DescriptorArray::CopyFrom(int index, DescriptorArray* src, int src_index) {
1520  Descriptor desc;
1521  src->Get(src_index, &desc);
1522  Set(index, &desc);
1523}
1524
1525
1526void DescriptorArray::Swap(int first, int second) {
1527  fast_swap(this, ToKeyIndex(first), ToKeyIndex(second));
1528  FixedArray* content_array = GetContentArray();
1529  fast_swap(content_array, ToValueIndex(first), ToValueIndex(second));
1530  fast_swap(content_array, ToDetailsIndex(first),  ToDetailsIndex(second));
1531}
1532
1533
1534bool NumberDictionary::requires_slow_elements() {
1535  Object* max_index_object = get(kMaxNumberKeyIndex);
1536  if (!max_index_object->IsSmi()) return false;
1537  return 0 !=
1538      (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask);
1539}
1540
1541uint32_t NumberDictionary::max_number_key() {
1542  ASSERT(!requires_slow_elements());
1543  Object* max_index_object = get(kMaxNumberKeyIndex);
1544  if (!max_index_object->IsSmi()) return 0;
1545  uint32_t value = static_cast<uint32_t>(Smi::cast(max_index_object)->value());
1546  return value >> kRequiresSlowElementsTagSize;
1547}
1548
1549void NumberDictionary::set_requires_slow_elements() {
1550  set(kMaxNumberKeyIndex,
1551      Smi::FromInt(kRequiresSlowElementsMask),
1552      SKIP_WRITE_BARRIER);
1553}
1554
1555
1556// ------------------------------------
1557// Cast operations
1558
1559
1560CAST_ACCESSOR(FixedArray)
1561CAST_ACCESSOR(DescriptorArray)
1562CAST_ACCESSOR(SymbolTable)
1563CAST_ACCESSOR(CompilationCacheTable)
1564CAST_ACCESSOR(MapCache)
1565CAST_ACCESSOR(String)
1566CAST_ACCESSOR(SeqString)
1567CAST_ACCESSOR(SeqAsciiString)
1568CAST_ACCESSOR(SeqTwoByteString)
1569CAST_ACCESSOR(ConsString)
1570CAST_ACCESSOR(ExternalString)
1571CAST_ACCESSOR(ExternalAsciiString)
1572CAST_ACCESSOR(ExternalTwoByteString)
1573CAST_ACCESSOR(JSObject)
1574CAST_ACCESSOR(Smi)
1575CAST_ACCESSOR(Failure)
1576CAST_ACCESSOR(HeapObject)
1577CAST_ACCESSOR(HeapNumber)
1578CAST_ACCESSOR(Oddball)
1579CAST_ACCESSOR(JSGlobalPropertyCell)
1580CAST_ACCESSOR(SharedFunctionInfo)
1581CAST_ACCESSOR(Map)
1582CAST_ACCESSOR(JSFunction)
1583CAST_ACCESSOR(GlobalObject)
1584CAST_ACCESSOR(JSGlobalProxy)
1585CAST_ACCESSOR(JSGlobalObject)
1586CAST_ACCESSOR(JSBuiltinsObject)
1587CAST_ACCESSOR(Code)
1588CAST_ACCESSOR(JSArray)
1589CAST_ACCESSOR(JSRegExp)
1590CAST_ACCESSOR(Proxy)
1591CAST_ACCESSOR(ByteArray)
1592CAST_ACCESSOR(PixelArray)
1593CAST_ACCESSOR(ExternalArray)
1594CAST_ACCESSOR(ExternalByteArray)
1595CAST_ACCESSOR(ExternalUnsignedByteArray)
1596CAST_ACCESSOR(ExternalShortArray)
1597CAST_ACCESSOR(ExternalUnsignedShortArray)
1598CAST_ACCESSOR(ExternalIntArray)
1599CAST_ACCESSOR(ExternalUnsignedIntArray)
1600CAST_ACCESSOR(ExternalFloatArray)
1601CAST_ACCESSOR(Struct)
1602
1603
1604#define MAKE_STRUCT_CAST(NAME, Name, name) CAST_ACCESSOR(Name)
1605  STRUCT_LIST(MAKE_STRUCT_CAST)
1606#undef MAKE_STRUCT_CAST
1607
1608
1609template <typename Shape, typename Key>
1610HashTable<Shape, Key>* HashTable<Shape, Key>::cast(Object* obj) {
1611  ASSERT(obj->IsHashTable());
1612  return reinterpret_cast<HashTable*>(obj);
1613}
1614
1615
1616INT_ACCESSORS(Array, length, kLengthOffset)
1617
1618
1619INT_ACCESSORS(String, length, kLengthOffset)
1620
1621
1622uint32_t String::hash_field() {
1623  return READ_UINT32_FIELD(this, kHashFieldOffset);
1624}
1625
1626
1627void String::set_hash_field(uint32_t value) {
1628  WRITE_UINT32_FIELD(this, kHashFieldOffset, value);
1629}
1630
1631
1632bool String::Equals(String* other) {
1633  if (other == this) return true;
1634  if (StringShape(this).IsSymbol() && StringShape(other).IsSymbol()) {
1635    return false;
1636  }
1637  return SlowEquals(other);
1638}
1639
1640
1641Object* String::TryFlattenIfNotFlat() {
1642  // We don't need to flatten strings that are already flat.  Since this code
1643  // is inlined, it can be helpful in the flat case to not call out to Flatten.
1644  if (!IsFlat()) {
1645    return TryFlatten();
1646  }
1647  return this;
1648}
1649
1650
1651uint16_t String::Get(int index) {
1652  ASSERT(index >= 0 && index < length());
1653  switch (StringShape(this).full_representation_tag()) {
1654    case kSeqStringTag | kAsciiStringTag:
1655      return SeqAsciiString::cast(this)->SeqAsciiStringGet(index);
1656    case kSeqStringTag | kTwoByteStringTag:
1657      return SeqTwoByteString::cast(this)->SeqTwoByteStringGet(index);
1658    case kConsStringTag | kAsciiStringTag:
1659    case kConsStringTag | kTwoByteStringTag:
1660      return ConsString::cast(this)->ConsStringGet(index);
1661    case kExternalStringTag | kAsciiStringTag:
1662      return ExternalAsciiString::cast(this)->ExternalAsciiStringGet(index);
1663    case kExternalStringTag | kTwoByteStringTag:
1664      return ExternalTwoByteString::cast(this)->ExternalTwoByteStringGet(index);
1665    default:
1666      break;
1667  }
1668
1669  UNREACHABLE();
1670  return 0;
1671}
1672
1673
1674void String::Set(int index, uint16_t value) {
1675  ASSERT(index >= 0 && index < length());
1676  ASSERT(StringShape(this).IsSequential());
1677
1678  return this->IsAsciiRepresentation()
1679      ? SeqAsciiString::cast(this)->SeqAsciiStringSet(index, value)
1680      : SeqTwoByteString::cast(this)->SeqTwoByteStringSet(index, value);
1681}
1682
1683
1684bool String::IsFlat() {
1685  switch (StringShape(this).representation_tag()) {
1686    case kConsStringTag: {
1687      String* second = ConsString::cast(this)->second();
1688      // Only flattened strings have second part empty.
1689      return second->length() == 0;
1690    }
1691    default:
1692      return true;
1693  }
1694}
1695
1696
1697uint16_t SeqAsciiString::SeqAsciiStringGet(int index) {
1698  ASSERT(index >= 0 && index < length());
1699  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1700}
1701
1702
1703void SeqAsciiString::SeqAsciiStringSet(int index, uint16_t value) {
1704  ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
1705  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
1706                   static_cast<byte>(value));
1707}
1708
1709
1710Address SeqAsciiString::GetCharsAddress() {
1711  return FIELD_ADDR(this, kHeaderSize);
1712}
1713
1714
1715char* SeqAsciiString::GetChars() {
1716  return reinterpret_cast<char*>(GetCharsAddress());
1717}
1718
1719
1720Address SeqTwoByteString::GetCharsAddress() {
1721  return FIELD_ADDR(this, kHeaderSize);
1722}
1723
1724
1725uc16* SeqTwoByteString::GetChars() {
1726  return reinterpret_cast<uc16*>(FIELD_ADDR(this, kHeaderSize));
1727}
1728
1729
1730uint16_t SeqTwoByteString::SeqTwoByteStringGet(int index) {
1731  ASSERT(index >= 0 && index < length());
1732  return READ_SHORT_FIELD(this, kHeaderSize + index * kShortSize);
1733}
1734
1735
1736void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
1737  ASSERT(index >= 0 && index < length());
1738  WRITE_SHORT_FIELD(this, kHeaderSize + index * kShortSize, value);
1739}
1740
1741
1742int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
1743  uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1744  return SizeFor(length);
1745}
1746
1747
1748int SeqAsciiString::SeqAsciiStringSize(InstanceType instance_type) {
1749  uint32_t length = READ_INT_FIELD(this, kLengthOffset);
1750  return SizeFor(length);
1751}
1752
1753
1754String* ConsString::first() {
1755  return String::cast(READ_FIELD(this, kFirstOffset));
1756}
1757
1758
1759Object* ConsString::unchecked_first() {
1760  return READ_FIELD(this, kFirstOffset);
1761}
1762
1763
1764void ConsString::set_first(String* value, WriteBarrierMode mode) {
1765  WRITE_FIELD(this, kFirstOffset, value);
1766  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
1767}
1768
1769
1770String* ConsString::second() {
1771  return String::cast(READ_FIELD(this, kSecondOffset));
1772}
1773
1774
1775Object* ConsString::unchecked_second() {
1776  return READ_FIELD(this, kSecondOffset);
1777}
1778
1779
1780void ConsString::set_second(String* value, WriteBarrierMode mode) {
1781  WRITE_FIELD(this, kSecondOffset, value);
1782  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
1783}
1784
1785
1786ExternalAsciiString::Resource* ExternalAsciiString::resource() {
1787  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1788}
1789
1790
1791void ExternalAsciiString::set_resource(
1792    ExternalAsciiString::Resource* resource) {
1793  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1794}
1795
1796
1797ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
1798  return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
1799}
1800
1801
1802void ExternalTwoByteString::set_resource(
1803    ExternalTwoByteString::Resource* resource) {
1804  *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
1805}
1806
1807
1808byte ByteArray::get(int index) {
1809  ASSERT(index >= 0 && index < this->length());
1810  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
1811}
1812
1813
1814void ByteArray::set(int index, byte value) {
1815  ASSERT(index >= 0 && index < this->length());
1816  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
1817}
1818
1819
1820int ByteArray::get_int(int index) {
1821  ASSERT(index >= 0 && (index * kIntSize) < this->length());
1822  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
1823}
1824
1825
1826ByteArray* ByteArray::FromDataStartAddress(Address address) {
1827  ASSERT_TAG_ALIGNED(address);
1828  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
1829}
1830
1831
1832Address ByteArray::GetDataStartAddress() {
1833  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
1834}
1835
1836
1837uint8_t* PixelArray::external_pointer() {
1838  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1839  return reinterpret_cast<uint8_t*>(ptr);
1840}
1841
1842
1843void PixelArray::set_external_pointer(uint8_t* value, WriteBarrierMode mode) {
1844  intptr_t ptr = reinterpret_cast<intptr_t>(value);
1845  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1846}
1847
1848
1849uint8_t PixelArray::get(int index) {
1850  ASSERT((index >= 0) && (index < this->length()));
1851  uint8_t* ptr = external_pointer();
1852  return ptr[index];
1853}
1854
1855
1856void PixelArray::set(int index, uint8_t value) {
1857  ASSERT((index >= 0) && (index < this->length()));
1858  uint8_t* ptr = external_pointer();
1859  ptr[index] = value;
1860}
1861
1862
1863void* ExternalArray::external_pointer() {
1864  intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
1865  return reinterpret_cast<void*>(ptr);
1866}
1867
1868
1869void ExternalArray::set_external_pointer(void* value, WriteBarrierMode mode) {
1870  intptr_t ptr = reinterpret_cast<intptr_t>(value);
1871  WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
1872}
1873
1874
1875int8_t ExternalByteArray::get(int index) {
1876  ASSERT((index >= 0) && (index < this->length()));
1877  int8_t* ptr = static_cast<int8_t*>(external_pointer());
1878  return ptr[index];
1879}
1880
1881
1882void ExternalByteArray::set(int index, int8_t value) {
1883  ASSERT((index >= 0) && (index < this->length()));
1884  int8_t* ptr = static_cast<int8_t*>(external_pointer());
1885  ptr[index] = value;
1886}
1887
1888
1889uint8_t ExternalUnsignedByteArray::get(int index) {
1890  ASSERT((index >= 0) && (index < this->length()));
1891  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1892  return ptr[index];
1893}
1894
1895
1896void ExternalUnsignedByteArray::set(int index, uint8_t value) {
1897  ASSERT((index >= 0) && (index < this->length()));
1898  uint8_t* ptr = static_cast<uint8_t*>(external_pointer());
1899  ptr[index] = value;
1900}
1901
1902
1903int16_t ExternalShortArray::get(int index) {
1904  ASSERT((index >= 0) && (index < this->length()));
1905  int16_t* ptr = static_cast<int16_t*>(external_pointer());
1906  return ptr[index];
1907}
1908
1909
1910void ExternalShortArray::set(int index, int16_t value) {
1911  ASSERT((index >= 0) && (index < this->length()));
1912  int16_t* ptr = static_cast<int16_t*>(external_pointer());
1913  ptr[index] = value;
1914}
1915
1916
1917uint16_t ExternalUnsignedShortArray::get(int index) {
1918  ASSERT((index >= 0) && (index < this->length()));
1919  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1920  return ptr[index];
1921}
1922
1923
1924void ExternalUnsignedShortArray::set(int index, uint16_t value) {
1925  ASSERT((index >= 0) && (index < this->length()));
1926  uint16_t* ptr = static_cast<uint16_t*>(external_pointer());
1927  ptr[index] = value;
1928}
1929
1930
1931int32_t ExternalIntArray::get(int index) {
1932  ASSERT((index >= 0) && (index < this->length()));
1933  int32_t* ptr = static_cast<int32_t*>(external_pointer());
1934  return ptr[index];
1935}
1936
1937
1938void ExternalIntArray::set(int index, int32_t value) {
1939  ASSERT((index >= 0) && (index < this->length()));
1940  int32_t* ptr = static_cast<int32_t*>(external_pointer());
1941  ptr[index] = value;
1942}
1943
1944
1945uint32_t ExternalUnsignedIntArray::get(int index) {
1946  ASSERT((index >= 0) && (index < this->length()));
1947  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1948  return ptr[index];
1949}
1950
1951
1952void ExternalUnsignedIntArray::set(int index, uint32_t value) {
1953  ASSERT((index >= 0) && (index < this->length()));
1954  uint32_t* ptr = static_cast<uint32_t*>(external_pointer());
1955  ptr[index] = value;
1956}
1957
1958
1959float ExternalFloatArray::get(int index) {
1960  ASSERT((index >= 0) && (index < this->length()));
1961  float* ptr = static_cast<float*>(external_pointer());
1962  return ptr[index];
1963}
1964
1965
1966void ExternalFloatArray::set(int index, float value) {
1967  ASSERT((index >= 0) && (index < this->length()));
1968  float* ptr = static_cast<float*>(external_pointer());
1969  ptr[index] = value;
1970}
1971
1972
1973int Map::instance_size() {
1974  return READ_BYTE_FIELD(this, kInstanceSizeOffset) << kPointerSizeLog2;
1975}
1976
1977
1978int Map::inobject_properties() {
1979  return READ_BYTE_FIELD(this, kInObjectPropertiesOffset);
1980}
1981
1982
1983int Map::pre_allocated_property_fields() {
1984  return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
1985}
1986
1987
1988int HeapObject::SizeFromMap(Map* map) {
1989  InstanceType instance_type = map->instance_type();
1990  // Only inline the most frequent cases.
1991  if (instance_type == JS_OBJECT_TYPE ||
1992      (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
1993      (kStringTag | kConsStringTag) ||
1994      instance_type == JS_ARRAY_TYPE) return map->instance_size();
1995  if (instance_type == FIXED_ARRAY_TYPE) {
1996    return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
1997  }
1998  if (instance_type == BYTE_ARRAY_TYPE) {
1999    return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
2000  }
2001  // Otherwise do the general size computation.
2002  return SlowSizeFromMap(map);
2003}
2004
2005
2006void Map::set_instance_size(int value) {
2007  ASSERT_EQ(0, value & (kPointerSize - 1));
2008  value >>= kPointerSizeLog2;
2009  ASSERT(0 <= value && value < 256);
2010  WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));
2011}
2012
2013
2014void Map::set_inobject_properties(int value) {
2015  ASSERT(0 <= value && value < 256);
2016  WRITE_BYTE_FIELD(this, kInObjectPropertiesOffset, static_cast<byte>(value));
2017}
2018
2019
2020void Map::set_pre_allocated_property_fields(int value) {
2021  ASSERT(0 <= value && value < 256);
2022  WRITE_BYTE_FIELD(this,
2023                   kPreAllocatedPropertyFieldsOffset,
2024                   static_cast<byte>(value));
2025}
2026
2027
2028InstanceType Map::instance_type() {
2029  return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
2030}
2031
2032
2033void Map::set_instance_type(InstanceType value) {
2034  ASSERT(0 <= value && value < 256);
2035  WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
2036}
2037
2038
2039int Map::unused_property_fields() {
2040  return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
2041}
2042
2043
2044void Map::set_unused_property_fields(int value) {
2045  WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
2046}
2047
2048
2049byte Map::bit_field() {
2050  return READ_BYTE_FIELD(this, kBitFieldOffset);
2051}
2052
2053
2054void Map::set_bit_field(byte value) {
2055  WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
2056}
2057
2058
2059byte Map::bit_field2() {
2060  return READ_BYTE_FIELD(this, kBitField2Offset);
2061}
2062
2063
2064void Map::set_bit_field2(byte value) {
2065  WRITE_BYTE_FIELD(this, kBitField2Offset, value);
2066}
2067
2068
2069void Map::set_non_instance_prototype(bool value) {
2070  if (value) {
2071    set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
2072  } else {
2073    set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
2074  }
2075}
2076
2077
2078bool Map::has_non_instance_prototype() {
2079  return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
2080}
2081
2082
2083void Map::set_is_access_check_needed(bool access_check_needed) {
2084  if (access_check_needed) {
2085    set_bit_field(bit_field() | (1 << kIsAccessCheckNeeded));
2086  } else {
2087    set_bit_field(bit_field() & ~(1 << kIsAccessCheckNeeded));
2088  }
2089}
2090
2091
2092bool Map::is_access_check_needed() {
2093  return ((1 << kIsAccessCheckNeeded) & bit_field()) != 0;
2094}
2095
2096
2097Code::Flags Code::flags() {
2098  return static_cast<Flags>(READ_INT_FIELD(this, kFlagsOffset));
2099}
2100
2101
2102void Code::set_flags(Code::Flags flags) {
2103  STATIC_ASSERT(Code::NUMBER_OF_KINDS <= (kFlagsKindMask >> kFlagsKindShift)+1);
2104  // Make sure that all call stubs have an arguments count.
2105  ASSERT(ExtractKindFromFlags(flags) != CALL_IC ||
2106         ExtractArgumentsCountFromFlags(flags) >= 0);
2107  WRITE_INT_FIELD(this, kFlagsOffset, flags);
2108}
2109
2110
2111Code::Kind Code::kind() {
2112  return ExtractKindFromFlags(flags());
2113}
2114
2115
2116InLoopFlag Code::ic_in_loop() {
2117  return ExtractICInLoopFromFlags(flags());
2118}
2119
2120
2121InlineCacheState Code::ic_state() {
2122  InlineCacheState result = ExtractICStateFromFlags(flags());
2123  // Only allow uninitialized or debugger states for non-IC code
2124  // objects. This is used in the debugger to determine whether or not
2125  // a call to code object has been replaced with a debug break call.
2126  ASSERT(is_inline_cache_stub() ||
2127         result == UNINITIALIZED ||
2128         result == DEBUG_BREAK ||
2129         result == DEBUG_PREPARE_STEP_IN);
2130  return result;
2131}
2132
2133
2134PropertyType Code::type() {
2135  ASSERT(ic_state() == MONOMORPHIC);
2136  return ExtractTypeFromFlags(flags());
2137}
2138
2139
2140int Code::arguments_count() {
2141  ASSERT(is_call_stub() || kind() == STUB);
2142  return ExtractArgumentsCountFromFlags(flags());
2143}
2144
2145
2146CodeStub::Major Code::major_key() {
2147  ASSERT(kind() == STUB);
2148  return static_cast<CodeStub::Major>(READ_BYTE_FIELD(this,
2149                                                      kStubMajorKeyOffset));
2150}
2151
2152
2153void Code::set_major_key(CodeStub::Major major) {
2154  ASSERT(kind() == STUB);
2155  ASSERT(0 <= major && major < 256);
2156  WRITE_BYTE_FIELD(this, kStubMajorKeyOffset, major);
2157}
2158
2159
2160bool Code::is_inline_cache_stub() {
2161  Kind kind = this->kind();
2162  return kind >= FIRST_IC_KIND && kind <= LAST_IC_KIND;
2163}
2164
2165
2166Code::Flags Code::ComputeFlags(Kind kind,
2167                               InLoopFlag in_loop,
2168                               InlineCacheState ic_state,
2169                               PropertyType type,
2170                               int argc) {
2171  // Compute the bit mask.
2172  int bits = kind << kFlagsKindShift;
2173  if (in_loop) bits |= kFlagsICInLoopMask;
2174  bits |= ic_state << kFlagsICStateShift;
2175  bits |= type << kFlagsTypeShift;
2176  bits |= argc << kFlagsArgumentsCountShift;
2177  // Cast to flags and validate result before returning it.
2178  Flags result = static_cast<Flags>(bits);
2179  ASSERT(ExtractKindFromFlags(result) == kind);
2180  ASSERT(ExtractICStateFromFlags(result) == ic_state);
2181  ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
2182  ASSERT(ExtractTypeFromFlags(result) == type);
2183  ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
2184  return result;
2185}
2186
2187
2188Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
2189                                          PropertyType type,
2190                                          InLoopFlag in_loop,
2191                                          int argc) {
2192  return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
2193}
2194
2195
2196Code::Kind Code::ExtractKindFromFlags(Flags flags) {
2197  int bits = (flags & kFlagsKindMask) >> kFlagsKindShift;
2198  return static_cast<Kind>(bits);
2199}
2200
2201
2202InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
2203  int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
2204  return static_cast<InlineCacheState>(bits);
2205}
2206
2207
2208InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
2209  int bits = (flags & kFlagsICInLoopMask);
2210  return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
2211}
2212
2213
2214PropertyType Code::ExtractTypeFromFlags(Flags flags) {
2215  int bits = (flags & kFlagsTypeMask) >> kFlagsTypeShift;
2216  return static_cast<PropertyType>(bits);
2217}
2218
2219
2220int Code::ExtractArgumentsCountFromFlags(Flags flags) {
2221  return (flags & kFlagsArgumentsCountMask) >> kFlagsArgumentsCountShift;
2222}
2223
2224
2225Code::Flags Code::RemoveTypeFromFlags(Flags flags) {
2226  int bits = flags & ~kFlagsTypeMask;
2227  return static_cast<Flags>(bits);
2228}
2229
2230
2231Code* Code::GetCodeFromTargetAddress(Address address) {
2232  HeapObject* code = HeapObject::FromAddress(address - Code::kHeaderSize);
2233  // GetCodeFromTargetAddress might be called when marking objects during mark
2234  // sweep. reinterpret_cast is therefore used instead of the more appropriate
2235  // Code::cast. Code::cast does not work when the object's map is
2236  // marked.
2237  Code* result = reinterpret_cast<Code*>(code);
2238  return result;
2239}
2240
2241
2242Object* Map::prototype() {
2243  return READ_FIELD(this, kPrototypeOffset);
2244}
2245
2246
2247void Map::set_prototype(Object* value, WriteBarrierMode mode) {
2248  ASSERT(value->IsNull() || value->IsJSObject());
2249  WRITE_FIELD(this, kPrototypeOffset, value);
2250  CONDITIONAL_WRITE_BARRIER(this, kPrototypeOffset, mode);
2251}
2252
2253
2254ACCESSORS(Map, instance_descriptors, DescriptorArray,
2255          kInstanceDescriptorsOffset)
2256ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
2257ACCESSORS(Map, constructor, Object, kConstructorOffset)
2258
2259ACCESSORS(JSFunction, shared, SharedFunctionInfo, kSharedFunctionInfoOffset)
2260ACCESSORS(JSFunction, literals, FixedArray, kLiteralsOffset)
2261
2262ACCESSORS(GlobalObject, builtins, JSBuiltinsObject, kBuiltinsOffset)
2263ACCESSORS(GlobalObject, global_context, Context, kGlobalContextOffset)
2264ACCESSORS(GlobalObject, global_receiver, JSObject, kGlobalReceiverOffset)
2265
2266ACCESSORS(JSGlobalProxy, context, Object, kContextOffset)
2267
2268ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
2269ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
2270ACCESSORS(AccessorInfo, data, Object, kDataOffset)
2271ACCESSORS(AccessorInfo, name, Object, kNameOffset)
2272ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
2273ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
2274
2275ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
2276ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
2277ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
2278
2279ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
2280ACCESSORS(InterceptorInfo, setter, Object, kSetterOffset)
2281ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
2282ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
2283ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
2284ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
2285
2286ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
2287ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
2288
2289ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
2290ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
2291
2292ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
2293ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
2294ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
2295          kPropertyAccessorsOffset)
2296ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
2297          kPrototypeTemplateOffset)
2298ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
2299ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
2300          kNamedPropertyHandlerOffset)
2301ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
2302          kIndexedPropertyHandlerOffset)
2303ACCESSORS(FunctionTemplateInfo, instance_template, Object,
2304          kInstanceTemplateOffset)
2305ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
2306ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
2307ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
2308          kInstanceCallHandlerOffset)
2309ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
2310          kAccessCheckInfoOffset)
2311ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
2312
2313ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
2314ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
2315          kInternalFieldCountOffset)
2316
2317ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
2318ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
2319
2320ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
2321
2322ACCESSORS(Script, source, Object, kSourceOffset)
2323ACCESSORS(Script, name, Object, kNameOffset)
2324ACCESSORS(Script, id, Object, kIdOffset)
2325ACCESSORS(Script, line_offset, Smi, kLineOffsetOffset)
2326ACCESSORS(Script, column_offset, Smi, kColumnOffsetOffset)
2327ACCESSORS(Script, data, Object, kDataOffset)
2328ACCESSORS(Script, context_data, Object, kContextOffset)
2329ACCESSORS(Script, wrapper, Proxy, kWrapperOffset)
2330ACCESSORS(Script, type, Smi, kTypeOffset)
2331ACCESSORS(Script, compilation_type, Smi, kCompilationTypeOffset)
2332ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
2333ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
2334ACCESSORS(Script, eval_from_instructions_offset, Smi,
2335          kEvalFrominstructionsOffsetOffset)
2336
2337#ifdef ENABLE_DEBUGGER_SUPPORT
2338ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
2339ACCESSORS(DebugInfo, original_code, Code, kOriginalCodeIndex)
2340ACCESSORS(DebugInfo, code, Code, kPatchedCodeIndex)
2341ACCESSORS(DebugInfo, break_points, FixedArray, kBreakPointsStateIndex)
2342
2343ACCESSORS(BreakPointInfo, code_position, Smi, kCodePositionIndex)
2344ACCESSORS(BreakPointInfo, source_position, Smi, kSourcePositionIndex)
2345ACCESSORS(BreakPointInfo, statement_position, Smi, kStatementPositionIndex)
2346ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
2347#endif
2348
2349ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
2350ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
2351ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
2352          kInstanceClassNameOffset)
2353ACCESSORS(SharedFunctionInfo, function_data, Object,
2354          kExternalReferenceDataOffset)
2355ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
2356ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
2357ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
2358ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
2359          kThisPropertyAssignmentsOffset)
2360
2361BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
2362               kHiddenPrototypeBit)
2363BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
2364BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
2365               kNeedsAccessCheckBit)
2366BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
2367               kIsExpressionBit)
2368BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
2369               kIsTopLevelBit)
2370BOOL_GETTER(SharedFunctionInfo, compiler_hints,
2371            has_only_simple_this_property_assignments,
2372            kHasOnlySimpleThisPropertyAssignments)
2373BOOL_ACCESSORS(SharedFunctionInfo,
2374               compiler_hints,
2375               try_fast_codegen,
2376               kTryFastCodegen)
2377
2378INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
2379INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
2380              kFormalParameterCountOffset)
2381INT_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
2382              kExpectedNofPropertiesOffset)
2383INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
2384              kStartPositionAndTypeOffset)
2385INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
2386INT_ACCESSORS(SharedFunctionInfo, function_token_position,
2387              kFunctionTokenPositionOffset)
2388INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
2389              kCompilerHintsOffset)
2390INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
2391              kThisPropertyAssignmentsCountOffset)
2392
2393
2394bool Script::HasValidSource() {
2395  Object* src = this->source();
2396  if (!src->IsString()) return true;
2397  String* src_str = String::cast(src);
2398  if (!StringShape(src_str).IsExternal()) return true;
2399  if (src_str->IsAsciiRepresentation()) {
2400    return ExternalAsciiString::cast(src)->resource() != NULL;
2401  } else if (src_str->IsTwoByteRepresentation()) {
2402    return ExternalTwoByteString::cast(src)->resource() != NULL;
2403  }
2404  return true;
2405}
2406
2407
2408void SharedFunctionInfo::DontAdaptArguments() {
2409  ASSERT(code()->kind() == Code::BUILTIN);
2410  set_formal_parameter_count(kDontAdaptArgumentsSentinel);
2411}
2412
2413
2414int SharedFunctionInfo::start_position() {
2415  return start_position_and_type() >> kStartPositionShift;
2416}
2417
2418
2419void SharedFunctionInfo::set_start_position(int start_position) {
2420  set_start_position_and_type((start_position << kStartPositionShift)
2421    | (start_position_and_type() & ~kStartPositionMask));
2422}
2423
2424
2425Code* SharedFunctionInfo::code() {
2426  return Code::cast(READ_FIELD(this, kCodeOffset));
2427}
2428
2429
2430void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
2431  WRITE_FIELD(this, kCodeOffset, value);
2432  CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
2433}
2434
2435
2436bool SharedFunctionInfo::is_compiled() {
2437  // TODO(1242782): Create a code kind for uncompiled code.
2438  return code()->kind() != Code::STUB;
2439}
2440
2441
2442bool JSFunction::IsBoilerplate() {
2443  return map() == Heap::boilerplate_function_map();
2444}
2445
2446
2447bool JSFunction::IsBuiltin() {
2448  return context()->global()->IsJSBuiltinsObject();
2449}
2450
2451
2452bool JSObject::IsLoaded() {
2453  return !map()->needs_loading();
2454}
2455
2456
2457Code* JSFunction::code() {
2458  return shared()->code();
2459}
2460
2461
2462void JSFunction::set_code(Code* value) {
2463  shared()->set_code(value);
2464}
2465
2466
2467Context* JSFunction::context() {
2468  return Context::cast(READ_FIELD(this, kContextOffset));
2469}
2470
2471
2472Object* JSFunction::unchecked_context() {
2473  return READ_FIELD(this, kContextOffset);
2474}
2475
2476
2477void JSFunction::set_context(Object* value) {
2478  ASSERT(value == Heap::undefined_value() || value->IsContext());
2479  WRITE_FIELD(this, kContextOffset, value);
2480  WRITE_BARRIER(this, kContextOffset);
2481}
2482
2483ACCESSORS(JSFunction, prototype_or_initial_map, Object,
2484          kPrototypeOrInitialMapOffset)
2485
2486
2487Map* JSFunction::initial_map() {
2488  return Map::cast(prototype_or_initial_map());
2489}
2490
2491
2492void JSFunction::set_initial_map(Map* value) {
2493  set_prototype_or_initial_map(value);
2494}
2495
2496
2497bool JSFunction::has_initial_map() {
2498  return prototype_or_initial_map()->IsMap();
2499}
2500
2501
2502bool JSFunction::has_instance_prototype() {
2503  return has_initial_map() || !prototype_or_initial_map()->IsTheHole();
2504}
2505
2506
2507bool JSFunction::has_prototype() {
2508  return map()->has_non_instance_prototype() || has_instance_prototype();
2509}
2510
2511
2512Object* JSFunction::instance_prototype() {
2513  ASSERT(has_instance_prototype());
2514  if (has_initial_map()) return initial_map()->prototype();
2515  // When there is no initial map and the prototype is a JSObject, the
2516  // initial map field is used for the prototype field.
2517  return prototype_or_initial_map();
2518}
2519
2520
2521Object* JSFunction::prototype() {
2522  ASSERT(has_prototype());
2523  // If the function's prototype property has been set to a non-JSObject
2524  // value, that value is stored in the constructor field of the map.
2525  if (map()->has_non_instance_prototype()) return map()->constructor();
2526  return instance_prototype();
2527}
2528
2529
2530bool JSFunction::is_compiled() {
2531  return shared()->is_compiled();
2532}
2533
2534
2535int JSFunction::NumberOfLiterals() {
2536  return literals()->length();
2537}
2538
2539
2540Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
2541  ASSERT(0 <= id && id < kJSBuiltinsCount);
2542  return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
2543}
2544
2545
2546void JSBuiltinsObject::set_javascript_builtin(Builtins::JavaScript id,
2547                                              Object* value) {
2548  ASSERT(0 <= id && id < kJSBuiltinsCount);
2549  WRITE_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize), value);
2550  WRITE_BARRIER(this, kJSBuiltinsOffset + (id * kPointerSize));
2551}
2552
2553
2554Address Proxy::proxy() {
2555  return AddressFrom<Address>(READ_INTPTR_FIELD(this, kProxyOffset));
2556}
2557
2558
2559void Proxy::set_proxy(Address value) {
2560  WRITE_INTPTR_FIELD(this, kProxyOffset, OffsetFrom(value));
2561}
2562
2563
2564void Proxy::ProxyIterateBody(ObjectVisitor* visitor) {
2565  visitor->VisitExternalReference(
2566      reinterpret_cast<Address *>(FIELD_ADDR(this, kProxyOffset)));
2567}
2568
2569
2570ACCESSORS(JSValue, value, Object, kValueOffset)
2571
2572
2573JSValue* JSValue::cast(Object* obj) {
2574  ASSERT(obj->IsJSValue());
2575  ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
2576  return reinterpret_cast<JSValue*>(obj);
2577}
2578
2579
2580INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
2581INT_ACCESSORS(Code, relocation_size, kRelocationSizeOffset)
2582INT_ACCESSORS(Code, sinfo_size, kSInfoSizeOffset)
2583
2584
2585byte* Code::instruction_start()  {
2586  return FIELD_ADDR(this, kHeaderSize);
2587}
2588
2589
2590int Code::body_size() {
2591  return RoundUp(instruction_size() + relocation_size(), kObjectAlignment);
2592}
2593
2594
2595byte* Code::relocation_start() {
2596  return FIELD_ADDR(this, kHeaderSize + instruction_size());
2597}
2598
2599
2600byte* Code::entry() {
2601  return instruction_start();
2602}
2603
2604
2605bool Code::contains(byte* pc) {
2606  return (instruction_start() <= pc) &&
2607      (pc < instruction_start() + instruction_size());
2608}
2609
2610
2611byte* Code::sinfo_start() {
2612  return FIELD_ADDR(this, kHeaderSize + body_size());
2613}
2614
2615
2616ACCESSORS(JSArray, length, Object, kLengthOffset)
2617
2618
2619ACCESSORS(JSRegExp, data, Object, kDataOffset)
2620
2621
2622JSRegExp::Type JSRegExp::TypeTag() {
2623  Object* data = this->data();
2624  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
2625  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
2626  return static_cast<JSRegExp::Type>(smi->value());
2627}
2628
2629
2630int JSRegExp::CaptureCount() {
2631  switch (TypeTag()) {
2632    case ATOM:
2633      return 0;
2634    case IRREGEXP:
2635      return Smi::cast(DataAt(kIrregexpCaptureCountIndex))->value();
2636    default:
2637      UNREACHABLE();
2638      return -1;
2639  }
2640}
2641
2642
2643JSRegExp::Flags JSRegExp::GetFlags() {
2644  ASSERT(this->data()->IsFixedArray());
2645  Object* data = this->data();
2646  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kFlagsIndex));
2647  return Flags(smi->value());
2648}
2649
2650
2651String* JSRegExp::Pattern() {
2652  ASSERT(this->data()->IsFixedArray());
2653  Object* data = this->data();
2654  String* pattern= String::cast(FixedArray::cast(data)->get(kSourceIndex));
2655  return pattern;
2656}
2657
2658
2659Object* JSRegExp::DataAt(int index) {
2660  ASSERT(TypeTag() != NOT_COMPILED);
2661  return FixedArray::cast(data())->get(index);
2662}
2663
2664
2665void JSRegExp::SetDataAt(int index, Object* value) {
2666  ASSERT(TypeTag() != NOT_COMPILED);
2667  ASSERT(index >= kDataIndex);  // Only implementation data can be set this way.
2668  FixedArray::cast(data())->set(index, value);
2669}
2670
2671
2672JSObject::ElementsKind JSObject::GetElementsKind() {
2673  Array* array = elements();
2674  if (array->IsFixedArray()) {
2675    // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
2676    if (array->map() == Heap::fixed_array_map()) {
2677      return FAST_ELEMENTS;
2678    }
2679    ASSERT(array->IsDictionary());
2680    return DICTIONARY_ELEMENTS;
2681  }
2682  if (array->IsExternalArray()) {
2683    switch (array->map()->instance_type()) {
2684      case EXTERNAL_BYTE_ARRAY_TYPE:
2685        return EXTERNAL_BYTE_ELEMENTS;
2686      case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2687        return EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2688      case EXTERNAL_SHORT_ARRAY_TYPE:
2689        return EXTERNAL_SHORT_ELEMENTS;
2690      case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2691        return EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2692      case EXTERNAL_INT_ARRAY_TYPE:
2693        return EXTERNAL_INT_ELEMENTS;
2694      case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2695        return EXTERNAL_UNSIGNED_INT_ELEMENTS;
2696      default:
2697        ASSERT(array->map()->instance_type() == EXTERNAL_FLOAT_ARRAY_TYPE);
2698        return EXTERNAL_FLOAT_ELEMENTS;
2699    }
2700  }
2701  ASSERT(array->IsPixelArray());
2702  return PIXEL_ELEMENTS;
2703}
2704
2705
2706bool JSObject::HasFastElements() {
2707  return GetElementsKind() == FAST_ELEMENTS;
2708}
2709
2710
2711bool JSObject::HasDictionaryElements() {
2712  return GetElementsKind() == DICTIONARY_ELEMENTS;
2713}
2714
2715
2716bool JSObject::HasPixelElements() {
2717  return GetElementsKind() == PIXEL_ELEMENTS;
2718}
2719
2720
2721bool JSObject::HasExternalArrayElements() {
2722  return (HasExternalByteElements() ||
2723          HasExternalUnsignedByteElements() ||
2724          HasExternalShortElements() ||
2725          HasExternalUnsignedShortElements() ||
2726          HasExternalIntElements() ||
2727          HasExternalUnsignedIntElements() ||
2728          HasExternalFloatElements());
2729}
2730
2731
2732bool JSObject::HasExternalByteElements() {
2733  return GetElementsKind() == EXTERNAL_BYTE_ELEMENTS;
2734}
2735
2736
2737bool JSObject::HasExternalUnsignedByteElements() {
2738  return GetElementsKind() == EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
2739}
2740
2741
2742bool JSObject::HasExternalShortElements() {
2743  return GetElementsKind() == EXTERNAL_SHORT_ELEMENTS;
2744}
2745
2746
2747bool JSObject::HasExternalUnsignedShortElements() {
2748  return GetElementsKind() == EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
2749}
2750
2751
2752bool JSObject::HasExternalIntElements() {
2753  return GetElementsKind() == EXTERNAL_INT_ELEMENTS;
2754}
2755
2756
2757bool JSObject::HasExternalUnsignedIntElements() {
2758  return GetElementsKind() == EXTERNAL_UNSIGNED_INT_ELEMENTS;
2759}
2760
2761
2762bool JSObject::HasExternalFloatElements() {
2763  return GetElementsKind() == EXTERNAL_FLOAT_ELEMENTS;
2764}
2765
2766
2767bool JSObject::HasNamedInterceptor() {
2768  return map()->has_named_interceptor();
2769}
2770
2771
2772bool JSObject::HasIndexedInterceptor() {
2773  return map()->has_indexed_interceptor();
2774}
2775
2776
2777StringDictionary* JSObject::property_dictionary() {
2778  ASSERT(!HasFastProperties());
2779  return StringDictionary::cast(properties());
2780}
2781
2782
2783NumberDictionary* JSObject::element_dictionary() {
2784  ASSERT(HasDictionaryElements());
2785  return NumberDictionary::cast(elements());
2786}
2787
2788
2789bool String::HasHashCode() {
2790  return (hash_field() & kHashComputedMask) != 0;
2791}
2792
2793
2794uint32_t String::Hash() {
2795  // Fast case: has hash code already been computed?
2796  uint32_t field = hash_field();
2797  if (field & kHashComputedMask) return field >> kHashShift;
2798  // Slow case: compute hash code and set it.
2799  return ComputeAndSetHash();
2800}
2801
2802
2803StringHasher::StringHasher(int length)
2804  : length_(length),
2805    raw_running_hash_(0),
2806    array_index_(0),
2807    is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
2808    is_first_char_(true),
2809    is_valid_(true) { }
2810
2811
2812bool StringHasher::has_trivial_hash() {
2813  return length_ > String::kMaxHashCalcLength;
2814}
2815
2816
2817void StringHasher::AddCharacter(uc32 c) {
2818  // Use the Jenkins one-at-a-time hash function to update the hash
2819  // for the given character.
2820  raw_running_hash_ += c;
2821  raw_running_hash_ += (raw_running_hash_ << 10);
2822  raw_running_hash_ ^= (raw_running_hash_ >> 6);
2823  // Incremental array index computation.
2824  if (is_array_index_) {
2825    if (c < '0' || c > '9') {
2826      is_array_index_ = false;
2827    } else {
2828      int d = c - '0';
2829      if (is_first_char_) {
2830        is_first_char_ = false;
2831        if (c == '0' && length_ > 1) {
2832          is_array_index_ = false;
2833          return;
2834        }
2835      }
2836      if (array_index_ > 429496729U - ((d + 2) >> 3)) {
2837        is_array_index_ = false;
2838      } else {
2839        array_index_ = array_index_ * 10 + d;
2840      }
2841    }
2842  }
2843}
2844
2845
2846void StringHasher::AddCharacterNoIndex(uc32 c) {
2847  ASSERT(!is_array_index());
2848  raw_running_hash_ += c;
2849  raw_running_hash_ += (raw_running_hash_ << 10);
2850  raw_running_hash_ ^= (raw_running_hash_ >> 6);
2851}
2852
2853
2854uint32_t StringHasher::GetHash() {
2855  // Get the calculated raw hash value and do some more bit ops to distribute
2856  // the hash further. Ensure that we never return zero as the hash value.
2857  uint32_t result = raw_running_hash_;
2858  result += (result << 3);
2859  result ^= (result >> 11);
2860  result += (result << 15);
2861  if (result == 0) {
2862    result = 27;
2863  }
2864  return result;
2865}
2866
2867
2868bool String::AsArrayIndex(uint32_t* index) {
2869  uint32_t field = hash_field();
2870  if ((field & kHashComputedMask) && !(field & kIsArrayIndexMask)) return false;
2871  return SlowAsArrayIndex(index);
2872}
2873
2874
2875Object* JSObject::GetPrototype() {
2876  return JSObject::cast(this)->map()->prototype();
2877}
2878
2879
2880PropertyAttributes JSObject::GetPropertyAttribute(String* key) {
2881  return GetPropertyAttributeWithReceiver(this, key);
2882}
2883
2884// TODO(504): this may be useful in other places too where JSGlobalProxy
2885// is used.
2886Object* JSObject::BypassGlobalProxy() {
2887  if (IsJSGlobalProxy()) {
2888    Object* proto = GetPrototype();
2889    if (proto->IsNull()) return Heap::undefined_value();
2890    ASSERT(proto->IsJSGlobalObject());
2891    return proto;
2892  }
2893  return this;
2894}
2895
2896
2897bool JSObject::HasHiddenPropertiesObject() {
2898  ASSERT(!IsJSGlobalProxy());
2899  return GetPropertyAttributePostInterceptor(this,
2900                                             Heap::hidden_symbol(),
2901                                             false) != ABSENT;
2902}
2903
2904
2905Object* JSObject::GetHiddenPropertiesObject() {
2906  ASSERT(!IsJSGlobalProxy());
2907  PropertyAttributes attributes;
2908  return GetLocalPropertyPostInterceptor(this,
2909                                         Heap::hidden_symbol(),
2910                                         &attributes);
2911}
2912
2913
2914Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
2915  ASSERT(!IsJSGlobalProxy());
2916  return SetPropertyPostInterceptor(Heap::hidden_symbol(),
2917                                    hidden_obj,
2918                                    DONT_ENUM);
2919}
2920
2921
2922bool JSObject::HasElement(uint32_t index) {
2923  return HasElementWithReceiver(this, index);
2924}
2925
2926
2927bool AccessorInfo::all_can_read() {
2928  return BooleanBit::get(flag(), kAllCanReadBit);
2929}
2930
2931
2932void AccessorInfo::set_all_can_read(bool value) {
2933  set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
2934}
2935
2936
2937bool AccessorInfo::all_can_write() {
2938  return BooleanBit::get(flag(), kAllCanWriteBit);
2939}
2940
2941
2942void AccessorInfo::set_all_can_write(bool value) {
2943  set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
2944}
2945
2946
2947bool AccessorInfo::prohibits_overwriting() {
2948  return BooleanBit::get(flag(), kProhibitsOverwritingBit);
2949}
2950
2951
2952void AccessorInfo::set_prohibits_overwriting(bool value) {
2953  set_flag(BooleanBit::set(flag(), kProhibitsOverwritingBit, value));
2954}
2955
2956
2957PropertyAttributes AccessorInfo::property_attributes() {
2958  return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
2959}
2960
2961
2962void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
2963  ASSERT(AttributesField::is_valid(attributes));
2964  int rest_value = flag()->value() & ~AttributesField::mask();
2965  set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
2966}
2967
2968template<typename Shape, typename Key>
2969void Dictionary<Shape, Key>::SetEntry(int entry,
2970                                      Object* key,
2971                                      Object* value,
2972                                      PropertyDetails details) {
2973  ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
2974  int index = HashTable<Shape, Key>::EntryToIndex(entry);
2975  WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
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::SetContent(FixedArray* storage) {
3010  set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
3011  set_elements(storage);
3012}
3013
3014
3015Object* FixedArray::Copy() {
3016  if (length() == 0) return this;
3017  return Heap::CopyFixedArray(this);
3018}
3019
3020
3021#undef CAST_ACCESSOR
3022#undef INT_ACCESSORS
3023#undef SMI_ACCESSORS
3024#undef ACCESSORS
3025#undef FIELD_ADDR
3026#undef READ_FIELD
3027#undef WRITE_FIELD
3028#undef WRITE_BARRIER
3029#undef CONDITIONAL_WRITE_BARRIER
3030#undef READ_MEMADDR_FIELD
3031#undef WRITE_MEMADDR_FIELD
3032#undef READ_DOUBLE_FIELD
3033#undef WRITE_DOUBLE_FIELD
3034#undef READ_INT_FIELD
3035#undef WRITE_INT_FIELD
3036#undef READ_SHORT_FIELD
3037#undef WRITE_SHORT_FIELD
3038#undef READ_BYTE_FIELD
3039#undef WRITE_BYTE_FIELD
3040
3041
3042} }  // namespace v8::internal
3043
3044#endif  // V8_OBJECTS_INL_H_
3045