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