Merge branch 'master' into mg/async_tweaks

This commit is contained in:
Matt Godbolt
2020-02-05 07:54:55 -06:00
10 changed files with 93 additions and 28 deletions

View File

@@ -1,6 +1,6 @@
# Contributing to Compiler Explorer
First of, if you're reading this: thank you! Even considering contributing to
First off, if you're reading this: thank you! Even considering contributing to
**Compiler Explorer** is very much appreciated!
Before we go too far, an apology: **Compiler Explorer** grew out of a bit of
hacky JavaScript into a pretty large and well-used project pretty quickly.

16
app.js
View File

@@ -40,6 +40,7 @@ const nopt = require('nopt'),
urljoin = require('url-join'),
_ = require('underscore'),
express = require('express'),
responseTime = require('response-time'),
Sentry = require('@sentry/node'),
{logger, logToPapertrail, suppressConsoleLog} = require('./lib/logger'),
utils = require('./lib/utils'),
@@ -462,16 +463,30 @@ async function main() {
rescanCompilerSecs * 1000);
}
const sentrySlowRequestMs = ceProps("sentrySlowRequestMs", 0);
webServer
.set('trust proxy', true)
.set('view engine', 'pug')
.on('error', err => logger.error('Caught error in web handler; continuing:', err))
// sentry request handler must be the first middleware on the app
.use(Sentry.Handlers.requestHandler())
// eslint-disable-next-line no-unused-vars
.use(responseTime((req, res, time) => {
if (sentrySlowRequestMs > 0 && time >= sentrySlowRequestMs) {
Sentry.withScope(scope => {
scope.setExtra('duration_ms', time);
Sentry.captureMessage('SlowRequest', 'warning');
});
}
}))
// Handle healthchecks at the root, as they're not expected from the outside world
.use('/healthcheck', new healthCheck.HealthCheckHandler(healthCheckFilePath).handle)
.use(httpRoot, router)
.use((req, res, next) => {
next({status: 404, message: `page "${req.path}" could not be found`});
})
// sentry error handler must be the first error handling middleware
.use(Sentry.Handlers.errorHandler)
// eslint-disable-next-line no-unused-vars
.use((err, req, res) => {
@@ -565,7 +580,6 @@ async function main() {
});
router
.use(Sentry.Handlers.requestHandler())
.use(morgan(morganFormat, {
stream: logger.stream,
// Skip for non errors (2xx, 3xx)

View File

@@ -28,4 +28,5 @@ eventLoopLagThresholdWarn=100
eventLoopLagThresholdErr=1000
staticUrl=https://static.ce-cdn.net/
sentryEnvironment=prod
sentryEnvironment=prod
sentrySlowRequestMs=20000

View File

@@ -2,7 +2,7 @@ compilers=&swift
demangler=/opt/compiler-explorer/swift-5.1/usr/bin/swift-demangle
defaultCompiler=swift51
group.swift.compilers=swift311:swift402:swift403:swift41:swift411:swift412:swift42:swift50:swift51
group.swift.compilers=swift311:swift402:swift403:swift41:swift411:swift412:swift42:swift50:swift51:swiftnightly
group.swift.isSemVer=true
group.swift.baseName=x86-64 swiftc
compiler.swift311.exe=/opt/compiler-explorer/swift-3.1.1/usr/bin/swiftc
@@ -23,7 +23,8 @@ compiler.swift50.exe=/opt/compiler-explorer/swift-5.0/usr/bin/swiftc
compiler.swift50.semver=5.0
compiler.swift51.exe=/opt/compiler-explorer/swift-5.1/usr/bin/swiftc
compiler.swift51.semver=5.1
compiler.swiftnightly.exe=/opt/compiler-explorer/swift-nightly/usr/bin/swiftc
compiler.swiftnightly.semver=nightly
#################################
#################################

View File

@@ -141,17 +141,14 @@ class Demangler extends AsmRegex {
* @param {string} translation
*/
addTranslation(symbol, translation) {
let metadataStr = "";
if (this.includeMetadata) {
const metadata = this.getMetadata(symbol);
metadataStr = metadata.map((meta) => " [" + meta.description + "]").join();
translation += this.getMetadata(symbol).map((meta) => " [" + meta.description + "]").join();
}
if (this.symbolstore.contains(symbol)) {
this.symbolstore.add(symbol, translation + metadataStr);
this.symbolstore.add(symbol, translation);
} else {
this.othersymbols.add(symbol, translation + metadataStr);
this.othersymbols.add(symbol, translation);
}
}
@@ -165,27 +162,19 @@ class Demangler extends AsmRegex {
for (let i = 0; i < lines.length; ++i)
this.addTranslation(this.input[i], lines[i]);
let translations = [];
translations = translations.concat(this.symbolstore.listTranslations());
translations = translations.concat(this.othersymbols.listTranslations());
const translations = [...this.symbolstore.listTranslations(), ...this.othersymbols.listTranslations()]
.filter(elem => elem[0] !== elem[1]);
for (let i = 0; i < this.result.asm.length; ++i) {
let line = this.result.asm[i].text;
for (let j = 0; j < translations.length; ++j) {
const oldValue = translations[j][0];
const newValue = translations[j][1];
line = line.replace(oldValue, newValue);
line = line.replace(oldValue, newValue);
this.demangleLabels(this.result.asm[i].labels,
oldValue, newValue);
for (const asm of this.result.asm) {
let line = asm.text;
for (const [oldValue, newValue] of translations) {
line = utils.replaceAll(line, oldValue, newValue);
this.demangleLabels(asm.labels, oldValue, newValue);
}
this.result.asm[i].text = line;
asm.text = line;
}
this.demangleLabelDefinitions(
this.result.labelDefinitions, translations);
this.demangleLabelDefinitions(this.result.labelDefinitions, translations);
return this.result;
}

View File

@@ -205,3 +205,18 @@ exports.toProperty = function toProperty(prop) {
if (prop.match(/^-?[0-9]*\.[0-9]+$/)) return parseFloat(prop);
return prop;
};
// This function replaces all the "oldValues" in line with "newValue". It handles overlapping string replacement cases,
// and is careful to return the exact same line object if there's no matches. This turns out to be super important for
// performance.
exports.replaceAll = function replaceAll(line, oldValue, newValue) {
if (oldValue.length === 0) return line;
let startPoint = 0;
for (; ;) {
const index = line.indexOf(oldValue, startPoint);
if (index === -1) break;
line = line.substr(0, index) + newValue + line.substr(index + oldValue.length);
startPoint = index + newValue.length;
}
return line;
};

9
package-lock.json generated
View File

@@ -7473,6 +7473,15 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true
},
"response-time": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/response-time/-/response-time-2.3.2.tgz",
"integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=",
"requires": {
"depd": "~1.1.0",
"on-headers": "~1.0.1"
}
},
"restore-cursor": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",

View File

@@ -53,6 +53,7 @@
"promise-queue": "2.2.3",
"pug": "^2.0.4",
"request": "^2.88.0",
"response-time": "^2.3.2",
"selectize": "0.12.4",
"semver": "^5.7.1",
"serve-favicon": "^2.4.5",

View File

@@ -83,6 +83,10 @@
<li>Nathan Bronson</li>
<li>Kaz Tros</li>
<li>Jean-François</li>
<li>Charles Wilkes</li>
<li>Kaido Kert</li>
<li>Carsten Schultz</li>
<li>Cornel Izbasa</li>
<li>Stefan Groth</li>
<li>Sorin Suciu</li>
<li>Andreas Gravgaard Andersen</li>

View File

@@ -319,3 +319,34 @@ describe('squashes horizontal whitespace', () => {
utils.squashHorizontalWhitespace(' abc abc').should.equals(' abc abc');
});
});
describe('replaces all substrings', () => {
it('works with no substitutions', () => {
const string = "This is a line with no replacements";
utils.replaceAll(string, "not present", "won't be substituted").should.equal(string);
});
it('handles odd cases', () => {
utils.replaceAll("", "", "").should.equal("");
utils.replaceAll("Hello", "", "").should.equal("Hello");
});
it('works with single replacement', () => {
utils.replaceAll("This is a line with a mistook in it", "mistook", "mistake")
.should.equal("This is a line with a mistake in it");
utils.replaceAll("This is a line with a mistook", "mistook", "mistake")
.should.equal("This is a line with a mistake");
utils.replaceAll("Mistooks were made", "Mistooks", "Mistakes")
.should.equal("Mistakes were made");
});
it('works with multiple replacements', () => {
utils.replaceAll("A mistook is a mistook", "mistook", "mistake")
.should.equal("A mistake is a mistake");
utils.replaceAll("aaaaaaaaaaaaaaaaaaaaaaaaaaa", "a", "b")
.should.equal("bbbbbbbbbbbbbbbbbbbbbbbbbbb");
});
it('works with overlapping replacements', () => {
utils.replaceAll("aaaaaaaa", "a", "ba")
.should.equal("babababababababa");
});
});