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