11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci(() => {
61cb0ef41Sopenharmony_ci  let all_profiles = [];
71cb0ef41Sopenharmony_ci  let instanceMap = new WeakMap();
81cb0ef41Sopenharmony_ci  let instanceCounter = 0;
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci  function instrument(imports, profile) {
111cb0ef41Sopenharmony_ci    let orig_imports = imports;
121cb0ef41Sopenharmony_ci    return new Proxy(imports, {
131cb0ef41Sopenharmony_ci      get: (obj, module_name) => {
141cb0ef41Sopenharmony_ci        let orig_module = orig_imports[module_name];
151cb0ef41Sopenharmony_ci        return new Proxy(orig_module, {
161cb0ef41Sopenharmony_ci          get: (obj, item_name) => {
171cb0ef41Sopenharmony_ci            let orig_func = orig_module[item_name];
181cb0ef41Sopenharmony_ci            let item = orig_func;
191cb0ef41Sopenharmony_ci            if (typeof orig_func == "function") {
201cb0ef41Sopenharmony_ci              var full_name = module_name + "." + item_name;
211cb0ef41Sopenharmony_ci              print("instrumented " + full_name);
221cb0ef41Sopenharmony_ci              profile[full_name] = {name: full_name, count: 0, total: 0};
231cb0ef41Sopenharmony_ci              item = function profiled_func(...args) {
241cb0ef41Sopenharmony_ci                var before = performance.now();
251cb0ef41Sopenharmony_ci                var result = orig_func(...args);
261cb0ef41Sopenharmony_ci                var delta = performance.now() - before;
271cb0ef41Sopenharmony_ci                var data = profile[full_name];
281cb0ef41Sopenharmony_ci                data.count++;
291cb0ef41Sopenharmony_ci                data.total += delta;
301cb0ef41Sopenharmony_ci                return result;
311cb0ef41Sopenharmony_ci              }
321cb0ef41Sopenharmony_ci            }
331cb0ef41Sopenharmony_ci            return item;
341cb0ef41Sopenharmony_ci          }
351cb0ef41Sopenharmony_ci        })
361cb0ef41Sopenharmony_ci      }
371cb0ef41Sopenharmony_ci    });
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  function dumpProfile(profile) {
411cb0ef41Sopenharmony_ci    let array = [];
421cb0ef41Sopenharmony_ci    for (let key in profile) {
431cb0ef41Sopenharmony_ci      if (key == "instanceNum") continue;
441cb0ef41Sopenharmony_ci      let data = profile[key];
451cb0ef41Sopenharmony_ci      if (data.count == 0) continue;
461cb0ef41Sopenharmony_ci      array.push(data);
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci    print(`--- Import profile for instance ${profile.instanceNum} ---`);
491cb0ef41Sopenharmony_ci    if (array.length == 0) return;
501cb0ef41Sopenharmony_ci    array.sort((a, b) => b.total - a.total);
511cb0ef41Sopenharmony_ci    for (let data of array) {
521cb0ef41Sopenharmony_ci      print(`${padl(data.name, 30)}: ${padr(data.count, 10)} ${padp(data.total, 10)}ms`);
531cb0ef41Sopenharmony_ci    }
541cb0ef41Sopenharmony_ci  }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  function padl(s, len) {
571cb0ef41Sopenharmony_ci    s = s.toString();
581cb0ef41Sopenharmony_ci    while (s.length < len) s = s + " ";
591cb0ef41Sopenharmony_ci    return s;
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci  function padr(s, len) {
621cb0ef41Sopenharmony_ci    s = s.toString();
631cb0ef41Sopenharmony_ci    while (s.length < len) s = " " + s;
641cb0ef41Sopenharmony_ci    return s;
651cb0ef41Sopenharmony_ci  }
661cb0ef41Sopenharmony_ci  function padp(s, len) {
671cb0ef41Sopenharmony_ci    s = s.toString();
681cb0ef41Sopenharmony_ci    var i = s.indexOf(".");
691cb0ef41Sopenharmony_ci    if (i == -1) i = s.length;
701cb0ef41Sopenharmony_ci    while (i++ < len) s = " " + s;
711cb0ef41Sopenharmony_ci    return s;
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  // patch: WebAssembly.instantiate (async)
751cb0ef41Sopenharmony_ci  let orig_instantiate = WebAssembly.instantiate;
761cb0ef41Sopenharmony_ci  WebAssembly.instantiate = (m, imports, ...args) => {
771cb0ef41Sopenharmony_ci    let profile = {};
781cb0ef41Sopenharmony_ci    let promise = orig_instantiate(m, instrument(imports, profile), ...args);
791cb0ef41Sopenharmony_ci    promise.then((instance) => {
801cb0ef41Sopenharmony_ci      instanceMap.set(instance, profile);
811cb0ef41Sopenharmony_ci      all_profiles.push(profile);
821cb0ef41Sopenharmony_ci      profile.instanceNum = instanceCounter++;
831cb0ef41Sopenharmony_ci    });
841cb0ef41Sopenharmony_ci    return promise;
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // patch: new WebAssembly.Instance (sync)
881cb0ef41Sopenharmony_ci  let orig_new_instance = WebAssembly.Instance;
891cb0ef41Sopenharmony_ci  WebAssembly.Instance = new Proxy(orig_new_instance, {
901cb0ef41Sopenharmony_ci    construct: (target, args) => {
911cb0ef41Sopenharmony_ci      let profile = {};
921cb0ef41Sopenharmony_ci      args[1] = instrument(args[1], profile);
931cb0ef41Sopenharmony_ci      let instance = new orig_new_instance(...args);
941cb0ef41Sopenharmony_ci      instanceMap.set(instance, profile);
951cb0ef41Sopenharmony_ci      all_profiles.push(profile);
961cb0ef41Sopenharmony_ci      profile.instanceNum = instanceCounter++;
971cb0ef41Sopenharmony_ci      return instance;
981cb0ef41Sopenharmony_ci    }
991cb0ef41Sopenharmony_ci  });
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  // expose: WebAssembly.dumpProfile(instance)
1021cb0ef41Sopenharmony_ci  WebAssembly.dumpProfile = (instance) => {
1031cb0ef41Sopenharmony_ci    let profile = instanceMap.get(instance);
1041cb0ef41Sopenharmony_ci    if (profile === undefined) return;
1051cb0ef41Sopenharmony_ci    dumpProfile(profile);
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci  // expose: WebAssembly.clearProfile(instance)
1081cb0ef41Sopenharmony_ci  WebAssembly.clearProfile = (instance) => {
1091cb0ef41Sopenharmony_ci    let profile = instanceMap.get(instance);
1101cb0ef41Sopenharmony_ci    if (profile === undefined) return;
1111cb0ef41Sopenharmony_ci    for (let key in profile) {
1121cb0ef41Sopenharmony_ci      if (key == "instanceNum") continue;
1131cb0ef41Sopenharmony_ci      let data = p[key];
1141cb0ef41Sopenharmony_ci      data.count = 0;
1151cb0ef41Sopenharmony_ci      data.total = 0;
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci  // expose: WebAssembly.dumpAllProfiles()
1191cb0ef41Sopenharmony_ci  WebAssembly.dumpAllProfiles = () => {
1201cb0ef41Sopenharmony_ci    for (let profile of all_profiles) dumpProfile(profile);
1211cb0ef41Sopenharmony_ci  }
1221cb0ef41Sopenharmony_ci  // expose: WebAssembly.getProfile(instance)
1231cb0ef41Sopenharmony_ci  // returns: {
1241cb0ef41Sopenharmony_ci  //    func_name1: {name: func_name1, count: <num>, total: <num>}
1251cb0ef41Sopenharmony_ci  //    func_name2: {name: func_name1, count: <num>, total: <num>}
1261cb0ef41Sopenharmony_ci  //    ...
1271cb0ef41Sopenharmony_ci  // }
1281cb0ef41Sopenharmony_ci  WebAssembly.getProfile = (instance) => {
1291cb0ef41Sopenharmony_ci    return instanceMap.get(instance);
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci})();
132