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

Side by Side Diff: src/elements.cc

Issue 7566004: Move element deletion into element handlers (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: white space tweaks 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/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 Object* receiver, 62 Object* receiver,
63 uint32_t index) { 63 uint32_t index) {
64 if (index < ElementsAccessorSubclass::GetLength(obj)) { 64 if (index < ElementsAccessorSubclass::GetLength(obj)) {
65 BackingStoreClass* backing_store = 65 BackingStoreClass* backing_store =
66 ElementsAccessorSubclass::GetBackingStore(obj); 66 ElementsAccessorSubclass::GetBackingStore(obj);
67 return backing_store->get(index); 67 return backing_store->get(index);
68 } 68 }
69 return obj->GetHeap()->the_hole_value(); 69 return obj->GetHeap()->the_hole_value();
70 } 70 }
71 71
72 virtual MaybeObject* Delete(JSObject* obj,
73 uint32_t index,
74 JSReceiver::DeleteMode mode) = 0;
75
72 protected: 76 protected:
73 static BackingStoreClass* GetBackingStore(JSObject* obj) { 77 static BackingStoreClass* GetBackingStore(JSObject* obj) {
74 return BackingStoreClass::cast(obj->elements()); 78 return BackingStoreClass::cast(obj->elements());
75 } 79 }
76 80
77 static uint32_t GetLength(JSObject* obj) { 81 static uint32_t GetLength(JSObject* obj) {
78 return ElementsAccessorSubclass::GetBackingStore(obj)->length(); 82 return ElementsAccessorSubclass::GetBackingStore(obj)->length();
79 } 83 }
80 84
81 private: 85 private:
82 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); 86 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
83 }; 87 };
84 88
85 89
86 class FastElementsAccessor 90 class FastElementsAccessor
87 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { 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 }
88 }; 142 };
89 143
90 144
91 class FastDoubleElementsAccessor 145 class FastDoubleElementsAccessor
92 : public ElementsAccessorBase<FastDoubleElementsAccessor, 146 : public ElementsAccessorBase<FastDoubleElementsAccessor,
93 FixedDoubleArray> { 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 }
94 }; 159 };
95 160
96 161
97 // Super class for all external element arrays. 162 // Super class for all external element arrays.
98 template<typename ExternalElementsAccessorSubclass, 163 template<typename ExternalElementsAccessorSubclass,
99 typename ExternalArray> 164 typename ExternalArray>
100 class ExternalElementsAccessor 165 class ExternalElementsAccessor
101 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, 166 : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
102 ExternalArray> { 167 ExternalArray> {
103 public: 168 public:
104 virtual MaybeObject* GetWithReceiver(JSObject* obj, 169 virtual MaybeObject* GetWithReceiver(JSObject* obj,
105 Object* receiver, 170 Object* receiver,
106 uint32_t index) { 171 uint32_t index) {
107 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) { 172 if (index < ExternalElementsAccessorSubclass::GetLength(obj)) {
108 ExternalArray* backing_store = 173 ExternalArray* backing_store =
109 ExternalElementsAccessorSubclass::GetBackingStore(obj); 174 ExternalElementsAccessorSubclass::GetBackingStore(obj);
110 return backing_store->get(index); 175 return backing_store->get(index);
111 } else { 176 } else {
112 return obj->GetHeap()->undefined_value(); 177 return obj->GetHeap()->undefined_value();
113 } 178 }
114 } 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 }
115 }; 187 };
116 188
117 189
118 class ExternalByteElementsAccessor 190 class ExternalByteElementsAccessor
119 : public ExternalElementsAccessor<ExternalByteElementsAccessor, 191 : public ExternalElementsAccessor<ExternalByteElementsAccessor,
120 ExternalByteArray> { 192 ExternalByteArray> {
121 }; 193 };
122 194
123 195
124 class ExternalUnsignedByteElementsAccessor 196 class ExternalUnsignedByteElementsAccessor
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 element, 259 element,
188 index, 260 index,
189 obj); 261 obj);
190 } else { 262 } else {
191 return element; 263 return element;
192 } 264 }
193 } 265 }
194 return obj->GetHeap()->the_hole_value(); 266 return obj->GetHeap()->the_hole_value();
195 } 267 }
196 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
197 virtual MaybeObject* GetWithReceiver(JSObject* obj, 320 virtual MaybeObject* GetWithReceiver(JSObject* obj,
198 Object* receiver, 321 Object* receiver,
199 uint32_t index) { 322 uint32_t index) {
200 return GetNumberDictionaryElement(obj, 323 return GetNumberDictionaryElement(obj,
201 receiver, 324 receiver,
202 obj->element_dictionary(), 325 obj->element_dictionary(),
203 index); 326 index);
204 } 327 }
205 }; 328 };
206 329
(...skipping 22 matching lines...) Expand all
229 obj, 352 obj,
230 receiver, 353 receiver,
231 NumberDictionary::cast(arguments), 354 NumberDictionary::cast(arguments),
232 index); 355 index);
233 } else if (index < static_cast<uint32_t>(arguments->length())) { 356 } else if (index < static_cast<uint32_t>(arguments->length())) {
234 return arguments->get(index); 357 return arguments->get(index);
235 } 358 }
236 } 359 }
237 return obj->GetHeap()->the_hole_value(); 360 return obj->GetHeap()->the_hole_value();
238 } 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 }
239 }; 385 };
240 386
241 387
242 void ElementsAccessor::InitializeOncePerProcess() { 388 void ElementsAccessor::InitializeOncePerProcess() {
243 static struct ConcreteElementsAccessors { 389 static struct ConcreteElementsAccessors {
244 FastElementsAccessor fast_elements_handler; 390 FastElementsAccessor fast_elements_handler;
245 FastDoubleElementsAccessor fast_double_elements_handler; 391 FastDoubleElementsAccessor fast_double_elements_handler;
246 DictionaryElementsAccessor dictionary_elements_handler; 392 DictionaryElementsAccessor dictionary_elements_handler;
247 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; 393 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler;
248 ExternalByteElementsAccessor byte_elements_handler; 394 ExternalByteElementsAccessor byte_elements_handler;
(...skipping 21 matching lines...) Expand all
270 &element_accessors.float_elements_handler, 416 &element_accessors.float_elements_handler,
271 &element_accessors.double_elements_handler, 417 &element_accessors.double_elements_handler,
272 &element_accessors.pixel_elements_handler 418 &element_accessors.pixel_elements_handler
273 }; 419 };
274 420
275 elements_accessors_ = accessor_array; 421 elements_accessors_ = accessor_array;
276 } 422 }
277 423
278 424
279 } } // namespace v8::internal 425 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/elements.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698