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