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: Small improvements Created Aug. 19, 2015, 12:14 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 delete this.length;
41
42 this.length = 0;
43 this.size = 0;
44 }
31 }; 45 };
32 46
33 function createGetter(elementGetter, elementShift) 47 function createGetter(elementGetter, elementShift)
34 { 48 {
35 return function(index) 49 return function(index)
36 { 50 {
37 if (index < 0 || index >= this.length) 51 if (index < 0 || index >= this.length)
38 throw new Error("Array index out of bounds"); 52 throw new Error("Array index out of bounds");
39 return elementGetter.call(this, this.arrayBufferIndex, this.arrayByteOffset + (index << elementShift)); 53 return elementGetter.call(this, this.arrayBufferIndex, this.arrayByteOffset + (index << elementShift));
40 }; 54 };
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 { 219 {
206 let length = this.length | 0; 220 let length = this.length | 0;
207 if (length == 0) 221 if (length == 0)
208 throw new Error("No elements in the array"); 222 throw new Error("No elements in the array");
209 223
210 let result = this.get(length - 1); 224 let result = this.get(length - 1);
211 this.length = this.length - 1; 225 this.length = this.length - 1;
212 return result; 226 return result;
213 } 227 }
214 228
229 function createSlicer(elementShift)
230 {
231 let {STATE_UNINITIALIZED} = require("typedObjects/objectTypes");
232
233 return function slice(start, end)
234 {
235 start = start | 0;
236 end = end | 0;
237
238 if (start < 0)
239 start = Math.max(0, this.length + start);
240 else
241 start = Math.min(start, this.length);
242
243 if (end > 0)
244 end = Math.min(0, end - this.length);
245 else
246 end = Math.max(end, -1 * this.length);
247
248 Object.defineProperties(this, {
249 length: {value: this.length, configurable: true}
250 });
251 this.retain();
252
253 let result = Object.create(this, {
254 arrayByteOffset: fixedPropertyDescriptor(
255 this.arrayByteOffset + start << elementShift
256 ),
257 length: {value: this.length - start + end, configurable: true},
258 _refCount: {value: 1, writable: true},
259 _copy: fixedPropertyDescriptor(true),
260 _state: {value: STATE_UNINITIALIZED, writable: true}
261 });
262
263 // TODO
264 // - A sliced array will have a read-only length even if all slices are
265 // released. We could fix this by keeping a count of slices, but is it
266 // worth it?
267 // - A slice of an array still keeps a reference to the array in it's
268 // __proto__ property after it's released. (We can't just replace it
269 // with null as modifying an object's prototype is apparently very slow.)
270
271 return result;
272 };
273 }
274
215 function splice(index, count) 275 function splice(index, count)
216 { 276 {
217 index = index | 0; 277 index = index | 0;
218 count = count | 0; 278 count = count | 0;
219 let length = this.length | 0; 279 let length = this.length | 0;
220 if (index < 0) 280 if (index < 0)
221 { 281 {
222 index += length; 282 index += length;
223 if (index < 0) 283 if (index < 0)
224 index = 0; 284 index = 0;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 }; 378 };
319 typeDescriptor.length = uint32; 379 typeDescriptor.length = uint32;
320 typeDescriptor.size = uint32; 380 typeDescriptor.size = uint32;
321 typeDescriptor.push = push; 381 typeDescriptor.push = push;
322 typeDescriptor.pop = pop; 382 typeDescriptor.pop = pop;
323 typeDescriptor.splice = splice; 383 typeDescriptor.splice = splice;
324 typeDescriptor.unshift = unshift; 384 typeDescriptor.unshift = unshift;
325 typeDescriptor.shift = shift; 385 typeDescriptor.shift = shift;
326 386
327 let elementShift = ilog2(elementType.referenceLength | 0); 387 let elementShift = ilog2(elementType.referenceLength | 0);
388 typeDescriptor.slice = createSlicer(elementShift);
328 typeDescriptor.get = createGetter(elementGetter, elementShift); 389 typeDescriptor.get = createGetter(elementGetter, elementShift);
329 typeDescriptor.set = createSetter(elementSetter, elementShift); 390 typeDescriptor.set = createSetter(elementSetter, elementShift);
330 391
331 if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function ") 392 if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function ")
332 meta.constructor = createCombinedConstructor(meta.constructor); 393 meta.constructor = createCombinedConstructor(meta.constructor);
333 else 394 else
334 meta.constructor = defaultArrayConstructor; 395 meta.constructor = defaultArrayConstructor;
335 396
336 if (meta.hasOwnProperty("destructor") && typeof meta.destructor == "function") 397 if (meta.hasOwnProperty("destructor") && typeof meta.destructor == "function")
337 meta.destructor = createCombinedDestructor(meta.destructor); 398 meta.destructor = createCombinedDestructor(meta.destructor);
338 else 399 else
339 meta.destructor = defaultArrayDestructor; 400 meta.destructor = defaultArrayDestructor;
340 401
341 if (!meta.watch || typeof meta.watch != "object") 402 if (!meta.watch || typeof meta.watch != "object")
342 meta.watch = {}; 403 meta.watch = {};
343 404
344 meta.watch.length = createLengthWatcher(elementType, elementSetter); 405 meta.watch.length = createLengthWatcher(elementType, elementSetter);
345 meta.watch.size = createSizeWatcher(elementType, minElements, bufferSize, buff ers, viewTypes, views, firstFree); 406 meta.watch.size = createSizeWatcher(elementType, minElements, bufferSize, buff ers, viewTypes, views, firstFree);
346 407
347 let {ObjectBase} = require("typedObjects/objectTypes"); 408 let {ObjectBase} = require("typedObjects/objectTypes");
348 return ObjectBase.extend(typeDescriptor, meta); 409 return ObjectBase.extend(typeDescriptor, meta);
349 } 410 }
350 411
351 exports.createArrayType = createArrayType; 412 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