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