|
41 | 41 | package com.oracle.graal.python.builtins.objects.code; |
42 | 42 |
|
43 | 43 | import static com.oracle.graal.python.nodes.StringLiterals.J_EMPTY_STRING; |
44 | | -import static com.oracle.graal.python.util.PythonUtils.EMPTY_OBJECT_ARRAY; |
45 | 44 | import static com.oracle.graal.python.util.PythonUtils.EMPTY_TRUFFLESTRING_ARRAY; |
46 | 45 | import static com.oracle.graal.python.util.PythonUtils.toInternedTruffleStringUncached; |
47 | 46 |
|
48 | 47 | import java.math.BigInteger; |
49 | | -import java.util.ArrayList; |
50 | 48 | import java.util.Arrays; |
51 | | -import java.util.HashMap; |
52 | | -import java.util.HashSet; |
53 | | -import java.util.List; |
54 | | -import java.util.Map; |
55 | | -import java.util.Set; |
56 | 49 |
|
57 | 50 | import com.oracle.graal.python.PythonLanguage; |
58 | | -import com.oracle.graal.python.builtins.objects.PNone; |
59 | 51 | import com.oracle.graal.python.builtins.objects.bytes.PBytes; |
60 | | -import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis; |
61 | 52 | import com.oracle.graal.python.builtins.objects.function.Signature; |
62 | 53 | import com.oracle.graal.python.builtins.objects.generator.PGenerator; |
63 | 54 | import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject; |
64 | 55 | import com.oracle.graal.python.builtins.objects.tuple.PTuple; |
65 | 56 | import com.oracle.graal.python.compiler.BytecodeCodeUnit; |
66 | 57 | import com.oracle.graal.python.compiler.CodeUnit; |
67 | | -import com.oracle.graal.python.compiler.OpCodes; |
68 | 58 | import com.oracle.graal.python.nodes.PRootNode; |
69 | 59 | import com.oracle.graal.python.nodes.bytecode.PBytecodeGeneratorFunctionRootNode; |
70 | 60 | import com.oracle.graal.python.nodes.bytecode.PBytecodeGeneratorRootNode; |
@@ -136,8 +126,6 @@ public final class PCode extends PythonBuiltinObject { |
136 | 126 | // qualified name with which this code object was defined |
137 | 127 | private TruffleString qualname; |
138 | 128 |
|
139 | | - private Map<CodeUnit, PCode> childCode; |
140 | | - |
141 | 129 | // number of first line in Python source code |
142 | 130 | private int firstlineno = -1; |
143 | 131 | // is a string encoding the mapping from bytecode offsets to line numbers |
@@ -293,55 +281,23 @@ private static TruffleString[] extractVarnames(RootNode node) { |
293 | 281 | return EMPTY_TRUFFLESTRING_ARRAY; |
294 | 282 | } |
295 | 283 |
|
| 284 | + private Object[] ensureConstants() { |
| 285 | + if (constants == null) { |
| 286 | + CodeUnit codeUnit = getCodeUnit(getRootNode()); |
| 287 | + constants = codeUnit != null ? new Object[codeUnit.constants.length] : PythonUtils.EMPTY_OBJECT_ARRAY; |
| 288 | + } |
| 289 | + return constants; |
| 290 | + } |
| 291 | + |
296 | 292 | @TruffleBoundary |
297 | | - private Object[] extractConstants(RootNode node) { |
298 | | - RootNode rootNode = rootNodeForExtraction(node); |
299 | | - if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER) { |
300 | | - if (rootNode instanceof PBytecodeDSLRootNode bytecodeDSLRootNode) { |
301 | | - BytecodeDSLCodeUnit co = bytecodeDSLRootNode.getCodeUnit(); |
302 | | - List<Object> constants = new ArrayList<>(); |
303 | | - for (int i = 0; i < co.constants.length; i++) { |
304 | | - Object constant = convertConstantToPythonSpace(co.constants[i]); |
305 | | - constants.add(constant); |
306 | | - } |
307 | | - return constants.toArray(new Object[0]); |
308 | | - } |
309 | | - } else if (rootNode instanceof PBytecodeRootNode bytecodeRootNode) { |
310 | | - BytecodeCodeUnit co = bytecodeRootNode.getCodeUnit(); |
311 | | - Set<Object> bytecodeConstants = new HashSet<>(); |
312 | | - for (int bci = 0; bci < co.code.length;) { |
313 | | - OpCodes op = OpCodes.fromOpCode(co.code[bci]); |
314 | | - if (op.quickens != null) { |
315 | | - op = op.quickens; |
316 | | - } |
317 | | - if (op == OpCodes.LOAD_BYTE) { |
318 | | - bytecodeConstants.add(Byte.toUnsignedInt(co.code[bci + 1])); |
319 | | - } else if (op == OpCodes.LOAD_NONE) { |
320 | | - bytecodeConstants.add(PNone.NONE); |
321 | | - } else if (op == OpCodes.LOAD_TRUE) { |
322 | | - bytecodeConstants.add(true); |
323 | | - } else if (op == OpCodes.LOAD_FALSE) { |
324 | | - bytecodeConstants.add(false); |
325 | | - } else if (op == OpCodes.LOAD_ELLIPSIS) { |
326 | | - bytecodeConstants.add(PEllipsis.INSTANCE); |
327 | | - } else if (op == OpCodes.LOAD_INT || op == OpCodes.LOAD_LONG) { |
328 | | - bytecodeConstants.add(co.primitiveConstants[Byte.toUnsignedInt(co.code[bci + 1])]); |
329 | | - } else if (op == OpCodes.LOAD_DOUBLE) { |
330 | | - bytecodeConstants.add(Double.longBitsToDouble(co.primitiveConstants[Byte.toUnsignedInt(co.code[bci + 1])])); |
331 | | - } |
332 | | - bci += op.length(); |
333 | | - } |
334 | | - List<Object> constants = new ArrayList<>(); |
335 | | - for (int i = 0; i < co.constants.length; i++) { |
336 | | - Object constant = convertConstantToPythonSpace(co.constants[i]); |
337 | | - if (constant != PNone.NONE || !bytecodeConstants.contains(PNone.NONE)) { |
338 | | - constants.add(constant); |
339 | | - } |
340 | | - } |
341 | | - constants.addAll(bytecodeConstants); |
342 | | - return constants.toArray(new Object[0]); |
| 293 | + private Object getOrCreateConstant(int index) { |
| 294 | + Object[] cachedConstants = ensureConstants(); |
| 295 | + Object constant = cachedConstants[index]; |
| 296 | + if (constant == null) { |
| 297 | + constant = convertConstantToPythonSpace(index); |
| 298 | + cachedConstants[index] = constant; |
343 | 299 | } |
344 | | - return EMPTY_OBJECT_ARRAY; |
| 300 | + return constant; |
345 | 301 | } |
346 | 302 |
|
347 | 303 | @TruffleBoundary |
@@ -419,9 +375,11 @@ public void fixCoFilename(TruffleString filename) { |
419 | 375 | * New code objects inherit the filename from parent, so no need to eagerly construct them |
420 | 376 | * here |
421 | 377 | */ |
422 | | - if (childCode != null) { |
423 | | - for (PCode code : childCode.values()) { |
424 | | - code.filename = filename; |
| 378 | + if (constants != null) { |
| 379 | + for (Object constant : constants) { |
| 380 | + if (constant instanceof PCode code) { |
| 381 | + code.filename = filename; |
| 382 | + } |
425 | 383 | } |
426 | 384 | } |
427 | 385 | } |
@@ -525,65 +483,66 @@ public CodeUnit getCodeUnit() { |
525 | 483 | } |
526 | 484 |
|
527 | 485 | public Object[] getConstants() { |
528 | | - if (constants == null) { |
529 | | - constants = extractConstants(getRootNode()); |
| 486 | + Object[] cachedConstants = ensureConstants(); |
| 487 | + for (int i = 0; i < cachedConstants.length; i++) { |
| 488 | + getOrCreateConstant(i); |
530 | 489 | } |
531 | | - return constants; |
| 490 | + return cachedConstants; |
532 | 491 | } |
533 | 492 |
|
534 | | - @TruffleBoundary |
535 | | - public PCode getOrCreateChildCode(BytecodeDSLCodeUnit codeUnit) { |
536 | | - PCode code = null; |
537 | | - if (childCode == null) { |
538 | | - childCode = new HashMap<>(); |
539 | | - } else { |
540 | | - code = childCode.get(codeUnit); |
541 | | - } |
| 493 | + public PCode getOrCreateChildCode(int index, BytecodeDSLCodeUnit codeUnit) { |
| 494 | + Object[] cachedConstants = ensureConstants(); |
| 495 | + PCode code = (PCode) cachedConstants[index]; |
542 | 496 | if (code == null) { |
543 | | - PBytecodeDSLRootNode outerRootNode = (PBytecodeDSLRootNode) getRootNode(); |
544 | | - PythonLanguage language = outerRootNode.getLanguage(); |
545 | | - RootCallTarget callTarget = language.createCachedCallTarget(l -> codeUnit.createRootNode(PythonContext.get(null), outerRootNode.getSource()), codeUnit); |
546 | | - PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) callTarget.getRootNode(); |
547 | | - code = PFactory.createCode(language, callTarget, rootNode.getSignature(), codeUnit, getFilename()); |
548 | | - childCode.put(codeUnit, code); |
| 497 | + code = createCode(codeUnit); |
| 498 | + cachedConstants[index] = code; |
549 | 499 | } |
550 | 500 | return code; |
551 | 501 | } |
552 | 502 |
|
553 | 503 | @TruffleBoundary |
554 | | - public PCode getOrCreateChildCode(BytecodeCodeUnit codeUnit) { |
555 | | - PCode code = null; |
556 | | - if (childCode == null) { |
557 | | - childCode = new HashMap<>(); |
558 | | - } else { |
559 | | - code = childCode.get(codeUnit); |
560 | | - } |
| 504 | + private PCode createCode(BytecodeDSLCodeUnit codeUnit) { |
| 505 | + PBytecodeDSLRootNode outerRootNode = (PBytecodeDSLRootNode) getRootNode(); |
| 506 | + PythonLanguage language = outerRootNode.getLanguage(); |
| 507 | + RootCallTarget callTarget = language.createCachedCallTarget(l -> codeUnit.createRootNode(PythonContext.get(null), outerRootNode.getSource()), codeUnit); |
| 508 | + PBytecodeDSLRootNode rootNode = (PBytecodeDSLRootNode) callTarget.getRootNode(); |
| 509 | + return PFactory.createCode(language, callTarget, rootNode.getSignature(), codeUnit, getFilename()); |
| 510 | + } |
| 511 | + |
| 512 | + public PCode getOrCreateChildCode(int index, BytecodeCodeUnit codeUnit) { |
| 513 | + Object[] cachedConstants = ensureConstants(); |
| 514 | + PCode code = (PCode) cachedConstants[index]; |
561 | 515 | if (code == null) { |
562 | | - PBytecodeRootNode outerRootNode = (PBytecodeRootNode) getRootNodeForExtraction(); |
563 | | - PythonLanguage language = outerRootNode.getLanguage(); |
564 | | - RootCallTarget callTarget = language.createCachedCallTarget( |
565 | | - l -> PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getLazySource(), outerRootNode.isInternal()), |
566 | | - codeUnit); |
567 | | - RootNode rootNode = callTarget.getRootNode(); |
568 | | - if (rootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { |
569 | | - rootNode = generatorRoot.getBytecodeRootNode(); |
570 | | - } |
571 | | - code = PFactory.createCode(language, callTarget, ((PBytecodeRootNode) rootNode).getSignature(), codeUnit, getFilename()); |
572 | | - childCode.put(codeUnit, code); |
| 516 | + code = createCode(codeUnit); |
| 517 | + cachedConstants[index] = code; |
573 | 518 | } |
574 | 519 | return code; |
575 | 520 | } |
576 | 521 |
|
577 | 522 | @TruffleBoundary |
578 | | - private Object convertConstantToPythonSpace(Object o) { |
| 523 | + private PCode createCode(BytecodeCodeUnit codeUnit) { |
| 524 | + PBytecodeRootNode outerRootNode = (PBytecodeRootNode) getRootNodeForExtraction(); |
| 525 | + PythonLanguage language = outerRootNode.getLanguage(); |
| 526 | + RootCallTarget callTarget = language.createCachedCallTarget( |
| 527 | + l -> PBytecodeRootNode.createMaybeGenerator(language, codeUnit, outerRootNode.getLazySource(), outerRootNode.isInternal()), codeUnit); |
| 528 | + RootNode rootNode = callTarget.getRootNode(); |
| 529 | + if (rootNode instanceof PBytecodeGeneratorFunctionRootNode generatorRoot) { |
| 530 | + rootNode = generatorRoot.getBytecodeRootNode(); |
| 531 | + } |
| 532 | + return PFactory.createCode(language, callTarget, ((PBytecodeRootNode) rootNode).getSignature(), codeUnit, getFilename()); |
| 533 | + } |
| 534 | + |
| 535 | + @TruffleBoundary |
| 536 | + private Object convertConstantToPythonSpace(int index) { |
| 537 | + Object o = getCodeUnit().constants[index]; |
579 | 538 | PythonLanguage language = PythonLanguage.get(null); |
580 | 539 | if (o instanceof CodeUnit) { |
581 | 540 | if (PythonOptions.ENABLE_BYTECODE_DSL_INTERPRETER) { |
582 | 541 | BytecodeDSLCodeUnit code = (BytecodeDSLCodeUnit) o; |
583 | | - return getOrCreateChildCode(code); |
| 542 | + return getOrCreateChildCode(index, code); |
584 | 543 | } else { |
585 | 544 | BytecodeCodeUnit code = (BytecodeCodeUnit) o; |
586 | | - return getOrCreateChildCode(code); |
| 545 | + return getOrCreateChildCode(index, code); |
587 | 546 | } |
588 | 547 | } else if (o instanceof BigInteger) { |
589 | 548 | return PFactory.createInt(language, (BigInteger) o); |
|
0 commit comments