001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen; 018 019 import com.intellij.openapi.progress.ProcessCanceledException; 020 import com.intellij.psi.PsiElement; 021 import kotlin.jvm.functions.Function0; 022 import org.jetbrains.annotations.NotNull; 023 import org.jetbrains.annotations.Nullable; 024 import org.jetbrains.kotlin.backend.common.CodegenUtil; 025 import org.jetbrains.kotlin.codegen.context.*; 026 import org.jetbrains.kotlin.codegen.inline.*; 027 import org.jetbrains.kotlin.codegen.state.GenerationState; 028 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 029 import org.jetbrains.kotlin.descriptors.*; 030 import org.jetbrains.kotlin.descriptors.annotations.Annotations; 031 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl; 032 import org.jetbrains.kotlin.fileClasses.FileClasses; 033 import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider; 034 import org.jetbrains.kotlin.load.java.JavaVisibilities; 035 import org.jetbrains.kotlin.load.java.JvmAbi; 036 import org.jetbrains.kotlin.name.Name; 037 import org.jetbrains.kotlin.name.SpecialNames; 038 import org.jetbrains.kotlin.psi.*; 039 import org.jetbrains.kotlin.resolve.*; 040 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 041 import org.jetbrains.kotlin.resolve.constants.ConstantValue; 042 import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator; 043 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; 044 import org.jetbrains.kotlin.resolve.jvm.AsmTypes; 045 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt; 046 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; 047 import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; 048 import org.jetbrains.kotlin.storage.LockBasedStorageManager; 049 import org.jetbrains.kotlin.storage.NotNullLazyValue; 050 import org.jetbrains.kotlin.types.ErrorUtils; 051 import org.jetbrains.kotlin.types.KotlinType; 052 import org.jetbrains.org.objectweb.asm.Label; 053 import org.jetbrains.org.objectweb.asm.MethodVisitor; 054 import org.jetbrains.org.objectweb.asm.Type; 055 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 056 import org.jetbrains.org.objectweb.asm.commons.Method; 057 058 import java.util.*; 059 060 import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags; 061 import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; 062 import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED; 063 import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE; 064 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; 065 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 066 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; 067 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic; 068 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 069 070 public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> { 071 protected final GenerationState state; 072 protected final T element; 073 protected final FieldOwnerContext context; 074 protected final ClassBuilder v; 075 protected final FunctionCodegen functionCodegen; 076 protected final PropertyCodegen propertyCodegen; 077 protected final JetTypeMapper typeMapper; 078 protected final BindingContext bindingContext; 079 protected final JvmFileClassesProvider fileClassesProvider; 080 private final MemberCodegen<?> parentCodegen; 081 private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages(); 082 protected final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>(); 083 084 protected ExpressionCodegen clInit; 085 private NameGenerator inlineNameGenerator; 086 087 private SourceMapper sourceMapper; 088 private final ConstantExpressionEvaluator constantExpressionEvaluator; 089 090 public MemberCodegen( 091 @NotNull GenerationState state, 092 @Nullable MemberCodegen<?> parentCodegen, 093 @NotNull FieldOwnerContext context, 094 T element, 095 @NotNull ClassBuilder builder 096 ) { 097 this.state = state; 098 this.typeMapper = state.getTypeMapper(); 099 this.bindingContext = state.getBindingContext(); 100 this.fileClassesProvider = state.getFileClassesProvider(); 101 this.element = element; 102 this.context = context; 103 this.v = builder; 104 this.functionCodegen = new FunctionCodegen(context, v, state, this); 105 this.propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this); 106 this.parentCodegen = parentCodegen; 107 this.constantExpressionEvaluator = new ConstantExpressionEvaluator(state.getModule().getBuiltIns()); 108 } 109 110 protected MemberCodegen(@NotNull MemberCodegen<T> wrapped, T declaration, FieldOwnerContext codegenContext) { 111 this(wrapped.state, wrapped.getParentCodegen(), codegenContext, declaration, wrapped.v); 112 } 113 114 public void generate() { 115 generateDeclaration(); 116 117 generateBody(); 118 119 generateSyntheticParts(); 120 121 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 122 generateKotlinMetadataAnnotation(); 123 } 124 125 done(); 126 } 127 128 protected abstract void generateDeclaration(); 129 130 protected abstract void generateBody(); 131 132 protected void generateSyntheticParts() { 133 } 134 135 protected abstract void generateKotlinMetadataAnnotation(); 136 137 @Nullable 138 protected ClassDescriptor classForInnerClassRecord() { 139 return null; 140 } 141 142 public static void markLineNumberForDescriptor(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) { 143 if (declarationDescriptor == null) { 144 return; 145 } 146 147 PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor); 148 if (classElement != null) { 149 markLineNumberForElement(classElement, v); 150 } 151 } 152 153 public static void markLineNumberForElement(@NotNull PsiElement element, @NotNull InstructionAdapter v) { 154 Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false); 155 if (lineNumber != null) { 156 Label label = new Label(); 157 v.visitLabel(label); 158 v.visitLineNumber(lineNumber, label); 159 } 160 } 161 162 protected void done() { 163 if (clInit != null) { 164 clInit.v.visitInsn(RETURN); 165 FunctionCodegen.endVisit(clInit.v, "static initializer", element); 166 } 167 168 writeInnerClasses(); 169 170 if (sourceMapper != null) { 171 SourceMapper.Companion.flushToClassBuilder(sourceMapper, v); 172 } 173 174 v.done(); 175 } 176 177 public void genFunctionOrProperty(@NotNull KtDeclaration functionOrProperty) { 178 if (functionOrProperty instanceof KtNamedFunction) { 179 try { 180 functionCodegen.gen((KtNamedFunction) functionOrProperty); 181 } 182 catch (ProcessCanceledException e) { 183 throw e; 184 } 185 catch (CompilationException e) { 186 throw e; 187 } 188 catch (Exception e) { 189 throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty); 190 } 191 } 192 else if (functionOrProperty instanceof KtProperty) { 193 try { 194 propertyCodegen.gen((KtProperty) functionOrProperty); 195 } 196 catch (ProcessCanceledException e) { 197 throw e; 198 } 199 catch (CompilationException e) { 200 throw e; 201 } 202 catch (Exception e) { 203 throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty); 204 } 205 } 206 else { 207 throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty); 208 } 209 } 210 211 public static void genClassOrObject( 212 @NotNull CodegenContext parentContext, 213 @NotNull KtClassOrObject aClass, 214 @NotNull GenerationState state, 215 @Nullable MemberCodegen<?> parentCodegen 216 ) { 217 ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); 218 219 if (descriptor == null || ErrorUtils.isError(descriptor)) { 220 badDescriptor(descriptor, state.getClassBuilderMode()); 221 return; 222 } 223 224 if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) { 225 badDescriptor(descriptor, state.getClassBuilderMode()); 226 } 227 228 Type classType = state.getTypeMapper().mapClass(descriptor); 229 ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile()); 230 ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); 231 new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate(); 232 } 233 234 private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) { 235 if (mode != ClassBuilderMode.LIGHT_CLASSES) { 236 throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor); 237 } 238 } 239 240 public void genClassOrObject(KtClassOrObject aClass) { 241 genClassOrObject(context, aClass, state, this); 242 } 243 244 private void writeInnerClasses() { 245 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information 246 // for each enclosing class and for each immediate member 247 ClassDescriptor classDescriptor = classForInnerClassRecord(); 248 if (classDescriptor != null) { 249 if (parentCodegen != null) { 250 parentCodegen.innerClasses.add(classDescriptor); 251 } 252 253 for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) { 254 ClassDescriptor outerClass = codegen.classForInnerClassRecord(); 255 if (outerClass != null) { 256 innerClasses.add(outerClass); 257 } 258 } 259 } 260 261 for (ClassDescriptor innerClass : innerClasses) { 262 writeInnerClass(innerClass); 263 } 264 } 265 266 private void writeInnerClass(@NotNull ClassDescriptor innerClass) { 267 DeclarationDescriptor containing = innerClass.getContainingDeclaration(); 268 String outerClassInternalName = null; 269 if (containing instanceof ClassDescriptor) { 270 outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName(); 271 } 272 String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); 273 String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName(); 274 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass)); 275 } 276 277 protected void writeOuterClassAndEnclosingMethod() { 278 CodegenContext context = this.context.getParentContext(); 279 280 while (context instanceof InlineLambdaContext) { 281 // If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext 282 //noinspection ConstantConditions 283 context = context.getParentContext().getParentContext(); 284 } 285 assert context != null : "Outermost context can't be null: " + this.context; 286 287 Type enclosingAsmType = computeOuterClass(context); 288 if (enclosingAsmType != null) { 289 Method method = computeEnclosingMethod(context); 290 291 v.visitOuterClass( 292 enclosingAsmType.getInternalName(), 293 method == null ? null : method.getName(), 294 method == null ? null : method.getDescriptor() 295 ); 296 } 297 } 298 299 @Nullable 300 private Type computeOuterClass(@NotNull CodegenContext<?> context) { 301 CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext(); 302 if (outermost instanceof ClassContext) { 303 return typeMapper.mapType(((ClassContext) outermost).getContextDescriptor()); 304 } 305 else if (outermost instanceof MultifileClassFacadeContext || outermost instanceof DelegatingToPartContext) { 306 Type implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(outermost); 307 if (implementationOwnerType != null) { 308 return implementationOwnerType; 309 } 310 else { 311 return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile()); 312 } 313 } 314 315 return null; 316 } 317 318 @Nullable 319 private Method computeEnclosingMethod(@NotNull CodegenContext context) { 320 if (context instanceof MethodContext) { 321 Method method = typeMapper.mapSignature(((MethodContext) context).getFunctionDescriptor()).getAsmMethod(); 322 if (!method.getName().equals("<clinit>")) { 323 return method; 324 } 325 } 326 return null; 327 } 328 329 @NotNull 330 public NameGenerator getInlineNameGenerator() { 331 if (inlineNameGenerator == null) { 332 String prefix = InlineCodegenUtil.getInlineName(context, typeMapper, fileClassesProvider); 333 inlineNameGenerator = new NameGenerator(prefix); 334 } 335 return inlineNameGenerator; 336 } 337 338 @NotNull 339 protected ExpressionCodegen createOrGetClInitCodegen() { 340 DeclarationDescriptor descriptor = context.getContextDescriptor(); 341 if (clInit == null) { 342 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), ACC_STATIC, "<clinit>", "()V", null, null); 343 SimpleFunctionDescriptorImpl clInit = 344 SimpleFunctionDescriptorImpl.create(descriptor, Annotations.Companion.getEMPTY(), Name.special("<clinit>"), SYNTHESIZED, 345 KotlinSourceElementKt.toSourceElement(element)); 346 clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(), 347 Collections.<ValueParameterDescriptor>emptyList(), 348 DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(), 349 null, Visibilities.PRIVATE); 350 351 this.clInit = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this); 352 } 353 return clInit; 354 } 355 356 protected void generateInitializers(@NotNull Function0<ExpressionCodegen> createCodegen) { 357 NotNullLazyValue<ExpressionCodegen> codegen = LockBasedStorageManager.NO_LOCKS.createLazyValue(createCodegen); 358 for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) { 359 if (declaration instanceof KtProperty) { 360 if (shouldInitializeProperty((KtProperty) declaration)) { 361 initializeProperty(codegen.invoke(), (KtProperty) declaration); 362 } 363 } 364 else if (declaration instanceof KtAnonymousInitializer) { 365 KtExpression body = ((KtAnonymousInitializer) declaration).getBody(); 366 if (body != null) { 367 codegen.invoke().gen(body, Type.VOID_TYPE); 368 } 369 } 370 } 371 } 372 373 private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) { 374 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property); 375 assert propertyDescriptor != null; 376 377 KtExpression initializer = property.getDelegateExpressionOrInitializer(); 378 assert initializer != null : "shouldInitializeProperty must return false if initializer is null"; 379 380 StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, false, null, true, StackValue.LOCAL_0); 381 382 propValue.store(codegen.gen(initializer), codegen.v); 383 } 384 385 private boolean shouldInitializeProperty(@NotNull KtProperty property) { 386 if (!property.hasDelegateExpressionOrInitializer()) return false; 387 388 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property); 389 assert propertyDescriptor != null; 390 391 if (propertyDescriptor.isConst()) { 392 //const initializer always inlined 393 return false; 394 } 395 396 KtExpression initializer = property.getInitializer(); 397 398 ConstantValue<?> initializerValue = computeInitializerValue(property, propertyDescriptor, initializer); 399 // we must write constant values for fields in light classes, 400 // because Java's completion for annotation arguments uses this information 401 if (initializerValue == null) return state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES; 402 403 //TODO: OPTIMIZATION: don't initialize static final fields 404 KotlinType jetType = getPropertyOrDelegateType(property, propertyDescriptor); 405 Type type = typeMapper.mapType(jetType); 406 return !skipDefaultValue(propertyDescriptor, initializerValue.getValue(), type); 407 } 408 409 @Nullable 410 private ConstantValue<?> computeInitializerValue( 411 @NotNull KtProperty property, 412 @NotNull PropertyDescriptor propertyDescriptor, 413 @Nullable KtExpression initializer 414 ) { 415 if (property.isVar() && initializer != null) { 416 BindingTrace tempTrace = TemporaryBindingTrace.create(state.getBindingTrace(), "property initializer"); 417 return constantExpressionEvaluator.evaluateToConstantValue(initializer, tempTrace, propertyDescriptor.getType()); 418 } 419 return propertyDescriptor.getCompileTimeInitializer(); 420 } 421 422 @NotNull 423 private KotlinType getPropertyOrDelegateType(@NotNull KtProperty property, @NotNull PropertyDescriptor descriptor) { 424 KtExpression delegateExpression = property.getDelegateExpression(); 425 if (delegateExpression != null) { 426 KotlinType delegateType = bindingContext.getType(delegateExpression); 427 assert delegateType != null : "Type of delegate expression should be recorded"; 428 return delegateType; 429 } 430 return descriptor.getType(); 431 } 432 433 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) { 434 if (isPrimitive(type)) { 435 if (!propertyDescriptor.getType().isMarkedNullable() && value instanceof Number) { 436 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) { 437 return true; 438 } 439 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) { 440 return true; 441 } 442 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) { 443 return true; 444 } 445 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) { 446 return true; 447 } 448 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) { 449 return true; 450 } 451 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) { 452 return true; 453 } 454 } 455 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) { 456 return true; 457 } 458 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) { 459 return true; 460 } 461 } 462 else { 463 if (value == null) { 464 return true; 465 } 466 } 467 return false; 468 } 469 470 protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) { 471 List<KtProperty> delegatedProperties = new ArrayList<KtProperty>(); 472 for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) { 473 if (declaration instanceof KtProperty) { 474 KtProperty property = (KtProperty) declaration; 475 if (property.hasDelegate()) { 476 delegatedProperties.add(property); 477 } 478 } 479 } 480 if (delegatedProperties.isEmpty()) return; 481 482 v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, 483 "[" + K_PROPERTY_TYPE, null, null); 484 485 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return; 486 487 InstructionAdapter iv = createOrGetClInitCodegen().v; 488 iv.iconst(delegatedProperties.size()); 489 iv.newarray(K_PROPERTY_TYPE); 490 491 for (int i = 0, size = delegatedProperties.size(); i < size; i++) { 492 PropertyDescriptor property = 493 (PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i)); 494 495 iv.dup(); 496 iv.iconst(i); 497 498 int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) + 499 (property.getExtensionReceiverParameter() != null ? 1 : 0); 500 Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount]; 501 iv.anew(implType); 502 iv.dup(); 503 // TODO: generate the container once and save to a local field instead (KT-10495) 504 ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state); 505 iv.aconst(property.getName().asString()); 506 iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state)); 507 iv.invokespecial( 508 implType.getInternalName(), "<init>", 509 Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false 510 ); 511 Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount); 512 iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false); 513 514 StackValue.onStack(implType).put(K_PROPERTY_TYPE, iv); 515 516 iv.astore(K_PROPERTY_TYPE); 517 } 518 519 iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE); 520 } 521 522 public String getClassName() { 523 return v.getThisName(); 524 } 525 526 @NotNull 527 public FieldOwnerContext<?> getContext() { 528 return context; 529 } 530 531 @NotNull 532 public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() { 533 return reifiedTypeParametersUsages; 534 } 535 536 public MemberCodegen<?> getParentCodegen() { 537 return parentCodegen; 538 } 539 540 @Override 541 public String toString() { 542 return context.toString(); 543 } 544 545 @NotNull 546 public SourceMapper getOrCreateSourceMapper() { 547 if (sourceMapper == null) { 548 sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo(element, getClassName()), null); 549 } 550 return sourceMapper; 551 } 552 553 protected void generateConstInstance(@NotNull Type thisAsmType, @NotNull Type fieldAsmType) { 554 v.newField( 555 JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, 556 fieldAsmType.getDescriptor(), null, null 557 ); 558 559 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 560 InstructionAdapter iv = createOrGetClInitCodegen().v; 561 iv.anew(thisAsmType); 562 iv.dup(); 563 iv.invokespecial(thisAsmType.getInternalName(), "<init>", "()V", false); 564 iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor()); 565 } 566 } 567 568 protected void generateSyntheticAccessors() { 569 for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) { 570 generateSyntheticAccessor(accessor); 571 } 572 } 573 574 private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor<?> accessorForCallableDescriptor) { 575 if (accessorForCallableDescriptor instanceof FunctionDescriptor) { 576 final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor; 577 final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor(); 578 functionCodegen.generateMethod( 579 Synthetic(null, original), accessor, 580 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) { 581 @Override 582 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 583 markLineNumberForElement(element, codegen.v); 584 585 generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v); 586 587 codegen.v.areturn(signature.getReturnType()); 588 } 589 } 590 ); 591 } 592 else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) { 593 final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor; 594 final PropertyDescriptor original = accessor.getCalleeDescriptor(); 595 596 class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { 597 public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) { 598 super(MemberCodegen.this.state, callableDescriptor); 599 } 600 601 @Override 602 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 603 boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal; 604 boolean forceFieldForCompanionProperty = JvmAbi.isPropertyWithBackingFieldInOuterClass(original) && 605 !isCompanionObject(accessor.getContainingDeclaration()); 606 boolean forceField = forceFieldForCompanionProperty || 607 syntheticBackingField || 608 original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY; 609 StackValue property = codegen.intermediateValueForProperty( 610 original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), forceFieldForCompanionProperty, StackValue.none() 611 ); 612 613 InstructionAdapter iv = codegen.v; 614 615 markLineNumberForElement(element, iv); 616 617 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 618 for (int i = 0, reg = 0; i < argTypes.length; i++) { 619 Type argType = argTypes[i]; 620 iv.load(reg, argType); 621 //noinspection AssignmentToForLoopParameter 622 reg += argType.getSize(); 623 } 624 625 if (callableDescriptor instanceof PropertyGetterDescriptor) { 626 property.put(signature.getReturnType(), iv); 627 } 628 else { 629 property.store(StackValue.onStack(property.type), iv, true); 630 } 631 632 iv.areturn(signature.getReturnType()); 633 } 634 } 635 636 if (accessor.isWithSyntheticGetterAccessor()) { 637 PropertyGetterDescriptor getter = accessor.getGetter(); 638 assert getter != null; 639 functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original), 640 getter, new PropertyAccessorStrategy(getter)); 641 } 642 643 if (accessor.isVar() && accessor.isWithSyntheticSetterAccessor()) { 644 PropertySetterDescriptor setter = accessor.getSetter(); 645 assert setter != null; 646 647 functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original), 648 setter, new PropertyAccessorStrategy(setter)); 649 } 650 } 651 else { 652 throw new UnsupportedOperationException(); 653 } 654 } 655 656 protected StackValue generateMethodCallTo( 657 @NotNull FunctionDescriptor functionDescriptor, 658 @Nullable FunctionDescriptor accessorDescriptor, 659 @NotNull InstructionAdapter iv 660 ) { 661 CallableMethod callableMethod = typeMapper.mapToCallableMethod( 662 functionDescriptor, 663 accessorDescriptor instanceof AccessorForCallableDescriptor && 664 ((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null 665 ); 666 667 boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration()); 668 int reg = hasDispatchReceiver ? 1 : 0; 669 boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor; 670 if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) { 671 iv.anew(callableMethod.getOwner()); 672 iv.dup(); 673 reg = 0; 674 } 675 else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && hasDispatchReceiver)) { 676 if (!AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor)) { 677 iv.load(0, OBJECT_TYPE); 678 } 679 } 680 681 for (Type argType : callableMethod.getParameterTypes()) { 682 if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) { 683 iv.aconst(null); 684 } 685 else { 686 iv.load(reg, argType); 687 reg += argType.getSize(); 688 } 689 } 690 691 callableMethod.genInvokeInstruction(iv); 692 693 return StackValue.onStack(callableMethod.getReturnType()); 694 } 695 }