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

Side by Side Diff: src/elements.cc

Issue 7657011: Implement UnionOfKeys for NonStrictArguments (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback 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') | test/cctest/test-api.cc » ('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 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "objects.h" 30 #include "objects.h"
31 #include "elements.h" 31 #include "elements.h"
32 #include "utils.h"
32 33
33 namespace v8 { 34 namespace v8 {
34 namespace internal { 35 namespace internal {
35 36
36 37
37 ElementsAccessor** ElementsAccessor::elements_accessors_; 38 ElementsAccessor** ElementsAccessor::elements_accessors_;
38 39
39 40
40 bool HasKey(FixedArray* array, Object* key) { 41 bool HasKey(FixedArray* array, Object* key) {
41 int len0 = array->length(); 42 int len0 = array->length();
(...skipping 21 matching lines...) Expand all
63 // BackingStoreClass> { 64 // BackingStoreClass> {
64 // ... 65 // ...
65 // } 66 // }
66 // 67 //
67 // This is an example of the Curiously Recurring Template Pattern (see 68 // This is an example of the Curiously Recurring Template Pattern (see
68 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use 69 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
69 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and 70 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
70 // specialization of SomeElementsAccessor methods). 71 // specialization of SomeElementsAccessor methods).
71 template <typename ElementsAccessorSubclass, typename BackingStoreClass> 72 template <typename ElementsAccessorSubclass, typename BackingStoreClass>
72 class ElementsAccessorBase : public ElementsAccessor { 73 class ElementsAccessorBase : public ElementsAccessor {
73 public: 74 protected:
74 ElementsAccessorBase() { } 75 ElementsAccessorBase() { }
75 virtual MaybeObject* GetWithReceiver(JSObject* obj, 76 virtual MaybeObject* GetWithReceiver(JSObject* obj,
76 Object* receiver, 77 Object* receiver,
77 uint32_t index) { 78 uint32_t key) {
78 BackingStoreClass* backing_store = BackingStoreClass::cast(obj->elements()); 79 BackingStoreClass* backing_store = BackingStoreClass::cast(obj->elements());
79 if (index < ElementsAccessorSubclass::GetLength(backing_store)) { 80 if (key < ElementsAccessorSubclass::GetCapacity(backing_store)) {
80 return backing_store->get(index); 81 return backing_store->get(key);
81 } 82 }
82 return obj->GetHeap()->the_hole_value(); 83 return obj->GetHeap()->the_hole_value();
83 } 84 }
84 85
85 virtual MaybeObject* Delete(JSObject* obj, 86 virtual MaybeObject* Delete(JSObject* obj,
86 uint32_t index, 87 uint32_t key,
87 JSReceiver::DeleteMode mode) = 0; 88 JSReceiver::DeleteMode mode) = 0;
88 89
89 virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from, 90 virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from,
90 FixedArray* to) { 91 FixedArray* to) {
91 int len0 = to->length(); 92 int len0 = to->length();
92 #ifdef DEBUG 93 #ifdef DEBUG
93 if (FLAG_enable_slow_asserts) { 94 if (FLAG_enable_slow_asserts) {
94 for (int i = 0; i < len0; i++) { 95 for (int i = 0; i < len0; i++) {
95 ASSERT(!to->get(i)->IsTheHole()); 96 ASSERT(!to->get(i)->IsTheHole());
96 } 97 }
97 } 98 }
98 #endif 99 #endif
99 BackingStoreClass* backing_store = BackingStoreClass::cast(from); 100 BackingStoreClass* backing_store = BackingStoreClass::cast(from);
100 int len1 = ElementsAccessorSubclass::GetCapacity(backing_store); 101 uint32_t len1 = ElementsAccessorSubclass::GetCapacity(backing_store);
101 102
102 // Optimize if 'other' is empty. 103 // Optimize if 'other' is empty.
103 // We cannot optimize if 'this' is empty, as other may have holes. 104 // We cannot optimize if 'this' is empty, as other may have holes.
104 if (len1 == 0) return to; 105 if (len1 == 0) return to;
105 106
106 // Compute how many elements are not in other. 107 // Compute how many elements are not in other.
107 int extra = 0; 108 int extra = 0;
108 for (int y = 0; y < len1; y++) { 109 for (uint32_t y = 0; y < len1; y++) {
109 Object* value; 110 if (ElementsAccessorSubclass::HasElementAtIndex(backing_store, y)) {
110 MaybeObject* maybe_value = 111 uint32_t key =
111 ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y); 112 ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
112 if (!maybe_value->ToObject(&value)) return maybe_value; 113 MaybeObject* maybe_value =
113 if (!value->IsTheHole() && !HasKey(to, value)) extra++; 114 ElementsAccessorSubclass::GetElement(backing_store, key);
115 Object* value;
116 if (!maybe_value->ToObject(&value)) return maybe_value;
117 ASSERT(!value->IsTheHole());
118 if (!HasKey(to, value)) {
119 extra++;
120 }
121 }
114 } 122 }
115 123
116 if (extra == 0) return to; 124 if (extra == 0) return to;
117 125
118 // Allocate the result 126 // Allocate the result
119 FixedArray* result; 127 FixedArray* result;
120 MaybeObject* maybe_obj = 128 MaybeObject* maybe_obj =
121 backing_store->GetHeap()->AllocateFixedArray(len0 + extra); 129 backing_store->GetHeap()->AllocateFixedArray(len0 + extra);
122 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj; 130 if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
123 131
124 // Fill in the content 132 // Fill in the content
125 { 133 {
126 AssertNoAllocation no_gc; 134 AssertNoAllocation no_gc;
127 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); 135 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
128 for (int i = 0; i < len0; i++) { 136 for (int i = 0; i < len0; i++) {
129 Object* e = to->get(i); 137 Object* e = to->get(i);
130 ASSERT(e->IsString() || e->IsNumber()); 138 ASSERT(e->IsString() || e->IsNumber());
131 result->set(i, e, mode); 139 result->set(i, e, mode);
132 } 140 }
133 } 141 }
134 // Fill in the extra values. 142 // Fill in the extra values.
135 int index = 0; 143 int index = 0;
136 for (int y = 0; y < len1; y++) { 144 for (uint32_t y = 0; y < len1; y++) {
137 MaybeObject* maybe_value = 145 if (ElementsAccessorSubclass::HasElementAtIndex(backing_store, y)) {
138 ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y); 146 uint32_t key =
139 Object* value; 147 ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
140 if (!maybe_value->ToObject(&value)) return maybe_value; 148 MaybeObject* maybe_value =
141 if (!value->IsTheHole() && !HasKey(to, value)) { 149 ElementsAccessorSubclass::GetElement(backing_store, key);
142 result->set(len0 + index, value); 150 Object* value;
143 index++; 151 if (!maybe_value->ToObject(&value)) return maybe_value;
152 if (!value->IsTheHole() && !HasKey(to, value)) {
153 result->set(len0 + index, value);
154 index++;
155 }
144 } 156 }
145 } 157 }
146 ASSERT(extra == index); 158 ASSERT(extra == index);
147 return result; 159 return result;
148 } 160 }
149 161
150 static uint32_t GetLength(BackingStoreClass* backing_store) { 162 protected:
163 static uint32_t GetCapacity(BackingStoreClass* backing_store) {
151 return backing_store->length(); 164 return backing_store->length();
152 } 165 }
153 166
154 static uint32_t GetCapacity(BackingStoreClass* backing_store) { 167 virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
155 return GetLength(backing_store); 168 return ElementsAccessorSubclass::GetCapacity(
169 BackingStoreClass::cast(backing_store));
156 } 170 }
157 171
158 static MaybeObject* GetElementAtCapacityIndex( 172 static MaybeObject* GetElement(
159 BackingStoreClass* backing_store, 173 BackingStoreClass* backing_store,
160 int index) { 174 uint32_t key) {
161 return backing_store->get(index); 175 return backing_store->get(key);
176 }
177
178 virtual MaybeObject* GetElement(FixedArrayBase* backing_store,
179 uint32_t key) {
180 return ElementsAccessorSubclass::GetElement(
181 BackingStoreClass::cast(backing_store), key);
182 }
183
184 static bool HasElementAtIndex(BackingStoreClass* backing_store,
185 uint32_t index) {
186 uint32_t key =
187 ElementsAccessorSubclass::GetKeyForIndex(backing_store, index);
188 MaybeObject* element = ElementsAccessorSubclass::GetElement(backing_store,
189 key);
190 return !element->IsTheHole();
191 }
192
193 virtual bool HasElementAtIndex(FixedArrayBase* backing_store,
194 uint32_t index) {
195 return ElementsAccessorSubclass::HasElementAtIndex(
196 BackingStoreClass::cast(backing_store), index);
197 }
198
199 static uint32_t GetKeyForIndex(BackingStoreClass* backing_store,
200 uint32_t index) {
201 return index;
202 }
203
204 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
205 uint32_t index) {
206 return ElementsAccessorSubclass::GetKeyForIndex(
207 BackingStoreClass::cast(backing_store), index);
162 } 208 }
163 209
164 private: 210 private:
165 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); 211 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
166 }; 212 };
167 213
168 214
169 class FastElementsAccessor 215 class FastElementsAccessor
170 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> { 216 : public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
171 public: 217 public:
172 static MaybeObject* DeleteCommon(JSObject* obj, 218 static MaybeObject* DeleteCommon(JSObject* obj,
173 uint32_t index) { 219 uint32_t key) {
174 ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements()); 220 ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
175 Heap* heap = obj->GetHeap(); 221 Heap* heap = obj->GetHeap();
176 FixedArray* backing_store = FixedArray::cast(obj->elements()); 222 FixedArray* backing_store = FixedArray::cast(obj->elements());
177 if (backing_store->map() == heap->non_strict_arguments_elements_map()) { 223 if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
178 backing_store = FixedArray::cast(backing_store->get(1)); 224 backing_store = FixedArray::cast(backing_store->get(1));
179 } else { 225 } else {
180 Object* writable; 226 Object* writable;
181 MaybeObject* maybe = obj->EnsureWritableFastElements(); 227 MaybeObject* maybe = obj->EnsureWritableFastElements();
182 if (!maybe->ToObject(&writable)) return maybe; 228 if (!maybe->ToObject(&writable)) return maybe;
183 backing_store = FixedArray::cast(writable); 229 backing_store = FixedArray::cast(writable);
184 } 230 }
185 uint32_t length = static_cast<uint32_t>( 231 uint32_t length = static_cast<uint32_t>(
186 obj->IsJSArray() 232 obj->IsJSArray()
187 ? Smi::cast(JSArray::cast(obj)->length())->value() 233 ? Smi::cast(JSArray::cast(obj)->length())->value()
188 : backing_store->length()); 234 : backing_store->length());
189 if (index < length) { 235 if (key < length) {
190 backing_store->set_the_hole(index); 236 backing_store->set_the_hole(key);
191 // If an old space backing store is larger than a certain size and 237 // If an old space backing store is larger than a certain size and
192 // has too few used values, normalize it. 238 // has too few used values, normalize it.
193 // To avoid doing the check on every delete we require at least 239 // To avoid doing the check on every delete we require at least
194 // one adjacent hole to the value being deleted. 240 // one adjacent hole to the value being deleted.
195 Object* hole = heap->the_hole_value(); 241 Object* hole = heap->the_hole_value();
196 const int kMinLengthForSparsenessCheck = 64; 242 const int kMinLengthForSparsenessCheck = 64;
197 if (backing_store->length() >= kMinLengthForSparsenessCheck && 243 if (backing_store->length() >= kMinLengthForSparsenessCheck &&
198 !heap->InNewSpace(backing_store) && 244 !heap->InNewSpace(backing_store) &&
199 ((index > 0 && backing_store->get(index - 1) == hole) || 245 ((key > 0 && backing_store->get(key - 1) == hole) ||
200 (index + 1 < length && backing_store->get(index + 1) == hole))) { 246 (key + 1 < length && backing_store->get(key + 1) == hole))) {
201 int num_used = 0; 247 int num_used = 0;
202 for (int i = 0; i < backing_store->length(); ++i) { 248 for (int i = 0; i < backing_store->length(); ++i) {
203 if (backing_store->get(i) != hole) ++num_used; 249 if (backing_store->get(i) != hole) ++num_used;
204 // Bail out early if more than 1/4 is used. 250 // Bail out early if more than 1/4 is used.
205 if (4 * num_used > backing_store->length()) break; 251 if (4 * num_used > backing_store->length()) break;
206 } 252 }
207 if (4 * num_used <= backing_store->length()) { 253 if (4 * num_used <= backing_store->length()) {
208 MaybeObject* result = obj->NormalizeElements(); 254 MaybeObject* result = obj->NormalizeElements();
209 if (result->IsFailure()) return result; 255 if (result->IsFailure()) return result;
210 } 256 }
211 } 257 }
212 } 258 }
213 return heap->true_value(); 259 return heap->true_value();
214 } 260 }
215 261
262 protected:
216 virtual MaybeObject* Delete(JSObject* obj, 263 virtual MaybeObject* Delete(JSObject* obj,
217 uint32_t index, 264 uint32_t key,
218 JSReceiver::DeleteMode mode) { 265 JSReceiver::DeleteMode mode) {
219 return DeleteCommon(obj, index); 266 return DeleteCommon(obj, key);
220 } 267 }
221 }; 268 };
222 269
223 270
224 class FastDoubleElementsAccessor 271 class FastDoubleElementsAccessor
225 : public ElementsAccessorBase<FastDoubleElementsAccessor, 272 : public ElementsAccessorBase<FastDoubleElementsAccessor,
226 FixedDoubleArray> { 273 FixedDoubleArray> {
274 protected:
275 friend class ElementsAccessorBase<FastDoubleElementsAccessor,
276 FixedDoubleArray>;
277
227 virtual MaybeObject* Delete(JSObject* obj, 278 virtual MaybeObject* Delete(JSObject* obj,
228 uint32_t index, 279 uint32_t key,
229 JSReceiver::DeleteMode mode) { 280 JSReceiver::DeleteMode mode) {
230 int length = obj->IsJSArray() 281 int length = obj->IsJSArray()
231 ? Smi::cast(JSArray::cast(obj)->length())->value() 282 ? Smi::cast(JSArray::cast(obj)->length())->value()
232 : FixedDoubleArray::cast(obj->elements())->length(); 283 : FixedDoubleArray::cast(obj->elements())->length();
233 if (index < static_cast<uint32_t>(length)) { 284 if (key < static_cast<uint32_t>(length)) {
234 FixedDoubleArray::cast(obj->elements())->set_the_hole(index); 285 FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
235 } 286 }
236 return obj->GetHeap()->true_value(); 287 return obj->GetHeap()->true_value();
237 } 288 }
289
290 static bool HasElementAtIndex(FixedDoubleArray* backing_store,
291 uint32_t index) {
292 return !backing_store->is_the_hole(index);
293 }
238 }; 294 };
239 295
240 296
241 // Super class for all external element arrays. 297 // Super class for all external element arrays.
242 template<typename ExternalElementsAccessorSubclass, 298 template<typename ExternalElementsAccessorSubclass,
243 typename ExternalArray> 299 typename ExternalArray>
244 class ExternalElementsAccessor 300 class ExternalElementsAccessor
245 : public ElementsAccessorBase<ExternalElementsAccessorSubclass, 301 : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
246 ExternalArray> { 302 ExternalArray> {
247 public: 303 protected:
248 virtual MaybeObject* GetWithReceiver(JSObject* obj, 304 virtual MaybeObject* GetWithReceiver(JSObject* obj,
249 Object* receiver, 305 Object* receiver,
250 uint32_t index) { 306 uint32_t key) {
251 ExternalArray* backing_store = ExternalArray::cast(obj->elements()); 307 ExternalArray* backing_store = ExternalArray::cast(obj->elements());
252 if (index < ExternalElementsAccessorSubclass::GetLength(backing_store)) { 308 if (key < ExternalElementsAccessorSubclass::GetCapacity(backing_store)) {
253 return backing_store->get(index); 309 return backing_store->get(key);
254 } else { 310 } else {
255 return obj->GetHeap()->undefined_value(); 311 return obj->GetHeap()->undefined_value();
256 } 312 }
257 } 313 }
258 314
259 virtual MaybeObject* Delete(JSObject* obj, 315 virtual MaybeObject* Delete(JSObject* obj,
260 uint32_t index, 316 uint32_t key,
261 JSReceiver::DeleteMode mode) { 317 JSReceiver::DeleteMode mode) {
262 // External arrays always ignore deletes. 318 // External arrays always ignore deletes.
263 return obj->GetHeap()->true_value(); 319 return obj->GetHeap()->true_value();
264 } 320 }
265 }; 321 };
266 322
267 323
268 class ExternalByteElementsAccessor 324 class ExternalByteElementsAccessor
269 : public ExternalElementsAccessor<ExternalByteElementsAccessor, 325 : public ExternalElementsAccessor<ExternalByteElementsAccessor,
270 ExternalByteArray> { 326 ExternalByteArray> {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 376
321 377
322 class DictionaryElementsAccessor 378 class DictionaryElementsAccessor
323 : public ElementsAccessorBase<DictionaryElementsAccessor, 379 : public ElementsAccessorBase<DictionaryElementsAccessor,
324 NumberDictionary> { 380 NumberDictionary> {
325 public: 381 public:
326 static MaybeObject* GetNumberDictionaryElement( 382 static MaybeObject* GetNumberDictionaryElement(
327 JSObject* obj, 383 JSObject* obj,
328 Object* receiver, 384 Object* receiver,
329 NumberDictionary* backing_store, 385 NumberDictionary* backing_store,
330 uint32_t index) { 386 uint32_t key) {
331 int entry = backing_store->FindEntry(index); 387 int entry = backing_store->FindEntry(key);
332 if (entry != NumberDictionary::kNotFound) { 388 if (entry != NumberDictionary::kNotFound) {
333 Object* element = backing_store->ValueAt(entry); 389 Object* element = backing_store->ValueAt(entry);
334 PropertyDetails details = backing_store->DetailsAt(entry); 390 PropertyDetails details = backing_store->DetailsAt(entry);
335 if (details.type() == CALLBACKS) { 391 if (details.type() == CALLBACKS) {
336 return obj->GetElementWithCallback(receiver, 392 return obj->GetElementWithCallback(receiver,
337 element, 393 element,
338 index, 394 key,
339 obj); 395 obj);
340 } else { 396 } else {
341 return element; 397 return element;
342 } 398 }
343 } 399 }
344 return obj->GetHeap()->the_hole_value(); 400 return obj->GetHeap()->the_hole_value();
345 } 401 }
346 402
347
348 static MaybeObject* DeleteCommon(JSObject* obj, 403 static MaybeObject* DeleteCommon(JSObject* obj,
349 uint32_t index, 404 uint32_t key,
350 JSReceiver::DeleteMode mode) { 405 JSReceiver::DeleteMode mode) {
351 Isolate* isolate = obj->GetIsolate(); 406 Isolate* isolate = obj->GetIsolate();
352 Heap* heap = isolate->heap(); 407 Heap* heap = isolate->heap();
353 FixedArray* backing_store = FixedArray::cast(obj->elements()); 408 FixedArray* backing_store = FixedArray::cast(obj->elements());
354 bool is_arguments = 409 bool is_arguments =
355 (obj->GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS); 410 (obj->GetElementsKind() == JSObject::NON_STRICT_ARGUMENTS_ELEMENTS);
356 if (is_arguments) { 411 if (is_arguments) {
357 backing_store = FixedArray::cast(backing_store->get(1)); 412 backing_store = FixedArray::cast(backing_store->get(1));
358 } 413 }
359 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); 414 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
360 int entry = dictionary->FindEntry(index); 415 int entry = dictionary->FindEntry(key);
361 if (entry != NumberDictionary::kNotFound) { 416 if (entry != NumberDictionary::kNotFound) {
362 Object* result = dictionary->DeleteProperty(entry, mode); 417 Object* result = dictionary->DeleteProperty(entry, mode);
363 if (result == heap->true_value()) { 418 if (result == heap->true_value()) {
364 MaybeObject* maybe_elements = dictionary->Shrink(index); 419 MaybeObject* maybe_elements = dictionary->Shrink(key);
365 FixedArray* new_elements = NULL; 420 FixedArray* new_elements = NULL;
366 if (!maybe_elements->To(&new_elements)) { 421 if (!maybe_elements->To(&new_elements)) {
367 return maybe_elements; 422 return maybe_elements;
368 } 423 }
369 if (is_arguments) { 424 if (is_arguments) {
370 FixedArray::cast(obj->elements())->set(1, new_elements); 425 FixedArray::cast(obj->elements())->set(1, new_elements);
371 } else { 426 } else {
372 obj->set_elements(new_elements); 427 obj->set_elements(new_elements);
373 } 428 }
374 } 429 }
375 if (mode == JSObject::STRICT_DELETION && 430 if (mode == JSObject::STRICT_DELETION &&
376 result == heap->false_value()) { 431 result == heap->false_value()) {
377 // In strict mode, attempting to delete a non-configurable property 432 // In strict mode, attempting to delete a non-configurable property
378 // throws an exception. 433 // throws an exception.
379 HandleScope scope(isolate); 434 HandleScope scope(isolate);
380 Handle<Object> holder(obj); 435 Handle<Object> holder(obj);
381 Handle<Object> name = isolate->factory()->NewNumberFromUint(index); 436 Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
382 Handle<Object> args[2] = { name, holder }; 437 Handle<Object> args[2] = { name, holder };
383 Handle<Object> error = 438 Handle<Object> error =
384 isolate->factory()->NewTypeError("strict_delete_property", 439 isolate->factory()->NewTypeError("strict_delete_property",
385 HandleVector(args, 2)); 440 HandleVector(args, 2));
386 return isolate->Throw(*error); 441 return isolate->Throw(*error);
387 } 442 }
388 } 443 }
389 return heap->true_value(); 444 return heap->true_value();
390 } 445 }
391 446
447 protected:
448 friend class ElementsAccessorBase<DictionaryElementsAccessor,
449 NumberDictionary>;
450
392 virtual MaybeObject* Delete(JSObject* obj, 451 virtual MaybeObject* Delete(JSObject* obj,
393 uint32_t index, 452 uint32_t key,
394 JSReceiver::DeleteMode mode) { 453 JSReceiver::DeleteMode mode) {
395 return DeleteCommon(obj, index, mode); 454 return DeleteCommon(obj, key, mode);
396 } 455 }
397 456
398 virtual MaybeObject* GetWithReceiver(JSObject* obj, 457 virtual MaybeObject* GetWithReceiver(JSObject* obj,
399 Object* receiver, 458 Object* receiver,
400 uint32_t index) { 459 uint32_t key) {
401 return GetNumberDictionaryElement(obj, 460 return GetNumberDictionaryElement(obj,
402 receiver, 461 receiver,
403 obj->element_dictionary(), 462 obj->element_dictionary(),
404 index); 463 key);
405 } 464 }
406 465
407 static uint32_t GetCapacity(NumberDictionary* dict) { 466 static uint32_t GetKeyForIndex(NumberDictionary* dict,
408 return dict->Capacity(); 467 uint32_t index) {
468 Object* key = dict->KeyAt(index);
469 return Smi::cast(key)->value();
409 } 470 }
410 471
411 static MaybeObject* GetElementAtCapacityIndex(NumberDictionary* dict, 472 static MaybeObject* GetElement(NumberDictionary* dict,
412 int index) { 473 int key) {
413 if (dict->IsKey(dict->KeyAt(index))) { 474 int entry = dict->FindEntry(key);
414 return dict->ValueAt(index); 475 if (entry != NumberDictionary::kNotFound) {
476 return dict->ValueAt(entry);
415 } else { 477 } else {
416 return dict->GetHeap()->the_hole_value(); 478 return dict->GetHeap()->the_hole_value();
417 } 479 }
418 } 480 }
419 }; 481 };
420 482
421 483
422 class NonStrictArgumentsElementsAccessor 484 class NonStrictArgumentsElementsAccessor
423 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor, 485 : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
424 FixedArray> { 486 FixedArray> {
425 public: 487 protected:
488 friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
489 FixedArray>;
490
426 virtual MaybeObject* GetWithReceiver(JSObject* obj, 491 virtual MaybeObject* GetWithReceiver(JSObject* obj,
427 Object* receiver, 492 Object* receiver,
428 uint32_t index) { 493 uint32_t key) {
429 FixedArray* parameter_map = FixedArray::cast(obj->elements()); 494 FixedArray* parameter_map = FixedArray::cast(obj->elements());
430 uint32_t length = parameter_map->length(); 495 Object* probe = GetParameterMapArg(parameter_map, key);
431 Object* probe = 496 if (!probe->IsTheHole()) {
432 (index < length - 2) ? parameter_map->get(index + 2) : NULL;
433 if (probe != NULL && !probe->IsTheHole()) {
434 Context* context = Context::cast(parameter_map->get(0)); 497 Context* context = Context::cast(parameter_map->get(0));
435 int context_index = Smi::cast(probe)->value(); 498 int context_index = Smi::cast(probe)->value();
436 ASSERT(!context->get(context_index)->IsTheHole()); 499 ASSERT(!context->get(context_index)->IsTheHole());
437 return context->get(context_index); 500 return context->get(context_index);
438 } else { 501 } else {
439 // Object is not mapped, defer to the arguments. 502 // Object is not mapped, defer to the arguments.
440 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 503 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
441 if (arguments->IsDictionary()) { 504 if (arguments->IsDictionary()) {
442 return DictionaryElementsAccessor::GetNumberDictionaryElement( 505 return DictionaryElementsAccessor::GetNumberDictionaryElement(
443 obj, 506 obj,
444 receiver, 507 receiver,
445 NumberDictionary::cast(arguments), 508 NumberDictionary::cast(arguments),
446 index); 509 key);
447 } else if (index < static_cast<uint32_t>(arguments->length())) { 510 } else if (key < static_cast<uint32_t>(arguments->length())) {
448 return arguments->get(index); 511 return arguments->get(key);
449 } 512 }
450 } 513 }
451 return obj->GetHeap()->the_hole_value(); 514 return obj->GetHeap()->the_hole_value();
452 } 515 }
453 516
454 virtual MaybeObject* Delete(JSObject* obj, 517 virtual MaybeObject* Delete(JSObject* obj,
455 uint32_t index, 518 uint32_t key
519 ,
456 JSReceiver::DeleteMode mode) { 520 JSReceiver::DeleteMode mode) {
457 FixedArray* parameter_map = FixedArray::cast(obj->elements()); 521 FixedArray* parameter_map = FixedArray::cast(obj->elements());
458 uint32_t length = parameter_map->length(); 522 Object* probe = GetParameterMapArg(parameter_map, key);
459 Object* probe = 523 if (!probe->IsTheHole()) {
460 index < (length - 2) ? parameter_map->get(index + 2) : NULL;
461 if (probe != NULL && !probe->IsTheHole()) {
462 // TODO(kmillikin): We could check if this was the last aliased 524 // TODO(kmillikin): We could check if this was the last aliased
463 // parameter, and revert to normal elements in that case. That 525 // parameter, and revert to normal elements in that case. That
464 // would enable GC of the context. 526 // would enable GC of the context.
465 parameter_map->set_the_hole(index + 2); 527 parameter_map->set_the_hole(key + 2);
466 } else { 528 } else {
467 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); 529 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
468 if (arguments->IsDictionary()) { 530 if (arguments->IsDictionary()) {
469 return DictionaryElementsAccessor::DeleteCommon(obj, index, mode); 531 return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
470 } else { 532 } else {
471 return FastElementsAccessor::DeleteCommon(obj, index); 533 return FastElementsAccessor::DeleteCommon(obj, key);
472 } 534 }
473 } 535 }
474 return obj->GetHeap()->true_value(); 536 return obj->GetHeap()->true_value();
475 } 537 }
476 538
477 static uint32_t GetCapacity(FixedArray* obj) { 539 static uint32_t GetCapacity(FixedArray* parameter_map) {
478 // TODO(danno): Return max of parameter map length or backing store 540 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
479 // capacity. 541 return Max(static_cast<uint32_t>(parameter_map->length() - 2),
480 return 0; 542 ForArray(arguments)->GetCapacity(arguments));
481 } 543 }
482 544
483 static MaybeObject* GetElementAtCapacityIndex(FixedArray* obj, int index) { 545 static uint32_t GetKeyForIndex(FixedArray* dict,
484 // TODO(danno): Return either value from parameter map of backing 546 uint32_t index) {
485 // store value at index. 547 return index;
486 return obj->GetHeap()->the_hole_value(); 548 }
549
550 static bool HasElementAtIndex(FixedArray* parameter_map,
551 uint32_t index) {
552 Object* probe = GetParameterMapArg(parameter_map, index);
553 if (!probe->IsTheHole()) {
554 return true;
555 } else {
556 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
557 ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
558 return !accessor->GetElement(arguments, index)->IsTheHole();
559 }
560 }
561
562 static MaybeObject* GetElement(FixedArray* parameter_map,
563 uint32_t key) {
564 Object* probe = GetParameterMapArg(parameter_map, key);
565 if (!probe->IsTheHole()) {
566 Context* context = Context::cast(parameter_map->get(0));
567 int context_index = Smi::cast(probe)->value();
568 ASSERT(!context->get(context_index)->IsTheHole());
569 return context->get(context_index);
570 } else {
571 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
572 return ForArray(arguments)->GetElement(arguments, key);
573 }
574 }
575
576 private:
577
578 static Object* GetParameterMapArg(FixedArray* parameter_map,
579 uint32_t key) {
580 uint32_t length = parameter_map->length();
581 return key < (length - 2 )
582 ? parameter_map->get(key + 2)
583 : parameter_map->GetHeap()->the_hole_value();
487 } 584 }
488 }; 585 };
489 586
490 587
588 ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
589 switch (array->map()->instance_type()) {
590 case FIXED_ARRAY_TYPE:
591 if (array->IsDictionary()) {
592 return elements_accessors_[JSObject::DICTIONARY_ELEMENTS];
593 } else {
594 return elements_accessors_[JSObject::FAST_ELEMENTS];
595 }
596 case EXTERNAL_BYTE_ARRAY_TYPE:
597 return elements_accessors_[JSObject::EXTERNAL_BYTE_ELEMENTS];
598 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
599 return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
600 case EXTERNAL_SHORT_ARRAY_TYPE:
601 return elements_accessors_[JSObject::EXTERNAL_SHORT_ELEMENTS];
602 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
603 return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
604 case EXTERNAL_INT_ARRAY_TYPE:
605 return elements_accessors_[JSObject::EXTERNAL_INT_ELEMENTS];
606 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
607 return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS];
608 case EXTERNAL_FLOAT_ARRAY_TYPE:
609 return elements_accessors_[JSObject::EXTERNAL_FLOAT_ELEMENTS];
610 case EXTERNAL_DOUBLE_ARRAY_TYPE:
611 return elements_accessors_[JSObject::EXTERNAL_DOUBLE_ELEMENTS];
612 case EXTERNAL_PIXEL_ARRAY_TYPE:
613 return elements_accessors_[JSObject::EXTERNAL_PIXEL_ELEMENTS];
614 default:
615 UNREACHABLE();
616 return NULL;
617 break;
618 }
619 }
620
621
491 void ElementsAccessor::InitializeOncePerProcess() { 622 void ElementsAccessor::InitializeOncePerProcess() {
492 static struct ConcreteElementsAccessors { 623 static struct ConcreteElementsAccessors {
493 FastElementsAccessor fast_elements_handler; 624 FastElementsAccessor fast_elements_handler;
494 FastDoubleElementsAccessor fast_double_elements_handler; 625 FastDoubleElementsAccessor fast_double_elements_handler;
495 DictionaryElementsAccessor dictionary_elements_handler; 626 DictionaryElementsAccessor dictionary_elements_handler;
496 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler; 627 NonStrictArgumentsElementsAccessor non_strict_arguments_elements_handler;
497 ExternalByteElementsAccessor byte_elements_handler; 628 ExternalByteElementsAccessor byte_elements_handler;
498 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler; 629 ExternalUnsignedByteElementsAccessor unsigned_byte_elements_handler;
499 ExternalShortElementsAccessor short_elements_handler; 630 ExternalShortElementsAccessor short_elements_handler;
500 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler; 631 ExternalUnsignedShortElementsAccessor unsigned_short_elements_handler;
(...skipping 18 matching lines...) Expand all
519 &element_accessors.float_elements_handler, 650 &element_accessors.float_elements_handler,
520 &element_accessors.double_elements_handler, 651 &element_accessors.double_elements_handler,
521 &element_accessors.pixel_elements_handler 652 &element_accessors.pixel_elements_handler
522 }; 653 };
523 654
524 elements_accessors_ = accessor_array; 655 elements_accessors_ = accessor_array;
525 } 656 }
526 657
527 658
528 } } // namespace v8::internal 659 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/elements.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698