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 017package org.jetbrains.jet.codegen; 018 019import com.google.common.collect.Lists; 020import com.google.common.collect.Maps; 021import com.intellij.openapi.editor.Document; 022import com.intellij.openapi.progress.ProcessCanceledException; 023import com.intellij.psi.PsiElement; 024import com.intellij.psi.tree.IElementType; 025import com.intellij.util.ArrayUtil; 026import com.intellij.util.Function; 027import com.intellij.util.containers.Stack; 028import org.jetbrains.annotations.NotNull; 029import org.jetbrains.annotations.Nullable; 030import org.jetbrains.asm4.Label; 031import org.jetbrains.asm4.MethodVisitor; 032import org.jetbrains.asm4.Type; 033import org.jetbrains.asm4.commons.InstructionAdapter; 034import org.jetbrains.asm4.commons.Method; 035import org.jetbrains.jet.codegen.binding.CalculatedClosure; 036import org.jetbrains.jet.codegen.binding.CodegenBinding; 037import org.jetbrains.jet.codegen.binding.MutableClosure; 038import org.jetbrains.jet.codegen.context.*; 039import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod; 040import org.jetbrains.jet.codegen.signature.JvmMethodSignature; 041import org.jetbrains.jet.codegen.state.GenerationState; 042import org.jetbrains.jet.codegen.state.JetTypeMapper; 043import org.jetbrains.jet.codegen.state.JetTypeMapperMode; 044import org.jetbrains.jet.lang.descriptors.*; 045import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; 046import org.jetbrains.jet.lang.psi.*; 047import org.jetbrains.jet.lang.resolve.BindingContext; 048import org.jetbrains.jet.lang.resolve.DescriptorUtils; 049import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver; 050import org.jetbrains.jet.lang.resolve.calls.model.*; 051import org.jetbrains.jet.lang.resolve.calls.util.CallMaker; 052import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor; 053import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 054import org.jetbrains.jet.lang.resolve.java.*; 055import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; 056import org.jetbrains.jet.lang.resolve.name.Name; 057import org.jetbrains.jet.lang.resolve.scopes.receivers.*; 058import org.jetbrains.jet.lang.types.JetType; 059import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 060import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 061import org.jetbrains.jet.lexer.JetTokens; 062import org.jetbrains.jet.renderer.DescriptorRenderer; 063 064import java.util.*; 065 066import static org.jetbrains.asm4.Opcodes.*; 067import static org.jetbrains.jet.codegen.AsmUtil.*; 068import static org.jetbrains.jet.codegen.CodegenUtil.*; 069import static org.jetbrains.jet.codegen.FunctionTypesUtil.functionTypeToImpl; 070import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionImplClassName; 071import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; 072import static org.jetbrains.jet.lang.resolve.BindingContext.*; 073import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; 074import static org.jetbrains.jet.lang.resolve.BindingContextUtils.getNotNull; 075import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.RECEIVER_ARGUMENT; 076import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.THIS_OBJECT; 077import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; 078import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER; 079 080public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implements LocalLookup { 081 082 private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; 083 private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; 084 public static final Set<DeclarationDescriptor> INTEGRAL_RANGES = KotlinBuiltIns.getInstance().getIntegralRanges(); 085 086 private int myLastLineNumber = -1; 087 088 final InstructionAdapter v; 089 final MethodVisitor methodVisitor; 090 final FrameMap myFrameMap; 091 final JetTypeMapper typeMapper; 092 093 private final GenerationState state; 094 private final Type returnType; 095 096 private final BindingContext bindingContext; 097 final MethodContext context; 098 private final CodegenStatementVisitor statementVisitor; 099 100 private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>(); 101 private final Collection<String> localVariableNames = new HashSet<String>(); 102 103 /* 104 * When we create a temporary variable to hold some value not to compute it many times 105 * we put it into this map to emit access to that variable instead of evaluating the whole expression 106 */ 107 private final Map<JetElement, StackValue.Local> tempVariables = Maps.newHashMap(); 108 109 public CalculatedClosure generateObjectLiteral( 110 GenerationState state, 111 JetObjectLiteralExpression literal 112 ) { 113 JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); 114 115 JvmClassName className = classNameForAnonymousClass(bindingContext, objectDeclaration); 116 ClassBuilder classBuilder = state.getFactory().newVisitor(className.getInternalName(), literal.getContainingFile()); 117 118 ClassDescriptor classDescriptor = bindingContext.get(CLASS, objectDeclaration); 119 assert classDescriptor != null; 120 121 //noinspection SuspiciousMethodCalls 122 CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor); 123 124 ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this); 125 ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, null); 126 127 implementationBodyCodegen.generate(); 128 129 return closure; 130 } 131 132 static class BlockStackElement { 133 } 134 135 static class LoopBlockStackElement extends BlockStackElement { 136 final Label continueLabel; 137 final Label breakLabel; 138 public final JetSimpleNameExpression targetLabel; 139 140 LoopBlockStackElement(Label breakLabel, Label continueLabel, JetSimpleNameExpression targetLabel) { 141 this.breakLabel = breakLabel; 142 this.continueLabel = continueLabel; 143 this.targetLabel = targetLabel; 144 } 145 } 146 147 static class FinallyBlockStackElement extends BlockStackElement { 148 final JetTryExpression expression; 149 150 FinallyBlockStackElement(JetTryExpression expression) { 151 this.expression = expression; 152 } 153 } 154 155 156 public ExpressionCodegen( 157 @NotNull MethodVisitor v, 158 @NotNull FrameMap myMap, 159 @NotNull Type returnType, 160 @NotNull MethodContext context, 161 @NotNull GenerationState state 162 ) { 163 this.myFrameMap = myMap; 164 this.typeMapper = state.getTypeMapper(); 165 this.returnType = returnType; 166 this.state = state; 167 this.methodVisitor = v; 168 this.v = createInstructionAdapter(methodVisitor); 169 this.bindingContext = state.getBindingContext(); 170 this.context = context; 171 this.statementVisitor = new CodegenStatementVisitor(this); 172 } 173 174 protected InstructionAdapter createInstructionAdapter(MethodVisitor mv) { 175 return new InstructionAdapter(methodVisitor) { 176 @Override 177 public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { 178 super.visitLocalVariable(name, desc, signature, start, end, index); 179 localVariableNames.add(name); 180 } 181 }; 182 } 183 184 public GenerationState getState() { 185 return state; 186 } 187 188 StackValue castToRequiredTypeOfInterfaceIfNeeded(StackValue inner, DeclarationDescriptor provided, @Nullable ClassDescriptor required) { 189 if (required == null) { 190 return inner; 191 } 192 193 if (provided instanceof CallableDescriptor) { 194 ReceiverParameterDescriptor receiverParameter = ((CallableDescriptor) provided).getReceiverParameter(); 195 assert receiverParameter != null : receiverParameter; 196 provided = receiverParameter.getType().getConstructor().getDeclarationDescriptor(); 197 } 198 199 assert provided instanceof ClassDescriptor; 200 201 if (!isInterface(provided) && isInterface(required)) { 202 inner.put(OBJECT_TYPE, v); 203 Type type = asmType(required.getDefaultType()); 204 v.checkcast(type); 205 return StackValue.onStack(type); 206 } 207 208 return inner; 209 } 210 211 public BindingContext getBindingContext() { 212 return bindingContext; 213 } 214 215 public Collection<String> getLocalVariableNamesForExpression() { 216 return localVariableNames; 217 } 218 219 public StackValue genQualified(StackValue receiver, JetElement selector) { 220 return genQualified(receiver, selector, this); 221 } 222 223 private StackValue genQualified(StackValue receiver, JetElement selector, JetVisitor<StackValue, StackValue> visitor) { 224 if (tempVariables.containsKey(selector)) { 225 throw new IllegalStateException("Inconsistent state: expression saved to a temporary variable is a selector"); 226 } 227 if (!(selector instanceof JetBlockExpression)) { 228 markLineNumber(selector); 229 } 230 try { 231 if (selector instanceof JetExpression) { 232 JetExpression expression = (JetExpression) selector; 233 CompileTimeConstant<?> constant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression); 234 if (constant != null) { 235 return StackValue.constant(constant.getValue(), expressionType(expression)); 236 } 237 ClassDescriptorFromJvmBytecode samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression); 238 if (samInterface != null) { 239 return genSamInterfaceValue(expression, samInterface, visitor); 240 } 241 } 242 243 return selector.accept(visitor, receiver); 244 } 245 catch (ProcessCanceledException e) { 246 throw e; 247 } 248 catch (CompilationException e) { 249 throw e; 250 } 251 catch (Throwable error) { 252 String message = error.getMessage(); 253 throw new CompilationException(message != null ? message : "null", error, selector); 254 } 255 } 256 257 public StackValue gen(JetElement expr) { 258 StackValue tempVar = tempVariables.get(expr); 259 return tempVar != null ? tempVar : genQualified(StackValue.none(), expr); 260 } 261 262 public void gen(JetElement expr, Type type) { 263 StackValue value = gen(expr); 264 value.put(type, v); 265 } 266 267 public void genToJVMStack(JetExpression expr) { 268 gen(expr, expressionType(expr)); 269 } 270 271 private StackValue genStatement(JetElement statement) { 272 return genQualified(StackValue.none(), statement, statementVisitor); 273 } 274 275 @Override 276 public StackValue visitClass(JetClass klass, StackValue data) { 277 return visitClassOrObject(klass); 278 } 279 280 private StackValue visitClassOrObject(JetClassOrObject declaration) { 281 ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, declaration); 282 assert descriptor != null; 283 284 JvmClassName className = 285 classNameForAnonymousClass(bindingContext, declaration); 286 ClassBuilder classBuilder = state.getFactory().newVisitor(className.getInternalName(), declaration.getContainingFile() 287 ); 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 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 1143 1144 for (int i = blockStackElements.size() - 1; i >= 0; --i) { 1145 BlockStackElement stackElement = blockStackElements.get(i); 1146 if (stackElement instanceof FinallyBlockStackElement) { 1147 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1148 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1149 //noinspection ConstantConditions 1150 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1151 } 1152 else if (stackElement instanceof LoopBlockStackElement) { 1153 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; 1154 //noinspection ConstantConditions 1155 if (labelElement == null || 1156 loopBlockStackElement.targetLabel != null && 1157 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { 1158 v.goTo(loopBlockStackElement.breakLabel); 1159 return StackValue.none(); 1160 } 1161 } 1162 else { 1163 throw new UnsupportedOperationException(); 1164 } 1165 } 1166 1167 throw new UnsupportedOperationException(); 1168 } 1169 1170 @Override 1171 public StackValue visitContinueExpression(JetContinueExpression expression, StackValue receiver) { 1172 JetSimpleNameExpression labelElement = expression.getTargetLabel(); 1173 1174 for (int i = blockStackElements.size() - 1; i >= 0; --i) { 1175 BlockStackElement stackElement = blockStackElements.get(i); 1176 if (stackElement instanceof FinallyBlockStackElement) { 1177 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1178 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1179 //noinspection ConstantConditions 1180 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1181 } 1182 else if (stackElement instanceof LoopBlockStackElement) { 1183 LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement; 1184 //noinspection ConstantConditions 1185 if (labelElement == null || 1186 loopBlockStackElement.targetLabel != null && 1187 labelElement.getReferencedName().equals(loopBlockStackElement.targetLabel.getReferencedName())) { 1188 v.goTo(loopBlockStackElement.continueLabel); 1189 return StackValue.none(); 1190 } 1191 } 1192 else { 1193 throw new UnsupportedOperationException(); 1194 } 1195 } 1196 1197 throw new UnsupportedOperationException(); 1198 } 1199 1200 private StackValue generateSingleBranchIf( 1201 StackValue condition, 1202 JetIfExpression ifExpression, 1203 JetExpression expression, 1204 boolean inverse, 1205 boolean isStatement 1206 ) { 1207 Label elseLabel = new Label(); 1208 condition.condJump(elseLabel, inverse, v); 1209 1210 if (isStatement) { 1211 gen(expression, Type.VOID_TYPE); 1212 v.mark(elseLabel); 1213 return StackValue.none(); 1214 } 1215 else { 1216 Type type = expressionType(expression); 1217 Type targetType = type.equals(JET_UNIT_TYPE) ? type : OBJECT_TYPE; 1218 1219 gen(expression, targetType); 1220 1221 Label end = new Label(); 1222 v.goTo(end); 1223 1224 markLineNumber(ifExpression); 1225 v.mark(elseLabel); 1226 StackValue.putUnitInstance(v); 1227 1228 v.mark(end); 1229 return StackValue.onStack(targetType); 1230 } 1231 } 1232 1233 @Override 1234 public StackValue visitConstantExpression(JetConstantExpression expression, StackValue receiver) { 1235 CompileTimeConstant<?> compileTimeValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expression); 1236 assert compileTimeValue != null; 1237 return StackValue.constant(compileTimeValue.getValue(), expressionType(expression)); 1238 } 1239 1240 @Override 1241 public StackValue visitStringTemplateExpression(JetStringTemplateExpression expression, StackValue receiver) { 1242 StringBuilder constantValue = new StringBuilder(""); 1243 JetStringTemplateEntry[] entries = expression.getEntries(); 1244 1245 if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) { 1246 JetExpression expr = entries[0].getExpression(); 1247 return genToString(v, gen(expr), expressionType(expr)); 1248 } 1249 1250 for (JetStringTemplateEntry entry : entries) { 1251 if (entry instanceof JetLiteralStringTemplateEntry) { 1252 constantValue.append(entry.getText()); 1253 } 1254 else if (entry instanceof JetEscapeStringTemplateEntry) { 1255 constantValue.append(((JetEscapeStringTemplateEntry) entry).getUnescapedValue()); 1256 } 1257 else { 1258 constantValue = null; 1259 break; 1260 } 1261 } 1262 if (constantValue != null) { 1263 Type type = expressionType(expression); 1264 return StackValue.constant(constantValue.toString(), type); 1265 } 1266 else { 1267 genStringBuilderConstructor(v); 1268 for (JetStringTemplateEntry entry : entries) { 1269 if (entry instanceof JetStringTemplateEntryWithExpression) { 1270 invokeAppend(entry.getExpression()); 1271 } 1272 else { 1273 String text = entry instanceof JetEscapeStringTemplateEntry 1274 ? ((JetEscapeStringTemplateEntry) entry).getUnescapedValue() 1275 : entry.getText(); 1276 v.aconst(text); 1277 genInvokeAppendMethod(v, JAVA_STRING_TYPE); 1278 } 1279 } 1280 v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); 1281 return StackValue.onStack(AsmTypeConstants.JAVA_STRING_TYPE); 1282 } 1283 } 1284 1285 @Override 1286 public StackValue visitBlockExpression(JetBlockExpression expression, StackValue receiver) { 1287 List<JetElement> statements = expression.getStatements(); 1288 JetType unitType = KotlinBuiltIns.getInstance().getUnitType(); 1289 boolean lastStatementIsExpression = !unitType.equals(bindingContext.get(EXPRESSION_TYPE, expression)); 1290 return generateBlock(statements, lastStatementIsExpression); 1291 } 1292 1293 @Override 1294 public StackValue visitNamedFunction(JetNamedFunction function, StackValue data) { 1295 assert data == StackValue.none(); 1296 1297 if (JetPsiUtil.isScriptDeclaration(function)) { 1298 return StackValue.none(); 1299 } 1300 1301 StackValue closure = genClosure(function, null); 1302 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); 1303 int index = lookupLocalIndex(descriptor); 1304 closure.put(OBJECT_TYPE, v); 1305 v.store(index, OBJECT_TYPE); 1306 return StackValue.none(); 1307 } 1308 1309 @Override 1310 public StackValue visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, StackValue receiver) { 1311 //noinspection ConstantConditions 1312 if (bindingContext.get(BindingContext.BLOCK, expression)) { 1313 //noinspection ConstantConditions 1314 return gen(expression.getFunctionLiteral().getBodyExpression()); 1315 } 1316 else { 1317 return genClosure(expression.getFunctionLiteral(), null); 1318 } 1319 } 1320 1321 private StackValue genClosure(JetDeclarationWithBody declaration, @Nullable ClassDescriptor samInterfaceClass) { 1322 FunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, declaration); 1323 assert descriptor != null : "Function is not resolved to descriptor: " + declaration.getText(); 1324 1325 JvmClassName closureSuperClass = samInterfaceClass == null ? getFunctionImplClassName(descriptor) : JvmClassName.byType(OBJECT_TYPE); 1326 1327 ClosureCodegen closureCodegen = new ClosureCodegen(state, declaration, descriptor, samInterfaceClass, closureSuperClass, context, 1328 this, new FunctionGenerationStrategy.FunctionDefault(state, descriptor, declaration)); 1329 1330 closureCodegen.gen(); 1331 1332 return closureCodegen.putInstanceOnStack(v, this); 1333 } 1334 1335 @Override 1336 public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) { 1337 CalculatedClosure closure = this.generateObjectLiteral(state, expression); 1338 1339 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, expression.getObjectDeclaration()); 1340 assert constructorDescriptor != null; 1341 CallableMethod constructor = typeMapper.mapToCallableMethod(constructorDescriptor, closure); 1342 1343 JvmClassName name = bindingContext.get(FQN, constructorDescriptor.getContainingDeclaration()); 1344 assert name != null; 1345 1346 Type type = name.getAsmType(); 1347 v.anew(type); 1348 v.dup(); 1349 Method cons = constructor.getSignature().getAsmMethod(); 1350 1351 pushClosureOnStack(closure, false); 1352 1353 JetDelegatorToSuperCall superCall = closure.getSuperCall(); 1354 if (superCall != null) { 1355 ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, 1356 superCall 1357 .getCalleeExpression() 1358 .getConstructorReferenceExpression()); 1359 assert superConstructor != null; 1360 //noinspection SuspiciousMethodCalls 1361 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); 1362 Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes(); 1363 ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, superCall.getCalleeExpression()); 1364 assert resolvedCall != null; 1365 pushMethodArguments(resolvedCall, Arrays.asList(argumentTypes)); 1366 } 1367 1368 v.invokespecial(name.getInternalName(), "<init>", cons.getDescriptor()); 1369 return StackValue.onStack(type); 1370 } 1371 1372 protected void pushClosureOnStack(CalculatedClosure closure, boolean ignoreThisAndReceiver) { 1373 if (closure != null) { 1374 if (!ignoreThisAndReceiver) { 1375 ClassDescriptor captureThis = closure.getCaptureThis(); 1376 if (captureThis != null) { 1377 generateThisOrOuter(captureThis, false).put(OBJECT_TYPE, v); 1378 } 1379 1380 ClassifierDescriptor captureReceiver = closure.getCaptureReceiver(); 1381 if (captureReceiver != null) { 1382 Type asmType = typeMapper.mapType(captureReceiver.getDefaultType(), JetTypeMapperMode.IMPL); 1383 v.load(context.isStatic() ? 0 : 1, asmType); 1384 } 1385 } 1386 1387 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) { 1388 //if (entry.getKey() instanceof VariableDescriptor && !(entry.getKey() instanceof PropertyDescriptor)) { 1389 Type sharedVarType = typeMapper.getSharedVarType(entry.getKey()); 1390 if (sharedVarType == null) { 1391 sharedVarType = typeMapper.mapType((VariableDescriptor) entry.getKey()); 1392 } 1393 entry.getValue().getOuterValue(this).put(sharedVarType, v); 1394 //} 1395 } 1396 } 1397 } 1398 1399 private StackValue generateBlock(List<JetElement> statements, boolean lastStatementIsExpression) { 1400 Label blockEnd = new Label(); 1401 1402 List<Function<StackValue, Void>> leaveTasks = Lists.newArrayList(); 1403 1404 StackValue answer = StackValue.none(); 1405 1406 for (Iterator<JetElement> iterator = statements.iterator(); iterator.hasNext(); ) { 1407 JetElement statement = iterator.next(); 1408 1409 if (statement instanceof JetNamedDeclaration) { 1410 JetNamedDeclaration declaration = (JetNamedDeclaration) statement; 1411 if (JetPsiUtil.isScriptDeclaration(declaration)) { 1412 continue; 1413 } 1414 } 1415 1416 if (statement instanceof JetMultiDeclaration) { 1417 JetMultiDeclaration multiDeclaration = (JetMultiDeclaration) statement; 1418 for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) { 1419 generateLocalVariableDeclaration(entry, blockEnd, leaveTasks); 1420 } 1421 } 1422 1423 if (statement instanceof JetVariableDeclaration) { 1424 generateLocalVariableDeclaration((JetVariableDeclaration) statement, blockEnd, leaveTasks); 1425 } 1426 1427 if (statement instanceof JetNamedFunction) { 1428 generateLocalFunctionDeclaration((JetNamedFunction) statement, leaveTasks); 1429 } 1430 1431 boolean isExpression = !iterator.hasNext() && lastStatementIsExpression; 1432 1433 StackValue result = isExpression ? gen(statement) : genStatement(statement); 1434 1435 if (!iterator.hasNext()) { 1436 answer = result; 1437 } 1438 else { 1439 result.put(Type.VOID_TYPE, v); 1440 } 1441 } 1442 1443 v.mark(blockEnd); 1444 1445 for (Function<StackValue, Void> task : Lists.reverse(leaveTasks)) { 1446 task.fun(answer); 1447 } 1448 1449 return answer; 1450 } 1451 1452 private void generateLocalVariableDeclaration( 1453 @NotNull JetVariableDeclaration variableDeclaration, 1454 final @NotNull Label blockEnd, 1455 @NotNull List<Function<StackValue, Void>> leaveTasks 1456 ) { 1457 final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 1458 assert variableDescriptor != null; 1459 1460 final Label scopeStart = new Label(); 1461 v.mark(scopeStart); 1462 1463 final Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 1464 final Type type = sharedVarType != null ? sharedVarType : asmType(variableDescriptor.getType()); 1465 int index = myFrameMap.enter(variableDescriptor, type); 1466 1467 if (sharedVarType != null) { 1468 v.anew(sharedVarType); 1469 v.dup(); 1470 v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V"); 1471 v.store(index, OBJECT_TYPE); 1472 } 1473 1474 leaveTasks.add(new Function<StackValue, Void>() { 1475 @Override 1476 public Void fun(StackValue answer) { 1477 int index = myFrameMap.leave(variableDescriptor); 1478 1479 if (sharedVarType != null) { 1480 if (answer instanceof StackValue.Shared && index == ((StackValue.Shared) answer).getIndex()) { 1481 ((StackValue.Shared) answer).releaseOnPut(); 1482 } 1483 else { 1484 v.aconst(null); 1485 v.store(index, OBJECT_TYPE); 1486 } 1487 } 1488 v.visitLocalVariable(variableDescriptor.getName().asString(), type.getDescriptor(), null, scopeStart, blockEnd, 1489 index); 1490 return null; 1491 } 1492 }); 1493 } 1494 1495 private void generateLocalFunctionDeclaration( 1496 @NotNull JetNamedFunction namedFunction, 1497 @NotNull List<Function<StackValue, Void>> leaveTasks 1498 ) { 1499 final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, namedFunction); 1500 myFrameMap.enter(descriptor, OBJECT_TYPE); 1501 1502 leaveTasks.add(new Function<StackValue, Void>() { 1503 @Override 1504 public Void fun(StackValue value) { 1505 myFrameMap.leave(descriptor); 1506 return null; 1507 } 1508 }); 1509 } 1510 1511 private void markLineNumber(@NotNull JetElement statement) { 1512 Document document = statement.getContainingFile().getViewProvider().getDocument(); 1513 if (document != null) { 1514 int lineNumber = document.getLineNumber(statement.getTextRange().getStartOffset()); // 0-based 1515 if (lineNumber == myLastLineNumber) { 1516 return; 1517 } 1518 myLastLineNumber = lineNumber; 1519 1520 Label label = new Label(); 1521 v.visitLabel(label); 1522 v.visitLineNumber(lineNumber + 1, label); // 1-based 1523 } 1524 } 1525 1526 private void doFinallyOnReturn() { 1527 for (int i = blockStackElements.size() - 1; i >= 0; --i) { 1528 BlockStackElement stackElement = blockStackElements.get(i); 1529 if (stackElement instanceof FinallyBlockStackElement) { 1530 FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement; 1531 JetTryExpression jetTryExpression = finallyBlockStackElement.expression; 1532 blockStackElements.pop(); 1533 //noinspection ConstantConditions 1534 gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); 1535 blockStackElements.push(finallyBlockStackElement); 1536 } 1537 else { 1538 break; 1539 } 1540 } 1541 } 1542 1543 @Override 1544 public StackValue visitReturnExpression(JetReturnExpression expression, StackValue receiver) { 1545 JetExpression returnedExpression = expression.getReturnedExpression(); 1546 if (returnedExpression != null) { 1547 gen(returnedExpression, returnType); 1548 doFinallyOnReturn(); 1549 v.areturn(returnType); 1550 } 1551 else { 1552 doFinallyOnReturn(); 1553 v.visitInsn(RETURN); 1554 } 1555 return StackValue.none(); 1556 } 1557 1558 public void returnExpression(JetExpression expr) { 1559 StackValue lastValue = gen(expr); 1560 1561 if (lastValue.type != Type.VOID_TYPE) { 1562 lastValue.put(returnType, v); 1563 v.areturn(returnType); 1564 } 1565 else if (!endsWithReturn(expr)) { 1566 v.areturn(returnType); 1567 } 1568 } 1569 1570 private static boolean endsWithReturn(JetElement bodyExpression) { 1571 if (bodyExpression instanceof JetBlockExpression) { 1572 List<JetElement> statements = ((JetBlockExpression) bodyExpression).getStatements(); 1573 return statements.size() > 0 && statements.get(statements.size() - 1) instanceof JetReturnExpression; 1574 } 1575 1576 return bodyExpression instanceof JetReturnExpression; 1577 } 1578 1579 @Override 1580 public StackValue visitSimpleNameExpression(JetSimpleNameExpression expression, StackValue receiver) { 1581 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression); 1582 1583 DeclarationDescriptor descriptor; 1584 if (resolvedCall == null) { 1585 descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 1586 } 1587 else { 1588 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1589 VariableAsFunctionResolvedCall call = (VariableAsFunctionResolvedCall) resolvedCall; 1590 resolvedCall = call.getVariableCall(); 1591 } 1592 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1593 descriptor = resolvedCall.getResultingDescriptor(); 1594 } 1595 1596 //if (descriptor instanceof VariableAsFunctionDescriptor) { 1597 // descriptor = ((VariableAsFunctionDescriptor) descriptor).getVariableDescriptor(); 1598 //} 1599 1600 if (descriptor instanceof CallableMemberDescriptor) { 1601 CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor; 1602 memberDescriptor = unwrapFakeOverride(memberDescriptor); 1603 1604 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor); 1605 if (intrinsic != null) { 1606 Type expectedType = expressionType(expression); 1607 return intrinsic.generate(this, v, expectedType, expression, Collections.<JetExpression>emptyList(), receiver, state); 1608 } 1609 } 1610 1611 1612 assert descriptor != null; 1613 1614 if (descriptor instanceof VariableDescriptor) { 1615 VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor; 1616 ClassDescriptor objectClassDescriptor = getBindingContext().get(BindingContext.OBJECT_DECLARATION_CLASS, variableDescriptor); 1617 if (objectClassDescriptor != null) { 1618 return genObjectClassInstance(variableDescriptor, objectClassDescriptor); 1619 } 1620 } 1621 1622 int index = lookupLocalIndex(descriptor); 1623 if (index >= 0) { 1624 return stackValueForLocal(descriptor, index); 1625 } 1626 1627 if (descriptor instanceof PropertyDescriptor) { 1628 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; 1629 1630 boolean directToField = 1631 expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL; 1632 JetExpression r = getReceiverForSelector(expression); 1633 boolean isSuper = r instanceof JetSuperExpression; 1634 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1635 StackValue iValue = 1636 intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression) r : null); 1637 if (directToField) { 1638 receiver = StackValue.receiverWithoutReceiverArgument(receiver); 1639 } 1640 receiver.put(receiver.type, v); 1641 1642 return iValue; 1643 } 1644 1645 if (descriptor instanceof ClassDescriptor) { 1646 ClassDescriptor classObjectDescriptor = ((ClassDescriptor) descriptor).getClassObjectDescriptor(); 1647 assert classObjectDescriptor != null : "Class object is not found for " + descriptor; 1648 return StackValue.singleton(classObjectDescriptor, typeMapper); 1649 } 1650 1651 if (descriptor instanceof TypeParameterDescriptor) { 1652 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; 1653 v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); 1654 JetType type = typeParameterDescriptor.getClassObjectType(); 1655 assert type != null; 1656 v.checkcast(asmType(type)); 1657 1658 return StackValue.onStack(OBJECT_TYPE); 1659 } 1660 1661 StackValue value = context.lookupInContext(descriptor, StackValue.local(0, OBJECT_TYPE), state, false); 1662 if (value != null) { 1663 1664 if (value instanceof StackValue.Composed) { 1665 StackValue.Composed composed = (StackValue.Composed) value; 1666 composed.prefix.put(OBJECT_TYPE, v); 1667 value = composed.suffix; 1668 } 1669 1670 if (value instanceof StackValue.FieldForSharedVar) { 1671 StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value; 1672 Type sharedType = StackValue.sharedTypeForType(value.type); 1673 v.visitFieldInsn(GETFIELD, fieldForSharedVar.owner.getInternalName(), fieldForSharedVar.name, 1674 sharedType.getDescriptor()); 1675 } 1676 1677 return value; 1678 } 1679 1680 if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) { 1681 ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration(); 1682 assert scriptDescriptor != null; 1683 JvmClassName scriptClassName = classNameForScriptDescriptor(bindingContext, scriptDescriptor); 1684 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor; 1685 ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_SCRIPT, scriptDescriptor); 1686 StackValue script = StackValue.thisOrOuter(this, scriptClass, false); 1687 script.put(script.type, v); 1688 Type fieldType = typeMapper.mapType(valueParameterDescriptor); 1689 return StackValue.field(fieldType, scriptClassName, valueParameterDescriptor.getName().getIdentifier(), false); 1690 } 1691 1692 throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); 1693 } 1694 1695 private StackValue genObjectClassInstance(VariableDescriptor variableDescriptor, ClassDescriptor objectClassDescriptor) { 1696 boolean isEnumEntry = DescriptorUtils.isEnumClassObject(variableDescriptor.getContainingDeclaration()); 1697 if (isEnumEntry) { 1698 ClassDescriptor containing = (ClassDescriptor) variableDescriptor.getContainingDeclaration().getContainingDeclaration(); 1699 assert containing != null; 1700 Type type = typeMapper.mapType(containing); 1701 return StackValue.field(type, JvmClassName.byType(type), variableDescriptor.getName().asString(), true); 1702 } 1703 else { 1704 return StackValue.singleton(objectClassDescriptor, typeMapper); 1705 } 1706 } 1707 1708 private StackValue stackValueForLocal(DeclarationDescriptor descriptor, int index) { 1709 if (descriptor instanceof VariableDescriptor) { 1710 Type sharedVarType = typeMapper.getSharedVarType(descriptor); 1711 JetType outType = ((VariableDescriptor) descriptor).getType(); 1712 if (sharedVarType != null) { 1713 return StackValue.shared(index, asmType(outType)); 1714 } 1715 else { 1716 return StackValue.local(index, asmType(outType)); 1717 } 1718 } 1719 else { 1720 return StackValue.local(index, OBJECT_TYPE); 1721 } 1722 } 1723 1724 @Override 1725 public boolean lookupLocal(DeclarationDescriptor descriptor) { 1726 return lookupLocalIndex(descriptor) != -1; 1727 } 1728 1729 public int lookupLocalIndex(DeclarationDescriptor descriptor) { 1730 return myFrameMap.getIndex(descriptor); 1731 } 1732 1733 @Nullable 1734 private static JetType getPropertyDelegateType(@NotNull PropertyDescriptor descriptor, @NotNull BindingContext bindingContext) { 1735 PropertyGetterDescriptor getter = descriptor.getGetter(); 1736 if (getter != null) { 1737 Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, getter); 1738 return call != null ? call.getExplicitReceiver().getType() : null; 1739 } 1740 return null; 1741 } 1742 1743 @NotNull 1744 public StackValue intermediateValueForProperty( 1745 @NotNull PropertyDescriptor propertyDescriptor, 1746 boolean forceField, 1747 @Nullable JetSuperExpression superExpression 1748 ) { 1749 return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL); 1750 } 1751 1752 public StackValue.StackValueWithSimpleReceiver intermediateValueForProperty( 1753 @NotNull PropertyDescriptor propertyDescriptor, 1754 boolean forceField, 1755 @Nullable JetSuperExpression superExpression, 1756 @NotNull MethodKind methodKind 1757 ) { 1758 JetTypeMapper typeMapper = state.getTypeMapper(); 1759 1760 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 1761 1762 boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor); 1763 boolean isStatic = containingDeclaration instanceof NamespaceDescriptor || isBackingFieldInAnotherClass; 1764 boolean isSuper = superExpression != null; 1765 boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context); 1766 boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context); 1767 1768 JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext()); 1769 boolean isDelegatedProperty = delegateType != null; 1770 1771 1772 CallableMethod callableGetter = null; 1773 CallableMethod callableSetter = null; 1774 1775 boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass; 1776 1777 CodegenContext backingFieldContext = context.getParentContext(); 1778 1779 if (isBackingFieldInAnotherClass && forceField) { 1780 //delegate call to classObject owner : OWNER 1781 backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration()); 1782 int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty); 1783 skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER; 1784 if (!skipPropertyAccessors) { 1785 propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor); 1786 } 1787 } 1788 1789 if (!skipPropertyAccessors) { 1790 if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) { 1791 callableGetter = null; 1792 } 1793 else { 1794 if (isSuper && !isInterface(containingDeclaration)) { 1795 ClassDescriptor owner = getSuperCallLabelTarget(superExpression, state.getBindingContext(), context); 1796 CodegenContext c = context.findParentContextWithDescriptor(owner); 1797 assert c != null : "Couldn't find a context for a super-call: " + propertyDescriptor; 1798 if (c != context.getParentContext()) { 1799 propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor); 1800 } 1801 } 1802 1803 propertyDescriptor = accessiblePropertyDescriptor(propertyDescriptor); 1804 1805 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 1806 if (getter != null) { 1807 callableGetter = typeMapper.mapToCallableMethod( 1808 getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1809 OwnerKind.IMPLEMENTATION); 1810 } 1811 } 1812 1813 if (propertyDescriptor.isVar()) { 1814 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 1815 if (setter != null) { 1816 if (couldUseDirectAccessToProperty(propertyDescriptor, false, isInsideClass, isDelegatedProperty)) { 1817 callableSetter = null; 1818 } 1819 else { 1820 callableSetter = typeMapper.mapToCallableMethod( 1821 setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, 1822 OwnerKind.IMPLEMENTATION); 1823 } 1824 } 1825 } 1826 } 1827 1828 JvmClassName owner; 1829 CallableMethod callableMethod = callableGetter != null ? callableGetter : callableSetter; 1830 1831 propertyDescriptor = unwrapFakeOverride(propertyDescriptor); 1832 if (callableMethod == null) { 1833 owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, 1834 context.getContextKind(), isInsideModule); 1835 } 1836 else { 1837 owner = callableMethod.getOwner(); 1838 } 1839 1840 String name; 1841 if (propertyDescriptor.getContainingDeclaration() == backingFieldContext.getContextDescriptor()) { 1842 assert backingFieldContext instanceof FieldOwnerContext : "Actual context is " + backingFieldContext + " but should be instance of FieldOwnerContext" ; 1843 name = ((FieldOwnerContext) backingFieldContext).getFieldName(propertyDescriptor, isDelegatedProperty); 1844 } else { 1845 name = JvmAbi.getDefaultPropertyName(propertyDescriptor.getName(), isDelegatedProperty, propertyDescriptor.getReceiverParameter() != null); 1846 } 1847 1848 return StackValue.property(propertyDescriptor, owner, 1849 typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()), 1850 isStatic, name, callableGetter, callableSetter, state); 1851 1852 } 1853 1854 @Override 1855 public StackValue visitCallExpression(JetCallExpression expression, StackValue receiver) { 1856 JetExpression callee = expression.getCalleeExpression(); 1857 assert callee != null; 1858 1859 ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, callee); 1860 if (resolvedCall == null) { 1861 throw new CompilationException("Cannot resolve: " + callee.getText(), null, expression); 1862 } 1863 1864 DeclarationDescriptor funDescriptor = resolvedCall.getResultingDescriptor(); 1865 1866 if (!(funDescriptor instanceof FunctionDescriptor)) { 1867 throw new UnsupportedOperationException("unknown type of callee descriptor: " + funDescriptor); 1868 } 1869 1870 funDescriptor = accessibleFunctionDescriptor((FunctionDescriptor) funDescriptor); 1871 1872 if (funDescriptor instanceof ConstructorDescriptor) { 1873 return generateNewCall(expression, resolvedCall, receiver); 1874 } 1875 1876 Call call = bindingContext.get(CALL, expression.getCalleeExpression()); 1877 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 1878 VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall; 1879 ResolvedCallWithTrace<FunctionDescriptor> functionCall = variableAsFunctionResolvedCall.getFunctionCall(); 1880 return invokeFunction(call, receiver, functionCall); 1881 } 1882 1883 if (funDescriptor instanceof SimpleFunctionDescriptor) { 1884 ClassDescriptorFromJvmBytecode samInterface = bindingContext.get( 1885 JavaBindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, ((SimpleFunctionDescriptor) funDescriptor).getOriginal()); 1886 1887 if (samInterface != null) { 1888 return invokeSamConstructor(expression, resolvedCall, samInterface); 1889 } 1890 } 1891 1892 return invokeFunction(call, receiver, resolvedCall); 1893 } 1894 1895 private StackValue invokeSamConstructor( 1896 JetCallExpression expression, 1897 ResolvedCall<? extends CallableDescriptor> resolvedCall, 1898 ClassDescriptorFromJvmBytecode samInterface 1899 ) { 1900 ResolvedValueArgument argument = resolvedCall.getValueArgumentsByIndex().get(0); 1901 if (!(argument instanceof ExpressionValueArgument)) { 1902 throw new IllegalStateException( 1903 "argument of SAM constructor is " + argument.getClass().getName() + " " + expression.getText()); 1904 } 1905 ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); 1906 assert valueArgument != null : "getValueArgument() is null for " + expression.getText(); 1907 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 1908 assert argumentExpression != null : "getArgumentExpression() is null for " + expression.getText(); 1909 1910 return genSamInterfaceValue(argumentExpression, samInterface, this); 1911 } 1912 1913 private StackValue genSamInterfaceValue( 1914 @NotNull JetExpression expression, 1915 @NotNull ClassDescriptorFromJvmBytecode samInterface, 1916 @NotNull JetVisitor<StackValue, StackValue> visitor 1917 ) { 1918 if (expression instanceof JetFunctionLiteralExpression) { 1919 return genClosure(((JetFunctionLiteralExpression) expression).getFunctionLiteral(), samInterface); 1920 } 1921 else { 1922 JvmClassName className = 1923 state.getSamWrapperClasses().getSamWrapperClass(samInterface, (JetFile) expression.getContainingFile()); 1924 1925 v.anew(className.getAsmType()); 1926 v.dup(); 1927 1928 Type functionType = typeMapper.mapType(samInterface.getFunctionTypeForSamInterface()); 1929 expression.accept(visitor, StackValue.none()).put(functionType, v); 1930 1931 Label ifNonNull = new Label(); 1932 Label afterAll = new Label(); 1933 1934 v.dup(); 1935 v.ifnonnull(ifNonNull); 1936 1937 // if null: pop function value and wrapper objects, put null 1938 v.pop(); 1939 v.pop2(); 1940 v.aconst(null); 1941 v.goTo(afterAll); 1942 1943 v.mark(ifNonNull); 1944 v.invokespecial(className.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, functionType)); 1945 1946 v.mark(afterAll); 1947 return StackValue.onStack(className.getAsmType()); 1948 } 1949 } 1950 1951 @NotNull 1952 private PropertyDescriptor accessiblePropertyDescriptor(PropertyDescriptor propertyDescriptor) { 1953 return context.accessiblePropertyDescriptor(propertyDescriptor); 1954 } 1955 1956 @NotNull 1957 protected FunctionDescriptor accessibleFunctionDescriptor(FunctionDescriptor fd) { 1958 return context.accessibleFunctionDescriptor(fd); 1959 } 1960 1961 @NotNull 1962 public StackValue invokeFunction( 1963 Call call, 1964 StackValue receiver, 1965 ResolvedCall<? extends CallableDescriptor> resolvedCall 1966 ) { 1967 FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 1968 boolean superCall = isSuperCall(call); 1969 1970 if (superCall && !isInterface(fd.getContainingDeclaration())) { 1971 JetSuperExpression expression = getSuperCallExpression(call); 1972 ClassDescriptor owner = getSuperCallLabelTarget(expression); 1973 CodegenContext c = context.findParentContextWithDescriptor(owner); 1974 assert c != null : "Couldn't find a context for a super-call: " + fd; 1975 if (c != context.getParentContext()) { 1976 fd = (FunctionDescriptor) c.getAccessor(fd); 1977 } 1978 } 1979 1980 fd = accessibleFunctionDescriptor(fd); 1981 1982 Callable callable = resolveToCallable(fd, superCall); 1983 if (callable instanceof CallableMethod) { 1984 CallableMethod callableMethod = (CallableMethod) callable; 1985 invokeMethodWithArguments(callableMethod, resolvedCall, call, receiver); 1986 1987 Type callReturnType = callableMethod.getSignature().getAsmMethod().getReturnType(); 1988 return returnValueAsStackValue(fd, callReturnType); 1989 } 1990 else { 1991 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 1992 1993 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 1994 List<JetExpression> args = new ArrayList<JetExpression>(); 1995 for (ValueArgument argument : call.getValueArguments()) { 1996 args.add(argument.getArgumentExpression()); 1997 } 1998 JetType type = resolvedCall.getCandidateDescriptor().getReturnType(); 1999 assert type != null; 2000 Type callType = typeMapper.mapType(type); 2001 2002 Type exprType = asmTypeOrVoid(type); 2003 StackValue stackValue = intrinsic.generate(this, v, callType, call.getCallElement(), args, receiver, state); 2004 stackValue.put(exprType, v); 2005 return StackValue.onStack(exprType); 2006 } 2007 } 2008 2009 @Nullable 2010 private static JetSuperExpression getSuperCallExpression(@NotNull Call call) { 2011 ReceiverValue explicitReceiver = call.getExplicitReceiver(); 2012 if (explicitReceiver instanceof ExpressionReceiver) { 2013 JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression(); 2014 if (receiverExpression instanceof JetSuperExpression) { 2015 return (JetSuperExpression) receiverExpression; 2016 } 2017 } 2018 return null; 2019 } 2020 2021 private static boolean isSuperCall(@NotNull Call call) { 2022 return getSuperCallExpression(call) != null; 2023 } 2024 2025 // Find the first parent of the current context which corresponds to a subclass of a given class 2026 @NotNull 2027 private static CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor, CodegenContext context) { 2028 CodegenContext c = context; 2029 while (true) { 2030 if (c instanceof ClassContext && DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) { 2031 return c; 2032 } 2033 c = c.getParentContext(); 2034 assert c != null; 2035 } 2036 } 2037 2038 @NotNull 2039 private StackValue returnValueAsStackValue(FunctionDescriptor fd, Type callReturnType) { 2040 if (callReturnType != Type.VOID_TYPE) { 2041 JetType type = fd.getReturnType(); 2042 assert type != null; 2043 Type retType = typeMapper.mapReturnType(type); 2044 StackValue.coerce(callReturnType, retType, v); 2045 return StackValue.onStack(retType); 2046 } 2047 return StackValue.none(); 2048 } 2049 2050 @NotNull 2051 Callable resolveToCallable(@NotNull FunctionDescriptor fd, boolean superCall) { 2052 IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(fd); 2053 if (intrinsic != null) { 2054 return intrinsic; 2055 } 2056 2057 return resolveToCallableMethod(fd, superCall, context); 2058 } 2059 2060 @NotNull 2061 private CallableMethod resolveToCallableMethod(@NotNull FunctionDescriptor fd, boolean superCall, @NotNull CodegenContext context) { 2062 if (isCallAsFunctionObject(fd)) { 2063 return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd)); 2064 } 2065 else { 2066 SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil 2067 .getOriginalIfSamAdapter(bindingContext, fd); 2068 return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall, 2069 isCallInsideSameClassAsDeclared(fd, context), 2070 isCallInsideSameModuleAsDeclared(fd, context), 2071 OwnerKind.IMPLEMENTATION); 2072 } 2073 } 2074 2075 private boolean isCallAsFunctionObject(FunctionDescriptor fd) { 2076 if (fd.getContainingDeclaration() instanceof ScriptDescriptor) { 2077 JetNamedFunction psi = (JetNamedFunction) descriptorToDeclaration(bindingContext, fd); 2078 assert psi != null; 2079 return !JetPsiUtil.isScriptDeclaration(psi); 2080 } 2081 else if (fd instanceof ExpressionAsFunctionDescriptor) { 2082 return true; 2083 } 2084 else if (fd instanceof SimpleFunctionDescriptor && 2085 (fd.getContainingDeclaration() instanceof FunctionDescriptor || 2086 fd.getContainingDeclaration() instanceof ScriptDescriptor)) { 2087 return true; 2088 } 2089 else { 2090 return false; 2091 } 2092 } 2093 2094 2095 public void invokeMethodWithArguments( 2096 @NotNull CallableMethod callableMethod, 2097 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 2098 @Nullable Call callToGenerateCallee, 2099 @NotNull StackValue receiver 2100 ) { 2101 Type calleeType = callableMethod.getGenerateCalleeType(); 2102 if (calleeType != null) { 2103 assert !callableMethod.isNeedsThis(); 2104 assert callToGenerateCallee != null : "Call can't be null when generating callee: " + resolvedCall.getResultingDescriptor(); 2105 gen(callToGenerateCallee.getCalleeExpression(), calleeType); 2106 } 2107 2108 if (resolvedCall instanceof VariableAsFunctionResolvedCall) { 2109 resolvedCall = ((VariableAsFunctionResolvedCall) resolvedCall).getFunctionCall(); 2110 } 2111 2112 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2113 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2114 receiver.put(receiver.type, v); 2115 if (calleeType != null) { 2116 StackValue.onStack(receiver.type).put(boxType(receiver.type), v); 2117 } 2118 } 2119 2120 int mask = pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes()); 2121 if (mask == 0) { 2122 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 2123 } 2124 else { 2125 callableMethod.invokeDefaultWithNotNullAssertion(v, state, resolvedCall, mask); 2126 } 2127 } 2128 2129 private void genThisAndReceiverFromResolvedCall( 2130 StackValue receiver, 2131 ResolvedCall<? extends CallableDescriptor> resolvedCall, 2132 CallableMethod callableMethod 2133 ) { 2134 receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); 2135 receiver.put(receiver.type, v); 2136 } 2137 2138 public void generateFromResolvedCall(@NotNull ReceiverValue descriptor, @NotNull Type type) { 2139 if (descriptor instanceof ClassReceiver) { 2140 Type exprType = asmType(descriptor.getType()); 2141 ClassReceiver classReceiver = (ClassReceiver) descriptor; 2142 ClassDescriptor classReceiverDeclarationDescriptor = classReceiver.getDeclarationDescriptor(); 2143 if (DescriptorUtils.isClassObject(classReceiverDeclarationDescriptor)) { 2144 if (context.getContextDescriptor() instanceof FunctionDescriptor && 2145 classReceiverDeclarationDescriptor == context.getContextDescriptor().getContainingDeclaration()) { 2146 v.load(0, OBJECT_TYPE); 2147 } 2148 else { 2149 FieldInfo info = FieldInfo.createForSingleton(classReceiverDeclarationDescriptor, typeMapper); 2150 v.getstatic(info.getOwnerInternalName(), info.getFieldName(), info.getFieldType().getDescriptor()); 2151 } 2152 StackValue.onStack(exprType).put(type, v); 2153 } 2154 else { 2155 StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v); 2156 } 2157 } 2158 else if (descriptor instanceof ScriptReceiver) { 2159 generateScript((ScriptReceiver) descriptor); 2160 } 2161 else if (descriptor instanceof ExtensionReceiver) { 2162 ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor; 2163 generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v); 2164 } 2165 else if (descriptor instanceof ExpressionReceiver) { 2166 ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor; 2167 JetExpression expr = expressionReceiver.getExpression(); 2168 gen(expr, type); 2169 } 2170 else if (descriptor instanceof AutoCastReceiver) { 2171 AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor; 2172 Type originalType = asmType(autoCastReceiver.getOriginal().getType()); 2173 generateFromResolvedCall(autoCastReceiver.getOriginal(), originalType); 2174 StackValue.onStack(originalType).put(type, v); 2175 } 2176 else { 2177 throw new UnsupportedOperationException("Unsupported receiver type: " + descriptor); 2178 } 2179 } 2180 2181 @Nullable 2182 private static JetExpression getReceiverForSelector(PsiElement expression) { 2183 if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) { 2184 JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent(); 2185 return parent.getReceiverExpression(); 2186 } 2187 return null; 2188 } 2189 2190 private StackValue generateReceiver(DeclarationDescriptor provided) { 2191 if (context.getCallableDescriptorWithReceiver() == provided) { 2192 StackValue result = context.getReceiverExpression(typeMapper); 2193 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2194 } 2195 2196 StackValue result = context.lookupInContext(provided, StackValue.local(0, OBJECT_TYPE), state, false); 2197 return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); 2198 } 2199 2200 private void generateScript(@NotNull ScriptReceiver receiver) { 2201 CodegenContext cur = context; 2202 StackValue result = StackValue.local(0, OBJECT_TYPE); 2203 while (cur != null) { 2204 if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { 2205 cur = cur.getParentContext(); 2206 } 2207 2208 if (cur instanceof ScriptContext) { 2209 ScriptContext scriptContext = (ScriptContext) cur; 2210 2211 JvmClassName currentScriptClassName = 2212 classNameForScriptDescriptor(bindingContext, 2213 scriptContext.getScriptDescriptor()); 2214 if (scriptContext.getScriptDescriptor() == receiver.getDeclarationDescriptor()) { 2215 result.put(currentScriptClassName.getAsmType(), v); 2216 } 2217 else { 2218 JvmClassName className = 2219 classNameForScriptDescriptor(bindingContext, 2220 receiver.getDeclarationDescriptor()); 2221 String fieldName = state.getScriptCodegen().getScriptFieldName(receiver.getDeclarationDescriptor()); 2222 result.put(currentScriptClassName.getAsmType(), v); 2223 StackValue.field(className.getAsmType(), currentScriptClassName, fieldName, false).put(className.getAsmType(), v); 2224 } 2225 return; 2226 } 2227 2228 assert cur != null; 2229 result = cur.getOuterExpression(result, false); 2230 2231 if (cur instanceof ConstructorContext) { 2232 cur = cur.getParentContext(); 2233 } 2234 assert cur != null; 2235 cur = cur.getParentContext(); 2236 } 2237 2238 throw new UnsupportedOperationException(); 2239 } 2240 2241 public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { 2242 boolean isSingleton = CodegenBinding.isSingleton(bindingContext, calleeContainingClass); 2243 if (isSingleton) { 2244 assert !isSuper; 2245 2246 if (context.hasThisDescriptor() && context.getThisDescriptor().equals(calleeContainingClass)) { 2247 return StackValue.local(0, typeMapper.mapType(calleeContainingClass)); 2248 } 2249 else { 2250 return StackValue.singleton(calleeContainingClass, typeMapper); 2251 } 2252 } 2253 2254 CodegenContext cur = context; 2255 Type type = asmType(calleeContainingClass.getDefaultType()); 2256 StackValue result = StackValue.local(0, type); 2257 while (cur != null) { 2258 if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { 2259 cur = cur.getParentContext(); 2260 } 2261 2262 assert cur != null; 2263 ClassDescriptor thisDescriptor = cur.getThisDescriptor(); 2264 if (!isSuper && thisDescriptor.equals(calleeContainingClass) 2265 || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { 2266 return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); 2267 } 2268 2269 result = cur.getOuterExpression(result, false); 2270 2271 if (cur instanceof ConstructorContext) { 2272 cur = cur.getParentContext(); 2273 } 2274 assert cur != null; 2275 cur = cur.getParentContext(); 2276 } 2277 2278 throw new UnsupportedOperationException(); 2279 } 2280 2281 private static boolean isReceiver(PsiElement expression) { 2282 PsiElement parent = expression.getParent(); 2283 if (parent instanceof JetQualifiedExpression) { 2284 JetExpression receiverExpression = ((JetQualifiedExpression) parent).getReceiverExpression(); 2285 return expression == receiverExpression; 2286 } 2287 return false; 2288 } 2289 2290 private int pushMethodArguments(@NotNull ResolvedCall resolvedCall, List<Type> valueParameterTypes) { 2291 @SuppressWarnings("unchecked") 2292 List<ResolvedValueArgument> valueArguments = resolvedCall.getValueArgumentsByIndex(); 2293 CallableDescriptor fd = resolvedCall.getResultingDescriptor(); 2294 2295 if (fd.getValueParameters().size() != valueArguments.size()) { 2296 throw new IllegalStateException(); 2297 } 2298 2299 int mask = 0; 2300 2301 for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) { 2302 ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex()); 2303 Type parameterType = valueParameterTypes.get(valueParameter.getIndex()); 2304 if (resolvedValueArgument instanceof ExpressionValueArgument) { 2305 ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument(); 2306 assert valueArgument != null; 2307 JetExpression argumentExpression = valueArgument.getArgumentExpression(); 2308 assert argumentExpression != null : valueArgument.asElement().getText(); 2309 2310 gen(argumentExpression, parameterType); 2311 } 2312 else if (resolvedValueArgument instanceof DefaultValueArgument) { 2313 pushDefaultValueOnStack(parameterType, v); 2314 mask |= (1 << valueParameter.getIndex()); 2315 } 2316 else if (resolvedValueArgument instanceof VarargValueArgument) { 2317 VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; 2318 genVarargs(valueParameter, valueArgument); 2319 } 2320 else { 2321 throw new UnsupportedOperationException(); 2322 } 2323 } 2324 return mask; 2325 } 2326 2327 public void genVarargs(ValueParameterDescriptor valueParameterDescriptor, VarargValueArgument valueArgument) { 2328 JetType outType = valueParameterDescriptor.getType(); 2329 2330 Type type = asmType(outType); 2331 assert type.getSort() == Type.ARRAY; 2332 Type elementType = correctElementType(type); 2333 List<ValueArgument> arguments = valueArgument.getArguments(); 2334 int size = arguments.size(); 2335 2336 boolean hasSpread = false; 2337 for (int i = 0; i != size; ++i) { 2338 if (arguments.get(i).getSpreadElement() != null) { 2339 hasSpread = true; 2340 break; 2341 } 2342 } 2343 2344 if (hasSpread) { 2345 if (size == 1) { 2346 gen(arguments.get(0).getArgumentExpression(), type); 2347 } 2348 else { 2349 String owner = "jet/runtime/Intrinsics$SpreadBuilder"; 2350 v.anew(Type.getObjectType(owner)); 2351 v.dup(); 2352 v.invokespecial(owner, "<init>", "()V"); 2353 for (int i = 0; i != size; ++i) { 2354 v.dup(); 2355 ValueArgument argument = arguments.get(i); 2356 if (argument.getSpreadElement() != null) { 2357 gen(argument.getArgumentExpression(), OBJECT_TYPE); 2358 v.invokevirtual(owner, "addSpread", "(Ljava/lang/Object;)V"); 2359 } 2360 else { 2361 gen(argument.getArgumentExpression(), elementType); 2362 v.invokevirtual(owner, "add", "(Ljava/lang/Object;)Z"); 2363 v.pop(); 2364 } 2365 } 2366 v.dup(); 2367 v.invokevirtual(owner, "size", "()I"); 2368 v.newarray(elementType); 2369 v.invokevirtual(owner, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); 2370 v.checkcast(type); 2371 } 2372 } 2373 else { 2374 v.iconst(arguments.size()); 2375 v.newarray(elementType); 2376 for (int i = 0; i != size; ++i) { 2377 v.dup(); 2378 v.iconst(i); 2379 gen(arguments.get(i).getArgumentExpression(), elementType); 2380 StackValue.arrayElement(elementType, false).store(elementType, v); 2381 } 2382 } 2383 } 2384 2385 public int pushMethodArguments(JetCallElement expression, List<Type> valueParameterTypes) { 2386 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2387 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); 2388 if (resolvedCall != null) { 2389 return pushMethodArguments(resolvedCall, valueParameterTypes); 2390 } 2391 else { 2392 List<? extends ValueArgument> args = expression.getValueArguments(); 2393 for (int i = 0, argsSize = args.size(); i < argsSize; i++) { 2394 ValueArgument arg = args.get(i); 2395 gen(arg.getArgumentExpression(), valueParameterTypes.get(i)); 2396 } 2397 return 0; 2398 } 2399 } 2400 2401 @NotNull 2402 public Type expressionType(JetExpression expr) { 2403 return typeMapper.expressionType(expr); 2404 } 2405 2406 public int indexOfLocal(JetReferenceExpression lhs) { 2407 DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, lhs); 2408 if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) { 2409 return -1; 2410 } 2411 return lookupLocalIndex(declarationDescriptor); 2412 } 2413 2414 @Override 2415 public StackValue visitCallableReferenceExpression(JetCallableReferenceExpression expression, StackValue data) { 2416 // TODO: properties 2417 final FunctionDescriptor functionDescriptor = bindingContext.get(CALLABLE_REFERENCE, expression); 2418 assert functionDescriptor != null : "Callable reference is not resolved to descriptor: " + expression.getText(); 2419 2420 final ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, expression.getCallableReference()); 2421 assert resolvedCall != null : "Callable reference is not resolved: " + functionDescriptor + " " + expression.getText(); 2422 2423 JetType kFunctionType = bindingContext.get(EXPRESSION_TYPE, expression); 2424 assert kFunctionType != null : "Callable reference is not type checked: " + expression.getText(); 2425 ClassDescriptor kFunctionImpl = functionTypeToImpl(kFunctionType); 2426 assert kFunctionImpl != null : "Impl type is not found for the function type: " + kFunctionType; 2427 2428 JvmClassName closureSuperClass = JvmClassName.byType(typeMapper.mapType(kFunctionImpl)); 2429 2430 ClosureCodegen closureCodegen = new ClosureCodegen(state, expression, functionDescriptor, null, closureSuperClass, context, this, 2431 new FunctionGenerationStrategy.CodegenBased<CallableDescriptor>(state, functionDescriptor) { 2432 2433 @NotNull 2434 @Override 2435 public ExpressionCodegen initializeExpressionCodegen( 2436 JvmMethodSignature signature, MethodContext context, MethodVisitor mv, 2437 Type returnType 2438 ) { 2439 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2440 JetType returnJetType = referencedFunction.getReturnType(); 2441 assert returnJetType != null : "Return type can't be null: " + referencedFunction; 2442 2443 return super.initializeExpressionCodegen(signature, context, 2444 mv, typeMapper.mapReturnType(returnJetType)); 2445 } 2446 2447 @Override 2448 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 2449 /* 2450 Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation 2451 of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of 2452 ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every 2453 argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of 2454 every argument boils down to calling LOAD with the corresponding index 2455 */ 2456 2457 FunctionDescriptor referencedFunction = (FunctionDescriptor) resolvedCall.getResultingDescriptor(); 2458 2459 JetCallExpression fakeExpression = constructFakeFunctionCall(referencedFunction); 2460 final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments(); 2461 2462 final ReceiverValue receiverValue = computeAndSaveReceiver(signature, codegen); 2463 computeAndSaveArguments(codegen.myFrameMap, fakeArguments, codegen); 2464 2465 ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) { 2466 @NotNull 2467 @Override 2468 public ReceiverValue getReceiverArgument() { 2469 return resolvedCall.getExplicitReceiverKind() == RECEIVER_ARGUMENT ? receiverValue : NO_RECEIVER; 2470 } 2471 2472 @NotNull 2473 @Override 2474 public ReceiverValue getThisObject() { 2475 return resolvedCall.getExplicitReceiverKind() == THIS_OBJECT ? receiverValue : NO_RECEIVER; 2476 } 2477 2478 @NotNull 2479 @Override 2480 public List<ResolvedValueArgument> getValueArgumentsByIndex() { 2481 List<ResolvedValueArgument> result = new ArrayList<ResolvedValueArgument>(fakeArguments.size()); 2482 for (ValueArgument argument : fakeArguments) { 2483 result.add(new ExpressionValueArgument(argument)); 2484 } 2485 return result; 2486 } 2487 }; 2488 2489 StackValue result; 2490 Type returnType = codegen.returnType; 2491 if (referencedFunction instanceof ConstructorDescriptor) { 2492 if (returnType.getSort() == Type.ARRAY) { 2493 JetType returnJetType = referencedFunction.getReturnType(); 2494 assert returnJetType != null; 2495 codegen.generateNewArray(fakeExpression, returnJetType); 2496 result = StackValue.onStack(returnType); 2497 } 2498 else { 2499 result = codegen.generateConstructorCall(fakeResolvedCall, StackValue.none(), returnType); 2500 } 2501 } 2502 else { 2503 Call call = CallMaker.makeCall(fakeExpression, NO_RECEIVER, null, fakeExpression, fakeArguments); 2504 result = codegen.invokeFunction(call, StackValue.none(), fakeResolvedCall); 2505 } 2506 2507 InstructionAdapter v = codegen.v; 2508 result.put(returnType, v); 2509 v.areturn(returnType); 2510 } 2511 2512 @NotNull 2513 private JetCallExpression constructFakeFunctionCall(@NotNull CallableDescriptor referencedFunction) { 2514 StringBuilder fakeFunctionCall = new StringBuilder("callableReferenceFakeCall("); 2515 for (Iterator<ValueParameterDescriptor> iterator = referencedFunction.getValueParameters().iterator(); 2516 iterator.hasNext(); ) { 2517 ValueParameterDescriptor descriptor = iterator.next(); 2518 fakeFunctionCall.append("p").append(descriptor.getIndex()); 2519 if (iterator.hasNext()) { 2520 fakeFunctionCall.append(", "); 2521 } 2522 } 2523 fakeFunctionCall.append(")"); 2524 return (JetCallExpression) JetPsiFactory.createExpression(state.getProject(), fakeFunctionCall.toString()); 2525 } 2526 2527 private void computeAndSaveArguments( 2528 @NotNull FrameMap frameMap, 2529 @NotNull List<? extends ValueArgument> fakeArguments, 2530 @NotNull ExpressionCodegen codegen 2531 ) { 2532 for (ValueParameterDescriptor parameter : functionDescriptor.getValueParameters()) { 2533 ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex()); 2534 Type type = typeMapper.mapType(parameter); 2535 int localIndex = frameMap.getIndex(parameter); 2536 codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type)); 2537 } 2538 } 2539 2540 @NotNull 2541 private ReceiverValue computeAndSaveReceiver( 2542 @NotNull JvmMethodSignature signature, 2543 @NotNull ExpressionCodegen codegen 2544 ) { 2545 CallableDescriptor referencedFunction = resolvedCall.getCandidateDescriptor(); 2546 2547 ReceiverParameterDescriptor receiverParameter = referencedFunction.getReceiverParameter(); 2548 ReceiverParameterDescriptor expectedThisObject = referencedFunction.getExpectedThisObject(); 2549 assert receiverParameter == null || expectedThisObject == null : 2550 "Extensions in classes can't be referenced via callable reference expressions: " + referencedFunction; 2551 2552 ReceiverParameterDescriptor receiver = receiverParameter != null ? receiverParameter : expectedThisObject; 2553 2554 if (receiver == null) { 2555 return NO_RECEIVER; 2556 } 2557 2558 JetExpression receiverExpression = JetPsiFactory.createExpression(state.getProject(), 2559 "callableReferenceFakeReceiver"); 2560 2561 Type firstParameterType = signature.getAsmMethod().getArgumentTypes()[0]; 2562 // 0 is this (the closure class), 1 is the method's first parameter 2563 codegen.tempVariables.put(receiverExpression, StackValue.local(1, firstParameterType)); 2564 2565 return new ExpressionReceiver(receiverExpression, receiver.getType()); 2566 } 2567 } 2568 ); 2569 2570 closureCodegen.gen(); 2571 2572 return closureCodegen.putInstanceOnStack(v, this); 2573 } 2574 2575 @Override 2576 public StackValue visitDotQualifiedExpression(JetDotQualifiedExpression expression, StackValue receiver) { 2577 StackValue receiverValue = StackValue.none(); 2578 return genQualified(receiverValue, expression.getSelectorExpression()); 2579 } 2580 2581 @Override 2582 public StackValue visitSafeQualifiedExpression(JetSafeQualifiedExpression expression, StackValue receiver) { 2583 JetExpression expr = expression.getReceiverExpression(); 2584 Type receiverType = expressionType(expr); 2585 gen(expr, receiverType); 2586 if (isPrimitive(receiverType)) { 2587 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2588 Type type = boxType(propValue.type); 2589 propValue.put(type, v); 2590 2591 return StackValue.onStack(type); 2592 } 2593 else { 2594 Label ifnull = new Label(); 2595 Label end = new Label(); 2596 v.dup(); 2597 v.ifnull(ifnull); 2598 StackValue propValue = genQualified(StackValue.onStack(receiverType), expression.getSelectorExpression()); 2599 Type type = boxType(propValue.type); 2600 propValue.put(type, v); 2601 v.goTo(end); 2602 2603 v.mark(ifnull); 2604 v.pop(); 2605 if (!type.equals(Type.VOID_TYPE)) { 2606 v.aconst(null); 2607 } 2608 v.mark(end); 2609 2610 return StackValue.onStack(type); 2611 } 2612 } 2613 2614 @Override 2615 public StackValue visitBinaryExpression(JetBinaryExpression expression, StackValue receiver) { 2616 IElementType opToken = expression.getOperationReference().getReferencedNameElementType(); 2617 if (opToken == JetTokens.EQ) { 2618 return generateAssignmentExpression(expression); 2619 } 2620 else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { 2621 return generateAugmentedAssignment(expression); 2622 } 2623 else if (opToken == JetTokens.ANDAND) { 2624 return generateBooleanAnd(expression); 2625 } 2626 else if (opToken == JetTokens.OROR) { 2627 return generateBooleanOr(expression); 2628 } 2629 else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ || 2630 opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) { 2631 return generateEquals(expression.getLeft(), expression.getRight(), opToken); 2632 } 2633 else if (opToken == JetTokens.LT || opToken == JetTokens.LTEQ || 2634 opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { 2635 return generateComparison(expression); 2636 } 2637 else if (opToken == JetTokens.ELVIS) { 2638 return generateElvis(expression); 2639 } 2640 else if (opToken == JetTokens.IN_KEYWORD || opToken == JetTokens.NOT_IN) { 2641 return generateIn(expression); 2642 } 2643 else { 2644 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2645 assert op instanceof FunctionDescriptor : String.valueOf(op); 2646 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2647 if (callable instanceof IntrinsicMethod) { 2648 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2649 return intrinsic.generate(this, v, expressionType(expression), expression, 2650 Arrays.asList(expression.getLeft(), expression.getRight()), receiver, state); 2651 } 2652 else { 2653 return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable); 2654 } 2655 } 2656 } 2657 2658 private StackValue generateIn(JetBinaryExpression expression) { 2659 boolean inverted = expression.getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IN; 2660 if (isIntRangeExpr(expression.getRight())) { 2661 StackValue leftValue = StackValue.expression(Type.INT_TYPE, expression.getLeft(), this); 2662 JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getRight(); 2663 getInIntRange(leftValue, rangeExpression, inverted); 2664 } 2665 else { 2666 invokeFunctionByReference(expression.getOperationReference()); 2667 if (inverted) { 2668 genInvertBoolean(v); 2669 } 2670 } 2671 return StackValue.onStack(Type.BOOLEAN_TYPE); 2672 } 2673 2674 private void getInIntRange(StackValue leftValue, JetBinaryExpression rangeExpression, boolean inverted) { 2675 v.iconst(1); 2676 // 1 2677 leftValue.put(Type.INT_TYPE, v); 2678 // 1 l 2679 v.dup2(); 2680 // 1 l 1 l 2681 2682 //noinspection ConstantConditions 2683 gen(rangeExpression.getLeft(), Type.INT_TYPE); 2684 // 1 l 1 l r 2685 Label lok = new Label(); 2686 v.ificmpge(lok); 2687 // 1 l 1 2688 v.pop(); 2689 v.iconst(0); 2690 v.mark(lok); 2691 // 1 l c 2692 v.dupX2(); 2693 // c 1 l c 2694 v.pop(); 2695 // c 1 l 2696 2697 gen(rangeExpression.getRight(), Type.INT_TYPE); 2698 // c 1 l r 2699 Label rok = new Label(); 2700 v.ificmple(rok); 2701 // c 1 2702 v.pop(); 2703 v.iconst(0); 2704 v.mark(rok); 2705 // c c 2706 2707 v.and(Type.INT_TYPE); 2708 if (inverted) { 2709 genInvertBoolean(v); 2710 } 2711 } 2712 2713 private StackValue generateBooleanAnd(JetBinaryExpression expression) { 2714 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2715 Label ifFalse = new Label(); 2716 v.ifeq(ifFalse); 2717 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2718 Label end = new Label(); 2719 v.goTo(end); 2720 v.mark(ifFalse); 2721 v.iconst(0); 2722 v.mark(end); 2723 return StackValue.onStack(Type.BOOLEAN_TYPE); 2724 } 2725 2726 private StackValue generateBooleanOr(JetBinaryExpression expression) { 2727 gen(expression.getLeft(), Type.BOOLEAN_TYPE); 2728 Label ifTrue = new Label(); 2729 v.ifne(ifTrue); 2730 gen(expression.getRight(), Type.BOOLEAN_TYPE); 2731 Label end = new Label(); 2732 v.goTo(end); 2733 v.mark(ifTrue); 2734 v.iconst(1); 2735 v.mark(end); 2736 return StackValue.onStack(Type.BOOLEAN_TYPE); 2737 } 2738 2739 private StackValue generateEquals(JetExpression left, JetExpression right, IElementType opToken) { 2740 Type leftType = expressionType(left); 2741 Type rightType = expressionType(right); 2742 2743 if (JetPsiUtil.isNullConstant(left)) { 2744 return genCmpWithNull(right, rightType, opToken); 2745 } 2746 2747 if (JetPsiUtil.isNullConstant(right)) { 2748 return genCmpWithNull(left, leftType, opToken); 2749 } 2750 2751 if (isIntZero(left, leftType) && isIntPrimitive(rightType)) { 2752 return genCmpWithZero(right, rightType, opToken); 2753 } 2754 2755 if (isIntZero(right, rightType) && isIntPrimitive(leftType)) { 2756 return genCmpWithZero(left, leftType, opToken); 2757 } 2758 2759 if (isPrimitive(leftType) != isPrimitive(rightType)) { 2760 leftType = boxType(leftType); 2761 gen(left, leftType); 2762 rightType = boxType(rightType); 2763 gen(right, rightType); 2764 } 2765 else { 2766 gen(left, leftType); 2767 gen(right, rightType); 2768 } 2769 2770 return genEqualsForExpressionsOnStack(v, opToken, leftType, rightType); 2771 } 2772 2773 private boolean isIntZero(JetExpression expr, Type exprType) { 2774 CompileTimeConstant<?> exprValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr); 2775 return isIntPrimitive(exprType) && exprValue != null && exprValue.getValue().equals(0); 2776 } 2777 2778 private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) { 2779 v.iconst(1); 2780 gen(exp, expType); 2781 Label ok = new Label(); 2782 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2783 v.ifeq(ok); 2784 } 2785 else { 2786 v.ifne(ok); 2787 } 2788 v.pop(); 2789 v.iconst(0); 2790 v.mark(ok); 2791 return StackValue.onStack(Type.BOOLEAN_TYPE); 2792 } 2793 2794 private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) { 2795 v.iconst(1); 2796 gen(exp, boxType(expType)); 2797 Label ok = new Label(); 2798 if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) { 2799 v.ifnull(ok); 2800 } 2801 else { 2802 v.ifnonnull(ok); 2803 } 2804 v.pop(); 2805 v.iconst(0); 2806 v.mark(ok); 2807 return StackValue.onStack(Type.BOOLEAN_TYPE); 2808 } 2809 2810 private StackValue generateElvis(JetBinaryExpression expression) { 2811 Type exprType = expressionType(expression); 2812 Type leftType = expressionType(expression.getLeft()); 2813 2814 gen(expression.getLeft(), leftType); 2815 2816 if (isPrimitive(leftType)) { 2817 return StackValue.onStack(leftType); 2818 } 2819 2820 v.dup(); 2821 Label ifNull = new Label(); 2822 v.ifnull(ifNull); 2823 StackValue.onStack(leftType).put(exprType, v); 2824 Label end = new Label(); 2825 v.goTo(end); 2826 v.mark(ifNull); 2827 v.pop(); 2828 gen(expression.getRight(), exprType); 2829 v.mark(end); 2830 2831 return StackValue.onStack(exprType); 2832 } 2833 2834 private StackValue generateComparison(JetBinaryExpression expression) { 2835 DeclarationDescriptor target = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2836 assert target instanceof FunctionDescriptor : "compareTo target should be a function: " + target; 2837 FunctionDescriptor descriptor = (FunctionDescriptor) target; 2838 2839 JetExpression left = expression.getLeft(); 2840 JetExpression right = expression.getRight(); 2841 Callable callable = resolveToCallable(descriptor, false); 2842 2843 Type type; 2844 if (callable instanceof IntrinsicMethod) { 2845 // Compare two primitive values 2846 type = comparisonOperandType(expressionType(left), expressionType(right)); 2847 StackValue receiver = gen(left); 2848 receiver.put(type, v); 2849 gen(right, type); 2850 } 2851 else { 2852 type = Type.INT_TYPE; 2853 StackValue result = invokeOperation(expression, descriptor, (CallableMethod) callable); 2854 result.put(type, v); 2855 v.iconst(0); 2856 } 2857 return StackValue.cmp(expression.getOperationToken(), type); 2858 } 2859 2860 private StackValue generateAssignmentExpression(JetBinaryExpression expression) { 2861 StackValue stackValue = gen(expression.getLeft()); 2862 JetExpression right = expression.getRight(); 2863 assert right != null : expression.getText(); 2864 gen(right, stackValue.type); 2865 stackValue.store(stackValue.type, v); 2866 return StackValue.none(); 2867 } 2868 2869 private StackValue generateAugmentedAssignment(JetBinaryExpression expression) { 2870 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2871 assert op instanceof FunctionDescriptor : String.valueOf(op); 2872 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2873 JetExpression lhs = expression.getLeft(); 2874 2875 // if (lhs instanceof JetArrayAccessExpression) { 2876 // JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs; 2877 // if (arrayAccessExpression.getIndexExpressions().size() != 1) { 2878 // throw new UnsupportedOperationException("Augmented assignment with multi-index"); 2879 // } 2880 // } 2881 2882 Type lhsType = expressionType(lhs); 2883 //noinspection ConstantConditions 2884 if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { 2885 if (callable instanceof IntrinsicMethod) { 2886 StackValue value = gen(lhs); // receiver 2887 value.dupReceiver(v); // receiver receiver 2888 value.put(lhsType, v); // receiver lhs 2889 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2890 //noinspection NullableProblems 2891 JetExpression right = expression.getRight(); 2892 assert right != null; 2893 StackValue stackValue = intrinsic.generate(this, v, lhsType, expression, 2894 Arrays.asList(right), 2895 StackValue.onStack(lhsType), state); 2896 value.store(stackValue.type, v); 2897 } 2898 else { 2899 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true); 2900 } 2901 } 2902 else { 2903 JetType type = ((FunctionDescriptor) op).getReturnType(); 2904 assert type != null; 2905 boolean keepReturnValue = !type.equals(KotlinBuiltIns.getInstance().getUnitType()); 2906 callAugAssignMethod(expression, (CallableMethod) callable, lhsType, keepReturnValue); 2907 } 2908 2909 return StackValue.none(); 2910 } 2911 2912 private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, boolean keepReturnValue) { 2913 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2914 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2915 assert resolvedCall != null; 2916 2917 StackValue value = gen(expression.getLeft()); 2918 if (keepReturnValue) { 2919 value.dupReceiver(v); 2920 } 2921 value.put(lhsType, v); 2922 StackValue receiver = StackValue.onStack(lhsType); 2923 2924 if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already 2925 receiver = StackValue.receiver(resolvedCall, receiver, this, callable); 2926 receiver.put(receiver.type, v); 2927 } 2928 2929 pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); 2930 callable.invokeWithNotNullAssertion(v, state, resolvedCall); 2931 if (keepReturnValue) { 2932 value.store(callable.getReturnType(), v); 2933 } 2934 } 2935 2936 public void invokeAppend(JetExpression expr) { 2937 if (expr instanceof JetBinaryExpression) { 2938 JetBinaryExpression binaryExpression = (JetBinaryExpression) expr; 2939 if (binaryExpression.getOperationToken() == JetTokens.PLUS) { 2940 JetExpression left = binaryExpression.getLeft(); 2941 JetExpression right = binaryExpression.getRight(); 2942 Type leftType = expressionType(left); 2943 Type rightType = expressionType(right); 2944 2945 if (leftType.equals(JAVA_STRING_TYPE) && rightType.equals(JAVA_STRING_TYPE)) { 2946 invokeAppend(left); 2947 invokeAppend(right); 2948 return; 2949 } 2950 } 2951 } 2952 Type exprType = expressionType(expr); 2953 gen(expr, exprType); 2954 genInvokeAppendMethod(v, exprType.getSort() == Type.ARRAY ? OBJECT_TYPE : exprType); 2955 } 2956 2957 @Nullable 2958 private static JetSimpleNameExpression targetLabel(JetExpression expression) { 2959 if (expression.getParent() instanceof JetPrefixExpression) { 2960 JetPrefixExpression parent = (JetPrefixExpression) expression.getParent(); 2961 JetSimpleNameExpression operationSign = parent.getOperationReference(); 2962 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2963 return operationSign; 2964 } 2965 } 2966 return null; 2967 } 2968 2969 @Override 2970 public StackValue visitPrefixExpression(JetPrefixExpression expression, StackValue receiver) { 2971 JetSimpleNameExpression operationSign = expression.getOperationReference(); 2972 if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { 2973 return genQualified(receiver, expression.getBaseExpression()); 2974 } 2975 2976 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 2977 assert op instanceof FunctionDescriptor : String.valueOf(op); 2978 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 2979 if (callable instanceof IntrinsicMethod) { 2980 IntrinsicMethod intrinsic = (IntrinsicMethod) callable; 2981 //noinspection ConstantConditions 2982 return intrinsic.generate(this, v, expressionType(expression), expression, 2983 Arrays.asList(expression.getBaseExpression()), receiver, state); 2984 } 2985 else { 2986 DeclarationDescriptor cls = op.getContainingDeclaration(); 2987 CallableMethod callableMethod = (CallableMethod) callable; 2988 if (isPrimitiveNumberClassDescriptor(cls) || !(op.getName().asString().equals("inc") || op.getName().asString().equals("dec"))) { 2989 return invokeOperation(expression, (FunctionDescriptor) op, callableMethod); 2990 } 2991 else { 2992 ResolvedCall<? extends CallableDescriptor> resolvedCall = 2993 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 2994 assert resolvedCall != null; 2995 2996 StackValue value = gen(expression.getBaseExpression()); 2997 value.dupReceiver(v); 2998 value.dupReceiver(v); 2999 3000 Type type = expressionType(expression.getBaseExpression()); 3001 value.put(type, v); 3002 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3003 3004 value.store(callableMethod.getReturnType(), v); 3005 value.put(type, v); 3006 return StackValue.onStack(type); 3007 } 3008 } 3009 } 3010 3011 private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) { 3012 int functionLocalIndex = lookupLocalIndex(op); 3013 if (functionLocalIndex >= 0) { 3014 stackValueForLocal(op, functionLocalIndex).put(getFunctionImplClassName(op).getAsmType(), v); 3015 } 3016 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3017 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3018 assert resolvedCall != null; 3019 genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable); 3020 pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); 3021 callable.invokeWithNotNullAssertion(v, state, resolvedCall); 3022 3023 return returnValueAsStackValue(op, callable.getSignature().getAsmMethod().getReturnType()); 3024 } 3025 3026 @Override 3027 public StackValue visitPostfixExpression(JetPostfixExpression expression, StackValue receiver) { 3028 if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL) { 3029 StackValue base = genQualified(receiver, expression.getBaseExpression()); 3030 if (isPrimitive(base.type)) { 3031 return base; 3032 } 3033 base.put(base.type, v); 3034 v.dup(); 3035 Label ok = new Label(); 3036 v.ifnonnull(ok); 3037 v.invokestatic("jet/runtime/Intrinsics", "throwNpe", "()V"); 3038 v.mark(ok); 3039 return StackValue.onStack(base.type); 3040 } 3041 3042 DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); 3043 if (!(op instanceof FunctionDescriptor)) { 3044 throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + op); 3045 } 3046 3047 Type asmType = expressionType(expression); 3048 DeclarationDescriptor cls = op.getContainingDeclaration(); 3049 3050 int increment; 3051 if (op.getName().asString().equals("inc")) { 3052 increment = 1; 3053 } 3054 else if (op.getName().asString().equals("dec")) { 3055 increment = -1; 3056 } 3057 else { 3058 throw new UnsupportedOperationException("Unsupported postfix operation: " + op); 3059 } 3060 3061 if (isPrimitiveNumberClassDescriptor(cls)) { 3062 receiver.put(receiver.type, v); 3063 JetExpression operand = expression.getBaseExpression(); 3064 if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { 3065 int index = indexOfLocal((JetReferenceExpression) operand); 3066 if (index >= 0) { 3067 return StackValue.postIncrement(index, increment); 3068 } 3069 } 3070 gen(operand, asmType); // old value 3071 generateIncrement(increment, asmType, operand, receiver); // increment in-place 3072 return StackValue.onStack(asmType); // old value 3073 } 3074 else { 3075 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3076 bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); 3077 assert resolvedCall != null; 3078 3079 Callable callable = resolveToCallable((FunctionDescriptor) op, false); 3080 3081 StackValue value = gen(expression.getBaseExpression()); 3082 value.dupReceiver(v); 3083 3084 Type type = expressionType(expression.getBaseExpression()); 3085 value.put(type, v); 3086 3087 switch (value.receiverSize()) { 3088 case 0: 3089 dup(v, type); 3090 break; 3091 3092 case 1: 3093 if (type.getSize() == 2) { 3094 v.dup2X1(); 3095 } 3096 else { 3097 v.dupX1(); 3098 } 3099 break; 3100 3101 case 2: 3102 if (type.getSize() == 2) { 3103 v.dup2X2(); 3104 } 3105 else { 3106 v.dupX2(); 3107 } 3108 break; 3109 3110 case -1: 3111 throw new UnsupportedOperationException(); 3112 } 3113 3114 CallableMethod callableMethod = (CallableMethod) callable; 3115 callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); 3116 3117 value.store(callableMethod.getReturnType(), v); 3118 return StackValue.onStack(type); 3119 } 3120 } 3121 3122 private void generateIncrement(int increment, Type asmType, JetExpression operand, StackValue receiver) { 3123 StackValue value = genQualified(receiver, operand); 3124 value.dupReceiver(v); 3125 value.put(asmType, v); 3126 genIncrement(asmType, increment, v); 3127 value.store(asmType, v); 3128 } 3129 3130 @Override 3131 public StackValue visitProperty(JetProperty property, StackValue receiver) { 3132 final JetExpression initializer = property.getInitializer(); 3133 if (initializer == null) { 3134 return StackValue.none(); 3135 } 3136 initializeLocalVariable(property, new Function<VariableDescriptor, Void>() { 3137 @Override 3138 public Void fun(VariableDescriptor descriptor) { 3139 Type varType = asmType(descriptor.getType()); 3140 gen(initializer, varType); 3141 return null; 3142 } 3143 }); 3144 return StackValue.none(); 3145 } 3146 3147 @Override 3148 public StackValue visitMultiDeclaration(JetMultiDeclaration multiDeclaration, StackValue receiver) { 3149 JetExpression initializer = multiDeclaration.getInitializer(); 3150 if (initializer == null) return StackValue.none(); 3151 3152 JetType initializerType = bindingContext.get(EXPRESSION_TYPE, initializer); 3153 assert initializerType != null; 3154 3155 Type initializerAsmType = asmType(initializerType); 3156 3157 final TransientReceiver initializerAsReceiver = new TransientReceiver(initializerType); 3158 3159 int tempVarIndex = myFrameMap.enterTemp(initializerAsmType); 3160 3161 gen(initializer, initializerAsmType); 3162 v.store(tempVarIndex, initializerAsmType); 3163 final StackValue.Local local = StackValue.local(tempVarIndex, initializerAsmType); 3164 3165 for (final JetMultiDeclarationEntry variableDeclaration : multiDeclaration.getEntries()) { 3166 initializeLocalVariable(variableDeclaration, new Function<VariableDescriptor, Void>() { 3167 @Override 3168 public Void fun(VariableDescriptor descriptor) { 3169 ResolvedCall<FunctionDescriptor> resolvedCall = 3170 bindingContext.get(BindingContext.COMPONENT_RESOLVED_CALL, variableDeclaration); 3171 assert resolvedCall != null : "Resolved call is null for " + variableDeclaration.getText(); 3172 Call call = makeFakeCall(initializerAsReceiver); 3173 invokeFunction(call, local, resolvedCall); 3174 return null; 3175 } 3176 }); 3177 } 3178 3179 if(initializerAsmType.getSort() == Type.OBJECT || initializerAsmType.getSort() == Type.ARRAY) { 3180 v.aconst(null); 3181 v.store(tempVarIndex, initializerAsmType); 3182 } 3183 myFrameMap.leaveTemp(initializerAsmType); 3184 3185 return StackValue.none(); 3186 } 3187 3188 private void initializeLocalVariable( 3189 @NotNull JetVariableDeclaration variableDeclaration, 3190 @NotNull Function<VariableDescriptor, Void> generateInitializer 3191 ) { 3192 3193 VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, variableDeclaration); 3194 3195 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3196 return; 3197 } 3198 int index = lookupLocalIndex(variableDescriptor); 3199 3200 if (index < 0) { 3201 throw new IllegalStateException("Local variable not found for " + variableDescriptor); 3202 } 3203 3204 Type sharedVarType = typeMapper.getSharedVarType(variableDescriptor); 3205 assert variableDescriptor != null; 3206 3207 Type varType = asmType(variableDescriptor.getType()); 3208 3209 if (JetPsiUtil.isScriptDeclaration(variableDeclaration)) { 3210 generateInitializer.fun(variableDescriptor); 3211 JetScript scriptPsi = JetPsiUtil.getScript(variableDeclaration); 3212 assert scriptPsi != null; 3213 JvmClassName scriptClassName = classNameForScriptPsi(bindingContext, scriptPsi); 3214 v.putfield(scriptClassName.getInternalName(), variableDeclaration.getName(), varType.getDescriptor()); 3215 } 3216 else if (sharedVarType == null) { 3217 generateInitializer.fun(variableDescriptor); 3218 v.store(index, varType); 3219 } 3220 else { 3221 v.load(index, OBJECT_TYPE); 3222 generateInitializer.fun(variableDescriptor); 3223 v.putfield(sharedVarType.getInternalName(), "ref", 3224 sharedVarType == JET_SHARED_VAR_TYPE ? "Ljava/lang/Object;" : varType.getDescriptor()); 3225 } 3226 } 3227 3228 @NotNull 3229 private StackValue generateNewCall( 3230 @NotNull JetCallExpression expression, 3231 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3232 @NotNull StackValue receiver 3233 ) { 3234 Type type = expressionType(expression); 3235 if (type.getSort() == Type.ARRAY) { 3236 generateNewArray(expression); 3237 return StackValue.onStack(type); 3238 } 3239 3240 return generateConstructorCall(resolvedCall, receiver, type); 3241 } 3242 3243 @NotNull 3244 private StackValue generateConstructorCall( 3245 @NotNull ResolvedCall<? extends CallableDescriptor> resolvedCall, 3246 @NotNull StackValue receiver, 3247 @NotNull Type type 3248 ) { 3249 v.anew(type); 3250 v.dup(); 3251 3252 receiver = StackValue.receiver(resolvedCall, receiver, this, null); 3253 receiver.put(receiver.type, v); 3254 3255 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 3256 MutableClosure closure = bindingContext.get(CLOSURE, constructorDescriptor.getContainingDeclaration()); 3257 3258 if (receiver.type.getSort() != Type.VOID && (closure == null || closure.getCaptureThis() == null)) { 3259 v.pop(); 3260 } 3261 3262 //Resolved call to local class constructor doesn't have resolvedCall.getThisObject() and resolvedCall.getReceiverArgument() 3263 //so we need generate closure on stack 3264 //See StackValue.receiver for more info 3265 pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists()); 3266 3267 ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil 3268 .getOriginalIfSamAdapter(bindingContext, constructorDescriptor); 3269 CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter); 3270 invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 3271 3272 return StackValue.onStack(type); 3273 } 3274 3275 public void generateNewArray(@NotNull JetCallExpression expression) { 3276 JetType arrayType = bindingContext.get(EXPRESSION_TYPE, expression); 3277 assert arrayType != null : "Array instantiation isn't type checked: " + expression.getText(); 3278 3279 generateNewArray(expression, arrayType); 3280 } 3281 3282 private void generateNewArray(@NotNull JetCallExpression expression, @NotNull JetType arrayType) { 3283 List<JetExpression> args = new ArrayList<JetExpression>(); 3284 for (ValueArgument va : expression.getValueArguments()) { 3285 args.add(va.getArgumentExpression()); 3286 } 3287 args.addAll(expression.getFunctionLiteralArguments()); 3288 3289 boolean isArray = KotlinBuiltIns.getInstance().isArray(arrayType); 3290 if (!isArray && args.size() != 1) { 3291 throw new CompilationException("primitive array constructor requires one argument", null, expression); 3292 } 3293 3294 if (isArray) { 3295 gen(args.get(0), Type.INT_TYPE); 3296 v.newarray(boxType(asmType(arrayType.getArguments().get(0).getType()))); 3297 } 3298 else { 3299 Type type = typeMapper.mapType(arrayType); 3300 gen(args.get(0), Type.INT_TYPE); 3301 v.newarray(correctElementType(type)); 3302 } 3303 3304 if (args.size() == 2) { 3305 int sizeIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3306 int indexIndex = myFrameMap.enterTemp(Type.INT_TYPE); 3307 3308 v.dup(); 3309 v.arraylength(); 3310 v.store(sizeIndex, Type.INT_TYPE); 3311 3312 v.iconst(0); 3313 v.store(indexIndex, Type.INT_TYPE); 3314 3315 gen(args.get(1), JET_FUNCTION1_TYPE); 3316 3317 Label begin = new Label(); 3318 Label end = new Label(); 3319 v.visitLabel(begin); 3320 v.load(indexIndex, Type.INT_TYPE); 3321 v.load(sizeIndex, Type.INT_TYPE); 3322 v.ificmpge(end); 3323 3324 v.dup2(); 3325 v.load(indexIndex, Type.INT_TYPE); 3326 v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 3327 v.invokeinterface("jet/Function1", "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;"); 3328 v.load(indexIndex, Type.INT_TYPE); 3329 v.iinc(indexIndex, 1); 3330 v.swap(); 3331 v.astore(OBJECT_TYPE); 3332 3333 v.goTo(begin); 3334 v.visitLabel(end); 3335 v.pop(); 3336 3337 myFrameMap.leaveTemp(Type.INT_TYPE); 3338 myFrameMap.leaveTemp(Type.INT_TYPE); 3339 } 3340 } 3341 3342 @Override 3343 public StackValue visitArrayAccessExpression(JetArrayAccessExpression expression, StackValue receiver) { 3344 JetExpression array = expression.getArrayExpression(); 3345 JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array); 3346 Type arrayType = asmTypeOrVoid(type); 3347 List<JetExpression> indices = expression.getIndexExpressions(); 3348 FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression); 3349 assert operationDescriptor != null; 3350 if (arrayType.getSort() == Type.ARRAY && 3351 indices.size() == 1 && 3352 operationDescriptor.getValueParameters().get(0).getType().equals(KotlinBuiltIns.getInstance().getIntType())) { 3353 gen(array, arrayType); 3354 for (JetExpression index : indices) { 3355 gen(index, Type.INT_TYPE); 3356 } 3357 assert type != null; 3358 if (KotlinBuiltIns.getInstance().isArray(type)) { 3359 JetType elementType = type.getArguments().get(0).getType(); 3360 Type notBoxed = asmType(elementType); 3361 return StackValue.arrayElement(notBoxed, true); 3362 } 3363 else { 3364 return StackValue.arrayElement(correctElementType(arrayType), false); 3365 } 3366 } 3367 else { 3368 ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression); 3369 ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression); 3370 3371 boolean isGetter = "get".equals(operationDescriptor.getName().asString()); 3372 3373 ResolvedCall<FunctionDescriptor> resolvedCall = isGetter ? resolvedGetCall : resolvedSetCall; 3374 assert resolvedCall != null : "couldn't find resolved call: " + expression.getText(); 3375 3376 Callable callable = resolveToCallable(operationDescriptor, false); 3377 if (callable instanceof CallableMethod) { 3378 genThisAndReceiverFromResolvedCall(receiver, resolvedCall, (CallableMethod) callable); 3379 } 3380 else { 3381 gen(array, arrayType); // intrinsic method 3382 } 3383 3384 int index = operationDescriptor.getReceiverParameter() != null ? 1 : 0; 3385 3386 Method asmMethod = resolveToCallableMethod(operationDescriptor, false, context).getSignature().getAsmMethod(); 3387 Type[] argumentTypes = asmMethod.getArgumentTypes(); 3388 for (JetExpression jetExpression : expression.getIndexExpressions()) { 3389 gen(jetExpression, argumentTypes[index]); 3390 index++; 3391 } 3392 3393 Type elementType = isGetter ? asmMethod.getReturnType() : ArrayUtil.getLastElement(argumentTypes); 3394 return StackValue.collectionElement(elementType, resolvedGetCall, resolvedSetCall, this, state); 3395 } 3396 } 3397 3398 @Override 3399 public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) { 3400 gen(expression.getThrownExpression(), JAVA_THROWABLE_TYPE); 3401 v.athrow(); 3402 return StackValue.none(); 3403 } 3404 3405 @Override 3406 public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) { 3407 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 3408 if (descriptor instanceof ClassDescriptor) { 3409 return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false); 3410 } 3411 else { 3412 if (descriptor instanceof CallableDescriptor) { 3413 return generateReceiver(descriptor); 3414 } 3415 throw new UnsupportedOperationException("neither this nor receiver"); 3416 } 3417 } 3418 3419 @Override 3420 public StackValue visitTryExpression(JetTryExpression expression, StackValue receiver) { 3421 return generateTryExpression(expression, false); 3422 } 3423 3424 public StackValue generateTryExpression(JetTryExpression expression, boolean isStatement) { 3425 /* 3426The "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 3427(or blocks). 3428 */ 3429 JetFinallySection finallyBlock = expression.getFinallyBlock(); 3430 FinallyBlockStackElement finallyBlockStackElement = null; 3431 if (finallyBlock != null) { 3432 finallyBlockStackElement = new FinallyBlockStackElement(expression); 3433 blockStackElements.push(finallyBlockStackElement); 3434 } 3435 3436 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); 3437 assert jetType != null; 3438 Type expectedAsmType = isStatement ? Type.VOID_TYPE : asmType(jetType); 3439 3440 Label tryStart = new Label(); 3441 v.mark(tryStart); 3442 v.nop(); // prevent verify error on empty try 3443 3444 gen(expression.getTryBlock(), expectedAsmType); 3445 3446 int savedValue = -1; 3447 if (!isStatement) { 3448 savedValue = myFrameMap.enterTemp(expectedAsmType); 3449 v.store(savedValue, expectedAsmType); 3450 } 3451 3452 Label tryEnd = new Label(); 3453 v.mark(tryEnd); 3454 if (finallyBlock != null) { 3455 blockStackElements.pop(); 3456 gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); 3457 blockStackElements.push(finallyBlockStackElement); 3458 } 3459 Label end = new Label(); 3460 v.goTo(end); 3461 3462 List<JetCatchClause> clauses = expression.getCatchClauses(); 3463 for (int i = 0, size = clauses.size(); i < size; i++) { 3464 JetCatchClause clause = clauses.get(i); 3465 3466 Label clauseStart = new Label(); 3467 v.mark(clauseStart); 3468 3469 VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter()); 3470 assert descriptor != null; 3471 Type descriptorType = asmType(descriptor.getType()); 3472 myFrameMap.enter(descriptor, descriptorType); 3473 int index = lookupLocalIndex(descriptor); 3474 v.store(index, descriptorType); 3475 3476 gen(clause.getCatchBody(), expectedAsmType); 3477 3478 if (!isStatement) { 3479 v.store(savedValue, expectedAsmType); 3480 } 3481 3482 myFrameMap.leave(descriptor); 3483 3484 if (finallyBlock != null) { 3485 blockStackElements.pop(); 3486 gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); 3487 blockStackElements.push(finallyBlockStackElement); 3488 } 3489 3490 if (i != size - 1 || finallyBlock != null) { 3491 v.goTo(end); 3492 } 3493 3494 v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName()); 3495 } 3496 3497 if (finallyBlock != null) { 3498 Label finallyStart = new Label(); 3499 v.mark(finallyStart); 3500 3501 int savedException = myFrameMap.enterTemp(JAVA_THROWABLE_TYPE); 3502 v.store(savedException, JAVA_THROWABLE_TYPE); 3503 3504 blockStackElements.pop(); 3505 gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); 3506 blockStackElements.push(finallyBlockStackElement); 3507 3508 v.load(savedException, JAVA_THROWABLE_TYPE); 3509 myFrameMap.leaveTemp(JAVA_THROWABLE_TYPE); 3510 3511 v.athrow(); 3512 3513 v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null); 3514 } 3515 3516 markLineNumber(expression); 3517 v.mark(end); 3518 3519 if (!isStatement) { 3520 v.load(savedValue, expectedAsmType); 3521 myFrameMap.leaveTemp(expectedAsmType); 3522 } 3523 3524 if (finallyBlock != null) { 3525 blockStackElements.pop(); 3526 } 3527 3528 return StackValue.onStack(expectedAsmType); 3529 } 3530 3531 @Override 3532 public StackValue visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, StackValue receiver) { 3533 JetSimpleNameExpression operationSign = expression.getOperationReference(); 3534 IElementType opToken = operationSign.getReferencedNameElementType(); 3535 if (opToken == JetTokens.COLON) { 3536 return gen(expression.getLeft()); 3537 } 3538 else { 3539 JetTypeReference typeReference = expression.getRight(); 3540 JetType rightType = bindingContext.get(BindingContext.TYPE, typeReference); 3541 assert rightType != null; 3542 Type rightTypeAsm = boxType(asmType(rightType)); 3543 JetExpression left = expression.getLeft(); 3544 DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); 3545 if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { 3546 StackValue value = genQualified(receiver, left); 3547 value.put(boxType(value.type), v); 3548 3549 if (opToken != JetTokens.AS_SAFE) { 3550 if (!CodegenUtil.isNullableType(rightType)) { 3551 v.dup(); 3552 Label nonnull = new Label(); 3553 v.ifnonnull(nonnull); 3554 JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); 3555 assert leftType != null; 3556 throwNewException(CLASS_TYPE_CAST_EXCEPTION, DescriptorRenderer.TEXT.renderType(leftType) + 3557 " cannot be cast to " + 3558 DescriptorRenderer.TEXT.renderType(rightType)); 3559 v.mark(nonnull); 3560 } 3561 } 3562 else { 3563 v.dup(); 3564 v.instanceOf(rightTypeAsm); 3565 Label ok = new Label(); 3566 v.ifne(ok); 3567 v.pop(); 3568 v.aconst(null); 3569 v.mark(ok); 3570 } 3571 3572 v.checkcast(rightTypeAsm); 3573 return StackValue.onStack(rightTypeAsm); 3574 } 3575 else { 3576 throw new UnsupportedOperationException("Don't know how to handle non-class types in as/as? : " + descriptor); 3577 } 3578 } 3579 } 3580 3581 @Override 3582 public StackValue visitIsExpression(JetIsExpression expression, StackValue receiver) { 3583 StackValue match = StackValue.expression(OBJECT_TYPE, expression.getLeftHandSide(), this); 3584 return generateIsCheck(match, expression.getTypeRef(), expression.isNegated()); 3585 } 3586 3587 private StackValue generateExpressionMatch(StackValue expressionToMatch, JetExpression patternExpression) { 3588 if (expressionToMatch != null) { 3589 Type subjectType = expressionToMatch.type; 3590 expressionToMatch.dupReceiver(v); 3591 expressionToMatch.put(subjectType, v); 3592 JetType condJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, patternExpression); 3593 Type condType; 3594 if (isNumberPrimitive(subjectType) || subjectType.getSort() == Type.BOOLEAN) { 3595 assert condJetType != null; 3596 condType = asmType(condJetType); 3597 if (!(isNumberPrimitive(condType) || condType.getSort() == Type.BOOLEAN)) { 3598 subjectType = boxType(subjectType); 3599 expressionToMatch.coerceTo(subjectType, v); 3600 } 3601 } 3602 else { 3603 condType = OBJECT_TYPE; 3604 } 3605 gen(patternExpression, condType); 3606 return genEqualsForExpressionsOnStack(v, JetTokens.EQEQ, subjectType, condType); 3607 } 3608 else { 3609 return gen(patternExpression); 3610 } 3611 } 3612 3613 private StackValue generateIsCheck(StackValue expressionToMatch, JetTypeReference typeReference, boolean negated) { 3614 JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); 3615 expressionToMatch.dupReceiver(v); 3616 generateInstanceOf(expressionToMatch, jetType, false); 3617 StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); 3618 return negated ? StackValue.not(value) : value; 3619 } 3620 3621 private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) { 3622 expressionToGen.put(OBJECT_TYPE, v); 3623 if (leaveExpressionOnStack) { 3624 v.dup(); 3625 } 3626 Type type = boxType(asmType(jetType)); 3627 if (jetType.isNullable()) { 3628 Label nope = new Label(); 3629 Label end = new Label(); 3630 3631 v.dup(); 3632 v.ifnull(nope); 3633 v.instanceOf(type); 3634 v.goTo(end); 3635 v.mark(nope); 3636 v.pop(); 3637 v.iconst(1); 3638 v.mark(end); 3639 } 3640 else { 3641 v.instanceOf(type); 3642 } 3643 } 3644 3645 @Override 3646 public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) { 3647 return generateWhenExpression(expression, false); 3648 } 3649 3650 public StackValue generateWhenExpression(JetWhenExpression expression, boolean isStatement) { 3651 JetExpression expr = expression.getSubjectExpression(); 3652 JetType subjectJetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr); 3653 Type subjectType = asmTypeOrVoid(subjectJetType); 3654 Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression); 3655 int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1; 3656 if (subjectLocal != -1) { 3657 gen(expr, subjectType); 3658 tempVariables.put(expr, StackValue.local(subjectLocal, subjectType)); 3659 v.store(subjectLocal, subjectType); 3660 } 3661 3662 Label end = new Label(); 3663 boolean hasElse = JetPsiUtil.checkWhenExpressionHasSingleElse(expression); 3664 3665 Label nextCondition = null; 3666 for (JetWhenEntry whenEntry : expression.getEntries()) { 3667 if (nextCondition != null) { 3668 v.mark(nextCondition); 3669 } 3670 nextCondition = new Label(); 3671 FrameMap.Mark mark = myFrameMap.mark(); 3672 Label thisEntry = new Label(); 3673 if (!whenEntry.isElse()) { 3674 JetWhenCondition[] conditions = whenEntry.getConditions(); 3675 for (int i = 0; i < conditions.length; i++) { 3676 StackValue conditionValue = generateWhenCondition(subjectType, subjectLocal, conditions[i]); 3677 conditionValue.condJump(nextCondition, true, v); 3678 if (i < conditions.length - 1) { 3679 v.goTo(thisEntry); 3680 v.mark(nextCondition); 3681 nextCondition = new Label(); 3682 } 3683 } 3684 } 3685 3686 v.visitLabel(thisEntry); 3687 gen(whenEntry.getExpression(), resultType); 3688 mark.dropTo(); 3689 if (!whenEntry.isElse()) { 3690 v.goTo(end); 3691 } 3692 } 3693 if (!hasElse && nextCondition != null) { 3694 v.mark(nextCondition); 3695 throwNewException(CLASS_NO_PATTERN_MATCHED_EXCEPTION); 3696 } 3697 3698 markLineNumber(expression); 3699 v.mark(end); 3700 3701 myFrameMap.leaveTemp(subjectType); 3702 tempVariables.remove(expr); 3703 return StackValue.onStack(resultType); 3704 } 3705 3706 private StackValue generateWhenCondition(Type subjectType, int subjectLocal, JetWhenCondition condition) { 3707 if (condition instanceof JetWhenConditionInRange) { 3708 JetWhenConditionInRange conditionInRange = (JetWhenConditionInRange) condition; 3709 JetExpression rangeExpression = conditionInRange.getRangeExpression(); 3710 while (rangeExpression instanceof JetParenthesizedExpression) { 3711 rangeExpression = ((JetParenthesizedExpression) rangeExpression).getExpression(); 3712 } 3713 JetSimpleNameExpression operationReference = conditionInRange.getOperationReference(); 3714 boolean inverted = operationReference.getReferencedNameElementType() == JetTokens.NOT_IN; 3715 if (isIntRangeExpr(rangeExpression)) { 3716 getInIntRange(new StackValue.Local(subjectLocal, subjectType), (JetBinaryExpression) rangeExpression, inverted); 3717 } 3718 else { 3719 //FunctionDescriptor op = 3720 // (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, conditionInRange.getOperationReference()); 3721 //genToJVMStack(rangeExpression); 3722 //new StackValue.Local(subjectLocal, subjectType).put(OBJECT_TYPE, v); 3723 //invokeFunctionNoParams(op, Type.BOOLEAN_TYPE, v); 3724 invokeFunctionByReference(operationReference); 3725 if (inverted) { 3726 genInvertBoolean(v); 3727 } 3728 } 3729 return StackValue.onStack(Type.BOOLEAN_TYPE); 3730 } 3731 StackValue.Local match = subjectLocal == -1 ? null : StackValue.local(subjectLocal, subjectType); 3732 if (condition instanceof JetWhenConditionIsPattern) { 3733 JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition; 3734 return generateIsCheck(match, patternCondition.getTypeRef(), patternCondition.isNegated()); 3735 } 3736 else if (condition instanceof JetWhenConditionWithExpression) { 3737 JetExpression patternExpression = ((JetWhenConditionWithExpression) condition).getExpression(); 3738 return generateExpressionMatch(match, patternExpression); 3739 } 3740 else { 3741 throw new UnsupportedOperationException("unsupported kind of when condition"); 3742 } 3743 } 3744 3745 private void invokeFunctionByReference(JetSimpleNameExpression operationReference) { 3746 ResolvedCall<? extends CallableDescriptor> resolvedCall = 3747 bindingContext.get(RESOLVED_CALL, operationReference); 3748 Call call = bindingContext.get(CALL, operationReference); 3749 invokeFunction(call, StackValue.none(), resolvedCall); 3750 } 3751 3752 private boolean isIntRangeExpr(JetExpression rangeExpression) { 3753 if (rangeExpression instanceof JetBinaryExpression) { 3754 JetBinaryExpression binaryExpression = (JetBinaryExpression) rangeExpression; 3755 if (binaryExpression.getOperationReference().getReferencedNameElementType() == JetTokens.RANGE) { 3756 JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, rangeExpression); 3757 assert jetType != null; 3758 DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); 3759 return INTEGRAL_RANGES.contains(descriptor); 3760 } 3761 } 3762 return false; 3763 } 3764 3765 private void throwNewException(@NotNull String className) { 3766 throwNewException(className, null); 3767 } 3768 3769 private void throwNewException(@NotNull String className, @Nullable String message) { 3770 v.anew(Type.getObjectType(className)); 3771 v.dup(); 3772 if (message != null) { 3773 v.visitLdcInsn(message); 3774 v.invokespecial(className, "<init>", "(Ljava/lang/String;)V"); 3775 } 3776 else { 3777 v.invokespecial(className, "<init>", "()V"); 3778 } 3779 v.athrow(); 3780 } 3781 3782 private Call makeFakeCall(ReceiverValue initializerAsReceiver) { 3783 JetSimpleNameExpression fake = JetPsiFactory.createSimpleName(state.getProject(), "fake"); 3784 return CallMaker.makeCall(fake, initializerAsReceiver); 3785 } 3786 3787 @Override 3788 public String toString() { 3789 return context.getContextDescriptor().toString(); 3790 } 3791}