# HG changeset patch # User Lukas Stadler # Date 1360594570 -3600 # Node ID 28371edb0d4fb9961cd4e9c29b7c49ad27e367f8 # Parent 4a6646d8eb87a42ea845c3fac1fecf8f895a310c# Parent 859f7ec58a71bf600909aec53f93b340d9c387e9 Merge diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java --- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Mon Feb 11 15:56:10 2013 +0100 @@ -37,7 +37,7 @@ CodeGenTest test = new CodeGenTest() { @Override - public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) { + public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64Assembler asm = new AMD64Assembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Int); asm.movl(ret, 8472); @@ -53,7 +53,7 @@ CodeGenTest test = new CodeGenTest() { @Override - public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) { + public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Double); compResult.recordDataReference(asm.codeBuffer.position(), Constant.forDouble(84.72), 8, false); diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Feb 11 15:56:10 2013 +0100 @@ -201,7 +201,7 @@ emitByte(op2 | encode(dst) << 3 | encode(src)); } - private void emitOperandHelper(Register reg, Address addr) { + protected void emitOperandHelper(Register reg, Address addr) { Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None; Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None; diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Feb 11 15:56:10 2013 +0100 @@ -38,7 +38,7 @@ public interface CodeGenTest { - Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig); + Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); } public AssemblerTest() { @@ -51,17 +51,28 @@ CompilationResult compResult = new CompilationResult(); - Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig); + Signature sig = method.getSignature(); + JavaType retType = sig.getReturnType(null); + JavaType[] argTypes = new JavaType[sig.getParameterCount(false)]; + for (int i = 0; i < argTypes.length; i++) { + argTypes[i] = sig.getParameterType(i, null); + } + CallingConvention cc = registerConfig.getCallingConvention(CallingConvention.Type.JavaCallee, retType, argTypes, codeCache.getTarget(), false); + + Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position()); return codeCache.addMethod(method, compResult, null); } - protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { + protected Object runTest(String methodName, CodeGenTest test, Object... args) { Method method = getMethod(methodName); InstalledCode code = assembleMethod(method, test); + return code.executeVarargs(args); + } - Object actual = code.executeVarargs(args); + protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { + Object actual = runTest(methodName, test, args); Assert.assertEquals("unexpected return value: " + actual, actual, expected); } } diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java --- a/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/Generic.java Mon Feb 11 15:56:10 2013 +0100 @@ -30,4 +30,7 @@ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) public @interface Generic { + + boolean useSpecializations() default true; + } diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/GenericParser.java Mon Feb 11 15:56:10 2013 +0100 @@ -53,7 +53,9 @@ @Override public SpecializationData create(TemplateMethod method) { - return new SpecializationData(method, true, false); + SpecializationData data = new SpecializationData(method, true, false); + data.setUseSpecializationsForGeneric(Utils.getAnnotationValueBoolean(data.getMarkerAnnotation(), "useSpecializations")); + return data; } @Override diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Mon Feb 11 15:56:10 2013 +0100 @@ -427,27 +427,32 @@ addValueParameters(method, node.getGenericSpecialization(), true); CodeTreeBuilder builder = method.createBuilder(); - boolean ifStarted = false; - for (int i = 0; i < node.getSpecializations().length; i++) { - SpecializationData specialization = node.getSpecializations()[i]; - if (specialization.isUninitialized()) { - continue; - } - if (!specialization.isGeneric()) { - if (!ifStarted) { - builder.startIf(); - ifStarted = true; + + if (node.getGenericSpecialization().isUseSpecializationsForGeneric()) { + boolean ifStarted = false; + for (int i = 0; i < node.getSpecializations().length; i++) { + SpecializationData specialization = node.getSpecializations()[i]; + if (specialization.isUninitialized()) { + continue; + } + if (!specialization.isGeneric()) { + if (!ifStarted) { + builder.startIf(); + ifStarted = true; + } else { + builder.startElseIf(); + } + emitGuards(getContext(), builder, "", specialization, false, true); + builder.end().startBlock(); } else { - builder.startElseIf(); + builder.startElseBlock(); } - emitGuards(getContext(), builder, "", specialization, false, true); - builder.end().startBlock(); - } else { - builder.startElseBlock(); + + emitInvokeDoMethod(builder, specialization, 0); + builder.end(); } - - emitInvokeDoMethod(builder, specialization, 0); - builder.end(); + } else { + emitInvokeDoMethod(builder, node.getGenericSpecialization(), 0); } return method; } @@ -529,57 +534,77 @@ NodeData node = specialization.getNode(); TypeSystemData typeSystem = node.getTypeSystem(); - if (!type.isVoid()) { - builder.startStatement().type(specialization.getReturnType().getActualType()).string(" result").end(); - } - + ExecutableTypeData castedType = node.findExecutableType(type); TypeData primaryType = specialization.getReturnType().getActualTypeData(typeSystem); ExecutableTypeData execType = specialization.getNode().findExecutableType(primaryType); - boolean needsTry = !specialization.getReturnType().getActualTypeData(typeSystem).isGeneric(); - if (needsTry) { - builder.startTryBlock(); - } + boolean needsTry = execType.hasUnexpectedValue(getContext()); + boolean returnVoid = type.isVoid(); - builder.startStatement(); - if (!type.isVoid()) { - builder.string("result = "); - } - buildExecute(builder, null, execType); - builder.end(); // statement + CodeTree primaryExecuteCall = null; + + CodeTreeBuilder executeBuilder = CodeTreeBuilder.createBuilder(); + buildExecute(executeBuilder, null, execType); + primaryExecuteCall = executeBuilder.getRoot(); if (needsTry) { - builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + if (!returnVoid) { + builder.declaration(primaryType.getPrimitiveType(), "value"); + } + builder.startTryBlock(); - if (!type.isVoid()) { - builder.startReturn(); - if (!type.isGeneric()) { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(type)); - } + if (returnVoid) { + builder.statement(primaryExecuteCall); + } else { + builder.startStatement(); + builder.string("value = "); + builder.tree(primaryExecuteCall); + builder.end(); + } - builder.string("ex.getResult()"); + builder.end().startCatchBlock(getUnexpectedValueException(), "ex"); + if (returnVoid) { + builder.string("// ignore").newLine(); + } else { + builder.startReturn(); + builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); + builder.end(); + } + builder.end(); - if (!type.isGeneric()) { - builder.end().end(); - } - builder.end(); // return + if (!returnVoid) { + builder.startReturn(); + builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("value"))); + builder.end(); + } + } else { + if (returnVoid) { + builder.statement(primaryExecuteCall); } else { - builder.string("// ignore").newLine(); + builder.startReturn(); + builder.tree(castPrimaryExecute(node, castedType, primaryExecuteCall)); + builder.end(); } } - builder.end(); // try/catch + } + + private CodeTree castPrimaryExecute(NodeData node, ExecutableTypeData castedType, CodeTree value) { + if (castedType.getType().isVoid()) { + return value; + } + if (castedType.getType().isGeneric()) { + return value; + } - if (!type.isVoid()) { - builder.startReturn(); - if (!type.isGeneric()) { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(type)); - } - builder.string("result"); - if (!type.isGeneric()) { - builder.end().end(); - } - builder.end(); // return + CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + if (castedType.hasUnexpectedValue(getContext())) { + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType())); + } else { + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.asTypeMethodName(castedType.getType())); } + builder.tree(value); + builder.end().end(); + return builder.getRoot(); } private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { @@ -794,16 +819,22 @@ addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true); specializeCall.end().end(); + TypeData expectedType = currentSpecialization.getReturnType().getActualTypeData(currentSpecialization.getNode().getTypeSystem()); if (canThrowUnexpected) { builder.startReturn(); - TypeData expectedType = currentSpecialization.getReturnType().getActualTypeData(currentSpecialization.getNode().getTypeSystem()); startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); builder.tree(specializeCall.getRoot()); builder.end().end(); builder.end(); // return } else { builder.startReturn(); - builder.tree(specializeCall.getRoot()); + if (!expectedType.isVoid() && !expectedType.isGeneric()) { + startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.asTypeMethodName(expectedType)); + builder.tree(specializeCall.getRoot()); + builder.end().end(); + } else { + builder.tree(specializeCall.getRoot()); + } builder.end(); } diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Mon Feb 11 15:56:10 2013 +0100 @@ -128,22 +128,29 @@ public ExecutableTypeData findGenericExecutableType(ProcessorContext context) { List types = findGenericExecutableTypes(context); - if (types.size() == 1) { + if (types.isEmpty()) { + return null; + } else if (types.size() == 1) { return types.get(0); - } else { - ExecutableTypeData execType = null; - for (ExecutableTypeData type : types) { - TypeData returnType = type.getReturnType().getActualTypeData(getTypeSystem()); - if (!returnType.isVoid()) { - if (execType != null) { - // multiple generic types not allowed - return null; - } - execType = type; + } else if (types.size() == 2) { + if (types.get(0).getType().isVoid()) { + return types.get(1); + } else if (types.get(1).getType().isVoid()) { + return types.get(0); + } + } + + ExecutableTypeData execType = null; + for (ExecutableTypeData type : types) { + TypeData returnType = type.getReturnType().getActualTypeData(getTypeSystem()); + if (returnType.isGeneric()) { + if (execType != null) { + return null; } + execType = type; } - return execType; } + return execType; } private List findGenericExecutableTypes(ProcessorContext context) { diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Mon Feb 11 15:56:10 2013 +0100 @@ -33,7 +33,7 @@ private final SpecializationThrowsData[] exceptions; private SpecializationGuardData[] guards; private ShortCircuitData[] shortCircuits; - + private boolean useSpecializationsForGeneric = true; private NodeData node; public SpecializationData(TemplateMethod template, int order, SpecializationThrowsData[] exceptions) { @@ -97,6 +97,14 @@ return shortCircuits; } + void setUseSpecializationsForGeneric(boolean useSpecializationsForGeneric) { + this.useSpecializationsForGeneric = useSpecializationsForGeneric; + } + + public boolean isUseSpecializationsForGeneric() { + return useSpecializationsForGeneric; + } + public SpecializationData findNextSpecialization() { SpecializationData[] specializations = node.getSpecializations(); for (int i = 0; i < specializations.length - 1; i++) { diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ParameterSpec.java Mon Feb 11 15:56:10 2013 +0100 @@ -66,7 +66,7 @@ } private static TypeMirror[] nodeTypeMirrors(NodeData nodeData) { - List typeMirrors = new ArrayList<>(); + Set typeMirrors = new LinkedHashSet<>(); for (ExecutableTypeData typeData : nodeData.getExecutableTypes()) { typeMirrors.add(typeData.getType().getPrimitiveType()); diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethodParser.java Mon Feb 11 15:56:10 2013 +0100 @@ -233,10 +233,9 @@ return new ActualParameter(specification, resolvedType); } - protected static List createTypeDefinitions(ParameterSpec returnType, List parameters) { + protected List createTypeDefinitions(ParameterSpec returnType, List parameters) { List typeDefs = new ArrayList<>(); - TypeMirror[] types = returnType.getAllowedTypes(); List allParams = new ArrayList<>(); allParams.add(returnType); allParams.addAll(parameters); @@ -244,10 +243,11 @@ int defIndex = 0; for (ParameterSpec spec : allParams) { TypeMirror[] allowedTypes = spec.getAllowedTypes(); + TypeMirror[] types = spec.getAllowedTypes(); if (types != null && allowedTypes.length > 1) { TypeDef foundDef = null; for (TypeDef def : typeDefs) { - if (Arrays.equals(spec.getAllowedTypes(), def.getTypes())) { + if (Arrays.equals(allowedTypes, def.getTypes())) { foundDef = def; break; } diff -r 4a6646d8eb87 -r 28371edb0d4f graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Mon Feb 11 15:55:27 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/typesystem/TypeSystemCodeGenerator.java Mon Feb 11 15:56:10 2013 +0100 @@ -215,6 +215,7 @@ method.addParameter(new CodeVariableElement(getContext().getType(Object.class), LOCAL_VALUE)); CodeTreeBuilder body = method.createBuilder(); + body.startAssert().startCall(isTypeMethodName(type)).string(LOCAL_VALUE).end().end(); body.startReturn().cast(type.getPrimitiveType(), body.create().string(LOCAL_VALUE).getTree()).end(); return method; @@ -233,5 +234,6 @@ return method; } + } }