Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/typedObjects/arrayTypes.js

Issue 29323484: Issue 507 - Implement lightweight array.slice() method (Closed)
Patch Set: Created Aug. 12, 2015, 4:41 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/typedObjects.js ('k') | lib/typedObjects/objectTypes.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 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 "use strict"; 18 "use strict";
19 19
20 let {ilog2, nextPow2, alloc, dealloc, addBuffer, removeBuffer} = require("typedO bjects/utils"); 20 let {ilog2, nextPow2, alloc, fixedPropertyDescriptor, dealloc, addBuffer, remove Buffer} = require("typedObjects/utils");
21 21
22 function defaultArrayConstructor() 22 function defaultArrayConstructor()
23 { 23 {
24 this.arrayBufferIndex = -1; 24 this.arrayBufferIndex = -1;
25 }; 25 };
26 26
27 function defaultArrayDestructor() 27 function defaultArrayDestructor()
28 { 28 {
29 this.length = 0; 29 if (this._copy)
30 this.size = 0; 30 {
31 // Carefully zero length + size if this is a slice of an array
32 Object.defineProperties(this, {
33 length: fixedPropertyDescriptor(0),
34 size: fixedPropertyDescriptor(0)
35 });
36 }
37 else
38 {
39 // Remove read-only length property for previously sliced arrays
40 if (this.hasOwnProperty("length"))
41 delete this.length;
42
43 this.length = 0;
44 this.size = 0;
45 }
31 }; 46 };
32 47
33 function createGetter(elementGetter, elementShift) 48 function createGetter(elementGetter, elementShift)
34 { 49 {
35 return function(index) 50 return function(index)
36 { 51 {
37 if (index < 0 || index >= this.length) 52 if (index < 0 || index >= this.length)
38 throw new Error("Array index out of bounds"); 53 throw new Error("Array index out of bounds");
39 return elementGetter.call(this, this.arrayBufferIndex, this.arrayByteOffset + (index << elementShift)); 54 return elementGetter.call(this, this.arrayBufferIndex, this.arrayByteOffset + (index << elementShift));
40 }; 55 };
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 { 220 {
206 let length = this.length | 0; 221 let length = this.length | 0;
207 if (length == 0) 222 if (length == 0)
208 throw new Error("No elements in the array"); 223 throw new Error("No elements in the array");
209 224
210 let result = this.get(length - 1); 225 let result = this.get(length - 1);
211 this.length = this.length - 1; 226 this.length = this.length - 1;
212 return result; 227 return result;
213 } 228 }
214 229
230 function createSlicer(elementShift)
231 {
232 return function slice(start, end)
233 {
234 start = start | 0;
235 end = end | 0;
236
237 if (start < 0)
238 start = Math.max(0, this.length + start);
239 else
240 start = Math.min(start, this.length);
241
242 if (end > 0)
243 end = Math.min(0, end - this.length);
244 else
245 end = Math.max(end, -1 * this.length);
246
247 Object.defineProperties(this, {
248 length: {value: this.length, configurable: true}
249 });
250 this.retain();
251
252 let result = Object.create(this, {
253 arrayByteOffset: fixedPropertyDescriptor(
254 this.arrayByteOffset + start << elementShift
255 ),
256 length: {value: this.length - start + end, configurable: true},
257 _refCount: {value: 1, writable: true},
258 _copy: fixedPropertyDescriptor(true),
259 _state: {value: 0, writable: true}
260 });
261
262 // TODO
263 // - A sliced array will have a read-only length even if all slices are
264 // released. We could fix this by keeping a count of slices, but is it
265 // worth it?
266 // - A slice of an array still keeps a reference to the array in it's
267 // __proto__ property after it's released. (We can't just replace it
268 // with null as modifying an object's prototype is apparently very slow.)
269
270 return result;
271 };
272 }
273
215 function splice(index, count) 274 function splice(index, count)
216 { 275 {
217 index = index | 0; 276 index = index | 0;
218 count = count | 0; 277 count = count | 0;
219 let length = this.length | 0; 278 let length = this.length | 0;
220 if (index < 0) 279 if (index < 0)
221 { 280 {
222 index += length; 281 index += length;
223 if (index < 0) 282 if (index < 0)
224 index = 0; 283 index = 0;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 }; 377 };
319 typeDescriptor.length = uint32; 378 typeDescriptor.length = uint32;
320 typeDescriptor.size = uint32; 379 typeDescriptor.size = uint32;
321 typeDescriptor.push = push; 380 typeDescriptor.push = push;
322 typeDescriptor.pop = pop; 381 typeDescriptor.pop = pop;
323 typeDescriptor.splice = splice; 382 typeDescriptor.splice = splice;
324 typeDescriptor.unshift = unshift; 383 typeDescriptor.unshift = unshift;
325 typeDescriptor.shift = shift; 384 typeDescriptor.shift = shift;
326 385
327 let elementShift = ilog2(elementType.referenceLength | 0); 386 let elementShift = ilog2(elementType.referenceLength | 0);
387 typeDescriptor.slice = createSlicer(elementShift);
328 typeDescriptor.get = createGetter(elementGetter, elementShift); 388 typeDescriptor.get = createGetter(elementGetter, elementShift);
329 typeDescriptor.set = createSetter(elementSetter, elementShift); 389 typeDescriptor.set = createSetter(elementSetter, elementShift);
330 390
331 if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function ") 391 if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function ")
332 meta.constructor = createCombinedConstructor(meta.constructor); 392 meta.constructor = createCombinedConstructor(meta.constructor);
333 else 393 else
334 meta.constructor = defaultArrayConstructor; 394 meta.constructor = defaultArrayConstructor;
335 395
336 if (meta.hasOwnProperty("destructor") && typeof meta.destructor == "function") 396 if (meta.hasOwnProperty("destructor") && typeof meta.destructor == "function")
337 meta.destructor = createCombinedDestructor(meta.destructor); 397 meta.destructor = createCombinedDestructor(meta.destructor);
338 else 398 else
339 meta.destructor = defaultArrayDestructor; 399 meta.destructor = defaultArrayDestructor;
340 400
341 if (!meta.watch || typeof meta.watch != "object") 401 if (!meta.watch || typeof meta.watch != "object")
342 meta.watch = {}; 402 meta.watch = {};
343 403
344 meta.watch.length = createLengthWatcher(elementType, elementSetter); 404 meta.watch.length = createLengthWatcher(elementType, elementSetter);
345 meta.watch.size = createSizeWatcher(elementType, minElements, bufferSize, buff ers, viewTypes, views, firstFree); 405 meta.watch.size = createSizeWatcher(elementType, minElements, bufferSize, buff ers, viewTypes, views, firstFree);
346 406
347 let {ObjectBase} = require("typedObjects/objectTypes"); 407 let {ObjectBase} = require("typedObjects/objectTypes");
348 return ObjectBase.extend(typeDescriptor, meta); 408 return ObjectBase.extend(typeDescriptor, meta);
349 } 409 }
350 410
351 exports.createArrayType = createArrayType; 411 exports.createArrayType = createArrayType;
OLDNEW
« no previous file with comments | « lib/typedObjects.js ('k') | lib/typedObjects/objectTypes.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld