author | joehw |
Thu, 21 Dec 2017 17:08:05 -0800 | |
changeset 48412 | d4412e380f6b |
parent 48409 | 5ab69533994b |
permissions | -rw-r--r-- |
6 | 1 |
/* |
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
2 |
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. |
6 | 3 |
*/ |
4 |
/* |
|
33349 | 5 |
* Licensed to the Apache Software Foundation (ASF) under one or more |
6 |
* contributor license agreements. See the NOTICE file distributed with |
|
7 |
* this work for additional information regarding copyright ownership. |
|
8 |
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
9 |
* (the "License"); you may not use this file except in compliance with |
|
10 |
* the License. You may obtain a copy of the License at |
|
6 | 11 |
* |
12 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
13 |
* |
|
14 |
* Unless required by applicable law or agreed to in writing, software |
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 |
* See the License for the specific language governing permissions and |
|
18 |
* limitations under the License. |
|
19 |
*/ |
|
20 |
/* |
|
21 |
* $Id: TestSeq.java,v 1.2.4.1 2005/09/12 11:31:38 pvedula Exp $ |
|
22 |
*/ |
|
23 |
||
24 |
package com.sun.org.apache.xalan.internal.xsltc.compiler; |
|
25 |
||
26 |
import com.sun.org.apache.bcel.internal.generic.GOTO_W; |
|
27 |
import com.sun.org.apache.bcel.internal.generic.InstructionHandle; |
|
28 |
import com.sun.org.apache.bcel.internal.generic.InstructionList; |
|
29 |
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; |
|
30 |
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
31 |
import java.util.ArrayList; |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
32 |
import java.util.List; |
33349 | 33 |
import java.util.Map; |
6 | 34 |
|
35 |
/** |
|
36 |
* A test sequence is a sequence of patterns that |
|
37 |
* |
|
38 |
* (1) occured in templates in the same mode |
|
39 |
* (2) share the same kernel node type (e.g. A/B and C/C/B) |
|
40 |
* (3) may also contain patterns matching "*" and "node()" |
|
41 |
* (element sequence only) or matching "@*" (attribute |
|
42 |
* sequence only). |
|
43 |
* |
|
44 |
* A test sequence may have a default template, which will be |
|
45 |
* instantiated if none of the other patterns match. |
|
46 |
* @author Jacek Ambroziak |
|
47 |
* @author Santiago Pericas-Geertsen |
|
48 |
* @author Erwin Bolwidt <ejb@klomp.org> |
|
48412 | 49 |
* @author Morten Jorgensen |
48409 | 50 |
* @LastModified: Nov 2017 |
6 | 51 |
*/ |
52 |
final class TestSeq { |
|
53 |
||
54 |
/** |
|
55 |
* Integer code for the kernel type of this test sequence |
|
56 |
*/ |
|
57 |
private int _kernelType; |
|
58 |
||
59 |
/** |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
60 |
* ArrayList of all patterns in the test sequence. May include |
6 | 61 |
* patterns with "*", "@*" or "node()" kernel. |
62 |
*/ |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
63 |
private List<LocationPathPattern> _patterns = null; |
6 | 64 |
|
65 |
/** |
|
66 |
* A reference to the Mode object. |
|
67 |
*/ |
|
68 |
private Mode _mode = null; |
|
69 |
||
70 |
/** |
|
71 |
* Default template for this test sequence |
|
72 |
*/ |
|
73 |
private Template _default = null; |
|
74 |
||
75 |
/** |
|
76 |
* Instruction list representing this test sequence. |
|
77 |
*/ |
|
78 |
private InstructionList _instructionList; |
|
79 |
||
80 |
/** |
|
81 |
* Cached handle to avoid compiling more than once. |
|
82 |
*/ |
|
83 |
private InstructionHandle _start = null; |
|
84 |
||
85 |
/** |
|
86 |
* Creates a new test sequence given a set of patterns and a mode. |
|
87 |
*/ |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
88 |
public TestSeq(List<LocationPathPattern> patterns, Mode mode) { |
6 | 89 |
this(patterns, -2, mode); |
90 |
} |
|
91 |
||
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
92 |
public TestSeq(List<LocationPathPattern> patterns, int kernelType, Mode mode) { |
6 | 93 |
_patterns = patterns; |
94 |
_kernelType = kernelType; |
|
95 |
_mode = mode; |
|
96 |
} |
|
97 |
||
98 |
/** |
|
99 |
* Returns a string representation of this test sequence. Notice |
|
100 |
* that test sequences are mutable, so the value returned by this |
|
101 |
* method is different before and after calling reduce(). |
|
102 |
*/ |
|
103 |
public String toString() { |
|
104 |
final int count = _patterns.size(); |
|
105 |
final StringBuffer result = new StringBuffer(); |
|
106 |
||
107 |
for (int i = 0; i < count; i++) { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
108 |
final LocationPathPattern pattern = _patterns.get(i); |
6 | 109 |
|
110 |
if (i == 0) { |
|
12458 | 111 |
result.append("Testseq for kernel ").append(_kernelType) |
6 | 112 |
.append('\n'); |
113 |
} |
|
12458 | 114 |
result.append(" pattern ").append(i).append(": ") |
6 | 115 |
.append(pattern.toString()) |
116 |
.append('\n'); |
|
117 |
} |
|
118 |
return result.toString(); |
|
119 |
} |
|
120 |
||
121 |
/** |
|
122 |
* Returns the instruction list for this test sequence |
|
123 |
*/ |
|
124 |
public InstructionList getInstructionList() { |
|
125 |
return _instructionList; |
|
126 |
} |
|
127 |
||
128 |
/** |
|
129 |
* Return the highest priority for a pattern in this test |
|
130 |
* sequence. This is either the priority of the first or |
|
131 |
* of the default pattern. |
|
132 |
*/ |
|
133 |
public double getPriority() { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
134 |
final Template template = (_patterns.isEmpty()) ? _default |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
135 |
: ((Pattern) _patterns.get(0)).getTemplate(); |
6 | 136 |
return template.getPriority(); |
137 |
} |
|
138 |
||
139 |
/** |
|
140 |
* Returns the position of the highest priority pattern in |
|
141 |
* this test sequence. |
|
142 |
*/ |
|
143 |
public int getPosition() { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
144 |
final Template template = (_patterns.isEmpty()) ? _default |
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
145 |
: ((Pattern) _patterns.get(0)).getTemplate(); |
6 | 146 |
return template.getPosition(); |
147 |
} |
|
148 |
||
149 |
/** |
|
150 |
* Reduce the patterns in this test sequence. Creates a new |
|
151 |
* vector of patterns and sets the default pattern if it |
|
152 |
* finds a patterns that is fully reduced. |
|
153 |
*/ |
|
154 |
public void reduce() { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
155 |
final List<LocationPathPattern> newPatterns = new ArrayList<>(); |
6 | 156 |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
157 |
for (LocationPathPattern pattern : _patterns) { |
6 | 158 |
// Reduce this pattern |
159 |
pattern.reduceKernelPattern(); |
|
160 |
||
161 |
// Is this pattern fully reduced? |
|
162 |
if (pattern.isWildcard()) { |
|
163 |
_default = pattern.getTemplate(); |
|
164 |
break; // Ignore following patterns |
|
165 |
} |
|
166 |
else { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
167 |
newPatterns.add(pattern); |
6 | 168 |
} |
169 |
} |
|
170 |
_patterns = newPatterns; |
|
171 |
} |
|
172 |
||
173 |
/** |
|
174 |
* Returns, by reference, the templates that are included in |
|
175 |
* this test sequence. Note that a single template can occur |
|
176 |
* in several test sequences if its pattern is a union. |
|
177 |
*/ |
|
33349 | 178 |
public void findTemplates(Map<Template, Object> templates) { |
6 | 179 |
if (_default != null) { |
180 |
templates.put(_default, this); |
|
181 |
} |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
182 |
for (LocationPathPattern pattern : _patterns) { |
6 | 183 |
templates.put(pattern.getTemplate(), this); |
184 |
} |
|
185 |
} |
|
186 |
||
187 |
/** |
|
188 |
* Get the instruction handle to a template's code. This is |
|
189 |
* used when a single template occurs in several test |
|
190 |
* sequences; that is, if its pattern is a union of patterns |
|
191 |
* (e.g. match="A/B | A/C"). |
|
192 |
*/ |
|
193 |
private InstructionHandle getTemplateHandle(Template template) { |
|
47712 | 194 |
return _mode.getTemplateInstructionHandle(template); |
6 | 195 |
} |
196 |
||
197 |
/** |
|
198 |
* Returns pattern n in this test sequence |
|
199 |
*/ |
|
200 |
private LocationPathPattern getPattern(int n) { |
|
47359
e1a6c0168741
8181150: Fix lint warnings in JAXP repo: rawtypes and unchecked
joehw
parents:
47216
diff
changeset
|
201 |
return _patterns.get(n); |
6 | 202 |
} |
203 |
||
204 |
/** |
|
205 |
* Compile the code for this test sequence. Compile patterns |
|
206 |
* from highest to lowest priority. Note that since patterns |
|
207 |
* can be share by multiple test sequences, instruction lists |
|
208 |
* must be copied before backpatching. |
|
209 |
*/ |
|
210 |
public InstructionHandle compile(ClassGenerator classGen, |
|
211 |
MethodGenerator methodGen, |
|
212 |
InstructionHandle continuation) |
|
213 |
{ |
|
214 |
// Returned cached value if already compiled |
|
215 |
if (_start != null) { |
|
216 |
return _start; |
|
217 |
} |
|
218 |
||
219 |
// If not patterns, then return handle for default template |
|
220 |
final int count = _patterns.size(); |
|
221 |
if (count == 0) { |
|
222 |
return (_start = getTemplateHandle(_default)); |
|
223 |
} |
|
224 |
||
225 |
// Init handle to jump when all patterns failed |
|
226 |
InstructionHandle fail = (_default == null) ? continuation |
|
227 |
: getTemplateHandle(_default); |
|
228 |
||
229 |
// Compile all patterns in reverse order |
|
230 |
for (int n = count - 1; n >= 0; n--) { |
|
231 |
final LocationPathPattern pattern = getPattern(n); |
|
232 |
final Template template = pattern.getTemplate(); |
|
233 |
final InstructionList il = new InstructionList(); |
|
234 |
||
235 |
// Patterns expect current node on top of stack |
|
236 |
il.append(methodGen.loadCurrentNode()); |
|
237 |
||
238 |
// Apply the test-code compiled for the pattern |
|
239 |
InstructionList ilist = methodGen.getInstructionList(pattern); |
|
240 |
if (ilist == null) { |
|
241 |
ilist = pattern.compile(classGen, methodGen); |
|
242 |
methodGen.addInstructionList(pattern, ilist); |
|
243 |
} |
|
244 |
||
245 |
// Make a copy of the instruction list for backpatching |
|
246 |
InstructionList copyOfilist = ilist.copy(); |
|
247 |
||
248 |
FlowList trueList = pattern.getTrueList(); |
|
249 |
if (trueList != null) { |
|
250 |
trueList = trueList.copyAndRedirect(ilist, copyOfilist); |
|
251 |
} |
|
252 |
FlowList falseList = pattern.getFalseList(); |
|
253 |
if (falseList != null) { |
|
254 |
falseList = falseList.copyAndRedirect(ilist, copyOfilist); |
|
255 |
} |
|
256 |
||
257 |
il.append(copyOfilist); |
|
258 |
||
259 |
// On success branch to the template code |
|
260 |
final InstructionHandle gtmpl = getTemplateHandle(template); |
|
261 |
final InstructionHandle success = il.append(new GOTO_W(gtmpl)); |
|
262 |
||
263 |
if (trueList != null) { |
|
264 |
trueList.backPatch(success); |
|
265 |
} |
|
266 |
if (falseList != null) { |
|
267 |
falseList.backPatch(fail); |
|
268 |
} |
|
269 |
||
270 |
// Next pattern's 'fail' target is this pattern's first instruction |
|
271 |
fail = il.getStart(); |
|
272 |
||
273 |
// Append existing instruction list to the end of this one |
|
274 |
if (_instructionList != null) { |
|
275 |
il.append(_instructionList); |
|
276 |
} |
|
277 |
||
278 |
// Set current instruction list to be this one |
|
279 |
_instructionList = il; |
|
280 |
} |
|
281 |
return (_start = fail); |
|
282 |
} |
|
283 |
} |