// micro_ops.cm — microbenchmarks for core operations function blackhole(sink, x) { return (sink + (x | 0)) | 0 } function make_obj_xy(x, y) { return {x: x, y: y} } function make_obj_yx(x, y) { // Different insertion order to force a different shape return {y: y, x: x} } function make_shapes(n) { var out = [] var i = 0 var o = null for (i = 0; i < n; i++) { o = {a: i} o[`p${i}`] = i push(out, o) } return out } function make_packed_array(n) { var a = [] var i = 0 for (i = 0; i < n; i++) push(a, i) return a } function make_holey_array(n) { var a = [] var i = 0 for (i = 0; i < n; i += 2) a[i] = i return a } return { // 0) Baseline loop cost loop_empty: function(n) { var sink = 0 var i = 0 for (i = 0; i < n; i++) {} return blackhole(sink, n) }, // 1) Numeric pipelines i32_add: function(n) { var sink = 0 var x = 1 var i = 0 for (i = 0; i < n; i++) x = (x + 3) | 0 return blackhole(sink, x) }, f64_add: function(n) { var sink = 0 var x = 1.0 var i = 0 for (i = 0; i < n; i++) x = x + 3.14159 return blackhole(sink, x | 0) }, mixed_add: function(n) { var sink = 0 var x = 1 var i = 0 for (i = 0; i < n; i++) x = x + 0.25 return blackhole(sink, x | 0) }, bit_ops: function(n) { var sink = 0 var x = 0x12345678 var i = 0 for (i = 0; i < n; i++) x = ((x << 5) ^ (x >>> 3)) | 0 return blackhole(sink, x) }, overflow_path: function(n) { var sink = 0 var x = 0x70000000 var i = 0 for (i = 0; i < n; i++) x = (x + 0x10000000) | 0 return blackhole(sink, x) }, // 2) Branching branch_predictable: function(n) { var sink = 0 var x = 0 var i = 0 for (i = 0; i < n; i++) { if ((i & 7) != 0) x++ else x += 2 } return blackhole(sink, x) }, branch_alternating: function(n) { var sink = 0 var x = 0 var i = 0 for (i = 0; i < n; i++) { if ((i & 1) == 0) x++ else x += 2 } return blackhole(sink, x) }, // 3) Calls call_direct: function(n) { var sink = 0 var f = function(a) { return (a + 1) | 0 } var x = 0 var i = 0 for (i = 0; i < n; i++) x = f(x) return blackhole(sink, x) }, call_indirect: function(n) { var sink = 0 var f = function(a) { return (a + 1) | 0 } var g = f var x = 0 var i = 0 for (i = 0; i < n; i++) x = g(x) return blackhole(sink, x) }, call_closure: function(n) { var sink = 0 var make_adder = function(k) { return function(a) { return (a + k) | 0 } } var add3 = make_adder(3) var x = 0 var i = 0 for (i = 0; i < n; i++) x = add3(x) return blackhole(sink, x) }, call_multi_arity: function(n) { var sink = 0 var f0 = function() { return 1 } var f1 = function(a) { return a + 1 } var f2 = function(a, b) { return a + b } var f3 = function(a, b, c) { return a + b + c } var f4 = function(a, b, c, d) { return a + b + c + d } var x = 0 var i = 0 for (i = 0; i < n; i++) { x = (x + f0() + f1(i) + f2(i, 1) + f3(i, 1, 2) + f4(i, 1, 2, 3)) | 0 } return blackhole(sink, x) }, // 4) Object props (ICs / shapes) prop_read_mono: function(n) { var sink = 0 var o = make_obj_xy(1, 2) var x = 0 var i = 0 for (i = 0; i < n; i++) x = (x + o.x) | 0 return blackhole(sink, x) }, prop_read_poly_2: function(n) { var sink = 0 var a = make_obj_xy(1, 2) var b = make_obj_yx(1, 2) var x = 0 var i = 0 var o = null for (i = 0; i < n; i++) { o = (i & 1) == 0 ? a : b x = (x + o.x) | 0 } return blackhole(sink, x) }, prop_read_poly_4: function(n) { var sink = 0 var shapes = [ {x: 1, y: 2}, {y: 2, x: 1}, {x: 1, z: 3, y: 2}, {w: 0, x: 1, y: 2} ] var x = 0 var i = 0 for (i = 0; i < n; i++) { x = (x + shapes[i & 3].x) | 0 } return blackhole(sink, x) }, prop_read_mega: function(n) { var sink = 0 var objs = make_shapes(32) var x = 0 var i = 0 for (i = 0; i < n; i++) { x = (x + objs[i & 31].a) | 0 } return blackhole(sink, x) }, prop_write_mono: function(n) { var sink = 0 var o = make_obj_xy(1, 2) var i = 0 for (i = 0; i < n; i++) o.x = (o.x + 1) | 0 return blackhole(sink, o.x) }, // 5) Arrays array_read_packed: function(n) { var sink = 0 var a = make_packed_array(1024) var x = 0 var i = 0 for (i = 0; i < n; i++) x = (x + a[i & 1023]) | 0 return blackhole(sink, x) }, array_write_packed: function(n) { var sink = 0 var a = make_packed_array(1024) var i = 0 for (i = 0; i < n; i++) a[i & 1023] = i return blackhole(sink, a[17] | 0) }, array_read_holey: function(n) { var sink = 0 var a = make_holey_array(2048) var x = 0 var i = 0 var v = null for (i = 0; i < n; i++) { v = a[(i & 2047)] if (v) x = (x + v) | 0 } return blackhole(sink, x) }, array_push_steady: function(n) { var sink = 0 var x = 0 var j = 0 var i = 0 var a = null for (j = 0; j < n; j++) { a = [] for (i = 0; i < 256; i++) push(a, i) x = (x + length(a)) | 0 } return blackhole(sink, x) }, array_push_pop: function(n) { var sink = 0 var a = [] var x = 0 var i = 0 var v = 0 for (i = 0; i < n; i++) { push(a, i) if (length(a) > 64) { v = a[] x = (x + v) | 0 } } return blackhole(sink, x) }, array_indexed_sum: function(n) { var sink = 0 var a = make_packed_array(1024) var x = 0 var j = 0 var i = 0 for (j = 0; j < n; j++) { x = 0 for (i = 0; i < 1024; i++) { x = (x + a[i]) | 0 } } return blackhole(sink, x) }, // 6) Strings string_concat_small: function(n) { var sink = 0 var x = 0 var j = 0 var i = 0 var s = null for (j = 0; j < n; j++) { s = "" for (i = 0; i < 16; i++) s = s + "x" x = (x + length(s)) | 0 } return blackhole(sink, x) }, string_concat_medium: function(n) { var sink = 0 var x = 0 var j = 0 var i = 0 var s = null for (j = 0; j < n; j++) { s = "" for (i = 0; i < 100; i++) s = s + "abcdefghij" x = (x + length(s)) | 0 } return blackhole(sink, x) }, string_interpolation: function(n) { var sink = 0 var x = 0 var i = 0 var s = null for (i = 0; i < n; i++) { s = `item_${i}_value_${i * 2}` x = (x + length(s)) | 0 } return blackhole(sink, x) }, string_slice: function(n) { var sink = 0 var base = "the quick brown fox jumps over the lazy dog" var x = 0 var i = 0 var s = null for (i = 0; i < n; i++) { s = text(base, i % 10, i % 10 + 10) x = (x + length(s)) | 0 } return blackhole(sink, x) }, // 7) Allocation / GC pressure alloc_tiny_objects: function(n) { var sink = 0 var x = 0 var i = 0 var o = null for (i = 0; i < n; i++) { o = {a: i, b: i + 1, c: i + 2} x = (x + o.b) | 0 } return blackhole(sink, x) }, alloc_linked_list: function(n) { var sink = 0 var head = null var i = 0 var x = 0 var p = null for (i = 0; i < n; i++) head = {v: i, next: head} x = 0 p = head while (p) { x = (x + p.v) | 0 p = p.next } return blackhole(sink, x) }, alloc_arrays: function(n) { var sink = 0 var x = 0 var i = 0 var a = null for (i = 0; i < n; i++) { a = [i, i + 1, i + 2, i + 3] x = (x + a[2]) | 0 } return blackhole(sink, x) }, alloc_short_lived: function(n) { var sink = 0 var x = 0 var i = 0 var o = null // Allocate objects that immediately become garbage for (i = 0; i < n; i++) { o = {val: i, data: {inner: i + 1}} x = (x + o.data.inner) | 0 } return blackhole(sink, x) }, alloc_long_lived_pressure: function(n) { var sink = 0 var store = [] var x = 0 var i = 0 var o = null // Keep first 1024 objects alive, churn the rest for (i = 0; i < n; i++) { o = {val: i, data: i * 2} if (i < 1024) { push(store, o) } x = (x + o.data) | 0 } return blackhole(sink, x) }, // 8) Meme (prototype clone) meme_clone_read: function(n) { var sink = 0 var base = {x: 1, y: 2} var x = 0 var i = 0 var o = null for (i = 0; i < n; i++) { o = meme(base) x = (x + o.x) | 0 } return blackhole(sink, x) }, // 9) Guard / type check paths guard_hot_number: function(n) { // Monomorphic number path — guards should hoist var sink = 0 var x = 1 var i = 0 for (i = 0; i < n; i++) x = x + 1 return blackhole(sink, x | 0) }, guard_mixed_types: function(n) { // Alternating number/text — guards must stay var sink = 0 var vals = [1, "a", 2, "b", 3, "c", 4, "d"] var x = 0 var i = 0 for (i = 0; i < n; i++) { if (is_number(vals[i & 7])) x = (x + vals[i & 7]) | 0 } return blackhole(sink, x) }, // 10) Reduce / higher-order reduce_sum: function(n) { var sink = 0 var a = make_packed_array(256) var x = 0 var i = 0 for (i = 0; i < n; i++) { x = (x + reduce(a, function(acc, v) { return acc + v }, 0)) | 0 } return blackhole(sink, x) }, filter_evens: function(n) { var sink = 0 var a = make_packed_array(256) var x = 0 var i = 0 for (i = 0; i < n; i++) { x = (x + length(filter(a, function(v) { return v % 2 == 0 }))) | 0 } return blackhole(sink, x) }, arrfor_sum: function(n) { var sink = 0 var a = make_packed_array(256) var x = 0 var i = 0 var sum = 0 for (i = 0; i < n; i++) { sum = 0 arrfor(a, function(v) { sum += v }) x = (x + sum) | 0 } return blackhole(sink, x) } }