001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.google.common.collect.Maps; 021 import com.intellij.openapi.progress.ProcessCanceledException; 022 import com.intellij.psi.PsiElement; 023 import com.intellij.psi.tree.IElementType; 024 import com.intellij.util.ArrayUtil; 025 import com.intellij.util.Function; 026 import com.intellij.util.containers.Stack; 027 import kotlin.ExtensionFunction0; 028 import kotlin.Function1; 029 import kotlin.KotlinPackage; 030 import kotlin.Unit; 031 import org.jetbrains.annotations.NotNull; 032 import org.jetbrains.annotations.Nullable; 033 import org.jetbrains.kotlin.backend.common.CodegenUtil; 034 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 035 import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; 036 import org.jetbrains.kotlin.codegen.context.*; 037 import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension; 038 import org.jetbrains.kotlin.codegen.inline.*; 039 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethod; 040 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; 041 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter; 042 import org.jetbrains.kotlin.codegen.state.GenerationState; 043 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 044 import org.jetbrains.kotlin.codegen.when.SwitchCodegen; 045 import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; 046 import org.jetbrains.kotlin.descriptors.*; 047 import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; 048 import org.jetbrains.kotlin.lexer.JetTokens; 049 import org.jetbrains.kotlin.load.java.JvmAbi; 050 import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; 051 import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor; 052 import org.jetbrains.kotlin.load.kotlin.PackageClassUtils; 053 import org.jetbrains.kotlin.name.Name; 054 import org.jetbrains.kotlin.psi.*; 055 import org.jetbrains.kotlin.renderer.DescriptorRenderer; 056 import org.jetbrains.kotlin.resolve.BindingContext; 057 import org.jetbrains.kotlin.resolve.BindingContextUtils; 058 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; 059 import org.jetbrains.kotlin.resolve.DescriptorUtils; 060 import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage; 061 import org.jetbrains.kotlin.resolve.calls.model.*; 062 import org.jetbrains.kotlin.resolve.calls.util.CallMaker; 063 import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject; 064 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 065 import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant; 066 import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage; 067 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage; 068 import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm; 069 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; 070 import org.jetbrains.kotlin.resolve.scopes.receivers.*; 071 import org.jetbrains.kotlin.types.Approximation; 072 import org.jetbrains.kotlin.types.JetType; 073 import org.jetbrains.kotlin.types.TypeProjection; 074 import org.jetbrains.kotlin.types.TypeUtils; 075 import org.jetbrains.kotlin.types.checker.JetTypeChecker; 076 import org.jetbrains.org.objectweb.asm.Label; 077 import org.jetbrains.org.objectweb.asm.MethodVisitor; 078 import org.jetbrains.org.objectweb.asm.Opcodes; 079 import org.jetbrains.org.objectweb.asm.Type; 080 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 081 import org.jetbrains.org.objectweb.asm.commons.Method; 082 083 import java.util.*; 084 085 import static org.jetbrains.kotlin.codegen.AsmUtil.*; 086 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; 087 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; 088 import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass; 089 import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory; 090 import static org.jetbrains.kotlin.resolve.BindingContext.*; 091 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull; 092 import static org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure; 093 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry; 094 import static org.jetbrains.kotlin.resolve.DescriptorUtils.isObject; 095 import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCall; 096 import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert; 097 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 098 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.OtherOrigin; 099 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.TraitImpl; 100 import static org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; 101 import static org.jetbrains.kotlin.serialization.deserialization.DeserializationPackage.findClassAcrossModuleDependencies; 102 import static org.jetbrains.org.objectweb.asm.Opcodes.ACC_PRIVATE; 103 104 public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup { 105 private static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges(); 106 107 private final GenerationState state; 108 final JetTypeMapper typeMapper; 109 private final BindingContext bindingContext; 110 111 public final InstructionAdapter v; 112 public final FrameMap myFrameMap; 113 private final MethodContext context; 114 private final Type returnType; 115 116 private final CodegenStatementVisitor statementVisitor = new CodegenStatementVisitor(this); 117 private final MemberCodegen<?> parentCodegen; 118 private final TailRecursionCodegen tailRecursionCodegen; 119 public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this); 120 121 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); 122 123 /* 124 * When we create a temporary variable to hold some value not to compute it many times 125 * we put it into this map to emit access to that variable instead of evaluating the whole expression 126 */ 127 public final Map<JetElement, StackValue> tempVariables = Maps.newHashMap(); 128 129 private int myLastLineNumber = -1; 130 private boolean shouldMarkLineNumbers = true; 131 132 public ExpressionCodegen( 133 @NotNull MethodVisitor mv, 134 @NotNull FrameMap frameMap, 135 @NotNull Type returnType, 136 @NotNull MethodContext context, 137 @NotNull GenerationState state, 138 @NotNull MemberCodegen<?> parentCodegen 139 ) { 140 this.state = state; 141 this.typeMapper = state.getTypeMapper(); 142 this.bindingContext = state.getBindingContext(); 143 this.v = new InstructionAdapter(mv); 144 this.myFrameMap = frameMap; 145 this.context = context; 146 this.returnType = returnType; 147 this.parentCodegen = parentCodegen; 148 this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state); 149 } 150 151 static class BlockStackElement { 152 } 153 154 static class LoopBlockStackElement extends BlockStackElement { 155 final Label continueLabel; 156 final Label breakLabel; 157 public final JetSimpleNameExpression targetLabel; 158 159 LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) { 160 this.breakLabel = breakLabel; 161 this.continueLabel = continueLabel; 162 this.targetLabel = targetLabel; 163 } 164 } 165 166 static class FinallyBlockStackElement extends BlockStackElement { 167 List<Label> gaps = new ArrayList<Label>(); 168 169 final JetTryExpression expression; 170 171 FinallyBlockStackElement(JetTryExpression expression) { 172 this.expression = expression; 173 } 174 175 private void addGapLabel(Label label){ 176 gaps.add(label); 177 } 178 } 179 180 @NotNull 181 public GenerationState getState() { 182 return state; 183 } 184 185 @NotNull 186 public BindingContext getBindingContext() { 187 return bindingContext; 188 } 189 190 @NotNull 191 public MemberCodegen<?> getParentCodegen() { 192 return parentCodegen; 193 } 194 195 @NotNull 196 public ObjectLiteralResult generateObjectLiteral(@NotNull JetObjectLiteralExpression literal) { 197 JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); 198 199 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration); 200 assert classDescriptor != null; 201 202 Type asmType = asmTypeForAnonymousClass(bindingContext, objectDeclaration); 203 ClassBuilder classBuilder = state.getFactory().newVisitor( 204 OtherOrigin(objectDeclaration, classDescriptor), 205 asmType, 206 literal.getContainingFile() 207 ); 208 209 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION); 210 211 MemberCodegen literalCodegen = new ImplementationBodyCodegen( 212 objectDeclaration, objectContext, classBuilder, state, getParentCodegen() 213 ); 214 literalCodegen.generate(); 215 216 addReifiedParametersFromSignature(literalCodegen, classDescriptor); 217 propagateChildReifiedTypeParametersUsages(literalCodegen.getReifiedTypeParametersUsages()); 218 219 return new ObjectLiteralResult( 220 literalCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters(), 221 classDescriptor 222 ); 223 } 224 225 private static void addReifiedParametersFromSignature(@NotNull MemberCodegen member, @NotNull ClassDescriptor descriptor) { 226 for (JetType type : descriptor.getTypeConstructor().getSupertypes()) { 227 for (TypeProjection supertypeArgument : type.getArguments()) { 228 TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(supertypeArgument.getType()); 229 if (parameterDescriptor != null && parameterDescriptor.isReified()) { 230 member.getReifiedTypeParametersUsages().addUsedReifiedParameter(parameterDescriptor.getName().asString()); 231 } 232 } 233 } 234 } 235 236 private static class ObjectLiteralResult { 237 private final boolean wereReifiedMarkers; 238 private final ClassDescriptor classDescriptor; 239 240 public ObjectLiteralResult(boolean wereReifiedMarkers, @NotNull ClassDescriptor classDescriptor) { 241 this.wereReifiedMarkers = wereReifiedMarkers; 242 this.classDescriptor = classDescriptor; 243 } 244 } 245 246 @NotNull 247 private StackValue castToRequiredTypeOfInterfaceIfNeeded( 248 StackValue inner, 249 @NotNull ClassDescriptor provided, 250 @NotNull ClassDescriptor required 251 ) { 252 if (!isInterface(provided) && isInterface(required)) { 253 return StackValue.coercion(inner, asmType(required.getDefaultType())); 254 } 255 256 return inner; 257 } 258 259 public StackValue genQualified(StackValue receiver, JetElement selector) { 260 return genQualified(receiver, selector, this); 261 } 262 263 private StackValue genQualified(StackValue receiver, JetElement selector, JetVisitor<StackValue, StackValue> visitor) { 264 if (tempVariables.containsKey(selector)) { 265 throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector"); 266 } 267 if (!(selector instanceof JetBlockExpression)) { 268 markStartLineNumber(selector); 269 } 270 try { 271 if (selector instanceof JetExpression) { 272 StackValue samValue = genSamInterfaceValue((JetExpression) selector, visitor); 273 if (samValue != null) { 274 return samValue; 275 } 276 } 277 278 StackValue stackValue = selector.accept(visitor, receiver); 279 280 Approximation.Info approximationInfo = null; 281 if (selector instanceof JetExpression) { 282 approximationInfo = bindingContext.get(BindingContext.EXPRESSION_RESULT_APPROXIMATION, (JetExpression) selector); 283 } 284 285 return genNotNullAssertions(state, stackValue, approximationInfo); 286 } 287 catch (ProcessCanceledException e) { 288 throw e; 289 } 290 catch (CompilationException e) { 291 throw e; 292 } 293 catch (Throwable error) { 294 String message = error.getMessage(); 295 throw new CompilationException(message != null ? message : "null", error, selector); 296 } 297 } 298 299 public StackValue gen(JetElement expr) { 300 StackValue tempVar = tempVariables.get(expr); 301 return tempVar != null ? tempVar : genQualified(StackValue.none(), expr); 302 } 303 304 public void gen(JetElement expr, Type type) { 305 StackValue value = Type.VOID_TYPE.equals(type) ? genStatement(expr) : gen(expr); 306 value.put(type, v); 307 } 308 309 public StackValue genLazy(JetElement expr, Type type) { 310 StackValue value = gen(expr); 311 return StackValue.coercion(value, type); 312 } 313 314 private StackValue genStatement(JetElement statement) { 315 return genQualified(StackValue.none(), statement, statementVisitor); 316 } 317 318 @Override 319 public StackValue visitClass(@NotNull JetClass klass, StackValue data) { 320 return visitClassOrObject(klass); 321 } 322 323 private StackValue visitClassOrObject(JetClassOrObject declaration) { 324 ClassDescriptor descriptor = bindingContext.get(CLASS, declaration); 325 assert descriptor != null; 326 327 Type asmType = asmTypeForAnonymousClass(bindingContext, declaration); 328 ClassBuilder classBuilder = state.getFactory().newVisitor(OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile()); 329 330 ClassContext objectContext = context.intoAnonymousClass(descriptor, this, OwnerKind.IMPLEMENTATION); 331 new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen()).generate(); 332 333 if (declaration instanceof JetClass && ((JetClass) declaration).isTrait()) { 334 Type traitImplType = state.getTypeMapper().mapTraitImpl(descriptor); 335 ClassBuilder traitImplBuilder = state.getFactory().newVisitor(TraitImpl(declaration, descriptor), traitImplType, declaration.getContainingFile()); 336 ClassContext traitImplContext = context.intoAnonymousClass(descriptor, this, OwnerKind.TRAIT_IMPL); 337 new TraitImplBodyCodegen(declaration, traitImplContext, traitImplBuilder, state, parentCodegen).generate(); 338 } 339 340 return StackValue.none(); 341 } 342 343 @Override 344 public StackValue visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, StackValue data) { 345 return visitClassOrObject(declaration); 346 } 347 348 @Override 349 public StackValue visitExpression(@NotNull JetExpression expression, StackValue receiver) { 350 throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented"); 351 } 352 353 @Override 354 public StackValue visitSuperExpression(@NotNull JetSuperExpression expression, StackValue data) { 355 return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true, true); 356 } 357 358 @NotNull 359 private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) { 360 PsiElement labelPsi = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); 361 ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, labelPsi); 362 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 363 // "super<descriptor>@labelTarget" 364 if (labelTarget != null) { 365 return labelTarget; 366 } 367 assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class"; 368 return getParentContextSubclassOf((ClassDescriptor) descriptor, context).getThisDescriptor(); 369 } 370 371 @NotNull 372 private Type asmType(@NotNull JetType type) { 373 return typeMapper.mapType(type); 374 } 375 376 @NotNull 377 public Type expressionType(JetExpression expression) { 378 JetType type = expressionJetType(expression); 379 return type == null ? Type.VOID_TYPE : asmType(type); 380 } 381 382 @Nullable 383 public JetType expressionJetType(JetExpression expression) { 384 return bindingContext.get(EXPRESSION_TYPE, expression); 385 } 386 387 @Override 388 public StackValue visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression, StackValue receiver) { 389 return genQualified(receiver, expression.getExpression()); 390 } 391 392 @Override 393 public StackValue visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression, StackValue receiver) { 394 return genQualified(receiver, expression.getBaseExpression()); 395 } 396 397 private static boolean isEmptyExpression(@Nullable JetElement expr) { 398 if (expr == null) { 399 return true; 400 } 401 if (expr instanceof JetBlockExpression) { 402 JetBlockExpression blockExpression = (JetBlockExpression) expr; 403 List<JetElement> statements = blockExpression.getStatements(); 404 if (statements.size() == 0 || statements.size() == 1 && isEmptyExpression(statements.get(0))) { 405 return true; 406 } 407 } 408 return false; 409 } 410 411 @Override 412 public StackValue visitIfExpression(@NotNull JetIfExpression expression, StackValue receiver) { 413 return generateIfExpression(expression, false); 414 } 415 416 /* package */ StackValue generateIfExpression(@NotNull final JetIfExpression expression, final boolean isStatement) { 417 final Type asmType = isStatement ? Type.VOID_TYPE : expressionType(expression); 418 final StackValue condition = gen(expression.getCondition()); 419 420 final JetExpression thenExpression = expression.getThen(); 421 final JetExpression elseExpression = expression.getElse(); 422 423 if (isEmptyExpression(thenExpression)) { 424 if (isEmptyExpression(elseExpression)) { 425 return StackValue.coercion(condition, asmType); 426 } 427 return generateSingleBranchIf(condition, expression, elseExpression, false, isStatement); 428 } 429 else { 430 if (isEmptyExpression(elseExpression)) { 431 return generateSingleBranchIf(condition, expression, thenExpression, true, isStatement); 432 } 433 } 434 435 return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() { 436 @Override 437 public Unit invoke(InstructionAdapter v) { 438 Label elseLabel = new Label(); 439 condition.condJump(elseLabel, true, v); // == 0, i.e. false 440 441 Label end = new Label(); 442 443 gen(thenExpression, asmType); 444 445 v.goTo(end); 446 v.mark(elseLabel); 447 448 gen(elseExpression, asmType); 449 450 markLineNumber(expression, isStatement); 451 v.mark(end); 452 return Unit.INSTANCE$; 453 } 454 }); 455 } 456 457 @Override 458 public StackValue visitWhileExpression(@NotNull JetWhileExpression expression, StackValue receiver) { 459 Label condition = new Label(); 460 v.mark(condition); 461 462 Label end = new Label(); 463 blockStackElements.push(new LoopBlockStackElement(end, condition, targetLabel(expression))); 464 465 StackValue conditionValue = gen(expression.getCondition()); 466 conditionValue.condJump(end, true, v); 467 468 generateLoopBody(expression.getBody()); 469 470 v.goTo(condition); 471 472 v.mark(end); 473 474 blockStackElements.pop(); 475 476 return StackValue.onStack(Type.VOID_TYPE); 477 } 478 479 480 @Override 481 public StackValue visitDoWhileExpression(@NotNull JetDoWhileExpression expression, StackValue receiver) { 482 Label beginLoopLabel = new Label(); 483 v.mark(beginLoopLabel); 484 485 Label breakLabel = new Label(); 486 Label continueLabel = new Label(); 487 488 blockStackElements.push(new LoopBlockStackElement(breakLabel, continueLabel, targetLabel(expression))); 489 490 JetExpression body = expression.getBody(); 491 JetExpression condition = expression.getCondition(); 492 StackValue conditionValue; 493 494 if (body instanceof JetBlockExpression) { 495 // If body's a block, it can contain variable declarations which may be used in the condition of a do-while loop. 496 // We handle this case separately because otherwise such variable will be out of the frame map after the block ends 497 List<JetElement> doWhileStatements = ((JetBlockExpression) body).getStatements(); 498 499 List<JetElement> statements = new ArrayList<JetElement>(doWhileStatements.size() + 1); 500 statements.addAll(doWhileStatements); 501 statements.add(condition); 502 503 conditionValue = generateBlock(statements, false, continueLabel, null); 504 } 505 else { 506 if (body != null) { 507 gen(body, Type.VOID_TYPE); 508 } 509 v.mark(continueLabel); 510 conditionValue = gen(condition); 511 } 512 513 conditionValue.condJump(beginLoopLabel, false, v); 514 v.mark(breakLabel); 515 516 blockStackElements.pop(); 517 return StackValue.none(); 518 } 519 520 @Override 521 public StackValue visitForExpression(@NotNull JetForExpression forExpression, StackValue receiver) { 522 // Is it a "1..2" or so 523 RangeCodegenUtil.BinaryCall binaryCall = RangeCodegenUtil.getRangeAsBinaryCall(forExpression); 524 if (binaryCall != null) { 525 ResolvedCall<?> resolvedCall = getResolvedCall(binaryCall.op, bindingContext); 526 if (resolvedCall != null) { 527 if (RangeCodegenUtil.isOptimizableRangeTo(resolvedCall.getResultingDescriptor())) { 528 generateForLoop(new ForInRangeLiteralLoopGenerator(forExpression, binaryCall)); 529 return StackValue.none(); 530 } 531 } 532 } 533 534 JetExpression loopRange = forExpression.getLoopRange(); 535 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, loopRange); 536 assert loopRangeType != null; 537 Type asmLoopRangeType = asmType(loopRangeType); 538 if (asmLoopRangeType.getSort() == Type.ARRAY) { 539 generateForLoop(new ForInArrayLoopGenerator(forExpression)); 540 return StackValue.none(); 541 } 542 543 if (RangeCodegenUtil.isRange(loopRangeType)) { 544 generateForLoop(new ForInRangeInstanceLoopGenerator(forExpression)); 545 return StackValue.none(); 546 } 547 548 if (RangeCodegenUtil.isProgression(loopRangeType)) { 549 generateForLoop(new ForInProgressionExpressionLoopGenerator(forExpression)); 550 return StackValue.none(); 551 } 552 553 generateForLoop(new IteratorForLoopGenerator(forExpression)); 554 return StackValue.none(); 555 } 556 557 private OwnerKind contextKind() { 558 return context.getContextKind(); 559 } 560 561 private void generateForLoop(AbstractForLoopGenerator generator) { 562 Label loopExit = new Label(); 563 Label loopEntry = new Label(); 564 Label continueLabel = new Label(); 565 566 generator.beforeLoop(); 567 generator.checkEmptyLoop(loopExit); 568 569 v.mark(loopEntry); 570 generator.checkPreCondition(loopExit); 571 572 generator.beforeBody(); 573 blockStackElements.push(new LoopBlockStackElement(loopExit, continueLabel, targetLabel(generator.forExpression))); 574 generator.body(); 575 blockStackElements.pop(); 576 v.mark(continueLabel); 577 generator.afterBody(loopExit); 578 579 v.goTo(loopEntry); 580 581 v.mark(loopExit); 582 generator.afterLoop(); 583 } 584 585 private abstract class AbstractForLoopGenerator { 586 587 // for (e : E in c) {...} 588 protected final JetForExpression forExpression; 589 private final Label bodyStart = new Label(); 590 private final Label bodyEnd = new Label(); 591 private final List<Runnable> leaveVariableTasks = Lists.newArrayList(); 592 593 protected final JetType elementType; 594 protected final Type asmElementType; 595 596 protected int loopParameterVar; 597 598 private AbstractForLoopGenerator(@NotNull JetForExpression forExpression) { 599 this.forExpression = forExpression; 600 this.elementType = getElementType(forExpression); 601 this.asmElementType = asmType(elementType); 602 } 603 604 @NotNull 605 private JetType getElementType(JetForExpression forExpression) { 606 JetExpression loopRange = forExpression.getLoopRange(); 607 assert loopRange != null; 608 ResolvedCall<FunctionDescriptor> nextCall = getNotNull(bindingContext, 609 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 610 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 611 //noinspection ConstantConditions 612 return nextCall.getResultingDescriptor().getReturnType(); 613 } 614 615 public void beforeLoop() { 616 JetParameter loopParameter = forExpression.getLoopParameter(); 617 if (loopParameter != null) { 618 // E e = tmp<iterator>.next() 619 final VariableDescriptor parameterDescriptor = bindingContext.get(VALUE_PARAMETER, loopParameter); 620 @SuppressWarnings("ConstantConditions") final Type asmTypeForParameter = asmType(parameterDescriptor.getType()); 621 loopParameterVar = myFrameMap.enter(parameterDescriptor, asmTypeForParameter); 622 scheduleLeaveVariable(new Runnable() { 623 @Override 624 public void run() { 625 myFrameMap.leave(parameterDescriptor); 626 v.visitLocalVariable(parameterDescriptor.getName().asString(), 627 asmTypeForParameter.getDescriptor(), null, 628 bodyStart, bodyEnd, 629 loopParameterVar); 630 } 631 }); 632 } 633 else { 634 JetMultiDeclaration multiParameter = forExpression.getMultiParameter(); 635 assert multiParameter != null; 636 637 // E tmp<e> = tmp<iterator>.next() 638 loopParameterVar = createLoopTempVariable(asmElementType); 639 } 640 } 641 642 public abstract void checkEmptyLoop(@NotNull Label loopExit); 643 644 public abstract void checkPreCondition(@NotNull Label loopExit); 645 646 public void beforeBody() { 647 v.mark(bodyStart); 648 649 assignToLoopParameter(); 650 651 if (forExpression.getLoopParameter() == null) { 652 JetMultiDeclaration multiParameter = forExpression.getMultiParameter(); 653 assert multiParameter != null; 654 655 generateMultiVariables(multiParameter.getEntries()); 656 } 657 } 658 659 private void generateMultiVariables(List<JetMultiDeclarationEntry> entries) { 660 for (JetMultiDeclarationEntry variableDeclaration : entries) { 661 final VariableDescriptor componentDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 662 663 @SuppressWarnings("ConstantConditions") final Type componentAsmType = asmType(componentDescriptor.getReturnType()); 664 final int componentVarIndex = myFrameMap.enter(componentDescriptor, componentAsmType); 665 scheduleLeaveVariable(new Runnable() { 666 @Override 667 public void run() { 668 myFrameMap.leave(componentDescriptor); 669 v.visitLocalVariable(componentDescriptor.getName().asString(), 670 componentAsmType.getDescriptor(), null, 671 bodyStart, bodyEnd, 672 componentVarIndex); 673 } 674 }); 675 676 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 677 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 678 Call call = makeFakeCall(new TransientReceiver(elementType)); 679 680 StackValue value = invokeFunction(call, resolvedCall, StackValue.local(loopParameterVar, asmElementType)); 681 StackValue.local(componentVarIndex, componentAsmType).store(value, v); 682 } 683 } 684 685 protected abstract void assignToLoopParameter(); 686 687 protected abstract void increment(@NotNull Label loopExit); 688 689 public void body() { 690 generateLoopBody(forExpression.getBody()); 691 } 692 693 private void scheduleLeaveVariable(Runnable runnable) { 694 leaveVariableTasks.add(runnable); 695 } 696 697 protected int createLoopTempVariable(final Type type) { 698 int varIndex = myFrameMap.enterTemp(type); 699 scheduleLeaveVariable(new Runnable() { 700 @Override 701 public void run() { 702 myFrameMap.leaveTemp(type); 703 } 704 }); 705 return varIndex; 706 } 707 708 public void afterBody(@NotNull Label loopExit) { 709 markStartLineNumber(forExpression); 710 711 increment(loopExit); 712 713 v.mark(bodyEnd); 714 } 715 716 public void afterLoop() { 717 for (Runnable task : Lists.reverse(leaveVariableTasks)) { 718 task.run(); 719 } 720 } 721 722 // This method consumes range/progression from stack 723 // The result is stored to local variable 724 protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) { 725 Type boxedType = boxType(elementType); 726 v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + boxedType.getDescriptor(), false); 727 StackValue.coerce(boxedType, elementType, v); 728 v.store(varToStore, elementType); 729 } 730 } 731 732 private void generateLoopBody(@Nullable JetExpression body) { 733 if (body != null) { 734 gen(body, Type.VOID_TYPE); 735 } 736 } 737 738 private class IteratorForLoopGenerator extends AbstractForLoopGenerator { 739 740 private int iteratorVarIndex; 741 private final ResolvedCall<FunctionDescriptor> iteratorCall; 742 private final ResolvedCall<FunctionDescriptor> nextCall; 743 private final Type asmTypeForIterator; 744 745 private IteratorForLoopGenerator(@NotNull JetForExpression forExpression) { 746 super(forExpression); 747 748 JetExpression loopRange = forExpression.getLoopRange(); 749 assert loopRange != null; 750 this.iteratorCall = getNotNull(bindingContext, 751 LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange, 752 "No .iterator() function " + DiagnosticUtils.atLocation(loopRange)); 753 754 JetType iteratorType = iteratorCall.getResultingDescriptor().getReturnType(); 755 assert iteratorType != null; 756 this.asmTypeForIterator = asmType(iteratorType); 757 758 this.nextCall = getNotNull(bindingContext, 759 LOOP_RANGE_NEXT_RESOLVED_CALL, loopRange, 760 "No next() function " + DiagnosticUtils.atLocation(loopRange)); 761 } 762 763 @Override 764 public void beforeLoop() { 765 super.beforeLoop(); 766 767 // Iterator<E> tmp<iterator> = c.iterator() 768 769 iteratorVarIndex = createLoopTempVariable(asmTypeForIterator); 770 771 StackValue.local(iteratorVarIndex, asmTypeForIterator).store(invokeFunction(iteratorCall, StackValue.none()), v); 772 } 773 774 @Override 775 public void checkEmptyLoop(@NotNull Label loopExit) { 776 } 777 778 @Override 779 public void checkPreCondition(@NotNull Label loopExit) { 780 // tmp<iterator>.hasNext() 781 782 JetExpression loopRange = forExpression.getLoopRange(); 783 @SuppressWarnings("ConstantConditions") ResolvedCall<FunctionDescriptor> hasNextCall = getNotNull(bindingContext, 784 LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, loopRange, 785 "No hasNext() function " + DiagnosticUtils.atLocation(loopRange)); 786 @SuppressWarnings("ConstantConditions") Call fakeCall = makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 787 StackValue result = invokeFunction(fakeCall, hasNextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)); 788 result.put(result.type, v); 789 790 JetType type = hasNextCall.getResultingDescriptor().getReturnType(); 791 assert type != null && JetTypeChecker.DEFAULT.isSubtypeOf(type, KotlinBuiltIns.getInstance().getBooleanType()); 792 793 Type asmType = asmType(type); 794 StackValue.coerce(asmType, Type.BOOLEAN_TYPE, v); 795 v.ifeq(loopExit); 796 } 797 798 @Override 799 protected void assignToLoopParameter() { 800 @SuppressWarnings("ConstantConditions") Call fakeCall = 801 makeFakeCall(new TransientReceiver(iteratorCall.getResultingDescriptor().getReturnType())); 802 StackValue value = invokeFunction(fakeCall, nextCall, StackValue.local(iteratorVarIndex, asmTypeForIterator)); 803 //noinspection ConstantConditions 804 StackValue.local(loopParameterVar, asmType(nextCall.getResultingDescriptor().getReturnType())).store(value, v); 805 } 806 807 @Override 808 protected void increment(@NotNull Label loopExit) { 809 } 810 } 811 812 private class ForInArrayLoopGenerator extends AbstractForLoopGenerator { 813 private int indexVar; 814 private int arrayVar; 815 private final JetType loopRangeType; 816 817 private ForInArrayLoopGenerator(@NotNull JetForExpression forExpression) { 818 super(forExpression); 819 loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 820 } 821 822 @Override 823 public void beforeLoop() { 824 super.beforeLoop(); 825 826 indexVar = createLoopTempVariable(Type.INT_TYPE); 827 828 JetExpression loopRange = forExpression.getLoopRange(); 829 StackValue value = gen(loopRange); 830 Type asmLoopRangeType = asmType(loopRangeType); 831 if (value instanceof StackValue.Local && value.type.equals(asmLoopRangeType)) { 832 arrayVar = ((StackValue.Local) value).index; // no need to copy local variable into another variable 833 } 834 else { 835 arrayVar = createLoopTempVariable(OBJECT_TYPE); 836 value.put(asmLoopRangeType, v); 837 v.store(arrayVar, OBJECT_TYPE); 838 } 839 840 v.iconst(0); 841 v.store(indexVar, Type.INT_TYPE); 842 } 843 844 @Override 845 public void checkEmptyLoop(@NotNull Label loopExit) { 846 } 847 848 @Override 849 public void checkPreCondition(@NotNull Label loopExit) { 850 v.load(indexVar, Type.INT_TYPE); 851 v.load(arrayVar, OBJECT_TYPE); 852 v.arraylength(); 853 v.ificmpge(loopExit); 854 } 855 856 @Override 857 protected void assignToLoopParameter() { 858 Type arrayElParamType; 859 if (KotlinBuiltIns.isArray(loopRangeType)) { 860 arrayElParamType = boxType(asmElementType); 861 } 862 else { 863 arrayElParamType = asmElementType; 864 } 865 866 v.load(arrayVar, OBJECT_TYPE); 867 v.load(indexVar, Type.INT_TYPE); 868 v.aload(arrayElParamType); 869 StackValue.onStack(arrayElParamType).put(asmElementType, v); 870 v.store(loopParameterVar, asmElementType); 871 } 872 873 @Override 874 protected void increment(@NotNull Label loopExit) { 875 v.iinc(indexVar, 1); 876 } 877 } 878 879 private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator { 880 protected int endVar; 881 882 // For integer progressions instead of comparing loopParameterVar with endVar at the beginning of an iteration we check whether 883 // loopParameterVar == finalVar at the end of the iteration (and also if there should be any iterations at all, before the loop) 884 protected final boolean isIntegerProgression; 885 886 private AbstractForInProgressionOrRangeLoopGenerator(@NotNull JetForExpression forExpression) { 887 super(forExpression); 888 889 switch (asmElementType.getSort()) { 890 case Type.INT: 891 case Type.BYTE: 892 case Type.SHORT: 893 case Type.CHAR: 894 case Type.LONG: 895 isIntegerProgression = true; 896 break; 897 898 case Type.DOUBLE: 899 case Type.FLOAT: 900 isIntegerProgression = false; 901 break; 902 903 default: 904 throw new IllegalStateException("Unexpected range element type: " + asmElementType); 905 } 906 } 907 908 @Override 909 public void beforeLoop() { 910 super.beforeLoop(); 911 912 endVar = createLoopTempVariable(asmElementType); 913 } 914 915 // Index of the local variable holding the actual last value of the loop parameter. 916 // For ranges it equals end, for progressions it's a function of start, end and increment 917 protected abstract int getFinalVar(); 918 919 protected void checkPostCondition(@NotNull Label loopExit) { 920 int finalVar = getFinalVar(); 921 assert isIntegerProgression && finalVar != -1 : 922 "Post-condition should be checked only in case of integer progressions, finalVar = " + finalVar; 923 924 v.load(loopParameterVar, asmElementType); 925 v.load(finalVar, asmElementType); 926 if (asmElementType.getSort() == Type.LONG) { 927 v.lcmp(); 928 v.ifeq(loopExit); 929 } 930 else { 931 v.ificmpeq(loopExit); 932 } 933 } 934 } 935 936 private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 937 private AbstractForInRangeLoopGenerator(@NotNull JetForExpression forExpression) { 938 super(forExpression); 939 } 940 941 @Override 942 public void beforeLoop() { 943 super.beforeLoop(); 944 945 storeRangeStartAndEnd(); 946 } 947 948 protected abstract void storeRangeStartAndEnd(); 949 950 @Override 951 protected int getFinalVar() { 952 return endVar; 953 } 954 955 @Override 956 public void checkPreCondition(@NotNull Label loopExit) { 957 if (isIntegerProgression) return; 958 959 v.load(loopParameterVar, asmElementType); 960 v.load(endVar, asmElementType); 961 962 v.cmpg(asmElementType); 963 v.ifgt(loopExit); 964 } 965 966 @Override 967 public void checkEmptyLoop(@NotNull Label loopExit) { 968 if (!isIntegerProgression) return; 969 970 v.load(loopParameterVar, asmElementType); 971 v.load(endVar, asmElementType); 972 if (asmElementType.getSort() == Type.LONG) { 973 v.lcmp(); 974 v.ifgt(loopExit); 975 } 976 else { 977 v.ificmpgt(loopExit); 978 } 979 } 980 981 @Override 982 protected void assignToLoopParameter() { 983 } 984 985 @Override 986 protected void increment(@NotNull Label loopExit) { 987 if (isIntegerProgression) { 988 checkPostCondition(loopExit); 989 } 990 991 if (asmElementType == Type.INT_TYPE) { 992 v.iinc(loopParameterVar, 1); 993 } 994 else { 995 v.load(loopParameterVar, asmElementType); 996 genIncrement(asmElementType, 1, v); 997 v.store(loopParameterVar, asmElementType); 998 } 999 } 1000 } 1001 1002 private class ForInRangeLiteralLoopGenerator extends AbstractForInRangeLoopGenerator { 1003 private final RangeCodegenUtil.BinaryCall rangeCall; 1004 1005 private ForInRangeLiteralLoopGenerator( 1006 @NotNull JetForExpression forExpression, 1007 @NotNull RangeCodegenUtil.BinaryCall rangeCall 1008 ) { 1009 super(forExpression); 1010 this.rangeCall = rangeCall; 1011 } 1012 1013 @Override 1014 protected void storeRangeStartAndEnd() { 1015 gen(rangeCall.left, asmElementType); 1016 v.store(loopParameterVar, asmElementType); 1017 1018 gen(rangeCall.right, asmElementType); 1019 v.store(endVar, asmElementType); 1020 } 1021 } 1022 1023 private class ForInRangeInstanceLoopGenerator extends AbstractForInRangeLoopGenerator { 1024 private ForInRangeInstanceLoopGenerator(@NotNull JetForExpression forExpression) { 1025 super(forExpression); 1026 } 1027 1028 @Override 1029 protected void storeRangeStartAndEnd() { 1030 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 1031 assert loopRangeType != null; 1032 Type asmLoopRangeType = asmType(loopRangeType); 1033 gen(forExpression.getLoopRange(), asmLoopRangeType); 1034 v.dup(); 1035 1036 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar); 1037 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar); 1038 } 1039 } 1040 1041 private class ForInProgressionExpressionLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { 1042 private int incrementVar; 1043 private Type incrementType; 1044 1045 private int finalVar; 1046 1047 private ForInProgressionExpressionLoopGenerator(@NotNull JetForExpression forExpression) { 1048 super(forExpression); 1049 } 1050 1051 @Override 1052 protected int getFinalVar() { 1053 return finalVar; 1054 } 1055 1056 @Override 1057 public void beforeLoop() { 1058 super.beforeLoop(); 1059 1060 incrementVar = createLoopTempVariable(asmElementType); 1061 1062 JetType loopRangeType = bindingContext.get(EXPRESSION_TYPE, forExpression.getLoopRange()); 1063 assert loopRangeType != null; 1064 Type asmLoopRangeType = asmType(loopRangeType); 1065 1066 Collection<VariableDescriptor> incrementProp = loopRangeType.getMemberScope().getProperties(Name.identifier("increment")); 1067 assert incrementProp.size() == 1 : loopRangeType + " " + incrementProp.size(); 1068 incrementType = asmType(incrementProp.iterator().next().getType()); 1069 1070 gen(forExpression.getLoopRange(), asmLoopRangeType); 1071 v.dup(); 1072 v.dup(); 1073 1074 generateRangeOrProgressionProperty(asmLoopRangeType, "getStart", asmElementType, loopParameterVar); 1075 generateRangeOrProgressionProperty(asmLoopRangeType, "getEnd", asmElementType, endVar); 1076 generateRangeOrProgressionProperty(asmLoopRangeType, "getIncrement", incrementType, incrementVar); 1077 1078 storeFinalVar(); 1079 } 1080 1081 private void storeFinalVar() { 1082 if (!isIntegerProgression) { 1083 finalVar = -1; 1084 return; 1085 } 1086 1087 v.load(loopParameterVar, asmElementType); 1088 v.load(endVar, asmElementType); 1089 v.load(incrementVar, incrementType); 1090 1091 Type methodParamType = asmElementType.getSort() == Type.LONG ? Type.LONG_TYPE : Type.INT_TYPE; 1092 v.invokestatic("kotlin/internal/InternalPackage", "getProgressionFinalElement", 1093 Type.getMethodDescriptor(methodParamType, methodParamType, methodParamType, methodParamType), false); 1094 1095 finalVar = createLoopTempVariable(asmElementType); 1096 v.store(finalVar, asmElementType); 1097 } 1098 1099 @Override 1100 public void checkPreCondition(@NotNull Label loopExit) { 1101 if (isIntegerProgression) return; 1102 1103 v.load(loopParameterVar, asmElementType); 1104 v.load(endVar, asmElementType); 1105 v.load(incrementVar, incrementType); 1106 1107 Label negativeIncrement = new Label(); 1108 Label afterIf = new Label(); 1109 1110 if (incrementType.getSort() == Type.DOUBLE) { 1111 v.dconst(0.0); 1112 } 1113 else { 1114 v.fconst(0.0f); 1115 } 1116 v.cmpl(incrementType); 1117 v.ifle(negativeIncrement); // if increment < 0, jump 1118 1119 // increment > 0 1120 v.cmpg(asmElementType); // if loop parameter is NaN, exit from loop, as well 1121 v.ifgt(loopExit); 1122 v.goTo(afterIf); 1123 1124 // increment < 0 1125 v.mark(negativeIncrement); 1126 v.cmpl(asmElementType); // if loop parameter is NaN, exit from loop, as well 1127 v.iflt(loopExit); 1128 v.mark(afterIf); 1129 } 1130 1131 @Override 1132 public void checkEmptyLoop(@NotNull Label loopExit) { 1133 if (!isIntegerProgression) return; 1134 1135 v.load(loopParameterVar, asmElementType); 1136 v.load(endVar, asmElementType); 1137 v.load(incrementVar, incrementType); 1138 1139 Label negativeIncrement = new Label(); 1140 Label afterIf = new Label(); 1141 1142 if (asmElementType.getSort() == Type.LONG) { 1143 v.lconst(0L); 1144 v.lcmp(); 1145 v.ifle(negativeIncrement); // if increment < 0, jump 1146 1147 // increment > 0 1148 v.lcmp(); 1149 v.ifgt(loopExit); 1150 v.goTo(afterIf); 1151 1152 // increment < 0 1153 v.mark(negativeIncrement); 1154 v.lcmp(); 1155 v.iflt(loopExit); 1156 v.mark(afterIf); 1157 } 1158 else { 1159 v.ifle(negativeIncrement); // if increment < 0, jump 1160 1161 // increment > 0 1162 v.ificmpgt(loopExit); 1163 v.goTo(afterIf); 1164 1165 // increment < 0 1166 v.mark(negativeIncrement); 1167 v.ificmplt(loopExit); 1168 v.mark(afterIf); 1169 } 1170 } 1171 1172 @Override 1173 protected void assignToLoopParameter() { 1174 } 1175 1176 @Override 1177 protected void increment(@NotNull Label loopExit) { 1178 if (isIntegerProgression) { 1179 checkPostCondition(loopExit); 1180 } 1181 1182 v.load(loopParameterVar, asmElementType); 1183 v.load(incrementVar, asmElementType); 1184 v.add(asmElementType); 1185 1186 if (asmElementType == Type.BYTE_TYPE || asmElementType == Type.SHORT_TYPE || asmElementType == Type.CHAR_TYPE) { 1187 StackValue.coerce(Type.INT_TYPE, asmElementType, v); 1188 } 1189 1190 v.store(loopParameterVar, asmElementType); 1191 } 1192 } 1193 1194 1195 @Override 1196 public StackValue visitBreakExpression(@NotNull JetBreakExpression expression, StackValue receiver) { 1197 return generateBreakOrContinueExpression(expression, true); 1198 } 1199 1200 @Override 1201 public StackValue visitContinueExpression(@NotNull JetContinueExpression expression, StackValue receiver) { 1202 return generateBreakOrContinueExpression(expression, false); 1203 } 1204 1205 @NotNull 1206 private StackValue generateBreakOrContinueExpression(@NotNull JetExpressionWithLabel expression, boolean isBreak) { 1207 assert expression instanceof JetContinueExpression || expression instanceof JetBreakExpression; 1208 1209 if (!blockStackElements.isEmpty()) { 1210 BlockStackElement stackElement = blockStackElements.peek(); 1211 1212 if (stackElement instanceof FinallyBlockStackElement) { 1213 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1214 //noinspection ConstantConditions 1215 genFinallyBlockOrGoto(finallyBlockStackElement, null); 1216 } 1217 else if (stackElement instanceof LoopBlockStackElement) { 1218 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; 1219 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 1220 //noinspection ConstantConditions 1221 if (labelElement == null || 1222 loopBlockStackElement.targetLabel != null && 1223 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { 1224 v.goTo(isBreak ? loopBlockStackElement.breakLabel : loopBlockStackElement.continueLabel); 1225 return StackValue.none(); 1226 } 1227 } 1228 else { 1229 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1230 } 1231 1232 blockStackElements.pop(); 1233 StackValue result = generateBreakOrContinueExpression(expression, isBreak); 1234 blockStackElements.push(stackElement); 1235 return result; 1236 } 1237 1238 throw new UnsupportedOperationException("Target label for break/continue not found"); 1239 } 1240 1241 private StackValue generateSingleBranchIf( 1242 final StackValue condition, 1243 final JetIfExpression ifExpression, 1244 final JetExpression expression, 1245 final boolean inverse, 1246 final boolean isStatement 1247 ) { 1248 Type targetType = isStatement ? Type.VOID_TYPE : expressionType(ifExpression); 1249 return StackValue.operation(targetType, new Function1<InstructionAdapter, Unit>() { 1250 @Override 1251 public Unit invoke(InstructionAdapter v) { 1252 Label elseLabel = new Label(); 1253 condition.condJump(elseLabel, inverse, v); 1254 1255 if (isStatement) { 1256 gen(expression, Type.VOID_TYPE); 1257 v.mark(elseLabel); 1258 } 1259 else { 1260 Type targetType = expressionType(ifExpression); 1261 gen(expression, targetType); 1262 Label end = new Label(); 1263 v.goTo(end); 1264 1265 v.mark(elseLabel); 1266 StackValue.putUnitInstance(v); 1267 1268 markStartLineNumber(ifExpression); 1269 v.mark(end); 1270 } 1271 return null; 1272 } 1273 }); 1274 } 1275 1276 @Override 1277 public StackValue visitConstantExpression(@NotNull JetConstantExpression expression, StackValue receiver) { 1278 CompileTimeConstant<?> compileTimeValue = getCompileTimeConstant(expression, bindingContext); 1279 assert compileTimeValue != null; 1280 return StackValue.constant(compileTimeValue.getValue(), expressionType(expression)); 1281 } 1282 1283 @Nullable 1284 public static CompileTimeConstant getCompileTimeConstant(@NotNull JetExpression expression, @NotNull BindingContext bindingContext) { 1285 CompileTimeConstant<?> compileTimeValue = bindingContext.get(COMPILE_TIME_VALUE, expression); 1286 if (compileTimeValue instanceof IntegerValueTypeConstant) { 1287 JetType expectedType = bindingContext.get(EXPRESSION_TYPE, expression); 1288 assert expectedType != null : "Expression is not type checked: " + expression.getText(); 1289 return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) compileTimeValue, expectedType); 1290 } 1291 return compileTimeValue; 1292 } 1293 1294 @Override 1295 public StackValue visitStringTemplateExpression(@NotNull JetStringTemplateExpression expression, StackValue receiver) { 1296 StringBuilder constantValue = new StringBuilder(""); 1297 final JetStringTemplateEntry[] entries = expression.getEntries(); 1298 1299 if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) { 1300 JetExpression expr = entries[0].getExpression(); 1301 return genToString(gen(expr), expressionType(expr)); 1302 } 1303 1304 for (JetStringTemplateEntry entry : entries) { 1305 if (entry instanceof JetLiteralStringTemplateEntry) { 1306 constantValue.append(entry.getText()); 1307 } 1308 else if (entry instanceof JetEscapeStringTemplateEntry) { 1309 constantValue.append(((JetEscapeStringTemplateEntry) entry).getUnescapedValue()); 1310 } 1311 else { 1312 constantValue = null; 1313 break; 1314 } 1315 } 1316 if (constantValue != null) { 1317 Type type = expressionType(expression); 1318 return StackValue.constant(constantValue.toString(), type); 1319 } 1320 else { 1321 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 1322 @Override 1323 public Unit invoke(InstructionAdapter v) { 1324 genStringBuilderConstructor(v); 1325 for (JetStringTemplateEntry entry : entries) { 1326 if (entry instanceof JetStringTemplateEntryWithExpression) { 1327 invokeAppend(entry.getExpression()); 1328 } 1329 else { 1330 String text = entry instanceof JetEscapeStringTemplateEntry 1331 ? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue() 1332 : entry.getText(); 1333 v.aconst(text); 1334 genInvokeAppendMethod(v, JAVA_STRING_TYPE); 1335 } 1336 } 1337 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 1338 return Unit.INSTANCE$; 1339 } 1340 }); 1341 } 1342 } 1343 1344 @Override 1345 public StackValue visitBlockExpression(@NotNull JetBlockExpression expression, StackValue receiver) { 1346 return generateBlock(expression, false); 1347 } 1348 1349 @Override 1350 public StackValue visitNamedFunction(@NotNull JetNamedFunction function, StackValue data) { 1351 return visitNamedFunction(function, data, false); 1352 } 1353 1354 public StackValue visitNamedFunction(@NotNull JetNamedFunction function, StackValue data, boolean isStatement) { 1355 assert data == StackValue.none(); 1356 1357 if (JetPsiUtil.isScriptDeclaration(function)) { 1358 return StackValue.none(); 1359 } 1360 1361 StackValue closure = genClosure(function, null, KotlinSyntheticClass.Kind.LOCAL_FUNCTION); 1362 if (isStatement) { 1363 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, function); 1364 int index = lookupLocalIndex(descriptor); 1365 closure.put(OBJECT_TYPE, v); 1366 v.store(index, OBJECT_TYPE); 1367 return StackValue.none(); 1368 } 1369 else { 1370 return closure; 1371 } 1372 } 1373 1374 @Override 1375 public StackValue visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression, StackValue receiver) { 1376 if (Boolean.TRUE.equals(bindingContext.get(BLOCK, expression))) { 1377 return gen(expression.getFunctionLiteral().getBodyExpression()); 1378 } 1379 else { 1380 return genClosure(expression.getFunctionLiteral(), null, KotlinSyntheticClass.Kind.ANONYMOUS_FUNCTION); 1381 } 1382 } 1383 1384 @NotNull 1385 private StackValue genClosure( 1386 JetDeclarationWithBody declaration, 1387 @Nullable SamType samType, 1388 @NotNull KotlinSyntheticClass.Kind kind 1389 ) { 1390 FunctionDescriptor descriptor = bindingContext.get(FUNCTION, declaration); 1391 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); 1392 1393 return genClosure( 1394 declaration, descriptor, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration), samType, kind 1395 ); 1396 } 1397 1398 @NotNull 1399 private StackValue genClosure( 1400 @NotNull JetElement declaration, 1401 @NotNull FunctionDescriptor descriptor, 1402 @NotNull FunctionGenerationStrategy strategy, 1403 @Nullable SamType samType, 1404 @NotNull KotlinSyntheticClass.Kind kind 1405 ) { 1406 ClassBuilder cv = state.getFactory().newVisitor( 1407 OtherOrigin(declaration, descriptor), 1408 asmTypeForAnonymousClass(bindingContext, descriptor), 1409 declaration.getContainingFile() 1410 ); 1411 1412 ClosureCodegen closureCodegen = new ClosureCodegen( 1413 state, declaration, samType, context.intoClosure(descriptor, this, typeMapper), kind, strategy, parentCodegen, cv 1414 ); 1415 1416 closureCodegen.generate(); 1417 1418 if (closureCodegen.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) { 1419 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1420 propagateChildReifiedTypeParametersUsages(closureCodegen.getReifiedTypeParametersUsages()); 1421 } 1422 1423 return closureCodegen.putInstanceOnStack(this); 1424 } 1425 1426 @Override 1427 public StackValue visitObjectLiteralExpression(@NotNull JetObjectLiteralExpression expression, StackValue receiver) { 1428 final ObjectLiteralResult objectLiteralResult = generateObjectLiteral(expression); 1429 final ClassDescriptor classDescriptor = objectLiteralResult.classDescriptor; 1430 final Type type = typeMapper.mapType(classDescriptor); 1431 1432 return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() { 1433 @Override 1434 public Unit invoke(InstructionAdapter v) { 1435 if (objectLiteralResult.wereReifiedMarkers) { 1436 ReifiedTypeInliner.putNeedClassReificationMarker(v); 1437 } 1438 v.anew(type); 1439 v.dup(); 1440 1441 pushClosureOnStack(classDescriptor, true, defaultCallGenerator); 1442 1443 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 1444 assert primaryConstructor != null : "There should be primary constructor for object literal"; 1445 ResolvedCall<ConstructorDescriptor> superCall = getDelegationConstructorCall(bindingContext, primaryConstructor); 1446 if (superCall != null) { 1447 // For an anonymous object, we should also generate all non-default arguments that it captures for its super call 1448 ConstructorDescriptor superConstructor = superCall.getResultingDescriptor(); 1449 List<ValueParameterDescriptor> superValueParameters = superConstructor.getValueParameters(); 1450 int params = superValueParameters.size(); 1451 List<Type> superMappedTypes = typeMapper.mapToCallableMethod(superConstructor).getValueParameterTypes(); 1452 assert superMappedTypes.size() >= params : String 1453 .format("Incorrect number of mapped parameters vs arguments: %d < %d for %s", 1454 superMappedTypes.size(), params, classDescriptor); 1455 1456 List<ResolvedValueArgument> valueArguments = new ArrayList<ResolvedValueArgument>(params); 1457 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(params); 1458 List<Type> mappedTypes = new ArrayList<Type>(params); 1459 for (ValueParameterDescriptor parameter : superValueParameters) { 1460 ResolvedValueArgument argument = superCall.getValueArguments().get(parameter); 1461 if (!(argument instanceof DefaultValueArgument)) { 1462 valueArguments.add(argument); 1463 valueParameters.add(parameter); 1464 mappedTypes.add(superMappedTypes.get(parameter.getIndex())); 1465 } 1466 } 1467 ArgumentGenerator argumentGenerator = 1468 new CallBasedArgumentGenerator(ExpressionCodegen.this, defaultCallGenerator, valueParameters, mappedTypes); 1469 1470 argumentGenerator.generate(valueArguments); 1471 } 1472 1473 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors(); 1474 assert constructors.size() == 1 : "Unexpected number of constructors for class: " + classDescriptor + " " + constructors; 1475 ConstructorDescriptor constructorDescriptor = KotlinPackage.single(constructors); 1476 1477 JvmMethodSignature constructor = typeMapper.mapSignature(constructorDescriptor); 1478 v.invokespecial(type.getInternalName(), "<init>", constructor.getAsmMethod().getDescriptor(), false); 1479 return Unit.INSTANCE$; 1480 } 1481 }); 1482 } 1483 1484 public void pushClosureOnStack(@NotNull ClassDescriptor classDescriptor, boolean putThis, @NotNull CallGenerator callGenerator) { 1485 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); 1486 if (closure == null) return; 1487 1488 int paramIndex = 0; 1489 1490 if (putThis) { 1491 ClassDescriptor captureThis = closure.getCaptureThis(); 1492 if (captureThis != null) { 1493 StackValue thisOrOuter = generateThisOrOuter(captureThis, false); 1494 assert !isPrimitive(thisOrOuter.type) : "This or outer should be non primitive: " + thisOrOuter.type; 1495 callGenerator.putCapturedValueOnStack(thisOrOuter, thisOrOuter.type, paramIndex++); 1496 } 1497 } 1498 1499 JetType captureReceiver = closure.getCaptureReceiverType(); 1500 if (captureReceiver != null) { 1501 Type asmType = typeMapper.mapType(captureReceiver); 1502 StackValue.Local capturedReceiver = StackValue.local(AsmUtil.getReceiverIndex(context, context.getContextDescriptor()), asmType); 1503 callGenerator.putCapturedValueOnStack(capturedReceiver, capturedReceiver.type, paramIndex++); 1504 } 1505 1506 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1507 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1508 if (sharedVarType == null) { 1509 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1510 } 1511 StackValue capturedVar = entry.getValue().getOuterValue(this); 1512 callGenerator.putCapturedValueOnStack(capturedVar, sharedVarType, paramIndex++); 1513 } 1514 1515 1516 ClassDescriptor superClass = DescriptorUtilPackage.getSuperClassNotAny(classDescriptor); 1517 if (superClass != null) { 1518 pushClosureOnStack( 1519 superClass, 1520 putThis && closure.getCaptureThis() == null, 1521 callGenerator 1522 ); 1523 } 1524 } 1525 1526 /* package */ StackValue generateBlock(@NotNull JetBlockExpression expression, boolean isStatement) { 1527 if (expression.getParent() instanceof JetNamedFunction) { 1528 // For functions end of block should be end of function label 1529 return generateBlock(expression.getStatements(), isStatement, null, context.getMethodEndLabel()); 1530 } 1531 return generateBlock(expression.getStatements(), isStatement, null, null); 1532 } 1533 1534 private StackValue generateBlock( 1535 List<JetElement> statements, 1536 boolean isStatement, 1537 Label labelBeforeLastExpression, 1538 @Nullable final Label labelBlockEnd 1539 ) { 1540 final Label blockEnd = labelBlockEnd != null ? labelBlockEnd : new Label(); 1541 1542 final List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1543 1544 StackValue answer = StackValue.none(); 1545 1546 for (Iterator<JetElement> iterator = statements.iterator(); iterator.hasNext(); ) { 1547 JetElement possiblyLabeledStatement = iterator.next(); 1548 1549 JetElement statement = possiblyLabeledStatement instanceof JetExpression 1550 ? JetPsiUtil.safeDeparenthesize((JetExpression) possiblyLabeledStatement, true) 1551 : possiblyLabeledStatement; 1552 1553 1554 if (statement instanceof JetNamedDeclaration) { 1555 JetNamedDeclaration declaration = (JetNamedDeclaration) statement; 1556 if (JetPsiUtil.isScriptDeclaration(declaration)) { 1557 continue; 1558 } 1559 } 1560 1561 putDescriptorIntoFrameMap(statement); 1562 1563 boolean isExpression = !iterator.hasNext() && !isStatement; 1564 if (isExpression && labelBeforeLastExpression != null) { 1565 v.mark(labelBeforeLastExpression); 1566 } 1567 1568 StackValue result = isExpression ? gen(possiblyLabeledStatement) : genStatement(possiblyLabeledStatement); 1569 1570 if (!iterator.hasNext()) { 1571 answer = result; 1572 } 1573 else { 1574 result.put(Type.VOID_TYPE, v); 1575 } 1576 1577 removeDescriptorFromFrameMap(statement, blockEnd, leaveTasks); 1578 } 1579 1580 return new StackValueWithLeaveTask(answer, new ExtensionFunction0<StackValueWithLeaveTask, Unit>() { 1581 @Override 1582 public Unit invoke(StackValueWithLeaveTask wrapper) { 1583 if (labelBlockEnd == null) { 1584 v.mark(blockEnd); 1585 } 1586 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1587 task.fun(wrapper.getStackValue()); 1588 } 1589 return Unit.INSTANCE$; 1590 } 1591 }); 1592 } 1593 1594 @NotNull 1595 private Type getVariableType(@NotNull VariableDescriptor variableDescriptor) { 1596 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1597 return sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1598 } 1599 1600 private static boolean isSharedVarType(@NotNull Type type) { 1601 return type.getSort() == Type.OBJECT && type.getInternalName().startsWith(REF_TYPE_PREFIX); 1602 } 1603 1604 1605 private void putDescriptorIntoFrameMap(@NotNull JetElement statement) { 1606 if (statement instanceof JetMultiDeclaration) { 1607 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement; 1608 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1609 putLocalVariableIntoFrameMap(entry); 1610 } 1611 } 1612 1613 if (statement instanceof JetVariableDeclaration) { 1614 putLocalVariableIntoFrameMap((JetVariableDeclaration) statement); 1615 } 1616 1617 if (statement instanceof JetNamedFunction) { 1618 DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1619 myFrameMap.enter(descriptor, OBJECT_TYPE); 1620 } 1621 } 1622 1623 private void putLocalVariableIntoFrameMap(@NotNull JetVariableDeclaration statement) { 1624 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1625 assert variableDescriptor != null : "Couldn't find variable declaration in binding context " + statement.getText(); 1626 1627 Type type = getVariableType(variableDescriptor); 1628 int index = myFrameMap.enter(variableDescriptor, type); 1629 1630 if (isSharedVarType(type)) { 1631 v.anew(type); 1632 v.dup(); 1633 v.invokespecial(type.getInternalName(), "<init>", "()V", false); 1634 v.store(index, OBJECT_TYPE); 1635 } 1636 } 1637 1638 private void removeDescriptorFromFrameMap( 1639 @NotNull JetElement statement, 1640 @NotNull Label blockEnd, 1641 @NotNull List<Function<StackValue, Void>> leaveTasks 1642 ) { 1643 if (statement instanceof JetMultiDeclaration) { 1644 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement; 1645 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1646 removeLocalVariableFromFrameMap(entry, blockEnd, leaveTasks); 1647 } 1648 } 1649 1650 if (statement instanceof JetVariableDeclaration) { 1651 removeLocalVariableFromFrameMap((JetVariableDeclaration) statement, blockEnd, leaveTasks); 1652 } 1653 1654 if (statement instanceof JetNamedFunction) { 1655 final DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, statement); 1656 leaveTasks.add(new Function<StackValue, Void>() { 1657 @Override 1658 public Void fun(StackValue value) { 1659 myFrameMap.leave(descriptor); 1660 return null; 1661 } 1662 }); 1663 } 1664 } 1665 1666 private void removeLocalVariableFromFrameMap( 1667 @NotNull JetVariableDeclaration statement, 1668 final Label blockEnd, 1669 @NotNull List<Function<StackValue, Void>> leaveTasks 1670 ) { 1671 final VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, statement); 1672 assert variableDescriptor != null; 1673 1674 final Type type = getVariableType(variableDescriptor); 1675 1676 final Label scopeStart = new Label(); 1677 v.mark(scopeStart); 1678 1679 leaveTasks.add(new Function<StackValue, Void>() { 1680 @Override 1681 public Void fun(StackValue answer) { 1682 int index = myFrameMap.leave(variableDescriptor); 1683 1684 if (isSharedVarType(type)) { 1685 v.aconst(null); 1686 v.store(index, OBJECT_TYPE); 1687 } 1688 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, index); 1689 return null; 1690 } 1691 }); 1692 } 1693 1694 public boolean isShouldMarkLineNumbers() { 1695 return shouldMarkLineNumbers; 1696 } 1697 1698 public void setShouldMarkLineNumbers(boolean shouldMarkLineNumbers) { 1699 this.shouldMarkLineNumbers = shouldMarkLineNumbers; 1700 } 1701 1702 public void markStartLineNumber(@NotNull JetElement element) { 1703 markLineNumber(element, false); 1704 } 1705 1706 public void markLineNumber(@NotNull JetElement statement, boolean markEndOffset) { 1707 if (!shouldMarkLineNumbers) return; 1708 1709 Integer lineNumber = CodegenUtil.getLineNumberForElement(statement, markEndOffset); 1710 if (lineNumber == null || lineNumber == myLastLineNumber) { 1711 return; 1712 } 1713 myLastLineNumber = lineNumber; 1714 1715 Label label = new Label(); 1716 v.visitLabel(label); 1717 v.visitLineNumber(lineNumber, label); 1718 } 1719 1720 private void doFinallyOnReturn() { 1721 if(!blockStackElements.isEmpty()) { 1722 BlockStackElement stackElement = blockStackElements.peek(); 1723 if (stackElement instanceof FinallyBlockStackElement) { 1724 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1725 genFinallyBlockOrGoto(finallyBlockStackElement, null); 1726 } 1727 else if (stackElement instanceof LoopBlockStackElement) { 1728 1729 } else { 1730 throw new UnsupportedOperationException("Wrong BlockStackElement in processing stack"); 1731 } 1732 1733 blockStackElements.pop(); 1734 doFinallyOnReturn(); 1735 blockStackElements.push(stackElement); 1736 } 1737 } 1738 1739 public boolean hasFinallyBlocks() { 1740 for (BlockStackElement element : blockStackElements) { 1741 if (element instanceof FinallyBlockStackElement) { 1742 return true; 1743 } 1744 } 1745 return false; 1746 } 1747 1748 private void genFinallyBlockOrGoto( 1749 @Nullable FinallyBlockStackElement finallyBlockStackElement, 1750 @Nullable Label tryCatchBlockEnd 1751 ) { 1752 if (finallyBlockStackElement != null) { 1753 assert finallyBlockStackElement.gaps.size() % 2 == 0 : "Finally block gaps are inconsistent"; 1754 1755 BlockStackElement topOfStack = blockStackElements.pop(); 1756 assert topOfStack == finallyBlockStackElement : "Top element of stack doesn't equals processing finally block"; 1757 1758 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1759 Label finallyStart = new Label(); 1760 v.mark(finallyStart); 1761 finallyBlockStackElement.addGapLabel(finallyStart); 1762 1763 //noinspection ConstantConditions 1764 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1765 } 1766 1767 if (tryCatchBlockEnd != null) { 1768 if (context.isInlineFunction()) { 1769 InlineCodegenUtil.generateGoToTryCatchBlockEndMarker(v); 1770 } 1771 v.goTo(tryCatchBlockEnd); 1772 } 1773 1774 if (finallyBlockStackElement != null) { 1775 Label finallyEnd = new Label(); 1776 v.mark(finallyEnd); 1777 finallyBlockStackElement.addGapLabel(finallyEnd); 1778 1779 blockStackElements.push(finallyBlockStackElement); 1780 } 1781 } 1782 1783 @Override 1784 public StackValue visitReturnExpression(@NotNull JetReturnExpression expression, StackValue receiver) { 1785 JetExpression returnedExpression = expression.getReturnedExpression(); 1786 CallableMemberDescriptor descriptor = getContext().getContextDescriptor(); 1787 NonLocalReturnInfo nonLocalReturn = getNonLocalReturnInfo(descriptor, expression); 1788 boolean isNonLocalReturn = nonLocalReturn != null; 1789 if (isNonLocalReturn && !state.isInlineEnabled()) { 1790 throw new CompilationException("Non local returns requires enabled inlining", null, expression); 1791 } 1792 1793 Type returnType = isNonLocalReturn ? nonLocalReturn.returnType : this.returnType; 1794 if (returnedExpression != null) { 1795 gen(returnedExpression, returnType); 1796 } 1797 1798 generateFinallyBlocksIfNeeded(returnType); 1799 1800 if (isNonLocalReturn) { 1801 InlineCodegenUtil.generateGlobalReturnFlag(v, nonLocalReturn.labelName); 1802 } 1803 v.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); 1804 1805 return StackValue.none(); 1806 } 1807 1808 public void generateFinallyBlocksIfNeeded(Type returnType) { 1809 if (hasFinallyBlocks()) { 1810 if (!Type.VOID_TYPE.equals(returnType)) { 1811 int returnValIndex = myFrameMap.enterTemp(returnType); 1812 StackValue.Local localForReturnValue = StackValue.local(returnValIndex, returnType); 1813 localForReturnValue.store(StackValue.onStack(returnType), v); 1814 doFinallyOnReturn(); 1815 localForReturnValue.put(returnType, v); 1816 myFrameMap.leaveTemp(returnType); 1817 } 1818 else { 1819 doFinallyOnReturn(); 1820 } 1821 } 1822 } 1823 1824 @Nullable 1825 private NonLocalReturnInfo getNonLocalReturnInfo(@NotNull CallableMemberDescriptor descriptor, @NotNull JetReturnExpression expression) { 1826 //call inside lambda 1827 if (DescriptorUtils.isFunctionLiteral(descriptor)) { 1828 if (expression.getLabelName() == null) { 1829 //non labeled return couldn't be local in lambda 1830 FunctionDescriptor containingFunction = 1831 BindingContextUtils.getContainingFunctionSkipFunctionLiterals(descriptor, true).getFirst(); 1832 //ROOT_LABEL to prevent clashing with existing labels 1833 return new NonLocalReturnInfo(typeMapper.mapReturnType(containingFunction), InlineCodegenUtil.ROOT_LABEL); 1834 } 1835 1836 PsiElement element = bindingContext.get(LABEL_TARGET, expression.getTargetLabel()); 1837 if (element != DescriptorToSourceUtils.getSourceFromDescriptor(context.getContextDescriptor())) { 1838 DeclarationDescriptor elementDescriptor = typeMapper.getBindingContext().get(DECLARATION_TO_DESCRIPTOR, element); 1839 assert element != null : "Expression should be not null " + expression.getText(); 1840 assert elementDescriptor != null : "Descriptor should be not null: " + element.getText(); 1841 return new NonLocalReturnInfo(typeMapper.mapReturnType((CallableDescriptor) elementDescriptor), expression.getLabelName()); 1842 } 1843 } 1844 return null; 1845 } 1846 1847 public void returnExpression(JetExpression expr) { 1848 boolean isBlockedNamedFunction = expr instanceof JetBlockExpression && expr.getParent() instanceof JetNamedFunction; 1849 1850 // If generating body for named block-bodied function, generate it as sequence of statements 1851 gen(expr, isBlockedNamedFunction ? Type.VOID_TYPE : returnType); 1852 1853 // If it does not end with return we should return something 1854 // because if we don't there can be VerifyError (specific cases with Nothing-typed expressions) 1855 if (!endsWithReturn(expr)) { 1856 markLineNumber(expr, true); 1857 1858 if (isBlockedNamedFunction && !Type.VOID_TYPE.equals(expressionType(expr))) { 1859 StackValue.none().put(returnType, v); 1860 } 1861 1862 v.areturn(returnType); 1863 } 1864 } 1865 1866 private static boolean endsWithReturn(JetElement bodyExpression) { 1867 if (bodyExpression instanceof JetBlockExpression) { 1868 List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements(); 1869 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof JetReturnExpression; 1870 } 1871 1872 return bodyExpression instanceof JetReturnExpression; 1873 } 1874 1875 @Override 1876 public StackValue visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, @NotNull StackValue receiver) { 1877 ResolvedCall<?> resolvedCall = getResolvedCall(expression, bindingContext); 1878 1879 DeclarationDescriptor descriptor; 1880 if (resolvedCall == null) { 1881 descriptor = bindingContext.get(REFERENCE_TARGET, expression); 1882 } 1883 else { 1884 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1885 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 1886 resolvedCall = call.getVariableCall(); 1887 } 1888 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1889 descriptor = resolvedCall.getResultingDescriptor(); 1890 if (descriptor instanceof FakeCallableDescriptorForObject) { 1891 descriptor = ((FakeCallableDescriptorForObject) descriptor).getReferencedDescriptor(); 1892 } 1893 } 1894 1895 assert descriptor != null : "Couldn't find descriptor for '" + expression.getText() + "'"; 1896 descriptor = descriptor.getOriginal(); 1897 1898 if (descriptor instanceof CallableMemberDescriptor) { 1899 CallableMemberDescriptor memberDescriptor = DescriptorUtils.unwrapFakeOverride((CallableMemberDescriptor) descriptor); 1900 1901 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1902 if (intrinsic != null) { 1903 Type returnType = typeMapper.mapType(memberDescriptor); 1904 return intrinsic.generate(this, returnType, expression, Collections.<JetExpression>emptyList(), receiver); 1905 } 1906 } 1907 1908 if (descriptor instanceof PropertyDescriptor) { 1909 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1910 1911 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.OBJECT$.getInstances(state.getProject()); 1912 if (!codegenExtensions.isEmpty() && resolvedCall != null) { 1913 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 1914 JetType returnType = propertyDescriptor.getReturnType(); 1915 for (ExpressionCodegenExtension extension : codegenExtensions) { 1916 if (returnType != null) { 1917 StackValue value = extension.applyProperty(receiver, resolvedCall, context); 1918 if (value != null) return value; 1919 } 1920 } 1921 } 1922 1923 boolean directToField = 1924 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; 1925 JetExpression r = getReceiverForSelector(expression); 1926 boolean isSuper = r instanceof JetSuperExpression; 1927 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1928 1929 if (directToField) { 1930 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1931 } 1932 StackValue.Property iValue = 1933 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null, receiver); 1934 1935 1936 return iValue; 1937 } 1938 1939 if (descriptor instanceof ClassDescriptor) { 1940 ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; 1941 if (isObject(classDescriptor)) { 1942 return StackValue.singleton(classDescriptor, typeMapper); 1943 } 1944 if (isEnumEntry(classDescriptor)) { 1945 DeclarationDescriptor enumClass = classDescriptor.getContainingDeclaration(); 1946 assert DescriptorUtils.isEnumClass(enumClass) : "Enum entry should be declared in enum class: " + descriptor; 1947 Type type = typeMapper.mapType((ClassDescriptor) enumClass); 1948 return StackValue.field(type, type, descriptor.getName().asString(), true, StackValue.none()); 1949 } 1950 ClassDescriptor companionObjectDescriptor = classDescriptor.getCompanionObjectDescriptor(); 1951 if (companionObjectDescriptor != null) { 1952 return StackValue.singleton(companionObjectDescriptor, typeMapper); 1953 } 1954 return StackValue.none(); 1955 } 1956 1957 StackValue localOrCaptured = findLocalOrCapturedValue(descriptor); 1958 if (localOrCaptured != null) { 1959 return localOrCaptured; 1960 } 1961 1962 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { 1963 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); 1964 Type scriptClassType = asmTypeForScriptDescriptor(bindingContext, scriptDescriptor); 1965 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; 1966 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); 1967 StackValue script = StackValue.thisOrOuter(this, scriptClass, false, false); 1968 Type fieldType = typeMapper.mapType(valueParameterDescriptor); 1969 return StackValue.field(fieldType, scriptClassType, valueParameterDescriptor.getName().getIdentifier(), false, script); 1970 } 1971 1972 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1973 } 1974 1975 @Nullable 1976 public StackValue findLocalOrCapturedValue(@NotNull DeclarationDescriptor descriptor) { 1977 int index = lookupLocalIndex(descriptor); 1978 if (index >= 0) { 1979 return stackValueForLocal(descriptor, index); 1980 } 1981 1982 if (context instanceof ConstructorContext) { 1983 return lookupCapturedValueInConstructorParameters(descriptor); 1984 } 1985 1986 return context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 1987 } 1988 1989 @Nullable 1990 private StackValue lookupCapturedValueInConstructorParameters(@NotNull DeclarationDescriptor descriptor) { 1991 StackValue parentResult = context.lookupInContext(descriptor, StackValue.LOCAL_0, state, false); 1992 if (context.closure == null || parentResult == null) return parentResult; 1993 1994 int parameterOffsetInConstructor = context.closure.getCapturedParameterOffsetInConstructor(descriptor); 1995 // when captured parameter is singleton 1996 // see compiler/testData/codegen/box/objects/objectInLocalAnonymousObject.kt (fun local() captured in A) 1997 if (parameterOffsetInConstructor == -1) return parentResult; 1998 1999 assert parentResult instanceof StackValue.Field || parentResult instanceof StackValue.FieldForSharedVar 2000 : "Part of closure should be either Field or FieldForSharedVar"; 2001 2002 if (parentResult instanceof StackValue.FieldForSharedVar) { 2003 return StackValue.shared(parameterOffsetInConstructor, parentResult.type); 2004 } 2005 2006 return StackValue.local(parameterOffsetInConstructor, parentResult.type); 2007 } 2008 2009 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 2010 if (descriptor instanceof VariableDescriptor) { 2011 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 2012 JetType outType = ((VariableDescriptor) descriptor).getType(); 2013 if (sharedVarType != null) { 2014 return StackValue.shared(index, asmType(outType)); 2015 } 2016 else { 2017 return StackValue.local(index, asmType(outType)); 2018 } 2019 } 2020 else { 2021 return StackValue.local(index, OBJECT_TYPE); 2022 } 2023 } 2024 2025 @Override 2026 public boolean lookupLocal(DeclarationDescriptor descriptor) { 2027 return lookupLocalIndex(descriptor) != -1; 2028 } 2029 2030 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 2031 return myFrameMap.getIndex(descriptor); 2032 } 2033 2034 @Nullable 2035 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 2036 PropertyGetterDescriptor getter = descriptor.getGetter(); 2037 if (getter != null) { 2038 Call call = bindingContext.get(DELEGATED_PROPERTY_CALL, getter); 2039 return call != null ? call.getExplicitReceiver().getType() : null; 2040 } 2041 return null; 2042 } 2043 2044 @NotNull 2045 public StackValue.Property intermediateValueForProperty( 2046 @NotNull PropertyDescriptor propertyDescriptor, 2047 boolean forceField, 2048 @Nullable JetSuperExpression superExpression, 2049 @NotNull StackValue receiver 2050 ) { 2051 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL, receiver); 2052 } 2053 2054 public StackValue.Property intermediateValueForProperty( 2055 @NotNull PropertyDescriptor propertyDescriptor, 2056 boolean forceField, 2057 @Nullable JetSuperExpression superExpression, 2058 @NotNull MethodKind methodKind, 2059 StackValue receiver 2060 ) { 2061 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 2062 2063 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 2064 boolean isStaticBackingField = DescriptorUtils.isStaticDeclaration(propertyDescriptor) || 2065 AsmUtil.isInstancePropertyWithStaticBackingField(propertyDescriptor); 2066 boolean isSuper = superExpression != null; 2067 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 2068 2069 JetType delegateType = getPropertyDelegateType(propertyDescriptor, bindingContext); 2070 boolean isDelegatedProperty = delegateType != null; 2071 2072 CallableMethod callableGetter = null; 2073 CallableMethod callableSetter = null; 2074 2075 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; 2076 2077 CodegenContext backingFieldContext = context.getParentContext(); 2078 boolean changeOwnerOnTypeMapping = isBackingFieldInAnotherClass; 2079 2080 if (isBackingFieldInAnotherClass && forceField) { 2081 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 2082 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 2083 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; 2084 if (!skipPropertyAccessors) { 2085 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType); 2086 changeOwnerOnTypeMapping = changeOwnerOnTypeMapping && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass); 2087 } 2088 } 2089 2090 if (!skipPropertyAccessors) { 2091 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isDelegatedProperty, context)) { 2092 callableGetter = null; 2093 } 2094 else { 2095 if (isSuper && !isInterface(containingDeclaration)) { 2096 ClassDescriptor owner = getSuperCallLabelTarget(superExpression); 2097 CodegenContext c = context.findParentContextWithDescriptor(owner); 2098 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 2099 if (c != context.getParentContext()) { 2100 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); 2101 } 2102 } 2103 2104 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 2105 2106 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 2107 if (getter != null) { 2108 callableGetter = typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); 2109 } 2110 } 2111 2112 if (propertyDescriptor.isVar()) { 2113 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 2114 if (setter != null) { 2115 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isDelegatedProperty, context)) { 2116 callableSetter = null; 2117 } 2118 else { 2119 callableSetter = typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context); 2120 } 2121 } 2122 } 2123 } 2124 2125 propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor); 2126 Type backingFieldOwner = typeMapper.mapOwner(changeOwnerOnTypeMapping ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, 2127 isCallInsideSameModuleAsDeclared(propertyDescriptor, context, state.getOutDirectory())); 2128 2129 String fieldName; 2130 if (isExtensionProperty && !isDelegatedProperty) { 2131 fieldName = null; 2132 } 2133 else if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 2134 assert backingFieldContext instanceof FieldOwnerContext 2135 : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext"; 2136 fieldName = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 2137 } 2138 else { 2139 fieldName = JvmAbi.getDefaultFieldNameForProperty(propertyDescriptor.getName(), isDelegatedProperty); 2140 } 2141 2142 return StackValue.property(propertyDescriptor, backingFieldOwner, 2143 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 2144 isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver); 2145 2146 } 2147 2148 @Override 2149 public StackValue visitCallExpression(@NotNull JetCallExpression expression, StackValue receiver) { 2150 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 2151 CallableDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); 2152 2153 if (!(funDescriptor instanceof FunctionDescriptor)) { 2154 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); 2155 } 2156 2157 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor); 2158 2159 if (funDescriptor instanceof ConstructorDescriptor) { 2160 return generateNewCall(expression, resolvedCall); 2161 } 2162 2163 if (funDescriptor.getOriginal() instanceof SamConstructorDescriptor) { 2164 JetExpression argumentExpression = bindingContext.get(SAM_CONSTRUCTOR_TO_ARGUMENT, expression); 2165 assert argumentExpression != null : "Argument expression is not saved for a SAM constructor: " + funDescriptor; 2166 return genSamInterfaceValue(argumentExpression, this); 2167 } 2168 2169 return invokeFunction(resolvedCall, receiver); 2170 } 2171 2172 @Nullable 2173 private StackValue genSamInterfaceValue( 2174 @NotNull final JetExpression expression, 2175 @NotNull final JetVisitor<StackValue, StackValue> visitor 2176 ) { 2177 final SamType samType = bindingContext.get(SAM_VALUE, expression); 2178 if (samType == null) return null; 2179 2180 if (expression instanceof JetFunctionLiteralExpression) { 2181 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samType, 2182 KotlinSyntheticClass.Kind.SAM_LAMBDA); 2183 } 2184 2185 final Type asmType = 2186 state.getSamWrapperClasses().getSamWrapperClass(samType, expression.getContainingJetFile(), getParentCodegen()); 2187 2188 return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() { 2189 @Override 2190 public Unit invoke(InstructionAdapter v) { 2191 v.anew(asmType); 2192 v.dup(); 2193 2194 Type functionType = typeMapper.mapType(samType.getKotlinFunctionType()); 2195 expression.accept(visitor, StackValue.none()).put(functionType, v); 2196 2197 Label ifNonNull = new Label(); 2198 Label afterAll = new Label(); 2199 2200 v.dup(); 2201 v.ifnonnull(ifNonNull); 2202 2203 // if null: pop function value and wrapper objects, put null 2204 v.pop(); 2205 v.pop2(); 2206 v.aconst(null); 2207 v.goTo(afterAll); 2208 2209 v.mark(ifNonNull); 2210 v.invokespecial(asmType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType), false); 2211 2212 v.mark(afterAll); 2213 return null; 2214 } 2215 }); 2216 } 2217 2218 @NotNull 2219 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) { 2220 return context.accessiblePropertyDescriptor(propertyDescriptor); 2221 } 2222 2223 @NotNull 2224 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) { 2225 return context.accessibleFunctionDescriptor(fd); 2226 } 2227 2228 @NotNull 2229 public StackValue invokeFunction(@NotNull ResolvedCall<?> resolvedCall, @NotNull StackValue receiver) { 2230 return invokeFunction(resolvedCall.getCall(), resolvedCall, receiver); 2231 } 2232 2233 @NotNull 2234 public StackValue invokeFunction(@NotNull Call call, @NotNull final ResolvedCall<?> resolvedCall, @NotNull final StackValue receiver) { 2235 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2236 return invokeFunction(call, ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(), receiver); 2237 } 2238 2239 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2240 JetSuperExpression superCallExpression = getSuperCallExpression(call); 2241 boolean superCall = superCallExpression != null; 2242 2243 if (superCall && !isInterface(fd.getContainingDeclaration())) { 2244 ClassDescriptor owner = getSuperCallLabelTarget(superCallExpression); 2245 CodegenContext c = context.findParentContextWithDescriptor(owner); 2246 assert c != null : "Couldn't find a context for a super-call: " + fd; 2247 if (c != context.getParentContext()) { 2248 fd = (FunctionDescriptor) c.getAccessor(fd); 2249 } 2250 } 2251 2252 FunctionDescriptor accessibleFunctionDescriptor = accessibleFunctionDescriptor(fd); 2253 final Callable callable = resolveToCallable(accessibleFunctionDescriptor, superCall); 2254 final Type returnType = typeMapper.mapReturnType(accessibleFunctionDescriptor); 2255 2256 if (callable instanceof CallableMethod) { 2257 return StackValue.functionCall(returnType, new Function1<InstructionAdapter, Unit>() { 2258 @Override 2259 public Unit invoke(InstructionAdapter v) { 2260 CallableMethod callableMethod = (CallableMethod) callable; 2261 invokeMethodWithArguments(callableMethod, resolvedCall, receiver); 2262 2263 StackValue.coerce(callableMethod.getReturnType(), returnType, v); 2264 return Unit.INSTANCE$; 2265 } 2266 }); 2267 } 2268 else { 2269 StackValue newReceiver = StackValue.receiver(resolvedCall, receiver, this, null); 2270 2271 List<JetExpression> args = new ArrayList<JetExpression>(); 2272 for (ValueArgument argument : call.getValueArguments()) { 2273 args.add(argument.getArgumentExpression()); 2274 } 2275 2276 return ((IntrinsicMethod) callable).generate(this, returnType, call.getCallElement(), args, newReceiver); 2277 } 2278 } 2279 2280 @Nullable 2281 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) { 2282 ReceiverValue explicitReceiver = call.getExplicitReceiver(); 2283 if (explicitReceiver instanceof ExpressionReceiver) { 2284 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression(); 2285 if (receiverExpression instanceof JetSuperExpression) { 2286 return (JetSuperExpression) receiverExpression; 2287 } 2288 } 2289 return null; 2290 } 2291 2292 // Find the first parent of the current context which corresponds to a subclass of a given class 2293 @NotNull 2294 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2295 CodegenContext c = context; 2296 while (true) { 2297 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2298 return c; 2299 } 2300 c = c.getParentContext(); 2301 assert c != null; 2302 } 2303 } 2304 2305 @NotNull 2306 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) { 2307 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2308 if (intrinsic != null) { 2309 return intrinsic; 2310 } 2311 2312 return resolveToCallableMethod(fd, superCall, context); 2313 } 2314 2315 @NotNull 2316 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) { 2317 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(fd); 2318 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, context); 2319 } 2320 2321 public void invokeMethodWithArguments( 2322 @NotNull CallableMethod callableMethod, 2323 @NotNull ResolvedCall<?> resolvedCall, 2324 @NotNull StackValue receiver 2325 ) { 2326 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2327 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2328 } 2329 2330 CallGenerator callGenerator = getOrCreateCallGenerator(resolvedCall); 2331 CallableDescriptor descriptor = resolvedCall.getResultingDescriptor(); 2332 2333 assert callGenerator == defaultCallGenerator || !tailRecursionCodegen.isTailRecursion(resolvedCall) : 2334 "Tail recursive method can't be inlined: " + descriptor; 2335 2336 ArgumentGenerator argumentGenerator = new CallBasedArgumentGenerator(this, callGenerator, descriptor.getValueParameters(), 2337 callableMethod.getValueParameterTypes()); 2338 2339 invokeMethodWithArguments(callableMethod, resolvedCall, receiver, callGenerator, argumentGenerator); 2340 } 2341 2342 public void invokeMethodWithArguments( 2343 @NotNull CallableMethod callableMethod, 2344 @NotNull ResolvedCall<?> resolvedCall, 2345 @NotNull StackValue receiver, 2346 @NotNull CallGenerator callGenerator, 2347 @NotNull ArgumentGenerator argumentGenerator 2348 ) { 2349 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2350 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2351 2352 Collection<ExpressionCodegenExtension> codegenExtensions = ExpressionCodegenExtension.OBJECT$.getInstances(state.getProject()); 2353 if (!codegenExtensions.isEmpty()) { 2354 ExpressionCodegenExtension.Context context = new ExpressionCodegenExtension.Context(typeMapper, v); 2355 for (ExpressionCodegenExtension extension : codegenExtensions) { 2356 if (extension.applyFunction(receiver, resolvedCall, context)) return; 2357 } 2358 } 2359 2360 receiver.put(receiver.type, v); 2361 } 2362 2363 callGenerator.putHiddenParams(); 2364 2365 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2366 assert valueArguments != null : "Failed to arrange value arguments by index: " + resolvedCall.getResultingDescriptor(); 2367 2368 List<Integer> masks = argumentGenerator.generate(valueArguments); 2369 2370 if (tailRecursionCodegen.isTailRecursion(resolvedCall)) { 2371 tailRecursionCodegen.generateTailRecursion(resolvedCall); 2372 return; 2373 } 2374 2375 for (int mask : masks) { 2376 callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE)); 2377 } 2378 2379 callGenerator.genCall(callableMethod, resolvedCall, !masks.isEmpty(), this); 2380 } 2381 2382 @NotNull 2383 protected CallGenerator getOrCreateCallGenerator( 2384 @NotNull CallableDescriptor descriptor, 2385 @Nullable JetElement callElement, 2386 @Nullable ReifiedTypeParameterMappings reifierTypeParameterMappings 2387 ) { 2388 if (callElement == null) return defaultCallGenerator; 2389 2390 // We should inline callable containing reified type parameters even if inline is disabled 2391 // because they may contain something to reify and straight call will probably fail at runtime 2392 boolean isInline = (state.isInlineEnabled() || DescriptorUtils.containsReifiedTypeParameters(descriptor)) && 2393 descriptor instanceof SimpleFunctionDescriptor && 2394 ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline(); 2395 2396 if (!isInline) return defaultCallGenerator; 2397 2398 SimpleFunctionDescriptor original = DescriptorUtils.unwrapFakeOverride((SimpleFunctionDescriptor) descriptor.getOriginal()); 2399 return new InlineCodegen(this, state, original, callElement, reifierTypeParameterMappings); 2400 } 2401 2402 @NotNull 2403 public CallGenerator getOrCreateCallGenerator(@NotNull FunctionDescriptor descriptor, @Nullable JetNamedFunction function) { 2404 return getOrCreateCallGenerator(descriptor, function, null); 2405 } 2406 2407 @NotNull 2408 private CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) { 2409 Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments(); 2410 ReifiedTypeParameterMappings mappings = new ReifiedTypeParameterMappings(); 2411 for (Map.Entry<TypeParameterDescriptor, JetType> entry : typeArguments.entrySet()) { 2412 TypeParameterDescriptor key = entry.getKey(); 2413 if (!key.isReified()) continue; 2414 2415 TypeParameterDescriptor parameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(entry.getValue()); 2416 if (parameterDescriptor == null) { 2417 // type is not generic 2418 BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE); 2419 Type type = typeMapper.mapTypeParameter(entry.getValue(), signatureWriter); 2420 2421 mappings.addParameterMappingToType( 2422 key.getName().getIdentifier(), 2423 type, 2424 signatureWriter.toString() 2425 ); 2426 } 2427 else { 2428 mappings.addParameterMappingToNewParameter( 2429 key.getName().getIdentifier(), 2430 parameterDescriptor.getName().getIdentifier() 2431 ); 2432 } 2433 } 2434 return getOrCreateCallGenerator( 2435 resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings 2436 ); 2437 } 2438 2439 @NotNull 2440 public StackValue generateReceiverValue(@NotNull ReceiverValue receiverValue) { 2441 if (receiverValue instanceof ClassReceiver) { 2442 ClassDescriptor receiverDescriptor = ((ClassReceiver) receiverValue).getDeclarationDescriptor(); 2443 if (DescriptorUtils.isCompanionObject(receiverDescriptor)) { 2444 CallableMemberDescriptor contextDescriptor = context.getContextDescriptor(); 2445 if (contextDescriptor instanceof FunctionDescriptor && receiverDescriptor == contextDescriptor.getContainingDeclaration()) { 2446 return StackValue.LOCAL_0; 2447 } 2448 else { 2449 return StackValue.singleton(receiverDescriptor, typeMapper); 2450 } 2451 } 2452 else { 2453 return StackValue.thisOrOuter(this, receiverDescriptor, false, false); 2454 } 2455 } 2456 else if (receiverValue instanceof ScriptReceiver) { 2457 // SCRIPT: generate script 2458 return generateScript((ScriptReceiver) receiverValue); 2459 } 2460 else if (receiverValue instanceof ExtensionReceiver) { 2461 return generateReceiver(((ExtensionReceiver) receiverValue).getDeclarationDescriptor()); 2462 } 2463 else if (receiverValue instanceof ExpressionReceiver) { 2464 return gen(((ExpressionReceiver) receiverValue).getExpression()); 2465 } 2466 else { 2467 throw new UnsupportedOperationException("Unsupported receiver value: " + receiverValue); 2468 } 2469 } 2470 2471 @Nullable 2472 private static JetExpression getReceiverForSelector(PsiElement expression) { 2473 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2474 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2475 return parent.getReceiverExpression(); 2476 } 2477 return null; 2478 } 2479 2480 @NotNull 2481 private StackValue generateReceiver(@NotNull CallableDescriptor descriptor) { 2482 return context.generateReceiver(descriptor, state, false); 2483 } 2484 2485 // SCRIPT: generate script, move to ScriptingUtil 2486 private StackValue generateScript(@NotNull ScriptReceiver receiver) { 2487 CodegenContext cur = context; 2488 StackValue result = StackValue.LOCAL_0; 2489 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2490 while (cur != null) { 2491 if (!inStartConstructorContext) { 2492 cur = getNotNullParentContextForMethod(cur); 2493 } 2494 2495 if (cur instanceof ScriptContext) { 2496 ScriptContext scriptContext = (ScriptContext) cur; 2497 2498 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2499 //TODO lazy 2500 return result; 2501 } 2502 else { 2503 Type currentScriptType = asmTypeForScriptDescriptor(bindingContext, scriptContext.getScriptDescriptor()); 2504 Type classType = asmTypeForScriptDescriptor(bindingContext, receiver.getDeclarationDescriptor()); 2505 String fieldName = scriptContext.getScriptFieldName(receiver.getDeclarationDescriptor()); 2506 return StackValue.field(classType, currentScriptType, fieldName, false, result); 2507 } 2508 } 2509 2510 result = cur.getOuterExpression(result, false); 2511 2512 if (inStartConstructorContext) { 2513 cur = getNotNullParentContextForMethod(cur); 2514 inStartConstructorContext = false; 2515 } 2516 2517 cur = cur.getParentContext(); 2518 } 2519 2520 throw new UnsupportedOperationException(); 2521 } 2522 2523 @NotNull 2524 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2525 boolean isSingleton = calleeContainingClass.getKind().isSingleton(); 2526 if (isSingleton) { 2527 if (calleeContainingClass.equals(context.getThisDescriptor()) && 2528 !AnnotationsPackage.isPlatformStaticInObjectOrClass(context.getContextDescriptor())) { 2529 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2530 } 2531 else { 2532 return StackValue.singleton(calleeContainingClass, typeMapper); 2533 } 2534 } 2535 2536 CodegenContext cur = context; 2537 Type type = asmType(calleeContainingClass.getDefaultType()); 2538 StackValue result = StackValue.local(0, type); 2539 boolean inStartConstructorContext = cur instanceof ConstructorContext; 2540 while (cur != null) { 2541 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2542 2543 if (!isSuper && thisDescriptor == calleeContainingClass) { 2544 return result; 2545 } 2546 2547 if (isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2548 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2549 } 2550 2551 //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer 2552 if (inStartConstructorContext) { 2553 result = cur.getOuterExpression(result, false); 2554 cur = getNotNullParentContextForMethod(cur); 2555 inStartConstructorContext = false; 2556 } 2557 else { 2558 cur = getNotNullParentContextForMethod(cur); 2559 result = cur.getOuterExpression(result, false); 2560 } 2561 2562 cur = cur.getParentContext(); 2563 } 2564 2565 throw new UnsupportedOperationException(); 2566 } 2567 2568 @NotNull 2569 private static CodegenContext getNotNullParentContextForMethod(CodegenContext cur) { 2570 if (cur instanceof MethodContext) { 2571 cur = cur.getParentContext(); 2572 } 2573 assert cur != null; 2574 return cur; 2575 } 2576 2577 2578 private static boolean isReceiver(PsiElement expression) { 2579 PsiElement parent = expression.getParent(); 2580 if (parent instanceof JetQualifiedExpression) { 2581 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2582 return expression == receiverExpression; 2583 } 2584 return false; 2585 } 2586 2587 public void genVarargs(@NotNull VarargValueArgument valueArgument, @NotNull JetType outType) { 2588 Type type = asmType(outType); 2589 assert type.getSort() == Type.ARRAY; 2590 Type elementType = correctElementType(type); 2591 List<ValueArgument> arguments = valueArgument.getArguments(); 2592 int size = arguments.size(); 2593 2594 boolean hasSpread = false; 2595 for (int i = 0; i != size; ++i) { 2596 if (arguments.get(i).getSpreadElement() != null) { 2597 hasSpread = true; 2598 break; 2599 } 2600 } 2601 2602 if (hasSpread) { 2603 if (size == 1) { 2604 gen(arguments.get(0).getArgumentExpression(), type); 2605 } 2606 else { 2607 String owner; 2608 String addDescriptor; 2609 String toArrayDescriptor; 2610 boolean arrayOfReferences = KotlinBuiltIns.isArray(outType); 2611 if (arrayOfReferences) { 2612 owner = "kotlin/jvm/internal/SpreadBuilder"; 2613 addDescriptor = "(Ljava/lang/Object;)V"; 2614 toArrayDescriptor = "([Ljava/lang/Object;)[Ljava/lang/Object;"; 2615 } 2616 else { 2617 String spreadBuilderClassName = AsmUtil.asmPrimitiveTypeToLangPrimitiveType(elementType).getTypeName().getIdentifier() + "SpreadBuilder"; 2618 owner = "kotlin/jvm/internal/" + spreadBuilderClassName; 2619 addDescriptor = "(" + elementType.getDescriptor() + ")V"; 2620 toArrayDescriptor = "()" + type.getDescriptor(); 2621 } 2622 v.anew(Type.getObjectType(owner)); 2623 v.dup(); 2624 v.iconst(size); 2625 v.invokespecial(owner, "<init>", "(I)V", false); 2626 for (int i = 0; i != size; ++i) { 2627 v.dup(); 2628 ValueArgument argument = arguments.get(i); 2629 if (argument.getSpreadElement() != null) { 2630 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2631 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V", false); 2632 } 2633 else { 2634 gen(argument.getArgumentExpression(), elementType); 2635 v.invokevirtual(owner, "add", addDescriptor, false); 2636 } 2637 } 2638 if (arrayOfReferences) { 2639 v.dup(); 2640 v.invokevirtual(owner, "size", "()I", false); 2641 newArrayInstruction(outType); 2642 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2643 v.checkcast(type); 2644 } 2645 else { 2646 v.invokevirtual(owner, "toArray", toArrayDescriptor, false); 2647 } 2648 } 2649 } 2650 else { 2651 v.iconst(arguments.size()); 2652 newArrayInstruction(outType); 2653 for (int i = 0; i != size; ++i) { 2654 v.dup(); 2655 StackValue rightSide = gen(arguments.get(i).getArgumentExpression()); 2656 StackValue.arrayElement(elementType, StackValue.onStack(type), StackValue.constant(i, Type.INT_TYPE)).store(rightSide, v); 2657 } 2658 } 2659 } 2660 2661 public int indexOfLocal(JetReferenceExpression lhs) { 2662 DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs); 2663 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2664 return -1; 2665 } 2666 return lookupLocalIndex(declarationDescriptor); 2667 } 2668 2669 @Override 2670 public StackValue visitClassLiteralExpression(@NotNull JetClassLiteralExpression expression, StackValue data) { 2671 checkReflectionIsAvailable(expression); 2672 2673 JetType type = bindingContext.get(EXPRESSION_TYPE, expression); 2674 assert type != null; 2675 2676 assert state.getReflectionTypes().getkClass().getTypeConstructor().equals(type.getConstructor()) 2677 : "::class expression should be type checked to a KClass: " + type; 2678 2679 ClassifierDescriptor typeArgument = KotlinPackage.single(type.getArguments()).getType().getConstructor().getDeclarationDescriptor(); 2680 assert typeArgument instanceof ClassDescriptor : "KClass argument should be a class: " + typeArgument; 2681 2682 return generateClassLiteralReference((ClassDescriptor) typeArgument); 2683 } 2684 2685 @Override 2686 public StackValue visitCallableReferenceExpression(@NotNull JetCallableReferenceExpression expression, StackValue data) { 2687 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression.getCallableReference(), bindingContext); 2688 FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression); 2689 if (functionDescriptor != null) { 2690 CallableReferenceGenerationStrategy strategy = new CallableReferenceGenerationStrategy(state, functionDescriptor, resolvedCall); 2691 return genClosure(expression, functionDescriptor, strategy, null, KotlinSyntheticClass.Kind.CALLABLE_REFERENCE_WRAPPER); 2692 } 2693 2694 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, expression); 2695 if (variableDescriptor == null) { 2696 throw new UnsupportedOperationException("Unsupported callable reference expression: " + expression.getText()); 2697 } 2698 2699 // TODO: this diagnostic should also be reported on function references once they obtain reflection 2700 checkReflectionIsAvailable(expression); 2701 2702 VariableDescriptor descriptor = (VariableDescriptor) resolvedCall.getResultingDescriptor(); 2703 2704 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); 2705 if (containingDeclaration instanceof PackageFragmentDescriptor) { 2706 return generateTopLevelPropertyReference(descriptor); 2707 } 2708 else if (containingDeclaration instanceof ClassDescriptor) { 2709 return generateMemberPropertyReference(descriptor, (ClassDescriptor) containingDeclaration); 2710 } 2711 else if (containingDeclaration instanceof ScriptDescriptor) { 2712 return generateMemberPropertyReference(descriptor, ((ScriptDescriptor) containingDeclaration).getClassDescriptor()); 2713 } 2714 else { 2715 throw new UnsupportedOperationException("Unsupported callable reference container: " + containingDeclaration); 2716 } 2717 } 2718 2719 private void checkReflectionIsAvailable(@NotNull JetExpression expression) { 2720 if (findClassAcrossModuleDependencies(state.getModule(), JvmAbi.REFLECTION_FACTORY_IMPL) == null) { 2721 state.getDiagnostics().report(ErrorsJvm.NO_REFLECTION_IN_CLASS_PATH.on(expression, expression)); 2722 } 2723 } 2724 2725 @NotNull 2726 private StackValue generateTopLevelPropertyReference(@NotNull final VariableDescriptor descriptor) { 2727 PackageFragmentDescriptor containingPackage = (PackageFragmentDescriptor) descriptor.getContainingDeclaration(); 2728 final String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(containingPackage.getFqName()); 2729 2730 final ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 2731 final Method factoryMethod; 2732 if (receiverParameter != null) { 2733 Type[] parameterTypes = new Type[] {JAVA_STRING_TYPE, K_PACKAGE_TYPE, getType(Class.class)}; 2734 factoryMethod = descriptor.isVar() 2735 ? method("mutableTopLevelExtensionProperty", K_MUTABLE_TOP_LEVEL_EXTENSION_PROPERTY_TYPE, parameterTypes) 2736 : method("topLevelExtensionProperty", K_TOP_LEVEL_EXTENSION_PROPERTY_TYPE, parameterTypes); 2737 } 2738 else { 2739 Type[] parameterTypes = new Type[] {JAVA_STRING_TYPE, K_PACKAGE_TYPE}; 2740 factoryMethod = descriptor.isVar() 2741 ? method("mutableTopLevelVariable", K_MUTABLE_TOP_LEVEL_VARIABLE_TYPE, parameterTypes) 2742 : method("topLevelVariable", K_TOP_LEVEL_VARIABLE_TYPE, parameterTypes); 2743 } 2744 2745 return StackValue.operation(factoryMethod.getReturnType(), new Function1<InstructionAdapter, Unit>() { 2746 @Override 2747 public Unit invoke(InstructionAdapter v) { 2748 v.visitLdcInsn(descriptor.getName().asString()); 2749 v.getstatic(packageClassInternalName, JvmAbi.KOTLIN_PACKAGE_FIELD_NAME, K_PACKAGE_TYPE.getDescriptor()); 2750 2751 if (receiverParameter != null) { 2752 putJavaLangClassInstance(v, typeMapper.mapType(receiverParameter)); 2753 } 2754 2755 v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false); 2756 return Unit.INSTANCE$; 2757 } 2758 }); 2759 } 2760 2761 @NotNull 2762 private StackValue generateMemberPropertyReference( 2763 @NotNull final VariableDescriptor descriptor, 2764 @NotNull final ClassDescriptor containingClass 2765 ) { 2766 final Method factoryMethod = descriptor.isVar() 2767 ? method("mutableMemberProperty", K_MUTABLE_MEMBER_PROPERTY_TYPE, JAVA_STRING_TYPE, K_CLASS_TYPE) 2768 : method("memberProperty", K_MEMBER_PROPERTY_TYPE, JAVA_STRING_TYPE, K_CLASS_TYPE); 2769 2770 return StackValue.operation(factoryMethod.getReturnType(), new Function1<InstructionAdapter, Unit>() { 2771 @Override 2772 public Unit invoke(InstructionAdapter v) { 2773 v.visitLdcInsn(descriptor.getName().asString()); 2774 StackValue receiverClass = generateClassLiteralReference(containingClass); 2775 receiverClass.put(receiverClass.type, v); 2776 v.invokestatic(REFLECTION, factoryMethod.getName(), factoryMethod.getDescriptor(), false); 2777 2778 return Unit.INSTANCE$; 2779 } 2780 }); 2781 } 2782 2783 @NotNull 2784 private StackValue generateClassLiteralReference(@NotNull final ClassDescriptor descriptor) { 2785 return StackValue.operation(K_CLASS_TYPE, new Function1<InstructionAdapter, Unit>() { 2786 @Override 2787 public Unit invoke(InstructionAdapter v) { 2788 Type classAsmType = typeMapper.mapClass(descriptor); 2789 ModuleDescriptor module = DescriptorUtils.getContainingModule(descriptor); 2790 if (descriptor instanceof JavaClassDescriptor || module == module.getBuiltIns().getBuiltInsModule()) { 2791 putJavaLangClassInstance(v, classAsmType); 2792 v.invokestatic(REFLECTION, "foreignKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false); 2793 } 2794 else { 2795 v.getstatic(classAsmType.getInternalName(), JvmAbi.KOTLIN_CLASS_FIELD_NAME, K_CLASS_TYPE.getDescriptor()); 2796 } 2797 2798 return Unit.INSTANCE$; 2799 } 2800 }); 2801 } 2802 2803 private static class CallableReferenceGenerationStrategy extends FunctionGenerationStrategy.CodegenBased<FunctionDescriptor> { 2804 private final ResolvedCall<?> resolvedCall; 2805 private final FunctionDescriptor referencedFunction; 2806 2807 public CallableReferenceGenerationStrategy( 2808 @NotNull GenerationState state, 2809 @NotNull FunctionDescriptor functionDescriptor, 2810 @NotNull ResolvedCall<?> resolvedCall 2811 ) { 2812 super(state, functionDescriptor); 2813 this.resolvedCall = resolvedCall; 2814 this.referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2815 } 2816 2817 @Override 2818 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2819 /* 2820 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2821 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2822 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2823 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2824 every argument boils down to calling LOAD with the corresponding index 2825 */ 2826 2827 JetCallExpression fakeExpression = constructFakeFunctionCall(); 2828 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2829 2830 final ReceiverValue dispatchReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getDispatchReceiverParameter()); 2831 final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getExtensionReceiverParameter()); 2832 computeAndSaveArguments(fakeArguments, codegen); 2833 2834 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2835 @NotNull 2836 @Override 2837 public ReceiverValue getExtensionReceiver() { 2838 return extensionReceiver; 2839 } 2840 2841 @NotNull 2842 @Override 2843 public ReceiverValue getDispatchReceiver() { 2844 return dispatchReceiver; 2845 } 2846 2847 @NotNull 2848 @Override 2849 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2850 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2851 for (ValueArgument argument : fakeArguments) { 2852 result.add(new ExpressionValueArgument(argument)); 2853 } 2854 return result; 2855 } 2856 }; 2857 2858 StackValue result; 2859 Type returnType = codegen.returnType; 2860 if (referencedFunction instanceof ConstructorDescriptor) { 2861 if (returnType.getSort() == Type.ARRAY) { 2862 //noinspection ConstantConditions 2863 result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType()); 2864 } 2865 else { 2866 result = codegen.generateConstructorCall(fakeResolvedCall, returnType); 2867 } 2868 } 2869 else { 2870 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2871 result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none()); 2872 } 2873 2874 InstructionAdapter v = codegen.v; 2875 result.put(returnType, v); 2876 v.areturn(returnType); 2877 } 2878 2879 @NotNull 2880 private JetCallExpression constructFakeFunctionCall() { 2881 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2882 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); iterator.hasNext(); ) { 2883 ValueParameterDescriptor descriptor = iterator.next(); 2884 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2885 if (iterator.hasNext()) { 2886 fakeFunctionCall.append(", "); 2887 } 2888 } 2889 fakeFunctionCall.append(")"); 2890 return (JetCallExpression) JetPsiFactory(state.getProject()).createExpression(fakeFunctionCall.toString()); 2891 } 2892 2893 private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) { 2894 for (ValueParameterDescriptor parameter : callableDescriptor.getValueParameters()) { 2895 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2896 Type type = state.getTypeMapper().mapType(parameter); 2897 int localIndex = codegen.myFrameMap.getIndex(parameter); 2898 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2899 } 2900 } 2901 2902 @NotNull 2903 private ReceiverValue computeAndSaveReceiver( 2904 @NotNull JvmMethodSignature signature, 2905 @NotNull ExpressionCodegen codegen, 2906 @Nullable ReceiverParameterDescriptor receiver 2907 ) { 2908 if (receiver == null) return NO_RECEIVER; 2909 2910 JetExpression receiverExpression = JetPsiFactory(state.getProject()).createExpression("callableReferenceFakeReceiver"); 2911 codegen.tempVariables.put(receiverExpression, receiverParameterStackValue(signature)); 2912 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2913 } 2914 2915 @NotNull 2916 private static StackValue.Local receiverParameterStackValue(@NotNull JvmMethodSignature signature) { 2917 // 0 is this (the callable reference class), 1 is the invoke() method's first parameter 2918 return StackValue.local(1, signature.getAsmMethod().getArgumentTypes()[0]); 2919 } 2920 } 2921 2922 @Override 2923 public StackValue visitDotQualifiedExpression(@NotNull JetDotQualifiedExpression expression, StackValue receiver) { 2924 StackValue receiverValue = StackValue.none(); //gen(expression.getReceiverExpression()) 2925 return genQualified(receiverValue, expression.getSelectorExpression()); 2926 } 2927 2928 private StackValue generateExpressionWithNullFallback(@NotNull JetExpression expression, @NotNull Label ifnull) { 2929 JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression); 2930 assert deparenthesized != null : "Unexpected empty expression"; 2931 2932 expression = deparenthesized; 2933 Type type = expressionType(expression); 2934 2935 if (expression instanceof JetSafeQualifiedExpression && !isPrimitive(type)) { 2936 return StackValue.coercion(generateSafeQualifiedExpression((JetSafeQualifiedExpression) expression, ifnull), type); 2937 } 2938 else { 2939 return genLazy(expression, type); 2940 } 2941 } 2942 2943 private StackValue generateSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, @NotNull Label ifNull) { 2944 JetExpression receiver = expression.getReceiverExpression(); 2945 JetExpression selector = expression.getSelectorExpression(); 2946 2947 Type receiverType = expressionType(receiver); 2948 StackValue receiverValue = generateExpressionWithNullFallback(receiver, ifNull); 2949 2950 //Do not optimize for primitives cause in case of safe call extension receiver should be generated before dispatch one 2951 StackValue newReceiver = new StackValue.SafeCall(receiverType, receiverValue, isPrimitive(receiverType) ? null : ifNull); 2952 return genQualified(newReceiver, selector); 2953 } 2954 2955 @Override 2956 public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) { 2957 Label ifnull = new Label(); 2958 Type type = boxType(expressionType(expression)); 2959 2960 StackValue value = generateSafeQualifiedExpression(expression, ifnull); 2961 StackValue newReceiver = StackValue.coercion(value, type); 2962 StackValue result; 2963 2964 if (!isPrimitive(expressionType(expression.getReceiverExpression()))) { 2965 result = new StackValue.SafeFallback(type, ifnull, newReceiver); 2966 } else { 2967 result = newReceiver; 2968 } 2969 2970 return result; 2971 } 2972 2973 @Override 2974 public StackValue visitBinaryExpression(@NotNull JetBinaryExpression expression, @NotNull StackValue receiver) { 2975 JetSimpleNameExpression reference = expression.getOperationReference(); 2976 IElementType opToken = reference.getReferencedNameElementType(); 2977 if (opToken == JetTokens.EQ) { 2978 return generateAssignmentExpression(expression); 2979 } 2980 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2981 return generateAugmentedAssignment(expression); 2982 } 2983 else if (opToken == JetTokens.ANDAND) { 2984 return generateBooleanAnd(expression); 2985 } 2986 else if (opToken == JetTokens.OROR) { 2987 return generateBooleanOr(expression); 2988 } 2989 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2990 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2991 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2992 } 2993 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2994 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2995 return generateComparison(expression, receiver); 2996 } 2997 else if (opToken == JetTokens.ELVIS) { 2998 return generateElvis(expression); 2999 } 3000 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 3001 return generateIn(StackValue.expression(expressionType(expression.getLeft()), expression.getLeft(), this), 3002 expression.getRight(), reference); 3003 } 3004 else { 3005 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 3006 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 3007 3008 if (descriptor instanceof ConstructorDescriptor) { 3009 return generateConstructorCall(resolvedCall, expressionType(expression)); 3010 } 3011 3012 Callable callable = resolveToCallable(descriptor, false); 3013 if (callable instanceof IntrinsicMethod) { 3014 Type returnType = typeMapper.mapType(descriptor); 3015 return ((IntrinsicMethod) callable).generate(this, returnType, expression, 3016 Arrays.asList(expression.getLeft(), expression.getRight()), receiver); 3017 } 3018 3019 return invokeFunction(resolvedCall, receiver); 3020 } 3021 } 3022 3023 private StackValue generateIn(final StackValue leftValue, JetExpression rangeExpression, final JetSimpleNameExpression operationReference) { 3024 final JetExpression deparenthesized = JetPsiUtil.deparenthesize(rangeExpression); 3025 3026 assert deparenthesized != null : "For with empty range expression"; 3027 3028 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3029 @Override 3030 public Unit invoke(InstructionAdapter v) { 3031 if (isIntRangeExpr(deparenthesized) && AsmUtil.isIntPrimitive(leftValue.type)) { 3032 genInIntRange(leftValue, (JetBinaryExpression) deparenthesized); 3033 } 3034 else { 3035 ResolvedCall<? extends CallableDescriptor> resolvedCall = getResolvedCallWithAssert(operationReference, bindingContext); 3036 StackValue result = invokeFunction(resolvedCall.getCall(), resolvedCall, StackValue.none()); 3037 result.put(result.type, v); 3038 } 3039 if (operationReference.getReferencedNameElementType() == JetTokens.NOT_IN) { 3040 genInvertBoolean(v); 3041 } 3042 return null; 3043 } 3044 }); 3045 } 3046 3047 private void genInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression) { 3048 v.iconst(1); 3049 // 1 3050 leftValue.put(Type.INT_TYPE, v); 3051 // 1 l 3052 v.dup2(); 3053 // 1 l 1 l 3054 3055 //noinspection ConstantConditions 3056 gen(rangeExpression.getLeft(), Type.INT_TYPE); 3057 // 1 l 1 l r 3058 Label lok = new Label(); 3059 v.ificmpge(lok); 3060 // 1 l 1 3061 v.pop(); 3062 v.iconst(0); 3063 v.mark(lok); 3064 // 1 l c 3065 v.dupX2(); 3066 // c 1 l c 3067 v.pop(); 3068 // c 1 l 3069 3070 gen(rangeExpression.getRight(), Type.INT_TYPE); 3071 // c 1 l r 3072 Label rok = new Label(); 3073 v.ificmple(rok); 3074 // c 1 3075 v.pop(); 3076 v.iconst(0); 3077 v.mark(rok); 3078 // c c 3079 3080 v.and(Type.INT_TYPE); 3081 } 3082 3083 private StackValue generateBooleanAnd(final JetBinaryExpression expression) { 3084 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3085 @Override 3086 public Unit invoke(InstructionAdapter v) { 3087 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 3088 Label ifFalse = new Label(); 3089 v.ifeq(ifFalse); 3090 gen(expression.getRight(), Type.BOOLEAN_TYPE); 3091 Label end = new Label(); 3092 v.goTo(end); 3093 v.mark(ifFalse); 3094 v.iconst(0); 3095 v.mark(end); 3096 return Unit.INSTANCE$; 3097 } 3098 }); 3099 } 3100 3101 private StackValue generateBooleanOr(final JetBinaryExpression expression) { 3102 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3103 @Override 3104 public Unit invoke(InstructionAdapter v) { 3105 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 3106 Label ifTrue = new Label(); 3107 v.ifne(ifTrue); 3108 gen(expression.getRight(), Type.BOOLEAN_TYPE); 3109 Label end = new Label(); 3110 v.goTo(end); 3111 v.mark(ifTrue); 3112 v.iconst(1); 3113 v.mark(end); 3114 return Unit.INSTANCE$; 3115 } 3116 }); 3117 } 3118 3119 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 3120 Type leftType = expressionType(left); 3121 Type rightType = expressionType(right); 3122 3123 if (JetPsiUtil.isNullConstant(left)) { 3124 return genCmpWithNull(right, rightType, opToken); 3125 } 3126 3127 if (JetPsiUtil.isNullConstant(right)) { 3128 return genCmpWithNull(left, leftType, opToken); 3129 } 3130 3131 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 3132 return genCmpWithZero(right, rightType, opToken); 3133 } 3134 3135 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 3136 return genCmpWithZero(left, leftType, opToken); 3137 } 3138 3139 if (isPrimitive(leftType) != isPrimitive(rightType)) { 3140 leftType = boxType(leftType); 3141 rightType = boxType(rightType); 3142 } 3143 3144 StackValue leftValue = genLazy(left, leftType); 3145 StackValue rightValue = genLazy(right, rightType); 3146 3147 if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 3148 // TODO: always casting to the type of the left operand in case of primitives looks wrong 3149 Type operandType = isPrimitive(leftType) ? leftType : OBJECT_TYPE; 3150 return StackValue.cmp(opToken, operandType, leftValue, rightValue); 3151 } 3152 3153 return genEqualsForExpressionsOnStack(opToken, leftValue, rightValue); 3154 } 3155 3156 private boolean isIntZero(JetExpression expr, Type exprType) { 3157 CompileTimeConstant<?> exprValue = getCompileTimeConstant(expr, bindingContext); 3158 return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue()); 3159 } 3160 3161 private StackValue genCmpWithZero(final JetExpression exp, final Type expType, final IElementType opToken) { 3162 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3163 @Override 3164 public Unit invoke(InstructionAdapter v) { 3165 gen(exp, expType); 3166 Label trueLabel = new Label(); 3167 Label afterLabel = new Label(); 3168 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 3169 v.ifeq(trueLabel); 3170 } 3171 else { 3172 v.ifne(trueLabel); 3173 } 3174 3175 v.iconst(0); 3176 v.goTo(afterLabel); 3177 3178 v.mark(trueLabel); 3179 v.iconst(1); 3180 3181 v.mark(afterLabel); 3182 return Unit.INSTANCE$; 3183 } 3184 }); 3185 } 3186 3187 private StackValue genCmpWithNull(final JetExpression exp, final Type expType, final IElementType opToken) { 3188 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3189 @Override 3190 public Unit invoke(InstructionAdapter v) { 3191 gen(exp, boxType(expType)); 3192 Label trueLabel = new Label(); 3193 Label afterLabel = new Label(); 3194 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 3195 v.ifnull(trueLabel); 3196 } 3197 else { 3198 v.ifnonnull(trueLabel); 3199 } 3200 3201 v.iconst(0); 3202 v.goTo(afterLabel); 3203 3204 v.mark(trueLabel); 3205 v.iconst(1); 3206 3207 v.mark(afterLabel); 3208 3209 return Unit.INSTANCE$; 3210 } 3211 }); 3212 } 3213 3214 private StackValue generateElvis(@NotNull final JetBinaryExpression expression) { 3215 JetExpression left = expression.getLeft(); 3216 3217 final Type exprType = expressionType(expression); 3218 final Type leftType = expressionType(left); 3219 3220 final Label ifNull = new Label(); 3221 3222 3223 assert left != null : "left expression in elvis should be not null: " + expression.getText(); 3224 final StackValue value = generateExpressionWithNullFallback(left, ifNull); 3225 3226 if (isPrimitive(leftType)) { 3227 return value; 3228 } 3229 3230 return StackValue.operation(exprType, new Function1<InstructionAdapter, Unit>() { 3231 @Override 3232 public Unit invoke(InstructionAdapter v) { 3233 value.put(value.type, v); 3234 v.dup(); 3235 3236 v.ifnull(ifNull); 3237 StackValue.onStack(leftType).put(exprType, v); 3238 3239 Label end = new Label(); 3240 v.goTo(end); 3241 3242 v.mark(ifNull); 3243 v.pop(); 3244 gen(expression.getRight(), exprType); 3245 v.mark(end); 3246 return null; 3247 } 3248 }); 3249 } 3250 3251 private StackValue generateComparison(JetBinaryExpression expression, StackValue receiver) { 3252 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 3253 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 3254 3255 JetExpression left = expression.getLeft(); 3256 JetExpression right = expression.getRight(); 3257 Callable callable = resolveToCallable(descriptor, false); 3258 3259 Type type; 3260 StackValue leftValue; 3261 StackValue rightValue; 3262 if (callable instanceof IntrinsicMethod) { 3263 // Compare two primitive values 3264 type = comparisonOperandType(expressionType(left), expressionType(right)); 3265 leftValue = gen(left); 3266 rightValue = gen(right); 3267 } 3268 else { 3269 type = Type.INT_TYPE; 3270 leftValue = invokeFunction(resolvedCall, receiver); 3271 rightValue = StackValue.constant(0, type); 3272 } 3273 return StackValue.cmp(expression.getOperationToken(), type, leftValue, rightValue); 3274 } 3275 3276 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 3277 StackValue stackValue = gen(expression.getLeft()); 3278 JetExpression right = expression.getRight(); 3279 assert right != null : expression.getText(); 3280 stackValue.store(gen(right), v); 3281 return StackValue.none(); 3282 } 3283 3284 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 3285 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 3286 FunctionDescriptor descriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 3287 Callable callable = resolveToCallable(descriptor, false); 3288 JetExpression lhs = expression.getLeft(); 3289 Type lhsType = expressionType(lhs); 3290 3291 boolean keepReturnValue; 3292 if (Boolean.TRUE.equals(bindingContext.get(VARIABLE_REASSIGNMENT, expression))) { 3293 if (callable instanceof IntrinsicMethod) { 3294 StackValue value = gen(lhs); // receiver 3295 value = StackValue.complexWriteReadReceiver(value); 3296 3297 value.put(lhsType, v); // receiver lhs 3298 Type returnType = typeMapper.mapType(descriptor); 3299 StackValue rightSide = ((IntrinsicMethod) callable).generate(this, returnType, expression, 3300 Collections.singletonList(expression.getRight()), StackValue.onStack(lhsType)); 3301 value.store(rightSide, v, true); 3302 return StackValue.none(); 3303 } 3304 else { 3305 keepReturnValue = true; 3306 } 3307 } 3308 else { 3309 keepReturnValue = !KotlinBuiltIns.getInstance().getUnitType().equals(descriptor.getReturnType()); 3310 } 3311 3312 callAugAssignMethod(expression, resolvedCall, (CallableMethod) callable, lhsType, keepReturnValue); 3313 3314 return StackValue.none(); 3315 } 3316 3317 private void callAugAssignMethod( 3318 @NotNull JetBinaryExpression expression, 3319 @NotNull ResolvedCall<?> resolvedCall, 3320 @NotNull CallableMethod callable, 3321 @NotNull Type lhsType, 3322 boolean keepReturnValue 3323 ) { 3324 StackValue value = gen(expression.getLeft()); 3325 if (keepReturnValue) { 3326 value = StackValue.complexWriteReadReceiver(value); 3327 //value.putWriteReadReceiver(v); 3328 } 3329 value.put(lhsType, v); 3330 StackValue receiver = StackValue.onStack(lhsType); 3331 3332 invokeMethodWithArguments(callable, resolvedCall, receiver); 3333 3334 if (keepReturnValue) { 3335 value.store(StackValue.onStack(callable.getReturnType()), v, true); 3336 } 3337 } 3338 3339 public void invokeAppend(JetExpression expr) { 3340 if (expr instanceof JetBinaryExpression) { 3341 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 3342 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 3343 JetExpression left = binaryExpression.getLeft(); 3344 JetExpression right = binaryExpression.getRight(); 3345 Type leftType = expressionType(left); 3346 3347 if (leftType.equals(JAVA_STRING_TYPE)) { 3348 invokeAppend(left); 3349 invokeAppend(right); 3350 return; 3351 } 3352 } 3353 } 3354 Type exprType = expressionType(expr); 3355 gen(expr, exprType); 3356 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 3357 } 3358 3359 @Nullable 3360 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 3361 if (expression.getParent() instanceof JetLabeledExpression) { 3362 return ((JetLabeledExpression) expression.getParent()).getTargetLabel(); 3363 } 3364 return null; 3365 } 3366 3367 @Override 3368 public StackValue visitLabeledExpression( 3369 @NotNull JetLabeledExpression expression, StackValue receiver 3370 ) { 3371 return genQualified(receiver, expression.getBaseExpression()); 3372 } 3373 3374 @Override 3375 public StackValue visitPrefixExpression(@NotNull JetPrefixExpression expression, @NotNull StackValue receiver) { 3376 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3377 ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 3378 CallableDescriptor op = resolvedCall.getResultingDescriptor(); 3379 3380 assert op instanceof FunctionDescriptor || originalOperation == null : String.valueOf(op); 3381 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3382 if (callable instanceof IntrinsicMethod) { 3383 Type returnType = typeMapper.mapType(op); 3384 return ((IntrinsicMethod) callable).generate(this, returnType, expression, 3385 Collections.singletonList(expression.getBaseExpression()), receiver); 3386 } 3387 3388 DeclarationDescriptor cls = op.getContainingDeclaration(); 3389 3390 if (isPrimitiveNumberClassDescriptor(cls) || !(originalOperation.getName().asString().equals("inc") || originalOperation.getName().asString().equals("dec"))) { 3391 return invokeFunction(resolvedCall, receiver); 3392 } 3393 3394 Type type = expressionType(expression.getBaseExpression()); 3395 StackValue value = gen(expression.getBaseExpression()); 3396 return StackValue.preIncrement(type, value, -1, callable, resolvedCall, this); 3397 } 3398 3399 @Override 3400 public StackValue visitPostfixExpression(@NotNull final JetPostfixExpression expression, StackValue receiver) { 3401 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 3402 final StackValue base = genQualified(receiver, expression.getBaseExpression()); 3403 if (isPrimitive(base.type)) { 3404 return base; 3405 } else { 3406 return StackValue.operation(base.type, new Function1<InstructionAdapter, Unit>() { 3407 @Override 3408 public Unit invoke(InstructionAdapter v) { 3409 base.put(base.type, v); 3410 v.dup(); 3411 Label ok = new Label(); 3412 v.ifnonnull(ok); 3413 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwNpe", "()V", false); 3414 v.mark(ok); 3415 return null; 3416 } 3417 }); 3418 } 3419 } 3420 3421 DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference()); 3422 String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null; 3423 final ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(expression, bindingContext); 3424 DeclarationDescriptor op = resolvedCall.getResultingDescriptor(); 3425 if (!(op instanceof FunctionDescriptor) || originalOperation == null) { 3426 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + originalOperationName + " " + op); 3427 } 3428 3429 3430 final Type asmResultType = expressionType(expression); 3431 final Type asmBaseType = expressionType(expression.getBaseExpression()); 3432 3433 DeclarationDescriptor cls = op.getContainingDeclaration(); 3434 3435 final int increment; 3436 if (originalOperationName.equals("inc")) { 3437 increment = 1; 3438 } 3439 else if (originalOperationName.equals("dec")) { 3440 increment = -1; 3441 } 3442 else { 3443 throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op); 3444 } 3445 3446 final boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls); 3447 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3448 JetExpression operand = expression.getBaseExpression(); 3449 if (operand instanceof JetReferenceExpression && asmResultType == Type.INT_TYPE) { 3450 int index = indexOfLocal((JetReferenceExpression) operand); 3451 if (index >= 0) { 3452 return StackValue.postIncrement(index, increment); 3453 } 3454 } 3455 } 3456 3457 return StackValue.operation(asmResultType, new Function1<InstructionAdapter, Unit>() { 3458 @Override 3459 public Unit invoke(InstructionAdapter v) { 3460 StackValue value = gen(expression.getBaseExpression()); 3461 value = StackValue.complexWriteReadReceiver(value); 3462 3463 Type type = expressionType(expression.getBaseExpression()); 3464 value.put(type, v); // old value 3465 3466 value.dup(v, true); 3467 3468 Type storeType; 3469 if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) { 3470 genIncrement(asmResultType, increment, v); 3471 storeType = type; 3472 } 3473 else { 3474 StackValue result = invokeFunction(resolvedCall, StackValue.onStack(type)); 3475 result.put(result.type, v); 3476 storeType = result.type; 3477 } 3478 3479 value.store(StackValue.onStack(storeType), v, true); 3480 return Unit.INSTANCE$; 3481 } 3482 }); 3483 } 3484 3485 @Override 3486 public StackValue visitProperty(@NotNull JetProperty property, StackValue receiver) { 3487 JetExpression initializer = property.getInitializer(); 3488 if (initializer == null) { 3489 return StackValue.none(); 3490 } 3491 initializeLocalVariable(property, gen(initializer)); 3492 return StackValue.none(); 3493 } 3494 3495 @Override 3496 public StackValue visitMultiDeclaration(@NotNull JetMultiDeclaration multiDeclaration, StackValue receiver) { 3497 JetExpression initializer = multiDeclaration.getInitializer(); 3498 if (initializer == null) return StackValue.none(); 3499 3500 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3501 assert initializerType != null; 3502 3503 Type initializerAsmType = asmType(initializerType); 3504 3505 TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3506 3507 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3508 3509 gen(initializer, initializerAsmType); 3510 v.store(tempVarIndex, initializerAsmType); 3511 StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3512 3513 for (JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3514 ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(COMPONENT_RESOLVED_CALL, variableDeclaration); 3515 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3516 Call call = makeFakeCall(initializerAsReceiver); 3517 initializeLocalVariable(variableDeclaration, invokeFunction(call, resolvedCall, local)); 3518 } 3519 3520 if (initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3521 v.aconst(null); 3522 v.store(tempVarIndex, initializerAsmType); 3523 } 3524 myFrameMap.leaveTemp(initializerAsmType); 3525 3526 return StackValue.none(); 3527 } 3528 3529 private void initializeLocalVariable( 3530 @NotNull JetVariableDeclaration variableDeclaration, 3531 @NotNull StackValue initializer 3532 ) { 3533 VariableDescriptor variableDescriptor = bindingContext.get(VARIABLE, variableDeclaration); 3534 3535 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3536 return; 3537 } 3538 int index = lookupLocalIndex(variableDescriptor); 3539 3540 if (index < 0) { 3541 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3542 } 3543 3544 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3545 assert variableDescriptor != null; 3546 3547 Type varType = asmType(variableDescriptor.getType()); 3548 3549 StackValue storeTo; 3550 // SCRIPT: Variable at the top of the script is generated as field 3551 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3552 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3553 assert scriptPsi != null; 3554 Type scriptClassType = asmTypeForScriptPsi(bindingContext, scriptPsi); 3555 storeTo = StackValue.field(varType, scriptClassType, variableDeclaration.getName(), false, StackValue.LOCAL_0); 3556 } 3557 else if (sharedVarType == null) { 3558 storeTo = StackValue.local(index, varType); 3559 } 3560 else { 3561 storeTo = StackValue.shared(index, varType); 3562 } 3563 3564 storeTo.store(initializer, v); 3565 } 3566 3567 @NotNull 3568 private StackValue generateNewCall(@NotNull JetCallExpression expression, @NotNull ResolvedCall<?> resolvedCall) { 3569 Type type = expressionType(expression); 3570 if (type.getSort() == Type.ARRAY) { 3571 return generateNewArray(expression); 3572 } 3573 3574 return generateConstructorCall(resolvedCall, type); 3575 } 3576 3577 @NotNull 3578 private StackValue generateConstructorCall(@NotNull final ResolvedCall<?> resolvedCall, @NotNull final Type objectType) { 3579 return StackValue.functionCall(objectType, new Function1<InstructionAdapter, Unit>() { 3580 @Override 3581 public Unit invoke(InstructionAdapter v) { 3582 v.anew(objectType); 3583 v.dup(); 3584 3585 ConstructorDescriptor constructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3586 3587 ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter(); 3588 if (dispatchReceiver != null) { 3589 Type receiverType = typeMapper.mapType(dispatchReceiver.getType()); 3590 generateReceiverValue(resolvedCall.getDispatchReceiver()).put(receiverType, v); 3591 } 3592 3593 // Resolved call to local class constructor doesn't have dispatchReceiver, so we need to generate closure on stack 3594 // See StackValue.receiver for more info 3595 pushClosureOnStack(constructor.getContainingDeclaration(), dispatchReceiver == null, defaultCallGenerator); 3596 3597 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil.getOriginalIfSamAdapter(constructor); 3598 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructor : originalOfSamAdapter); 3599 invokeMethodWithArguments(method, resolvedCall, StackValue.none()); 3600 3601 return Unit.INSTANCE$; 3602 } 3603 }); 3604 } 3605 3606 public StackValue generateNewArray(@NotNull JetCallExpression expression) { 3607 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3608 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3609 3610 return generateNewArray(expression, arrayType); 3611 } 3612 3613 private StackValue generateNewArray(@NotNull JetCallExpression expression, @NotNull final JetType arrayType) { 3614 assert expression.getValueArguments().size() == 1 : "Size argument expected"; 3615 3616 final JetExpression sizeExpression = expression.getValueArguments().get(0).getArgumentExpression(); 3617 Type type = typeMapper.mapType(arrayType); 3618 3619 return StackValue.operation(type, new Function1<InstructionAdapter, Unit>() { 3620 @Override 3621 public Unit invoke(InstructionAdapter v) { 3622 gen(sizeExpression, Type.INT_TYPE); 3623 newArrayInstruction(arrayType); 3624 return Unit.INSTANCE$; 3625 } 3626 }); 3627 } 3628 3629 public void newArrayInstruction(@NotNull JetType arrayType) { 3630 if (KotlinBuiltIns.isArray(arrayType)) { 3631 JetType elementJetType = arrayType.getArguments().get(0).getType(); 3632 putReifierMarkerIfTypeIsReifiedParameter( 3633 elementJetType, 3634 ReifiedTypeInliner.NEW_ARRAY_MARKER_METHOD_NAME 3635 ); 3636 v.newarray(boxType(asmType(elementJetType))); 3637 } 3638 else { 3639 Type type = typeMapper.mapType(arrayType); 3640 v.newarray(correctElementType(type)); 3641 } 3642 } 3643 3644 @Override 3645 public StackValue visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, StackValue receiver) { 3646 JetExpression array = expression.getArrayExpression(); 3647 JetType type = bindingContext.get(EXPRESSION_TYPE, array); 3648 Type arrayType = expressionType(array); 3649 List<JetExpression> indices = expression.getIndexExpressions(); 3650 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(REFERENCE_TARGET, expression); 3651 assert operationDescriptor != null; 3652 if (arrayType.getSort() == Type.ARRAY && 3653 indices.size() == 1 && 3654 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3655 assert type != null; 3656 Type elementType; 3657 if (KotlinBuiltIns.isArray(type)) { 3658 JetType jetElementType = type.getArguments().get(0).getType(); 3659 elementType = boxType(asmType(jetElementType)); 3660 } 3661 else { 3662 elementType = correctElementType(arrayType); 3663 } 3664 StackValue arrayValue = gen(array); 3665 StackValue index = genLazy(indices.get(0), Type.INT_TYPE); 3666 3667 return StackValue.arrayElement(elementType, arrayValue, index); 3668 } 3669 else { 3670 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression); 3671 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(INDEXED_LVALUE_GET, expression); 3672 3673 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3674 3675 3676 Callable callable = resolveToCallable(operationDescriptor, false); 3677 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getAsmMethod(); 3678 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3679 3680 StackValue collectionElementReceiver = 3681 createCollectionElementReceiver(expression, receiver, array, arrayType, operationDescriptor, isGetter, resolvedGetCall, resolvedSetCall, 3682 callable, 3683 argumentTypes); 3684 3685 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3686 return StackValue.collectionElement(collectionElementReceiver, elementType, resolvedGetCall, resolvedSetCall, this, state); 3687 } 3688 } 3689 3690 private StackValue createCollectionElementReceiver( 3691 JetArrayAccessExpression expression, 3692 StackValue receiver, 3693 JetExpression array, 3694 Type arrayType, 3695 FunctionDescriptor operationDescriptor, 3696 boolean isGetter, 3697 ResolvedCall<FunctionDescriptor> resolvedGetCall, 3698 ResolvedCall<FunctionDescriptor> resolvedSetCall, 3699 Callable callable, 3700 Type[] argumentTypes 3701 ) { 3702 3703 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3704 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3705 3706 if (callable instanceof CallableMethod) { 3707 CallableMethod callableMethod = (CallableMethod) callable; 3708 ArgumentGenerator argumentGenerator = 3709 new CallBasedArgumentGenerator(this, defaultCallGenerator, 3710 resolvedCall.getResultingDescriptor().getValueParameters(), 3711 callableMethod.getValueParameterTypes()); 3712 3713 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 3714 assert valueArguments != null : "Failed to arrange value arguments by index: " + operationDescriptor; 3715 3716 if (!isGetter) { 3717 assert valueArguments.size() >= 2 : "Setter call should have at least 2 arguments: " + operationDescriptor; 3718 // Skip generation of the right hand side of an indexed assignment, which is the last value argument 3719 valueArguments.remove(valueArguments.size() - 1); 3720 } 3721 3722 return new StackValue.CollectionElementReceiver(callable, receiver, resolvedGetCall, resolvedSetCall, isGetter, this, 3723 argumentGenerator, valueArguments, array, arrayType, expression, argumentTypes); 3724 } 3725 else { 3726 return new StackValue.CollectionElementReceiver(callable, receiver, resolvedGetCall, resolvedSetCall, isGetter, this, 3727 null, null, array, arrayType, expression, argumentTypes); 3728 } 3729 } 3730 3731 @Override 3732 public StackValue visitThrowExpression(@NotNull JetThrowExpression expression, StackValue receiver) { 3733 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3734 v.athrow(); 3735 return StackValue.none(); 3736 } 3737 3738 @Override 3739 public StackValue visitThisExpression(@NotNull JetThisExpression expression, StackValue receiver) { 3740 DeclarationDescriptor descriptor = bindingContext.get(REFERENCE_TARGET, expression.getInstanceReference()); 3741 if (descriptor instanceof ClassDescriptor) { 3742 //TODO rewrite with context.lookupInContext() 3743 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false, true); 3744 } 3745 if (descriptor instanceof CallableDescriptor) { 3746 return generateReceiver((CallableDescriptor) descriptor); 3747 } 3748 throw new UnsupportedOperationException("Neither this nor receiver: " + descriptor); 3749 } 3750 3751 @Override 3752 public StackValue visitTryExpression(@NotNull JetTryExpression expression, StackValue receiver) { 3753 return generateTryExpression(expression, false); 3754 } 3755 3756 public StackValue generateTryExpression(final JetTryExpression expression, final boolean isStatement) { 3757 /* 3758 The "returned" value of try expression with no finally is either the last expression in the try block or the last expression in the catch block 3759 (or blocks). 3760 */ 3761 3762 JetType jetType = bindingContext.get(EXPRESSION_TYPE, expression); 3763 assert jetType != null; 3764 final Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3765 3766 return StackValue.operation(expectedAsmType, new Function1<InstructionAdapter, Unit>() { 3767 @Override 3768 public Unit invoke(InstructionAdapter v) { 3769 3770 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3771 FinallyBlockStackElement finallyBlockStackElement = null; 3772 if (finallyBlock != null) { 3773 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3774 blockStackElements.push(finallyBlockStackElement); 3775 } 3776 3777 3778 Label tryStart = new Label(); 3779 v.mark(tryStart); 3780 v.nop(); // prevent verify error on empty try 3781 3782 gen(expression.getTryBlock(), expectedAsmType); 3783 3784 int savedValue = -1; 3785 if (!isStatement) { 3786 savedValue = myFrameMap.enterTemp(expectedAsmType); 3787 v.store(savedValue, expectedAsmType); 3788 } 3789 3790 Label tryEnd = new Label(); 3791 v.mark(tryEnd); 3792 3793 //do it before finally block generation 3794 List<Label> tryBlockRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, tryEnd); 3795 3796 Label end = new Label(); 3797 3798 genFinallyBlockOrGoto(finallyBlockStackElement, end); 3799 3800 List<JetCatchClause> clauses = expression.getCatchClauses(); 3801 for (int i = 0, size = clauses.size(); i < size; i++) { 3802 JetCatchClause clause = clauses.get(i); 3803 3804 Label clauseStart = new Label(); 3805 v.mark(clauseStart); 3806 3807 VariableDescriptor descriptor = bindingContext.get(VALUE_PARAMETER, clause.getCatchParameter()); 3808 assert descriptor != null; 3809 Type descriptorType = asmType(descriptor.getType()); 3810 myFrameMap.enter(descriptor, descriptorType); 3811 int index = lookupLocalIndex(descriptor); 3812 v.store(index, descriptorType); 3813 3814 gen(clause.getCatchBody(), expectedAsmType); 3815 3816 if (!isStatement) { 3817 v.store(savedValue, expectedAsmType); 3818 } 3819 3820 myFrameMap.leave(descriptor); 3821 3822 Label clauseEnd = new Label(); 3823 v.mark(clauseEnd); 3824 3825 v.visitLocalVariable(descriptor.getName().asString(), descriptorType.getDescriptor(), null, clauseStart, clauseEnd, 3826 index); 3827 3828 genFinallyBlockOrGoto(finallyBlockStackElement, i != size - 1 || finallyBlock != null ? end : null); 3829 3830 generateExceptionTable(clauseStart, tryBlockRegions, descriptorType.getInternalName()); 3831 } 3832 3833 3834 //for default catch clause 3835 if (finallyBlock != null) { 3836 Label defaultCatchStart = new Label(); 3837 v.mark(defaultCatchStart); 3838 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3839 v.store(savedException, JAVA_THROWABLE_TYPE); 3840 Label defaultCatchEnd = new Label(); 3841 v.mark(defaultCatchEnd); 3842 3843 //do it before finally block generation 3844 //javac also generates entry in exception table for default catch clause too!!!! so defaultCatchEnd as end parameter 3845 List<Label> defaultCatchRegions = getCurrentCatchIntervals(finallyBlockStackElement, tryStart, defaultCatchEnd); 3846 3847 3848 genFinallyBlockOrGoto(finallyBlockStackElement, null); 3849 3850 v.load(savedException, JAVA_THROWABLE_TYPE); 3851 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3852 3853 v.athrow(); 3854 3855 generateExceptionTable(defaultCatchStart, defaultCatchRegions, null); 3856 } 3857 3858 markLineNumber(expression, isStatement); 3859 v.mark(end); 3860 3861 if (!isStatement) { 3862 v.load(savedValue, expectedAsmType); 3863 myFrameMap.leaveTemp(expectedAsmType); 3864 } 3865 3866 if (finallyBlock != null) { 3867 blockStackElements.pop(); 3868 } 3869 return Unit.INSTANCE$; 3870 } 3871 }); 3872 } 3873 3874 private void generateExceptionTable(@NotNull Label catchStart, @NotNull List<Label> catchedRegions, @Nullable String exception) { 3875 for (int i = 0; i < catchedRegions.size(); i += 2) { 3876 Label startRegion = catchedRegions.get(i); 3877 Label endRegion = catchedRegions.get(i+1); 3878 v.visitTryCatchBlock(startRegion, endRegion, catchStart, exception); 3879 } 3880 } 3881 3882 @NotNull 3883 private static List<Label> getCurrentCatchIntervals( 3884 @Nullable FinallyBlockStackElement finallyBlockStackElement, 3885 @NotNull Label blockStart, 3886 @NotNull Label blockEnd 3887 ) { 3888 List<Label> gapsInBlock = 3889 finallyBlockStackElement != null ? new ArrayList<Label>(finallyBlockStackElement.gaps) : Collections.<Label>emptyList(); 3890 assert gapsInBlock.size() % 2 == 0; 3891 List<Label> blockRegions = new ArrayList<Label>(gapsInBlock.size() + 2); 3892 blockRegions.add(blockStart); 3893 blockRegions.addAll(gapsInBlock); 3894 blockRegions.add(blockEnd); 3895 return blockRegions; 3896 } 3897 3898 @Override 3899 public StackValue visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3900 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3901 final IElementType opToken = operationSign.getReferencedNameElementType(); 3902 if (opToken == JetTokens.COLON) { 3903 return gen(expression.getLeft()); 3904 } 3905 else { 3906 JetTypeReference typeReference = expression.getRight(); 3907 final JetType rightType = bindingContext.get(TYPE, typeReference); 3908 assert rightType != null; 3909 3910 final Type rightTypeAsm = boxType(asmType(rightType)); 3911 final JetExpression left = expression.getLeft(); 3912 3913 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3914 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3915 final StackValue value = genQualified(receiver, left); 3916 3917 return StackValue.operation(rightTypeAsm, new Function1<InstructionAdapter, Unit>() { 3918 @Override 3919 public Unit invoke(InstructionAdapter v) { 3920 value.put(boxType(value.type), v); 3921 3922 if (opToken != JetTokens.AS_SAFE) { 3923 if (!TypeUtils.isNullableType(rightType)) { 3924 v.dup(); 3925 Label nonnull = new Label(); 3926 v.ifnonnull(nonnull); 3927 JetType leftType = bindingContext.get(EXPRESSION_TYPE, left); 3928 assert leftType != null; 3929 genThrow(v, "kotlin/TypeCastException", DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(leftType) + 3930 " cannot be cast to " + 3931 DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(rightType)); 3932 v.mark(nonnull); 3933 } 3934 } 3935 else if (value.type == Type.VOID_TYPE) { 3936 v.aconst(null); 3937 } 3938 else { 3939 v.dup(); 3940 generateInstanceOfInstruction(rightType); 3941 Label ok = new Label(); 3942 v.ifne(ok); 3943 v.pop(); 3944 v.aconst(null); 3945 v.mark(ok); 3946 } 3947 3948 generateCheckCastInstruction(rightType); 3949 return Unit.INSTANCE$; 3950 } 3951 }); 3952 } 3953 else { 3954 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3955 } 3956 } 3957 } 3958 3959 @Override 3960 public StackValue visitIsExpression(@NotNull JetIsExpression expression, StackValue receiver) { 3961 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3962 return generateIsCheck(match, expression.getTypeReference(), expression.isNegated()); 3963 } 3964 3965 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3966 if (expressionToMatch != null) { 3967 Type subjectType = expressionToMatch.type; 3968 markStartLineNumber(patternExpression); 3969 JetType condJetType = bindingContext.get(EXPRESSION_TYPE, patternExpression); 3970 Type condType; 3971 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3972 assert condJetType != null; 3973 condType = asmType(condJetType); 3974 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3975 subjectType = boxType(subjectType); 3976 } 3977 } 3978 else { 3979 condType = OBJECT_TYPE; 3980 } 3981 StackValue condition = genLazy(patternExpression, condType); 3982 return genEqualsForExpressionsOnStack(JetTokens.EQEQ, StackValue.coercion(expressionToMatch, subjectType), condition); 3983 } 3984 else { 3985 return gen(patternExpression); 3986 } 3987 } 3988 3989 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3990 JetType jetType = bindingContext.get(TYPE, typeReference); 3991 markStartLineNumber(typeReference); 3992 StackValue value = generateInstanceOf(expressionToMatch, jetType, false); 3993 return negated ? StackValue.not(value) : value; 3994 } 3995 3996 private StackValue generateInstanceOf(final StackValue expressionToGen, final JetType jetType, final boolean leaveExpressionOnStack) { 3997 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 3998 @Override 3999 public Unit invoke(InstructionAdapter v) { 4000 expressionToGen.put(OBJECT_TYPE, v); 4001 if (leaveExpressionOnStack) { 4002 v.dup(); 4003 } 4004 if (jetType.isMarkedNullable()) { 4005 Label nope = new Label(); 4006 Label end = new Label(); 4007 4008 v.dup(); 4009 v.ifnull(nope); 4010 generateInstanceOfInstruction(jetType); 4011 v.goTo(end); 4012 v.mark(nope); 4013 v.pop(); 4014 v.iconst(1); 4015 v.mark(end); 4016 } 4017 else { 4018 generateInstanceOfInstruction(jetType); 4019 } 4020 return null; 4021 } 4022 }); 4023 } 4024 4025 private void generateInstanceOfInstruction(@NotNull JetType jetType) { 4026 Type type = boxType(asmType(jetType)); 4027 putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.INSTANCEOF_MARKER_METHOD_NAME); 4028 v.instanceOf(type); 4029 } 4030 4031 @NotNull 4032 private StackValue generateCheckCastInstruction(@NotNull JetType jetType) { 4033 Type type = boxType(asmType(jetType)); 4034 putReifierMarkerIfTypeIsReifiedParameter(jetType, ReifiedTypeInliner.CHECKCAST_MARKER_METHOD_NAME); 4035 v.checkcast(type); 4036 return StackValue.onStack(type); 4037 } 4038 4039 public void putReifierMarkerIfTypeIsReifiedParameter(@NotNull JetType type, @NotNull String markerMethodName) { 4040 TypeParameterDescriptor typeParameterDescriptor = TypeUtils.getTypeParameterDescriptorOrNull(type); 4041 if (typeParameterDescriptor != null && typeParameterDescriptor.isReified()) { 4042 if (typeParameterDescriptor.getContainingDeclaration() != context.getContextDescriptor()) { 4043 parentCodegen.getReifiedTypeParametersUsages(). 4044 addUsedReifiedParameter(typeParameterDescriptor.getName().asString()); 4045 } 4046 4047 v.visitLdcInsn(typeParameterDescriptor.getName().asString()); 4048 v.invokestatic( 4049 IntrinsicMethods.INTRINSICS_CLASS_NAME, markerMethodName, 4050 Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class)), false 4051 ); 4052 } 4053 } 4054 4055 public void propagateChildReifiedTypeParametersUsages(@NotNull ReifiedTypeParametersUsages usages) { 4056 parentCodegen.getReifiedTypeParametersUsages().propagateChildUsagesWithinContext(usages, context); 4057 } 4058 4059 @Override 4060 public StackValue visitWhenExpression(@NotNull JetWhenExpression expression, StackValue receiver) { 4061 return generateWhenExpression(expression, false); 4062 } 4063 4064 public StackValue generateWhenExpression(final JetWhenExpression expression, final boolean isStatement) { 4065 final JetExpression expr = expression.getSubjectExpression(); 4066 final Type subjectType = expressionType(expr); 4067 4068 final Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 4069 4070 return StackValue.operation(resultType, new Function1<InstructionAdapter, Unit>() { 4071 @Override 4072 public Unit invoke(InstructionAdapter v) { 4073 SwitchCodegen switchCodegen = 4074 SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(expression, isStatement, ExpressionCodegen.this); 4075 if (switchCodegen != null) { 4076 switchCodegen.generate(); 4077 return Unit.INSTANCE$; 4078 } 4079 4080 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 4081 if (subjectLocal != -1) { 4082 gen(expr, subjectType); 4083 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 4084 v.store(subjectLocal, subjectType); 4085 } 4086 4087 Label end = new Label(); 4088 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 4089 4090 Label nextCondition = null; 4091 for (JetWhenEntry whenEntry : expression.getEntries()) { 4092 if (nextCondition != null) { 4093 v.mark(nextCondition); 4094 } 4095 nextCondition = new Label(); 4096 FrameMap.Mark mark = myFrameMap.mark(); 4097 Label thisEntry = new Label(); 4098 if (!whenEntry.isElse()) { 4099 JetWhenCondition[] conditions = whenEntry.getConditions(); 4100 for (int i = 0; i < conditions.length; i++) { 4101 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 4102 conditionValue.condJump(nextCondition, true, v); 4103 if (i < conditions.length - 1) { 4104 v.goTo(thisEntry); 4105 v.mark(nextCondition); 4106 nextCondition = new Label(); 4107 } 4108 } 4109 } 4110 4111 v.visitLabel(thisEntry); 4112 gen(whenEntry.getExpression(), resultType); 4113 mark.dropTo(); 4114 if (!whenEntry.isElse()) { 4115 v.goTo(end); 4116 } 4117 } 4118 if (!hasElse && nextCondition != null) { 4119 v.mark(nextCondition); 4120 if (!isStatement) { 4121 putUnitInstanceOntoStackForNonExhaustiveWhen(expression); 4122 } 4123 } 4124 4125 markLineNumber(expression, isStatement); 4126 v.mark(end); 4127 4128 myFrameMap.leaveTemp(subjectType); 4129 tempVariables.remove(expr); 4130 return null; 4131 } 4132 }); 4133 } 4134 4135 public void putUnitInstanceOntoStackForNonExhaustiveWhen( 4136 @NotNull JetWhenExpression expression 4137 ) { 4138 if (Boolean.TRUE.equals(bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, expression))) { 4139 // when() is supposed to be exhaustive 4140 genThrow(v, "kotlin/NoWhenBranchMatchedException", null); 4141 } 4142 else { 4143 // non-exhaustive when() with no else -> Unit must be expected 4144 StackValue.putUnitInstance(v); 4145 } 4146 } 4147 4148 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 4149 if (condition instanceof JetWhenConditionInRange) { 4150 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 4151 return generateIn(StackValue.local(subjectLocal, subjectType), 4152 conditionInRange.getRangeExpression(), 4153 conditionInRange.getOperationReference()); 4154 } 4155 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 4156 if (condition instanceof JetWhenConditionIsPattern) { 4157 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 4158 return generateIsCheck(match, patternCondition.getTypeReference(), patternCondition.isNegated()); 4159 } 4160 else if (condition instanceof JetWhenConditionWithExpression) { 4161 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 4162 return generateExpressionMatch(match, patternExpression); 4163 } 4164 else { 4165 throw new UnsupportedOperationException("unsupported kind of when condition"); 4166 } 4167 } 4168 4169 private boolean isIntRangeExpr(JetExpression rangeExpression) { 4170 if (rangeExpression instanceof JetBinaryExpression) { 4171 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 4172 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 4173 JetType jetType = bindingContext.get(EXPRESSION_TYPE, rangeExpression); 4174 assert jetType != null; 4175 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 4176 return INTEGRAL_RANGES.contains(descriptor); 4177 } 4178 } 4179 return false; 4180 } 4181 4182 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 4183 JetSimpleNameExpression fake = JetPsiFactory(state.getProject()).createSimpleName("fake"); 4184 return CallMaker.makeCall(fake, initializerAsReceiver); 4185 } 4186 4187 @Override 4188 public String toString() { 4189 return context.getContextDescriptor().toString(); 4190 } 4191 4192 @NotNull 4193 public FrameMap getFrameMap() { 4194 return myFrameMap; 4195 } 4196 4197 @NotNull 4198 public MethodContext getContext() { 4199 return context; 4200 } 4201 4202 @NotNull 4203 public NameGenerator getInlineNameGenerator() { 4204 NameGenerator nameGenerator = getParentCodegen().getInlineNameGenerator(); 4205 Name name = context.getContextDescriptor().getName(); 4206 return nameGenerator.subGenerator((name.isSpecial() ? "$special" : name.asString()) + "$$inlined" ); 4207 } 4208 4209 public Type getReturnType() { 4210 return returnType; 4211 } 4212 4213 public Stack<BlockStackElement> getBlockStackElements() { 4214 return new Stack<BlockStackElement>(blockStackElements); 4215 } 4216 4217 public void addBlockStackElementsForNonLocalReturns(@NotNull Stack<BlockStackElement> elements) { 4218 blockStackElements.addAll(elements); 4219 } 4220 4221 private static class NonLocalReturnInfo { 4222 4223 final Type returnType; 4224 4225 final String labelName; 4226 4227 private NonLocalReturnInfo(Type type, String name) { 4228 returnType = type; 4229 labelName = name; 4230 } 4231 } 4232 }