OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 (function(global, shared, exports) { | 5 (function(global, shared, exports) { |
6 | 6 |
7 "use strict"; | 7 "use strict"; |
8 | 8 |
9 %CheckIsBootstrapping(); | 9 %CheckIsBootstrapping(); |
10 | 10 |
11 var GlobalArray = global.Array; | 11 var GlobalArray = global.Array; |
12 var GlobalArrayBuffer = global.ArrayBuffer; | 12 var GlobalSharedArrayBuffer = global.SharedArrayBuffer; |
13 var GlobalDataView = global.DataView; | 13 var GlobalDataView = global.DataView; |
14 var GlobalObject = global.Object; | 14 var GlobalObject = global.Object; |
15 | 15 |
16 macro TYPED_ARRAYS(FUNCTION) | 16 macro SHARED_TYPED_ARRAYS(FUNCTION) |
17 // arrayIds below should be synchronized with Runtime_TypedArrayInitialize. | 17 // arrayIds below should be synchronized with Runtime_TypedArrayInitialize. |
18 FUNCTION(1, Uint8Array, 1) | 18 FUNCTION(1, SharedUint8Array, 1) |
19 FUNCTION(2, Int8Array, 1) | 19 FUNCTION(2, SharedInt8Array, 1) |
20 FUNCTION(3, Uint16Array, 2) | 20 FUNCTION(3, SharedUint16Array, 2) |
21 FUNCTION(4, Int16Array, 2) | 21 FUNCTION(4, SharedInt16Array, 2) |
22 FUNCTION(5, Uint32Array, 4) | 22 FUNCTION(5, SharedUint32Array, 4) |
23 FUNCTION(6, Int32Array, 4) | 23 FUNCTION(6, SharedInt32Array, 4) |
24 FUNCTION(7, Float32Array, 4) | 24 FUNCTION(7, SharedFloat32Array, 4) |
25 FUNCTION(8, Float64Array, 8) | 25 FUNCTION(8, SharedFloat64Array, 8) |
26 FUNCTION(9, Uint8ClampedArray, 1) | 26 FUNCTION(9, SharedUint8ClampedArray, 1) |
27 endmacro | 27 endmacro |
28 | 28 |
29 macro DECLARE_GLOBALS(INDEX, NAME, SIZE) | 29 macro DECLARE_GLOBALS(INDEX, NAME, SIZE) |
30 var GlobalNAME = global.NAME; | 30 var GlobalNAME = global.NAME; |
31 endmacro | 31 endmacro |
32 | 32 |
33 TYPED_ARRAYS(DECLARE_GLOBALS) | 33 SHARED_TYPED_ARRAYS(DECLARE_GLOBALS) |
34 | 34 |
35 // --------------- Typed Arrays --------------------- | 35 // --------------- Shared Typed Arrays --------------------- |
36 | 36 |
37 macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) | 37 macro SHARED_TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE) |
38 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { | 38 function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) { |
39 if (!IS_UNDEFINED(byteOffset)) { | 39 if (!IS_UNDEFINED(byteOffset)) { |
40 byteOffset = | 40 byteOffset = |
41 $toPositiveInteger(byteOffset, kInvalidTypedArrayLength); | 41 $toPositiveInteger(byteOffset, kInvalidTypedArrayLength); |
42 } | 42 } |
43 if (!IS_UNDEFINED(length)) { | 43 if (!IS_UNDEFINED(length)) { |
44 length = $toPositiveInteger(length, kInvalidTypedArrayLength); | 44 length = $toPositiveInteger(length, kInvalidTypedArrayLength); |
45 } | 45 } |
46 | 46 |
47 var bufferByteLength = %_ArrayBufferGetByteLength(buffer); | 47 var bufferByteLength = %_ArrayBufferGetByteLength(buffer); |
48 var offset; | 48 var offset; |
49 if (IS_UNDEFINED(byteOffset)) { | 49 if (IS_UNDEFINED(byteOffset)) { |
50 offset = 0; | 50 offset = 0; |
51 } else { | 51 } else { |
52 offset = byteOffset; | 52 offset = byteOffset; |
53 | 53 |
54 if (offset % ELEMENT_SIZE !== 0) { | 54 if (offset % ELEMENT_SIZE !== 0) { |
55 throw MakeRangeError(kInvalidTypedArrayAlignment, | 55 throw MakeRangeError(kInvalidTypedArrayAlignment, "start offset", "NAME", |
56 "start offset", "NAME", ELEMENT_SIZE); | 56 ELEMENT_SIZE); |
57 } | 57 } |
58 if (offset > bufferByteLength) { | 58 if (offset > bufferByteLength) { |
59 throw MakeRangeError(kInvalidTypedArrayOffset); | 59 throw MakeRangeError(kInvalidTypedArrayOffset); |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 var newByteLength; | 63 var newByteLength; |
64 var newLength; | 64 var newLength; |
65 if (IS_UNDEFINED(length)) { | 65 if (IS_UNDEFINED(length)) { |
66 if (bufferByteLength % ELEMENT_SIZE !== 0) { | 66 if (bufferByteLength % ELEMENT_SIZE !== 0) { |
67 throw MakeRangeError(kInvalidTypedArrayAlignment, | 67 throw MakeRangeError(kInvalidTypedArrayAlignment, "byte length", "NAME", |
68 "byte length", "NAME", ELEMENT_SIZE); | 68 ELEMENT_SIZE); |
69 } | 69 } |
70 newByteLength = bufferByteLength - offset; | 70 newByteLength = bufferByteLength - offset; |
71 newLength = newByteLength / ELEMENT_SIZE; | 71 newLength = newByteLength / ELEMENT_SIZE; |
72 } else { | 72 } else { |
73 var newLength = length; | 73 var newLength = length; |
74 newByteLength = newLength * ELEMENT_SIZE; | 74 newByteLength = newLength * ELEMENT_SIZE; |
75 } | 75 } |
76 if ((offset + newByteLength > bufferByteLength) | 76 if ((offset + newByteLength > bufferByteLength) |
77 || (newLength > %_MaxSmi())) { | 77 || (newLength > %_MaxSmi())) { |
78 throw MakeRangeError(kInvalidTypedArrayLength); | 78 throw MakeRangeError(kInvalidTypedArrayLength); |
79 } | 79 } |
80 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength); | 80 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength); |
81 } | 81 } |
82 | 82 |
83 function NAMEConstructByLength(obj, length) { | 83 function NAMEConstructByLength(obj, length) { |
84 var l = IS_UNDEFINED(length) ? | 84 var l = IS_UNDEFINED(length) ? |
85 0 : $toPositiveInteger(length, kInvalidTypedArrayLength); | 85 0 : $toPositiveInteger(length, kInvalidTypedArrayLength); |
86 if (l > %_MaxSmi()) { | 86 if (l > %_MaxSmi()) { |
87 throw MakeRangeError(kInvalidTypedArrayLength); | 87 throw MakeRangeError(kInvalidTypedArrayLength); |
88 } | 88 } |
89 var byteLength = l * ELEMENT_SIZE; | 89 var byteLength = l * ELEMENT_SIZE; |
90 if (byteLength > %_TypedArrayMaxSizeInHeap()) { | 90 var buffer = new GlobalSharedArrayBuffer(byteLength); |
91 var buffer = new GlobalArrayBuffer(byteLength); | 91 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength); |
92 %_TypedArrayInitialize(obj, ARRAY_ID, buffer, 0, byteLength); | |
93 } else { | |
94 %_TypedArrayInitialize(obj, ARRAY_ID, null, 0, byteLength); | |
95 } | |
96 } | |
97 | |
98 function NAMEConstructByArrayLike(obj, arrayLike) { | |
99 var length = arrayLike.length; | |
100 var l = $toPositiveInteger(length, kInvalidTypedArrayLength); | |
101 | |
102 if (l > %_MaxSmi()) { | |
103 throw MakeRangeError(kInvalidTypedArrayLength); | |
104 } | |
105 if(!%TypedArrayInitializeFromArrayLike(obj, ARRAY_ID, arrayLike, l)) { | |
106 for (var i = 0; i < l; i++) { | |
107 // It is crucial that we let any execptions from arrayLike[i] | |
108 // propagate outside the function. | |
109 obj[i] = arrayLike[i]; | |
110 } | |
111 } | |
112 } | 92 } |
113 | 93 |
114 function NAMEConstructor(arg1, arg2, arg3) { | 94 function NAMEConstructor(arg1, arg2, arg3) { |
115 if (%_IsConstructCall()) { | 95 if (%_IsConstructCall()) { |
116 if (IS_ARRAYBUFFER(arg1)) { | 96 if (IS_SHAREDARRAYBUFFER(arg1)) { |
117 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); | 97 NAMEConstructByArrayBuffer(this, arg1, arg2, arg3); |
118 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) || | 98 } else if (IS_NUMBER(arg1) || IS_STRING(arg1) || |
119 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) { | 99 IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) { |
120 NAMEConstructByLength(this, arg1); | 100 NAMEConstructByLength(this, arg1); |
121 } else { | 101 } else { |
122 NAMEConstructByArrayLike(this, arg1); | 102 throw MakeTypeError(kInvalidArgument); |
123 } | 103 } |
124 } else { | 104 } else { |
125 throw MakeTypeError(kConstructorNotFunction, "NAME") | 105 throw MakeTypeError(kConstructorNotFunction, "NAME") |
126 } | 106 } |
127 } | 107 } |
128 | 108 |
129 function NAME_GetBuffer() { | 109 function NAME_GetBuffer() { |
130 if (!(%_ClassOf(this) === 'NAME')) { | 110 if (!(%_ClassOf(this) === 'NAME')) { |
131 throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.buffer", this); | 111 throw MakeTypeError(kIncompatibleMethodReceiver, "NAME.buffer", this); |
132 } | 112 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 endInt = $max(0, srcLength + endInt); | 155 endInt = $max(0, srcLength + endInt); |
176 } else { | 156 } else { |
177 endInt = $min(endInt, srcLength); | 157 endInt = $min(endInt, srcLength); |
178 } | 158 } |
179 if (endInt < beginInt) { | 159 if (endInt < beginInt) { |
180 endInt = beginInt; | 160 endInt = beginInt; |
181 } | 161 } |
182 var newLength = endInt - beginInt; | 162 var newLength = endInt - beginInt; |
183 var beginByteOffset = | 163 var beginByteOffset = |
184 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; | 164 %_ArrayBufferViewGetByteOffset(this) + beginInt * ELEMENT_SIZE; |
185 return new GlobalNAME(%TypedArrayGetBuffer(this), | 165 return new GlobalNAME(%TypedArrayGetBuffer(this), beginByteOffset, |
186 beginByteOffset, newLength); | 166 newLength); |
187 } | 167 } |
188 endmacro | 168 endmacro |
189 | 169 |
190 TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTOR) | 170 SHARED_TYPED_ARRAYS(SHARED_TYPED_ARRAY_CONSTRUCTOR) |
191 | |
192 | 171 |
193 function TypedArraySetFromArrayLike(target, source, sourceLength, offset) { | 172 function TypedArraySetFromArrayLike(target, source, sourceLength, offset) { |
194 if (offset > 0) { | 173 if (offset > 0) { |
195 for (var i = 0; i < sourceLength; i++) { | 174 for (var i = 0; i < sourceLength; i++) { |
196 target[offset + i] = source[i]; | 175 target[offset + i] = source[i]; |
197 } | 176 } |
198 } | 177 } |
199 else { | 178 else { |
200 for (var i = 0; i < sourceLength; i++) { | 179 for (var i = 0; i < sourceLength; i++) { |
201 target[i] = source[i]; | 180 target[i] = source[i]; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 | 273 |
295 function TypedArrayGetToStringTag() { | 274 function TypedArrayGetToStringTag() { |
296 if (!%IsTypedArray(this)) return; | 275 if (!%IsTypedArray(this)) return; |
297 var name = %_ClassOf(this); | 276 var name = %_ClassOf(this); |
298 if (IS_UNDEFINED(name)) return; | 277 if (IS_UNDEFINED(name)) return; |
299 return name; | 278 return name; |
300 } | 279 } |
301 | 280 |
302 // ------------------------------------------------------------------- | 281 // ------------------------------------------------------------------- |
303 | 282 |
304 macro SETUP_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) | 283 |
| 284 macro SETUP_SHARED_TYPED_ARRAY(ARRAY_ID, NAME, ELEMENT_SIZE) |
305 %SetCode(GlobalNAME, NAMEConstructor); | 285 %SetCode(GlobalNAME, NAMEConstructor); |
306 %FunctionSetPrototype(GlobalNAME, new GlobalObject()); | 286 %FunctionSetPrototype(GlobalNAME, new GlobalObject()); |
307 | 287 |
308 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE, | 288 %AddNamedProperty(GlobalNAME, "BYTES_PER_ELEMENT", ELEMENT_SIZE, |
309 READ_ONLY | DONT_ENUM | DONT_DELETE); | 289 READ_ONLY | DONT_ENUM | DONT_DELETE); |
310 %AddNamedProperty(GlobalNAME.prototype, | 290 %AddNamedProperty(GlobalNAME.prototype, |
311 "constructor", global.NAME, DONT_ENUM); | 291 "constructor", global.NAME, DONT_ENUM); |
312 %AddNamedProperty(GlobalNAME.prototype, | 292 %AddNamedProperty(GlobalNAME.prototype, |
313 "BYTES_PER_ELEMENT", ELEMENT_SIZE, | 293 "BYTES_PER_ELEMENT", ELEMENT_SIZE, |
314 READ_ONLY | DONT_ENUM | DONT_DELETE); | 294 READ_ONLY | DONT_ENUM | DONT_DELETE); |
315 $installGetter(GlobalNAME.prototype, "buffer", NAME_GetBuffer); | 295 $installGetter(GlobalNAME.prototype, "buffer", NAME_GetBuffer); |
316 $installGetter(GlobalNAME.prototype, "byteOffset", NAME_GetByteOffset, | 296 $installGetter(GlobalNAME.prototype, "byteOffset", NAME_GetByteOffset, |
317 DONT_ENUM | DONT_DELETE); | 297 DONT_ENUM | DONT_DELETE); |
318 $installGetter(GlobalNAME.prototype, "byteLength", NAME_GetByteLength, | 298 $installGetter(GlobalNAME.prototype, "byteLength", NAME_GetByteLength, |
319 DONT_ENUM | DONT_DELETE); | 299 DONT_ENUM | DONT_DELETE); |
320 $installGetter(GlobalNAME.prototype, "length", NAME_GetLength, | 300 $installGetter(GlobalNAME.prototype, "length", NAME_GetLength, |
321 DONT_ENUM | DONT_DELETE); | 301 DONT_ENUM | DONT_DELETE); |
322 $installGetter(GlobalNAME.prototype, symbolToStringTag, | 302 $installGetter(GlobalNAME.prototype, symbolToStringTag, |
323 TypedArrayGetToStringTag); | 303 TypedArrayGetToStringTag); |
324 $installFunctions(GlobalNAME.prototype, DONT_ENUM, [ | 304 $installFunctions(GlobalNAME.prototype, DONT_ENUM, [ |
325 "subarray", NAMESubArray, | 305 "subarray", NAMESubArray, |
326 "set", TypedArraySet | 306 "set", TypedArraySet |
327 ]); | 307 ]); |
328 endmacro | 308 endmacro |
329 | 309 |
330 TYPED_ARRAYS(SETUP_TYPED_ARRAY) | 310 SHARED_TYPED_ARRAYS(SETUP_SHARED_TYPED_ARRAY) |
331 | |
332 // --------------------------- DataView ----------------------------- | |
333 | |
334 function DataViewConstructor(buffer, byteOffset, byteLength) { // length = 3 | |
335 if (%_IsConstructCall()) { | |
336 if (!IS_ARRAYBUFFER(buffer)) throw MakeTypeError(kDataViewNotArrayBuffer); | |
337 if (!IS_UNDEFINED(byteOffset)) { | |
338 byteOffset = $toPositiveInteger(byteOffset, kInvalidDataViewOffset); | |
339 } | |
340 if (!IS_UNDEFINED(byteLength)) { | |
341 byteLength = TO_INTEGER(byteLength); | |
342 } | |
343 | |
344 var bufferByteLength = %_ArrayBufferGetByteLength(buffer); | |
345 | |
346 var offset = IS_UNDEFINED(byteOffset) ? 0 : byteOffset; | |
347 if (offset > bufferByteLength) throw MakeRangeError(kInvalidDataViewOffset); | |
348 | |
349 var length = IS_UNDEFINED(byteLength) | |
350 ? bufferByteLength - offset | |
351 : byteLength; | |
352 if (length < 0 || offset + length > bufferByteLength) { | |
353 throw new MakeRangeError(kInvalidDataViewLength); | |
354 } | |
355 %_DataViewInitialize(this, buffer, offset, length); | |
356 } else { | |
357 throw MakeTypeError(kConstructorNotFunction, "DataView"); | |
358 } | |
359 } | |
360 | |
361 function DataViewGetBufferJS() { | |
362 if (!IS_DATAVIEW(this)) { | |
363 throw MakeTypeError(kIncompatibleMethodReceiver, 'DataView.buffer', this); | |
364 } | |
365 return %DataViewGetBuffer(this); | |
366 } | |
367 | |
368 function DataViewGetByteOffset() { | |
369 if (!IS_DATAVIEW(this)) { | |
370 throw MakeTypeError(kIncompatibleMethodReceiver, | |
371 'DataView.byteOffset', this); | |
372 } | |
373 return %_ArrayBufferViewGetByteOffset(this); | |
374 } | |
375 | |
376 function DataViewGetByteLength() { | |
377 if (!IS_DATAVIEW(this)) { | |
378 throw MakeTypeError(kIncompatibleMethodReceiver, | |
379 'DataView.byteLength', this); | |
380 } | |
381 return %_ArrayBufferViewGetByteLength(this); | |
382 } | |
383 | |
384 macro DATA_VIEW_TYPES(FUNCTION) | |
385 FUNCTION(Int8) | |
386 FUNCTION(Uint8) | |
387 FUNCTION(Int16) | |
388 FUNCTION(Uint16) | |
389 FUNCTION(Int32) | |
390 FUNCTION(Uint32) | |
391 FUNCTION(Float32) | |
392 FUNCTION(Float64) | |
393 endmacro | |
394 | |
395 | |
396 macro DATA_VIEW_GETTER_SETTER(TYPENAME) | |
397 function DataViewGetTYPENAMEJS(offset, little_endian) { | |
398 if (!IS_DATAVIEW(this)) { | |
399 throw MakeTypeError(kIncompatibleMethodReceiver, | |
400 'DataView.getTYPENAME', this); | |
401 } | |
402 if (%_ArgumentsLength() < 1) throw MakeTypeError(kInvalidArgument); | |
403 offset = $toPositiveInteger(offset, kInvalidDataViewAccessorOffset); | |
404 return %DataViewGetTYPENAME(this, offset, !!little_endian); | |
405 } | |
406 | |
407 function DataViewSetTYPENAMEJS(offset, value, little_endian) { | |
408 if (!IS_DATAVIEW(this)) { | |
409 throw MakeTypeError(kIncompatibleMethodReceiver, | |
410 'DataView.setTYPENAME', this); | |
411 } | |
412 if (%_ArgumentsLength() < 2) throw MakeTypeError(kInvalidArgument); | |
413 offset = $toPositiveInteger(offset, kInvalidDataViewAccessorOffset); | |
414 %DataViewSetTYPENAME(this, offset, TO_NUMBER_INLINE(value), !!little_endian); | |
415 } | |
416 endmacro | |
417 | |
418 DATA_VIEW_TYPES(DATA_VIEW_GETTER_SETTER) | |
419 | |
420 // Setup the DataView constructor. | |
421 %SetCode(GlobalDataView, DataViewConstructor); | |
422 %FunctionSetPrototype(GlobalDataView, new GlobalObject); | |
423 | |
424 // Set up constructor property on the DataView prototype. | |
425 %AddNamedProperty(GlobalDataView.prototype, "constructor", GlobalDataView, | |
426 DONT_ENUM); | |
427 %AddNamedProperty(GlobalDataView.prototype, symbolToStringTag, "DataView", | |
428 READ_ONLY|DONT_ENUM); | |
429 | |
430 $installGetter(GlobalDataView.prototype, "buffer", DataViewGetBufferJS); | |
431 $installGetter(GlobalDataView.prototype, "byteOffset", DataViewGetByteOffset); | |
432 $installGetter(GlobalDataView.prototype, "byteLength", DataViewGetByteLength); | |
433 | |
434 $installFunctions(GlobalDataView.prototype, DONT_ENUM, [ | |
435 "getInt8", DataViewGetInt8JS, | |
436 "setInt8", DataViewSetInt8JS, | |
437 | |
438 "getUint8", DataViewGetUint8JS, | |
439 "setUint8", DataViewSetUint8JS, | |
440 | |
441 "getInt16", DataViewGetInt16JS, | |
442 "setInt16", DataViewSetInt16JS, | |
443 | |
444 "getUint16", DataViewGetUint16JS, | |
445 "setUint16", DataViewSetUint16JS, | |
446 | |
447 "getInt32", DataViewGetInt32JS, | |
448 "setInt32", DataViewSetInt32JS, | |
449 | |
450 "getUint32", DataViewGetUint32JS, | |
451 "setUint32", DataViewSetUint32JS, | |
452 | |
453 "getFloat32", DataViewGetFloat32JS, | |
454 "setFloat32", DataViewSetFloat32JS, | |
455 | |
456 "getFloat64", DataViewGetFloat64JS, | |
457 "setFloat64", DataViewSetFloat64JS | |
458 ]); | |
459 | 311 |
460 }) | 312 }) |
OLD | NEW |