11cb0ef41Sopenharmony_ci// Copyright 2021 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_ciimport {calcOffsetInVMCage} from '../js/helper.mjs';
61cb0ef41Sopenharmony_ciimport {DOM, FileReader,} from '../js/web-api-helper.mjs';
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ciimport {kSpaceNames} from './space-categories.mjs';
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciclass TraceLogParseHelper {
111cb0ef41Sopenharmony_ci  static re_gc_header = /(Before|After) GC:\d/;
121cb0ef41Sopenharmony_ci  static re_page_info =
131cb0ef41Sopenharmony_ci      /\{owner:.+,address:.+,size:.+,allocated_bytes:.+,wasted_memory:.+\}/;
141cb0ef41Sopenharmony_ci  static re_owner = /(?<=owner:)[a-z_]+_space/;
151cb0ef41Sopenharmony_ci  static re_address = /(?<=address:)0x[a-f0-9]+(?=,)/;
161cb0ef41Sopenharmony_ci  static re_size = /(?<=size:)\d+(?=,)/;
171cb0ef41Sopenharmony_ci  static re_allocated_bytes = /(?<=allocated_bytes:)\d+(?=,)/;
181cb0ef41Sopenharmony_ci  static re_wasted_memory = /(?<=wasted_memory:)\d+(?=})/;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci  static matchGCHeader(content) {
211cb0ef41Sopenharmony_ci    return this.re_gc_header.test(content);
221cb0ef41Sopenharmony_ci  }
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci  static matchPageInfo(content) {
251cb0ef41Sopenharmony_ci    return this.re_page_info.test(content);
261cb0ef41Sopenharmony_ci  }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci  static parsePageInfo(content) {
291cb0ef41Sopenharmony_ci    const owner = this.re_owner.exec(content)[0];
301cb0ef41Sopenharmony_ci    const address =
311cb0ef41Sopenharmony_ci        calcOffsetInVMCage(BigInt(this.re_address.exec(content)[0], 16));
321cb0ef41Sopenharmony_ci    const size = parseInt(this.re_size.exec(content)[0]);
331cb0ef41Sopenharmony_ci    const allocated_bytes = parseInt(this.re_allocated_bytes.exec(content)[0]);
341cb0ef41Sopenharmony_ci    const wasted_memory = parseInt(this.re_wasted_memory.exec(content)[0]);
351cb0ef41Sopenharmony_ci    const info = [
361cb0ef41Sopenharmony_ci      owner,
371cb0ef41Sopenharmony_ci      address,
381cb0ef41Sopenharmony_ci      address + size,
391cb0ef41Sopenharmony_ci      allocated_bytes,
401cb0ef41Sopenharmony_ci      wasted_memory,
411cb0ef41Sopenharmony_ci    ];
421cb0ef41Sopenharmony_ci    return info;
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  // Create a empty snapshot.
461cb0ef41Sopenharmony_ci  static createSnapShotData() {
471cb0ef41Sopenharmony_ci    let snapshot = {header: null, data: {}};
481cb0ef41Sopenharmony_ci    for (let space_name of kSpaceNames) {
491cb0ef41Sopenharmony_ci      snapshot.data[space_name] = [];
501cb0ef41Sopenharmony_ci    }
511cb0ef41Sopenharmony_ci    return snapshot;
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  static createModelFromV8TraceFile(contents) {
551cb0ef41Sopenharmony_ci    let snapshots = [];
561cb0ef41Sopenharmony_ci    let snapshot = this.createSnapShotData();
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci    // Fill data info a snapshot, then push it into snapshots.
591cb0ef41Sopenharmony_ci    for (let content of contents) {
601cb0ef41Sopenharmony_ci      if (this.matchGCHeader(content)) {
611cb0ef41Sopenharmony_ci        if (snapshot.header != null) {
621cb0ef41Sopenharmony_ci          snapshots.push(snapshot);
631cb0ef41Sopenharmony_ci        }
641cb0ef41Sopenharmony_ci        snapshot = this.createSnapShotData();
651cb0ef41Sopenharmony_ci        snapshot.header = content;
661cb0ef41Sopenharmony_ci        continue;
671cb0ef41Sopenharmony_ci      }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci      if (this.matchPageInfo(content)) {
701cb0ef41Sopenharmony_ci        let pageinfo = this.parsePageInfo(content);
711cb0ef41Sopenharmony_ci        try {
721cb0ef41Sopenharmony_ci          snapshot.data[pageinfo[0]].push(pageinfo);
731cb0ef41Sopenharmony_ci        } catch (e) {
741cb0ef41Sopenharmony_ci          console.error(e);
751cb0ef41Sopenharmony_ci        }
761cb0ef41Sopenharmony_ci      }
771cb0ef41Sopenharmony_ci    }
781cb0ef41Sopenharmony_ci    // EOL, push the last.
791cb0ef41Sopenharmony_ci    if (snapshot.header != null) {
801cb0ef41Sopenharmony_ci      snapshots.push(snapshot);
811cb0ef41Sopenharmony_ci    }
821cb0ef41Sopenharmony_ci    return snapshots;
831cb0ef41Sopenharmony_ci  }
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ciDOM.defineCustomElement('../js/log-file-reader', 'trace-file-reader',
871cb0ef41Sopenharmony_ci                        (templateText) =>
881cb0ef41Sopenharmony_ci                            class TraceFileReader extends FileReader {
891cb0ef41Sopenharmony_ci  constructor() {
901cb0ef41Sopenharmony_ci    super(templateText);
911cb0ef41Sopenharmony_ci    this.fullDataFromFile = '';
921cb0ef41Sopenharmony_ci    this.addEventListener('fileuploadchunk', (e) => this.handleLoadChunk(e));
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci    this.addEventListener('fileuploadend', (e) => this.handleLoadEnd(e));
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  handleLoadChunk(event) {
981cb0ef41Sopenharmony_ci    this.fullDataFromFile += event.detail;
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  handleLoadEnd(event) {
1021cb0ef41Sopenharmony_ci    let contents = this.fullDataFromFile.split('\n');
1031cb0ef41Sopenharmony_ci    let snapshots = TraceLogParseHelper.createModelFromV8TraceFile(contents);
1041cb0ef41Sopenharmony_ci    this.dispatchEvent(new CustomEvent('change', {
1051cb0ef41Sopenharmony_ci      bubbles: true,
1061cb0ef41Sopenharmony_ci      composed: true,
1071cb0ef41Sopenharmony_ci      detail: snapshots,
1081cb0ef41Sopenharmony_ci    }));
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci});
111