Skip to content

Commit 43aa7fc

Browse files
authored
Mozilla bug 1861010 - Improve nsHTMLAttributeName performance for non-interned attributes. (#89)
1 parent 756e6ff commit 43aa7fc

File tree

9 files changed

+228
-74
lines changed

9 files changed

+228
-74
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2023 Mozilla Foundation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20+
* DEALINGS IN THE SOFTWARE.
21+
*/
22+
23+
package nu.validator.htmlparser.annotation;
24+
import java.lang.annotation.Target;
25+
import java.lang.annotation.ElementType;
26+
27+
/**
28+
* The array member marked with this annotation will be inline.
29+
*
30+
* @version $Id$
31+
* @author Emilio Cobos Álvarez <[email protected]>
32+
*/
33+
@Target(ElementType.FIELD)
34+
public @interface CppInlineLength {
35+
int value();
36+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2023 Mozilla Foundation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20+
* DEALINGS IN THE SOFTWARE.
21+
*/
22+
23+
package nu.validator.htmlparser.annotation;
24+
25+
/**
26+
* The local name of an element or attribute. Must be comparable with
27+
* <code>==</code> (interned <code>String</code> in Java).
28+
*
29+
* @version $Id$
30+
* @author Emilio Cobos Álvarez <[email protected]>
31+
*/
32+
public @interface StaticLocal {
33+
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2023 Mozilla Foundation
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20+
* DEALINGS IN THE SOFTWARE.
21+
*/
22+
23+
package nu.validator.htmlparser.annotation;
24+
25+
/**
26+
* The local name of an element or attribute. Must be comparable with
27+
* <code>==</code> (interned <code>String</code> in Java).
28+
*
29+
* @version $Id$
30+
* @author Emilio Cobos Álvarez <[email protected]>
31+
*/
32+
public @interface WeakLocal {
33+
34+
}

src/nu/validator/htmlparser/impl/AttributeName.java

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
import java.util.LinkedList;
2828
import java.util.List;
2929

30+
import nu.validator.htmlparser.annotation.CppInlineLength;
3031
import nu.validator.htmlparser.annotation.Inline;
3132
import nu.validator.htmlparser.annotation.Local;
33+
import nu.validator.htmlparser.annotation.StaticLocal;
34+
import nu.validator.htmlparser.annotation.WeakLocal;
3235
import nu.validator.htmlparser.annotation.NoLength;
3336
import nu.validator.htmlparser.annotation.NsUri;
3437
import nu.validator.htmlparser.annotation.Prefix;
@@ -66,6 +69,8 @@ public final class AttributeName
6669
// ]NOCPP]
6770
};
6871

72+
// CPPONLY: static final @NoLength @StaticLocal String[] SAME_LOCAL_NULL = { null, null, null, };
73+
6974
/**
7075
* An array that has no namespace for the HTML mode but the XMLNS namespace
7176
* for the SVG and MathML modes.
@@ -181,9 +186,9 @@ public final class AttributeName
181186
* the name for the SVG mode
182187
* @return the initialized name array
183188
*/
184-
private static @NoLength @Local String[] SVG_DIFFERENT(@Local String name,
185-
@Local String camel) {
186-
@NoLength @Local String[] arr = new String[4];
189+
private static @NoLength @StaticLocal String[] SVG_DIFFERENT(@StaticLocal String name,
190+
@StaticLocal String camel) {
191+
@NoLength @StaticLocal String[] arr = new String[4];
187192
arr[0] = name;
188193
arr[1] = name;
189194
arr[2] = camel;
@@ -203,9 +208,9 @@ public final class AttributeName
203208
* the name for the MathML mode
204209
* @return the initialized name array
205210
*/
206-
private static @NoLength @Local String[] MATH_DIFFERENT(@Local String name,
207-
@Local String camel) {
208-
@NoLength @Local String[] arr = new String[4];
211+
private static @NoLength @StaticLocal String[] MATH_DIFFERENT(@StaticLocal String name,
212+
@StaticLocal String camel) {
213+
@NoLength @StaticLocal String[] arr = new String[4];
209214
arr[0] = name;
210215
arr[1] = camel;
211216
arr[2] = name;
@@ -225,9 +230,9 @@ public final class AttributeName
225230
* the name for the SVG and MathML modes
226231
* @return the initialized name array
227232
*/
228-
private static @NoLength @Local String[] COLONIFIED_LOCAL(
229-
@Local String name, @Local String suffix) {
230-
@NoLength @Local String[] arr = new String[4];
233+
private static @NoLength @StaticLocal String[] COLONIFIED_LOCAL(
234+
@StaticLocal String name, @StaticLocal String suffix) {
235+
@NoLength @StaticLocal String[] arr = new String[4];
231236
arr[0] = name;
232237
arr[1] = suffix;
233238
arr[2] = suffix;
@@ -244,8 +249,8 @@ public final class AttributeName
244249
* the name
245250
* @return the initialized name array
246251
*/
247-
static @NoLength @Local String[] SAME_LOCAL(@Local String name) {
248-
@NoLength @Local String[] arr = new String[4];
252+
static @NoLength @StaticLocal String[] SAME_LOCAL(@StaticLocal String name) {
253+
@NoLength @StaticLocal String[] arr = new String[4];
249254
arr[0] = name;
250255
arr[1] = name;
251256
arr[2] = name;
@@ -376,17 +381,20 @@ public final class AttributeName
376381
/**
377382
* The namespaces indexable by mode.
378383
*/
379-
private final @NsUri @NoLength String[] uri;
384+
private final @CppInlineLength(3) @NsUri @NoLength String[] uri;
380385

381386
/**
382387
* The local names indexable by mode.
388+
*
389+
* These are weak because they're either all static, or
390+
* all the same, in wich case we just need to take one reference.
383391
*/
384-
private final @Local @NoLength String[] local;
392+
private final @CppInlineLength(3) @WeakLocal @NoLength String[] local;
385393

386394
/**
387395
* The prefixes indexably by mode.
388396
*/
389-
private final @Prefix @NoLength String[] prefix;
397+
private final @CppInlineLength(3) @Prefix @NoLength String[] prefix;
390398

391399
// CPPONLY: private final boolean custom;
392400

@@ -416,7 +424,7 @@ public final class AttributeName
416424
* whether this is an xmlns attribute
417425
*/
418426
private AttributeName(@NsUri @NoLength String[] uri,
419-
@Local @NoLength String[] local, @Prefix @NoLength String[] prefix
427+
@StaticLocal @NoLength String[] local, @Prefix @NoLength String[] prefix
420428
// [NOCPP[
421429
, int flags
422430
// ]NOCPP]
@@ -429,11 +437,12 @@ private AttributeName(@NsUri @NoLength String[] uri,
429437
this.flags = flags;
430438
// ]NOCPP]
431439
// CPPONLY: this.custom = false;
440+
// CPPONLY: Portability.deleteArray(local);
432441
}
433442

434443
// CPPONLY: public AttributeName() {
435-
// CPPONLY: this.uri = AttributeName.ALL_NO_NS;
436-
// CPPONLY: this.local = AttributeName.SAME_LOCAL(null);
444+
// CPPONLY: this.uri = ALL_NO_NS;
445+
// CPPONLY: this.local = SAME_LOCAL_NULL;
437446
// CPPONLY: this.prefix = ALL_NO_PREFIX;
438447
// CPPONLY: this.custom = true;
439448
// CPPONLY: }
@@ -444,6 +453,8 @@ private AttributeName(@NsUri @NoLength String[] uri,
444453
// CPPONLY:
445454
// CPPONLY: @Inline public void setNameForNonInterned(@Local String name) {
446455
// CPPONLY: assert custom;
456+
// CPPONLY: Portability.addrefIfNonNull(name);
457+
// CPPONLY: Portability.releaseIfNonNull(local[0]);
447458
// CPPONLY: local[0] = name;
448459
// CPPONLY: local[1] = name;
449460
// CPPONLY: local[2] = name;
@@ -458,28 +469,28 @@ private AttributeName(@NsUri @NoLength String[] uri,
458469
* whether to check ncnameness
459470
* @return an <code>AttributeName</code>
460471
*/
461-
static AttributeName createAttributeName(@Local String name
462472
// [NOCPP[
473+
static AttributeName createAttributeName(@Local String name
463474
, boolean checkNcName
464-
// ]NOCPP]
465475
) {
466-
// [NOCPP[
467476
int flags = NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG;
468477
if (name.startsWith("xmlns:")) {
469478
flags = IS_XMLNS;
470479
} else if (checkNcName && !NCName.isNCName(name)) {
471480
flags = 0;
472481
}
473-
// ]NOCPP]
474482
return new AttributeName(AttributeName.ALL_NO_NS,
475483
AttributeName.SAME_LOCAL(name), ALL_NO_PREFIX, flags);
476484
}
485+
// ]NOCPP]
477486

478487
/**
479488
* The C++ destructor.
480489
*/
481490
@SuppressWarnings("unused") private void destructor() {
482-
Portability.deleteArray(local);
491+
// CPPONLY: if (custom) {
492+
// CPPONLY: Portability.releaseIfNonNull(local[0]);
493+
// CPPONLY: }
483494
}
484495

485496
// [NOCPP[

translator-src/nu/validator/htmlparser/cpptranslate/AnnotationHelperVisitor.java

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@
3939

4040
import java.util.List;
4141

42+
import japa.parser.ast.expr.Expression;
43+
import japa.parser.ast.expr.IntegerLiteralExpr;
4244
import japa.parser.ast.expr.AnnotationExpr;
4345
import japa.parser.ast.expr.MarkerAnnotationExpr;
46+
import japa.parser.ast.expr.SingleMemberAnnotationExpr;
4447
import japa.parser.ast.type.ReferenceType;
4548
import japa.parser.ast.visitor.VoidVisitorAdapter;
4649

@@ -56,6 +59,14 @@ protected boolean prefix() {
5659
return hasAnnotation("Prefix");
5760
}
5861

62+
protected boolean staticLocal() {
63+
return hasAnnotation("StaticLocal");
64+
}
65+
66+
protected boolean weakLocal() {
67+
return hasAnnotation("WeakLocal");
68+
}
69+
5970
protected boolean local() {
6071
return hasAnnotation("Local");
6172
}
@@ -108,32 +119,59 @@ protected boolean svgCreator() {
108119
return hasAnnotation("SvgCreator");
109120
}
110121

122+
protected int inlineLength() {
123+
AnnotationExpr anno = findAnnotation("CppInlineLength");
124+
if (anno == null || !(anno instanceof SingleMemberAnnotationExpr)) {
125+
return 0;
126+
}
127+
Expression expr = ((SingleMemberAnnotationExpr)anno).getMemberValue();
128+
if (!(expr instanceof IntegerLiteralExpr)) {
129+
return 0;
130+
}
131+
return Integer.parseInt(((IntegerLiteralExpr)expr).getValue());
132+
}
133+
111134
private boolean hasAnnotation(String anno) {
135+
AnnotationExpr expr = findAnnotation(anno);
136+
return expr != null && expr instanceof MarkerAnnotationExpr;
137+
}
138+
139+
private AnnotationExpr findAnnotation(String anno) {
112140
if (currentAnnotations == null) {
113-
return false;
141+
return null;
114142
}
115143
for (AnnotationExpr ann : currentAnnotations) {
116144
if (ann instanceof MarkerAnnotationExpr) {
117-
MarkerAnnotationExpr marker = (MarkerAnnotationExpr) ann;
118-
if (marker.getName().getName().equals(anno)) {
119-
return true;
145+
if (((MarkerAnnotationExpr)ann).getName().getName().equals(anno)) {
146+
return ann;
147+
}
148+
}
149+
if (ann instanceof SingleMemberAnnotationExpr) {
150+
if (((SingleMemberAnnotationExpr)ann).getName().getName().equals(anno)) {
151+
return ann;
120152
}
121153
}
122154
}
123-
return false;
155+
return null;
124156
}
125157

126158
protected Type convertType(japa.parser.ast.type.Type type, int modifiers) {
127159
if (type instanceof ReferenceType) {
128160
ReferenceType referenceType = (ReferenceType) type;
129-
return new Type(convertTypeName(referenceType.getType().toString()), referenceType.getArrayCount(), noLength(), modifiers);
161+
return new Type(convertTypeName(referenceType.getType().toString()));
130162
} else {
131-
return new Type(convertTypeName(type.toString()), 0, false, modifiers);
163+
return new Type(convertTypeName(type.toString()));
132164
}
133165
}
134166

135167
private String convertTypeName(String name) {
136168
if ("String".equals(name)) {
169+
if (staticLocal()) {
170+
return "@StaticLocal";
171+
}
172+
if (weakLocal()) {
173+
return "@WeakLocal";
174+
}
137175
if (local()) {
138176
return "@Local";
139177
}

translator-src/nu/validator/htmlparser/cpptranslate/CppTypes.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ public String localType() {
250250
return "RefPtr<nsAtom>";
251251
}
252252

253+
public String staticLocalType() {
254+
return "nsStaticAtom*";
255+
}
256+
253257
public String prefixType() {
254258
return "nsStaticAtom*";
255259
}
@@ -514,6 +518,14 @@ public String[] stateLoopPolicies() {
514518
return STATE_LOOP_POLICIES;
515519
}
516520

521+
public String releaseIfNonNull() {
522+
return "NS_IF_RELEASE";
523+
}
524+
525+
public String addrefIfNonNull() {
526+
return "NS_IF_ADDREF";
527+
}
528+
517529
public String assertionMacro() {
518530
return "MOZ_ASSERT";
519531
}

0 commit comments

Comments
 (0)