comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/TypeSystemCodeGenerator.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 3912400fc33a
children c0fb70634640
comparison
equal deleted inserted replaced
18760:6fa3999631d8 18761:a665483c3881
21 * questions. 21 * questions.
22 */ 22 */
23 package com.oracle.truffle.dsl.processor.generator; 23 package com.oracle.truffle.dsl.processor.generator;
24 24
25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*; 25 import static com.oracle.truffle.dsl.processor.java.ElementUtils.*;
26 import static com.oracle.truffle.dsl.processor.generator.GeneratorUtils.*;
26 import static javax.lang.model.element.Modifier.*; 27 import static javax.lang.model.element.Modifier.*;
27 28
28 import java.util.*; 29 import java.util.*;
29 30
30 import javax.lang.model.type.*; 31 import javax.lang.model.type.*;
31 32
33 import com.oracle.truffle.api.nodes.*;
32 import com.oracle.truffle.dsl.processor.*; 34 import com.oracle.truffle.dsl.processor.*;
33 import com.oracle.truffle.dsl.processor.java.*; 35 import com.oracle.truffle.dsl.processor.java.*;
34 import com.oracle.truffle.dsl.processor.java.model.*; 36 import com.oracle.truffle.dsl.processor.java.model.*;
35 import com.oracle.truffle.dsl.processor.model.*; 37 import com.oracle.truffle.dsl.processor.model.*;
36 38
38 40
39 public static CodeTree cast(TypeData type, String content) { 41 public static CodeTree cast(TypeData type, String content) {
40 return cast(type, CodeTreeBuilder.singleString(content)); 42 return cast(type, CodeTreeBuilder.singleString(content));
41 } 43 }
42 44
43 public static CodeTree implicitType(TypeData type, String valueName) { 45 public static CodeTree implicitType(TypeData type, CodeTree value) {
44 if (type.isGeneric()) { 46 if (type.isGeneric()) {
45 return CodeTreeBuilder.singleString(valueName); 47 return value;
46 } 48 }
47 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 49 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
48 TypeSystemData typeSystem = type.getTypeSystem(); 50 TypeSystemData typeSystem = type.getTypeSystem();
49 builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).string(valueName); 51 builder.startStaticCall(createTypeSystemGen(typeSystem), getImplicitClass(type)).tree(value);
50 builder.end(); 52 builder.end();
51 return builder.getRoot(); 53 return builder.build();
52 } 54 }
53 55
54 public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) { 56 public static CodeTree invokeImplicitCast(ImplicitCastData cast, CodeTree expression) {
55 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 57 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
56 TypeSystemData typeSystem = cast.getTargetType().getTypeSystem(); 58 TypeSystemData typeSystem = cast.getTargetType().getTypeSystem();
57 builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression); 59 builder.startStaticCall(createTypeSystemGen(typeSystem), cast.getMethodName()).tree(expression);
58 builder.end(); 60 builder.end();
59 return builder.getRoot(); 61 return builder.build();
60 } 62 }
61 63
62 public static CodeTree implicitCheck(TypeData type, String valueName, String typeHint) { 64 public static CodeTree implicitCheck(TypeData type, CodeTree value, String typeHint) {
63 if (type.isGeneric()) { 65 if (type.isGeneric()) {
64 return CodeTreeBuilder.singleString(valueName); 66 return value;
65 } 67 }
66 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 68 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
67 TypeSystemData typeSystem = type.getTypeSystem(); 69 TypeSystemData typeSystem = type.getTypeSystem();
68 builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).string(valueName); 70 builder.startStaticCall(createTypeSystemGen(typeSystem), isImplicitTypeMethodName(type)).tree(value);
69 if (typeHint != null) { 71 if (typeHint != null) {
70 builder.string(typeHint); 72 builder.string(typeHint);
71 } 73 }
72 builder.end(); 74 builder.end();
73 return builder.getRoot(); 75 return builder.build();
74 } 76 }
75 77
76 public static CodeTree implicitCast(TypeData type, String valueName, String typeHint) { 78 public static CodeTree implicitExpect(TypeData type, CodeTree value, String typeHint) {
77 if (type.isGeneric()) { 79 if (type.isGeneric()) {
78 return CodeTreeBuilder.singleString(valueName); 80 return value;
79 } 81 }
80 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 82 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
81 TypeSystemData typeSystem = type.getTypeSystem(); 83 TypeSystemData typeSystem = type.getTypeSystem();
82 builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).string(valueName); 84 builder.startStaticCall(createTypeSystemGen(typeSystem), expectImplicitTypeMethodName(type)).tree(value);
83 if (typeHint != null) { 85 if (typeHint != null) {
84 builder.string(typeHint); 86 builder.string(typeHint);
85 } 87 }
86 builder.end(); 88 builder.end();
87 return builder.getRoot(); 89 return builder.build();
90 }
91
92 public static CodeTree implicitCast(TypeData type, CodeTree value, String typeHint) {
93 if (type.isGeneric()) {
94 return value;
95 }
96 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
97 TypeSystemData typeSystem = type.getTypeSystem();
98 builder.startStaticCall(createTypeSystemGen(typeSystem), asImplicitTypeMethodName(type)).tree(value);
99 if (typeHint != null) {
100 builder.string(typeHint);
101 }
102 builder.end();
103 return builder.build();
88 } 104 }
89 105
90 public static CodeTree cast(TypeData type, CodeTree content) { 106 public static CodeTree cast(TypeData type, CodeTree content) {
91 if (type.isGeneric()) { 107 if (type.isGeneric()) {
92 return content; 108 return content;
97 if (type.isDefaultCast()) { 113 if (type.isDefaultCast()) {
98 builder.cast(type.getPrimitiveType(), content); 114 builder.cast(type.getPrimitiveType(), content);
99 } else { 115 } else {
100 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end(); 116 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeCasts().get(0).getMethodName()).tree(content).end();
101 } 117 }
102 return builder.getRoot(); 118 return builder.build();
103 } 119 }
104 120
105 public static CodeTree expect(TypeData type, CodeTree content) { 121 public static CodeTree expect(TypeData type, CodeTree content) {
106 if (type.isGeneric()) { 122 if (type.isGeneric() || type.isVoid()) {
107 return content; 123 return content;
108 } 124 }
109 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); 125 CodeTreeBuilder builder = CodeTreeBuilder.createBuilder();
110 TypeSystemData typeSystem = type.getTypeSystem(); 126 TypeSystemData typeSystem = type.getTypeSystem();
111 builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end(); 127 builder.startStaticCall(createTypeSystemGen(typeSystem), expectTypeMethodName(type)).tree(content).end();
112 return builder.getRoot(); 128 return builder.build();
113 } 129 }
114 130
115 private static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) { 131 public static CodeTree expect(TypeData sourceType, TypeData targetType, CodeTree content) {
132 if (sourceType != null && !sourceType.needsCastTo(targetType)) {
133 return content;
134 } else {
135 return expect(targetType, content);
136 }
137 }
138
139 public static CodeTypeMirror createTypeSystemGen(TypeSystemData typeSystem) {
116 return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem)); 140 return new GeneratedTypeMirror(ElementUtils.getPackageName(typeSystem.getTemplateType()), typeName(typeSystem));
117 } 141 }
118 142
119 public static CodeTree check(TypeData type, String content) { 143 public static CodeTree check(TypeData type, String content) {
120 return check(type, CodeTreeBuilder.singleString(content)); 144 return check(type, CodeTreeBuilder.singleString(content));
130 if (type.isDefaultCheck()) { 154 if (type.isDefaultCheck()) {
131 builder.instanceOf(content, type.getBoxedType()); 155 builder.instanceOf(content, type.getBoxedType());
132 } else { 156 } else {
133 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end(); 157 builder.startStaticCall(typeSystem.getTemplateType().asType(), type.getTypeChecks().get(0).getMethodName()).tree(content).end();
134 } 158 }
135 return builder.getRoot(); 159 return builder.build();
136 } 160 }
137 161
138 public static String isTypeMethodName(TypeData type) { 162 public static String isTypeMethodName(TypeData type) {
139 return "is" + ElementUtils.getTypeId(type.getBoxedType()); 163 return "is" + ElementUtils.getTypeId(type.getBoxedType());
140 } 164 }
147 return "as" + ElementUtils.getTypeId(type.getBoxedType()); 171 return "as" + ElementUtils.getTypeId(type.getBoxedType());
148 } 172 }
149 173
150 static String asImplicitTypeMethodName(TypeData type) { 174 static String asImplicitTypeMethodName(TypeData type) {
151 return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType()); 175 return "asImplicit" + ElementUtils.getTypeId(type.getBoxedType());
176 }
177
178 static String expectImplicitTypeMethodName(TypeData type) {
179 return "expectImplicit" + ElementUtils.getTypeId(type.getBoxedType());
152 } 180 }
153 181
154 static String getImplicitClass(TypeData type) { 182 static String getImplicitClass(TypeData type) {
155 return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class"; 183 return "getImplicit" + ElementUtils.getTypeId(type.getBoxedType()) + "Class";
156 } 184 }
168 return createConstantName(getSimpleName(type.getTemplateType().asType())); 196 return createConstantName(getSimpleName(type.getTemplateType().asType()));
169 } 197 }
170 198
171 @Override 199 @Override
172 public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) { 200 public CodeTypeElement create(ProcessorContext context, TypeSystemData typeSystem) {
173 return new TypeClassFactory(context, typeSystem).create(); 201 CodeTypeElement clazz = new TypeClassFactory(context, typeSystem).create();
202
203 if (typeSystem.getOptions().useNewLayout()) {
204 clazz.add(new TypeSystemNodeFactory(context, typeSystem).create());
205
206 if (typeSystem.getOptions().implicitCastOptimization().isMergeCasts()) {
207 for (TypeData type : typeSystem.getTypes()) {
208 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
209 if (sourceTypes.size() > 1) {
210 clazz.add(new ImplicitCastNodeFactory(context, type).create());
211 }
212 }
213 }
214 }
215 return clazz;
174 } 216 }
175 217
176 private static class TypeClassFactory { 218 private static class TypeClassFactory {
177 219
178 private static final String LOCAL_VALUE = "value"; 220 private static final String LOCAL_VALUE = "value";
185 this.typeSystem = typeSystem; 227 this.typeSystem = typeSystem;
186 } 228 }
187 229
188 public CodeTypeElement create() { 230 public CodeTypeElement create() {
189 String name = typeName(typeSystem); 231 String name = typeName(typeSystem);
190 CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType(), false); 232 CodeTypeElement clazz = GeneratorUtils.createClass(typeSystem, null, modifiers(PUBLIC, FINAL), name, typeSystem.getTemplateType().asType());
191 233
192 clazz.add(GeneratorUtils.createConstructorUsingFields(context, modifiers(PROTECTED), clazz)); 234 clazz.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), clazz));
193 CodeVariableElement singleton = createSingleton(clazz); 235 CodeVariableElement singleton = createSingleton(clazz);
194 clazz.add(singleton); 236 clazz.add(singleton);
195 237
196 for (TypeData type : typeSystem.getTypes()) { 238 for (TypeData type : typeSystem.getTypes()) {
197 if (type.isGeneric() || type.isVoid()) { 239 if (type.isVoid() || type.isGeneric()) {
198 continue; 240 continue;
199 } 241 }
242
200 clazz.addOptional(createIsTypeMethod(type)); 243 clazz.addOptional(createIsTypeMethod(type));
201 clazz.addOptional(createAsTypeMethod(type)); 244 clazz.addOptional(createAsTypeMethod(type));
202 245
203 for (TypeData sourceType : collectExpectSourceTypes(type)) { 246 for (TypeData sourceType : collectExpectSourceTypes(type)) {
204 clazz.addOptional(createExpectTypeMethod(type, sourceType)); 247 clazz.addOptional(createExpectTypeMethod(type, sourceType));
205 } 248 }
206 249
207 clazz.addOptional(createAsImplicitTypeMethod(type, true)); 250 if (type.hasImplicitSourceTypes()) {
208 clazz.addOptional(createAsImplicitTypeMethod(type, false)); 251 clazz.add(createAsImplicitTypeMethod(type, false));
209 clazz.addOptional(createIsImplicitTypeMethod(type, true)); 252 if (typeSystem.getOptions().implicitCastOptimization().isNone()) {
210 clazz.addOptional(createIsImplicitTypeMethod(type, false)); 253 clazz.add(createExpectImplicitTypeMethod(type, false));
211 clazz.addOptional(createGetTypeIndex(type)); 254 }
255 clazz.add(createIsImplicitTypeMethod(type, false));
256
257 if (typeSystem.getOptions().implicitCastOptimization().isDuplicateTail()) {
258 clazz.add(createAsImplicitTypeMethod(type, true));
259 clazz.add(createExpectImplicitTypeMethod(type, true));
260 clazz.add(createIsImplicitTypeMethod(type, true));
261 clazz.add(createGetImplicitClass(type));
262 }
263 }
212 } 264 }
213 265
214 return clazz; 266 return clazz;
215 } 267 }
216 268
236 288
237 return field; 289 return field;
238 } 290 }
239 291
240 private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) { 292 private CodeExecutableElement createIsImplicitTypeMethod(TypeData type, boolean typed) {
241 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type);
242 if (casts.isEmpty()) {
243 return null;
244 }
245 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type)); 293 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(boolean.class), TypeSystemCodeGenerator.isImplicitTypeMethodName(type));
246 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); 294 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
247 if (typed) { 295 if (typed) {
248 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); 296 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
249 } 297 }
273 builder.end(); 321 builder.end();
274 builder.end(); 322 builder.end();
275 return method; 323 return method;
276 } 324 }
277 325
278 private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean typed) { 326 private CodeExecutableElement createAsImplicitTypeMethod(TypeData type, boolean useTypeHint) {
279 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); 327 String name = asImplicitTypeMethodName(type);
280 if (casts.isEmpty()) { 328 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name);
281 return null; 329 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
282 } 330 if (useTypeHint) {
283 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), TypeSystemCodeGenerator.asImplicitTypeMethodName(type));
284 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
285 if (typed) {
286 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint")); 331 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
287 } 332 }
288 333
289 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); 334 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
290 335
291 CodeTreeBuilder builder = method.createBuilder(); 336 CodeTreeBuilder builder = method.createBuilder();
292 boolean elseIf = false; 337 boolean elseIf = false;
293 for (TypeData sourceType : sourceTypes) { 338 for (TypeData sourceType : sourceTypes) {
294 elseIf = builder.startIf(elseIf); 339 elseIf = builder.startIf(elseIf);
295 if (typed) { 340 if (useTypeHint) {
296 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType()); 341 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
297 } else { 342 } else {
298 builder.tree(check(sourceType, LOCAL_VALUE)); 343 builder.tree(check(sourceType, LOCAL_VALUE));
299 } 344 }
300 345
312 builder.end(); 357 builder.end();
313 builder.end(); 358 builder.end();
314 } 359 }
315 360
316 builder.startElseBlock(); 361 builder.startElseBlock();
317 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); 362 builder.tree(createTransferToInterpreterAndInvalidate());
318 builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); 363 builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
319 builder.end(); 364 builder.end();
320 return method; 365 return method;
321 } 366 }
322 367
323 private CodeExecutableElement createGetTypeIndex(TypeData type) { 368 private CodeExecutableElement createExpectImplicitTypeMethod(TypeData type, boolean useTypeHint) {
324 List<ImplicitCastData> casts = typeSystem.lookupByTargetType(type); 369 String name = expectImplicitTypeMethodName(type);
325 if (casts.isEmpty()) { 370 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), type.getPrimitiveType(), name);
326 return null; 371 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
327 } 372 if (useTypeHint) {
373 method.addParameter(new CodeVariableElement(context.getType(Class.class), "typeHint"));
374 }
375 method.getThrownTypes().add(context.getType(UnexpectedResultException.class));
376
377 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
378
379 CodeTreeBuilder builder = method.createBuilder();
380 boolean elseIf = false;
381 for (TypeData sourceType : sourceTypes) {
382 elseIf = builder.startIf(elseIf);
383 if (useTypeHint) {
384 builder.string("typeHint == ").typeLiteral(sourceType.getPrimitiveType());
385 builder.string(" && ");
386 }
387 builder.tree(check(sourceType, LOCAL_VALUE));
388
389 builder.end().startBlock();
390
391 builder.startReturn();
392 ImplicitCastData cast = typeSystem.lookupCast(sourceType, type);
393 if (cast != null) {
394 builder.startCall(cast.getMethodName());
395 }
396 builder.tree(cast(sourceType, LOCAL_VALUE)).end();
397 if (cast != null) {
398 builder.end();
399 }
400 builder.end();
401 builder.end();
402 }
403
404 builder.startElseBlock();
405 builder.startThrow().startNew(context.getType(UnexpectedResultException.class)).string(LOCAL_VALUE).end().end();
406 builder.end();
407 return method;
408 }
409
410 private CodeExecutableElement createGetImplicitClass(TypeData type) {
328 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type)); 411 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), context.getType(Class.class), TypeSystemCodeGenerator.getImplicitClass(type));
329 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE)); 412 method.addParameter(new CodeVariableElement(context.getType(Object.class), LOCAL_VALUE));
330 413
331 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type); 414 List<TypeData> sourceTypes = typeSystem.lookupSourceTypes(type);
332 CodeTreeBuilder builder = method.createBuilder(); 415 CodeTreeBuilder builder = method.createBuilder();
338 builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end(); 421 builder.startReturn().typeLiteral(sourceType.getPrimitiveType()).end();
339 builder.end(); 422 builder.end();
340 } 423 }
341 424
342 builder.startElseBlock(); 425 builder.startElseBlock();
343 builder.startStatement().startStaticCall(context.getTruffleTypes().getCompilerDirectives(), "transferToInterpreterAndInvalidate").end().end(); 426 builder.tree(createTransferToInterpreterAndInvalidate());
344 builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end(); 427 builder.startThrow().startNew(context.getType(IllegalArgumentException.class)).doubleQuote("Illegal type ").end().end();
345 builder.end(); 428 builder.end();
346 429
347 return method; 430 return method;
348 } 431 }