Skip to content

Commit 9169766

Browse files
committed
[GR-60213] [GR-60214] Bytecode DSL: disallow uncached compilation & fix docs
PullRequest: graal/19490
2 parents 6e1388b + e0d746e commit 9169766

File tree

13 files changed

+89
-49
lines changed

13 files changed

+89
-49
lines changed

truffle/docs/bytecode_dsl/Optimization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Boxing elimination avoids these unnecessary boxing steps.
1313
The interpreter can speculatively rewrite bytecode instructions to specialized instructions that pass primitive values whenever possible.
1414
Boxing elimination can also improve compiled performance, because Graal is not always able to remove box-unbox sequences during compilation.
1515

16-
To enable boxing elimination, specify a set of `boxingEliminationTypes` on the [`@GenerateBytecode`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode./src/com/oracle/truffle/api/bytecode/GenerateBytecode.java) annotation. For example, the following configuration
16+
To enable boxing elimination, specify a set of `boxingEliminationTypes` on the [`@GenerateBytecode`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/GenerateBytecode.java) annotation. For example, the following configuration
1717

1818
```java
1919
@GenerateBytecode(
@@ -35,7 +35,7 @@ Quickened operations can be introduced to reduce the work required to evaluate a
3535
For example, a quickened operation that only accepts `int` inputs might avoid operand boxing and the additional type checks required by the general operation.
3636
Additionally, a custom operation that has only one active specialization could be quickened to an operation that only supports that single specialization, avoiding extra specialization state checks.
3737

38-
At the moment, quickened instructions can only be specified manually using [`@ForceQuickening`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode./src/com/oracle/truffle/api/bytecode/ForceQuickening.java).
38+
At the moment, quickened instructions can only be specified manually using [`@ForceQuickening`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/ForceQuickening.java).
3939
In the future, [tracing](#tracing) will be able to automatically infer useful quickenings.
4040

4141

truffle/docs/bytecode_dsl/ShortCircuitOperations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
One limitation of regular operations is that they are *eager*: all of the child operations are evaluated before the operation itself evaluates.
44
Many languages define *short-circuiting* operators (e.g., Java's `&&`) which can evaluate a subset of their operands, terminating early when an operand meets a particular condition (e.g., when it is `true`).
55

6-
The Bytecode DSL allows you to define [`@ShortCircuitOperation`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode./src/com/oracle/truffle/api/bytecode/ShortCircuitOperation.java)s to implement short-circuiting behaviour.
6+
The Bytecode DSL allows you to define [`@ShortCircuitOperation`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/ShortCircuitOperation.java)s to implement short-circuiting behaviour.
77
A short-circuit operation implements `AND` or `OR` semantics, executing each child operation until the first `false` or `true` value, respectively.
88

99
### Basic example

truffle/docs/bytecode_dsl/UserGuide.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ The current state is encapsulated in a [`BytecodeNode`](https://github.com/oracl
106106
It is worth familiarizing yourself with its APIs.
107107

108108
The `BytecodeNode` (and the bytecode itself) can change over the execution of a program for various reasons (e.g., [transitioning from uncached to cached](#cached-and-uncached-execution), [reparsing metadata](#reparsing), [quickening](Optimization.md#quickening)), so you should use `BytecodeRootNode#getBytecodeNode()` to obtain the up-to-date bytecode node each time you need it.
109-
Custom operations can also `@Bind BytecodeNode` in their specializations (see [Bind parameters](#bind-parameters)).
109+
Custom operations can also `@Bind BytecodeNode` in their specializations (more about special Bind parameters [here](#expressions-in-operations)).
110110

111111
Because the bytecode may change, a bytecode index (obtained using `@Bind("$bytecodeIndex")`) must be paired with a `BytecodeNode` to meaningfully identify a program location.
112112
You can also instantiate a [`BytecodeLocation`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/BytecodeLocation.java), which logically represents the bytecode node and index, using `BytecodeNode#getBytecodeLocation(int)` or `@Bind BytecodeLocation`.
@@ -271,7 +271,7 @@ The builder will emit code to collect these values into an `Object[]`.
271271

272272
An operation can also define _constant operands_, which are embedded in the bytecode and produce partial evaluation constant values, by declaring [`@ConstantOperand`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/ConstantOperand.java)s.
273273

274-
An operation may need to produce more than one result, or to modify local variables. For either case, the operation can use [`LocalAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessor.java) or [`LocalAccessorRange`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessorRange.java).
274+
An operation may need to produce more than one result, or to modify local variables. For either case, the operation can use [`LocalAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessor.java) or [`LocalRangeAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalRangeAccessor.java).
275275

276276

277277
## Locals
@@ -298,7 +298,7 @@ b.endBlock();
298298
All local accesses must be (directly or indirectly) nested within the operation that created the local.
299299

300300
The `LoadLocal` and `StoreLocal` operations are the preferred way to access locals because they are efficient and can be quickened to [avoid boxing](Optimization.md#boxing-elimination).
301-
Some behaviour cannot be easily implemented using only these operations, in which case an operation can declare a [`LocalAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessor.java) or [`LocalAccessorRange`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessorRange.java) operand to perform local accesses.
301+
Some behaviour cannot be easily implemented using only these operations, in which case an operation can declare a [`LocalAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalAccessor.java) or [`LocalRangeAccessor`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/LocalRangeAccessor.java) operand to perform local accesses.
302302
For example, an operation producing multiple values cannot "return" both values, and may instead use a local accessor to write one of the values back to a local.
303303
The [`BytecodeNode`](https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/BytecodeNode.java) class also declares a variety of helper methods for accessing locals.
304304
These helpers often have extra indirection, so the built-in operations and accessors are preferred.
@@ -533,7 +533,7 @@ It is recommended to enclose the `Root` operation in appropriate `Source` and `S
533533
The generated root node will override `Node#getSourceSection` to return this information.
534534

535535
Source information is designed to have no performance overhead until it is requested (see [Reparsing metadata](#reparsing)).
536-
This information [should generally not be accessed from compiled code](RuntimeCompilation.md#source-information).
536+
Take extra care if accessing source information in [compiled code](RuntimeCompilation.md#source-information).
537537

538538
### Instrumentation
539539

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/examples/GettingStarted.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ public void testIfThenElse() {
447447
* while i < n:
448448
* i += 1
449449
* total += i
450+
* return total
450451
* </pre>
451452
*/
452453
@Test
@@ -507,7 +508,7 @@ public void testLoop() {
507508
}
508509

509510
/**
510-
* For more advanced control flow, The Bytecode DSL also allows you to define and branch to
511+
* For more advanced control flow, the Bytecode DSL also allows you to define and branch to
511512
* labels. Programs can branch forward to labels using the {@code Branch} operation. Let's use
512513
* labels to implement {@code sumToN} using a {@code break}:
513514
*
@@ -593,7 +594,7 @@ public void testLoopWithBreak() {
593594
}
594595

595596
/*
596-
* In addition to the condition and looping contructs, The Bytecode DSL has other control flow
597+
* In addition to the condition and looping constructs, the Bytecode DSL has other control flow
597598
* mechanisms for exception handling ({@code TryCatch}, {@code TryFinally}, and {@code
598599
* TryCatchOtherwise}) and continuations ({@code Yield}). We will not cover those here.
599600
*/

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/examples/ParsingTutorial.java

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@
6060
* This tutorial demonstrates how to programmatically parse bytecode for a Bytecode DSL interpreter.
6161
* It refers to the interpreter defined in the {@link GettingStarted} guide. It is recommended to
6262
* read that guide first.
63-
*
64-
* @see <a href=
65-
* "https://github.com/oracle/graal/blob/master/truffle/docs/bytecode_dsl/GettingStarted.md">Getting
66-
* started guide</a>
6763
*/
6864
public class ParsingTutorial {
6965
/**
@@ -565,7 +561,25 @@ public void visitForEach(ForEach f) {
565561
}
566562

567563
/**
568-
* Now, let's test it.
564+
* Finally, let's test it below.
565+
*
566+
* This tutorial demonstrated how to parse programs using visitors. It also demonstrated how to
567+
* "desugar" complex nodes into simpler operations.
568+
* <p>
569+
* Still, some more advanced features (e.g., {@code TryFinally} operations) have not been
570+
* covered. We encourage you to consult the other resources available:
571+
*
572+
* @see <a href=
573+
* "https://github.com/oracle/graal/blob/master/truffle/docs/bytecode_dsl/UserGuide.md">User
574+
* guide</a>.
575+
*
576+
* @see <a href=
577+
* "https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/bytecode/package-summary.html">Javadoc
578+
* </a>.
579+
*
580+
* @see <a href=
581+
* "https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/bytecode/SLBytecodeRootNode.java">Simple
582+
* Language implementation</a>.
569583
*/
570584
public void testForEach() {
571585
// @formatter:off
@@ -599,28 +613,4 @@ private static BytecodeDSLTestLanguage getLanguage() {
599613
return null;
600614
}
601615

602-
/**
603-
* This tutorial demonstrated how to parse programs using visitors. It also demonstrated how to
604-
* "desugar" complex nodes into simpler operations.
605-
* <p>
606-
* Still, some more advanced features (e.g., {@code TryFinally} operations) have not been
607-
* covered. We encourage you to consult the other resources available:
608-
*
609-
* @see <a href=
610-
* "https://github.com/oracle/graal/blob/master/truffle/docs/bytecode_dsl/UserGuide.md">User
611-
* guide</a>.
612-
*
613-
* @see <a href=
614-
* "https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/bytecode/package-summary.html">Javadoc
615-
* </a>.
616-
*
617-
* @see <a href=
618-
* "https://github.com/oracle/graal/blob/master/truffle/src/com.oracle.truffle.sl/src/com/oracle/truffle/sl/bytecode/SLBytecodeRootNode.java">Simple
619-
* Language implementation</a>.
620-
*
621-
* @see <a href=
622-
* "https://github.com/oracle/graalpython/blob/master/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/bytecode_dsl/PBytecodeDSLRootNode.java">GraalPython
623-
* implementation</a>.
624-
*/
625-
626616
}

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/examples/SerializationTutorial.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public class SerializationTutorial {
9393
* {@link GenerateBytecode} specification, set {@code enableSerialization = true}. Then, rebuild
9494
* your project to update the generated interpreter.
9595
* <p>
96-
* When serialization is enabled, The Bytecode DSL generates extra methods that you can use to
96+
* When serialization is enabled, the Bytecode DSL generates extra methods that you can use to
9797
* serialize/deserialize your bytecode nodes. It also validates that all of the
9898
* non-{@code transient} fields (which will be serialized) are reachable.
9999
*/

truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/debug/package-info.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
* SOFTWARE.
4040
*/
4141

42+
/*
43+
@ApiInfo(
44+
group="Truffle"
45+
)
46+
*/
47+
4248
/**
4349
* Debug utilities for the Bytecode DSL. These features are not intended to be used in production
4450
* interpreters for performance reasons.

truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/package-info.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
* SOFTWARE.
4040
*/
4141

42+
/*
43+
@ApiInfo(
44+
group="Truffle"
45+
)
46+
*/
47+
4248
/**
4349
* The Bytecode DSL is a DSL and runtime support component of Truffle that makes it easier to
4450
* implement bytecode interpreters. Start {@link com.oracle.truffle.api.bytecode.GenerateBytecode

truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/serialization/package-info.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@
3939
* SOFTWARE.
4040
*/
4141

42+
/*
43+
@ApiInfo(
44+
group="Truffle"
45+
)
46+
*/
47+
4248
/**
4349
* Serialization-specific classes for the Bytecode DSL.
4450
*

truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/bytecode/generator/BytecodeRootNodeElement.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,10 @@ final class BytecodeRootNodeElement extends CodeTypeElement {
383383
this.add(createTransitionToCached());
384384
this.add(createUpdateBytecode());
385385

386+
// Other root node overrides.
386387
this.add(createIsInstrumentable());
387388
this.addOptional(createPrepareForInstrumentation());
389+
this.addOptional(createPrepareForCompilation());
388390

389391
this.add(createEncodeTags());
390392
if (model.enableTagInstrumentation) {
@@ -1650,6 +1652,18 @@ private CodeExecutableElement createPrepareForInstrumentation() {
16501652
return ex;
16511653
}
16521654

1655+
private CodeExecutableElement createPrepareForCompilation() {
1656+
if (!model.enableUncachedInterpreter) {
1657+
return null;
1658+
}
1659+
1660+
CodeExecutableElement ex = overrideImplementRootNodeMethod(model, "prepareForCompilation", new String[]{"rootCompilation", "compilationTier", "lastTier"});
1661+
CodeTreeBuilder b = ex.createBuilder();
1662+
// Disable compilation for the uncached interpreter.
1663+
b.startReturn().string("bytecode.getTier() != ").staticReference(types.BytecodeTier, "UNCACHED").end();
1664+
return ex;
1665+
}
1666+
16531667
private CodeExecutableElement createEncodeTags() {
16541668
CodeExecutableElement ex = new CodeExecutableElement(Set.of(PRIVATE, STATIC), type(int.class), "encodeTags");
16551669
ex.addParameter(new CodeVariableElement(arrayOf(type(Class.class)), "tags"));
@@ -13104,8 +13118,6 @@ private List<CodeExecutableElement> createContinueAt() {
1310413118
b.statement("$root.transitionToCached()");
1310513119
b.startReturn().string("startState").end();
1310613120
return methods;
13107-
} else if (tier.isUncached()) {
13108-
b.tree(GeneratorUtils.createTransferToInterpreterAndInvalidate());
1310913121
}
1311013122

1311113123
b.startDeclaration(types.VirtualFrame, "frame").startCall("ACCESS.uncheckedCast").string("frame_").string("FRAME_TYPE").end().end();
@@ -16273,6 +16285,7 @@ void lazyInit() {
1627316285
// RootNode overrides.
1627416286
this.add(createIsCloningAllowed());
1627516287
this.add(createIsCloneUninitializedSupported());
16288+
this.addOptional(createPrepareForCompilation());
1627616289
// Should appear last. Uses current method set to determine which methods need to be
1627716290
// implemented.
1627816291
this.addAll(createRootNodeProxyMethods());
@@ -16432,6 +16445,17 @@ private CodeExecutableElement createIsCloneUninitializedSupported() {
1643216445
return ex;
1643316446
}
1643416447

16448+
private CodeExecutableElement createPrepareForCompilation() {
16449+
if (!model.enableUncachedInterpreter) {
16450+
return null;
16451+
}
16452+
16453+
CodeExecutableElement ex = overrideImplementRootNodeMethod(model, "prepareForCompilation", new String[]{"rootCompilation", "compilationTier", "lastTier"});
16454+
CodeTreeBuilder b = ex.createBuilder();
16455+
b.startReturn().startCall("root.prepareForCompilation").string("rootCompilation").string("compilationTier").string("lastTier").end(2);
16456+
return ex;
16457+
}
16458+
1643516459
private List<CodeExecutableElement> createRootNodeProxyMethods() {
1643616460
List<CodeExecutableElement> result = new ArrayList<>();
1643716461

0 commit comments

Comments
 (0)