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