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 #include "v8.h"
29
30 #include "objects.h"
31 #include "transitions-inl.h"
32 #include "utils.h"
33
34 namespace v8 {
35 namespace internal {
36
37
AllocateRaw(Isolate * isolate,int length)38 static MaybeObject* AllocateRaw(Isolate* isolate, int length) {
39 // Use FixedArray to not use TransitionArray::cast on incomplete object.
40 FixedArray* array;
41 MaybeObject* maybe_array = isolate->heap()->AllocateFixedArray(length);
42 if (!maybe_array->To(&array)) return maybe_array;
43 return array;
44 }
45
46
Allocate(Isolate * isolate,int number_of_transitions)47 MaybeObject* TransitionArray::Allocate(Isolate* isolate,
48 int number_of_transitions) {
49 FixedArray* array;
50 MaybeObject* maybe_array =
51 AllocateRaw(isolate, ToKeyIndex(number_of_transitions));
52 if (!maybe_array->To(&array)) return maybe_array;
53 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
54 return array;
55 }
56
57
NoIncrementalWriteBarrierCopyFrom(TransitionArray * origin,int origin_transition,int target_transition)58 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
59 int origin_transition,
60 int target_transition) {
61 NoIncrementalWriteBarrierSet(target_transition,
62 origin->GetKey(origin_transition),
63 origin->GetTarget(origin_transition));
64 }
65
66
InsertionPointFound(Name * key1,Name * key2)67 static bool InsertionPointFound(Name* key1, Name* key2) {
68 return key1->Hash() > key2->Hash();
69 }
70
71
NewWith(SimpleTransitionFlag flag,Name * key,Map * target,Object * back_pointer)72 MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag,
73 Name* key,
74 Map* target,
75 Object* back_pointer) {
76 TransitionArray* result;
77 MaybeObject* maybe_result;
78
79 if (flag == SIMPLE_TRANSITION) {
80 maybe_result = AllocateRaw(target->GetIsolate(), kSimpleTransitionSize);
81 if (!maybe_result->To(&result)) return maybe_result;
82 result->set(kSimpleTransitionTarget, target);
83 } else {
84 maybe_result = Allocate(target->GetIsolate(), 1);
85 if (!maybe_result->To(&result)) return maybe_result;
86 result->NoIncrementalWriteBarrierSet(0, key, target);
87 }
88 result->set_back_pointer_storage(back_pointer);
89 return result;
90 }
91
92
ExtendToFullTransitionArray()93 MaybeObject* TransitionArray::ExtendToFullTransitionArray() {
94 ASSERT(!IsFullTransitionArray());
95 int nof = number_of_transitions();
96 TransitionArray* result;
97 MaybeObject* maybe_result = Allocate(GetIsolate(), nof);
98 if (!maybe_result->To(&result)) return maybe_result;
99
100 if (nof == 1) {
101 result->NoIncrementalWriteBarrierCopyFrom(this, kSimpleTransitionIndex, 0);
102 }
103
104 result->set_back_pointer_storage(back_pointer_storage());
105 return result;
106 }
107
108
CopyInsert(Name * name,Map * target)109 MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
110 TransitionArray* result;
111
112 int number_of_transitions = this->number_of_transitions();
113 int new_size = number_of_transitions;
114
115 int insertion_index = this->Search(name);
116 if (insertion_index == kNotFound) ++new_size;
117
118 MaybeObject* maybe_array;
119 maybe_array = TransitionArray::Allocate(GetIsolate(), new_size);
120 if (!maybe_array->To(&result)) return maybe_array;
121
122 if (HasPrototypeTransitions()) {
123 result->SetPrototypeTransitions(GetPrototypeTransitions());
124 }
125
126 if (insertion_index != kNotFound) {
127 for (int i = 0; i < number_of_transitions; ++i) {
128 if (i != insertion_index) {
129 result->NoIncrementalWriteBarrierCopyFrom(this, i, i);
130 }
131 }
132 result->NoIncrementalWriteBarrierSet(insertion_index, name, target);
133 result->set_back_pointer_storage(back_pointer_storage());
134 return result;
135 }
136
137 insertion_index = 0;
138 for (; insertion_index < number_of_transitions; ++insertion_index) {
139 if (InsertionPointFound(GetKey(insertion_index), name)) break;
140 result->NoIncrementalWriteBarrierCopyFrom(
141 this, insertion_index, insertion_index);
142 }
143
144 result->NoIncrementalWriteBarrierSet(insertion_index, name, target);
145
146 for (; insertion_index < number_of_transitions; ++insertion_index) {
147 result->NoIncrementalWriteBarrierCopyFrom(
148 this, insertion_index, insertion_index + 1);
149 }
150
151 result->set_back_pointer_storage(back_pointer_storage());
152 return result;
153 }
154
155
156 } } // namespace v8::internal
157