23 |
23 |
24 |
24 |
25 package org.graalvm.compiler.replacements; |
25 package org.graalvm.compiler.replacements; |
26 |
26 |
27 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; |
27 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; |
|
28 import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; |
28 |
29 |
29 import org.graalvm.compiler.api.replacements.Fold; |
30 import org.graalvm.compiler.api.replacements.Fold; |
30 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; |
31 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; |
31 import org.graalvm.compiler.api.replacements.Snippet; |
32 import org.graalvm.compiler.api.replacements.Snippet; |
32 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; |
33 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; |
42 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; |
43 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; |
43 |
44 |
44 import jdk.vm.ci.code.TargetDescription; |
45 import jdk.vm.ci.code.TargetDescription; |
45 import jdk.vm.ci.meta.JavaKind; |
46 import jdk.vm.ci.meta.JavaKind; |
46 import jdk.vm.ci.meta.MetaAccessProvider; |
47 import jdk.vm.ci.meta.MetaAccessProvider; |
|
48 import sun.misc.Unsafe; |
47 |
49 |
48 public class ConstantStringIndexOfSnippets implements Snippets { |
50 public class ConstantStringIndexOfSnippets implements Snippets { |
|
51 private static final Unsafe UNSAFE = getUnsafe(); |
|
52 |
49 public static class Templates extends AbstractTemplates { |
53 public static class Templates extends AbstractTemplates { |
50 |
54 |
51 private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant"); |
55 private final SnippetInfo indexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "indexOfConstant"); |
52 private final SnippetInfo latin1IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "latin1IndexOfConstant"); |
56 private final SnippetInfo latin1IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "latin1IndexOfConstant"); |
53 private final SnippetInfo utf16IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "utf16IndexOfConstant"); |
57 private final SnippetInfo utf16IndexOfConstant = snippet(ConstantStringIndexOfSnippets.class, "utf16IndexOfConstant"); |
155 int c = target.length / 2; |
159 int c = target.length / 2; |
156 if (c == 0) { |
160 if (c == 0) { |
157 return 0; |
161 return 0; |
158 } |
162 } |
159 long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); |
163 long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); |
160 char lastChar = UnsafeAccess.UNSAFE.getChar(target, base + (c - 1) * 2); |
164 char lastChar = UNSAFE.getChar(target, base + (c - 1) * 2); |
161 int md2 = c; |
165 int md2 = c; |
162 for (int i = 0; i < c - 1; i++) { |
166 for (int i = 0; i < c - 1; i++) { |
163 char currChar = UnsafeAccess.UNSAFE.getChar(target, base + i * 2); |
167 char currChar = UNSAFE.getChar(target, base + i * 2); |
164 if (currChar == lastChar) { |
168 if (currChar == lastChar) { |
165 md2 = (c - 1) - i; |
169 md2 = (c - 1) - i; |
166 } |
170 } |
167 } |
171 } |
168 return md2; |
172 return md2; |
172 int c = s.length / 2; |
176 int c = s.length / 2; |
173 int cache = 0; |
177 int cache = 0; |
174 int i; |
178 int i; |
175 long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); |
179 long base = metaAccess.getArrayBaseOffset(JavaKind.Byte); |
176 for (i = 0; i < c - 1; i++) { |
180 for (i = 0; i < c - 1; i++) { |
177 char currChar = UnsafeAccess.UNSAFE.getChar(s, base + i * 2); |
181 char currChar = UNSAFE.getChar(s, base + i * 2); |
178 cache |= (1 << (currChar & 63)); |
182 cache |= (1 << (currChar & 63)); |
179 } |
183 } |
180 return cache; |
184 return cache; |
181 } |
185 } |
182 |
186 |
210 |
214 |
211 int targetCountLess1 = targetCount - 1; |
215 int targetCountLess1 = targetCount - 1; |
212 int sourceEnd = sourceCount - targetCountLess1; |
216 int sourceEnd = sourceCount - targetCountLess1; |
213 |
217 |
214 long base = charArrayBaseOffset(INJECTED); |
218 long base = charArrayBaseOffset(INJECTED); |
215 int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2); |
219 int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2); |
216 |
220 |
217 outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) { |
221 outer_loop: for (long i = sourceOffset + fromIndex; i < sourceEnd;) { |
218 int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); |
222 int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); |
219 if (src == lastChar) { |
223 if (src == lastChar) { |
220 // With random strings and a 4-character alphabet, |
224 // With random strings and a 4-character alphabet, |
221 // reverse matching at this point sets up 0.8% fewer |
225 // reverse matching at this point sets up 0.8% fewer |
222 // frames, but (paradoxically) makes 0.3% more probes. |
226 // frames, but (paradoxically) makes 0.3% more probes. |
223 // Since those probes are nearer the lastChar probe, |
227 // Since those probes are nearer the lastChar probe, |
227 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
231 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
228 if (targetCount <= 8) { |
232 if (targetCount <= 8) { |
229 ExplodeLoopNode.explodeLoop(); |
233 ExplodeLoopNode.explodeLoop(); |
230 } |
234 } |
231 for (long j = 0; j < targetCountLess1; j++) { |
235 for (long j = 0; j < targetCountLess1; j++) { |
232 char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2); |
236 char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2); |
233 if (UnsafeAccess.UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) { |
237 if (UNSAFE.getChar(target, base + (targetOffset + j) * 2) != sourceChar) { |
234 if ((cache & (1 << sourceChar)) == 0) { |
238 if ((cache & (1 << sourceChar)) == 0) { |
235 if (md2 < j + 1) { |
239 if (md2 < j + 1) { |
236 i += j + 1; |
240 i += j + 1; |
237 continue outer_loop; |
241 continue outer_loop; |
238 } |
242 } |
268 |
272 |
269 int targetCountLess1 = targetCount - 1; |
273 int targetCountLess1 = targetCount - 1; |
270 int sourceEnd = sourceCount - targetCountLess1; |
274 int sourceEnd = sourceCount - targetCountLess1; |
271 |
275 |
272 long base = byteArrayBaseOffset(INJECTED); |
276 long base = byteArrayBaseOffset(INJECTED); |
273 int lastChar = UnsafeAccess.UNSAFE.getChar(target, base + targetCountLess1 * 2); |
277 int lastChar = UNSAFE.getChar(target, base + targetCountLess1 * 2); |
274 |
278 |
275 outer_loop: for (long i = fromIndex; i < sourceEnd;) { |
279 outer_loop: for (long i = fromIndex; i < sourceEnd;) { |
276 int src = UnsafeAccess.UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); |
280 int src = UNSAFE.getChar(source, base + (i + targetCountLess1) * 2); |
277 if (src == lastChar) { |
281 if (src == lastChar) { |
278 // With random strings and a 4-character alphabet, |
282 // With random strings and a 4-character alphabet, |
279 // reverse matching at this point sets up 0.8% fewer |
283 // reverse matching at this point sets up 0.8% fewer |
280 // frames, but (paradoxically) makes 0.3% more probes. |
284 // frames, but (paradoxically) makes 0.3% more probes. |
281 // Since those probes are nearer the lastChar probe, |
285 // Since those probes are nearer the lastChar probe, |
285 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
289 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
286 if (targetCount <= 8) { |
290 if (targetCount <= 8) { |
287 ExplodeLoopNode.explodeLoop(); |
291 ExplodeLoopNode.explodeLoop(); |
288 } |
292 } |
289 for (long j = 0; j < targetCountLess1; j++) { |
293 for (long j = 0; j < targetCountLess1; j++) { |
290 char sourceChar = UnsafeAccess.UNSAFE.getChar(source, base + (i + j) * 2); |
294 char sourceChar = UNSAFE.getChar(source, base + (i + j) * 2); |
291 if (UnsafeAccess.UNSAFE.getChar(target, base + j * 2) != sourceChar) { |
295 if (UNSAFE.getChar(target, base + j * 2) != sourceChar) { |
292 if ((cache & (1 << sourceChar)) == 0) { |
296 if ((cache & (1 << sourceChar)) == 0) { |
293 if (md2 < j + 1) { |
297 if (md2 < j + 1) { |
294 i += j + 1; |
298 i += j + 1; |
295 continue outer_loop; |
299 continue outer_loop; |
296 } |
300 } |
326 |
330 |
327 int targetCountLess1 = targetCount - 1; |
331 int targetCountLess1 = targetCount - 1; |
328 int sourceEnd = sourceCount - targetCountLess1; |
332 int sourceEnd = sourceCount - targetCountLess1; |
329 |
333 |
330 long base = byteArrayBaseOffset(INJECTED); |
334 long base = byteArrayBaseOffset(INJECTED); |
331 int lastByte = UnsafeAccess.UNSAFE.getByte(target, base + targetCountLess1); |
335 int lastByte = UNSAFE.getByte(target, base + targetCountLess1); |
332 |
336 |
333 outer_loop: for (long i = fromIndex; i < sourceEnd;) { |
337 outer_loop: for (long i = fromIndex; i < sourceEnd;) { |
334 int src = UnsafeAccess.UNSAFE.getByte(source, base + i + targetCountLess1); |
338 int src = UNSAFE.getByte(source, base + i + targetCountLess1); |
335 if (src == lastByte) { |
339 if (src == lastByte) { |
336 // With random strings and a 4-character alphabet, |
340 // With random strings and a 4-character alphabet, |
337 // reverse matching at this point sets up 0.8% fewer |
341 // reverse matching at this point sets up 0.8% fewer |
338 // frames, but (paradoxically) makes 0.3% more probes. |
342 // frames, but (paradoxically) makes 0.3% more probes. |
339 // Since those probes are nearer the lastByte probe, |
343 // Since those probes are nearer the lastByte probe, |
343 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
347 // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount) |
344 if (targetCount <= 8) { |
348 if (targetCount <= 8) { |
345 ExplodeLoopNode.explodeLoop(); |
349 ExplodeLoopNode.explodeLoop(); |
346 } |
350 } |
347 for (long j = 0; j < targetCountLess1; j++) { |
351 for (long j = 0; j < targetCountLess1; j++) { |
348 byte sourceByte = UnsafeAccess.UNSAFE.getByte(source, base + i + j); |
352 byte sourceByte = UNSAFE.getByte(source, base + i + j); |
349 if (UnsafeAccess.UNSAFE.getByte(target, base + j) != sourceByte) { |
353 if (UNSAFE.getByte(target, base + j) != sourceByte) { |
350 if ((cache & (1 << sourceByte)) == 0) { |
354 if ((cache & (1 << sourceByte)) == 0) { |
351 if (md2 < j + 1) { |
355 if (md2 < j + 1) { |
352 i += j + 1; |
356 i += j + 1; |
353 continue outer_loop; |
357 continue outer_loop; |
354 } |
358 } |