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 |