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

Side by Side Diff: src/elements.cc

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

Powered by Google App Engine
This is Rietveld 408576698