1<html>
2<head>
3<title>ArrayBuffer External Memory test</title>
4<script>
5
6var log;
7function print(message, color)
8{
9    var paragraph = document.createElement("div");
10    paragraph.appendChild(document.createTextNode(message));
11    paragraph.style.fontFamily = "monospace";
12    if (color)
13        paragraph.style.color = color;
14    log.appendChild(paragraph);
15}
16
17function pass(msg)
18{
19    print("PASS: " + msg, "green");
20}
21
22function fail(msg)
23{
24    print("FAIL: " + msg, "red");
25}
26
27var KB = 1024;
28var MB = KB * KB;
29var noise = KB;
30
31function externalMemory() {
32    return getV8Statistics().amount_of_external_allocated_memory;
33}
34
35function collectGarbage() {
36    for (var i = 0; i < 10; i++) gc();
37}
38
39function allocationsThatIncreaseExternalMemory() {
40    function test(expression) {
41        var before = externalMemory();
42        (function () { eval(expression); }) ();
43        var now = externalMemory();
44        if (now < before + MB - noise) {
45            fail(expression + " did not increase the amount of external memory (" +
46                  before + ", " + now + ").");
47        } else {
48            pass(expression + " increased the amount of external memory.");
49        }
50        collectGarbage();
51        var after = externalMemory();
52        if (after > now + noise) {
53            fail("Garbage collection after " + expression +
54                 " did not return the amount of external memory to the initial value (" +
55                 now + ", " + after + ").");
56        } else {
57            pass("Garbage collection after " + expression +
58                 " returned the amount of external memory to the initial value.");
59        }
60    }
61
62    test("(new ArrayBuffer(MB))");
63    test("(new Float32Array(MB))");
64    test("(new Float64Array(MB))");
65    test("(new Int8Array(MB))");
66    test("(new Int16Array(MB))");
67    test("(new Int32Array(MB))");
68    test("(new Uint8Array(MB))");
69    test("(new Uint16Array(MB))");
70    test("(new Uint32Array(MB))");
71    var largeJSArray = [];
72    for (var i = 0; i < MB; i++) largeJSArray.push(i);
73    test("(new Float32Array(largeJSArray))");
74    test("(new Float64Array(largeJSArray))");
75    test("(new Int8Array(largeJSArray))");
76    test("(new Int16Array(largeJSArray))");
77    test("(new Int32Array(largeJSArray))");
78    test("(new Uint8Array(largeJSArray))");
79    test("(new Uint16Array(largeJSArray))");
80    test("(new Uint32Array(largeJSArray))");
81    var int8Array = new Int8Array(MB);
82    test("(new  Float32Array(int8Array))");
83    test("(new  Float64Array(int8Array))");
84    test("(new  Int8Array(int8Array))");
85    test("(new  Int16Array(int8Array))");
86    test("(new  Int32Array(int8Array))");
87    test("(new  Uint8Array(int8Array))");
88    test("(new  Uint16Array(int8Array))");
89    test("(new  Uint32Array(int8Array))");
90}
91
92
93function allocationsThatDoNotChangeExternalMemory() {
94    function test(expression) {
95        var before = externalMemory();
96        (function () { eval(expression); }) ();
97        var now = externalMemory();
98        if (now > before + noise) {
99            fail(expression + " increased the amount of external memory (" + before + ", " + now + ").");
100        } else {
101            pass(expression + " did not increase the amount of external memory.");
102        }
103        collectGarbage();
104        var after = externalMemory();
105        if (after < now - noise) {
106            fail("Garbage collection after " + expression + " decreased the amount of external memory (" +
107                 now + ", " + after + ").");
108        } else {
109            pass("Garbage collection after " + expression +
110                 " did not decrease the amount of external memory.");
111        }
112    }
113    var arrayBuffer = new ArrayBuffer(MB);
114    test("(new  Float32Array(arrayBuffer))");
115    test("(new  Float64Array(arrayBuffer))");
116    test("(new  Int8Array(arrayBuffer))");
117    test("(new  Int16Array(arrayBuffer))");
118    test("(new  Int32Array(arrayBuffer))");
119    test("(new  Uint8Array(arrayBuffer))");
120    test("(new  Uint16Array(arrayBuffer))");
121    test("(new  Uint32Array(arrayBuffer))");
122    var int8Array = new Int8Array(MB);
123    test("(new  Float32Array(int8Array.buffer))");
124    test("(new  Float64Array(int8Array.buffer))");
125    test("(new  Int8Array(int8Array.buffer))");
126    test("(new  Int16Array(int8Array.buffer))");
127    test("(new  Int32Array(int8Array.buffer))");
128    test("(new  Uint8Array(int8Array.buffer))");
129    test("(new  Uint16Array(int8Array.buffer))");
130    test("(new  Uint32Array(int8Array.buffer))");
131}
132
133
134function transfersThatDecreaseExternalMemory() {
135    var workerSource =
136"function externalMemory() {\n" +
137"    return getV8Statistics().amount_of_external_allocated_memory;\n" +
138"}\n" +
139"var KB = 1024;\n" +
140"var MB = KB * KB;\n" +
141"var noise = KB;\n" +
142"self.onmessage = function(e) {\n" +
143"    var before = externalMemory();\n" +
144"    e.data;\n" +
145"    var after = externalMemory();\n" +
146"    if (after > before + MB - noise) {\n" +
147"      self.postMessage('PASS: Amount of external memory increased.');\n" +
148"    } else {\n" +
149"      self.postMessage('FAIL: Amount of external memory did not increase.');\n" +
150"    }\n" +
151"}\n";
152
153    var blob = new Blob([workerSource]);
154    var worker = new Worker(window.webkitURL.createObjectURL(blob));
155    worker.onmessage = function (e) {
156        print("message from worker: " + e.data, "blue");
157    }
158    function test(expression)
159    {
160        var buffer = eval(expression);
161        try {
162            var before = externalMemory();
163            worker.postMessage(buffer, [buffer]);
164            var now = externalMemory();
165            if (now > before - MB + noise) {
166                fail("Transfer of " + expression + " did not decrease the amount of external memory (" +
167                     before + ", " + now + ").");
168            } else {
169                pass("Transfer of " + expression + " decreased the amount of external memory.");
170            }
171            collectGarbage();
172            var after = externalMemory();
173            if (after < now - noise) {
174                fail("Garbage collection after transfer of " + expression +
175                     " decreased the amount of external memory (" + now + ", " + after + ").");
176            } else {
177                pass("Garbage collection after transfer of " + expression +
178                     " did not decrease the amount of external memory.");
179            }
180        } catch (e) {
181            fail("Transfer of " + name + ": could not webkitPostMessage: " + e);
182            return false;
183        }
184        return true;
185    }
186    test("(new ArrayBuffer(MB))");
187    test("(new Float32Array(MB)).buffer");
188    test("(new Float64Array(MB)).buffer");
189    test("(new Int8Array(MB)).buffer");
190    test("(new Int16Array(MB)).buffer");
191    test("(new Int32Array(MB)).buffer");
192    test("(new Uint8Array(MB)).buffer");
193    test("(new Uint16Array(MB)).buffer");
194    test("(new Uint32Array(MB)).buffer");
195}
196
197
198function runAll() {
199    log = document.getElementById("log1");
200    if (typeof gc == "undefined" || typeof getV8Statistics == "undefined") {
201        print("Run chrome browser with --js-flags='--expose_gc --track_gc_object_stats'", "red");
202    } else {
203         allocationsThatIncreaseExternalMemory();
204         collectGarbage();
205         allocationsThatDoNotChangeExternalMemory();
206         collectGarbage();
207         log = document.getElementById("log2");
208         transfersThatDecreaseExternalMemory();
209         collectGarbage();
210    }
211}
212
213</script>
214</head>
215<body onload="runAll()">
216<p>This test checks that allocation and deallocation of typed arrays correctly
217adjusts the amount of external memory in V8.</p>
218<div id='log1'></div>
219<p>This test checks that transfer of an array buffer to worker decreases amount of
220external memory in the main V8 isolate.</p>
221<div id='log2'></div>
222</body>
223</html>
224