| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 // Need to ensure that the arguments passed in args can be contained in | 255 // Need to ensure that the arguments passed in args can be contained in |
| 256 // the array. | 256 // the array. |
| 257 int args_length = args->length(); | 257 int args_length = args->length(); |
| 258 if (first_added_arg >= args_length) return handle(array->elements(), isolate); | 258 if (first_added_arg >= args_length) return handle(array->elements(), isolate); |
| 259 | 259 |
| 260 ElementsKind origin_kind = array->map()->elements_kind(); | 260 ElementsKind origin_kind = array->map()->elements_kind(); |
| 261 DCHECK(!IsFastObjectElementsKind(origin_kind)); | 261 DCHECK(!IsFastObjectElementsKind(origin_kind)); |
| 262 ElementsKind target_kind = origin_kind; | 262 ElementsKind target_kind = origin_kind; |
| 263 { | 263 { |
| 264 DisallowHeapAllocation no_gc; | 264 DisallowHeapAllocation no_gc; |
| 265 int arg_count = args->length() - first_added_arg; | 265 int arg_count = args_length - first_added_arg; |
| 266 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); | 266 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); |
| 267 for (int i = 0; i < arg_count; i++) { | 267 for (int i = 0; i < arg_count; i++) { |
| 268 Object* arg = arguments[i]; | 268 Object* arg = arguments[i]; |
| 269 if (arg->IsHeapObject()) { | 269 if (arg->IsHeapObject()) { |
| 270 if (arg->IsHeapNumber()) { | 270 if (arg->IsHeapNumber()) { |
| 271 target_kind = FAST_DOUBLE_ELEMENTS; | 271 target_kind = FAST_DOUBLE_ELEMENTS; |
| 272 } else { | 272 } else { |
| 273 target_kind = FAST_ELEMENTS; | 273 target_kind = FAST_ELEMENTS; |
| 274 break; | 274 break; |
| 275 } | 275 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 314 |
| 315 BUILTIN(ArrayPush) { | 315 BUILTIN(ArrayPush) { |
| 316 HandleScope scope(isolate); | 316 HandleScope scope(isolate); |
| 317 Handle<Object> receiver = args.receiver(); | 317 Handle<Object> receiver = args.receiver(); |
| 318 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 318 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 319 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 319 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 320 Handle<FixedArrayBase> elms_obj; | 320 Handle<FixedArrayBase> elms_obj; |
| 321 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 321 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 322 return CallJsBuiltin(isolate, "$arrayPush", args); | 322 return CallJsBuiltin(isolate, "$arrayPush", args); |
| 323 } | 323 } |
| 324 | 324 // Fast Elements Path |
| 325 int push_size = args.length() - 1; |
| 325 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 326 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 326 int len = Smi::cast(array->length())->value(); | 327 int len = Smi::cast(array->length())->value(); |
| 327 int to_add = args.length() - 1; | 328 if (push_size == 0) { |
| 328 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { | 329 return Smi::FromInt(len); |
| 330 } |
| 331 if (push_size > 0 && |
| 332 JSArray::WouldChangeReadOnlyLength(array, len + push_size)) { |
| 329 return CallJsBuiltin(isolate, "$arrayPush", args); | 333 return CallJsBuiltin(isolate, "$arrayPush", args); |
| 330 } | 334 } |
| 331 DCHECK(!array->map()->is_observed()); | 335 DCHECK(!array->map()->is_observed()); |
| 332 | 336 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 333 ElementsKind kind = array->GetElementsKind(); | 337 int new_length = accessor->Push(array, elms_obj, &args[1], push_size, |
| 334 | 338 ElementsAccessor::kDirectionReverse); |
| 335 if (IsFastSmiOrObjectElementsKind(kind)) { | 339 return Smi::FromInt(new_length); |
| 336 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | |
| 337 if (to_add == 0) { | |
| 338 return Smi::FromInt(len); | |
| 339 } | |
| 340 // Currently fixed arrays cannot grow too big, so | |
| 341 // we should never hit this case. | |
| 342 DCHECK(to_add <= (Smi::kMaxValue - len)); | |
| 343 | |
| 344 int new_length = len + to_add; | |
| 345 | |
| 346 if (new_length > elms->length()) { | |
| 347 // New backing storage is needed. | |
| 348 int capacity = new_length + (new_length >> 1) + 16; | |
| 349 Handle<FixedArray> new_elms = | |
| 350 isolate->factory()->NewUninitializedFixedArray(capacity); | |
| 351 | |
| 352 ElementsAccessor* accessor = array->GetElementsAccessor(); | |
| 353 accessor->CopyElements( | |
| 354 elms_obj, 0, kind, new_elms, 0, | |
| 355 ElementsAccessor::kCopyToEndAndInitializeToHole); | |
| 356 | |
| 357 elms = new_elms; | |
| 358 } | |
| 359 | |
| 360 // Add the provided values. | |
| 361 DisallowHeapAllocation no_gc; | |
| 362 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | |
| 363 for (int index = 0; index < to_add; index++) { | |
| 364 elms->set(index + len, args[index + 1], mode); | |
| 365 } | |
| 366 | |
| 367 if (*elms != array->elements()) { | |
| 368 array->set_elements(*elms); | |
| 369 } | |
| 370 | |
| 371 // Set the length. | |
| 372 array->set_length(Smi::FromInt(new_length)); | |
| 373 return Smi::FromInt(new_length); | |
| 374 } else { | |
| 375 int elms_len = elms_obj->length(); | |
| 376 if (to_add == 0) { | |
| 377 return Smi::FromInt(len); | |
| 378 } | |
| 379 // Currently fixed arrays cannot grow too big, so | |
| 380 // we should never hit this case. | |
| 381 DCHECK(to_add <= (Smi::kMaxValue - len)); | |
| 382 | |
| 383 int new_length = len + to_add; | |
| 384 | |
| 385 Handle<FixedDoubleArray> new_elms; | |
| 386 | |
| 387 if (new_length > elms_len) { | |
| 388 // New backing storage is needed. | |
| 389 int capacity = new_length + (new_length >> 1) + 16; | |
| 390 // Create new backing store; since capacity > 0, we can | |
| 391 // safely cast to FixedDoubleArray. | |
| 392 new_elms = Handle<FixedDoubleArray>::cast( | |
| 393 isolate->factory()->NewFixedDoubleArray(capacity)); | |
| 394 | |
| 395 ElementsAccessor* accessor = array->GetElementsAccessor(); | |
| 396 accessor->CopyElements( | |
| 397 elms_obj, 0, kind, new_elms, 0, | |
| 398 ElementsAccessor::kCopyToEndAndInitializeToHole); | |
| 399 | |
| 400 } else { | |
| 401 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the | |
| 402 // empty_fixed_array. | |
| 403 new_elms = Handle<FixedDoubleArray>::cast(elms_obj); | |
| 404 } | |
| 405 | |
| 406 // Add the provided values. | |
| 407 DisallowHeapAllocation no_gc; | |
| 408 int index; | |
| 409 for (index = 0; index < to_add; index++) { | |
| 410 Object* arg = args[index + 1]; | |
| 411 new_elms->set(index + len, arg->Number()); | |
| 412 } | |
| 413 | |
| 414 if (*new_elms != array->elements()) { | |
| 415 array->set_elements(*new_elms); | |
| 416 } | |
| 417 | |
| 418 // Set the length. | |
| 419 array->set_length(Smi::FromInt(new_length)); | |
| 420 return Smi::FromInt(new_length); | |
| 421 } | |
| 422 } | 340 } |
| 423 | 341 |
| 424 | 342 |
| 425 BUILTIN(ArrayPop) { | 343 BUILTIN(ArrayPop) { |
| 426 HandleScope scope(isolate); | 344 HandleScope scope(isolate); |
| 427 Handle<Object> receiver = args.receiver(); | 345 Handle<Object> receiver = args.receiver(); |
| 428 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 346 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 429 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 347 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
| 430 Handle<FixedArrayBase> elms_obj; | 348 Handle<FixedArrayBase> elms_obj; |
| 431 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 349 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 | 414 |
| 497 // Set the length. | 415 // Set the length. |
| 498 array->set_length(Smi::FromInt(len - 1)); | 416 array->set_length(Smi::FromInt(len - 1)); |
| 499 | 417 |
| 500 return *first; | 418 return *first; |
| 501 } | 419 } |
| 502 | 420 |
| 503 | 421 |
| 504 BUILTIN(ArrayUnshift) { | 422 BUILTIN(ArrayUnshift) { |
| 505 HandleScope scope(isolate); | 423 HandleScope scope(isolate); |
| 506 Heap* heap = isolate->heap(); | |
| 507 Handle<Object> receiver = args.receiver(); | 424 Handle<Object> receiver = args.receiver(); |
| 508 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 425 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 509 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 426 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 510 Handle<FixedArrayBase> elms_obj; | 427 Handle<FixedArrayBase> elms_obj; |
| 511 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 428 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 512 return CallJsBuiltin(isolate, "$arrayUnshift", args); | 429 return CallJsBuiltin(isolate, "$arrayUnshift", args); |
| 513 } | 430 } |
| 514 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 431 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 515 DCHECK(!array->map()->is_observed()); | 432 DCHECK(!array->map()->is_observed()); |
| 516 if (!array->HasFastSmiOrObjectElements()) { | 433 if (!array->HasFastSmiOrObjectElements()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 538 ElementsKind kind = array->GetElementsKind(); | 455 ElementsKind kind = array->GetElementsKind(); |
| 539 ElementsAccessor* accessor = array->GetElementsAccessor(); | 456 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 540 accessor->CopyElements( | 457 accessor->CopyElements( |
| 541 elms, 0, kind, new_elms, to_add, | 458 elms, 0, kind, new_elms, to_add, |
| 542 ElementsAccessor::kCopyToEndAndInitializeToHole); | 459 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 543 | 460 |
| 544 elms = new_elms; | 461 elms = new_elms; |
| 545 array->set_elements(*elms); | 462 array->set_elements(*elms); |
| 546 } else { | 463 } else { |
| 547 DisallowHeapAllocation no_gc; | 464 DisallowHeapAllocation no_gc; |
| 465 Heap* heap = isolate->heap(); |
| 548 heap->MoveElements(*elms, to_add, 0, len); | 466 heap->MoveElements(*elms, to_add, 0, len); |
| 549 } | 467 } |
| 550 | 468 |
| 551 // Add the provided values. | 469 // Add the provided values. |
| 552 DisallowHeapAllocation no_gc; | 470 DisallowHeapAllocation no_gc; |
| 553 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 471 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 554 for (int i = 0; i < to_add; i++) { | 472 for (int i = 0; i < to_add; i++) { |
| 555 elms->set(i, args[i + 1], mode); | 473 elms->set(i, args[i + 1], mode); |
| 556 } | 474 } |
| 557 | 475 |
| (...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1617 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1535 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1618 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1536 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1619 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1537 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1620 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1538 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1621 #undef DEFINE_BUILTIN_ACCESSOR_C | 1539 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1622 #undef DEFINE_BUILTIN_ACCESSOR_A | 1540 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1623 | 1541 |
| 1624 | 1542 |
| 1625 } // namespace internal | 1543 } // namespace internal |
| 1626 } // namespace v8 | 1544 } // namespace v8 |
| OLD | NEW |