| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to implement [TypedElement.type] because our | 9 * methods. We need to implement [TypedElement.type] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 HGraph graph; | 40 HGraph graph; |
| 41 ElementKind kind = element.kind; | 41 ElementKind kind = element.kind; |
| 42 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 42 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 43 graph = compileConstructor(builder, work); | 43 graph = compileConstructor(builder, work); |
| 44 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 44 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 45 kind == ElementKind.FUNCTION || | 45 kind == ElementKind.FUNCTION || |
| 46 kind == ElementKind.GETTER || | 46 kind == ElementKind.GETTER || |
| 47 kind == ElementKind.SETTER) { | 47 kind == ElementKind.SETTER) { |
| 48 graph = builder.buildMethod(element); | 48 graph = builder.buildMethod(element); |
| 49 } else if (kind == ElementKind.FIELD) { | 49 } else if (kind == ElementKind.FIELD) { |
| 50 if (element.isInstanceMember()) { | 50 if (element.isInstanceMember) { |
| 51 assert(compiler.enableTypeAssertions); | 51 assert(compiler.enableTypeAssertions); |
| 52 graph = builder.buildCheckedSetter(element); | 52 graph = builder.buildCheckedSetter(element); |
| 53 } else { | 53 } else { |
| 54 graph = builder.buildLazyInitializer(element); | 54 graph = builder.buildLazyInitializer(element); |
| 55 } | 55 } |
| 56 } else { | 56 } else { |
| 57 compiler.internalError(element, 'Unexpected element kind $kind.'); | 57 compiler.internalError(element, 'Unexpected element kind $kind.'); |
| 58 } | 58 } |
| 59 assert(graph.isValid()); | 59 assert(graph.isValid()); |
| 60 if (!identical(kind, ElementKind.FIELD)) { | 60 if (!identical(kind, ElementKind.FIELD)) { |
| 61 FunctionElement function = element; | 61 FunctionElement function = element; |
| 62 FunctionSignature signature = function.functionSignature; | 62 FunctionSignature signature = function.functionSignature; |
| 63 signature.forEachOptionalParameter((Element parameter) { | 63 signature.forEachOptionalParameter((Element parameter) { |
| 64 // This ensures the default value will be computed. | 64 // This ensures the default value will be computed. |
| 65 Constant constant = | 65 Constant constant = |
| 66 backend.constants.getConstantForVariable(parameter); | 66 backend.constants.getConstantForVariable(parameter); |
| 67 backend.registerCompileTimeConstant(constant, work.resolutionTree); | 67 backend.registerCompileTimeConstant(constant, work.resolutionTree); |
| 68 backend.constants.addCompileTimeConstantForEmission(constant); | 68 backend.constants.addCompileTimeConstantForEmission(constant); |
| 69 }); | 69 }); |
| 70 } | 70 } |
| 71 if (compiler.tracer.enabled) { | 71 if (compiler.tracer.enabled) { |
| 72 String name; | 72 String name; |
| 73 if (element.isMember()) { | 73 if (element.isMember) { |
| 74 String className = element.getEnclosingClass().name; | 74 String className = element.enclosingClass.name; |
| 75 String memberName = element.name; | 75 String memberName = element.name; |
| 76 name = "$className.$memberName"; | 76 name = "$className.$memberName"; |
| 77 if (element.isGenerativeConstructorBody()) { | 77 if (element.isGenerativeConstructorBody) { |
| 78 name = "$name (body)"; | 78 name = "$name (body)"; |
| 79 } | 79 } |
| 80 } else { | 80 } else { |
| 81 name = "${element.name}"; | 81 name = "${element.name}"; |
| 82 } | 82 } |
| 83 compiler.tracer.traceCompilation( | 83 compiler.tracer.traceCompilation( |
| 84 name, work.compilationContext, compiler); | 84 name, work.compilationContext, compiler); |
| 85 compiler.tracer.traceGraph('builder', graph); | 85 compiler.tracer.traceGraph('builder', graph); |
| 86 } | 86 } |
| 87 return graph; | 87 return graph; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 * If the scope (function or loop) [node] has captured variables then this | 157 * If the scope (function or loop) [node] has captured variables then this |
| 158 * method creates a box and sets up the redirections. | 158 * method creates a box and sets up the redirections. |
| 159 */ | 159 */ |
| 160 void enterScope(ast.Node node, Element element) { | 160 void enterScope(ast.Node node, Element element) { |
| 161 // See if any variable in the top-scope of the function is captured. If yes | 161 // See if any variable in the top-scope of the function is captured. If yes |
| 162 // we need to create a box-object. | 162 // we need to create a box-object. |
| 163 ClosureScope scopeData = closureData.capturingScopes[node]; | 163 ClosureScope scopeData = closureData.capturingScopes[node]; |
| 164 if (scopeData == null) return; | 164 if (scopeData == null) return; |
| 165 HInstruction box; | 165 HInstruction box; |
| 166 // The scope has captured variables. | 166 // The scope has captured variables. |
| 167 if (element != null && element.isGenerativeConstructorBody()) { | 167 if (element != null && element.isGenerativeConstructorBody) { |
| 168 // The box is passed as a parameter to a generative | 168 // The box is passed as a parameter to a generative |
| 169 // constructor body. | 169 // constructor body. |
| 170 JavaScriptBackend backend = builder.backend; | 170 JavaScriptBackend backend = builder.backend; |
| 171 box = builder.addParameter(scopeData.boxElement, backend.nonNullType); | 171 box = builder.addParameter(scopeData.boxElement, backend.nonNullType); |
| 172 } else { | 172 } else { |
| 173 box = createBox(); | 173 box = createBox(); |
| 174 } | 174 } |
| 175 // Add the box to the known locals. | 175 // Add the box to the known locals. |
| 176 directLocals[scopeData.boxElement] = box; | 176 directLocals[scopeData.boxElement] = box; |
| 177 // Make sure that accesses to the boxed locals go into the box. We also | 177 // Make sure that accesses to the boxed locals go into the box. We also |
| 178 // need to make sure that parameters are copied into the box if necessary. | 178 // need to make sure that parameters are copied into the box if necessary. |
| 179 scopeData.capturedVariableMapping.forEach((Element from, Element to) { | 179 scopeData.capturedVariableMapping.forEach((Element from, Element to) { |
| 180 // The [from] can only be a parameter for function-scopes and not | 180 // The [from] can only be a parameter for function-scopes and not |
| 181 // loop scopes. | 181 // loop scopes. |
| 182 if (from.isParameter() && !element.isGenerativeConstructorBody()) { | 182 if (from.isParameter && !element.isGenerativeConstructorBody) { |
| 183 // Now that the redirection is set up, the update to the local will | 183 // Now that the redirection is set up, the update to the local will |
| 184 // write the parameter value into the box. | 184 // write the parameter value into the box. |
| 185 // Store the captured parameter in the box. Get the current value | 185 // Store the captured parameter in the box. Get the current value |
| 186 // before we put the redirection in place. | 186 // before we put the redirection in place. |
| 187 // We don't need to update the local for a generative | 187 // We don't need to update the local for a generative |
| 188 // constructor body, because it receives a box that already | 188 // constructor body, because it receives a box that already |
| 189 // contains the updates as the last parameter. | 189 // contains the updates as the last parameter. |
| 190 HInstruction instruction = readLocal(from); | 190 HInstruction instruction = readLocal(from); |
| 191 redirectElement(from, to); | 191 redirectElement(from, to); |
| 192 updateLocal(from, instruction); | 192 updateLocal(from, instruction); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 void startFunction(Element element, ast.Node node) { | 224 void startFunction(Element element, ast.Node node) { |
| 225 assert(invariant(element, element.isImplementation)); | 225 assert(invariant(element, element.isImplementation)); |
| 226 Compiler compiler = builder.compiler; | 226 Compiler compiler = builder.compiler; |
| 227 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 227 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 228 element, node, builder.elements); | 228 element, node, builder.elements); |
| 229 | 229 |
| 230 if (element is FunctionElement) { | 230 if (element is FunctionElement) { |
| 231 FunctionElement functionElement = element; | 231 FunctionElement functionElement = element; |
| 232 FunctionSignature params = functionElement.functionSignature; | 232 FunctionSignature params = functionElement.functionSignature; |
| 233 params.orderedForEachParameter((Element parameterElement) { | 233 params.orderedForEachParameter((Element parameterElement) { |
| 234 if (element.isGenerativeConstructorBody()) { | 234 if (element.isGenerativeConstructorBody) { |
| 235 ClosureScope scopeData = closureData.capturingScopes[node]; | 235 ClosureScope scopeData = closureData.capturingScopes[node]; |
| 236 if (scopeData != null | 236 if (scopeData != null |
| 237 && scopeData.capturedVariableMapping.containsKey( | 237 && scopeData.capturedVariableMapping.containsKey( |
| 238 parameterElement)) { | 238 parameterElement)) { |
| 239 // The parameter will be a field in the box passed as the | 239 // The parameter will be a field in the box passed as the |
| 240 // last parameter. So no need to have it. | 240 // last parameter. So no need to have it. |
| 241 return; | 241 return; |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 HInstruction parameter = builder.addParameter( | 244 HInstruction parameter = builder.addParameter( |
| 245 parameterElement, | 245 parameterElement, |
| 246 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler)); | 246 TypeMaskFactory.inferredTypeForElement(parameterElement, compiler)); |
| 247 builder.parameters[parameterElement] = parameter; | 247 builder.parameters[parameterElement] = parameter; |
| 248 directLocals[parameterElement] = parameter; | 248 directLocals[parameterElement] = parameter; |
| 249 }); | 249 }); |
| 250 } | 250 } |
| 251 | 251 |
| 252 enterScope(node, element); | 252 enterScope(node, element); |
| 253 | 253 |
| 254 // If the freeVariableMapping is not empty, then this function was a | 254 // If the freeVariableMapping is not empty, then this function was a |
| 255 // nested closure that captures variables. Redirect the captured | 255 // nested closure that captures variables. Redirect the captured |
| 256 // variables to fields in the closure. | 256 // variables to fields in the closure. |
| 257 closureData.freeVariableMapping.forEach((Element from, Element to) { | 257 closureData.freeVariableMapping.forEach((Element from, Element to) { |
| 258 redirectElement(from, to); | 258 redirectElement(from, to); |
| 259 }); | 259 }); |
| 260 JavaScriptBackend backend = compiler.backend; | 260 JavaScriptBackend backend = compiler.backend; |
| 261 if (closureData.isClosure()) { | 261 if (closureData.isClosure) { |
| 262 // Inside closure redirect references to itself to [:this:]. | 262 // Inside closure redirect references to itself to [:this:]. |
| 263 HThis thisInstruction = new HThis(closureData.thisElement, | 263 HThis thisInstruction = new HThis(closureData.thisElement, |
| 264 backend.nonNullType); | 264 backend.nonNullType); |
| 265 builder.graph.thisInstruction = thisInstruction; | 265 builder.graph.thisInstruction = thisInstruction; |
| 266 builder.graph.entry.addAtEntry(thisInstruction); | 266 builder.graph.entry.addAtEntry(thisInstruction); |
| 267 updateLocal(closureData.closureElement, thisInstruction); | 267 updateLocal(closureData.closureElement, thisInstruction); |
| 268 } else if (element.isInstanceMember()) { | 268 } else if (element.isInstanceMember) { |
| 269 // Once closures have been mapped to classes their instance members might | 269 // Once closures have been mapped to classes their instance members might |
| 270 // not have any thisElement if the closure was created inside a static | 270 // not have any thisElement if the closure was created inside a static |
| 271 // context. | 271 // context. |
| 272 HThis thisInstruction = new HThis( | 272 HThis thisInstruction = new HThis( |
| 273 closureData.thisElement, builder.getTypeOfThis()); | 273 closureData.thisElement, builder.getTypeOfThis()); |
| 274 builder.graph.thisInstruction = thisInstruction; | 274 builder.graph.thisInstruction = thisInstruction; |
| 275 builder.graph.entry.addAtEntry(thisInstruction); | 275 builder.graph.entry.addAtEntry(thisInstruction); |
| 276 directLocals[closureData.thisElement] = thisInstruction; | 276 directLocals[closureData.thisElement] = thisInstruction; |
| 277 } | 277 } |
| 278 | 278 |
| 279 // If this method is an intercepted method, add the extra | 279 // If this method is an intercepted method, add the extra |
| 280 // parameter to it, that is the actual receiver for intercepted | 280 // parameter to it, that is the actual receiver for intercepted |
| 281 // classes, or the same as [:this:] for non-intercepted classes. | 281 // classes, or the same as [:this:] for non-intercepted classes. |
| 282 ClassElement cls = element.getEnclosingClass(); | 282 ClassElement cls = element.enclosingClass; |
| 283 | 283 |
| 284 // When the class extends a native class, the instance is pre-constructed | 284 // When the class extends a native class, the instance is pre-constructed |
| 285 // and passed to the generative constructor factory function as a parameter. | 285 // and passed to the generative constructor factory function as a parameter. |
| 286 // Instead of allocating and initializing the object, the constructor | 286 // Instead of allocating and initializing the object, the constructor |
| 287 // 'upgrades' the native subclass object by initializing the Dart fields. | 287 // 'upgrades' the native subclass object by initializing the Dart fields. |
| 288 bool isNativeUpgradeFactory = element.isGenerativeConstructor() | 288 bool isNativeUpgradeFactory = element.isGenerativeConstructor |
| 289 && Elements.isNativeOrExtendsNative(cls); | 289 && Elements.isNativeOrExtendsNative(cls); |
| 290 if (backend.isInterceptedMethod(element)) { | 290 if (backend.isInterceptedMethod(element)) { |
| 291 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); | 291 bool isInterceptorClass = backend.isInterceptorClass(cls.declaration); |
| 292 String name = isInterceptorClass ? 'receiver' : '_'; | 292 String name = isInterceptorClass ? 'receiver' : '_'; |
| 293 Element parameter = new InterceptedElement( | 293 Element parameter = new InterceptedElement( |
| 294 cls.thisType, name, element); | 294 cls.thisType, name, element); |
| 295 HParameterValue value = | 295 HParameterValue value = |
| 296 new HParameterValue(parameter, builder.getTypeOfThis()); | 296 new HParameterValue(parameter, builder.getTypeOfThis()); |
| 297 builder.graph.explicitReceiverParameter = value; | 297 builder.graph.explicitReceiverParameter = value; |
| 298 builder.graph.entry.addAfter( | 298 builder.graph.entry.addAfter( |
| (...skipping 22 matching lines...) Expand all Loading... |
| 321 assert(element != null); | 321 assert(element != null); |
| 322 return redirectionMapping[element] == null | 322 return redirectionMapping[element] == null |
| 323 && !closureData.usedVariablesInTry.contains(element); | 323 && !closureData.usedVariablesInTry.contains(element); |
| 324 } | 324 } |
| 325 | 325 |
| 326 bool isStoredInClosureField(Element element) { | 326 bool isStoredInClosureField(Element element) { |
| 327 assert(element != null); | 327 assert(element != null); |
| 328 if (isAccessedDirectly(element)) return false; | 328 if (isAccessedDirectly(element)) return false; |
| 329 Element redirectTarget = redirectionMapping[element]; | 329 Element redirectTarget = redirectionMapping[element]; |
| 330 if (redirectTarget == null) return false; | 330 if (redirectTarget == null) return false; |
| 331 if (redirectTarget.isMember()) { | 331 if (redirectTarget.isMember) { |
| 332 assert(redirectTarget is ClosureFieldElement); | 332 assert(redirectTarget is ClosureFieldElement); |
| 333 return true; | 333 return true; |
| 334 } | 334 } |
| 335 return false; | 335 return false; |
| 336 } | 336 } |
| 337 | 337 |
| 338 bool isBoxed(Element element) { | 338 bool isBoxed(Element element) { |
| 339 if (isAccessedDirectly(element)) return false; | 339 if (isAccessedDirectly(element)) return false; |
| 340 if (isStoredInClosureField(element)) return false; | 340 if (isStoredInClosureField(element)) return false; |
| 341 return redirectionMapping[element] != null; | 341 return redirectionMapping[element] != null; |
| 342 } | 342 } |
| 343 | 343 |
| 344 bool isUsedInTry(Element element) { | 344 bool isUsedInTry(Element element) { |
| 345 return closureData.usedVariablesInTry.contains(element); | 345 return closureData.usedVariablesInTry.contains(element); |
| 346 } | 346 } |
| 347 | 347 |
| 348 /** | 348 /** |
| 349 * Returns an [HInstruction] for the given element. If the element is | 349 * Returns an [HInstruction] for the given element. If the element is |
| 350 * boxed or stored in a closure then the method generates code to retrieve | 350 * boxed or stored in a closure then the method generates code to retrieve |
| 351 * the value. | 351 * the value. |
| 352 */ | 352 */ |
| 353 HInstruction readLocal(Element element) { | 353 HInstruction readLocal(Element element) { |
| 354 if (isAccessedDirectly(element)) { | 354 if (isAccessedDirectly(element)) { |
| 355 if (directLocals[element] == null) { | 355 if (directLocals[element] == null) { |
| 356 if (element.isTypeVariable()) { | 356 if (element.isTypeVariable) { |
| 357 builder.compiler.internalError(builder.compiler.currentElement, | 357 builder.compiler.internalError(builder.compiler.currentElement, |
| 358 "Runtime type information not available for $element."); | 358 "Runtime type information not available for $element."); |
| 359 } else { | 359 } else { |
| 360 builder.compiler.internalError(element, | 360 builder.compiler.internalError(element, |
| 361 "Cannot find value $element."); | 361 "Cannot find value $element."); |
| 362 } | 362 } |
| 363 } | 363 } |
| 364 return directLocals[element]; | 364 return directLocals[element]; |
| 365 } else if (isStoredInClosureField(element)) { | 365 } else if (isStoredInClosureField(element)) { |
| 366 Element redirect = redirectionMapping[element]; | 366 Element redirect = redirectionMapping[element]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 } | 403 } |
| 404 return res; | 404 return res; |
| 405 } | 405 } |
| 406 | 406 |
| 407 HLocalValue getLocal(Element element) { | 407 HLocalValue getLocal(Element element) { |
| 408 // If the element is a parameter, we already have a | 408 // If the element is a parameter, we already have a |
| 409 // HParameterValue for it. We cannot create another one because | 409 // HParameterValue for it. We cannot create another one because |
| 410 // it could then have another name than the real parameter. And | 410 // it could then have another name than the real parameter. And |
| 411 // the other one would not know it is just a copy of the real | 411 // the other one would not know it is just a copy of the real |
| 412 // parameter. | 412 // parameter. |
| 413 if (element.isParameter()) return builder.parameters[element]; | 413 if (element.isParameter) return builder.parameters[element]; |
| 414 | 414 |
| 415 return builder.activationVariables.putIfAbsent(element, () { | 415 return builder.activationVariables.putIfAbsent(element, () { |
| 416 JavaScriptBackend backend = builder.backend; | 416 JavaScriptBackend backend = builder.backend; |
| 417 HLocalValue local = new HLocalValue(element, backend.nonNullType); | 417 HLocalValue local = new HLocalValue(element, backend.nonNullType); |
| 418 builder.graph.entry.addAtExit(local); | 418 builder.graph.entry.addAtExit(local); |
| 419 return local; | 419 return local; |
| 420 }); | 420 }); |
| 421 } | 421 } |
| 422 | 422 |
| 423 /** | 423 /** |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 add(attachPosition(instruction, node)); | 1031 add(attachPosition(instruction, node)); |
| 1032 } | 1032 } |
| 1033 | 1033 |
| 1034 SourceFile currentSourceFile() { | 1034 SourceFile currentSourceFile() { |
| 1035 Element element = sourceElement; | 1035 Element element = sourceElement; |
| 1036 // TODO(johnniwinther): remove the 'element.patch' hack. | 1036 // TODO(johnniwinther): remove the 'element.patch' hack. |
| 1037 if (element is FunctionElement) { | 1037 if (element is FunctionElement) { |
| 1038 FunctionElement functionElement = element; | 1038 FunctionElement functionElement = element; |
| 1039 if (functionElement.patch != null) element = functionElement.patch; | 1039 if (functionElement.patch != null) element = functionElement.patch; |
| 1040 } | 1040 } |
| 1041 Script script = element.getCompilationUnit().script; | 1041 Script script = element.compilationUnit.script; |
| 1042 return script.file; | 1042 return script.file; |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 void checkValidSourceFileLocation( | 1045 void checkValidSourceFileLocation( |
| 1046 SourceFileLocation location, SourceFile sourceFile, int offset) { | 1046 SourceFileLocation location, SourceFile sourceFile, int offset) { |
| 1047 if (!location.isValid()) { | 1047 if (!location.isValid()) { |
| 1048 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | 1048 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( |
| 1049 {'offset': offset, | 1049 {'offset': offset, |
| 1050 'fileName': sourceFile.filename, | 1050 'fileName': sourceFile.filename, |
| 1051 'length': sourceFile.length}); | 1051 'length': sourceFile.length}); |
| 1052 } | 1052 } |
| 1053 } | 1053 } |
| 1054 | 1054 |
| 1055 /** | 1055 /** |
| 1056 * Returns a complete argument list for a call of [function]. | 1056 * Returns a complete argument list for a call of [function]. |
| 1057 */ | 1057 */ |
| 1058 List<HInstruction> completeSendArgumentsList( | 1058 List<HInstruction> completeSendArgumentsList( |
| 1059 FunctionElement function, | 1059 FunctionElement function, |
| 1060 Selector selector, | 1060 Selector selector, |
| 1061 List<HInstruction> providedArguments, | 1061 List<HInstruction> providedArguments, |
| 1062 ast.Node currentNode) { | 1062 ast.Node currentNode) { |
| 1063 assert(invariant(function, function.isImplementation)); | 1063 assert(invariant(function, function.isImplementation)); |
| 1064 assert(providedArguments != null); | 1064 assert(providedArguments != null); |
| 1065 | 1065 |
| 1066 bool isInstanceMember = function.isInstanceMember(); | 1066 bool isInstanceMember = function.isInstanceMember; |
| 1067 // For static calls, [providedArguments] is complete, default arguments | 1067 // For static calls, [providedArguments] is complete, default arguments |
| 1068 // have been included if necessary, see [addStaticSendArgumentsToList]. | 1068 // have been included if necessary, see [addStaticSendArgumentsToList]. |
| 1069 if (!isInstanceMember | 1069 if (!isInstanceMember |
| 1070 || currentNode == null // In erroneous code, currentNode can be null. | 1070 || currentNode == null // In erroneous code, currentNode can be null. |
| 1071 || providedArgumentsKnownToBeComplete(currentNode) | 1071 || providedArgumentsKnownToBeComplete(currentNode) |
| 1072 || function.isGenerativeConstructorBody() | 1072 || function.isGenerativeConstructorBody |
| 1073 || selector.isGetter()) { | 1073 || selector.isGetter) { |
| 1074 // For these cases, the provided argument list is known to be complete. | 1074 // For these cases, the provided argument list is known to be complete. |
| 1075 return providedArguments; | 1075 return providedArguments; |
| 1076 } else { | 1076 } else { |
| 1077 return completeDynamicSendArgumentsList( | 1077 return completeDynamicSendArgumentsList( |
| 1078 selector, function, providedArguments); | 1078 selector, function, providedArguments); |
| 1079 } | 1079 } |
| 1080 } | 1080 } |
| 1081 | 1081 |
| 1082 /** | 1082 /** |
| 1083 * Returns a complete argument list for a dynamic call of [function]. The | 1083 * Returns a complete argument list for a dynamic call of [function]. The |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 // Don't inline from one output unit to another. If something is deferred | 1173 // Don't inline from one output unit to another. If something is deferred |
| 1174 // it is to save space in the loading code. | 1174 // it is to save space in the loading code. |
| 1175 if (!compiler.deferredLoadTask | 1175 if (!compiler.deferredLoadTask |
| 1176 .inSameOutputUnit(element,compiler.currentElement)) { | 1176 .inSameOutputUnit(element,compiler.currentElement)) { |
| 1177 return false; | 1177 return false; |
| 1178 } | 1178 } |
| 1179 if (compiler.disableInlining) return false; | 1179 if (compiler.disableInlining) return false; |
| 1180 | 1180 |
| 1181 assert(selector != null | 1181 assert(selector != null |
| 1182 || Elements.isStaticOrTopLevel(element) | 1182 || Elements.isStaticOrTopLevel(element) |
| 1183 || element.isGenerativeConstructorBody()); | 1183 || element.isGenerativeConstructorBody); |
| 1184 if (selector != null && !selector.applies(function, compiler)) { | 1184 if (selector != null && !selector.applies(function, compiler)) { |
| 1185 return false; | 1185 return false; |
| 1186 } | 1186 } |
| 1187 | 1187 |
| 1188 // Don't inline operator== methods if the parameter can be null. | 1188 // Don't inline operator== methods if the parameter can be null. |
| 1189 if (element.name == '==') { | 1189 if (element.name == '==') { |
| 1190 if (element.getEnclosingClass() != compiler.objectClass | 1190 if (element.enclosingClass != compiler.objectClass |
| 1191 && providedArguments[1].canBeNull()) { | 1191 && providedArguments[1].canBeNull()) { |
| 1192 return false; | 1192 return false; |
| 1193 } | 1193 } |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 // Generative constructors of native classes should not be called directly | 1196 // Generative constructors of native classes should not be called directly |
| 1197 // and have an extra argument that causes problems with inlining. | 1197 // and have an extra argument that causes problems with inlining. |
| 1198 if (element.isGenerativeConstructor() | 1198 if (element.isGenerativeConstructor |
| 1199 && Elements.isNativeOrExtendsNative(element.getEnclosingClass())) { | 1199 && Elements.isNativeOrExtendsNative(element.enclosingClass)) { |
| 1200 return false; | 1200 return false; |
| 1201 } | 1201 } |
| 1202 | 1202 |
| 1203 // A generative constructor body is not seen by global analysis, | 1203 // A generative constructor body is not seen by global analysis, |
| 1204 // so we should not query for its type. | 1204 // so we should not query for its type. |
| 1205 if (!element.isGenerativeConstructorBody()) { | 1205 if (!element.isGenerativeConstructorBody) { |
| 1206 // Don't inline if the return type was inferred to be non-null empty. | 1206 // Don't inline if the return type was inferred to be non-null empty. |
| 1207 // This means that the function always throws an exception. | 1207 // This means that the function always throws an exception. |
| 1208 TypeMask returnType = | 1208 TypeMask returnType = |
| 1209 compiler.typesTask.getGuaranteedReturnTypeOfElement(element); | 1209 compiler.typesTask.getGuaranteedReturnTypeOfElement(element); |
| 1210 if (returnType != null | 1210 if (returnType != null |
| 1211 && returnType.isEmpty | 1211 && returnType.isEmpty |
| 1212 && !returnType.isNullable) { | 1212 && !returnType.isNullable) { |
| 1213 isReachable = false; | 1213 isReachable = false; |
| 1214 return false; | 1214 return false; |
| 1215 } | 1215 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 } else { | 1259 } else { |
| 1260 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); | 1260 backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop); |
| 1261 } | 1261 } |
| 1262 return canInline; | 1262 return canInline; |
| 1263 } | 1263 } |
| 1264 | 1264 |
| 1265 void doInlining() { | 1265 void doInlining() { |
| 1266 // Add an explicit null check on the receiver before doing the | 1266 // Add an explicit null check on the receiver before doing the |
| 1267 // inlining. We use [element] to get the same name in the | 1267 // inlining. We use [element] to get the same name in the |
| 1268 // NoSuchMethodError message as if we had called it. | 1268 // NoSuchMethodError message as if we had called it. |
| 1269 if (element.isInstanceMember() | 1269 if (element.isInstanceMember |
| 1270 && !element.isGenerativeConstructorBody() | 1270 && !element.isGenerativeConstructorBody |
| 1271 && (selector.mask == null || selector.mask.isNullable)) { | 1271 && (selector.mask == null || selector.mask.isNullable)) { |
| 1272 addWithPosition( | 1272 addWithPosition( |
| 1273 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1273 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
| 1274 isAssignable: false), | 1274 isAssignable: false), |
| 1275 currentNode); | 1275 currentNode); |
| 1276 } | 1276 } |
| 1277 List<HInstruction> compiledArguments = completeSendArgumentsList( | 1277 List<HInstruction> compiledArguments = completeSendArgumentsList( |
| 1278 function, selector, providedArguments, currentNode); | 1278 function, selector, providedArguments, currentNode); |
| 1279 enterInlinedMethod(function, currentNode, compiledArguments); | 1279 enterInlinedMethod(function, currentNode, compiledArguments); |
| 1280 inlinedFrom(function, () { | 1280 inlinedFrom(function, () { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1308 | 1308 |
| 1309 HInstruction handleConstantForOptionalParameter(Element parameter) { | 1309 HInstruction handleConstantForOptionalParameter(Element parameter) { |
| 1310 Constant constant = | 1310 Constant constant = |
| 1311 backend.constants.getConstantForVariable(parameter); | 1311 backend.constants.getConstantForVariable(parameter); |
| 1312 assert(invariant(parameter, constant != null, | 1312 assert(invariant(parameter, constant != null, |
| 1313 message: 'No constant computed for $parameter')); | 1313 message: 'No constant computed for $parameter')); |
| 1314 return graph.addConstant(constant, compiler); | 1314 return graph.addConstant(constant, compiler); |
| 1315 } | 1315 } |
| 1316 | 1316 |
| 1317 Element get currentNonClosureClass { | 1317 Element get currentNonClosureClass { |
| 1318 ClassElement cls = sourceElement.getEnclosingClass(); | 1318 ClassElement cls = sourceElement.enclosingClass; |
| 1319 if (cls != null && cls.isClosure()) { | 1319 if (cls != null && cls.isClosure) { |
| 1320 var closureClass = cls; | 1320 var closureClass = cls; |
| 1321 return closureClass.methodElement.getEnclosingClass(); | 1321 return closureClass.methodElement.enclosingClass; |
| 1322 } else { | 1322 } else { |
| 1323 return cls; | 1323 return cls; |
| 1324 } | 1324 } |
| 1325 } | 1325 } |
| 1326 | 1326 |
| 1327 /** | 1327 /** |
| 1328 * Returns whether this builder is building code for [element]. | 1328 * Returns whether this builder is building code for [element]. |
| 1329 */ | 1329 */ |
| 1330 bool isBuildingFor(Element element) { | 1330 bool isBuildingFor(Element element) { |
| 1331 return work.element == element; | 1331 return work.element == element; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 backend.constants.getConstantForVariable(element); | 1363 backend.constants.getConstantForVariable(element); |
| 1364 return initialValue == null; | 1364 return initialValue == null; |
| 1365 } | 1365 } |
| 1366 | 1366 |
| 1367 TypeMask cachedTypeOfThis; | 1367 TypeMask cachedTypeOfThis; |
| 1368 | 1368 |
| 1369 TypeMask getTypeOfThis() { | 1369 TypeMask getTypeOfThis() { |
| 1370 TypeMask result = cachedTypeOfThis; | 1370 TypeMask result = cachedTypeOfThis; |
| 1371 if (result == null) { | 1371 if (result == null) { |
| 1372 Element element = localsHandler.closureData.thisElement; | 1372 Element element = localsHandler.closureData.thisElement; |
| 1373 ClassElement cls = element.enclosingElement.getEnclosingClass(); | 1373 ClassElement cls = element.enclosingElement.enclosingClass; |
| 1374 if (compiler.world.isUsedAsMixin(cls)) { | 1374 if (compiler.world.isUsedAsMixin(cls)) { |
| 1375 // If the enclosing class is used as a mixin, [:this:] can be | 1375 // If the enclosing class is used as a mixin, [:this:] can be |
| 1376 // of the class that mixins the enclosing class. These two | 1376 // of the class that mixins the enclosing class. These two |
| 1377 // classes do not have a subclass relationship, so, for | 1377 // classes do not have a subclass relationship, so, for |
| 1378 // simplicity, we mark the type as an interface type. | 1378 // simplicity, we mark the type as an interface type. |
| 1379 result = new TypeMask.nonNullSubtype(cls.declaration); | 1379 result = new TypeMask.nonNullSubtype(cls.declaration); |
| 1380 } else { | 1380 } else { |
| 1381 result = new TypeMask.nonNullSubclass(cls.declaration); | 1381 result = new TypeMask.nonNullSubclass(cls.declaration); |
| 1382 } | 1382 } |
| 1383 cachedTypeOfThis = result; | 1383 cachedTypeOfThis = result; |
| 1384 } | 1384 } |
| 1385 return result; | 1385 return result; |
| 1386 } | 1386 } |
| 1387 | 1387 |
| 1388 Map<Element, TypeMask> cachedTypesOfCapturedVariables = | 1388 Map<Element, TypeMask> cachedTypesOfCapturedVariables = |
| 1389 new Map<Element, TypeMask>(); | 1389 new Map<Element, TypeMask>(); |
| 1390 | 1390 |
| 1391 TypeMask getTypeOfCapturedVariable(Element element) { | 1391 TypeMask getTypeOfCapturedVariable(Element element) { |
| 1392 assert(element.isField()); | 1392 assert(element.isField); |
| 1393 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { | 1393 return cachedTypesOfCapturedVariables.putIfAbsent(element, () { |
| 1394 return TypeMaskFactory.inferredTypeForElement(element, compiler); | 1394 return TypeMaskFactory.inferredTypeForElement(element, compiler); |
| 1395 }); | 1395 }); |
| 1396 } | 1396 } |
| 1397 | 1397 |
| 1398 /** | 1398 /** |
| 1399 * Documentation wanted -- johnniwinther | 1399 * Documentation wanted -- johnniwinther |
| 1400 * | 1400 * |
| 1401 * Invariant: [functionElement] must be an implementation element. | 1401 * Invariant: [functionElement] must be an implementation element. |
| 1402 */ | 1402 */ |
| 1403 HGraph buildMethod(FunctionElement functionElement) { | 1403 HGraph buildMethod(FunctionElement functionElement) { |
| 1404 assert(invariant(functionElement, functionElement.isImplementation)); | 1404 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1405 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); | 1405 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); |
| 1406 ast.FunctionExpression function = functionElement.parseNode(compiler); | 1406 ast.FunctionExpression function = functionElement.parseNode(compiler); |
| 1407 assert(function != null); | 1407 assert(function != null); |
| 1408 assert(!function.modifiers.isExternal()); | 1408 assert(!function.modifiers.isExternal); |
| 1409 assert(elements[function] != null); | 1409 assert(elements[function] != null); |
| 1410 openFunction(functionElement, function); | 1410 openFunction(functionElement, function); |
| 1411 String name = functionElement.name; | 1411 String name = functionElement.name; |
| 1412 // If [functionElement] is `operator==` we explicitely add a null check at | 1412 // If [functionElement] is `operator==` we explicitely add a null check at |
| 1413 // the beginning of the method. This is to avoid having call sites do the | 1413 // the beginning of the method. This is to avoid having call sites do the |
| 1414 // null check. | 1414 // null check. |
| 1415 if (name == '==') { | 1415 if (name == '==') { |
| 1416 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1416 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 1417 handleIf( | 1417 handleIf( |
| 1418 function, | 1418 function, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 return closeFunction(); | 1460 return closeFunction(); |
| 1461 } | 1461 } |
| 1462 | 1462 |
| 1463 /** | 1463 /** |
| 1464 * Returns the constructor body associated with the given constructor or | 1464 * Returns the constructor body associated with the given constructor or |
| 1465 * creates a new constructor body, if none can be found. | 1465 * creates a new constructor body, if none can be found. |
| 1466 * | 1466 * |
| 1467 * Returns [:null:] if the constructor does not have a body. | 1467 * Returns [:null:] if the constructor does not have a body. |
| 1468 */ | 1468 */ |
| 1469 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 1469 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| 1470 assert(constructor.isGenerativeConstructor()); | 1470 assert(constructor.isGenerativeConstructor); |
| 1471 assert(invariant(constructor, constructor.isImplementation)); | 1471 assert(invariant(constructor, constructor.isImplementation)); |
| 1472 if (constructor.isSynthesized) return null; | 1472 if (constructor.isSynthesized) return null; |
| 1473 ast.FunctionExpression node = constructor.parseNode(compiler); | 1473 ast.FunctionExpression node = constructor.parseNode(compiler); |
| 1474 // If we know the body doesn't have any code, we don't generate it. | 1474 // If we know the body doesn't have any code, we don't generate it. |
| 1475 if (!node.hasBody()) return null; | 1475 if (!node.hasBody()) return null; |
| 1476 if (node.hasEmptyBody()) return null; | 1476 if (node.hasEmptyBody()) return null; |
| 1477 ClassElement classElement = constructor.getEnclosingClass(); | 1477 ClassElement classElement = constructor.enclosingClass; |
| 1478 ConstructorBodyElement bodyElement; | 1478 ConstructorBodyElement bodyElement; |
| 1479 classElement.forEachBackendMember((Element backendMember) { | 1479 classElement.forEachBackendMember((Element backendMember) { |
| 1480 if (backendMember.isGenerativeConstructorBody()) { | 1480 if (backendMember.isGenerativeConstructorBody) { |
| 1481 ConstructorBodyElement body = backendMember; | 1481 ConstructorBodyElement body = backendMember; |
| 1482 if (body.constructor == constructor) { | 1482 if (body.constructor == constructor) { |
| 1483 // TODO(kasperl): Find a way of stopping the iteration | 1483 // TODO(kasperl): Find a way of stopping the iteration |
| 1484 // through the backend members. | 1484 // through the backend members. |
| 1485 bodyElement = backendMember; | 1485 bodyElement = backendMember; |
| 1486 } | 1486 } |
| 1487 } | 1487 } |
| 1488 }); | 1488 }); |
| 1489 if (bodyElement == null) { | 1489 if (bodyElement == null) { |
| 1490 bodyElement = new ConstructorBodyElementX(constructor); | 1490 bodyElement = new ConstructorBodyElementX(constructor); |
| 1491 classElement.addBackendMember(bodyElement); | 1491 classElement.addBackendMember(bodyElement); |
| 1492 | 1492 |
| 1493 if (constructor.isPatch) { | 1493 if (constructor.isPatch) { |
| 1494 // Create origin body element for patched constructors. | 1494 // Create origin body element for patched constructors. |
| 1495 ConstructorBodyElementX patch = bodyElement; | 1495 ConstructorBodyElementX patch = bodyElement; |
| 1496 ConstructorBodyElementX origin = | 1496 ConstructorBodyElementX origin = |
| 1497 new ConstructorBodyElementX(constructor.origin); | 1497 new ConstructorBodyElementX(constructor.origin); |
| 1498 origin.applyPatch(patch); | 1498 origin.applyPatch(patch); |
| 1499 classElement.origin.addBackendMember(bodyElement.origin); | 1499 classElement.origin.addBackendMember(bodyElement.origin); |
| 1500 } | 1500 } |
| 1501 } | 1501 } |
| 1502 assert(bodyElement.isGenerativeConstructorBody()); | 1502 assert(bodyElement.isGenerativeConstructorBody); |
| 1503 return bodyElement; | 1503 return bodyElement; |
| 1504 } | 1504 } |
| 1505 | 1505 |
| 1506 HParameterValue addParameter(Element element, TypeMask type) { | 1506 HParameterValue addParameter(Element element, TypeMask type) { |
| 1507 assert(inliningStack.isEmpty); | 1507 assert(inliningStack.isEmpty); |
| 1508 HParameterValue result = new HParameterValue(element, type); | 1508 HParameterValue result = new HParameterValue(element, type); |
| 1509 if (lastAddedParameter == null) { | 1509 if (lastAddedParameter == null) { |
| 1510 graph.entry.addBefore(graph.entry.first, result); | 1510 graph.entry.addBefore(graph.entry.first, result); |
| 1511 } else { | 1511 } else { |
| 1512 graph.entry.addAfter(lastAddedParameter, result); | 1512 graph.entry.addAfter(lastAddedParameter, result); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1532 function, function.parseNode(compiler), elements); | 1532 function, function.parseNode(compiler), elements); |
| 1533 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. | 1533 // TODO(kasperl): Bad smell. We shouldn't be constructing elements here. |
| 1534 returnElement = new VariableElementX.synthetic("result", | 1534 returnElement = new VariableElementX.synthetic("result", |
| 1535 ElementKind.VARIABLE, function); | 1535 ElementKind.VARIABLE, function); |
| 1536 localsHandler.updateLocal(returnElement, | 1536 localsHandler.updateLocal(returnElement, |
| 1537 graph.addConstantNull(compiler)); | 1537 graph.addConstantNull(compiler)); |
| 1538 | 1538 |
| 1539 inTryStatement = false; // TODO(lry): why? Document. | 1539 inTryStatement = false; // TODO(lry): why? Document. |
| 1540 | 1540 |
| 1541 int argumentIndex = 0; | 1541 int argumentIndex = 0; |
| 1542 if (function.isInstanceMember()) { | 1542 if (function.isInstanceMember) { |
| 1543 localsHandler.updateLocal(localsHandler.closureData.thisElement, | 1543 localsHandler.updateLocal(localsHandler.closureData.thisElement, |
| 1544 compiledArguments[argumentIndex++]); | 1544 compiledArguments[argumentIndex++]); |
| 1545 } | 1545 } |
| 1546 | 1546 |
| 1547 FunctionSignature signature = function.functionSignature; | 1547 FunctionSignature signature = function.functionSignature; |
| 1548 signature.orderedForEachParameter((Element parameter) { | 1548 signature.orderedForEachParameter((Element parameter) { |
| 1549 HInstruction argument = compiledArguments[argumentIndex++]; | 1549 HInstruction argument = compiledArguments[argumentIndex++]; |
| 1550 localsHandler.updateLocal(parameter, argument); | 1550 localsHandler.updateLocal(parameter, argument); |
| 1551 }); | 1551 }); |
| 1552 | 1552 |
| 1553 ClassElement enclosing = function.getEnclosingClass(); | 1553 ClassElement enclosing = function.enclosingClass; |
| 1554 if ((function.isConstructor() || function.isGenerativeConstructorBody()) | 1554 if ((function.isConstructor || function.isGenerativeConstructorBody) |
| 1555 && backend.classNeedsRti(enclosing)) { | 1555 && backend.classNeedsRti(enclosing)) { |
| 1556 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 1556 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1557 HInstruction argument = compiledArguments[argumentIndex++]; | 1557 HInstruction argument = compiledArguments[argumentIndex++]; |
| 1558 localsHandler.updateLocal(typeVariable.element, argument); | 1558 localsHandler.updateLocal(typeVariable.element, argument); |
| 1559 }); | 1559 }); |
| 1560 } | 1560 } |
| 1561 assert(argumentIndex == compiledArguments.length); | 1561 assert(argumentIndex == compiledArguments.length); |
| 1562 | 1562 |
| 1563 elements = compiler.enqueuer.resolution.getCachedElements(function); | 1563 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 1564 assert(elements != null); | 1564 assert(elements != null); |
| 1565 returnType = signature.type.returnType; | 1565 returnType = signature.type.returnType; |
| 1566 stack = <HInstruction>[]; | 1566 stack = <HInstruction>[]; |
| 1567 } | 1567 } |
| 1568 | 1568 |
| 1569 void restoreState(AstInliningState state) { | 1569 void restoreState(AstInliningState state) { |
| 1570 localsHandler = state.oldLocalsHandler; | 1570 localsHandler = state.oldLocalsHandler; |
| 1571 returnElement = state.oldReturnElement; | 1571 returnElement = state.oldReturnElement; |
| 1572 inTryStatement = state.inTryStatement; | 1572 inTryStatement = state.inTryStatement; |
| 1573 elements = state.oldElements; | 1573 elements = state.oldElements; |
| 1574 returnType = state.oldReturnType; | 1574 returnType = state.oldReturnType; |
| 1575 assert(stack.isEmpty); | 1575 assert(stack.isEmpty); |
| 1576 stack = state.oldStack; | 1576 stack = state.oldStack; |
| 1577 } | 1577 } |
| 1578 | 1578 |
| 1579 /** | 1579 /** |
| 1580 * Run this builder on the body of the [function] to be inlined. | 1580 * Run this builder on the body of the [function] to be inlined. |
| 1581 */ | 1581 */ |
| 1582 void visitInlinedFunction(FunctionElement function) { | 1582 void visitInlinedFunction(FunctionElement function) { |
| 1583 potentiallyCheckInlinedParameterTypes(function); | 1583 potentiallyCheckInlinedParameterTypes(function); |
| 1584 if (function.isGenerativeConstructor()) { | 1584 if (function.isGenerativeConstructor) { |
| 1585 buildFactory(function); | 1585 buildFactory(function); |
| 1586 } else { | 1586 } else { |
| 1587 ast.FunctionExpression functionNode = function.parseNode(compiler); | 1587 ast.FunctionExpression functionNode = function.parseNode(compiler); |
| 1588 functionNode.body.accept(this); | 1588 functionNode.body.accept(this); |
| 1589 } | 1589 } |
| 1590 } | 1590 } |
| 1591 | 1591 |
| 1592 | 1592 |
| 1593 addInlinedInstantiation(DartType type) { | 1593 addInlinedInstantiation(DartType type) { |
| 1594 if (type != null) { | 1594 if (type != null) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1615 /** | 1615 /** |
| 1616 * In checked mode, generate type tests for the parameters of the inlined | 1616 * In checked mode, generate type tests for the parameters of the inlined |
| 1617 * function. | 1617 * function. |
| 1618 */ | 1618 */ |
| 1619 void potentiallyCheckInlinedParameterTypes(FunctionElement function) { | 1619 void potentiallyCheckInlinedParameterTypes(FunctionElement function) { |
| 1620 if (!compiler.enableTypeAssertions) return; | 1620 if (!compiler.enableTypeAssertions) return; |
| 1621 | 1621 |
| 1622 FunctionSignature signature = function.functionSignature; | 1622 FunctionSignature signature = function.functionSignature; |
| 1623 | 1623 |
| 1624 InterfaceType contextType; | 1624 InterfaceType contextType; |
| 1625 if (function.isSynthesized && function.isGenerativeConstructor()) { | 1625 if (function.isSynthesized && function.isGenerativeConstructor) { |
| 1626 // Synthesized constructors reuse the parameters from the | 1626 // Synthesized constructors reuse the parameters from the |
| 1627 // [targetConstructor]. In face of generic types, the type variables | 1627 // [targetConstructor]. In face of generic types, the type variables |
| 1628 // occurring in the parameter types must be substituted by the type | 1628 // occurring in the parameter types must be substituted by the type |
| 1629 // arguments of the enclosing class. | 1629 // arguments of the enclosing class. |
| 1630 FunctionElement target = function; | 1630 FunctionElement target = function; |
| 1631 while (target.targetConstructor != null) { | 1631 while (target.targetConstructor != null) { |
| 1632 target = target.targetConstructor; | 1632 target = target.targetConstructor; |
| 1633 } | 1633 } |
| 1634 if (target != function) { | 1634 if (target != function) { |
| 1635 ClassElement functionClass = function.getEnclosingClass(); | 1635 ClassElement functionClass = function.enclosingClass; |
| 1636 ClassElement targetClass = target.getEnclosingClass(); | 1636 ClassElement targetClass = target.enclosingClass; |
| 1637 contextType = functionClass.thisType.asInstanceOf(targetClass); | 1637 contextType = functionClass.thisType.asInstanceOf(targetClass); |
| 1638 } | 1638 } |
| 1639 } | 1639 } |
| 1640 | 1640 |
| 1641 signature.orderedForEachParameter((ParameterElement parameter) { | 1641 signature.orderedForEachParameter((ParameterElement parameter) { |
| 1642 HInstruction argument = localsHandler.readLocal(parameter); | 1642 HInstruction argument = localsHandler.readLocal(parameter); |
| 1643 DartType parameterType = parameter.type; | 1643 DartType parameterType = parameter.type; |
| 1644 if (contextType != null) { | 1644 if (contextType != null) { |
| 1645 parameterType = parameterType.substByContext(contextType); | 1645 parameterType = parameterType.substByContext(contextType); |
| 1646 } | 1646 } |
| 1647 potentiallyCheckType(argument, parameterType); | 1647 potentiallyCheckType(argument, parameterType); |
| 1648 }); | 1648 }); |
| 1649 } | 1649 } |
| 1650 | 1650 |
| 1651 /** | 1651 /** |
| 1652 * Documentation wanted -- johnniwinther | 1652 * Documentation wanted -- johnniwinther |
| 1653 * | 1653 * |
| 1654 * Invariant: [constructors] must contain only implementation elements. | 1654 * Invariant: [constructors] must contain only implementation elements. |
| 1655 */ | 1655 */ |
| 1656 void inlineSuperOrRedirect(FunctionElement callee, | 1656 void inlineSuperOrRedirect(FunctionElement callee, |
| 1657 List<HInstruction> compiledArguments, | 1657 List<HInstruction> compiledArguments, |
| 1658 List<FunctionElement> constructors, | 1658 List<FunctionElement> constructors, |
| 1659 Map<Element, HInstruction> fieldValues, | 1659 Map<Element, HInstruction> fieldValues, |
| 1660 FunctionElement caller) { | 1660 FunctionElement caller) { |
| 1661 callee = callee.implementation; | 1661 callee = callee.implementation; |
| 1662 compiler.withCurrentElement(callee, () { | 1662 compiler.withCurrentElement(callee, () { |
| 1663 constructors.add(callee); | 1663 constructors.add(callee); |
| 1664 ClassElement enclosingClass = callee.getEnclosingClass(); | 1664 ClassElement enclosingClass = callee.enclosingClass; |
| 1665 if (backend.classNeedsRti(enclosingClass)) { | 1665 if (backend.classNeedsRti(enclosingClass)) { |
| 1666 // If [enclosingClass] needs RTI, we have to give a value to its | 1666 // If [enclosingClass] needs RTI, we have to give a value to its |
| 1667 // type parameters. | 1667 // type parameters. |
| 1668 ClassElement currentClass = caller.getEnclosingClass(); | 1668 ClassElement currentClass = caller.enclosingClass; |
| 1669 // For a super constructor call, the type is the supertype of | 1669 // For a super constructor call, the type is the supertype of |
| 1670 // [currentClass]. For a redirecting constructor, the type is | 1670 // [currentClass]. For a redirecting constructor, the type is |
| 1671 // the current type. [InterfaceType.asInstanceOf] takes care | 1671 // the current type. [InterfaceType.asInstanceOf] takes care |
| 1672 // of both. | 1672 // of both. |
| 1673 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); | 1673 InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass); |
| 1674 Link<DartType> typeVariables = enclosingClass.typeVariables; | 1674 Link<DartType> typeVariables = enclosingClass.typeVariables; |
| 1675 type.typeArguments.forEach((DartType argument) { | 1675 type.typeArguments.forEach((DartType argument) { |
| 1676 localsHandler.updateLocal( | 1676 localsHandler.updateLocal( |
| 1677 typeVariables.head.element, | 1677 typeVariables.head.element, |
| 1678 analyzeTypeArgument(argument)); | 1678 analyzeTypeArgument(argument)); |
| 1679 typeVariables = typeVariables.tail; | 1679 typeVariables = typeVariables.tail; |
| 1680 }); | 1680 }); |
| 1681 // If the supertype is a raw type, we need to set to null the | 1681 // If the supertype is a raw type, we need to set to null the |
| 1682 // type variables. | 1682 // type variables. |
| 1683 assert(typeVariables.isEmpty | 1683 assert(typeVariables.isEmpty |
| 1684 || enclosingClass.typeVariables == typeVariables); | 1684 || enclosingClass.typeVariables == typeVariables); |
| 1685 while (!typeVariables.isEmpty) { | 1685 while (!typeVariables.isEmpty) { |
| 1686 localsHandler.updateLocal(typeVariables.head.element, | 1686 localsHandler.updateLocal(typeVariables.head.element, |
| 1687 graph.addConstantNull(compiler)); | 1687 graph.addConstantNull(compiler)); |
| 1688 typeVariables = typeVariables.tail; | 1688 typeVariables = typeVariables.tail; |
| 1689 } | 1689 } |
| 1690 } | 1690 } |
| 1691 | 1691 |
| 1692 // For redirecting constructors, the fields have already been | 1692 // For redirecting constructors, the fields have already been |
| 1693 // initialized by the caller. | 1693 // initialized by the caller. |
| 1694 if (callee.getEnclosingClass() != caller.getEnclosingClass()) { | 1694 if (callee.enclosingClass != caller.enclosingClass) { |
| 1695 inlinedFrom(callee, () { | 1695 inlinedFrom(callee, () { |
| 1696 buildFieldInitializers(callee.enclosingElement.implementation, | 1696 buildFieldInitializers(callee.enclosingElement.implementation, |
| 1697 fieldValues); | 1697 fieldValues); |
| 1698 }); | 1698 }); |
| 1699 } | 1699 } |
| 1700 | 1700 |
| 1701 int index = 0; | 1701 int index = 0; |
| 1702 FunctionSignature params = callee.functionSignature; | 1702 FunctionSignature params = callee.functionSignature; |
| 1703 params.orderedForEachParameter((Element parameter) { | 1703 params.orderedForEachParameter((Element parameter) { |
| 1704 HInstruction argument = compiledArguments[index++]; | 1704 HInstruction argument = compiledArguments[index++]; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1804 visit(arguments.head); | 1804 visit(arguments.head); |
| 1805 }); | 1805 }); |
| 1806 fieldValues[elements[init]] = pop(); | 1806 fieldValues[elements[init]] = pop(); |
| 1807 } | 1807 } |
| 1808 } | 1808 } |
| 1809 } | 1809 } |
| 1810 | 1810 |
| 1811 if (!foundSuperOrRedirect) { | 1811 if (!foundSuperOrRedirect) { |
| 1812 // No super initializer found. Try to find the default constructor if | 1812 // No super initializer found. Try to find the default constructor if |
| 1813 // the class is not Object. | 1813 // the class is not Object. |
| 1814 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1814 ClassElement enclosingClass = constructor.enclosingClass; |
| 1815 ClassElement superClass = enclosingClass.superclass; | 1815 ClassElement superClass = enclosingClass.superclass; |
| 1816 if (!enclosingClass.isObject(compiler)) { | 1816 if (!enclosingClass.isObject(compiler)) { |
| 1817 assert(superClass != null); | 1817 assert(superClass != null); |
| 1818 assert(superClass.resolutionState == STATE_DONE); | 1818 assert(superClass.resolutionState == STATE_DONE); |
| 1819 Selector selector = | 1819 Selector selector = |
| 1820 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); | 1820 new Selector.callDefaultConstructor(enclosingClass.library); |
| 1821 // TODO(johnniwinther): Should we find injected constructors as well? | 1821 // TODO(johnniwinther): Should we find injected constructors as well? |
| 1822 FunctionElement target = superClass.lookupConstructor(selector); | 1822 FunctionElement target = superClass.lookupConstructor(selector); |
| 1823 if (target == null) { | 1823 if (target == null) { |
| 1824 compiler.internalError(superClass, | 1824 compiler.internalError(superClass, |
| 1825 "No default constructor available."); | 1825 "No default constructor available."); |
| 1826 } | 1826 } |
| 1827 List<HInstruction> arguments = <HInstruction>[]; | 1827 List<HInstruction> arguments = <HInstruction>[]; |
| 1828 selector.addArgumentsToList(const Link<ast.Node>(), | 1828 selector.addArgumentsToList(const Link<ast.Node>(), |
| 1829 arguments, | 1829 arguments, |
| 1830 target.implementation, | 1830 target.implementation, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1882 * [functionElement]: | 1882 * [functionElement]: |
| 1883 * - Initialize fields with the values of the field initializers of the | 1883 * - Initialize fields with the values of the field initializers of the |
| 1884 * current constructor and super constructors or constructors redirected | 1884 * current constructor and super constructors or constructors redirected |
| 1885 * to, starting from the current constructor. | 1885 * to, starting from the current constructor. |
| 1886 * - Call the constructor bodies, starting from the constructor(s) in the | 1886 * - Call the constructor bodies, starting from the constructor(s) in the |
| 1887 * super class(es). | 1887 * super class(es). |
| 1888 */ | 1888 */ |
| 1889 HGraph buildFactory(FunctionElement functionElement) { | 1889 HGraph buildFactory(FunctionElement functionElement) { |
| 1890 functionElement = functionElement.implementation; | 1890 functionElement = functionElement.implementation; |
| 1891 ClassElement classElement = | 1891 ClassElement classElement = |
| 1892 functionElement.getEnclosingClass().implementation; | 1892 functionElement.enclosingClass.implementation; |
| 1893 bool isNativeUpgradeFactory = | 1893 bool isNativeUpgradeFactory = |
| 1894 Elements.isNativeOrExtendsNative(classElement); | 1894 Elements.isNativeOrExtendsNative(classElement); |
| 1895 ast.FunctionExpression function = functionElement.parseNode(compiler); | 1895 ast.FunctionExpression function = functionElement.parseNode(compiler); |
| 1896 // Note that constructors (like any other static function) do not need | 1896 // Note that constructors (like any other static function) do not need |
| 1897 // to deal with optional arguments. It is the callers job to provide all | 1897 // to deal with optional arguments. It is the callers job to provide all |
| 1898 // arguments as if they were positional. | 1898 // arguments as if they were positional. |
| 1899 | 1899 |
| 1900 if (inliningStack.isEmpty) { | 1900 if (inliningStack.isEmpty) { |
| 1901 // The initializer list could contain closures. | 1901 // The initializer list could contain closures. |
| 1902 openFunction(functionElement, function); | 1902 openFunction(functionElement, function); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 HConstant index = invoke.inputs[1]; | 2011 HConstant index = invoke.inputs[1]; |
| 2012 HInstruction newSource = invoke.inputs[0]; | 2012 HInstruction newSource = invoke.inputs[0]; |
| 2013 if (newSource is! HThis) { | 2013 if (newSource is! HThis) { |
| 2014 return false; | 2014 return false; |
| 2015 } | 2015 } |
| 2016 if (source == null) { | 2016 if (source == null) { |
| 2017 // This is the first match. Extract the context class for the type | 2017 // This is the first match. Extract the context class for the type |
| 2018 // variables and get the list of type variables to keep track of how | 2018 // variables and get the list of type variables to keep track of how |
| 2019 // many arguments we need to process. | 2019 // many arguments we need to process. |
| 2020 source = newSource; | 2020 source = newSource; |
| 2021 contextClass = source.sourceElement.getEnclosingClass(); | 2021 contextClass = source.sourceElement.enclosingClass; |
| 2022 typeVariables = contextClass.typeVariables; | 2022 typeVariables = contextClass.typeVariables; |
| 2023 } else { | 2023 } else { |
| 2024 assert(source == newSource); | 2024 assert(source == newSource); |
| 2025 } | 2025 } |
| 2026 // If there are no more type variables, then there are more type | 2026 // If there are no more type variables, then there are more type |
| 2027 // arguments for the new object than the source has, and it can't be | 2027 // arguments for the new object than the source has, and it can't be |
| 2028 // a copy. Otherwise remove one argument. | 2028 // a copy. Otherwise remove one argument. |
| 2029 if (typeVariables.isEmpty) return false; | 2029 if (typeVariables.isEmpty) return false; |
| 2030 typeVariables = typeVariables.tail; | 2030 typeVariables = typeVariables.tail; |
| 2031 // Check that the index is the one we expect. | 2031 // Check that the index is the one we expect. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2076 FunctionSignature functionSignature = body.functionSignature; | 2076 FunctionSignature functionSignature = body.functionSignature; |
| 2077 // Provide the parameters to the generative constructor body. | 2077 // Provide the parameters to the generative constructor body. |
| 2078 functionSignature.orderedForEachParameter((parameter) { | 2078 functionSignature.orderedForEachParameter((parameter) { |
| 2079 // If [parameter] is boxed, it will be a field in the box passed as the | 2079 // If [parameter] is boxed, it will be a field in the box passed as the |
| 2080 // last parameter. So no need to directly pass it. | 2080 // last parameter. So no need to directly pass it. |
| 2081 if (!localsHandler.isBoxed(parameter)) { | 2081 if (!localsHandler.isBoxed(parameter)) { |
| 2082 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 2082 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 2083 } | 2083 } |
| 2084 }); | 2084 }); |
| 2085 | 2085 |
| 2086 ClassElement currentClass = constructor.getEnclosingClass(); | 2086 ClassElement currentClass = constructor.enclosingClass; |
| 2087 if (backend.classNeedsRti(currentClass)) { | 2087 if (backend.classNeedsRti(currentClass)) { |
| 2088 // If [currentClass] needs RTI, we add the type variables as | 2088 // If [currentClass] needs RTI, we add the type variables as |
| 2089 // parameters of the generative constructor body. | 2089 // parameters of the generative constructor body. |
| 2090 currentClass.typeVariables.forEach((DartType argument) { | 2090 currentClass.typeVariables.forEach((DartType argument) { |
| 2091 bodyCallInputs.add(localsHandler.readLocal(argument.element)); | 2091 bodyCallInputs.add(localsHandler.readLocal(argument.element)); |
| 2092 }); | 2092 }); |
| 2093 } | 2093 } |
| 2094 | 2094 |
| 2095 // If there are locals that escape (ie mutated in closures), we | 2095 // If there are locals that escape (ie mutated in closures), we |
| 2096 // pass the box to the constructor. | 2096 // pass the box to the constructor. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2131 | 2131 |
| 2132 localsHandler.startFunction(element, node); | 2132 localsHandler.startFunction(element, node); |
| 2133 close(new HGoto()).addSuccessor(block); | 2133 close(new HGoto()).addSuccessor(block); |
| 2134 | 2134 |
| 2135 open(block); | 2135 open(block); |
| 2136 | 2136 |
| 2137 // Add the type parameters of the class as parameters of this method. This | 2137 // Add the type parameters of the class as parameters of this method. This |
| 2138 // must be done before adding the normal parameters, because their types | 2138 // must be done before adding the normal parameters, because their types |
| 2139 // may contain references to type variables. | 2139 // may contain references to type variables. |
| 2140 var enclosing = element.enclosingElement; | 2140 var enclosing = element.enclosingElement; |
| 2141 if ((element.isConstructor() || element.isGenerativeConstructorBody()) | 2141 if ((element.isConstructor || element.isGenerativeConstructorBody) |
| 2142 && backend.classNeedsRti(enclosing)) { | 2142 && backend.classNeedsRti(enclosing)) { |
| 2143 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { | 2143 enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
| 2144 HParameterValue param = addParameter( | 2144 HParameterValue param = addParameter( |
| 2145 typeVariable.element, backend.nonNullType); | 2145 typeVariable.element, backend.nonNullType); |
| 2146 localsHandler.directLocals[typeVariable.element] = param; | 2146 localsHandler.directLocals[typeVariable.element] = param; |
| 2147 }); | 2147 }); |
| 2148 } | 2148 } |
| 2149 | 2149 |
| 2150 if (element is FunctionElement) { | 2150 if (element is FunctionElement) { |
| 2151 FunctionElement functionElement = element; | 2151 FunctionElement functionElement = element; |
| 2152 FunctionSignature signature = functionElement.functionSignature; | 2152 FunctionSignature signature = functionElement.functionSignature; |
| 2153 | 2153 |
| 2154 // Put the type checks in the first successor of the entry, | 2154 // Put the type checks in the first successor of the entry, |
| 2155 // because that is where the type guards will also be inserted. | 2155 // because that is where the type guards will also be inserted. |
| 2156 // This way we ensure that a type guard will dominate the type | 2156 // This way we ensure that a type guard will dominate the type |
| 2157 // check. | 2157 // check. |
| 2158 signature.orderedForEachParameter((ParameterElement parameterElement) { | 2158 signature.orderedForEachParameter((ParameterElement parameterElement) { |
| 2159 if (element.isGenerativeConstructorBody()) { | 2159 if (element.isGenerativeConstructorBody) { |
| 2160 ClosureScope scopeData = | 2160 ClosureScope scopeData = |
| 2161 localsHandler.closureData.capturingScopes[node]; | 2161 localsHandler.closureData.capturingScopes[node]; |
| 2162 if (scopeData != null | 2162 if (scopeData != null |
| 2163 && scopeData.capturedVariableMapping.containsKey( | 2163 && scopeData.capturedVariableMapping.containsKey( |
| 2164 parameterElement)) { | 2164 parameterElement)) { |
| 2165 // The parameter will be a field in the box passed as the | 2165 // The parameter will be a field in the box passed as the |
| 2166 // last parameter. So no need to have it. | 2166 // last parameter. So no need to have it. |
| 2167 return; | 2167 return; |
| 2168 } | 2168 } |
| 2169 } | 2169 } |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2814 // TODO(ahe): This should be registered in codegen, not here. | 2814 // TODO(ahe): This should be registered in codegen, not here. |
| 2815 compiler.enqueuer.codegen.addToWorkList(callElement); | 2815 compiler.enqueuer.codegen.addToWorkList(callElement); |
| 2816 // TODO(ahe): This should be registered in codegen, not here. | 2816 // TODO(ahe): This should be registered in codegen, not here. |
| 2817 compiler.enqueuer.codegen.registerInstantiatedClass( | 2817 compiler.enqueuer.codegen.registerInstantiatedClass( |
| 2818 closureClassElement, work.resolutionTree); | 2818 closureClassElement, work.resolutionTree); |
| 2819 | 2819 |
| 2820 List<HInstruction> capturedVariables = <HInstruction>[]; | 2820 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 2821 closureClassElement.forEachMember((_, Element member) { | 2821 closureClassElement.forEachMember((_, Element member) { |
| 2822 // The backendMembers also contains the call method(s). We are only | 2822 // The backendMembers also contains the call method(s). We are only |
| 2823 // interested in the fields. | 2823 // interested in the fields. |
| 2824 if (member.isField()) { | 2824 if (member.isField) { |
| 2825 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; | 2825 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; |
| 2826 assert(capturedLocal != null); | 2826 assert(capturedLocal != null); |
| 2827 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 2827 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 2828 } | 2828 } |
| 2829 }); | 2829 }); |
| 2830 | 2830 |
| 2831 TypeMask type = new TypeMask.nonNullExact(compiler.functionClass); | 2831 TypeMask type = new TypeMask.nonNullExact(compiler.functionClass); |
| 2832 push(new HForeignNew(closureClassElement, type, capturedVariables)); | 2832 push(new HForeignNew(closureClassElement, type, capturedVariables)); |
| 2833 | 2833 |
| 2834 Element methodElement = nestedClosureData.closureElement; | 2834 Element methodElement = nestedClosureData.closureElement; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2943 } | 2943 } |
| 2944 | 2944 |
| 2945 /** | 2945 /** |
| 2946 * Returns a set of interceptor classes that contain the given | 2946 * Returns a set of interceptor classes that contain the given |
| 2947 * [selector]. | 2947 * [selector]. |
| 2948 */ | 2948 */ |
| 2949 void generateInstanceGetterWithCompiledReceiver(ast.Send send, | 2949 void generateInstanceGetterWithCompiledReceiver(ast.Send send, |
| 2950 Selector selector, | 2950 Selector selector, |
| 2951 HInstruction receiver) { | 2951 HInstruction receiver) { |
| 2952 assert(Elements.isInstanceSend(send, elements)); | 2952 assert(Elements.isInstanceSend(send, elements)); |
| 2953 assert(selector.isGetter()); | 2953 assert(selector.isGetter); |
| 2954 pushInvokeDynamic(send, selector, [receiver]); | 2954 pushInvokeDynamic(send, selector, [receiver]); |
| 2955 } | 2955 } |
| 2956 | 2956 |
| 2957 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that | 2957 /// Inserts a call to checkDeferredIsLoaded if the send has a prefix that |
| 2958 /// resolves to a deferred library. | 2958 /// resolves to a deferred library. |
| 2959 void generateIsDeferredLoadedCheckIfNeeded(ast.Send node) { | 2959 void generateIsDeferredLoadedCheckIfNeeded(ast.Send node) { |
| 2960 DeferredLoadTask deferredTask = compiler.deferredLoadTask; | 2960 DeferredLoadTask deferredTask = compiler.deferredLoadTask; |
| 2961 PrefixElement prefixElement = | 2961 PrefixElement prefixElement = |
| 2962 deferredTask.deferredPrefixElement(node, elements); | 2962 deferredTask.deferredPrefixElement(node, elements); |
| 2963 if (prefixElement != null) { | 2963 if (prefixElement != null) { |
| 2964 String loadId = | 2964 String loadId = |
| 2965 deferredTask.importDeferName[prefixElement.deferredImport]; | 2965 deferredTask.importDeferName[prefixElement.deferredImport]; |
| 2966 HInstruction loadIdConstant = addConstantString(loadId); | 2966 HInstruction loadIdConstant = addConstantString(loadId); |
| 2967 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); | 2967 String uri = prefixElement.deferredImport.uri.dartString.slowToString(); |
| 2968 HInstruction uriConstant = addConstantString(uri); | 2968 HInstruction uriConstant = addConstantString(uri); |
| 2969 Element helper = backend.getCheckDeferredIsLoaded(); | 2969 Element helper = backend.getCheckDeferredIsLoaded(); |
| 2970 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]); | 2970 pushInvokeStatic(node, helper, [loadIdConstant, uriConstant]); |
| 2971 pop(); | 2971 pop(); |
| 2972 } | 2972 } |
| 2973 } | 2973 } |
| 2974 | 2974 |
| 2975 void generateGetter(ast.Send send, Element element) { | 2975 void generateGetter(ast.Send send, Element element) { |
| 2976 if (element != null && element.isForeign(compiler)) { | 2976 if (element != null && element.isForeign(compiler)) { |
| 2977 visitForeignGetter(send); | 2977 visitForeignGetter(send); |
| 2978 } else if (Elements.isStaticOrTopLevelField(element)) { | 2978 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 2979 Constant value; | 2979 Constant value; |
| 2980 if (element.isField() && !element.isAssignable()) { | 2980 if (element.isField && !element.isAssignable) { |
| 2981 // A static final or const. Get its constant value and inline it if | 2981 // A static final or const. Get its constant value and inline it if |
| 2982 // the value can be compiled eagerly. | 2982 // the value can be compiled eagerly. |
| 2983 value = backend.constants.getConstantForVariable(element); | 2983 value = backend.constants.getConstantForVariable(element); |
| 2984 } | 2984 } |
| 2985 if (value != null) { | 2985 if (value != null) { |
| 2986 HConstant instruction = graph.addConstant(value, compiler); | 2986 HConstant instruction = graph.addConstant(value, compiler); |
| 2987 stack.add(instruction); | 2987 stack.add(instruction); |
| 2988 // The inferrer may have found a better type than the constant | 2988 // The inferrer may have found a better type than the constant |
| 2989 // handler in the case of lists, because the constant handler | 2989 // handler in the case of lists, because the constant handler |
| 2990 // does not look at elements in the list. | 2990 // does not look at elements in the list. |
| 2991 TypeMask type = | 2991 TypeMask type = |
| 2992 TypeMaskFactory.inferredTypeForElement(element, compiler); | 2992 TypeMaskFactory.inferredTypeForElement(element, compiler); |
| 2993 if (!type.containsAll(compiler) && !instruction.isConstantNull()) { | 2993 if (!type.containsAll(compiler) && !instruction.isConstantNull()) { |
| 2994 // TODO(13429): The inferrer should know that an element | 2994 // TODO(13429): The inferrer should know that an element |
| 2995 // cannot be null. | 2995 // cannot be null. |
| 2996 instruction.instructionType = type.nonNullable(); | 2996 instruction.instructionType = type.nonNullable(); |
| 2997 } | 2997 } |
| 2998 } else if (element.isField() && isLazilyInitialized(element)) { | 2998 } else if (element.isField && isLazilyInitialized(element)) { |
| 2999 HInstruction instruction = new HLazyStatic( | 2999 HInstruction instruction = new HLazyStatic( |
| 3000 element, | 3000 element, |
| 3001 TypeMaskFactory.inferredTypeForElement(element, compiler)); | 3001 TypeMaskFactory.inferredTypeForElement(element, compiler)); |
| 3002 push(instruction); | 3002 push(instruction); |
| 3003 } else { | 3003 } else { |
| 3004 if (element.isGetter()) { | 3004 if (element.isGetter) { |
| 3005 pushInvokeStatic(send, element, <HInstruction>[]); | 3005 pushInvokeStatic(send, element, <HInstruction>[]); |
| 3006 } else { | 3006 } else { |
| 3007 // TODO(5346): Try to avoid the need for calling [declaration] before | 3007 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 3008 // creating an [HStatic]. | 3008 // creating an [HStatic]. |
| 3009 HInstruction instruction = new HStatic( | 3009 HInstruction instruction = new HStatic( |
| 3010 element.declaration, | 3010 element.declaration, |
| 3011 TypeMaskFactory.inferredTypeForElement(element, compiler)); | 3011 TypeMaskFactory.inferredTypeForElement(element, compiler)); |
| 3012 push(instruction); | 3012 push(instruction); |
| 3013 } | 3013 } |
| 3014 } | 3014 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3040 ast.Node location}) { | 3040 ast.Node location}) { |
| 3041 assert(send == null || Elements.isInstanceSend(send, elements)); | 3041 assert(send == null || Elements.isInstanceSend(send, elements)); |
| 3042 if (selector == null) { | 3042 if (selector == null) { |
| 3043 assert(send != null); | 3043 assert(send != null); |
| 3044 selector = elements.getSelector(send); | 3044 selector = elements.getSelector(send); |
| 3045 } | 3045 } |
| 3046 if (location == null) { | 3046 if (location == null) { |
| 3047 assert(send != null); | 3047 assert(send != null); |
| 3048 location = send; | 3048 location = send; |
| 3049 } | 3049 } |
| 3050 assert(selector.isSetter()); | 3050 assert(selector.isSetter); |
| 3051 pushInvokeDynamic(location, selector, [receiver, value]); | 3051 pushInvokeDynamic(location, selector, [receiver, value]); |
| 3052 pop(); | 3052 pop(); |
| 3053 stack.add(value); | 3053 stack.add(value); |
| 3054 } | 3054 } |
| 3055 | 3055 |
| 3056 void generateNonInstanceSetter(ast.SendSet send, | 3056 void generateNonInstanceSetter(ast.SendSet send, |
| 3057 Element element, | 3057 Element element, |
| 3058 HInstruction value, | 3058 HInstruction value, |
| 3059 {ast.Node location}) { | 3059 {ast.Node location}) { |
| 3060 assert(send == null || !Elements.isInstanceSend(send, elements)); | 3060 assert(send == null || !Elements.isInstanceSend(send, elements)); |
| 3061 if (location == null) { | 3061 if (location == null) { |
| 3062 assert(send != null); | 3062 assert(send != null); |
| 3063 location = send; | 3063 location = send; |
| 3064 } | 3064 } |
| 3065 if (Elements.isStaticOrTopLevelField(element)) { | 3065 if (Elements.isStaticOrTopLevelField(element)) { |
| 3066 if (element.isSetter()) { | 3066 if (element.isSetter) { |
| 3067 pushInvokeStatic(location, element, <HInstruction>[value]); | 3067 pushInvokeStatic(location, element, <HInstruction>[value]); |
| 3068 pop(); | 3068 pop(); |
| 3069 } else { | 3069 } else { |
| 3070 VariableElement field = element; | 3070 VariableElement field = element; |
| 3071 value = | 3071 value = |
| 3072 potentiallyCheckType(value, field.type); | 3072 potentiallyCheckType(value, field.type); |
| 3073 addWithPosition(new HStaticStore(element, value), location); | 3073 addWithPosition(new HStaticStore(element, value), location); |
| 3074 } | 3074 } |
| 3075 stack.add(value); | 3075 stack.add(value); |
| 3076 } else if (Elements.isErroneousElement(element)) { | 3076 } else if (Elements.isErroneousElement(element)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3112 } | 3112 } |
| 3113 | 3113 |
| 3114 // TODO(karlklose): change construction of the representations to be GVN'able | 3114 // TODO(karlklose): change construction of the representations to be GVN'able |
| 3115 // (dartbug.com/7182). | 3115 // (dartbug.com/7182). |
| 3116 HInstruction buildTypeArgumentRepresentations(DartType type) { | 3116 HInstruction buildTypeArgumentRepresentations(DartType type) { |
| 3117 // Compute the representation of the type arguments, including access | 3117 // Compute the representation of the type arguments, including access |
| 3118 // to the runtime type information for type variables as instructions. | 3118 // to the runtime type information for type variables as instructions. |
| 3119 if (type.kind == TypeKind.TYPE_VARIABLE) { | 3119 if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 3120 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); | 3120 return buildLiteralList(<HInstruction>[addTypeVariableReference(type)]); |
| 3121 } else { | 3121 } else { |
| 3122 assert(type.element.isClass()); | 3122 assert(type.element.isClass); |
| 3123 InterfaceType interface = type; | 3123 InterfaceType interface = type; |
| 3124 List<HInstruction> inputs = <HInstruction>[]; | 3124 List<HInstruction> inputs = <HInstruction>[]; |
| 3125 bool first = true; | 3125 bool first = true; |
| 3126 List<String> templates = <String>[]; | 3126 List<String> templates = <String>[]; |
| 3127 for (DartType argument in interface.typeArguments) { | 3127 for (DartType argument in interface.typeArguments) { |
| 3128 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { | 3128 templates.add(rti.getTypeRepresentationWithHashes(argument, (variable) { |
| 3129 HInstruction runtimeType = addTypeVariableReference(variable); | 3129 HInstruction runtimeType = addTypeVariableReference(variable); |
| 3130 inputs.add(runtimeType); | 3130 inputs.add(runtimeType); |
| 3131 })); | 3131 })); |
| 3132 } | 3132 } |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3310 | 3310 |
| 3311 visitDynamicSend(ast.Send node) { | 3311 visitDynamicSend(ast.Send node) { |
| 3312 Selector selector = elements.getSelector(node); | 3312 Selector selector = elements.getSelector(node); |
| 3313 | 3313 |
| 3314 List<HInstruction> inputs = <HInstruction>[]; | 3314 List<HInstruction> inputs = <HInstruction>[]; |
| 3315 HInstruction receiver = generateInstanceSendReceiver(node); | 3315 HInstruction receiver = generateInstanceSendReceiver(node); |
| 3316 inputs.add(receiver); | 3316 inputs.add(receiver); |
| 3317 addDynamicSendArgumentsToList(node, inputs); | 3317 addDynamicSendArgumentsToList(node, inputs); |
| 3318 | 3318 |
| 3319 pushInvokeDynamic(node, selector, inputs); | 3319 pushInvokeDynamic(node, selector, inputs); |
| 3320 if (selector.isSetter() || selector.isIndexSet()) { | 3320 if (selector.isSetter || selector.isIndexSet) { |
| 3321 pop(); | 3321 pop(); |
| 3322 stack.add(inputs.last); | 3322 stack.add(inputs.last); |
| 3323 } | 3323 } |
| 3324 } | 3324 } |
| 3325 | 3325 |
| 3326 visitClosureSend(ast.Send node) { | 3326 visitClosureSend(ast.Send node) { |
| 3327 Selector selector = elements.getSelector(node); | 3327 Selector selector = elements.getSelector(node); |
| 3328 assert(node.receiver == null); | 3328 assert(node.receiver == null); |
| 3329 Element element = elements[node]; | 3329 Element element = elements[node]; |
| 3330 HInstruction closureTarget; | 3330 HInstruction closureTarget; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3676 } else if (name == 'JS_STRING_CONCAT') { | 3676 } else if (name == 'JS_STRING_CONCAT') { |
| 3677 handleJsStringConcat(node); | 3677 handleJsStringConcat(node); |
| 3678 } else { | 3678 } else { |
| 3679 throw "Unknown foreign: ${selector}"; | 3679 throw "Unknown foreign: ${selector}"; |
| 3680 } | 3680 } |
| 3681 } | 3681 } |
| 3682 | 3682 |
| 3683 visitForeignGetter(ast.Send node) { | 3683 visitForeignGetter(ast.Send node) { |
| 3684 Element element = elements[node]; | 3684 Element element = elements[node]; |
| 3685 // Until now we only handle these as getters. | 3685 // Until now we only handle these as getters. |
| 3686 invariant(node, element.isDeferredLoaderGetter()); | 3686 invariant(node, element.isDeferredLoaderGetter); |
| 3687 FunctionElement deferredLoader = element; | 3687 FunctionElement deferredLoader = element; |
| 3688 Element loadFunction = compiler.loadLibraryFunction; | 3688 Element loadFunction = compiler.loadLibraryFunction; |
| 3689 PrefixElement prefixElement = deferredLoader.enclosingElement; | 3689 PrefixElement prefixElement = deferredLoader.enclosingElement; |
| 3690 String loadId = compiler.deferredLoadTask | 3690 String loadId = compiler.deferredLoadTask |
| 3691 .importDeferName[prefixElement.deferredImport]; | 3691 .importDeferName[prefixElement.deferredImport]; |
| 3692 var inputs = [graph.addConstantString( | 3692 var inputs = [graph.addConstantString( |
| 3693 new ast.DartString.literal(loadId), compiler)]; | 3693 new ast.DartString.literal(loadId), compiler)]; |
| 3694 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, | 3694 push(new HInvokeStatic(loadFunction, inputs, backend.nonNullType, |
| 3695 targetCanThrow: false)); | 3695 targetCanThrow: false)); |
| 3696 } | 3696 } |
| 3697 | 3697 |
| 3698 generateSuperNoSuchMethodSend(ast.Send node, | 3698 generateSuperNoSuchMethodSend(ast.Send node, |
| 3699 Selector selector, | 3699 Selector selector, |
| 3700 List<HInstruction> arguments) { | 3700 List<HInstruction> arguments) { |
| 3701 String name = selector.name; | 3701 String name = selector.name; |
| 3702 | 3702 |
| 3703 ClassElement cls = currentNonClosureClass; | 3703 ClassElement cls = currentNonClosureClass; |
| 3704 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); | 3704 Element element = cls.lookupSuperMember(Compiler.NO_SUCH_METHOD); |
| 3705 if (compiler.enabledInvokeOn | 3705 if (compiler.enabledInvokeOn |
| 3706 && element.enclosingElement.declaration != compiler.objectClass) { | 3706 && element.enclosingElement.declaration != compiler.objectClass) { |
| 3707 // Register the call as dynamic if [noSuchMethod] on the super | 3707 // Register the call as dynamic if [noSuchMethod] on the super |
| 3708 // class is _not_ the default implementation from [Object], in | 3708 // class is _not_ the default implementation from [Object], in |
| 3709 // case the [noSuchMethod] implementation calls | 3709 // case the [noSuchMethod] implementation calls |
| 3710 // [JSInvocationMirror._invokeOn]. | 3710 // [JSInvocationMirror._invokeOn]. |
| 3711 compiler.enqueuer.codegen.registerSelectorUse(selector.asUntyped); | 3711 compiler.enqueuer.codegen.registerSelectorUse(selector.asUntyped); |
| 3712 } | 3712 } |
| 3713 String publicName = name; | 3713 String publicName = name; |
| 3714 if (selector.isSetter()) publicName += '='; | 3714 if (selector.isSetter) publicName += '='; |
| 3715 | 3715 |
| 3716 Constant nameConstant = constantSystem.createString( | 3716 Constant nameConstant = constantSystem.createString( |
| 3717 new ast.DartString.literal(publicName)); | 3717 new ast.DartString.literal(publicName)); |
| 3718 | 3718 |
| 3719 String internalName = backend.namer.invocationName(selector); | 3719 String internalName = backend.namer.invocationName(selector); |
| 3720 Constant internalNameConstant = | 3720 Constant internalNameConstant = |
| 3721 constantSystem.createString(new ast.DartString.literal(internalName)); | 3721 constantSystem.createString(new ast.DartString.literal(internalName)); |
| 3722 | 3722 |
| 3723 Element createInvocationMirror = backend.getCreateInvocationMirror(); | 3723 Element createInvocationMirror = backend.getCreateInvocationMirror(); |
| 3724 var argumentsInstruction = buildLiteralList(arguments); | 3724 var argumentsInstruction = buildLiteralList(arguments); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3755 if (Elements.isUnresolved(element)) { | 3755 if (Elements.isUnresolved(element)) { |
| 3756 List<HInstruction> arguments = <HInstruction>[]; | 3756 List<HInstruction> arguments = <HInstruction>[]; |
| 3757 if (!node.isPropertyAccess) { | 3757 if (!node.isPropertyAccess) { |
| 3758 addGenericSendArgumentsToList(node.arguments, arguments); | 3758 addGenericSendArgumentsToList(node.arguments, arguments); |
| 3759 } | 3759 } |
| 3760 return generateSuperNoSuchMethodSend(node, selector, arguments); | 3760 return generateSuperNoSuchMethodSend(node, selector, arguments); |
| 3761 } | 3761 } |
| 3762 List<HInstruction> inputs = <HInstruction>[]; | 3762 List<HInstruction> inputs = <HInstruction>[]; |
| 3763 if (node.isPropertyAccess) { | 3763 if (node.isPropertyAccess) { |
| 3764 push(buildInvokeSuper(selector, element, inputs)); | 3764 push(buildInvokeSuper(selector, element, inputs)); |
| 3765 } else if (element.isFunction() || element.isGenerativeConstructor()) { | 3765 } else if (element.isFunction || element.isGenerativeConstructor) { |
| 3766 if (selector.applies(element, compiler)) { | 3766 if (selector.applies(element, compiler)) { |
| 3767 // TODO(5347): Try to avoid the need for calling [implementation] before | 3767 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 3768 // calling [addStaticSendArgumentsToList]. | 3768 // calling [addStaticSendArgumentsToList]. |
| 3769 FunctionElement function = element.implementation; | 3769 FunctionElement function = element.implementation; |
| 3770 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 3770 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 3771 function, inputs); | 3771 function, inputs); |
| 3772 assert(succeeded); | 3772 assert(succeeded); |
| 3773 push(buildInvokeSuper(selector, element, inputs)); | 3773 push(buildInvokeSuper(selector, element, inputs)); |
| 3774 } else if (element.isGenerativeConstructor()) { | 3774 } else if (element.isGenerativeConstructor) { |
| 3775 generateWrongArgumentCountError(node, element, node.arguments); | 3775 generateWrongArgumentCountError(node, element, node.arguments); |
| 3776 } else { | 3776 } else { |
| 3777 addGenericSendArgumentsToList(node.arguments, inputs); | 3777 addGenericSendArgumentsToList(node.arguments, inputs); |
| 3778 generateSuperNoSuchMethodSend(node, selector, inputs); | 3778 generateSuperNoSuchMethodSend(node, selector, inputs); |
| 3779 } | 3779 } |
| 3780 } else { | 3780 } else { |
| 3781 HInstruction target = buildInvokeSuper(selector, element, inputs); | 3781 HInstruction target = buildInvokeSuper(selector, element, inputs); |
| 3782 add(target); | 3782 add(target); |
| 3783 inputs = <HInstruction>[target]; | 3783 inputs = <HInstruction>[target]; |
| 3784 addDynamicSendArgumentsToList(node, inputs); | 3784 addDynamicSendArgumentsToList(node, inputs); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3797 } | 3797 } |
| 3798 | 3798 |
| 3799 /** | 3799 /** |
| 3800 * Generate code to extract the type arguments from the object, substitute | 3800 * Generate code to extract the type arguments from the object, substitute |
| 3801 * them as an instance of the type we are testing against (if necessary), and | 3801 * them as an instance of the type we are testing against (if necessary), and |
| 3802 * extract the type argument by the index of the variable in the list of type | 3802 * extract the type argument by the index of the variable in the list of type |
| 3803 * variables for that class. | 3803 * variables for that class. |
| 3804 */ | 3804 */ |
| 3805 HInstruction readTypeVariable(ClassElement cls, | 3805 HInstruction readTypeVariable(ClassElement cls, |
| 3806 TypeVariableElement variable) { | 3806 TypeVariableElement variable) { |
| 3807 assert(sourceElement.isInstanceMember()); | 3807 assert(sourceElement.isInstanceMember); |
| 3808 | 3808 |
| 3809 HInstruction target = localsHandler.readThis(); | 3809 HInstruction target = localsHandler.readThis(); |
| 3810 HConstant index = graph.addConstantInt( | 3810 HConstant index = graph.addConstantInt( |
| 3811 RuntimeTypes.getTypeVariableIndex(variable), | 3811 RuntimeTypes.getTypeVariableIndex(variable), |
| 3812 compiler); | 3812 compiler); |
| 3813 | 3813 |
| 3814 if (needsSubstitutionForTypeVariableAccess(cls)) { | 3814 if (needsSubstitutionForTypeVariableAccess(cls)) { |
| 3815 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 3815 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
| 3816 // string concatenation in the implementation), and may prevent | 3816 // string concatenation in the implementation), and may prevent |
| 3817 // segmentation of '$'. | 3817 // segmentation of '$'. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3836 bool hasDirectLocal(Element element) { | 3836 bool hasDirectLocal(Element element) { |
| 3837 return !localsHandler.isAccessedDirectly(element) || | 3837 return !localsHandler.isAccessedDirectly(element) || |
| 3838 localsHandler.directLocals[element] != null; | 3838 localsHandler.directLocals[element] != null; |
| 3839 } | 3839 } |
| 3840 | 3840 |
| 3841 /** | 3841 /** |
| 3842 * Helper to create an instruction that gets the value of a type variable. | 3842 * Helper to create an instruction that gets the value of a type variable. |
| 3843 */ | 3843 */ |
| 3844 HInstruction addTypeVariableReference(TypeVariableType type) { | 3844 HInstruction addTypeVariableReference(TypeVariableType type) { |
| 3845 Element member = sourceElement; | 3845 Element member = sourceElement; |
| 3846 bool isClosure = member.enclosingElement.isClosure(); | 3846 bool isClosure = member.enclosingElement.isClosure; |
| 3847 if (isClosure) { | 3847 if (isClosure) { |
| 3848 ClosureClassElement closureClass = member.enclosingElement; | 3848 ClosureClassElement closureClass = member.enclosingElement; |
| 3849 member = closureClass.methodElement; | 3849 member = closureClass.methodElement; |
| 3850 member = member.getOutermostEnclosingMemberOrTopLevel(); | 3850 member = member.outermostEnclosingMemberOrTopLevel; |
| 3851 } | 3851 } |
| 3852 bool isInConstructorContext = member.isConstructor() || | 3852 bool isInConstructorContext = member.isConstructor || |
| 3853 member.isGenerativeConstructorBody(); | 3853 member.isGenerativeConstructorBody; |
| 3854 if (isClosure) { | 3854 if (isClosure) { |
| 3855 if (member.isFactoryConstructor() || | 3855 if (member.isFactoryConstructor || |
| 3856 (isInConstructorContext && hasDirectLocal(type.element))) { | 3856 (isInConstructorContext && hasDirectLocal(type.element))) { |
| 3857 // The type variable is used from a closure in a factory constructor. | 3857 // The type variable is used from a closure in a factory constructor. |
| 3858 // The value of the type argument is stored as a local on the closure | 3858 // The value of the type argument is stored as a local on the closure |
| 3859 // itself. | 3859 // itself. |
| 3860 return localsHandler.readLocal(type.element); | 3860 return localsHandler.readLocal(type.element); |
| 3861 } else if (member.isFunction() || | 3861 } else if (member.isFunction || |
| 3862 member.isGetter() || | 3862 member.isGetter || |
| 3863 member.isSetter() || | 3863 member.isSetter || |
| 3864 isInConstructorContext) { | 3864 isInConstructorContext) { |
| 3865 // The type variable is stored on the "enclosing object" and needs to be | 3865 // The type variable is stored on the "enclosing object" and needs to be |
| 3866 // accessed using the this-reference in the closure. | 3866 // accessed using the this-reference in the closure. |
| 3867 return readTypeVariable(member.getEnclosingClass(), type.element); | 3867 return readTypeVariable(member.enclosingClass, type.element); |
| 3868 } else { | 3868 } else { |
| 3869 assert(member.isField()); | 3869 assert(member.isField); |
| 3870 // The type variable is stored in a parameter of the method. | 3870 // The type variable is stored in a parameter of the method. |
| 3871 return localsHandler.readLocal(type.element); | 3871 return localsHandler.readLocal(type.element); |
| 3872 } | 3872 } |
| 3873 } else if (isInConstructorContext || | 3873 } else if (isInConstructorContext || |
| 3874 // When [member] is a field, we can be either | 3874 // When [member] is a field, we can be either |
| 3875 // generating a checked setter or inlining its | 3875 // generating a checked setter or inlining its |
| 3876 // initializer in a constructor. An initializer is | 3876 // initializer in a constructor. An initializer is |
| 3877 // never built standalone, so [isBuildingFor] will | 3877 // never built standalone, so [isBuildingFor] will |
| 3878 // always return true when seeing one. | 3878 // always return true when seeing one. |
| 3879 (member.isField() && !isBuildingFor(member))) { | 3879 (member.isField && !isBuildingFor(member))) { |
| 3880 // The type variable is stored in a parameter of the method. | 3880 // The type variable is stored in a parameter of the method. |
| 3881 return localsHandler.readLocal(type.element); | 3881 return localsHandler.readLocal(type.element); |
| 3882 } else if (member.isInstanceMember()) { | 3882 } else if (member.isInstanceMember) { |
| 3883 // The type variable is stored on the object. | 3883 // The type variable is stored on the object. |
| 3884 return readTypeVariable(member.getEnclosingClass(), | 3884 return readTypeVariable(member.enclosingClass, |
| 3885 type.element); | 3885 type.element); |
| 3886 } else { | 3886 } else { |
| 3887 // TODO(ngeoffray): Match the VM behavior and throw an | 3887 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3888 // exception at runtime. | 3888 // exception at runtime. |
| 3889 compiler.internalError(type.element, | 3889 compiler.internalError(type.element, |
| 3890 'Unimplemented unresolved type variable.'); | 3890 'Unimplemented unresolved type variable.'); |
| 3891 return null; | 3891 return null; |
| 3892 } | 3892 } |
| 3893 } | 3893 } |
| 3894 | 3894 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3986 TypeMask inferred = | 3986 TypeMask inferred = |
| 3987 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); | 3987 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); |
| 3988 return inferred.containsAll(compiler) | 3988 return inferred.containsAll(compiler) |
| 3989 ? backend.extendableArrayType | 3989 ? backend.extendableArrayType |
| 3990 : inferred; | 3990 : inferred; |
| 3991 } else if (Elements.isConstructorOfTypedArraySubclass( | 3991 } else if (Elements.isConstructorOfTypedArraySubclass( |
| 3992 originalElement, compiler)) { | 3992 originalElement, compiler)) { |
| 3993 isFixedList = true; | 3993 isFixedList = true; |
| 3994 TypeMask inferred = | 3994 TypeMask inferred = |
| 3995 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); | 3995 TypeMaskFactory.inferredForNode(sourceElement, send, compiler); |
| 3996 ClassElement cls = element.getEnclosingClass(); | 3996 ClassElement cls = element.enclosingClass; |
| 3997 assert(cls.thisType.element.isNative()); | 3997 assert(cls.thisType.element.isNative); |
| 3998 return inferred.containsAll(compiler) | 3998 return inferred.containsAll(compiler) |
| 3999 ? new TypeMask.nonNullExact(cls.thisType.element) | 3999 ? new TypeMask.nonNullExact(cls.thisType.element) |
| 4000 : inferred; | 4000 : inferred; |
| 4001 } else if (element.isGenerativeConstructor()) { | 4001 } else if (element.isGenerativeConstructor) { |
| 4002 ClassElement cls = element.getEnclosingClass(); | 4002 ClassElement cls = element.enclosingClass; |
| 4003 return new TypeMask.nonNullExact(cls.thisType.element); | 4003 return new TypeMask.nonNullExact(cls.thisType.element); |
| 4004 } else { | 4004 } else { |
| 4005 return TypeMaskFactory.inferredReturnTypeForElement( | 4005 return TypeMaskFactory.inferredReturnTypeForElement( |
| 4006 originalElement, compiler); | 4006 originalElement, compiler); |
| 4007 } | 4007 } |
| 4008 } | 4008 } |
| 4009 | 4009 |
| 4010 Element constructor = elements[send]; | 4010 Element constructor = elements[send]; |
| 4011 Selector selector = elements.getSelector(send); | 4011 Selector selector = elements.getSelector(send); |
| 4012 FunctionElement functionElement = constructor; | 4012 FunctionElement functionElement = constructor; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4026 message: 'Constructor Symbol.validated is missing')); | 4026 message: 'Constructor Symbol.validated is missing')); |
| 4027 } | 4027 } |
| 4028 | 4028 |
| 4029 bool isRedirected = functionElement.isRedirectingFactory; | 4029 bool isRedirected = functionElement.isRedirectingFactory; |
| 4030 InterfaceType type = elements.getType(node); | 4030 InterfaceType type = elements.getType(node); |
| 4031 InterfaceType expectedType = functionElement.computeTargetType(type); | 4031 InterfaceType expectedType = functionElement.computeTargetType(type); |
| 4032 | 4032 |
| 4033 if (checkTypeVariableBounds(node, type)) return; | 4033 if (checkTypeVariableBounds(node, type)) return; |
| 4034 | 4034 |
| 4035 var inputs = <HInstruction>[]; | 4035 var inputs = <HInstruction>[]; |
| 4036 if (constructor.isGenerativeConstructor() && | 4036 if (constructor.isGenerativeConstructor && |
| 4037 Elements.isNativeOrExtendsNative(constructor.getEnclosingClass())) { | 4037 Elements.isNativeOrExtendsNative(constructor.enclosingClass)) { |
| 4038 // Native class generative constructors take a pre-constructed object. | 4038 // Native class generative constructors take a pre-constructed object. |
| 4039 inputs.add(graph.addConstantNull(compiler)); | 4039 inputs.add(graph.addConstantNull(compiler)); |
| 4040 } | 4040 } |
| 4041 // TODO(5347): Try to avoid the need for calling [implementation] before | 4041 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4042 // calling [addStaticSendArgumentsToList]. | 4042 // calling [addStaticSendArgumentsToList]. |
| 4043 bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, | 4043 bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, |
| 4044 constructor.implementation, | 4044 constructor.implementation, |
| 4045 inputs); | 4045 inputs); |
| 4046 if (!succeeded) { | 4046 if (!succeeded) { |
| 4047 generateWrongArgumentCountError(send, constructor, send.arguments); | 4047 generateWrongArgumentCountError(send, constructor, send.arguments); |
| 4048 return; | 4048 return; |
| 4049 } | 4049 } |
| 4050 | 4050 |
| 4051 if (constructor.isFactoryConstructor() && | 4051 if (constructor.isFactoryConstructor && |
| 4052 !expectedType.typeArguments.isEmpty) { | 4052 !expectedType.typeArguments.isEmpty) { |
| 4053 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); | 4053 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); |
| 4054 } | 4054 } |
| 4055 | 4055 |
| 4056 TypeMask elementType = computeType(constructor); | 4056 TypeMask elementType = computeType(constructor); |
| 4057 if (isFixedListConstructorCall) { | 4057 if (isFixedListConstructorCall) { |
| 4058 if (!inputs[0].isNumber(compiler)) { | 4058 if (!inputs[0].isNumber(compiler)) { |
| 4059 HTypeConversion conversion = new HTypeConversion( | 4059 HTypeConversion conversion = new HTypeConversion( |
| 4060 null, HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, | 4060 null, HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, |
| 4061 inputs[0], null); | 4061 inputs[0], null); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4081 js.Template code = js.js.parseForeignJS(r'#.fixed$length = init'); | 4081 js.Template code = js.js.parseForeignJS(r'#.fixed$length = init'); |
| 4082 // We set the instruction as [canThrow] to avoid it being dead code. | 4082 // We set the instruction as [canThrow] to avoid it being dead code. |
| 4083 // We need a finer grained side effect. | 4083 // We need a finer grained side effect. |
| 4084 add(new HForeign( | 4084 add(new HForeign( |
| 4085 code, backend.nullType, [stack.last], canThrow: true)); | 4085 code, backend.nullType, [stack.last], canThrow: true)); |
| 4086 } | 4086 } |
| 4087 } else if (isGrowableListConstructorCall) { | 4087 } else if (isGrowableListConstructorCall) { |
| 4088 push(buildLiteralList(<HInstruction>[])); | 4088 push(buildLiteralList(<HInstruction>[])); |
| 4089 stack.last.instructionType = elementType; | 4089 stack.last.instructionType = elementType; |
| 4090 } else { | 4090 } else { |
| 4091 ClassElement cls = constructor.getEnclosingClass(); | 4091 ClassElement cls = constructor.enclosingClass; |
| 4092 if (cls.isAbstract && constructor.isGenerativeConstructor()) { | 4092 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
| 4093 generateAbstractClassInstantiationError(send, cls.name); | 4093 generateAbstractClassInstantiationError(send, cls.name); |
| 4094 return; | 4094 return; |
| 4095 } | 4095 } |
| 4096 if (backend.classNeedsRti(cls)) { | 4096 if (backend.classNeedsRti(cls)) { |
| 4097 Link<DartType> typeVariable = cls.typeVariables; | 4097 Link<DartType> typeVariable = cls.typeVariables; |
| 4098 expectedType.typeArguments.forEach((DartType argument) { | 4098 expectedType.typeArguments.forEach((DartType argument) { |
| 4099 inputs.add(analyzeTypeArgument(argument)); | 4099 inputs.add(analyzeTypeArgument(argument)); |
| 4100 typeVariable = typeVariable.tail; | 4100 typeVariable = typeVariable.tail; |
| 4101 }); | 4101 }); |
| 4102 assert(typeVariable.isEmpty); | 4102 assert(typeVariable.isEmpty); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4196 if (!compiler.enableUserAssertions) { | 4196 if (!compiler.enableUserAssertions) { |
| 4197 stack.add(graph.addConstantNull(compiler)); | 4197 stack.add(graph.addConstantNull(compiler)); |
| 4198 return; | 4198 return; |
| 4199 } | 4199 } |
| 4200 visitStaticSend(node); | 4200 visitStaticSend(node); |
| 4201 } | 4201 } |
| 4202 | 4202 |
| 4203 visitStaticSend(ast.Send node) { | 4203 visitStaticSend(ast.Send node) { |
| 4204 Selector selector = elements.getSelector(node); | 4204 Selector selector = elements.getSelector(node); |
| 4205 Element element = elements[node]; | 4205 Element element = elements[node]; |
| 4206 if (element.isForeign(compiler) && element.isFunction()) { | 4206 if (element.isForeign(compiler) && element.isFunction) { |
| 4207 visitForeignSend(node); | 4207 visitForeignSend(node); |
| 4208 return; | 4208 return; |
| 4209 } | 4209 } |
| 4210 if (element.isErroneous()) { | 4210 if (element.isErroneous) { |
| 4211 // An erroneous element indicates that the funciton could not be resolved | 4211 // An erroneous element indicates that the funciton could not be resolved |
| 4212 // (a warning has been issued). | 4212 // (a warning has been issued). |
| 4213 generateThrowNoSuchMethod(node, | 4213 generateThrowNoSuchMethod(node, |
| 4214 getTargetName(element), | 4214 getTargetName(element), |
| 4215 argumentNodes: node.arguments); | 4215 argumentNodes: node.arguments); |
| 4216 return; | 4216 return; |
| 4217 } | 4217 } |
| 4218 invariant(element, !element.isGenerativeConstructor()); | 4218 invariant(element, !element.isGenerativeConstructor); |
| 4219 generateIsDeferredLoadedCheckIfNeeded(node); | 4219 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4220 if (element.isFunction()) { | 4220 if (element.isFunction) { |
| 4221 var inputs = <HInstruction>[]; | 4221 var inputs = <HInstruction>[]; |
| 4222 // TODO(5347): Try to avoid the need for calling [implementation] before | 4222 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4223 // calling [addStaticSendArgumentsToList]. | 4223 // calling [addStaticSendArgumentsToList]. |
| 4224 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 4224 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 4225 element.implementation, | 4225 element.implementation, |
| 4226 inputs); | 4226 inputs); |
| 4227 if (!succeeded) { | 4227 if (!succeeded) { |
| 4228 generateWrongArgumentCountError(node, element, node.arguments); | 4228 generateWrongArgumentCountError(node, element, node.arguments); |
| 4229 return; | 4229 return; |
| 4230 } | 4230 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4248 } | 4248 } |
| 4249 | 4249 |
| 4250 HConstant addConstantString(String string) { | 4250 HConstant addConstantString(String string) { |
| 4251 ast.DartString dartString = new ast.DartString.literal(string); | 4251 ast.DartString dartString = new ast.DartString.literal(string); |
| 4252 Constant constant = constantSystem.createString(dartString); | 4252 Constant constant = constantSystem.createString(dartString); |
| 4253 return graph.addConstant(constant, compiler); | 4253 return graph.addConstant(constant, compiler); |
| 4254 } | 4254 } |
| 4255 | 4255 |
| 4256 visitTypeReferenceSend(ast.Send node) { | 4256 visitTypeReferenceSend(ast.Send node) { |
| 4257 Element element = elements[node]; | 4257 Element element = elements[node]; |
| 4258 if (element.isClass() || element.isTypedef()) { | 4258 if (element.isClass || element.isTypedef) { |
| 4259 // TODO(karlklose): add type representation | 4259 // TODO(karlklose): add type representation |
| 4260 if (node.isCall) { | 4260 if (node.isCall) { |
| 4261 // The node itself is not a constant but we register the selector (the | 4261 // The node itself is not a constant but we register the selector (the |
| 4262 // identifier that refers to the class/typedef) as a constant. | 4262 // identifier that refers to the class/typedef) as a constant. |
| 4263 stack.add(addConstant(node.selector)); | 4263 stack.add(addConstant(node.selector)); |
| 4264 } else { | 4264 } else { |
| 4265 stack.add(addConstant(node)); | 4265 stack.add(addConstant(node)); |
| 4266 } | 4266 } |
| 4267 } else if (element.isTypeVariable()) { | 4267 } else if (element.isTypeVariable) { |
| 4268 TypeVariableElement typeVariable = element; | 4268 TypeVariableElement typeVariable = element; |
| 4269 HInstruction value = addTypeVariableReference(typeVariable.type); | 4269 HInstruction value = addTypeVariableReference(typeVariable.type); |
| 4270 pushInvokeStatic(node, | 4270 pushInvokeStatic(node, |
| 4271 backend.getRuntimeTypeToString(), | 4271 backend.getRuntimeTypeToString(), |
| 4272 [value], | 4272 [value], |
| 4273 backend.stringType); | 4273 backend.stringType); |
| 4274 pushInvokeStatic(node, | 4274 pushInvokeStatic(node, |
| 4275 backend.getCreateRuntimeType(), | 4275 backend.getCreateRuntimeType(), |
| 4276 [pop()]); | 4276 [pop()]); |
| 4277 } else { | 4277 } else { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4389 if (Elements.isErroneousElement(element)) { | 4389 if (Elements.isErroneousElement(element)) { |
| 4390 ErroneousElement error = element; | 4390 ErroneousElement error = element; |
| 4391 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { | 4391 if (error.messageKind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { |
| 4392 generateThrowNoSuchMethod(node.send, | 4392 generateThrowNoSuchMethod(node.send, |
| 4393 getTargetName(error, 'constructor'), | 4393 getTargetName(error, 'constructor'), |
| 4394 argumentNodes: node.send.arguments); | 4394 argumentNodes: node.send.arguments); |
| 4395 } else { | 4395 } else { |
| 4396 Message message = error.messageKind.message(error.messageArguments); | 4396 Message message = error.messageKind.message(error.messageArguments); |
| 4397 generateRuntimeError(node.send, message.toString()); | 4397 generateRuntimeError(node.send, message.toString()); |
| 4398 } | 4398 } |
| 4399 } else if (node.isConst()) { | 4399 } else if (node.isConst) { |
| 4400 stack.add(addConstant(node)); | 4400 stack.add(addConstant(node)); |
| 4401 if (isSymbolConstructor) { | 4401 if (isSymbolConstructor) { |
| 4402 ConstructedConstant symbol = getConstantForNode(node); | 4402 ConstructedConstant symbol = getConstantForNode(node); |
| 4403 StringConstant stringConstant = symbol.fields.single; | 4403 StringConstant stringConstant = symbol.fields.single; |
| 4404 String nameString = stringConstant.toDartString().slowToString(); | 4404 String nameString = stringConstant.toDartString().slowToString(); |
| 4405 compiler.enqueuer.codegen.registerConstSymbol(nameString, elements); | 4405 compiler.enqueuer.codegen.registerConstSymbol(nameString, elements); |
| 4406 } | 4406 } |
| 4407 } else { | 4407 } else { |
| 4408 handleNewSend(node); | 4408 handleNewSend(node); |
| 4409 } | 4409 } |
| 4410 } | 4410 } |
| 4411 | 4411 |
| 4412 void pushInvokeDynamic(ast.Node node, | 4412 void pushInvokeDynamic(ast.Node node, |
| 4413 Selector selector, | 4413 Selector selector, |
| 4414 List<HInstruction> arguments, | 4414 List<HInstruction> arguments, |
| 4415 {ast.Node location}) { | 4415 {ast.Node location}) { |
| 4416 if (location == null) location = node; | 4416 if (location == null) location = node; |
| 4417 | 4417 |
| 4418 // We prefer to not inline certain operations on indexables, | 4418 // We prefer to not inline certain operations on indexables, |
| 4419 // because the constant folder will handle them better and turn | 4419 // because the constant folder will handle them better and turn |
| 4420 // them into simpler instructions that allow further | 4420 // them into simpler instructions that allow further |
| 4421 // optimizations. | 4421 // optimizations. |
| 4422 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { | 4422 bool isOptimizableOperationOnIndexable(Selector selector, Element element) { |
| 4423 bool isLength = selector.isGetter() | 4423 bool isLength = selector.isGetter |
| 4424 && selector.name == "length"; | 4424 && selector.name == "length"; |
| 4425 if (isLength || selector.isIndex()) { | 4425 if (isLength || selector.isIndex) { |
| 4426 TypeMask type = new TypeMask.nonNullExact( | 4426 TypeMask type = new TypeMask.nonNullExact( |
| 4427 element.getEnclosingClass().declaration); | 4427 element.enclosingClass.declaration); |
| 4428 return type.satisfies(backend.jsIndexableClass, compiler); | 4428 return type.satisfies(backend.jsIndexableClass, compiler); |
| 4429 } else if (selector.isIndexSet()) { | 4429 } else if (selector.isIndexSet) { |
| 4430 TypeMask type = new TypeMask.nonNullExact( | 4430 TypeMask type = new TypeMask.nonNullExact( |
| 4431 element.getEnclosingClass().declaration); | 4431 element.enclosingClass.declaration); |
| 4432 return type.satisfies(backend.jsMutableIndexableClass, compiler); | 4432 return type.satisfies(backend.jsMutableIndexableClass, compiler); |
| 4433 } else { | 4433 } else { |
| 4434 return false; | 4434 return false; |
| 4435 } | 4435 } |
| 4436 } | 4436 } |
| 4437 | 4437 |
| 4438 bool isOptimizableOperation(Selector selector, Element element) { | 4438 bool isOptimizableOperation(Selector selector, Element element) { |
| 4439 ClassElement cls = element.getEnclosingClass(); | 4439 ClassElement cls = element.enclosingClass; |
| 4440 if (isOptimizableOperationOnIndexable(selector, element)) return true; | 4440 if (isOptimizableOperationOnIndexable(selector, element)) return true; |
| 4441 if (!backend.interceptedClasses.contains(cls)) return false; | 4441 if (!backend.interceptedClasses.contains(cls)) return false; |
| 4442 if (selector.isOperator()) return true; | 4442 if (selector.isOperator) return true; |
| 4443 if (selector.isSetter()) return true; | 4443 if (selector.isSetter) return true; |
| 4444 if (selector.isIndex()) return true; | 4444 if (selector.isIndex) return true; |
| 4445 if (selector.isIndexSet()) return true; | 4445 if (selector.isIndexSet) return true; |
| 4446 if (element == backend.jsArrayAdd | 4446 if (element == backend.jsArrayAdd |
| 4447 || element == backend.jsArrayRemoveLast | 4447 || element == backend.jsArrayRemoveLast |
| 4448 || element == backend.jsStringSplit) { | 4448 || element == backend.jsStringSplit) { |
| 4449 return true; | 4449 return true; |
| 4450 } | 4450 } |
| 4451 return false; | 4451 return false; |
| 4452 } | 4452 } |
| 4453 | 4453 |
| 4454 Element element = compiler.world.locateSingleElement(selector); | 4454 Element element = compiler.world.locateSingleElement(selector); |
| 4455 if (element != null | 4455 if (element != null |
| 4456 && !element.isField() | 4456 && !element.isField |
| 4457 && !(element.isGetter() && selector.isCall()) | 4457 && !(element.isGetter && selector.isCall) |
| 4458 && !(element.isFunction() && selector.isGetter()) | 4458 && !(element.isFunction && selector.isGetter) |
| 4459 && !isOptimizableOperation(selector, element)) { | 4459 && !isOptimizableOperation(selector, element)) { |
| 4460 if (tryInlineMethod(element, selector, arguments, node)) { | 4460 if (tryInlineMethod(element, selector, arguments, node)) { |
| 4461 return; | 4461 return; |
| 4462 } | 4462 } |
| 4463 } | 4463 } |
| 4464 | 4464 |
| 4465 HInstruction receiver = arguments[0]; | 4465 HInstruction receiver = arguments[0]; |
| 4466 List<HInstruction> inputs = <HInstruction>[]; | 4466 List<HInstruction> inputs = <HInstruction>[]; |
| 4467 bool isIntercepted = backend.isInterceptedSelector(selector); | 4467 bool isIntercepted = backend.isInterceptedSelector(selector); |
| 4468 if (isIntercepted) { | 4468 if (isIntercepted) { |
| 4469 inputs.add(invokeInterceptor(receiver)); | 4469 inputs.add(invokeInterceptor(receiver)); |
| 4470 } | 4470 } |
| 4471 inputs.addAll(arguments); | 4471 inputs.addAll(arguments); |
| 4472 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); | 4472 TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler); |
| 4473 if (selector.isGetter()) { | 4473 if (selector.isGetter) { |
| 4474 pushWithPosition( | 4474 pushWithPosition( |
| 4475 new HInvokeDynamicGetter(selector, null, inputs, type), | 4475 new HInvokeDynamicGetter(selector, null, inputs, type), |
| 4476 location); | 4476 location); |
| 4477 } else if (selector.isSetter()) { | 4477 } else if (selector.isSetter) { |
| 4478 pushWithPosition( | 4478 pushWithPosition( |
| 4479 new HInvokeDynamicSetter(selector, null, inputs, type), | 4479 new HInvokeDynamicSetter(selector, null, inputs, type), |
| 4480 location); | 4480 location); |
| 4481 } else { | 4481 } else { |
| 4482 pushWithPosition( | 4482 pushWithPosition( |
| 4483 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), | 4483 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), |
| 4484 location); | 4484 location); |
| 4485 } | 4485 } |
| 4486 } | 4486 } |
| 4487 | 4487 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4522 List<HInstruction> inputs = <HInstruction>[]; | 4522 List<HInstruction> inputs = <HInstruction>[]; |
| 4523 if (backend.isInterceptedSelector(selector) && | 4523 if (backend.isInterceptedSelector(selector) && |
| 4524 // Fields don't need an interceptor; consider generating HFieldGet/Set | 4524 // Fields don't need an interceptor; consider generating HFieldGet/Set |
| 4525 // instead. | 4525 // instead. |
| 4526 element.kind != ElementKind.FIELD) { | 4526 element.kind != ElementKind.FIELD) { |
| 4527 inputs.add(invokeInterceptor(receiver)); | 4527 inputs.add(invokeInterceptor(receiver)); |
| 4528 } | 4528 } |
| 4529 inputs.add(receiver); | 4529 inputs.add(receiver); |
| 4530 inputs.addAll(arguments); | 4530 inputs.addAll(arguments); |
| 4531 TypeMask type; | 4531 TypeMask type; |
| 4532 if (!element.isGetter() && selector.isGetter()) { | 4532 if (!element.isGetter && selector.isGetter) { |
| 4533 type = TypeMaskFactory.inferredTypeForElement(element, compiler); | 4533 type = TypeMaskFactory.inferredTypeForElement(element, compiler); |
| 4534 } else { | 4534 } else { |
| 4535 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 4535 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); |
| 4536 } | 4536 } |
| 4537 HInstruction instruction = new HInvokeSuper( | 4537 HInstruction instruction = new HInvokeSuper( |
| 4538 element, | 4538 element, |
| 4539 currentNonClosureClass, | 4539 currentNonClosureClass, |
| 4540 selector, | 4540 selector, |
| 4541 inputs, | 4541 inputs, |
| 4542 type, | 4542 type, |
| 4543 isSetter: selector.isSetter() || selector.isIndexSet()); | 4543 isSetter: selector.isSetter || selector.isIndexSet); |
| 4544 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); | 4544 instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector); |
| 4545 return instruction; | 4545 return instruction; |
| 4546 } | 4546 } |
| 4547 | 4547 |
| 4548 void handleComplexOperatorSend(ast.SendSet node, | 4548 void handleComplexOperatorSend(ast.SendSet node, |
| 4549 HInstruction receiver, | 4549 HInstruction receiver, |
| 4550 Link<ast.Node> arguments) { | 4550 Link<ast.Node> arguments) { |
| 4551 HInstruction rhs; | 4551 HInstruction rhs; |
| 4552 if (node.isPrefix || node.isPostfix) { | 4552 if (node.isPrefix || node.isPostfix) { |
| 4553 rhs = graph.addConstantInt(1, compiler); | 4553 rhs = graph.addConstantInt(1, compiler); |
| 4554 } else { | 4554 } else { |
| 4555 visit(arguments.head); | 4555 visit(arguments.head); |
| 4556 assert(arguments.tail.isEmpty); | 4556 assert(arguments.tail.isEmpty); |
| 4557 rhs = pop(); | 4557 rhs = pop(); |
| 4558 } | 4558 } |
| 4559 visitBinary(receiver, node.assignmentOperator, rhs, | 4559 visitBinary(receiver, node.assignmentOperator, rhs, |
| 4560 elements.getOperatorSelectorInComplexSendSet(node), node); | 4560 elements.getOperatorSelectorInComplexSendSet(node), node); |
| 4561 } | 4561 } |
| 4562 | 4562 |
| 4563 visitSendSet(ast.SendSet node) { | 4563 visitSendSet(ast.SendSet node) { |
| 4564 generateIsDeferredLoadedCheckIfNeeded(node); | 4564 generateIsDeferredLoadedCheckIfNeeded(node); |
| 4565 Element element = elements[node]; | 4565 Element element = elements[node]; |
| 4566 if (!Elements.isUnresolved(element) && element.impliesType()) { | 4566 if (!Elements.isUnresolved(element) && element.impliesType) { |
| 4567 ast.Identifier selector = node.selector; | 4567 ast.Identifier selector = node.selector; |
| 4568 generateThrowNoSuchMethod(node, selector.source, | 4568 generateThrowNoSuchMethod(node, selector.source, |
| 4569 argumentNodes: node.arguments); | 4569 argumentNodes: node.arguments); |
| 4570 return; | 4570 return; |
| 4571 } | 4571 } |
| 4572 ast.Operator op = node.assignmentOperator; | 4572 ast.Operator op = node.assignmentOperator; |
| 4573 if (node.isSuperCall) { | 4573 if (node.isSuperCall) { |
| 4574 HInstruction result; | 4574 HInstruction result; |
| 4575 List<HInstruction> setterInputs = <HInstruction>[]; | 4575 List<HInstruction> setterInputs = <HInstruction>[]; |
| 4576 if (identical(node.assignmentOperator.source, '=')) { | 4576 if (identical(node.assignmentOperator.source, '=')) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4671 } else if (identical(op.source, "is")) { | 4671 } else if (identical(op.source, "is")) { |
| 4672 compiler.internalError(op, "is-operator as SendSet."); | 4672 compiler.internalError(op, "is-operator as SendSet."); |
| 4673 } else { | 4673 } else { |
| 4674 assert("++" == op.source || "--" == op.source || | 4674 assert("++" == op.source || "--" == op.source || |
| 4675 node.assignmentOperator.source.endsWith("=")); | 4675 node.assignmentOperator.source.endsWith("=")); |
| 4676 | 4676 |
| 4677 // [receiver] is only used if the node is an instance send. | 4677 // [receiver] is only used if the node is an instance send. |
| 4678 HInstruction receiver = null; | 4678 HInstruction receiver = null; |
| 4679 Element getter = elements[node.selector]; | 4679 Element getter = elements[node.selector]; |
| 4680 | 4680 |
| 4681 if (!Elements.isUnresolved(getter) && getter.impliesType()) { | 4681 if (!Elements.isUnresolved(getter) && getter.impliesType) { |
| 4682 ast.Identifier selector = node.selector; | 4682 ast.Identifier selector = node.selector; |
| 4683 generateThrowNoSuchMethod(node, selector.source, | 4683 generateThrowNoSuchMethod(node, selector.source, |
| 4684 argumentNodes: node.arguments); | 4684 argumentNodes: node.arguments); |
| 4685 return; | 4685 return; |
| 4686 } else if (Elements.isInstanceSend(node, elements)) { | 4686 } else if (Elements.isInstanceSend(node, elements)) { |
| 4687 receiver = generateInstanceSendReceiver(node); | 4687 receiver = generateInstanceSendReceiver(node); |
| 4688 generateInstanceGetterWithCompiledReceiver( | 4688 generateInstanceGetterWithCompiledReceiver( |
| 4689 node, elements.getGetterSelectorInComplexSendSet(node), receiver); | 4689 node, elements.getGetterSelectorInComplexSendSet(node), receiver); |
| 4690 } else { | 4690 } else { |
| 4691 generateGetter(node, getter); | 4691 generateGetter(node, getter); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4790 if (exception == null) { | 4790 if (exception == null) { |
| 4791 exception = graph.addConstantNull(compiler); | 4791 exception = graph.addConstantNull(compiler); |
| 4792 compiler.internalError(node, | 4792 compiler.internalError(node, |
| 4793 'rethrowableException should not be null.'); | 4793 'rethrowableException should not be null.'); |
| 4794 } | 4794 } |
| 4795 handleInTryStatement(); | 4795 handleInTryStatement(); |
| 4796 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 4796 closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
| 4797 } | 4797 } |
| 4798 | 4798 |
| 4799 visitReturn(ast.Return node) { | 4799 visitReturn(ast.Return node) { |
| 4800 if (identical(node.getBeginToken().stringValue, 'native')) { | 4800 if (identical(node.beginToken.stringValue, 'native')) { |
| 4801 native.handleSsaNative(this, node.expression); | 4801 native.handleSsaNative(this, node.expression); |
| 4802 return; | 4802 return; |
| 4803 } | 4803 } |
| 4804 HInstruction value; | 4804 HInstruction value; |
| 4805 if (node.isRedirectingFactoryBody) { | 4805 if (node.isRedirectingFactoryBody) { |
| 4806 FunctionElement targetConstructor = | 4806 FunctionElement targetConstructor = |
| 4807 elements[node.expression].implementation; | 4807 elements[node.expression].implementation; |
| 4808 FunctionElement redirectingConstructor = sourceElement; | 4808 FunctionElement redirectingConstructor = sourceElement; |
| 4809 List<HInstruction> inputs = <HInstruction>[]; | 4809 List<HInstruction> inputs = <HInstruction>[]; |
| 4810 FunctionSignature targetSignature = targetConstructor.functionSignature; | 4810 FunctionSignature targetSignature = targetConstructor.functionSignature; |
| 4811 FunctionSignature redirectingSignature = | 4811 FunctionSignature redirectingSignature = |
| 4812 redirectingConstructor.functionSignature; | 4812 redirectingConstructor.functionSignature; |
| 4813 redirectingSignature.forEachRequiredParameter((Element element) { | 4813 redirectingSignature.forEachRequiredParameter((Element element) { |
| 4814 inputs.add(localsHandler.readLocal(element)); | 4814 inputs.add(localsHandler.readLocal(element)); |
| 4815 }); | 4815 }); |
| 4816 List<Element> targetOptionals = | 4816 List<Element> targetOptionals = |
| 4817 targetSignature.orderedOptionalParameters; | 4817 targetSignature.orderedOptionalParameters; |
| 4818 List<Element> redirectingOptionals = | 4818 List<Element> redirectingOptionals = |
| 4819 redirectingSignature.orderedOptionalParameters; | 4819 redirectingSignature.orderedOptionalParameters; |
| 4820 int i = 0; | 4820 int i = 0; |
| 4821 for (; i < redirectingOptionals.length; i++) { | 4821 for (; i < redirectingOptionals.length; i++) { |
| 4822 inputs.add(localsHandler.readLocal(redirectingOptionals[i])); | 4822 inputs.add(localsHandler.readLocal(redirectingOptionals[i])); |
| 4823 } | 4823 } |
| 4824 for (; i < targetOptionals.length; i++) { | 4824 for (; i < targetOptionals.length; i++) { |
| 4825 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); | 4825 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); |
| 4826 } | 4826 } |
| 4827 | 4827 |
| 4828 ClassElement targetClass = targetConstructor.getEnclosingClass(); | 4828 ClassElement targetClass = targetConstructor.enclosingClass; |
| 4829 if (backend.classNeedsRti(targetClass)) { | 4829 if (backend.classNeedsRti(targetClass)) { |
| 4830 ClassElement cls = redirectingConstructor.getEnclosingClass(); | 4830 ClassElement cls = redirectingConstructor.enclosingClass; |
| 4831 InterfaceType targetType = | 4831 InterfaceType targetType = |
| 4832 redirectingConstructor.computeTargetType(cls.thisType); | 4832 redirectingConstructor.computeTargetType(cls.thisType); |
| 4833 targetType.typeArguments.forEach((DartType argument) { | 4833 targetType.typeArguments.forEach((DartType argument) { |
| 4834 inputs.add(analyzeTypeArgument(argument)); | 4834 inputs.add(analyzeTypeArgument(argument)); |
| 4835 }); | 4835 }); |
| 4836 } | 4836 } |
| 4837 pushInvokeStatic(node, targetConstructor, inputs); | 4837 pushInvokeStatic(node, targetConstructor, inputs); |
| 4838 value = pop(); | 4838 value = pop(); |
| 4839 } else if (node.expression == null) { | 4839 } else if (node.expression == null) { |
| 4840 value = graph.addConstantNull(compiler); | 4840 value = graph.addConstantNull(compiler); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4889 arguments.add(analyzeTypeArgument(argument)); | 4889 arguments.add(analyzeTypeArgument(argument)); |
| 4890 } | 4890 } |
| 4891 // TODO(15489): Register at codegen. | 4891 // TODO(15489): Register at codegen. |
| 4892 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); | 4892 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); |
| 4893 return callSetRuntimeTypeInfo(type.element, arguments, object); | 4893 return callSetRuntimeTypeInfo(type.element, arguments, object); |
| 4894 } | 4894 } |
| 4895 | 4895 |
| 4896 visitLiteralList(ast.LiteralList node) { | 4896 visitLiteralList(ast.LiteralList node) { |
| 4897 HInstruction instruction; | 4897 HInstruction instruction; |
| 4898 | 4898 |
| 4899 if (node.isConst()) { | 4899 if (node.isConst) { |
| 4900 instruction = addConstant(node); | 4900 instruction = addConstant(node); |
| 4901 } else { | 4901 } else { |
| 4902 List<HInstruction> inputs = <HInstruction>[]; | 4902 List<HInstruction> inputs = <HInstruction>[]; |
| 4903 for (Link<ast.Node> link = node.elements.nodes; | 4903 for (Link<ast.Node> link = node.elements.nodes; |
| 4904 !link.isEmpty; | 4904 !link.isEmpty; |
| 4905 link = link.tail) { | 4905 link = link.tail) { |
| 4906 visit(link.head); | 4906 visit(link.head); |
| 4907 inputs.add(pop()); | 4907 inputs.add(pop()); |
| 4908 } | 4908 } |
| 4909 instruction = buildLiteralList(inputs); | 4909 instruction = buildLiteralList(inputs); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5088 // There was at least one reachable break, so the label is needed. | 5088 // There was at least one reachable break, so the label is needed. |
| 5089 entryBlock.setBlockFlow( | 5089 entryBlock.setBlockFlow( |
| 5090 new HLabeledBlockInformation(new HSubGraphBlockInformation(bodyGraph), | 5090 new HLabeledBlockInformation(new HSubGraphBlockInformation(bodyGraph), |
| 5091 handler.labels()), | 5091 handler.labels()), |
| 5092 joinBlock); | 5092 joinBlock); |
| 5093 } | 5093 } |
| 5094 handler.close(); | 5094 handler.close(); |
| 5095 } | 5095 } |
| 5096 | 5096 |
| 5097 visitLiteralMap(ast.LiteralMap node) { | 5097 visitLiteralMap(ast.LiteralMap node) { |
| 5098 if (node.isConst()) { | 5098 if (node.isConst) { |
| 5099 stack.add(addConstant(node)); | 5099 stack.add(addConstant(node)); |
| 5100 return; | 5100 return; |
| 5101 } | 5101 } |
| 5102 List<HInstruction> listInputs = <HInstruction>[]; | 5102 List<HInstruction> listInputs = <HInstruction>[]; |
| 5103 for (Link<ast.Node> link = node.entries.nodes; | 5103 for (Link<ast.Node> link = node.entries.nodes; |
| 5104 !link.isEmpty; | 5104 !link.isEmpty; |
| 5105 link = link.tail) { | 5105 link = link.tail) { |
| 5106 visit(link.head); | 5106 visit(link.head); |
| 5107 listInputs.add(pop()); | 5107 listInputs.add(pop()); |
| 5108 listInputs.add(pop()); | 5108 listInputs.add(pop()); |
| 5109 } | 5109 } |
| 5110 | 5110 |
| 5111 Element constructor; | 5111 Element constructor; |
| 5112 List<HInstruction> inputs = <HInstruction>[]; | 5112 List<HInstruction> inputs = <HInstruction>[]; |
| 5113 | 5113 |
| 5114 if (listInputs.isEmpty) { | 5114 if (listInputs.isEmpty) { |
| 5115 constructor = backend.mapLiteralConstructorEmpty; | 5115 constructor = backend.mapLiteralConstructorEmpty; |
| 5116 } else { | 5116 } else { |
| 5117 constructor = backend.mapLiteralConstructor; | 5117 constructor = backend.mapLiteralConstructor; |
| 5118 HLiteralList keyValuePairs = buildLiteralList(listInputs); | 5118 HLiteralList keyValuePairs = buildLiteralList(listInputs); |
| 5119 add(keyValuePairs); | 5119 add(keyValuePairs); |
| 5120 inputs.add(keyValuePairs); | 5120 inputs.add(keyValuePairs); |
| 5121 } | 5121 } |
| 5122 | 5122 |
| 5123 assert(constructor.isFactoryConstructor()); | 5123 assert(constructor.isFactoryConstructor); |
| 5124 | 5124 |
| 5125 FunctionElement functionElement = constructor; | 5125 FunctionElement functionElement = constructor; |
| 5126 constructor = functionElement.redirectionTarget; | 5126 constructor = functionElement.redirectionTarget; |
| 5127 | 5127 |
| 5128 InterfaceType type = elements.getType(node); | 5128 InterfaceType type = elements.getType(node); |
| 5129 InterfaceType expectedType = functionElement.computeTargetType(type); | 5129 InterfaceType expectedType = functionElement.computeTargetType(type); |
| 5130 | 5130 |
| 5131 if (constructor.isFactoryConstructor()) { | 5131 if (constructor.isFactoryConstructor) { |
| 5132 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); | 5132 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); |
| 5133 } | 5133 } |
| 5134 | 5134 |
| 5135 ClassElement cls = constructor.getEnclosingClass(); | 5135 ClassElement cls = constructor.enclosingClass; |
| 5136 | 5136 |
| 5137 if (backend.classNeedsRti(cls)) { | 5137 if (backend.classNeedsRti(cls)) { |
| 5138 Link<DartType> typeVariable = cls.typeVariables; | 5138 Link<DartType> typeVariable = cls.typeVariables; |
| 5139 expectedType.typeArguments.forEach((DartType argument) { | 5139 expectedType.typeArguments.forEach((DartType argument) { |
| 5140 inputs.add(analyzeTypeArgument(argument)); | 5140 inputs.add(analyzeTypeArgument(argument)); |
| 5141 typeVariable = typeVariable.tail; | 5141 typeVariable = typeVariable.tail; |
| 5142 }); | 5142 }); |
| 5143 assert(typeVariable.isEmpty); | 5143 assert(typeVariable.isEmpty); |
| 5144 } | 5144 } |
| 5145 | 5145 |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5937 } | 5937 } |
| 5938 | 5938 |
| 5939 void visitRethrow(ast.Rethrow node) { | 5939 void visitRethrow(ast.Rethrow node) { |
| 5940 if (!registerNode()) return; | 5940 if (!registerNode()) return; |
| 5941 tooDifficult = true; | 5941 tooDifficult = true; |
| 5942 } | 5942 } |
| 5943 | 5943 |
| 5944 void visitReturn(ast.Return node) { | 5944 void visitReturn(ast.Return node) { |
| 5945 if (!registerNode()) return; | 5945 if (!registerNode()) return; |
| 5946 if (seenReturn | 5946 if (seenReturn |
| 5947 || identical(node.getBeginToken().stringValue, 'native') | 5947 || identical(node.beginToken.stringValue, 'native') |
| 5948 || node.isRedirectingFactoryBody) { | 5948 || node.isRedirectingFactoryBody) { |
| 5949 tooDifficult = true; | 5949 tooDifficult = true; |
| 5950 return; | 5950 return; |
| 5951 } | 5951 } |
| 5952 node.visitChildren(this); | 5952 node.visitChildren(this); |
| 5953 seenReturn = true; | 5953 seenReturn = true; |
| 5954 } | 5954 } |
| 5955 | 5955 |
| 5956 void visitTryStatement(ast.Node node) { | 5956 void visitTryStatement(ast.Node node) { |
| 5957 if (!registerNode()) return; | 5957 if (!registerNode()) return; |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6240 | 6240 |
| 6241 void visitVoidType(VoidType type, SsaBuilder builder) { | 6241 void visitVoidType(VoidType type, SsaBuilder builder) { |
| 6242 ClassElement cls = builder.compiler.findHelper('VoidRuntimeType'); | 6242 ClassElement cls = builder.compiler.findHelper('VoidRuntimeType'); |
| 6243 builder.push(new HVoidType(type, new TypeMask.exact(cls))); | 6243 builder.push(new HVoidType(type, new TypeMask.exact(cls))); |
| 6244 } | 6244 } |
| 6245 | 6245 |
| 6246 void visitTypeVariableType(TypeVariableType type, | 6246 void visitTypeVariableType(TypeVariableType type, |
| 6247 SsaBuilder builder) { | 6247 SsaBuilder builder) { |
| 6248 ClassElement cls = builder.compiler.findHelper('RuntimeType'); | 6248 ClassElement cls = builder.compiler.findHelper('RuntimeType'); |
| 6249 TypeMask instructionType = new TypeMask.subclass(cls); | 6249 TypeMask instructionType = new TypeMask.subclass(cls); |
| 6250 if (!builder.sourceElement.enclosingElement.isClosure() && | 6250 if (!builder.sourceElement.enclosingElement.isClosure && |
| 6251 builder.sourceElement.isInstanceMember()) { | 6251 builder.sourceElement.isInstanceMember) { |
| 6252 HInstruction receiver = builder.localsHandler.readThis(); | 6252 HInstruction receiver = builder.localsHandler.readThis(); |
| 6253 builder.push(new HReadTypeVariable(type, receiver, instructionType)); | 6253 builder.push(new HReadTypeVariable(type, receiver, instructionType)); |
| 6254 } else { | 6254 } else { |
| 6255 builder.push( | 6255 builder.push( |
| 6256 new HReadTypeVariable.noReceiver( | 6256 new HReadTypeVariable.noReceiver( |
| 6257 type, builder.addTypeVariableReference(type), instructionType)); | 6257 type, builder.addTypeVariableReference(type), instructionType)); |
| 6258 } | 6258 } |
| 6259 } | 6259 } |
| 6260 | 6260 |
| 6261 void visitFunctionType(FunctionType type, SsaBuilder builder) { | 6261 void visitFunctionType(FunctionType type, SsaBuilder builder) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6318 DartType unaliased = type.unalias(builder.compiler); | 6318 DartType unaliased = type.unalias(builder.compiler); |
| 6319 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6319 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6320 unaliased.accept(this, builder); | 6320 unaliased.accept(this, builder); |
| 6321 } | 6321 } |
| 6322 | 6322 |
| 6323 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6323 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6324 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); | 6324 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6325 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6325 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6326 } | 6326 } |
| 6327 } | 6327 } |
| OLD | NEW |