use of com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder in project graal by oracle.
the class FlatNodeGenFactory method createTypeCheckOrCast.
private IfTriple createTypeCheckOrCast(FrameState frameState, SpecializationGroup group, TypeGuard typeGuard, NodeExecutionMode specializationExecution, boolean castOnly, boolean forceImplicitCast) {
CodeTreeBuilder prepareBuilder = CodeTreeBuilder.createBuilder();
CodeTreeBuilder checkBuilder = CodeTreeBuilder.createBuilder();
int signatureIndex = typeGuard.getSignatureIndex();
LocalVariable value = frameState.getValue(signatureIndex);
TypeMirror targetType = typeGuard.getType();
if (!ElementUtils.needsCastTo(value.getTypeMirror(), targetType)) {
boolean foundImplicitSubType = false;
if (forceImplicitCast) {
List<ImplicitCastData> casts = typeSystem.lookupByTargetType(targetType);
for (ImplicitCastData cast : casts) {
if (ElementUtils.isSubtype(cast.getSourceType(), targetType)) {
foundImplicitSubType = true;
break;
}
}
}
if (!foundImplicitSubType) {
return null;
}
}
NodeExecutionData execution = node.getChildExecutions().get(signatureIndex);
CodeTreeBuilder castBuilder = prepareBuilder.create();
List<ImplicitCastData> sourceTypes = typeSystem.lookupByTargetType(targetType);
CodeTree valueReference = value.createReference();
if (sourceTypes.isEmpty()) {
checkBuilder.tree(TypeSystemCodeGenerator.check(typeSystem, targetType, valueReference));
castBuilder.tree(TypeSystemCodeGenerator.cast(typeSystem, targetType, valueReference));
} else {
List<SpecializationData> specializations = group.collectSpecializations();
List<Parameter> parameters = new ArrayList<>();
for (SpecializationData otherSpecialization : specializations) {
parameters.add(otherSpecialization.findParameterOrDie(execution));
}
if (specializationExecution.isFastPath() || specializationExecution.isGuardFallback()) {
CodeTree implicitState;
if (specializationExecution.isGuardFallback()) {
implicitState = CodeTreeBuilder.singleString("0b" + allsetMask(sourceTypes.size() + 1));
} else {
implicitState = state.createExtractInteger(frameState, typeGuard);
}
checkBuilder.tree(TypeSystemCodeGenerator.implicitCheckFlat(typeSystem, targetType, valueReference, implicitState));
castBuilder.tree(TypeSystemCodeGenerator.implicitCastFlat(typeSystem, targetType, valueReference, implicitState));
} else {
Parameter parameter = parameters.get(0);
String implicitStateName = createImplicitTypeStateLocalName(parameter);
CodeTree defaultValue = null;
prepareBuilder.declaration(context.getType(int.class), implicitStateName, defaultValue);
CodeTree specializeCall = TypeSystemCodeGenerator.implicitSpecializeFlat(typeSystem, targetType, valueReference);
checkBuilder.startParantheses();
checkBuilder.string(implicitStateName, " = ").tree(specializeCall);
checkBuilder.end();
checkBuilder.string(" != 0");
castBuilder.tree(TypeSystemCodeGenerator.implicitCastFlat(typeSystem, targetType, valueReference, CodeTreeBuilder.singleString(implicitStateName)));
}
}
if (castOnly) {
LocalVariable currentValue = frameState.getValue(execution);
CodeTreeBuilder localsBuilder = CodeTreeBuilder.createBuilder();
LocalVariable castVariable = currentValue.nextName().newType(typeGuard.getType()).accessWith(null);
frameState.setValue(execution, castVariable);
localsBuilder.tree(castVariable.createDeclaration(castBuilder.build()));
return new IfTriple(localsBuilder.build(), null, null);
} else {
return new IfTriple(prepareBuilder.build(), checkBuilder.build(), null);
}
}
use of com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder in project graal by oracle.
the class FlatNodeGenFactory method executeFastPathGroup.
private CodeTree executeFastPathGroup(final CodeTreeBuilder parent, FrameState frameState, final ExecutableTypeData currentType, SpecializationGroup group, int sharedExecutes, List<SpecializationData> allowedSpecializations) {
CodeTreeBuilder builder = parent.create();
FrameState originalFrameState = frameState.copy();
for (NodeExecutionData execution : node.getChildExecutions()) {
if (execution.getIndex() < sharedExecutes) {
// skip shared executes
continue;
}
builder.tree(createFastPathExecuteChild(builder, originalFrameState, frameState, currentType, group, execution));
}
builder.tree(visitSpecializationGroup(builder, group, currentType, frameState, allowedSpecializations, NodeExecutionMode.FAST_PATH));
if (group.hasFallthrough()) {
builder.tree(createTransferToInterpreterAndInvalidate());
builder.tree(createCallExecuteAndSpecialize(currentType, originalFrameState));
}
return builder.build();
}
use of com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder in project graal by oracle.
the class FlatNodeGenFactory method createExcludeThis.
private CodeTree createExcludeThis(CodeTreeBuilder parent, FrameState frameState, ExecutableTypeData forType, SpecializationData specialization, NodeExecutionMode mode) {
CodeTreeBuilder builder = parent.create();
// slow path might be already already locked
if (!mode.isSlowPath()) {
builder.declaration(context.getType(Lock.class), "lock", "getLock()");
}
builder.statement("lock.lock()");
builder.startTryBlock();
// pass null frame state to ensure values are reloaded.
builder.tree(this.exclude.createSet(null, new Object[] { specialization }, true, true));
builder.tree(this.state.createSet(null, new Object[] { specialization }, false, true));
if (useSpecializationClass(specialization)) {
String fieldName = createSpecializationFieldName(specialization);
builder.statement("this." + fieldName + " = null");
}
builder.end().startFinallyBlock();
builder.statement("lock.unlock()");
builder.end();
boolean hasUnexpectedResultRewrite = specialization.hasUnexpectedResultRewrite();
boolean hasReexecutingRewrite = !hasUnexpectedResultRewrite || specialization.getExceptions().size() > 1;
if (hasReexecutingRewrite) {
if (hasUnexpectedResultRewrite) {
builder.startIf().string("ex").instanceOf(context.getType(UnexpectedResultException.class)).end().startBlock();
builder.tree(createReturnUnexpectedResult(forType, true));
builder.end().startElseBlock();
builder.tree(createCallExecuteAndSpecialize(forType, frameState));
builder.end();
} else {
builder.tree(createCallExecuteAndSpecialize(forType, frameState));
}
} else {
assert hasUnexpectedResultRewrite;
builder.tree(createReturnUnexpectedResult(forType, false));
}
builder.end();
return builder.build();
}
use of com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder in project graal by oracle.
the class FlatNodeGenFactory method persistCache.
private Collection<IfTriple> persistCache(FrameState frameState, SpecializationData specialization, CacheExpression cache, CodeTree cacheValue) {
String name = createFieldName(specialization, cache.getParameter());
LocalVariable local = frameState.get(name);
CodeTree value;
if (local != null) {
// already initialized and stored don't use init.
value = local.createReference();
} else if (cacheValue == null) {
return Collections.emptyList();
} else {
value = cacheValue;
}
TypeMirror type = cache.getParameter().getType();
String frameStateInitialized = name + "$initialized";
if (frameState.getBoolean(frameStateInitialized, false)) {
return Collections.emptyList();
} else {
frameState.setBoolean(frameStateInitialized, true);
}
List<IfTriple> triples = new ArrayList<>();
CodeTreeBuilder builder = new CodeTreeBuilder(null);
Parameter parameter = cache.getParameter();
boolean useSpecializationClass = useSpecializationClass(specialization);
if (!useSpecializationClass || frameState.getBoolean(createSpecializationClassPersisted(specialization), false)) {
String insertTarget;
if (useSpecializationClass) {
insertTarget = createSpecializationLocalName(specialization);
} else {
insertTarget = "super";
}
TypeMirror nodeType = context.getType(Node.class);
TypeMirror nodeArrayType = context.getType(Node[].class);
boolean isNode = ElementUtils.isAssignable(parameter.getType(), nodeType);
boolean isNodeInterface = isNode || ElementUtils.isAssignable(type, context.getType(NodeInterface.class));
boolean isNodeArray = ElementUtils.isAssignable(type, nodeArrayType);
boolean isNodeInterfaceArray = isNodeArray || isNodeInterfaceArray(type);
if (isNodeInterface || isNodeInterfaceArray) {
builder = new CodeTreeBuilder(null);
String fieldName = createFieldName(specialization, cache.getParameter()) + "__";
String insertName = useSpecializationClass ? useInsertAccessor(specialization, !isNodeInterface) : "insert";
final TypeMirror castType;
if (isNodeInterface) {
if (isNode) {
castType = null;
} else {
castType = nodeType;
}
} else {
assert isNodeInterfaceArray;
if (isNodeArray) {
castType = null;
} else {
castType = nodeArrayType;
}
}
if (castType == null) {
CodeTreeBuilder noCast = new CodeTreeBuilder(null);
noCast.startCall(insertTarget, insertName);
noCast.tree(value);
noCast.end();
value = noCast.build();
} else {
builder.declaration(cache.getExpression().getResolvedType(), fieldName, value);
builder.startIf().string(fieldName).instanceOf(castType).end().startBlock();
builder.startStatement().startCall(insertTarget, insertName);
builder.startGroup().cast(castType).string(fieldName).end();
builder.end().end();
builder.end();
value = CodeTreeBuilder.singleString(fieldName);
}
}
}
builder.startStatement();
builder.tree(createCacheReference(frameState, specialization, cache.getParameter())).string(" = ").tree(value);
builder.end();
triples.add(new IfTriple(builder.build(), null, null));
return triples;
}
use of com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder in project graal by oracle.
the class FlatNodeGenFactory method createFastPathExecuteChild.
private CodeTree createFastPathExecuteChild(final CodeTreeBuilder parent, FrameState originalFrameState, FrameState frameState, final ExecutableTypeData currentType, SpecializationGroup group, NodeExecutionData execution) {
CodeTreeBuilder builder = parent.create();
LocalVariable var = frameState.getValue(execution);
if (var == null) {
TypeMirror targetType;
TypeGuard eliminatedGuard = null;
if (boxingEliminationEnabled) {
for (TypeGuard checkedGuard : group.getTypeGuards()) {
if (!ElementUtils.isPrimitive(checkedGuard.getType())) {
// no elimination for non primitive types
continue;
} else if (node.getChildExecutions().get(checkedGuard.getSignatureIndex()).getChild().findExecutableType(checkedGuard.getType()) == null) {
// type cannot be executed so it cannot be eliminated
continue;
}
if (checkedGuard.getSignatureIndex() == execution.getIndex()) {
eliminatedGuard = checkedGuard;
break;
}
}
}
if (eliminatedGuard != null) {
// we can optimize the type guard away by executing it
group.getTypeGuards().remove(eliminatedGuard);
targetType = eliminatedGuard.getType();
} else {
targetType = execution.getChild().findAnyGenericExecutableType(context).getReturnType();
}
var = frameState.createValue(execution, targetType).nextName();
LocalVariable fallbackVar;
List<TypeMirror> originalSourceTypes = typeSystem.lookupSourceTypes(targetType);
List<TypeMirror> sourceTypes = resolveOptimizedImplicitSourceTypes(execution, targetType);
if (sourceTypes.size() > 1) {
TypeGuard typeGuard = new TypeGuard(targetType, execution.getIndex());
TypeMirror generic = node.getPolymorphicSpecialization().findParameterOrDie(execution).getType();
fallbackVar = originalFrameState.createValue(execution, generic);
// we want to create the check tree in reverse order
Collections.reverse(sourceTypes);
CodeTree access = var.createReference();
boolean first = true;
for (TypeMirror sType : sourceTypes) {
if (ElementUtils.typeEquals(sType, targetType)) {
continue;
}
String localName = createSourceTypeLocalName(var, sType);
builder.declaration(sType, localName, CodeTreeBuilder.createBuilder().defaultValue(sType).build());
CodeTreeBuilder accessBuilder = builder.create();
accessBuilder.startParantheses();
accessBuilder.tree(state.createContainsOnly(frameState, originalSourceTypes.indexOf(sType), 1, new Object[] { typeGuard }, new Object[] { typeGuard }));
accessBuilder.string(" && ");
accessBuilder.tree(state.createIsNotAny(frameState, reachableSpecializationsArray));
accessBuilder.string(" ? ");
if (ElementUtils.isPrimitive(sType)) {
accessBuilder.string("(").type(generic).string(") ");
}
accessBuilder.string(localName);
accessBuilder.string(" : ");
if (first && ElementUtils.isPrimitive(targetType)) {
accessBuilder.string("(").type(generic).string(") ");
}
accessBuilder.tree(access);
accessBuilder.end();
access = accessBuilder.build();
first = false;
}
fallbackVar = fallbackVar.accessWith(access);
} else {
fallbackVar = var;
}
builder.tree(createAssignExecuteChild(originalFrameState, frameState, builder, execution, currentType, var));
frameState.setValue(execution, var);
originalFrameState.setValue(execution, fallbackVar);
}
return builder.build();
}
Aggregations