Allocate typed arrays uninitialized when constructing from array-like.
authordslomov@chromium.org <dslomov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 10:50:14 +0000 (10:50 +0000)
committerdslomov@chromium.org <dslomov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 24 Sep 2013 10:50:14 +0000 (10:50 +0000)
This is a fix for performance regression. For new Uint8Array(arrayLike)
and the likes, we allocate the backing store of typed array
uninitialized and then proceed to feel it in with elements of arrayLike.
If the loop over arrayLike runs to completion, we know that all elements
of typed arrays had been assigned to and there is no uninitialized
memory. If the loop does not run to completion, we propagate the
exception to constructor caller, therefore the typed array is not
exposed to user program.

BUG=270507
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/23463050

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16914 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/runtime.cc
src/typedarray.js

index dbc8f11..7dc6bce 100644 (file)
@@ -933,17 +933,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
             HandleVector<Object>(NULL, 0)));
   }
 
+  // NOTE: not initializing backing store.
   // We assume that the caller of this function will initialize holder
   // with the loop
   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
+  // We assume that the caller of this function is always a typed array
+  // constructor.
   // If source is a typed array, this loop will always run to completion,
   // so we are sure that the backing store will be initialized.
-  // Otherwise, we do not know (the indexing operation might throw).
-  // Hence we require zero initialization unless our source is a typed array.
-  bool should_zero_initialize = !source->IsJSTypedArray();
+  // Otherwise, the indexing operation might throw, so the loop will not
+  // run to completion and the typed array might remain partly initialized.
+  // However we further assume that the caller of this function is a typed array
+  // constructor, and the exception will propagate out of the constructor,
+  // therefore uninitialized memory will not be accessible by a user program.
+  //
+  // TODO(dslomov): revise this once we support subclassing.
 
   if (!Runtime::SetupArrayBufferAllocatingData(
-        isolate, buffer, byte_length, should_zero_initialize)) {
+        isolate, buffer, byte_length, false)) {
     return isolate->Throw(*isolate->factory()->
           NewRangeError("invalid_array_buffer_length",
             HandleVector<Object>(NULL, 0)));
index 7bd16f6..da12ccf 100644 (file)
@@ -76,9 +76,11 @@ function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
 
   function ConstructByArrayLike(obj, arrayLike) {
     var length = arrayLike.length;
-    var l =  ToPositiveInteger(length, "invalid_typed_array_length");
+    var l = ToPositiveInteger(length, "invalid_typed_array_length");
     if(!%TypedArrayInitializeFromArrayLike(obj, arrayId, arrayLike, l)) {
       for (var i = 0; i < l; i++) {
+        // It is crucial that we let any execptions from arrayLike[i]
+        // propagate outside the function.
         obj[i] = arrayLike[i];
       }
     }