Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java @ 18761:a665483c3881
Truffle-DSL: new node layout implementation.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 29 Dec 2014 23:38:54 +0100 |
parents | |
children | 18c0f02fa4d2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/ImplicitCastNodeFactory.java Mon Dec 29 23:38:54 2014 +0100 @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.generator; + +import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; +import static javax.lang.model.element.Modifier.*; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.api.dsl.internal.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.java.model.*; +import com.oracle.truffle.dsl.processor.model.*; + +import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*; + +public class ImplicitCastNodeFactory { + + private final ProcessorContext context; + private final TypeData forType; + private final TypeSystemData typeSystem; + private final DSLOptions options; + private final List<TypeData> sourceTypes; + + public ImplicitCastNodeFactory(ProcessorContext context, TypeData forType) { + this.context = context; + this.forType = forType; + this.typeSystem = forType.getTypeSystem(); + this.options = typeSystem.getOptions(); + this.sourceTypes = typeSystem.lookupSourceTypes(forType); + } + + public static String typeName(TypeData type) { + return "Implicit" + getTypeId(type.getBoxedType()) + "Cast"; + } + + public static TypeMirror type(TypeData type) { + TypeSystemData typeSystem = type.getTypeSystem(); + String typeSystemName = TypeSystemCodeGenerator.typeName(typeSystem); + return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()) + "." + typeSystemName, typeName(type)); + } + + public static CodeTree create(TypeData type, CodeTree value) { + return CodeTreeBuilder.createBuilder().startStaticCall(type(type), "create").tree(value).end().build(); + } + + public static CodeTree cast(String nodeName, CodeTree value) { + return CodeTreeBuilder.createBuilder().startCall(nodeName, "cast").tree(value).end().build(); + } + + public static CodeTree check(String nodeName, CodeTree value) { + return CodeTreeBuilder.createBuilder().startCall(nodeName, "check").tree(value).end().build(); + } + + private static String seenFieldName(TypeData type) { + return "seen" + getTypeId(type.getBoxedType()); + } + + public CodeTypeElement create() { + String typeName = typeName(forType); + TypeMirror baseType = context.getType(Object.class); + CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL, STATIC), typeName, baseType); + + for (TypeData sourceType : sourceTypes) { + CodeVariableElement hasSeen = new CodeVariableElement(modifiers(PUBLIC), context.getType(boolean.class), seenFieldName(sourceType)); + hasSeen.getAnnotationMirrors().add(new CodeAnnotationMirror(context.getDeclaredType(CompilationFinal.class))); + clazz.add(hasSeen); + } + + clazz.add(createConstructor(clazz)); + if (isTypeBoxingOptimized(options.monomorphicTypeBoxingOptimization(), forType)) { + clazz.add(createIsMonomorphic()); + } + clazz.add(createCast(false)); + clazz.add(createCast(true)); + clazz.add(createCheck()); + clazz.add(createMerge(clazz)); + clazz.add(createCreate(clazz)); + + return clazz; + } + + private Element createIsMonomorphic() { + String methodName = "isMonomorphic"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName); + CodeTreeBuilder builder = method.createBuilder(); + builder.startReturn(); + String operator = ""; + for (TypeData sourceType : sourceTypes) { + builder.string(operator); + builder.string(seenFieldName(sourceType)); + operator = " ^ "; + } + builder.end(); + return method; + } + + private static Element createConstructor(CodeTypeElement clazz) { + return new CodeExecutableElement(modifiers(PRIVATE), null, clazz.getSimpleName().toString()); + } + + private Element createCreate(CodeTypeElement clazz) { + String methodName = "create"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), clazz.asType(), methodName); + method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + CodeTreeBuilder builder = method.createBuilder(); + + builder.declaration(clazz.asType(), "newCast", builder.create().startNew(clazz.asType()).end()); + + for (TypeData sourceType : sourceTypes) { + String seenField = seenFieldName(sourceType); + builder.startStatement(); + builder.string("newCast.").string(seenField).string(" = ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.end(); + } + builder.startReturn().string("newCast").end(); + return method; + } + + private Element createMerge(CodeTypeElement clazz) { + String methodName = "merge"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(void.class), methodName); + method.addParameter(new CodeVariableElement(clazz.asType(), "otherCast")); + CodeTreeBuilder builder = method.createBuilder(); + + for (TypeData sourceType : sourceTypes) { + String seenField = seenFieldName(sourceType); + builder.startStatement(); + builder.string("this.").string(seenField).string(" |= ").string("otherCast.").string(seenField); + builder.end(); + } + return method; + } + + private Element createCheck() { + String methodName = "check"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), context.getType(boolean.class), methodName); + method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + CodeTreeBuilder builder = method.createBuilder(); + + boolean elseIf = false; + for (TypeData sourceType : sourceTypes) { + elseIf = builder.startIf(elseIf); + builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.end(); + builder.startBlock().returnTrue().end(); + } + builder.returnFalse(); + return method; + } + + private Element createCast(boolean expect) { + String methodName = expect ? "expect" : "cast"; + CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), forType.getPrimitiveType(), methodName); + method.addParameter(new CodeVariableElement(typeSystem.getGenericType(), "value")); + if (expect) { + method.getThrownTypes().add(context.getType(UnexpectedResultException.class)); + } + + CodeTreeBuilder builder = method.createBuilder(); + + boolean elseIf = false; + for (TypeData sourceType : sourceTypes) { + elseIf = builder.startIf(elseIf); + builder.string(seenFieldName(sourceType)).string(" && ").tree(TypeSystemCodeGenerator.check(sourceType, "value")); + builder.end(); + builder.startBlock(); + builder.startReturn(); + CodeTree castTree = TypeSystemCodeGenerator.cast(sourceType, "value"); + ImplicitCastData cast = typeSystem.lookupCast(sourceType, forType); + if (cast != null) { + builder.tree(TypeSystemCodeGenerator.invokeImplicitCast(cast, castTree)); + } else { + builder.tree(castTree); + } + builder.end(); + builder.end(); + } + if (expect) { + builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string("value").end().end(); + } else { + builder.startStatement().startStaticCall(context.getType(CompilerDirectives.class), "transferToInterpreter").end().end(); + builder.startThrow().startNew(context.getType(AssertionError.class)).end().end(); + } + return method; + } + +}