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

Side by Side Diff: src/d8.cc

Issue 10694051: Implement typedarray.set and arraybuffer.slice for d8. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Handle overlapping for differing element sizes correctly. Created 8 years, 5 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/d8.h ('k') | test/mjsunit/external-array.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 ASSERT(kMaxLength == i::ExternalArray::kMaxLength); 317 ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
318 #endif // V8_SHARED 318 #endif // V8_SHARED
319 if (raw_value > static_cast<int32_t>(kMaxLength)) { 319 if (raw_value > static_cast<int32_t>(kMaxLength)) {
320 ThrowException( 320 ThrowException(
321 String::New("Array length exceeds maximum length.")); 321 String::New("Array length exceeds maximum length."));
322 } 322 }
323 return raw_value; 323 return raw_value;
324 } 324 }
325 325
326 326
327 // TODO(rossberg): should replace these by proper uses of HasInstance,
328 // once we figure out a good way to make the templates global.
327 const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_"; 329 const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_";
328 const char kArrayMarkerPropName[] = "d8::_is_typed_array_"; 330 const char kArrayMarkerPropName[] = "d8::_is_typed_array_";
329 331
330 332
331 Handle<Value> Shell::CreateExternalArrayBuffer(Handle<Object> buffer, 333 Handle<Value> Shell::CreateExternalArrayBuffer(Handle<Object> buffer,
332 int32_t length) { 334 int32_t length) {
333 static const int32_t kMaxSize = 0x7fffffff; 335 static const int32_t kMaxSize = 0x7fffffff;
334 // Make sure the total size fits into a (signed) int. 336 // Make sure the total size fits into a (signed) int.
335 if (length < 0 || length > kMaxSize) { 337 if (length < 0 || length > kMaxSize) {
336 return ThrowException(String::New("ArrayBuffer exceeds maximum size (2G)")); 338 return ThrowException(String::New("ArrayBuffer exceeds maximum size (2G)"));
337 } 339 }
338 uint8_t* data = new uint8_t[length]; 340 uint8_t* data = new uint8_t[length];
339 if (data == NULL) { 341 if (data == NULL) {
340 return ThrowException(String::New("Memory allocation failed.")); 342 return ThrowException(String::New("Memory allocation failed"));
341 } 343 }
342 memset(data, 0, length); 344 memset(data, 0, length);
343 345
344 buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); 346 buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True());
345 Persistent<Object> persistent_array = Persistent<Object>::New(buffer); 347 Persistent<Object> persistent_array = Persistent<Object>::New(buffer);
346 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); 348 persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
347 persistent_array.MarkIndependent(); 349 persistent_array.MarkIndependent();
348 V8::AdjustAmountOfExternalAllocatedMemory(length); 350 V8::AdjustAmountOfExternalAllocatedMemory(length);
349 351
350 buffer->SetIndexedPropertiesToExternalArrayData( 352 buffer->SetIndexedPropertiesToExternalArrayData(
351 data, v8::kExternalByteArray, length); 353 data, v8::kExternalByteArray, length);
352 buffer->Set(String::New("byteLength"), Int32::New(length), ReadOnly); 354 buffer->Set(String::New("byteLength"), Int32::New(length), ReadOnly);
353 355
354 return buffer; 356 return buffer;
355 } 357 }
356 358
357 359
358 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { 360 Handle<Value> Shell::ArrayBuffer(const Arguments& args) {
359 if (!args.IsConstructCall()) { 361 if (!args.IsConstructCall()) {
360 Handle<Value>* rec_args = new Handle<Value>[args.Length()]; 362 Handle<Value>* rec_args = new Handle<Value>[args.Length()];
361 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; 363 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i];
362 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args); 364 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args);
363 delete[] rec_args; 365 delete[] rec_args;
364 return result; 366 return result;
365 } 367 }
366 368
367 if (args.Length() == 0) { 369 if (args.Length() == 0) {
368 return ThrowException( 370 return ThrowException(
369 String::New("ArrayBuffer constructor must have one parameter.")); 371 String::New("ArrayBuffer constructor must have one argument"));
370 } 372 }
371 TryCatch try_catch; 373 TryCatch try_catch;
372 int32_t length = convertToUint(args[0], &try_catch); 374 int32_t length = convertToUint(args[0], &try_catch);
373 if (try_catch.HasCaught()) return try_catch.Exception(); 375 if (try_catch.HasCaught()) return try_catch.ReThrow();
374 376
375 return CreateExternalArrayBuffer(args.This(), length); 377 return CreateExternalArrayBuffer(args.This(), length);
376 } 378 }
377 379
378 380
379 Handle<Object> Shell::CreateExternalArray(Handle<Object> array, 381 Handle<Object> Shell::CreateExternalArray(Handle<Object> array,
380 Handle<Object> buffer, 382 Handle<Object> buffer,
381 ExternalArrayType type, 383 ExternalArrayType type,
382 int32_t length, 384 int32_t length,
383 int32_t byteLength, 385 int32_t byteLength,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 // TypedArray(ArrayBuffer buffer, 427 // TypedArray(ArrayBuffer buffer,
426 // optional unsigned long byteOffset, 428 // optional unsigned long byteOffset,
427 // optional unsigned long length) 429 // optional unsigned long length)
428 Handle<Object> buffer; 430 Handle<Object> buffer;
429 int32_t length; 431 int32_t length;
430 int32_t byteLength; 432 int32_t byteLength;
431 int32_t byteOffset; 433 int32_t byteOffset;
432 bool init_from_array = false; 434 bool init_from_array = false;
433 if (args.Length() == 0) { 435 if (args.Length() == 0) {
434 return ThrowException( 436 return ThrowException(
435 String::New("Array constructor must have at least one parameter.")); 437 String::New("Array constructor must have at least one argument"));
436 } 438 }
437 if (args[0]->IsObject() && 439 if (args[0]->IsObject() &&
438 !args[0]->ToObject()->GetHiddenValue( 440 !args[0]->ToObject()->GetHiddenValue(
439 String::New(kArrayBufferMarkerPropName)).IsEmpty()) { 441 String::New(kArrayBufferMarkerPropName)).IsEmpty()) {
440 // Construct from ArrayBuffer. 442 // Construct from ArrayBuffer.
441 buffer = args[0]->ToObject(); 443 buffer = args[0]->ToObject();
442 int32_t bufferLength = 444 int32_t bufferLength =
443 convertToUint(buffer->Get(String::New("byteLength")), &try_catch); 445 convertToUint(buffer->Get(String::New("byteLength")), &try_catch);
444 if (try_catch.HasCaught()) return try_catch.Exception(); 446 if (try_catch.HasCaught()) return try_catch.ReThrow();
445 447
446 if (args.Length() < 2 || args[1]->IsUndefined()) { 448 if (args.Length() < 2 || args[1]->IsUndefined()) {
447 byteOffset = 0; 449 byteOffset = 0;
448 } else { 450 } else {
449 byteOffset = convertToUint(args[1], &try_catch); 451 byteOffset = convertToUint(args[1], &try_catch);
450 if (try_catch.HasCaught()) return try_catch.Exception(); 452 if (try_catch.HasCaught()) return try_catch.ReThrow();
451 if (byteOffset > bufferLength) { 453 if (byteOffset > bufferLength) {
452 return ThrowException(String::New("byteOffset out of bounds")); 454 return ThrowException(String::New("byteOffset out of bounds"));
453 } 455 }
454 if (byteOffset % element_size != 0) { 456 if (byteOffset % element_size != 0) {
455 return ThrowException( 457 return ThrowException(
456 String::New("byteOffset must be multiple of element_size")); 458 String::New("byteOffset must be multiple of element size"));
457 } 459 }
458 } 460 }
459 461
460 if (args.Length() < 3 || args[2]->IsUndefined()) { 462 if (args.Length() < 3 || args[2]->IsUndefined()) {
461 byteLength = bufferLength - byteOffset; 463 byteLength = bufferLength - byteOffset;
462 length = byteLength / element_size; 464 length = byteLength / element_size;
463 if (byteLength % element_size != 0) { 465 if (byteLength % element_size != 0) {
464 return ThrowException( 466 return ThrowException(
465 String::New("buffer size must be multiple of element_size")); 467 String::New("buffer size must be multiple of element size"));
466 } 468 }
467 } else { 469 } else {
468 length = convertToUint(args[2], &try_catch); 470 length = convertToUint(args[2], &try_catch);
469 if (try_catch.HasCaught()) return try_catch.Exception(); 471 if (try_catch.HasCaught()) return try_catch.ReThrow();
470 byteLength = length * element_size; 472 byteLength = length * element_size;
471 if (byteOffset + byteLength > bufferLength) { 473 if (byteOffset + byteLength > bufferLength) {
472 return ThrowException(String::New("length out of bounds")); 474 return ThrowException(String::New("length out of bounds"));
473 } 475 }
474 } 476 }
475 } else { 477 } else {
476 if (args[0]->IsObject() && 478 if (args[0]->IsObject() &&
477 args[0]->ToObject()->Has(String::New("length"))) { 479 args[0]->ToObject()->Has(String::New("length"))) {
478 // Construct from array. 480 // Construct from array.
479 length = convertToUint( 481 length = convertToUint(
480 args[0]->ToObject()->Get(String::New("length")), &try_catch); 482 args[0]->ToObject()->Get(String::New("length")), &try_catch);
481 if (try_catch.HasCaught()) return try_catch.Exception(); 483 if (try_catch.HasCaught()) return try_catch.ReThrow();
482 init_from_array = true; 484 init_from_array = true;
483 } else { 485 } else {
484 // Construct from size. 486 // Construct from size.
485 length = convertToUint(args[0], &try_catch); 487 length = convertToUint(args[0], &try_catch);
486 if (try_catch.HasCaught()) return try_catch.Exception(); 488 if (try_catch.HasCaught()) return try_catch.ReThrow();
487 } 489 }
488 byteLength = length * element_size; 490 byteLength = length * element_size;
489 byteOffset = 0; 491 byteOffset = 0;
490 492
491 Handle<Object> global = Context::GetCurrent()->Global(); 493 Handle<Object> global = Context::GetCurrent()->Global();
492 Handle<Value> array_buffer = global->Get(String::New("ArrayBuffer")); 494 Handle<Value> array_buffer = global->Get(String::New("ArrayBuffer"));
493 ASSERT(!try_catch.HasCaught() && array_buffer->IsFunction()); 495 ASSERT(!try_catch.HasCaught() && array_buffer->IsFunction());
494 Handle<Value> buffer_args[] = { Uint32::New(byteLength) }; 496 Handle<Value> buffer_args[] = { Uint32::New(byteLength) };
495 Handle<Value> result = Handle<Function>::Cast(array_buffer)->NewInstance( 497 Handle<Value> result = Handle<Function>::Cast(array_buffer)->NewInstance(
496 1, buffer_args); 498 1, buffer_args);
497 if (try_catch.HasCaught()) return result; 499 if (try_catch.HasCaught()) return result;
498 buffer = result->ToObject(); 500 buffer = result->ToObject();
499 } 501 }
500 502
501 Handle<Object> array = CreateExternalArray( 503 Handle<Object> array = CreateExternalArray(
502 args.This(), buffer, type, length, byteLength, byteOffset, element_size); 504 args.This(), buffer, type, length, byteLength, byteOffset, element_size);
503 505
504 if (init_from_array) { 506 if (init_from_array) {
505 Handle<Object> init = args[0]->ToObject(); 507 Handle<Object> init = args[0]->ToObject();
506 for (int i = 0; i < length; ++i) array->Set(i, init->Get(i)); 508 for (int i = 0; i < length; ++i) array->Set(i, init->Get(i));
507 } 509 }
508 510
509 return array; 511 return array;
510 } 512 }
511 513
512 514
513 Handle<Value> Shell::SubArray(const Arguments& args) { 515 Handle<Value> Shell::ArrayBufferSlice(const Arguments& args) {
514 TryCatch try_catch; 516 TryCatch try_catch;
515 517
516 if (!args.This()->IsObject()) { 518 if (!args.This()->IsObject()) {
517 return ThrowException( 519 return ThrowException(
518 String::New("subarray invoked on non-object receiver.")); 520 String::New("'slice' invoked on non-object receiver"));
521 }
522
523 Local<Object> self = args.This();
524 Local<Value> marker =
525 self->GetHiddenValue(String::New(kArrayBufferMarkerPropName));
526 if (marker.IsEmpty()) {
527 return ThrowException(
528 String::New("'slice' invoked on wrong receiver type"));
529 }
530
531 int32_t length =
532 convertToUint(self->Get(String::New("byteLength")), &try_catch);
533 if (try_catch.HasCaught()) return try_catch.ReThrow();
534
535 if (args.Length() == 0) {
536 return ThrowException(
537 String::New("'slice' must have at least one argument"));
538 }
539 int32_t begin = convertToInt(args[0], &try_catch);
540 if (try_catch.HasCaught()) return try_catch.ReThrow();
541 if (begin < 0) begin += length;
542 if (begin < 0) begin = 0;
543 if (begin > length) begin = length;
544
545 int32_t end;
546 if (args.Length() < 2 || args[1]->IsUndefined()) {
547 end = length;
548 } else {
549 end = convertToInt(args[1], &try_catch);
550 if (try_catch.HasCaught()) return try_catch.ReThrow();
551 if (end < 0) end += length;
552 if (end < 0) end = 0;
553 if (end > length) end = length;
554 if (end < begin) end = begin;
555 }
556
557 Local<Function> constructor = Local<Function>::Cast(self->GetConstructor());
558 Handle<Value> new_args[] = { Uint32::New(end - begin) };
559 Handle<Value> result = constructor->NewInstance(1, new_args);
560 if (try_catch.HasCaught()) return result;
561 Handle<Object> buffer = result->ToObject();
562 uint8_t* dest =
563 static_cast<uint8_t*>(buffer->GetIndexedPropertiesExternalArrayData());
564 uint8_t* src = begin + static_cast<uint8_t*>(
565 self->GetIndexedPropertiesExternalArrayData());
566 memcpy(dest, src, end - begin);
567
568 return buffer;
569 }
570
571
572 Handle<Value> Shell::ArraySubArray(const Arguments& args) {
573 TryCatch try_catch;
574
575 if (!args.This()->IsObject()) {
576 return ThrowException(
577 String::New("'subarray' invoked on non-object receiver"));
519 } 578 }
520 579
521 Local<Object> self = args.This(); 580 Local<Object> self = args.This();
522 Local<Value> marker = self->GetHiddenValue(String::New(kArrayMarkerPropName)); 581 Local<Value> marker = self->GetHiddenValue(String::New(kArrayMarkerPropName));
523 if (marker.IsEmpty()) { 582 if (marker.IsEmpty()) {
524 return ThrowException( 583 return ThrowException(
525 String::New("subarray invoked on wrong receiver type.")); 584 String::New("'subarray' invoked on wrong receiver type"));
526 } 585 }
527 586
528 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject(); 587 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject();
529 if (try_catch.HasCaught()) return try_catch.Exception(); 588 if (try_catch.HasCaught()) return try_catch.ReThrow();
530 int32_t length = 589 int32_t length =
531 convertToUint(self->Get(String::New("length")), &try_catch); 590 convertToUint(self->Get(String::New("length")), &try_catch);
532 if (try_catch.HasCaught()) return try_catch.Exception(); 591 if (try_catch.HasCaught()) return try_catch.ReThrow();
533 int32_t byteOffset = 592 int32_t byteOffset =
534 convertToUint(self->Get(String::New("byteOffset")), &try_catch); 593 convertToUint(self->Get(String::New("byteOffset")), &try_catch);
535 if (try_catch.HasCaught()) return try_catch.Exception(); 594 if (try_catch.HasCaught()) return try_catch.ReThrow();
536 int32_t element_size = 595 int32_t element_size =
537 convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); 596 convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch);
538 if (try_catch.HasCaught()) return try_catch.Exception(); 597 if (try_catch.HasCaught()) return try_catch.ReThrow();
539 598
540 if (args.Length() == 0) { 599 if (args.Length() == 0) {
541 return ThrowException( 600 return ThrowException(
542 String::New("subarray must have at least one parameter.")); 601 String::New("'subarray' must have at least one argument"));
543 } 602 }
544 int32_t begin = convertToInt(args[0], &try_catch); 603 int32_t begin = convertToInt(args[0], &try_catch);
545 if (try_catch.HasCaught()) return try_catch.Exception(); 604 if (try_catch.HasCaught()) return try_catch.ReThrow();
546 if (begin < 0) begin += length; 605 if (begin < 0) begin += length;
547 if (begin < 0) begin = 0; 606 if (begin < 0) begin = 0;
548 if (begin > length) begin = length; 607 if (begin > length) begin = length;
549 608
550 int32_t end; 609 int32_t end;
551 if (args.Length() < 2 || args[1]->IsUndefined()) { 610 if (args.Length() < 2 || args[1]->IsUndefined()) {
552 end = length; 611 end = length;
553 } else { 612 } else {
554 end = convertToInt(args[1], &try_catch); 613 end = convertToInt(args[1], &try_catch);
555 if (try_catch.HasCaught()) return try_catch.Exception(); 614 if (try_catch.HasCaught()) return try_catch.ReThrow();
556 if (end < 0) end += length; 615 if (end < 0) end += length;
557 if (end < 0) end = 0; 616 if (end < 0) end = 0;
558 if (end > length) end = length; 617 if (end > length) end = length;
559 if (end < begin) end = begin; 618 if (end < begin) end = begin;
560 } 619 }
561 620
562 length = end - begin; 621 length = end - begin;
563 byteOffset += begin * element_size; 622 byteOffset += begin * element_size;
564 623
565 Local<Function> constructor = Local<Function>::Cast(self->GetConstructor()); 624 Local<Function> constructor = Local<Function>::Cast(self->GetConstructor());
566 Handle<Value> construct_args[] = { 625 Handle<Value> construct_args[] = {
567 buffer, Uint32::New(byteOffset), Uint32::New(length) 626 buffer, Uint32::New(byteOffset), Uint32::New(length)
568 }; 627 };
569 return constructor->NewInstance(3, construct_args); 628 return constructor->NewInstance(3, construct_args);
570 } 629 }
571 630
572 631
632 Handle<Value> Shell::ArraySet(const Arguments& args) {
633 TryCatch try_catch;
634
635 if (!args.This()->IsObject()) {
636 return ThrowException(
637 String::New("'set' invoked on non-object receiver"));
638 }
639
640 Local<Object> self = args.This();
641 Local<Value> marker = self->GetHiddenValue(String::New(kArrayMarkerPropName));
642 if (marker.IsEmpty()) {
643 return ThrowException(
644 String::New("'set' invoked on wrong receiver type"));
645 }
646 int32_t length =
647 convertToUint(self->Get(String::New("length")), &try_catch);
648 if (try_catch.HasCaught()) return try_catch.ReThrow();
649 int32_t element_size =
650 convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch);
651 if (try_catch.HasCaught()) return try_catch.ReThrow();
652
653 if (args.Length() == 0) {
654 return ThrowException(
655 String::New("'set' must have at least one argument"));
656 }
657 if (!args[0]->IsObject() ||
658 !args[0]->ToObject()->Has(String::New("length"))) {
659 return ThrowException(
660 String::New("'set' invoked with non-array argument"));
661 }
662 Handle<Object> source = args[0]->ToObject();
663 int32_t source_length =
664 convertToUint(source->Get(String::New("length")), &try_catch);
665 if (try_catch.HasCaught()) return try_catch.ReThrow();
666
667 int32_t offset;
668 if (args.Length() < 2 || args[1]->IsUndefined()) {
669 offset = 0;
670 } else {
671 offset = convertToUint(args[1], &try_catch);
672 if (try_catch.HasCaught()) return try_catch.ReThrow();
673 }
674 if (offset + source_length > length) {
675 return ThrowException(String::New("offset or source length out of bounds"));
676 }
677
678 int32_t source_element_size;
679 if (source->GetHiddenValue(String::New(kArrayMarkerPropName)).IsEmpty()) {
680 source_element_size = 0;
681 } else {
682 source_element_size =
683 convertToUint(source->Get(String::New("BYTES_PER_ELEMENT")), &try_catch);
684 if (try_catch.HasCaught()) return try_catch.ReThrow();
685 }
686
687 if (element_size == source_element_size &&
688 self->GetConstructor()->StrictEquals(source->GetConstructor())) {
689 // Use memmove on the array buffers.
690 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject();
691 if (try_catch.HasCaught()) return try_catch.ReThrow();
692 Handle<Object> source_buffer =
693 source->Get(String::New("buffer"))->ToObject();
694 if (try_catch.HasCaught()) return try_catch.ReThrow();
695 int32_t byteOffset =
696 convertToUint(self->Get(String::New("byteOffset")), &try_catch);
697 if (try_catch.HasCaught()) return try_catch.ReThrow();
698 int32_t source_byteOffset =
699 convertToUint(source->Get(String::New("byteOffset")), &try_catch);
700 if (try_catch.HasCaught()) return try_catch.ReThrow();
701
702 uint8_t* dest = byteOffset + offset * element_size + static_cast<uint8_t*>(
703 buffer->GetIndexedPropertiesExternalArrayData());
704 uint8_t* src = source_byteOffset + static_cast<uint8_t*>(
705 source_buffer->GetIndexedPropertiesExternalArrayData());
706 memmove(dest, src, source_length * element_size);
707 } else if (source_element_size == 0) {
708 // Source is not a typed array, copy element-wise sequentially.
709 for (int i = 0; i < source_length; ++i) {
710 self->Set(offset + i, source->Get(i));
711 if (try_catch.HasCaught()) return try_catch.ReThrow();
712 }
713 } else {
714 // Need to copy element-wise to make the right conversions.
715 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject();
716 if (try_catch.HasCaught()) return try_catch.ReThrow();
717 Handle<Object> source_buffer =
718 source->Get(String::New("buffer"))->ToObject();
719 if (try_catch.HasCaught()) return try_catch.ReThrow();
720
721 if (buffer->StrictEquals(source_buffer)) {
722 // Same backing store, need to handle overlap correctly.
723 // This gets a bit tricky in the case of different element sizes
724 // (which, of course, is extremely unlikely to ever occur in practice).
725 int32_t byteOffset =
726 convertToUint(self->Get(String::New("byteOffset")), &try_catch);
727 if (try_catch.HasCaught()) return try_catch.ReThrow();
728 int32_t source_byteOffset =
729 convertToUint(source->Get(String::New("byteOffset")), &try_catch);
730 if (try_catch.HasCaught()) return try_catch.ReThrow();
731
732 // Copy as much as we can from left to right.
733 int i = 0;
734 int32_t next_dest_offset = byteOffset + (offset + 1) * element_size;
735 int32_t next_src_offset = source_byteOffset + source_element_size;
736 while (i < length && next_dest_offset <= next_src_offset) {
737 self->Set(offset + i, source->Get(i));
738 ++i;
739 next_dest_offset += element_size;
740 next_src_offset += source_element_size;
741 }
742 // Of what's left, copy as much as we can from right to left.
743 int j = length - 1;
744 int32_t dest_offset = byteOffset + (offset + j) * element_size;
745 int32_t src_offset = source_byteOffset + j * source_element_size;
746 while (j >= i && dest_offset >= src_offset) {
747 self->Set(offset + j, source->Get(j));
748 --j;
749 dest_offset -= element_size;
750 src_offset -= source_element_size;
751 }
752 // There can be at most 8 entries left in the middle that need buffering
753 // (because the largest element_size is 8 times the smallest).
754 ASSERT(j+1 - i <= 8);
755 Handle<Value> temp[8];
756 for (int k = i; k <= j; ++k) {
757 temp[k - i] = source->Get(k);
758 }
759 for (int k = i; k <= j; ++k) {
760 self->Set(offset + k, temp[k - i]);
761 }
762 } else {
763 // Different backing stores, safe to copy element-wise sequentially.
764 for (int i = 0; i < source_length; ++i)
765 self->Set(offset + i, source->Get(i));
766 }
767 }
768
769 return Undefined();
770 }
771
772
573 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { 773 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) {
574 HandleScope scope; 774 HandleScope scope;
575 int32_t length = 775 int32_t length =
576 object->ToObject()->Get(String::New("byteLength"))->Uint32Value(); 776 object->ToObject()->Get(String::New("byteLength"))->Uint32Value();
577 V8::AdjustAmountOfExternalAllocatedMemory(-length); 777 V8::AdjustAmountOfExternalAllocatedMemory(-length);
578 delete[] static_cast<uint8_t*>(data); 778 delete[] static_cast<uint8_t*>(data);
579 object.Dispose(); 779 object.Dispose();
580 } 780 }
581 781
582 782
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 0, 1); 1112 0, 1);
913 if (result == BZ_OK) { 1113 if (result == BZ_OK) {
914 *raw_data_size = decompressed_size; 1114 *raw_data_size = decompressed_size;
915 } 1115 }
916 return result; 1116 return result;
917 } 1117 }
918 }; 1118 };
919 #endif 1119 #endif
920 1120
921 1121
1122 Handle<FunctionTemplate> Shell::CreateArrayBufferTemplate(
1123 InvocationCallback fun) {
1124 Handle<FunctionTemplate> buffer_template = FunctionTemplate::New(fun);
1125 Local<Template> proto_template = buffer_template->PrototypeTemplate();
1126 proto_template->Set(String::New("slice"),
1127 FunctionTemplate::New(ArrayBufferSlice));
1128 return buffer_template;
1129 }
1130
1131
922 Handle<FunctionTemplate> Shell::CreateArrayTemplate(InvocationCallback fun) { 1132 Handle<FunctionTemplate> Shell::CreateArrayTemplate(InvocationCallback fun) {
923 Handle<FunctionTemplate> array_template = FunctionTemplate::New(fun); 1133 Handle<FunctionTemplate> array_template = FunctionTemplate::New(fun);
924 Local<Template> proto_template = array_template->PrototypeTemplate(); 1134 Local<Template> proto_template = array_template->PrototypeTemplate();
925 proto_template->Set(String::New("subarray"), FunctionTemplate::New(SubArray)); 1135 proto_template->Set(String::New("set"), FunctionTemplate::New(ArraySet));
1136 proto_template->Set(String::New("subarray"),
1137 FunctionTemplate::New(ArraySubArray));
926 return array_template; 1138 return array_template;
927 } 1139 }
928 1140
929 1141
930 Handle<ObjectTemplate> Shell::CreateGlobalTemplate() { 1142 Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
931 Handle<ObjectTemplate> global_template = ObjectTemplate::New(); 1143 Handle<ObjectTemplate> global_template = ObjectTemplate::New();
932 global_template->Set(String::New("print"), FunctionTemplate::New(Print)); 1144 global_template->Set(String::New("print"), FunctionTemplate::New(Print));
933 global_template->Set(String::New("write"), FunctionTemplate::New(Write)); 1145 global_template->Set(String::New("write"), FunctionTemplate::New(Write));
934 global_template->Set(String::New("read"), FunctionTemplate::New(Read)); 1146 global_template->Set(String::New("read"), FunctionTemplate::New(Read));
935 global_template->Set(String::New("readbuffer"), 1147 global_template->Set(String::New("readbuffer"),
936 FunctionTemplate::New(ReadBuffer)); 1148 FunctionTemplate::New(ReadBuffer));
937 global_template->Set(String::New("readline"), 1149 global_template->Set(String::New("readline"),
938 FunctionTemplate::New(ReadLine)); 1150 FunctionTemplate::New(ReadLine));
939 global_template->Set(String::New("load"), FunctionTemplate::New(Load)); 1151 global_template->Set(String::New("load"), FunctionTemplate::New(Load));
940 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit)); 1152 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
941 global_template->Set(String::New("version"), FunctionTemplate::New(Version)); 1153 global_template->Set(String::New("version"), FunctionTemplate::New(Version));
942 global_template->Set(String::New("enableProfiler"), 1154 global_template->Set(String::New("enableProfiler"),
943 FunctionTemplate::New(EnableProfiler)); 1155 FunctionTemplate::New(EnableProfiler));
944 global_template->Set(String::New("disableProfiler"), 1156 global_template->Set(String::New("disableProfiler"),
945 FunctionTemplate::New(DisableProfiler)); 1157 FunctionTemplate::New(DisableProfiler));
946 1158
947 // Bind the handlers for external arrays. 1159 // Bind the handlers for external arrays.
948 PropertyAttribute attr = 1160 PropertyAttribute attr =
949 static_cast<PropertyAttribute>(ReadOnly | DontDelete); 1161 static_cast<PropertyAttribute>(ReadOnly | DontDelete);
950 global_template->Set(String::New("ArrayBuffer"), 1162 global_template->Set(String::New("ArrayBuffer"),
951 CreateArrayTemplate(ArrayBuffer), attr); 1163 CreateArrayBufferTemplate(ArrayBuffer), attr);
952 global_template->Set(String::New("Int8Array"), 1164 global_template->Set(String::New("Int8Array"),
953 CreateArrayTemplate(Int8Array), attr); 1165 CreateArrayTemplate(Int8Array), attr);
954 global_template->Set(String::New("Uint8Array"), 1166 global_template->Set(String::New("Uint8Array"),
955 CreateArrayTemplate(Uint8Array), attr); 1167 CreateArrayTemplate(Uint8Array), attr);
956 global_template->Set(String::New("Int16Array"), 1168 global_template->Set(String::New("Int16Array"),
957 CreateArrayTemplate(Int16Array), attr); 1169 CreateArrayTemplate(Int16Array), attr);
958 global_template->Set(String::New("Uint16Array"), 1170 global_template->Set(String::New("Uint16Array"),
959 CreateArrayTemplate(Uint16Array), attr); 1171 CreateArrayTemplate(Uint16Array), attr);
960 global_template->Set(String::New("Int32Array"), 1172 global_template->Set(String::New("Int32Array"),
961 CreateArrayTemplate(Int32Array), attr); 1173 CreateArrayTemplate(Int32Array), attr);
(...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 } 1889 }
1678 1890
1679 } // namespace v8 1891 } // namespace v8
1680 1892
1681 1893
1682 #ifndef GOOGLE3 1894 #ifndef GOOGLE3
1683 int main(int argc, char* argv[]) { 1895 int main(int argc, char* argv[]) {
1684 return v8::Shell::Main(argc, argv); 1896 return v8::Shell::Main(argc, argv);
1685 } 1897 }
1686 #endif 1898 #endif
OLDNEW
« no previous file with comments | « src/d8.h ('k') | test/mjsunit/external-array.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698