OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // Inside closure redirect references to itself to [:this:]. | 351 // Inside closure redirect references to itself to [:this:]. |
352 HInstruction thisInstruction = new HThis(); | 352 HInstruction thisInstruction = new HThis(); |
353 builder.add(thisInstruction); | 353 builder.add(thisInstruction); |
354 updateLocal(closureData.closureElement, thisInstruction); | 354 updateLocal(closureData.closureElement, thisInstruction); |
355 } else if (function.isInstanceMember() | 355 } else if (function.isInstanceMember() |
356 || function.isGenerativeConstructor()) { | 356 || function.isGenerativeConstructor()) { |
357 // Once closures have been mapped to classes their instance members might | 357 // Once closures have been mapped to classes their instance members might |
358 // not have any thisElement if the closure was created inside a static | 358 // not have any thisElement if the closure was created inside a static |
359 // context. | 359 // context. |
360 ClassElement cls = function.getEnclosingClass(); | 360 ClassElement cls = function.getEnclosingClass(); |
361 Type type = cls.computeType(builder.compiler); | 361 DartType type = cls.computeType(builder.compiler); |
362 HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type)); | 362 HInstruction thisInstruction = new HThis(new HBoundedType.nonNull(type)); |
363 builder.add(thisInstruction); | 363 builder.add(thisInstruction); |
364 directLocals[closureData.thisElement] = thisInstruction; | 364 directLocals[closureData.thisElement] = thisInstruction; |
365 } | 365 } |
366 } | 366 } |
367 | 367 |
368 bool hasValueForDirectLocal(Element element) { | 368 bool hasValueForDirectLocal(Element element) { |
369 assert(element !== null); | 369 assert(element !== null); |
370 assert(isAccessedDirectly(element)); | 370 assert(isAccessedDirectly(element)); |
371 return directLocals[element] !== null; | 371 return directLocals[element] !== null; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 | 444 |
445 HType cachedTypeOfThis; | 445 HType cachedTypeOfThis; |
446 | 446 |
447 HInstruction readThis() { | 447 HInstruction readThis() { |
448 HInstruction res = readLocal(closureData.thisElement); | 448 HInstruction res = readLocal(closureData.thisElement); |
449 if (res.guaranteedType === null) { | 449 if (res.guaranteedType === null) { |
450 if (cachedTypeOfThis === null) { | 450 if (cachedTypeOfThis === null) { |
451 assert(closureData.isClosure()); | 451 assert(closureData.isClosure()); |
452 Element element = closureData.thisElement; | 452 Element element = closureData.thisElement; |
453 ClassElement cls = element.enclosingElement.getEnclosingClass(); | 453 ClassElement cls = element.enclosingElement.getEnclosingClass(); |
454 Type type = cls.computeType(builder.compiler); | 454 DartType type = cls.computeType(builder.compiler); |
455 cachedTypeOfThis = new HBoundedType.nonNull(type); | 455 cachedTypeOfThis = new HBoundedType.nonNull(type); |
456 } | 456 } |
457 res.guaranteedType = cachedTypeOfThis; | 457 res.guaranteedType = cachedTypeOfThis; |
458 } | 458 } |
459 return res; | 459 return res; |
460 } | 460 } |
461 | 461 |
462 HLocalValue getLocal(Element element) { | 462 HLocalValue getLocal(Element element) { |
463 // If the element is a parameter, we already have a | 463 // If the element is a parameter, we already have a |
464 // HParameterValue for it. We cannot create another one because | 464 // HParameterValue for it. We cannot create another one because |
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 HInstruction potentiallyCheckType(HInstruction original, | 1264 HInstruction potentiallyCheckType(HInstruction original, |
1265 Element sourceElement) { | 1265 Element sourceElement) { |
1266 if (!compiler.enableTypeAssertions) return original; | 1266 if (!compiler.enableTypeAssertions) return original; |
1267 return convertType(original, sourceElement, | 1267 return convertType(original, sourceElement, |
1268 HTypeConversion.CHECKED_MODE_CHECK); | 1268 HTypeConversion.CHECKED_MODE_CHECK); |
1269 } | 1269 } |
1270 | 1270 |
1271 HInstruction convertType(HInstruction original, | 1271 HInstruction convertType(HInstruction original, |
1272 Element sourceElement, | 1272 Element sourceElement, |
1273 int kind) { | 1273 int kind) { |
1274 Type type = sourceElement.computeType(compiler); | 1274 DartType type = sourceElement.computeType(compiler); |
1275 if (type === null) return original; | 1275 if (type === null) return original; |
1276 if (type.element === compiler.dynamicClass) return original; | 1276 if (type.element === compiler.dynamicClass) return original; |
1277 if (type.element === compiler.objectClass) return original; | 1277 if (type.element === compiler.objectClass) return original; |
1278 | 1278 |
1279 // If the original can't be null, type conversion also can't produce null. | 1279 // If the original can't be null, type conversion also can't produce null. |
1280 bool canBeNull = original.guaranteedType.canBeNull(); | 1280 bool canBeNull = original.guaranteedType.canBeNull(); |
1281 HType convertedType = | 1281 HType convertedType = |
1282 new HType.fromBoundedType(type, compiler, canBeNull); | 1282 new HType.fromBoundedType(type, compiler, canBeNull); |
1283 | 1283 |
1284 // No need to convert if we know the instruction has | 1284 // No need to convert if we know the instruction has |
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2064 Node argument = node.arguments.head; | 2064 Node argument = node.arguments.head; |
2065 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); | 2065 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); |
2066 bool isNot = false; | 2066 bool isNot = false; |
2067 // TODO(ngeoffray): Duplicating pattern in resolver. We should | 2067 // TODO(ngeoffray): Duplicating pattern in resolver. We should |
2068 // add a new kind of node. | 2068 // add a new kind of node. |
2069 if (typeAnnotation == null) { | 2069 if (typeAnnotation == null) { |
2070 typeAnnotation = argument.asSend().receiver; | 2070 typeAnnotation = argument.asSend().receiver; |
2071 isNot = true; | 2071 isNot = true; |
2072 } | 2072 } |
2073 | 2073 |
2074 Type type = elements.getType(typeAnnotation); | 2074 DartType type = elements.getType(typeAnnotation); |
2075 HInstruction typeInfo = null; | 2075 HInstruction typeInfo = null; |
2076 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 2076 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
2077 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); | 2077 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
2078 typeInfo = pop(); | 2078 typeInfo = pop(); |
2079 } | 2079 } |
2080 if (type.element.kind === ElementKind.TYPE_VARIABLE) { | 2080 if (type.element.kind === ElementKind.TYPE_VARIABLE) { |
2081 // TODO(karlklose): We emulate the behavior of the old frog | 2081 // TODO(karlklose): We emulate the behavior of the old frog |
2082 // compiler and answer true to any is check involving a type variable | 2082 // compiler and answer true to any is check involving a type variable |
2083 // -- both is T and is !T -- until we have a proper implementation of | 2083 // -- both is T and is !T -- until we have a proper implementation of |
2084 // reified generics. | 2084 // reified generics. |
2085 stack.add(graph.addConstantBool(true)); | 2085 stack.add(graph.addConstantBool(true)); |
2086 } else { | 2086 } else { |
2087 HInstruction instruction; | 2087 HInstruction instruction; |
2088 if (typeInfo !== null) { | 2088 if (typeInfo !== null) { |
2089 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); | 2089 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); |
2090 } else { | 2090 } else { |
2091 instruction = new HIs(type, expression); | 2091 instruction = new HIs(type, expression); |
2092 } | 2092 } |
2093 if (isNot) { | 2093 if (isNot) { |
2094 add(instruction); | 2094 add(instruction); |
2095 instruction = new HNot(instruction); | 2095 instruction = new HNot(instruction); |
2096 } | 2096 } |
2097 push(instruction); | 2097 push(instruction); |
2098 } | 2098 } |
2099 } else if (const SourceString("as") == op.source) { | 2099 } else if (const SourceString("as") == op.source) { |
2100 visit(node.receiver); | 2100 visit(node.receiver); |
2101 HInstruction expression = pop(); | 2101 HInstruction expression = pop(); |
2102 Node argument = node.arguments.head; | 2102 Node argument = node.arguments.head; |
2103 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); | 2103 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); |
2104 Type type = elements.getType(typeAnnotation); | 2104 DartType type = elements.getType(typeAnnotation); |
2105 HInstruction converted = convertType(expression, type.element, | 2105 HInstruction converted = convertType(expression, type.element, |
2106 HTypeConversion.CAST_TYPE_CHECK); | 2106 HTypeConversion.CAST_TYPE_CHECK); |
2107 stack.add(converted); | 2107 stack.add(converted); |
2108 } else { | 2108 } else { |
2109 visit(node.receiver); | 2109 visit(node.receiver); |
2110 visit(node.argumentsNode); | 2110 visit(node.argumentsNode); |
2111 var right = pop(); | 2111 var right = pop(); |
2112 var left = pop(); | 2112 var left = pop(); |
2113 visitBinary(left, op, right); | 2113 visitBinary(left, op, right); |
2114 } | 2114 } |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2449 push(new HInvokeSuper(inputs)); | 2449 push(new HInvokeSuper(inputs)); |
2450 } else { | 2450 } else { |
2451 target = new HInvokeSuper(inputs); | 2451 target = new HInvokeSuper(inputs); |
2452 add(target); | 2452 add(target); |
2453 inputs = <HInstruction>[target]; | 2453 inputs = <HInstruction>[target]; |
2454 addDynamicSendArgumentsToList(node, inputs); | 2454 addDynamicSendArgumentsToList(node, inputs); |
2455 push(new HInvokeClosure(selector, inputs)); | 2455 push(new HInvokeClosure(selector, inputs)); |
2456 } | 2456 } |
2457 } | 2457 } |
2458 | 2458 |
2459 HInstruction analyzeTypeArgument(Type argument, Node currentNode) { | 2459 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { |
2460 if (argument.element.isTypeVariable()) { | 2460 if (argument.element.isTypeVariable()) { |
2461 if (work.element.isFactoryConstructor() | 2461 if (work.element.isFactoryConstructor() |
2462 || work.element.isGenerativeConstructor()) { | 2462 || work.element.isGenerativeConstructor()) { |
2463 // The type variable is stored in a parameter of the | 2463 // The type variable is stored in a parameter of the |
2464 // factory. | 2464 // factory. |
2465 return localsHandler.readLocal(argument.element); | 2465 return localsHandler.readLocal(argument.element); |
2466 } else if (work.element.isInstanceMember()) { | 2466 } else if (work.element.isInstanceMember()) { |
2467 // The type variable is stored in [this]. | 2467 // The type variable is stored in [this]. |
2468 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), | 2468 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), |
2469 localsHandler.readThis()); | 2469 localsHandler.readThis()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2517 inputs.add(target); | 2517 inputs.add(target); |
2518 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2518 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
2519 constructor, inputs); | 2519 constructor, inputs); |
2520 if (!succeeded) { | 2520 if (!succeeded) { |
2521 // TODO(ngeoffray): Match the VM behavior and throw an | 2521 // TODO(ngeoffray): Match the VM behavior and throw an |
2522 // exception at runtime. | 2522 // exception at runtime. |
2523 compiler.cancel('Unimplemented non-matching static call', node: node); | 2523 compiler.cancel('Unimplemented non-matching static call', node: node); |
2524 } | 2524 } |
2525 | 2525 |
2526 TypeAnnotation annotation = getTypeAnnotationFromSend(node); | 2526 TypeAnnotation annotation = getTypeAnnotationFromSend(node); |
2527 elements.getType(annotation).arguments.forEach((Type argument) { | 2527 elements.getType(annotation).arguments.forEach((DartType argument) { |
2528 inputs.add(analyzeTypeArgument(argument, node)); | 2528 inputs.add(analyzeTypeArgument(argument, node)); |
2529 }); | 2529 }); |
2530 | 2530 |
2531 HType elementType = computeType(constructor); | 2531 HType elementType = computeType(constructor); |
2532 HInstruction newInstance = new HInvokeStatic(inputs, elementType); | 2532 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
2533 pushWithPosition(newInstance, node); | 2533 pushWithPosition(newInstance, node); |
2534 } | 2534 } |
2535 | 2535 |
2536 visitStaticSend(Send node) { | 2536 visitStaticSend(Send node) { |
2537 Selector selector = elements.getSelector(node); | 2537 Selector selector = elements.getSelector(node); |
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3440 HInstruction oldRethrowableException = rethrowableException; | 3440 HInstruction oldRethrowableException = rethrowableException; |
3441 rethrowableException = exception; | 3441 rethrowableException = exception; |
3442 | 3442 |
3443 pushInvokeHelper1(interceptors.getExceptionUnwrapper(), exception); | 3443 pushInvokeHelper1(interceptors.getExceptionUnwrapper(), exception); |
3444 HInvokeStatic unwrappedException = pop(); | 3444 HInvokeStatic unwrappedException = pop(); |
3445 tryInstruction.exception = exception; | 3445 tryInstruction.exception = exception; |
3446 Link<Node> link = node.catchBlocks.nodes; | 3446 Link<Node> link = node.catchBlocks.nodes; |
3447 | 3447 |
3448 void pushCondition(CatchBlock catchBlock) { | 3448 void pushCondition(CatchBlock catchBlock) { |
3449 if (catchBlock.onKeyword != null) { | 3449 if (catchBlock.onKeyword != null) { |
3450 Type type = elements.getType(catchBlock.type); | 3450 DartType type = elements.getType(catchBlock.type); |
3451 if (type == null) { | 3451 if (type == null) { |
3452 compiler.cancel('On with unresolved type', | 3452 compiler.cancel('On with unresolved type', |
3453 node: catchBlock.type); | 3453 node: catchBlock.type); |
3454 } | 3454 } |
3455 HInstruction condition = new HIs(type, unwrappedException); | 3455 HInstruction condition = new HIs(type, unwrappedException); |
3456 push(condition); | 3456 push(condition); |
3457 } | 3457 } |
3458 else { | 3458 else { |
3459 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 3459 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
3460 HInstruction condition = null; | 3460 HInstruction condition = null; |
3461 if (declaration.type == null) { | 3461 if (declaration.type == null) { |
3462 condition = graph.addConstantBool(true); | 3462 condition = graph.addConstantBool(true); |
3463 stack.add(condition); | 3463 stack.add(condition); |
3464 } else { | 3464 } else { |
3465 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 3465 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
3466 // "if" condition above and this "else" branch should be deleted as | 3466 // "if" condition above and this "else" branch should be deleted as |
3467 // type of declared variable won't matter for the catch | 3467 // type of declared variable won't matter for the catch |
3468 // condition | 3468 // condition |
3469 Type type = elements.getType(declaration.type); | 3469 DartType type = elements.getType(declaration.type); |
3470 if (type == null) { | 3470 if (type == null) { |
3471 compiler.cancel('Catch with unresolved type', node: catchBlock); | 3471 compiler.cancel('Catch with unresolved type', node: catchBlock); |
3472 } | 3472 } |
3473 condition = new HIs(type, unwrappedException, nullOk: true); | 3473 condition = new HIs(type, unwrappedException, nullOk: true); |
3474 push(condition); | 3474 push(condition); |
3475 } | 3475 } |
3476 } | 3476 } |
3477 } | 3477 } |
3478 | 3478 |
3479 void visitThen() { | 3479 void visitThen() { |
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3939 new HSubGraphBlockInformation(elseBranch.graph)); | 3939 new HSubGraphBlockInformation(elseBranch.graph)); |
3940 | 3940 |
3941 HBasicBlock conditionStartBlock = conditionBranch.block; | 3941 HBasicBlock conditionStartBlock = conditionBranch.block; |
3942 conditionStartBlock.setBlockFlow(info, joinBlock); | 3942 conditionStartBlock.setBlockFlow(info, joinBlock); |
3943 SubGraph conditionGraph = conditionBranch.graph; | 3943 SubGraph conditionGraph = conditionBranch.graph; |
3944 HIf branch = conditionGraph.end.last; | 3944 HIf branch = conditionGraph.end.last; |
3945 assert(branch is HIf); | 3945 assert(branch is HIf); |
3946 branch.blockInformation = conditionStartBlock.blockFlow; | 3946 branch.blockInformation = conditionStartBlock.blockFlow; |
3947 } | 3947 } |
3948 } | 3948 } |
OLD | NEW |