Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_TRANSITIONS_INL_H_
     29 #define V8_TRANSITIONS_INL_H_
     30 
     31 #include "objects-inl.h"
     32 #include "transitions.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 
     38 #define FIELD_ADDR(p, offset) \
     39   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
     40 
     41 #define WRITE_FIELD(p, offset, value) \
     42   (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
     43 
     44 #define CONDITIONAL_WRITE_BARRIER(heap, object, offset, value, mode)    \
     45   if (mode == UPDATE_WRITE_BARRIER) {                                   \
     46     heap->incremental_marking()->RecordWrite(                           \
     47       object, HeapObject::RawField(object, offset), value);             \
     48     if (heap->InNewSpace(value)) {                                      \
     49       heap->RecordWrite(object->address(), offset);                     \
     50     }                                                                   \
     51   }
     52 
     53 
     54 TransitionArray* TransitionArray::cast(Object* object) {
     55   ASSERT(object->IsTransitionArray());
     56   return reinterpret_cast<TransitionArray*>(object);
     57 }
     58 
     59 
     60 bool TransitionArray::HasElementsTransition() {
     61   return Search(GetHeap()->elements_transition_symbol()) != kNotFound;
     62 }
     63 
     64 
     65 Object* TransitionArray::back_pointer_storage() {
     66   return get(kBackPointerStorageIndex);
     67 }
     68 
     69 
     70 void TransitionArray::set_back_pointer_storage(Object* back_pointer,
     71                                                WriteBarrierMode mode) {
     72   Heap* heap = GetHeap();
     73   WRITE_FIELD(this, kBackPointerStorageOffset, back_pointer);
     74   CONDITIONAL_WRITE_BARRIER(
     75       heap, this, kBackPointerStorageOffset, back_pointer, mode);
     76 }
     77 
     78 
     79 bool TransitionArray::HasPrototypeTransitions() {
     80   return IsFullTransitionArray() &&
     81       get(kPrototypeTransitionsIndex) != Smi::FromInt(0);
     82 }
     83 
     84 
     85 FixedArray* TransitionArray::GetPrototypeTransitions() {
     86   ASSERT(IsFullTransitionArray());
     87   Object* prototype_transitions = get(kPrototypeTransitionsIndex);
     88   return FixedArray::cast(prototype_transitions);
     89 }
     90 
     91 
     92 HeapObject* TransitionArray::UncheckedPrototypeTransitions() {
     93   ASSERT(HasPrototypeTransitions());
     94   return reinterpret_cast<HeapObject*>(get(kPrototypeTransitionsIndex));
     95 }
     96 
     97 
     98 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions,
     99                                               WriteBarrierMode mode) {
    100   ASSERT(IsFullTransitionArray());
    101   ASSERT(transitions->IsFixedArray());
    102   Heap* heap = GetHeap();
    103   WRITE_FIELD(this, kPrototypeTransitionsOffset, transitions);
    104   CONDITIONAL_WRITE_BARRIER(
    105       heap, this, kPrototypeTransitionsOffset, transitions, mode);
    106 }
    107 
    108 
    109 Object** TransitionArray::GetPrototypeTransitionsSlot() {
    110   return HeapObject::RawField(reinterpret_cast<HeapObject*>(this),
    111                               kPrototypeTransitionsOffset);
    112 }
    113 
    114 
    115 Object** TransitionArray::GetKeySlot(int transition_number) {
    116   ASSERT(!IsSimpleTransition());
    117   ASSERT(transition_number < number_of_transitions());
    118   return HeapObject::RawField(
    119       reinterpret_cast<HeapObject*>(this),
    120       OffsetOfElementAt(ToKeyIndex(transition_number)));
    121 }
    122 
    123 
    124 Name* TransitionArray::GetKey(int transition_number) {
    125   if (IsSimpleTransition()) {
    126     Map* target = GetTarget(kSimpleTransitionIndex);
    127     int descriptor = target->LastAdded();
    128     Name* key = target->instance_descriptors()->GetKey(descriptor);
    129     return key;
    130   }
    131   ASSERT(transition_number < number_of_transitions());
    132   return Name::cast(get(ToKeyIndex(transition_number)));
    133 }
    134 
    135 
    136 void TransitionArray::SetKey(int transition_number, Name* key) {
    137   ASSERT(!IsSimpleTransition());
    138   ASSERT(transition_number < number_of_transitions());
    139   set(ToKeyIndex(transition_number), key);
    140 }
    141 
    142 
    143 Map* TransitionArray::GetTarget(int transition_number) {
    144   if (IsSimpleTransition()) {
    145     ASSERT(transition_number == kSimpleTransitionIndex);
    146     return Map::cast(get(kSimpleTransitionTarget));
    147   }
    148   ASSERT(transition_number < number_of_transitions());
    149   return Map::cast(get(ToTargetIndex(transition_number)));
    150 }
    151 
    152 
    153 void TransitionArray::SetTarget(int transition_number, Map* value) {
    154   if (IsSimpleTransition()) {
    155     ASSERT(transition_number == kSimpleTransitionIndex);
    156     return set(kSimpleTransitionTarget, value);
    157   }
    158   ASSERT(transition_number < number_of_transitions());
    159   set(ToTargetIndex(transition_number), value);
    160 }
    161 
    162 
    163 PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
    164   Map* map = GetTarget(transition_number);
    165   DescriptorArray* descriptors = map->instance_descriptors();
    166   int descriptor = map->LastAdded();
    167   return descriptors->GetDetails(descriptor);
    168 }
    169 
    170 
    171 int TransitionArray::Search(Name* name) {
    172   if (IsSimpleTransition()) {
    173     Name* key = GetKey(kSimpleTransitionIndex);
    174     if (key->Equals(name)) return kSimpleTransitionIndex;
    175     return kNotFound;
    176   }
    177   return internal::Search<ALL_ENTRIES>(this, name);
    178 }
    179 
    180 
    181 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
    182                                                    Name* key,
    183                                                    Map* target) {
    184   FixedArray::NoIncrementalWriteBarrierSet(
    185       this, ToKeyIndex(transition_number), key);
    186   FixedArray::NoIncrementalWriteBarrierSet(
    187       this, ToTargetIndex(transition_number), target);
    188 }
    189 
    190 
    191 #undef FIELD_ADDR
    192 #undef WRITE_FIELD
    193 #undef CONDITIONAL_WRITE_BARRIER
    194 
    195 
    196 } }  // namespace v8::internal
    197 
    198 #endif  // V8_TRANSITIONS_INL_H_
    199