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