Commit ff8b1abb authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[builtins] Reland of Port TypedArrayInitialize to CodeStubAssembler.

Turbofan is a lot slower than Crankshaft at constructing TypedArrays,
because we always go to the C++ builtin. Port the builtin to CSA
to improve performance, and to clean up the implementation, which is
split across multiple files and pieces at the moment.

This CL increases the performance with --future to roughly the same
as with crankshaft.

BUG=v8:5977

Change-Id: Id0d91a4592de41a3a308846d79bd44a608931762
Reviewed-on: https://chromium-review.googlesource.com/448537Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43548}
parent d7cb3cfc
...@@ -1546,6 +1546,14 @@ ExternalReference ExternalReference::libc_memchr_function(Isolate* isolate) { ...@@ -1546,6 +1546,14 @@ ExternalReference ExternalReference::libc_memchr_function(Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memchr))); return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memchr)));
} }
void* libc_memset(void* string, int character, size_t n) {
return memset(string, character, n);
}
ExternalReference ExternalReference::libc_memset_function(Isolate* isolate) {
return ExternalReference(Redirect(isolate, FUNCTION_ADDR(libc_memset)));
}
ExternalReference ExternalReference::page_flags(Page* page) { ExternalReference ExternalReference::page_flags(Page* page) {
return ExternalReference(reinterpret_cast<Address>(page) + return ExternalReference(reinterpret_cast<Address>(page) +
MemoryChunk::kFlagsOffset); MemoryChunk::kFlagsOffset);
......
...@@ -978,6 +978,7 @@ class ExternalReference BASE_EMBEDDED { ...@@ -978,6 +978,7 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference ieee754_tanh_function(Isolate* isolate); static ExternalReference ieee754_tanh_function(Isolate* isolate);
static ExternalReference libc_memchr_function(Isolate* isolate); static ExternalReference libc_memchr_function(Isolate* isolate);
static ExternalReference libc_memset_function(Isolate* isolate);
static ExternalReference page_flags(Page* page); static ExternalReference page_flags(Page* page);
......
...@@ -2620,6 +2620,13 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -2620,6 +2620,13 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
} }
TYPED_ARRAYS(INSTALL_TYPED_ARRAY) TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
#undef INSTALL_TYPED_ARRAY #undef INSTALL_TYPED_ARRAY
// %typed_array_initialize
Handle<JSFunction> typed_array_initialize = SimpleCreateFunction(
isolate, factory->NewStringFromAsciiChecked("typedArrayInitialize"),
Builtins::kTypedArrayInitialize, 6, false);
InstallWithIntrinsicDefaultProto(isolate, typed_array_initialize,
Context::TYPED_ARRAY_INITIALIZE_INDEX);
} }
{ // -- D a t a V i e w { // -- D a t a V i e w
......
...@@ -21,8 +21,231 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler { ...@@ -21,8 +21,231 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
int object_offset); int object_offset);
template <IterationKind kIterationKind> template <IterationKind kIterationKind>
void GenerateTypedArrayPrototypeIterationMethod(const char* method_name); void GenerateTypedArrayPrototypeIterationMethod(const char* method_name);
void LoadMapAndElementsSize(Node* array, Variable* typed_map, Variable* size);
}; };
void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* array,
Variable* typed_map,
Variable* size) {
Label unreachable(this), done(this);
Label uint8_elements(this), uint8_clamped_elements(this), int8_elements(this),
uint16_elements(this), int16_elements(this), uint32_elements(this),
int32_elements(this), float32_elements(this), float64_elements(this);
Label* elements_kind_labels[] = {
&uint8_elements, &uint8_clamped_elements, &int8_elements,
&uint16_elements, &int16_elements, &uint32_elements,
&int32_elements, &float32_elements, &float64_elements};
int32_t elements_kinds[] = {
UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS};
const size_t kTypedElementsKindCount = LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
1;
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
Node* array_map = LoadMap(array);
Node* elements_kind = LoadMapElementsKind(array_map);
Switch(elements_kind, &unreachable, elements_kinds, elements_kind_labels,
kTypedElementsKindCount);
for (int i = 0; i < static_cast<int>(kTypedElementsKindCount); i++) {
Bind(elements_kind_labels[i]);
{
ElementsKind kind = static_cast<ElementsKind>(elements_kinds[i]);
ExternalArrayType type =
isolate()->factory()->GetArrayTypeFromElementsKind(kind);
Handle<Map> map(isolate()->heap()->MapForFixedTypedArray(type));
typed_map->Bind(HeapConstant(map));
size->Bind(SmiConstant(static_cast<int>(
isolate()->factory()->GetExternalArrayElementSize(type))));
Goto(&done);
}
}
Bind(&unreachable);
{ Unreachable(); }
Bind(&done);
}
TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
Node* holder = Parameter(1);
Node* length = Parameter(2);
Node* maybe_buffer = Parameter(3);
Node* byte_offset = Parameter(4);
Node* byte_length = Parameter(5);
Node* initialize = Parameter(6);
Node* context = Parameter(9);
static const int32_t fta_base_data_offset =
FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
Label setup_holder(this), alloc_array_buffer(this), aligned(this),
allocate_elements(this), attach_buffer(this), done(this);
Variable fixed_typed_map(this, MachineRepresentation::kTagged);
Variable element_size(this, MachineRepresentation::kTagged);
Variable total_size(this, MachineType::PointerRepresentation());
// Make sure length is a Smi. The caller guarantees this is the case.
length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
CSA_ASSERT(this, TaggedIsSmi(length));
byte_offset =
ToInteger(context, byte_offset, CodeStubAssembler::kTruncateMinusZero);
CSA_ASSERT(this, TaggedIsSmi(byte_offset));
// byte_length can be -0, get rid of it.
byte_length =
ToInteger(context, byte_length, CodeStubAssembler::kTruncateMinusZero);
GotoIfNot(IsNull(maybe_buffer), &setup_holder);
// If the buffer is null, then we need a Smi byte_length. The caller
// guarantees this is the case, because when byte_length >
// TypedArrayMaxSizeInHeap, a buffer is allocated and passed in here.
CSA_ASSERT(this, TaggedIsSmi(byte_length));
Goto(&setup_holder);
Bind(&setup_holder);
{
LoadMapAndElementsSize(holder, &fixed_typed_map, &element_size);
// Setup the holder (JSArrayBufferView).
// - Set the length.
// - Set the byte_offset.
// - Set the byte_length.
// - Set InternalFields to 0.
StoreObjectField(holder, JSTypedArray::kLengthOffset, length);
StoreObjectField(holder, JSArrayBufferView::kByteOffsetOffset, byte_offset);
StoreObjectField(holder, JSArrayBufferView::kByteLengthOffset, byte_length);
for (int offset = JSTypedArray::kSize;
offset < JSTypedArray::kSizeWithInternalFields;
offset += kPointerSize) {
StoreObjectField(holder, offset, SmiConstant(Smi::kZero));
}
Branch(IsNull(maybe_buffer), &alloc_array_buffer, &attach_buffer);
}
Bind(&alloc_array_buffer);
{
// Allocate a new ArrayBuffer and initialize it with empty properties and
// elements.
Node* const native_context = LoadNativeContext(context);
Node* const map =
LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX);
Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
Node* buffer = Allocate(JSArrayBuffer::kSizeWithInternalFields);
StoreMapNoWriteBarrier(buffer, map);
StoreObjectFieldNoWriteBarrier(buffer, JSArray::kPropertiesOffset,
empty_fixed_array);
StoreObjectFieldNoWriteBarrier(buffer, JSArray::kElementsOffset,
empty_fixed_array);
// Setup the ArrayBuffer.
// - Set BitField to 0.
// - Set IsExternal and IsNeuterable bits of BitFieldSlot.
// - Set the byte_length field to byte_length.
// - Set backing_store to null/Smi(0).
// - Set all internal fields to Smi(0).
StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldSlot,
SmiConstant(Smi::kZero));
int32_t bitfield_value = (1 << JSArrayBuffer::IsExternal::kShift) |
(1 << JSArrayBuffer::IsNeuterable::kShift);
StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldOffset,
Int32Constant(bitfield_value),
MachineRepresentation::kWord32);
StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kByteLengthOffset,
byte_length);
StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBackingStoreOffset,
SmiConstant(Smi::kZero));
for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
int offset = JSArrayBuffer::kSize + i * kPointerSize;
StoreObjectFieldNoWriteBarrier(buffer, offset, SmiConstant(Smi::kZero));
}
StoreObjectField(holder, JSArrayBufferView::kBufferOffset, buffer);
// Check the alignment.
GotoIf(SmiEqual(SmiMod(element_size.value(), SmiConstant(kObjectAlignment)),
SmiConstant(0)),
&aligned);
// Fix alignment if needed.
DCHECK_EQ(0, FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask);
Node* aligned_header_size =
IntPtrConstant(FixedTypedArrayBase::kHeaderSize + kObjectAlignmentMask);
Node* size = IntPtrAdd(SmiToWord(byte_length), aligned_header_size);
total_size.Bind(WordAnd(size, IntPtrConstant(~kObjectAlignmentMask)));
Goto(&allocate_elements);
}
Bind(&aligned);
{
Node* header_size = IntPtrConstant(FixedTypedArrayBase::kHeaderSize);
total_size.Bind(IntPtrAdd(SmiToWord(byte_length), header_size));
Goto(&allocate_elements);
}
Bind(&allocate_elements);
{
// Allocate a FixedTypedArray and set the length, base pointer and external
// pointer.
CSA_ASSERT(this, IsRegularHeapObjectSize(total_size.value()));
Node* elements = Allocate(total_size.value());
StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
StoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kBasePointerOffset, elements);
StoreObjectFieldNoWriteBarrier(elements,
FixedTypedArrayBase::kExternalPointerOffset,
IntPtrConstant(fta_base_data_offset),
MachineType::PointerRepresentation());
StoreObjectField(holder, JSObject::kElementsOffset, elements);
GotoIf(IsFalse(initialize), &done);
// Initialize the backing store by filling it with 0s.
Node* backing_store = IntPtrAdd(BitcastTaggedToWord(elements),
IntPtrConstant(fta_base_data_offset));
// Call out to memset to perform initialization.
Node* memset =
ExternalConstant(ExternalReference::libc_memset_function(isolate()));
CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
MachineType::IntPtr(), MachineType::UintPtr(), memset,
backing_store, IntPtrConstant(0), SmiToWord(byte_length));
Goto(&done);
}
Bind(&attach_buffer);
{
StoreObjectField(holder, JSArrayBufferView::kBufferOffset, maybe_buffer);
Node* elements = Allocate(FixedTypedArrayBase::kHeaderSize);
StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
StoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kBasePointerOffset, SmiConstant(0));
Node* backing_store =
LoadObjectField(maybe_buffer, JSArrayBuffer::kBackingStoreOffset,
MachineType::Pointer());
Node* external_pointer = IntPtrAdd(backing_store, SmiToWord(byte_offset));
StoreObjectFieldNoWriteBarrier(
elements, FixedTypedArrayBase::kExternalPointerOffset, external_pointer,
MachineType::PointerRepresentation());
StoreObjectField(holder, JSObject::kElementsOffset, elements);
Goto(&done);
}
Bind(&done);
{ Return(UndefinedConstant()); }
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ES6 section 22.2 TypedArray Objects // ES6 section 22.2 TypedArray Objects
......
...@@ -805,6 +805,7 @@ class Isolate; ...@@ -805,6 +805,7 @@ class Isolate;
TFJ(SymbolPrototypeValueOf, 0) \ TFJ(SymbolPrototypeValueOf, 0) \
\ \
/* TypedArray */ \ /* TypedArray */ \
TFJ(TypedArrayInitialize, 6) \
CPP(TypedArrayPrototypeBuffer) \ CPP(TypedArrayPrototypeBuffer) \
/* ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength */ \ /* ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength */ \
TFJ(TypedArrayPrototypeByteLength, 0) \ TFJ(TypedArrayPrototypeByteLength, 0) \
......
...@@ -68,6 +68,7 @@ enum ContextLookupFlags { ...@@ -68,6 +68,7 @@ enum ContextLookupFlags {
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \ V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \ V(SPREAD_ARGUMENTS_INDEX, JSFunction, spread_arguments) \
V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \ V(SPREAD_ITERABLE_INDEX, JSFunction, spread_iterable) \
V(TYPED_ARRAY_INITIALIZE_INDEX, JSFunction, typed_array_initialize) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \ V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \ V(MATH_POW_INDEX, JSFunction, math_pow) \
V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \ V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
......
...@@ -233,6 +233,8 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) { ...@@ -233,6 +233,8 @@ void ExternalReferenceTable::AddReferences(Isolate* isolate) {
"wasm::call_trap_callback_for_testing"); "wasm::call_trap_callback_for_testing");
Add(ExternalReference::libc_memchr_function(isolate).address(), Add(ExternalReference::libc_memchr_function(isolate).address(),
"libc_memchr"); "libc_memchr");
Add(ExternalReference::libc_memset_function(isolate).address(),
"libc_memset");
Add(ExternalReference::log_enter_external_function(isolate).address(), Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal"); "Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(), Add(ExternalReference::log_leave_external_function(isolate).address(),
......
...@@ -2017,23 +2017,20 @@ Handle<JSSetIterator> Factory::NewJSSetIterator() { ...@@ -2017,23 +2017,20 @@ Handle<JSSetIterator> Factory::NewJSSetIterator() {
JSSetIterator); JSSetIterator);
} }
ExternalArrayType Factory::GetArrayTypeFromElementsKind(ElementsKind kind) {
namespace { switch (kind) {
ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case kExternal##Type##Array: \ case TYPE##_ELEMENTS: \
return TYPE##_ELEMENTS; return kExternal##Type##Array;
TYPED_ARRAYS(TYPED_ARRAY_CASE) TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
return kExternalInt8Array;
} }
UNREACHABLE();
return FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
} }
size_t Factory::GetExternalArrayElementSize(ExternalArrayType type) {
size_t GetExternalArrayElementSize(ExternalArrayType type) {
switch (type) { switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case kExternal##Type##Array: \ case kExternal##Type##Array: \
...@@ -2046,30 +2043,29 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) { ...@@ -2046,30 +2043,29 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) {
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
} }
namespace {
size_t GetFixedTypedArraysElementSize(ElementsKind kind) { ElementsKind GetExternalArrayElementsKind(ExternalArrayType type) {
switch (kind) { switch (type) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case TYPE##_ELEMENTS: \ case kExternal##Type##Array: \
return size; return TYPE##_ELEMENTS;
TYPED_ARRAYS(TYPED_ARRAY_CASE) TYPED_ARRAYS(TYPED_ARRAY_CASE)
default:
UNREACHABLE();
return 0;
} }
UNREACHABLE();
return FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
} }
size_t GetFixedTypedArraysElementSize(ElementsKind kind) {
ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
switch (kind) { switch (kind) {
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case TYPE##_ELEMENTS: \ case TYPE##_ELEMENTS: \
return kExternal##Type##Array; return size;
TYPED_ARRAYS(TYPED_ARRAY_CASE) TYPED_ARRAYS(TYPED_ARRAY_CASE)
default: default:
UNREACHABLE(); UNREACHABLE();
return kExternalInt8Array; return 0;
} }
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
} }
......
...@@ -536,6 +536,9 @@ class V8_EXPORT_PRIVATE Factory final { ...@@ -536,6 +536,9 @@ class V8_EXPORT_PRIVATE Factory final {
SharedFlag shared = SharedFlag::kNotShared, SharedFlag shared = SharedFlag::kNotShared,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind);
size_t GetExternalArrayElementSize(ExternalArrayType type);
Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type, Handle<JSTypedArray> NewJSTypedArray(ExternalArrayType type,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
......
...@@ -169,13 +169,14 @@ function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { ...@@ -169,13 +169,14 @@ function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
throw %make_range_error(kInvalidTypedArrayLength); throw %make_range_error(kInvalidTypedArrayLength);
} }
} }
%_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength, true); var newLength = newByteLength / ELEMENT_SIZE;
%typed_array_initialize(obj, newLength, buffer, offset, newByteLength, true);
} }
function NAMEConstructByLength(obj, length) { function NAMEConstructByLength(obj, length) {
var l = IS_UNDEFINED(length) ? var l = IS_UNDEFINED(length) ?
0 : ToIndex(length, kInvalidTypedArrayLength); 0 : ToIndex(length, kInvalidTypedArrayLength);
if (length > %_MaxSmi()) { if (l > %_MaxSmi()) {
// Note: this is not per spec, but rather a constraint of our current // Note: this is not per spec, but rather a constraint of our current
// representation (which uses smi's). // representation (which uses smi's).
throw %make_range_error(kInvalidTypedArrayLength); throw %make_range_error(kInvalidTypedArrayLength);
...@@ -183,9 +184,9 @@ function NAMEConstructByLength(obj, length) { ...@@ -183,9 +184,9 @@ function NAMEConstructByLength(obj, length) {
var byteLength = l * ELEMENT_SIZE; var byteLength = l * ELEMENT_SIZE;
if (byteLength > %_TypedArrayMaxSizeInHeap()) { if (byteLength > %_TypedArrayMaxSizeInHeap()) {
var buffer = new GlobalArrayBuffer(byteLength); var buffer = new GlobalArrayBuffer(byteLength);
%_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength, true); %typed_array_initialize(obj, l, buffer, 0, byteLength, true);
} else { } else {
%_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, true); %typed_array_initialize(obj, l, null, 0, byteLength, true);
} }
} }
...@@ -198,7 +199,7 @@ function NAMEConstructByArrayLike(obj, arrayLike, length) { ...@@ -198,7 +199,7 @@ function NAMEConstructByArrayLike(obj, arrayLike, length) {
var initialized = false; var initialized = false;
var byteLength = l * ELEMENT_SIZE; var byteLength = l * ELEMENT_SIZE;
if (byteLength <= %_TypedArrayMaxSizeInHeap()) { if (byteLength <= %_TypedArrayMaxSizeInHeap()) {
%_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength, false); %typed_array_initialize(obj, l, null, 0, byteLength, false);
} else { } else {
initialized = initialized =
%TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l); %TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l);
......
...@@ -822,3 +822,12 @@ function TestNonConfigurableProperties(constructor) { ...@@ -822,3 +822,12 @@ function TestNonConfigurableProperties(constructor) {
for(i = 0; i < typedArrayConstructors.length; i++) { for(i = 0; i < typedArrayConstructors.length; i++) {
TestNonConfigurableProperties(typedArrayConstructors[i]); TestNonConfigurableProperties(typedArrayConstructors[i]);
} }
(function TestInitialization() {
for (var i = 0; i <= 128; i++) {
var arr = new Uint8Array(i);
for (var j = 0; j < i; j++) {
assertEquals(0, arr[j]);
}
}
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment