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