OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 array->set_length(len); | 239 array->set_length(len); |
240 | 240 |
241 return array; | 241 return array; |
242 } | 242 } |
243 | 243 |
244 | 244 |
245 BUILTIN(ArrayPush) { | 245 BUILTIN(ArrayPush) { |
246 JSArray* array = JSArray::cast(*args.receiver()); | 246 JSArray* array = JSArray::cast(*args.receiver()); |
247 ASSERT(array->HasFastElements()); | 247 ASSERT(array->HasFastElements()); |
248 | 248 |
249 // Make sure we have space for the elements. | |
250 int len = Smi::cast(array->length())->value(); | 249 int len = Smi::cast(array->length())->value(); |
| 250 int to_add = args.length() - 1; |
| 251 if (to_add == 0) { |
| 252 return Smi::FromInt(len); |
| 253 } |
251 | 254 |
252 // Set new length. | 255 int new_length = len + to_add; |
253 int new_length = len + args.length() - 1; | |
254 FixedArray* elms = FixedArray::cast(array->elements()); | 256 FixedArray* elms = FixedArray::cast(array->elements()); |
255 | 257 |
256 if (new_length <= elms->length()) { | 258 if (new_length > elms->length()) { |
257 // Backing storage has extra space for the provided values. | |
258 for (int index = 0; index < args.length() - 1; index++) { | |
259 elms->set(index + len, args[index+1]); | |
260 } | |
261 } else { | |
262 // New backing storage is needed. | 259 // New backing storage is needed. |
263 int capacity = new_length + (new_length >> 1) + 16; | 260 int capacity = new_length + (new_length >> 1) + 16; |
264 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); | 261 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
265 if (obj->IsFailure()) return obj; | 262 if (obj->IsFailure()) return obj; |
266 | 263 |
267 AssertNoAllocation no_gc; | 264 AssertNoAllocation no_gc; |
268 FixedArray* new_elms = FixedArray::cast(obj); | 265 FixedArray* new_elms = FixedArray::cast(obj); |
269 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); | 266 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); |
270 // Fill out the new array with old elements. | 267 // Fill out the new array with old elements. |
271 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); | 268 for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode); |
272 // Add the provided values. | 269 elms = new_elms; |
273 for (int index = 0; index < args.length() - 1; index++) { | 270 array->set_elements(elms); |
274 new_elms->set(index + len, args[index+1], mode); | |
275 } | |
276 // Set the new backing storage. | |
277 array->set_elements(new_elms); | |
278 } | 271 } |
| 272 |
| 273 AssertNoAllocation no_gc; |
| 274 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 275 |
| 276 // Add the provided values. |
| 277 for (int index = 0; index < to_add; index++) { |
| 278 elms->set(index + len, args[index + 1], mode); |
| 279 } |
| 280 |
279 // Set the length. | 281 // Set the length. |
280 array->set_length(Smi::FromInt(new_length)); | 282 array->set_length(Smi::FromInt(new_length)); |
281 return array->length(); | 283 return Smi::FromInt(new_length); |
282 } | 284 } |
283 | 285 |
284 | 286 |
285 BUILTIN(ArrayPop) { | 287 BUILTIN(ArrayPop) { |
286 JSArray* array = JSArray::cast(*args.receiver()); | 288 JSArray* array = JSArray::cast(*args.receiver()); |
287 ASSERT(array->HasFastElements()); | 289 ASSERT(array->HasFastElements()); |
288 Object* undefined = Heap::undefined_value(); | 290 Object* undefined = Heap::undefined_value(); |
289 | 291 |
290 int len = Smi::cast(array->length())->value(); | 292 int len = Smi::cast(array->length())->value(); |
291 if (len == 0) return undefined; | 293 if (len == 0) return undefined; |
(...skipping 14 matching lines...) Expand all Loading... |
306 // Remember to check the prototype chain. | 308 // Remember to check the prototype chain. |
307 JSFunction* array_function = | 309 JSFunction* array_function = |
308 Top::context()->global_context()->array_function(); | 310 Top::context()->global_context()->array_function(); |
309 JSObject* prototype = JSObject::cast(array_function->prototype()); | 311 JSObject* prototype = JSObject::cast(array_function->prototype()); |
310 top = prototype->GetElement(len - 1); | 312 top = prototype->GetElement(len - 1); |
311 | 313 |
312 return top; | 314 return top; |
313 } | 315 } |
314 | 316 |
315 | 317 |
| 318 static Object* GetElementToMove(uint32_t index, |
| 319 FixedArray* elms, |
| 320 JSObject* prototype) { |
| 321 Object* e = elms->get(index); |
| 322 if (e->IsTheHole() && prototype->HasElement(index)) { |
| 323 e = prototype->GetElement(index); |
| 324 } |
| 325 return e; |
| 326 } |
| 327 |
| 328 |
316 BUILTIN(ArrayShift) { | 329 BUILTIN(ArrayShift) { |
317 JSArray* array = JSArray::cast(*args.receiver()); | 330 JSArray* array = JSArray::cast(*args.receiver()); |
318 ASSERT(array->HasFastElements()); | 331 ASSERT(array->HasFastElements()); |
319 | 332 |
320 int len = Smi::cast(array->length())->value(); | 333 int len = Smi::cast(array->length())->value(); |
321 if (len == 0) return Heap::undefined_value(); | 334 if (len == 0) return Heap::undefined_value(); |
322 | 335 |
323 // Fetch the prototype. | 336 // Fetch the prototype. |
324 JSFunction* array_function = | 337 JSFunction* array_function = |
325 Top::context()->global_context()->array_function(); | 338 Top::context()->global_context()->array_function(); |
326 JSObject* prototype = JSObject::cast(array_function->prototype()); | 339 JSObject* prototype = JSObject::cast(array_function->prototype()); |
327 | 340 |
| 341 FixedArray* elms = FixedArray::cast(array->elements()); |
| 342 |
328 // Get first element | 343 // Get first element |
329 FixedArray* elms = FixedArray::cast(array->elements()); | |
330 Object* first = elms->get(0); | 344 Object* first = elms->get(0); |
331 | |
332 if (first->IsTheHole()) { | 345 if (first->IsTheHole()) { |
333 first = prototype->GetElement(0); | 346 first = prototype->GetElement(0); |
334 } | 347 } |
335 | 348 |
336 // Shift the elements. | 349 // Shift the elements. |
337 for (int i = 0; i < len - 1; i++) { | 350 for (int i = 0; i < len - 1; i++) { |
338 Object* e = elms->get(i + 1); | 351 elms->set(i, GetElementToMove(i + 1, elms, prototype)); |
339 if (e->IsTheHole() && prototype->HasElement(i + 1)) { | |
340 e = prototype->GetElement(i + 1); | |
341 } | |
342 elms->set(i, e); | |
343 } | 352 } |
344 elms->set(len - 1, Heap::the_hole_value()); | 353 elms->set(len - 1, Heap::the_hole_value()); |
345 | 354 |
346 // Set the length. | 355 // Set the length. |
347 array->set_length(Smi::FromInt(len - 1)); | 356 array->set_length(Smi::FromInt(len - 1)); |
348 | 357 |
349 return first; | 358 return first; |
350 } | 359 } |
351 | 360 |
352 | 361 |
| 362 BUILTIN(ArrayUnshift) { |
| 363 JSArray* array = JSArray::cast(*args.receiver()); |
| 364 ASSERT(array->HasFastElements()); |
| 365 |
| 366 int len = Smi::cast(array->length())->value(); |
| 367 int to_add = args.length() - 1; |
| 368 // Note that we cannot quit early if to_add == 0 as |
| 369 // values should be lifted from prototype into |
| 370 // the array. |
| 371 |
| 372 int new_length = len + to_add; |
| 373 FixedArray* elms = FixedArray::cast(array->elements()); |
| 374 |
| 375 // Fetch the prototype. |
| 376 JSFunction* array_function = |
| 377 Top::context()->global_context()->array_function(); |
| 378 JSObject* prototype = JSObject::cast(array_function->prototype()); |
| 379 |
| 380 if (new_length > elms->length()) { |
| 381 // New backing storage is needed. |
| 382 int capacity = new_length + (new_length >> 1) + 16; |
| 383 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 384 if (obj->IsFailure()) return obj; |
| 385 |
| 386 AssertNoAllocation no_gc; |
| 387 FixedArray* new_elms = FixedArray::cast(obj); |
| 388 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); |
| 389 // Fill out the new array with old elements. |
| 390 for (int i = 0; i < len; i++) |
| 391 new_elms->set(to_add + i, |
| 392 GetElementToMove(i, elms, prototype), |
| 393 mode); |
| 394 |
| 395 elms = new_elms; |
| 396 array->set_elements(elms); |
| 397 } else { |
| 398 AssertNoAllocation no_gc; |
| 399 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 400 |
| 401 // Move elements to the right |
| 402 for (int i = 0; i < len; i++) { |
| 403 elms->set(new_length - i - 1, |
| 404 GetElementToMove(len - i - 1, elms, prototype), |
| 405 mode); |
| 406 } |
| 407 } |
| 408 |
| 409 // Add the provided values. |
| 410 AssertNoAllocation no_gc; |
| 411 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 412 for (int i = 0; i < to_add; i++) { |
| 413 elms->set(i, args[i + 1], mode); |
| 414 } |
| 415 |
| 416 // Set the length. |
| 417 array->set_length(Smi::FromInt(new_length)); |
| 418 return Smi::FromInt(new_length); |
| 419 } |
| 420 |
| 421 |
353 // ----------------------------------------------------------------------------- | 422 // ----------------------------------------------------------------------------- |
354 // | 423 // |
355 | 424 |
356 | 425 |
357 // Returns the holder JSObject if the function can legally be called | 426 // Returns the holder JSObject if the function can legally be called |
358 // with this receiver. Returns Heap::null_value() if the call is | 427 // with this receiver. Returns Heap::null_value() if the call is |
359 // illegal. Any arguments that don't fit the expected type is | 428 // illegal. Any arguments that don't fit the expected type is |
360 // overwritten with undefined. Arguments that do fit the expected | 429 // overwritten with undefined. Arguments that do fit the expected |
361 // type is overwritten with the object in the prototype chain that | 430 // type is overwritten with the object in the prototype chain that |
362 // actually has that type. | 431 // actually has that type. |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 if (entry->contains(pc)) { | 1058 if (entry->contains(pc)) { |
990 return names_[i]; | 1059 return names_[i]; |
991 } | 1060 } |
992 } | 1061 } |
993 } | 1062 } |
994 return NULL; | 1063 return NULL; |
995 } | 1064 } |
996 | 1065 |
997 | 1066 |
998 } } // namespace v8::internal | 1067 } } // namespace v8::internal |
OLD | NEW |