<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[201813] trunk/PerformanceTests</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/201813">201813</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-06-08 11:13:20 -0700 (Wed, 08 Jun 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Use more ES6 features in JSAir
https://bugs.webkit.org/show_bug.cgi?id=158497
Reviewed by Keith Miller.
This improves JSAir with the following ES6 features suggested by JoePeck:
- String interpolation.
- Destructuring inside PatchCustom.
- Default arguments.
All of these things are on hot paths.
Note that I didn't use string interpolation everywhere that I could, only in those places
where it made the code more readable. In Ruby, I used the style that if the interpolation
expression has any non-trivial stuff (like a ternary operator, a chain of calls, or embedded
strings) then it's better to use regular strcat. I think that's what I carried over to here.
Note that the previous change (Add result validation to JSAir) also made the Proxy code not
dead, though it's not necessarily on the hot path. The Proxy isn't called into frequently
but it's used from a function that is otherwise hot, so if calling into the Proxy prevents
that function from being optimized then it will hurt so good.
I also reenabled tail calls in a few places.
This change doesn't seem to change the performance of the benchmark for us. That's expected
since these ES6 features are cheap. Note that this claim doesn't include Proxy, which was
added in a separate change and that change did make the benchmark overall more expensive.
* JSAir/allocate_stack.js:
(allocateStack):
* JSAir/arg.js:
(Arg.createBitImm64):
(Arg.createAddr):
(Arg.createStack):
(Arg.logScale):
(Arg.createIndex):
* JSAir/basic_block.js:
(BasicBlock.get headerString):
(BasicBlock.prototype.get if):
(BasicBlock):
* JSAir/benchmark.js:
(benchmark):
* JSAir/code.js:
(Code):
(Code.prototype.addBlock):
(Code.prototype.addStackSlot):
(Code.prototype.newTmp):
(Code.prototype.get size):
(Code.prototype.get blocks):
(Code.prototype.get stackSlots):
(Code.prototype.tmps):
(Code.prototype.get callArgAreaSize):
(Code.prototype.toString):
* JSAir/custom.js:
(const.PatchCustom.forEachArg):
* JSAir/inst.js:
(Inst):
* JSAir/reg.js:
(Reg.prototype.toString):
* JSAir/util.js:
(symbolName):
(lowerSymbolName):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkPerformanceTestsChangeLog">trunk/PerformanceTests/ChangeLog</a></li>
<li><a href="#trunkPerformanceTestsJSAirallocate_stackjs">trunk/PerformanceTests/JSAir/allocate_stack.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirargjs">trunk/PerformanceTests/JSAir/arg.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirbasic_blockjs">trunk/PerformanceTests/JSAir/basic_block.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirbenchmarkjs">trunk/PerformanceTests/JSAir/benchmark.js</a></li>
<li><a href="#trunkPerformanceTestsJSAircodejs">trunk/PerformanceTests/JSAir/code.js</a></li>
<li><a href="#trunkPerformanceTestsJSAircustomjs">trunk/PerformanceTests/JSAir/custom.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirinstjs">trunk/PerformanceTests/JSAir/inst.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirregjs">trunk/PerformanceTests/JSAir/reg.js</a></li>
<li><a href="#trunkPerformanceTestsJSAirutiljs">trunk/PerformanceTests/JSAir/util.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkPerformanceTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/ChangeLog (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/ChangeLog        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/ChangeLog        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -1,3 +1,69 @@
</span><ins>+2016-06-08 Filip Pizlo <fpizlo@apple.com>
+
+ Use more ES6 features in JSAir
+ https://bugs.webkit.org/show_bug.cgi?id=158497
+
+ Reviewed by Keith Miller.
+
+ This improves JSAir with the following ES6 features suggested by JoePeck:
+
+ - String interpolation.
+ - Destructuring inside PatchCustom.
+ - Default arguments.
+
+ All of these things are on hot paths.
+
+ Note that I didn't use string interpolation everywhere that I could, only in those places
+ where it made the code more readable. In Ruby, I used the style that if the interpolation
+ expression has any non-trivial stuff (like a ternary operator, a chain of calls, or embedded
+ strings) then it's better to use regular strcat. I think that's what I carried over to here.
+
+ Note that the previous change (Add result validation to JSAir) also made the Proxy code not
+ dead, though it's not necessarily on the hot path. The Proxy isn't called into frequently
+ but it's used from a function that is otherwise hot, so if calling into the Proxy prevents
+ that function from being optimized then it will hurt so good.
+
+ I also reenabled tail calls in a few places.
+
+ This change doesn't seem to change the performance of the benchmark for us. That's expected
+ since these ES6 features are cheap. Note that this claim doesn't include Proxy, which was
+ added in a separate change and that change did make the benchmark overall more expensive.
+
+ * JSAir/allocate_stack.js:
+ (allocateStack):
+ * JSAir/arg.js:
+ (Arg.createBitImm64):
+ (Arg.createAddr):
+ (Arg.createStack):
+ (Arg.logScale):
+ (Arg.createIndex):
+ * JSAir/basic_block.js:
+ (BasicBlock.get headerString):
+ (BasicBlock.prototype.get if):
+ (BasicBlock):
+ * JSAir/benchmark.js:
+ (benchmark):
+ * JSAir/code.js:
+ (Code):
+ (Code.prototype.addBlock):
+ (Code.prototype.addStackSlot):
+ (Code.prototype.newTmp):
+ (Code.prototype.get size):
+ (Code.prototype.get blocks):
+ (Code.prototype.get stackSlots):
+ (Code.prototype.tmps):
+ (Code.prototype.get callArgAreaSize):
+ (Code.prototype.toString):
+ * JSAir/custom.js:
+ (const.PatchCustom.forEachArg):
+ * JSAir/inst.js:
+ (Inst):
+ * JSAir/reg.js:
+ (Reg.prototype.toString):
+ * JSAir/util.js:
+ (symbolName):
+ (lowerSymbolName):
+
</ins><span class="cx"> 2016-06-07 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> Add result validation to JSAir
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirallocate_stackjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/allocate_stack.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/allocate_stack.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/allocate_stack.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -227,8 +227,7 @@
</span><span class="cx"> // zero fills.
</span><span class="cx"> if (slot.byteSize != 8) {
</span><span class="cx"> throw new Error(
</span><del>- "Bad spill slot size for ZDef: " + slot.byteSize + ", width is " +
- width);
</del><ins>+ `Bad spill slot size for ZDef: ${slot.byteSize}, width is ${width}`);
</ins><span class="cx"> }
</span><span class="cx"> if (width != 32)
</span><span class="cx"> throw new Error("Bad width for ZDef");
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirargjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/arg.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/arg.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/arg.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -333,10 +333,8 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- static createAddr(base, offset)
</del><ins>+ static createAddr(base, offset = 0)
</ins><span class="cx"> {
</span><del>- if (offset == null)
- offset = 0;
</del><span class="cx"> let result = new Arg();
</span><span class="cx"> result._kind = Arg.Addr;
</span><span class="cx"> result._base = base;
</span><span class="lines">@@ -344,10 +342,8 @@
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- static createStack(slot, offset)
</del><ins>+ static createStack(slot, offset = 0)
</ins><span class="cx"> {
</span><del>- if (offset == null)
- offset = 0;
</del><span class="cx"> let result = new Arg();
</span><span class="cx"> result._kind = Arg.Stack;
</span><span class="cx"> result._slot = slot;
</span><span class="lines">@@ -400,12 +396,8 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- static createIndex(base, index, scale, offset)
</del><ins>+ static createIndex(base, index, scale = 1, offset = 0)
</ins><span class="cx"> {
</span><del>- if (scale == null)
- scale = 1;
- if (offset == null)
- offset = 0;
</del><span class="cx"> let result = new Arg();
</span><span class="cx"> result._kind = Arg.Index;
</span><span class="cx"> result._base = base;
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirbasic_blockjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/basic_block.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/basic_block.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/basic_block.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -108,7 +108,7 @@
</span><span class="cx"> get headerString()
</span><span class="cx"> {
</span><span class="cx"> let result = "";
</span><del>- result += "BB" + this + ": ; frequency = " + this._frequency + "\n";
</del><ins>+ result += `BB${this}: ; frequency = ${this._frequency}\n`;
</ins><span class="cx"> if (this._predecessors.length)
</span><span class="cx"> result += " Predecessors: " + this._predecessors.join(", ") + "\n";
</span><span class="cx"> return result;
</span><span class="lines">@@ -127,7 +127,7 @@
</span><span class="cx"> let result = "";
</span><span class="cx"> result += this.headerString;
</span><span class="cx"> for (let inst of this)
</span><del>- result += " " + inst + "\n";
</del><ins>+ result += ` ${inst}\n`;
</ins><span class="cx"> result += this.footerString;
</span><span class="cx"> return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirbenchmarkjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/benchmark.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/benchmark.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/benchmark.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -52,7 +52,7 @@
</span><span class="cx">
</span><span class="cx"> let hash = code.hash();
</span><span class="cx"> if (hash != payload.earlyHash)
</span><del>- throw new Error("Wrong early hash for " + payload.generate.name +": " + hash);
</del><ins>+ throw new Error(`Wrong early hash for ${payload.generate.name}: ${hash}`);
</ins><span class="cx">
</span><span class="cx"> allocateStack(code);
</span><span class="cx">
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx">
</span><span class="cx"> hash = code.hash();
</span><span class="cx"> if (hash != payload.lateHash)
</span><del>- throw new Error("Wrong late hash for " + payload.generate.name +": " + hash);
</del><ins>+ throw new Error(`Wrong late hash for ${payload.generate.name}: ${hash}`);
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAircodejs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/code.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/code.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/code.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -35,24 +35,19 @@
</span><span class="cx"> this._frameSize = 0;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- addBlock(frequency)
</del><ins>+ addBlock(frequency = 1)
</ins><span class="cx"> {
</span><del>- if (frequency == null)
- frequency = 1;
- let result = addIndexed(this._blocks, BasicBlock, frequency);
- return result;
</del><ins>+ return addIndexed(this._blocks, BasicBlock, frequency);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> addStackSlot(byteSize, kind)
</span><span class="cx"> {
</span><del>- let result = addIndexed(this._stackSlots, StackSlot, byteSize, kind);
- return result;
</del><ins>+ return addIndexed(this._stackSlots, StackSlot, byteSize, kind);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> newTmp(type)
</span><span class="cx"> {
</span><del>- let result = addIndexed(this["_" + symbolName(type).toLowerCase() + "Tmps"], Tmp, type);
- return result;
</del><ins>+ return addIndexed(this[`_${lowerSymbolName(type)}Tmps`], Tmp, type);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> get size() { return this._blocks.length; }
</span><span class="lines">@@ -66,7 +61,7 @@
</span><span class="cx"> get blocks() { return this._blocks; }
</span><span class="cx"> get stackSlots() { return this._stackSlots; }
</span><span class="cx">
</span><del>- tmps(type) { return this["_" + symbolName(type).toLowerCase() + "Tmps"]; }
</del><ins>+ tmps(type) { return this[`_${lowerSymbolName(type)}Tmps`]; }
</ins><span class="cx">
</span><span class="cx"> get callArgAreaSize() { return this._callArgAreaSize; }
</span><span class="cx">
</span><span class="lines">@@ -116,12 +111,12 @@
</span><span class="cx"> if (this.stackSlots.length) {
</span><span class="cx"> result += "Stack slots:\n";
</span><span class="cx"> for (let slot of this.stackSlots)
</span><del>- result += " " + slot + "\n";
</del><ins>+ result += ` ${slot}\n`;
</ins><span class="cx"> }
</span><span class="cx"> if (this._frameSize)
</span><del>- result += "Frame size: " + this._frameSize + "\n";
</del><ins>+ result += `Frame size: ${this._frameSize}\n`;
</ins><span class="cx"> if (this._callArgAreaSize)
</span><del>- result += "Call arg area size: " + this._callArgAreaSize + "\n";
</del><ins>+ result += `Call arg area size: ${this._callArgAreaSize}\n`;
</ins><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAircustomjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/custom.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/custom.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/custom.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -50,9 +50,8 @@
</span><span class="cx"> forEachArg(inst, func)
</span><span class="cx"> {
</span><span class="cx"> for (let i = 0; i < inst.args.length; ++i) {
</span><del>- inst.visitArg(
- i, func, inst.patchArgData[i].role, inst.patchArgData[i].type,
- inst.patchArgData[i].width);
</del><ins>+ let {type, role, width} = inst.patchArgData[i];
+ inst.visitArg(i, func, role, type, width);
</ins><span class="cx"> }
</span><span class="cx"> },
</span><span class="cx">
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirinstjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/inst.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/inst.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/inst.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -25,10 +25,10 @@
</span><span class="cx"> "use strict";
</span><span class="cx">
</span><span class="cx"> class Inst {
</span><del>- constructor(opcode, args)
</del><ins>+ constructor(opcode, args = [])
</ins><span class="cx"> {
</span><span class="cx"> this._opcode = opcode;
</span><del>- this._args = args == null ? [] : args;
</del><ins>+ this._args = args;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> append(...args)
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirregjs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/reg.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/reg.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/reg.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx">
</span><span class="cx"> toString()
</span><span class="cx"> {
</span><del>- return "%" + this._name;
</del><ins>+ return `%${this._name}`;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> static extract(arg)
</span><span class="lines">@@ -109,12 +109,12 @@
</span><span class="cx"> Reg.rsi = newGPR("rsi");
</span><span class="cx"> Reg.rdi = newGPR("rdi");
</span><span class="cx"> for (let i = 8; i <= 15; ++i)
</span><del>- Reg["r" + i] = newGPR("r" + i, i >= 12);
</del><ins>+ Reg[`r${i}`] = newGPR(`r${i}`, i >= 12);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // Define X86_64 FPRs.
</span><span class="cx"> for (let i = 0; i <= 15; ++i)
</span><del>- Reg["xmm" + i] = newReg(i, FP, "xmm" + i);
</del><ins>+ Reg[`xmm${i}`] = newReg(i, FP, `xmm${i}`);
</ins><span class="cx">
</span><span class="cx"> Reg.gprs = []
</span><span class="cx"> Reg.fprs = []
</span></span></pre></div>
<a id="trunkPerformanceTestsJSAirutiljs"></a>
<div class="modfile"><h4>Modified: trunk/PerformanceTests/JSAir/util.js (201812 => 201813)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/PerformanceTests/JSAir/util.js        2016-06-08 18:03:08 UTC (rev 201812)
+++ trunk/PerformanceTests/JSAir/util.js        2016-06-08 18:13:20 UTC (rev 201813)
</span><span class="lines">@@ -49,6 +49,11 @@
</span><span class="cx"> return fullString.substring("Symbol(".length, fullString.length - ")".length);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+function lowerSymbolName(symbol)
+{
+ return symbolName(symbol).toLowerCase();
+}
+
</ins><span class="cx"> function setToString(set)
</span><span class="cx"> {
</span><span class="cx"> let result = "";
</span></span></pre>
</div>
</div>
</body>
</html>