Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: src/elements.cc

Issue 7607031: Update gc branch to bleeding_edge revision 8862. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Fix bug in weak-map merge Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/elements.h ('k') | src/execution.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2011 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 "elements.h"
32
33 namespace v8 {
34 namespace internal {
35
36
37 ElementsAccessor** ElementsAccessor::elements_accessors_;
38
39
40 // Base class for element handler implementations. Contains the
41 // the common logic for objects with different ElementsKinds.
42 // Subclasses must specialize method for which the element
43 // implementation differs from the base class implementation.
44 //
45 // This class is intended to be used in the following way:
46 //
47 // class SomeElementsAccessor :
48 // public ElementsAccessorBase<SomeElementsAccessor,
49 // BackingStoreClass> {
50 // ...
51 // }
52 //
53 // This is an example of the Curiously Recurring Template Pattern (see
54 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
55 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
56 // specialization of SomeElementsAccessor methods).
57 template <typename ElementsAccessorSubclass, typename BackingStoreClass>
58 class ElementsAccessorBase : public ElementsAccessor {
59 public:
60 ElementsAccessorBase() { }
61 virtual MaybeObject* GetWithReceiver(JSObject* obj,
62 Object* receiver,
63 uint32_t index) {
64 if (index < ElementsAccessorSubclass::GetLength(obj)) {
65 BackingStoreClass* backing_store =
66 ElementsAccessorSubclass::GetBackingStore(obj);
67 return backing_store->get(index);
68 }
69 return obj->GetHeap()->the_hole_value();
70 }
71
72 virtual MaybeObject* Delete(JSObject* obj,
73 uint32_t index,
74 JSReceiver::DeleteMode mode) = 0;
75
76 protected:
77 static BackingStoreClass* GetBackingStore(JSObject* obj) {
78 return BackingStoreClass::cast(obj->elements());
79 }
80
81 static uint32_t GetLength(JSObject* obj) {
82 return ElementsAccessorSubclass::GetBackingStore(obj)->length();
83 }
84
85 private:
86 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
87 };
88
89
90 class FastElementsAccessor
91 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
92 public:
93 static MaybeObject* DeleteCommon(JSObject* obj,
94 uint32_t index) {
95 ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
96 Heap* heap = obj->GetHeap();
97 FixedArray* backing_store = FixedArray::cast(obj->elements());
98 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
99 backing_store = FixedArray::cast(backing_store->get(1));
100 } else {
101 Object* writable;
102 MaybeObject* maybe = obj->EnsureWritableFastElements();
103 if (!maybe->ToObject(&writable)) return maybe;
104 backing_store = FixedArray::cast(writable);
105 }
106 uint32_t length = static_cast<uint32_t>(
107 obj->IsJSArray()
108 ? Smi::cast(JSArray::cast(obj)->length())->value()
109 : backing_store->length());
110 if (index < length) {
111 backing_store->set_the_hole(index);
112 // If an old space backing store is larger than a certain size and
113 // has too few used values, normalize it.
114 // To avoid doing the check on every delete we require at least
115 // one adjacent hole to the value being deleted.
116 Object* hole = heap->the_hole_value();
117 const int kMinLengthForSparsenessCheck = 64;
118 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
119 !heap->InNewSpace(backing_store) &&
120 ((index > 0 && backing_store->get(index - 1) == hole) ||
121 (index + 1 < length && backing_store->get(index + 1) == hole))) {
122 int num_used = 0;
123 for (int i = 0; i < backing_store->length(); ++i) {
124 if (backing_store->get(i) != hole) ++num_used;
125 // Bail out early if more than 1/4 is used.
126 if (4 * num_used > backing_store->length()) break;
127 }
128 if (4 * num_used <= backing_store->length()) {
129 MaybeObject* result = obj->NormalizeElements();
130 if (result->IsFailure()) return result;
131 }
132 }
133 }
134 return heap->true_value();
135 }
136
137 virtual MaybeObject* Delete(JSObject* obj,
138 uint32_t index,
139 JSReceiver::DeleteMode mode) {
140 return DeleteCommon(obj, index);
141 }
142 };
143
144
145 class FastDoubleElementsAccessor
146 : public ElementsAccessorBase<FastDoubleElementsAccessor,
147 FixedDoubleArray> {
148 virtual MaybeObject* Delete(JSObject* obj,
149 uint32_t index,
150 JSReceiver::DeleteMode mode) {
151 int length = obj->IsJSArray()
152 ? Smi::cast(JSArray::cast(obj)->length())->value()
153 : FixedDoubleArray::cast(obj->elements())->length();
154 if (index < static_cast<uint32_t>(length)) {
155 FixedDoubleArray::cast(obj->elements())->set_the_hole(index);
156 }
157 return obj->GetHeap()->true_value();
158 }
159 };
160
161
162 // Super class for all external element arrays.
163 template<typename ExternalElementsAccessorSubclass,
164 typename ExternalArray>
165 class ExternalElementsAccessor
166 : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
167 ExternalArray> {
168 public:
169 virtual MaybeObject* GetWithReceiver(JSObject* obj,
170 Object* receiver,
171 uint32_t index) {
172 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) {
173 ExternalArray* backing_store =
174 ExternalElementsAccessorSubclass::GetBackingStore(obj);
175 return backing_store->get(index);
176 } else {
177 return obj->GetHeap()->undefined_value();
178 }
179 }
180
181 virtual MaybeObject* Delete(JSObject* obj,
182 uint32_t index,
183 JSReceiver::DeleteMode mode) {
184 // External arrays always ignore deletes.
185 return obj->GetHeap()->true_value();
186 }
187 };
188
189
190 class ExternalByteElementsAccessor
191 : public ExternalElementsAccessor<ExternalByteElementsAccessor,
192 ExternalByteArray> {
193 };
194
195
196 class ExternalUnsignedByteElementsAccessor
197 : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
198 ExternalUnsignedByteArray> {
199 };
200
201
202 class ExternalShortElementsAccessor
203 : public ExternalElementsAccessor<ExternalShortElementsAccessor,
204 ExternalShortArray> {
205 };
206
207
208 class ExternalUnsignedShortElementsAccessor
209 : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
210 ExternalUnsignedShortArray> {
211 };
212
213
214 class ExternalIntElementsAccessor
215 : public ExternalElementsAccessor<ExternalIntElementsAccessor,
216 ExternalIntArray> {
217 };
218
219
220 class ExternalUnsignedIntElementsAccessor
221 : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
222 ExternalUnsignedIntArray> {
223 };
224
225
226 class ExternalFloatElementsAccessor
227 : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
228 ExternalFloatArray> {
229 };
230
231
232 class ExternalDoubleElementsAccessor
233 : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
234 ExternalDoubleArray> {
235 };
236
237
238 class PixelElementsAccessor
239 : public ExternalElementsAccessor<PixelElementsAccessor,
240 ExternalPixelArray> {
241 };
242
243
244 class DictionaryElementsAccessor
245 : public ElementsAccessorBase<DictionaryElementsAccessor,
246 NumberDictionary> {
247 public:
248 static MaybeObject* GetNumberDictionaryElement(
249 JSObject* obj,
250 Object* receiver,
251 NumberDictionary* backing_store,
252 uint32_t index) {
253 int entry = backing_store->FindEntry(index);
254 if (entry != NumberDictionary::kNotFound) {
255 Object* element = backing_store->ValueAt(entry);
256 PropertyDetails details = backing_store->DetailsAt(entry);
257 if (details.type() == CALLBACKS) {
258 return obj->GetElementWithCallback(receiver,
259 element,
260 index,
261 obj);
262 } else {
263 return element;
264 }
265 }
266 return obj->GetHeap()->the_hole_value();
267 }
268
269
270 static MaybeObject* DeleteCommon(JSObject* obj,
271 uint32_t index,
272 JSReceiver::DeleteMode mode) {
273 Isolate* isolate = obj->GetIsolate();
274 Heap* heap = isolate->heap();
275 FixedArray* backing_store = FixedArray::cast(obj->elements());
276 bool is_arguments =
277 (obj->GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
278 if (is_arguments) {
279 backing_store = FixedArray::cast(backing_store->get(1));
280 }
281 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
282 int entry = dictionary->FindEntry(index);
283 if (entry != NumberDictionary::kNotFound) {
284 Object* result = dictionary->DeleteProperty(entry, mode);
285 if (result == heap->true_value()) {
286 MaybeObject* maybe_elements = dictionary->Shrink(index);
287 FixedArray* new_elements = NULL;
288 if (!maybe_elements->To(&new_elements)) {
289 return maybe_elements;
290 }
291 if (is_arguments) {
292 FixedArray::cast(obj->elements())->set(1, new_elements);
293 } else {
294 obj->set_elements(new_elements);
295 }
296 }
297 if (mode == JSObject::STRICT_DELETION &&
298 result == heap->false_value()) {
299 // In strict mode, attempting to delete a non-configurable property
300 // throws an exception.
301 HandleScope scope(isolate);
302 Handle<Object> holder(obj);
303 Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
304 Handle<Object> args[2] = { name, holder };
305 Handle<Object> error =
306 isolate->factory()->NewTypeError("strict_delete_property",
307 HandleVector(args, 2));
308 return isolate->Throw(*error);
309 }
310 }
311 return heap->true_value();
312 }
313
314 virtual MaybeObject* Delete(JSObject* obj,
315 uint32_t index,
316 JSReceiver::DeleteMode mode) {
317 return DeleteCommon(obj, index, mode);
318 }
319
320 virtual MaybeObject* GetWithReceiver(JSObject* obj,
321 Object* receiver,
322 uint32_t index) {
323 return GetNumberDictionaryElement(obj,
324 receiver,
325 obj->element_dictionary(),
326 index);
327 }
328 };
329
330
331 class NonStrictArgumentsElementsAccessor
332 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
333 FixedArray> {
334 public:
335 virtual MaybeObject* GetWithReceiver(JSObject* obj,
336 Object* receiver,
337 uint32_t index) {
338 FixedArray* parameter_map = GetBackingStore(obj);
339 uint32_t length = parameter_map->length();
340 Object* probe =
341 (index < length - 2) ? parameter_map->get(index + 2) : NULL;
342 if (probe != NULL && !probe->IsTheHole()) {
343 Context* context = Context::cast(parameter_map->get(0));
344 int context_index = Smi::cast(probe)->value();
345 ASSERT(!context->get(context_index)->IsTheHole());
346 return context->get(context_index);
347 } else {
348 // Object is not mapped, defer to the arguments.
349 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
350 if (arguments->IsDictionary()) {
351 return DictionaryElementsAccessor::GetNumberDictionaryElement(
352 obj,
353 receiver,
354 NumberDictionary::cast(arguments),
355 index);
356 } else if (index < static_cast<uint32_t>(arguments->length())) {
357 return arguments->get(index);
358 }
359 }
360 return obj->GetHeap()->the_hole_value();
361 }
362
363 virtual MaybeObject* Delete(JSObject* obj,
364 uint32_t index,
365 JSReceiver::DeleteMode mode) {
366 FixedArray* parameter_map = FixedArray::cast(obj->elements());
367 uint32_t length = parameter_map->length();
368 Object* probe =
369 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
370 if (probe != NULL && !probe->IsTheHole()) {
371 // TODO(kmillikin): We could check if this was the last aliased
372 // parameter, and revert to normal elements in that case. That
373 // would enable GC of the context.
374 parameter_map->set_the_hole(index + 2);
375 } else {
376 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
377 if (arguments->IsDictionary()) {
378 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode);
379 } else {
380 return FastElementsAccessor::DeleteCommon(obj, index);
381 }
382 }
383 return obj->GetHeap()->true_value();
384 }
385 };
386
387
388 void ElementsAccessor::InitializeOncePerProcess() {
389 static struct ConcreteElementsAccessors {
390 FastElementsAccessor fast_elements_handler;
391 FastDoubleElementsAccessor fast_double_elements_handler;
392 DictionaryElementsAccessor dictionary_elements_handler;
393 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler;
394 ExternalByteElementsAccessor byte_elements_handler;
395 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler;
396 ExternalShortElementsAccessor short_elements_handler;
397 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler;
398 ExternalIntElementsAccessor int_elements_handler;
399 ExternalUnsignedIntElementsAccessor unsigned_int_elements_handler;
400 ExternalFloatElementsAccessor float_elements_handler;
401 ExternalDoubleElementsAccessor double_elements_handler;
402 PixelElementsAccessor pixel_elements_handler;
403 } element_accessors;
404
405 static ElementsAccessor* accessor_array[] = {
406 &element_accessors.fast_elements_handler,
407 &element_accessors.fast_double_elements_handler,
408 &element_accessors.dictionary_elements_handler,
409 &element_accessors.non_strict_arguments_elements_handler,
410 &element_accessors.byte_elements_handler,
411 &element_accessors.unsigned_byte_elements_handler,
412 &element_accessors.short_elements_handler,
413 &element_accessors.unsigned_short_elements_handler,
414 &element_accessors.int_elements_handler,
415 &element_accessors.unsigned_int_elements_handler,
416 &element_accessors.float_elements_handler,
417 &element_accessors.double_elements_handler,
418 &element_accessors.pixel_elements_handler
419 };
420
421 elements_accessors_ = accessor_array;
422 }
423
424
425 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/execution.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698