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