Chromium Code Reviews| 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 #ifdef DEBUG | 78 #ifdef DEBUG |
| 79 template <> | 79 template <> |
| 80 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() { | 80 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() { |
| 81 // Check we have at least the receiver and the called function. | 81 // Check we have at least the receiver and the called function. |
| 82 DCHECK(Arguments::length() >= 2); | 82 DCHECK(Arguments::length() >= 2); |
| 83 // Make sure cast to JSFunction succeeds. | 83 // Make sure cast to JSFunction succeeds. |
| 84 called_function(); | 84 called_function(); |
| 85 } | 85 } |
| 86 #endif | 86 #endif |
| 87 | 87 |
| 88 | |
| 89 #define DEF_ARG_TYPE(name, spec) \ | 88 #define DEF_ARG_TYPE(name, spec) \ |
| 90 typedef BuiltinArguments<spec> name##ArgumentsType; | 89 typedef BuiltinArguments<spec> name##ArgumentsType; |
| 91 BUILTIN_LIST_C(DEF_ARG_TYPE) | 90 BUILTIN_LIST_C(DEF_ARG_TYPE) |
| 92 #undef DEF_ARG_TYPE | 91 #undef DEF_ARG_TYPE |
| 93 | 92 |
| 94 } // namespace | 93 } // namespace |
| 95 | 94 |
| 96 // ---------------------------------------------------------------------------- | 95 // ---------------------------------------------------------------------------- |
| 97 // Support macro for defining builtins in C++. | 96 // Support macro for defining builtins in C++. |
| 98 // ---------------------------------------------------------------------------- | 97 // ---------------------------------------------------------------------------- |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 | 313 |
| 315 BUILTIN(ArrayPush) { | 314 BUILTIN(ArrayPush) { |
| 316 HandleScope scope(isolate); | 315 HandleScope scope(isolate); |
| 317 Handle<Object> receiver = args.receiver(); | 316 Handle<Object> receiver = args.receiver(); |
| 318 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 317 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 319 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 318 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 320 Handle<FixedArrayBase> elms_obj; | 319 Handle<FixedArrayBase> elms_obj; |
| 321 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 320 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 322 return CallJsBuiltin(isolate, "$arrayPush", args); | 321 return CallJsBuiltin(isolate, "$arrayPush", args); |
| 323 } | 322 } |
| 324 | |
| 325 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 323 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 326 int len = Smi::cast(array->length())->value(); | 324 int len = Smi::cast(array->length())->value(); |
| 327 int to_add = args.length() - 1; | 325 int to_add = args.length() - 1; |
| 328 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { | 326 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) { |
| 329 return CallJsBuiltin(isolate, "$arrayPush", args); | 327 return CallJsBuiltin(isolate, "$arrayPush", args); |
| 330 } | 328 } |
| 331 DCHECK(!array->map()->is_observed()); | 329 DCHECK(!array->map()->is_observed()); |
| 332 | 330 |
| 333 ElementsKind kind = array->GetElementsKind(); | 331 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 334 | 332 int new_length = accessor->Push(array, elms_obj, &args[0], 1, to_add, |
|
Jakob Kummerow
2015/07/30 11:54:59
If you pass in &args[1] here, you don't need the |
| |
| 335 if (IsFastSmiOrObjectElementsKind(kind)) { | 333 ElementsAccessor::kDirectionReverse); |
| 336 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj); | 334 return Smi::FromInt(new_length); |
| 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 } | 335 } |
| 423 | 336 |
| 424 | 337 |
| 425 BUILTIN(ArrayPop) { | 338 BUILTIN(ArrayPop) { |
| 426 HandleScope scope(isolate); | 339 HandleScope scope(isolate); |
| 427 Handle<Object> receiver = args.receiver(); | 340 Handle<Object> receiver = args.receiver(); |
| 428 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 341 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 429 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); | 342 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0); |
| 430 Handle<FixedArrayBase> elms_obj; | 343 Handle<FixedArrayBase> elms_obj; |
| 431 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 344 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 | 409 |
| 497 // Set the length. | 410 // Set the length. |
| 498 array->set_length(Smi::FromInt(len - 1)); | 411 array->set_length(Smi::FromInt(len - 1)); |
| 499 | 412 |
| 500 return *first; | 413 return *first; |
| 501 } | 414 } |
| 502 | 415 |
| 503 | 416 |
| 504 BUILTIN(ArrayUnshift) { | 417 BUILTIN(ArrayUnshift) { |
| 505 HandleScope scope(isolate); | 418 HandleScope scope(isolate); |
| 506 Heap* heap = isolate->heap(); | |
| 507 Handle<Object> receiver = args.receiver(); | 419 Handle<Object> receiver = args.receiver(); |
| 508 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 420 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
| 509 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); | 421 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1); |
| 510 Handle<FixedArrayBase> elms_obj; | 422 Handle<FixedArrayBase> elms_obj; |
| 511 if (!maybe_elms_obj.ToHandle(&elms_obj)) { | 423 if (!maybe_elms_obj.ToHandle(&elms_obj)) { |
| 512 return CallJsBuiltin(isolate, "$arrayUnshift", args); | 424 return CallJsBuiltin(isolate, "$arrayUnshift", args); |
| 513 } | 425 } |
| 514 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 426 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
| 515 DCHECK(!array->map()->is_observed()); | 427 DCHECK(!array->map()->is_observed()); |
| 516 if (!array->HasFastSmiOrObjectElements()) { | 428 if (!array->HasFastSmiOrObjectElements()) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 538 ElementsKind kind = array->GetElementsKind(); | 450 ElementsKind kind = array->GetElementsKind(); |
| 539 ElementsAccessor* accessor = array->GetElementsAccessor(); | 451 ElementsAccessor* accessor = array->GetElementsAccessor(); |
| 540 accessor->CopyElements( | 452 accessor->CopyElements( |
| 541 elms, 0, kind, new_elms, to_add, | 453 elms, 0, kind, new_elms, to_add, |
| 542 ElementsAccessor::kCopyToEndAndInitializeToHole); | 454 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 543 | 455 |
| 544 elms = new_elms; | 456 elms = new_elms; |
| 545 array->set_elements(*elms); | 457 array->set_elements(*elms); |
| 546 } else { | 458 } else { |
| 547 DisallowHeapAllocation no_gc; | 459 DisallowHeapAllocation no_gc; |
| 460 Heap* heap = isolate->heap(); | |
| 548 heap->MoveElements(*elms, to_add, 0, len); | 461 heap->MoveElements(*elms, to_add, 0, len); |
| 549 } | 462 } |
| 550 | 463 |
| 551 // Add the provided values. | 464 // Add the provided values. |
| 552 DisallowHeapAllocation no_gc; | 465 DisallowHeapAllocation no_gc; |
| 553 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 466 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 554 for (int i = 0; i < to_add; i++) { | 467 for (int i = 0; i < to_add; i++) { |
| 555 elms->set(i, args[i + 1], mode); | 468 elms->set(i, args[i + 1], mode); |
| 556 } | 469 } |
| 557 | 470 |
| (...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1617 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1530 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1618 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1531 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1619 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1532 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1620 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1533 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1621 #undef DEFINE_BUILTIN_ACCESSOR_C | 1534 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1622 #undef DEFINE_BUILTIN_ACCESSOR_A | 1535 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1623 | 1536 |
| 1624 | 1537 |
| 1625 } // namespace internal | 1538 } // namespace internal |
| 1626 } // namespace v8 | 1539 } // namespace v8 |
| OLD | NEW |