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