Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions core/src/com/google/inject/internal/BoundProviderFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.google.inject.Key;
import com.google.inject.internal.InjectorImpl.JitLimitation;
import com.google.inject.spi.Dependency;
import java.lang.invoke.MethodHandle;

/** Delegates to a custom factory which is also bound in the injector. */
final class BoundProviderFactory<T> extends ProviderInternalFactory<T> implements CreationListener {
Expand Down Expand Up @@ -64,16 +63,12 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return context.makeHandle(
this,
() ->
InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
circularGetHandle(
providerFactory.getHandle(context, PROVIDER_DEPENDENCY, /* linked= */ true),
dependency,
provisionCallback),
providerKey));
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachable(
InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
circularGetHandle(
providerFactory.getHandle(context, /* linked= */ true), provisionCallback),
providerKey));
}

@Override
Expand Down
29 changes: 5 additions & 24 deletions core/src/com/google/inject/internal/ConstantFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,14 @@

package com.google.inject.internal;

import static java.lang.invoke.MethodType.methodType;

import com.google.common.base.MoreObjects;
import com.google.inject.Provider;
import com.google.inject.spi.Dependency;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;

/**
* @author [email protected] (Bob Lee)
*/
final class ConstantFactory<T> implements InternalFactory<T> {
private static final MethodHandle ON_NULL_INJECTED_INTO_NON_NULLABLE_DEPENDENCY_MH =
InternalMethodHandles.findStaticOrDie(
InternalProvisionException.class,
"onNullInjectedIntoNonNullableDependency",
methodType(void.class, Object.class, Dependency.class));
final class ConstantFactory<T> extends InternalFactory<T> {

private static <T> InternalFactory<T> nullFactory(Object source) {
return new InternalFactory<T>() {
Expand All @@ -51,19 +42,9 @@ public Provider<T> makeProvider(InjectorImpl injector, Dependency<?> dependency)
}

@Override
public MethodHandle getHandle(
LinkageContext context, Dependency<?> dependency, boolean linked) {
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
var returnNull = InternalMethodHandles.constantFactoryGetHandle(null);
if (dependency.isNullable()) {
// Just return a constant null handle.
return returnNull;
}
// We need to call onNullInjectedIntoNonNullableDependency and then return null. It is
// possible that the former will throw but that depends on some runtime conditions.
var onNull =
MethodHandles.insertArguments(
ON_NULL_INJECTED_INTO_NON_NULLABLE_DEPENDENCY_MH, 0, source, dependency);
return MethodHandles.foldArguments(returnNull, onNull);
return makeCachable(InternalMethodHandles.nullCheckResult(returnNull, source));
}
};
}
Expand Down Expand Up @@ -92,8 +73,8 @@ public Provider<T> makeProvider(InjectorImpl injector, Dependency<?> dependency)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.constantFactoryGetHandle(instance);
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachable(InternalMethodHandles.constantFactoryGetHandle(instance));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.inject.spi.Dependency;
import java.lang.invoke.MethodHandle;
import javax.annotation.Nullable;
import jakarta.inject.Provider;
import javax.annotation.Nullable;

/** An InternalFactory that delegates to a constant provider. */
final class ConstantProviderInternalFactory<T> extends ProviderInternalFactory<T> {
Expand All @@ -45,8 +44,9 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return circularGetHandleImmediate(
InternalMethodHandles.constantFactoryGetHandle(provider), dependency, provisionCallback);
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachable(
circularGetHandleImmediate(
InternalMethodHandles.constantFactoryGetHandle(provider), provisionCallback));
}
}
2 changes: 1 addition & 1 deletion core/src/com/google/inject/internal/ConstructionProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ interface ConstructionProxy<T> {
* Returns the method handle for the constructor, using the supplied handles to provide
* parameters.
*
* <p>The returned handle has {@link InternalMethodHandles#FACTORY_TYPE} as its signature.
* <p>The returned handle has {@link InternalMethodHandles#ELEMENT_FACTORY_TYPE} as its signature.
*/
MethodHandle getConstructHandle(MethodHandle[] parameterHandles);

Expand Down
19 changes: 9 additions & 10 deletions core/src/com/google/inject/internal/ConstructorBindingImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ public int hashCode() {
return Objects.hashCode(getKey(), getScoping(), constructorInjectionPoint);
}

private static class Factory<T> implements InternalFactory<T> {
private static class Factory<T> extends InternalFactory<T> {
private final boolean failIfNotLinked;
private final Key<?> key;
private ConstructorInjector<T> constructorInjector;
Expand Down Expand Up @@ -309,20 +309,19 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(
LinkageContext context, Dependency<?> dependency, boolean linked) {
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
if (!linked && failIfNotLinked) {
var throwHandle =
MethodHandles.foldArguments(
MethodHandles.throwException(
dependency.getKey().getTypeLiteral().getRawType(),
InternalProvisionException.class),
MethodHandles.throwException(Object.class, InternalProvisionException.class),
MethodHandles.insertArguments(JIT_DISABLED_HANDLE, 0, key));
return MethodHandles.dropArguments(throwHandle, 0, InternalContext.class);
return makeCachableOnLinkedSetting(MethodHandles.dropArguments(throwHandle, 0, InternalContext.class, Dependency.class));
}
return context.makeHandle(
this,
() -> constructorInjector.getConstructHandle(context, dependency, provisionCallback));
var handle = constructorInjector.getConstructHandle(context, provisionCallback);
if (failIfNotLinked) {
return makeCachableOnLinkedSetting(handle);
}
return makeCachable(handle);
}

private static final MethodHandle JIT_DISABLED_HANDLE =
Expand Down
17 changes: 7 additions & 10 deletions core/src/com/google/inject/internal/ConstructorInjector.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static com.google.common.base.Preconditions.checkState;

import com.google.common.collect.ImmutableSet;
import com.google.inject.internal.MembersInjectorImpl.MethodHandleMembersInjectorImpl;
import com.google.inject.internal.ProvisionListenerStackCallback.ProvisionCallback;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.InjectionPoint;
Expand Down Expand Up @@ -92,18 +93,17 @@ Object construct(

/**
* Returns a method handle for constructing the instance with the signature {@code
* (InternalContext) -> T}
* (InternalContext, Dependency<?>) -> T}
*/
MethodHandle getConstructHandle(
LinkageContext linkageContext,
Dependency<?> dependency,
@Nullable ProvisionListenerStackCallback<T> provisionCallback) {

var handle =
constructionProxy.getConstructHandle(
SingleParameterInjector.getAllHandles(linkageContext, parameterInjectors));
checkState(
handle.type().equals(InternalMethodHandles.FACTORY_TYPE),
handle.type().equals(InternalMethodHandles.ELEMENT_FACTORY_TYPE),
"expected %s but got %s",
InternalMethodHandles.FACTORY_TYPE,
handle.type());
Expand All @@ -112,7 +112,7 @@ MethodHandle getConstructHandle(
if (membersInjector != null) {
handle = InternalMethodHandles.finishConstructionAndSetReference(handle, circularFactoryId);
// Members injectors have the signature `(Object, InternalContext)->void`
var membersHandle = membersInjector.getInjectMembersAndNotifyListenersHandle(linkageContext);
var membersHandle = ((MethodHandleMembersInjectorImpl<?>)membersInjector).getInjectMembersAndNotifyListenersHandle(linkageContext);
// Compose it into a handle that just returns the first parameter.
membersHandle =
MethodHandles.foldArguments(
Expand All @@ -127,19 +127,16 @@ MethodHandle getConstructHandle(
handle = InternalMethodHandles.finishConstruction(handle, circularFactoryId);
}

handle =
InternalMethodHandles.catchErrorInConstructorAndRethrowWithSource(
handle, constructionProxy.getInjectionPoint());
if (membersInjector != null) {
// If we called finishConstructionAndSetReference, we need to clear the reference here.
handle = InternalMethodHandles.clearReference(handle, circularFactoryId);
}

// Wrap the whole thing in a provision callback if needed.
handle =
InternalMethodHandles.invokeThroughProvisionCallback(handle, dependency, provisionCallback);
handle = MethodHandles.dropArguments(handle, 1, Dependency.class);
handle = InternalMethodHandles.invokeThroughProvisionCallback(handle, provisionCallback);
// call tryStartConstruction
handle = InternalMethodHandles.tryStartConstruction(handle, dependency, circularFactoryId);
handle = InternalMethodHandles.tryStartConstruction(handle, circularFactoryId);
// (InternalContext)->T
return handle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.inject.internal;

import static com.google.inject.internal.InternalMethodHandles.CONSTRUCTOR_NEWINSTANCE_HANDLE;
import static com.google.inject.internal.InternalMethodHandles.castReturnTo;
import static com.google.inject.internal.InternalMethodHandles.castReturnToObject;
import static java.lang.invoke.MethodType.methodType;
Expand Down Expand Up @@ -134,17 +133,14 @@ public MethodHandle getConstructHandle(MethodHandle[] parameterHandles) {
InternalMethodHandles.BIFUNCTION_APPLY_HANDLE
.bindTo(fastConstructor)
.asType(methodType(Object.class, Object.class, Object[].class));
// (Object[])->Object
handle = MethodHandles.insertArguments(handle, 0, (Object) null); // no receiver type.
// NOTE: is is safe to use asCollector here because the number of parameters is the same
// as the number of parameters to the constructor which should never exceed the maxiumum
// number of method parameters.
handle = handle.asCollector(Object[].class, parameterHandles.length);
// Pass all the parameters to the constructor.
handle = MethodHandles.filterArguments(handle, 0, parameterHandles);
// merge all the internalcontext parameters into a single object factory.
// catch here so we don't catch errors from our parameters
handle = InternalMethodHandles.catchErrorInConstructorAndRethrowWithSource(handle, injectionPoint);
// (InternalContext)->Object
handle =
MethodHandles.permuteArguments(
handle, InternalMethodHandles.FACTORY_TYPE, new int[parameterHandles.length]);
MethodHandles.filterArguments(
handle, 0, InternalMethodHandles.buildObjectArrayFactory(parameterHandles));
return handle;
}
}
Expand All @@ -168,14 +164,16 @@ public T newInstance(Object... arguments) throws InvocationTargetException {
@Override
public MethodHandle getConstructHandle(MethodHandle[] parameterHandles) {
// See comments in ProviderMethod on how this rarely happens and why it happens
var handle = CONSTRUCTOR_NEWINSTANCE_HANDLE.bindTo(constructor);
// collect the parameters into an array of type Object[]
handle = handle.asCollector(Object[].class, parameterHandles.length);
// apply all the parameters to the constructor.
handle = MethodHandles.filterArguments(handle, 0, parameterHandles);
// merge all the internalcontext parameters into a single object factory.
return MethodHandles.permuteArguments(
handle, InternalMethodHandles.FACTORY_TYPE, new int[parameterHandles.length]);
// (Object[])->Object
var handle = InternalMethodHandles.newInstanceHandle(constructor);
// Catch here so we don't catch errors from our parameters
handle = InternalMethodHandles.catchErrorInConstructorAndRethrowWithSource(handle, injectionPoint);

// (InternalContext)->Object
handle =
MethodHandles.filterArguments(
handle, 0, InternalMethodHandles.buildObjectArrayFactory(parameterHandles));
return handle;
}
}

Expand Down Expand Up @@ -207,10 +205,12 @@ public MethodHandle getConstructHandle(MethodHandle[] parameterHandles) {
IntStream.range(0, parameterHandles.length)
.mapToObj(i -> castReturnTo(parameterHandles[i], type.parameterType(i)))
.toArray(MethodHandle[]::new);
var handle = MethodHandles.filterArguments(target, 0, typedHandles);
// catch errors from the constructor
var handle = InternalMethodHandles.catchErrorInConstructorAndRethrowWithSource(target, injectionPoint);
handle = MethodHandles.filterArguments(handle, 0, typedHandles);
handle = castReturnToObject(handle); // satisfy the signature of the factory type.
return MethodHandles.permuteArguments(
handle, InternalMethodHandles.FACTORY_TYPE, new int[typedHandles.length]);
handle, InternalMethodHandles.ELEMENT_FACTORY_TYPE, new int[typedHandles.length]);
}
}
}
10 changes: 5 additions & 5 deletions core/src/com/google/inject/internal/ExposedKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
import com.google.inject.Key;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.PrivateElements;
import java.lang.invoke.MethodHandle;

/**
* This factory exists in a parent injector. When invoked, it retrieves its value from a child
* injector.
*/
final class ExposedKeyFactory<T> implements InternalFactory<T>, CreationListener {
final class ExposedKeyFactory<T> extends InternalFactory<T> implements CreationListener {
private final Key<T> key;
private final Object source;
private final PrivateElements privateElements;
Expand Down Expand Up @@ -66,8 +65,9 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
this.delegate.getHandle(context, dependency, linked), source);
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachableOnLinkedSetting(
InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
this.delegate.getHandle(context, linked), source));
}
}
10 changes: 5 additions & 5 deletions core/src/com/google/inject/internal/FactoryProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@
import com.google.inject.Key;
import com.google.inject.internal.InjectorImpl.JitLimitation;
import com.google.inject.spi.Dependency;
import java.lang.invoke.MethodHandle;

/**
* A placeholder which enables us to swap in the real factory once the injector is created. Used for
* a linked binding, so that getting the linked binding returns the link's factory.
*/
final class FactoryProxy<T> implements InternalFactory<T>, CreationListener {
final class FactoryProxy<T> extends InternalFactory<T> implements CreationListener {

private final InjectorImpl injector;
private final Key<T> key;
Expand Down Expand Up @@ -64,9 +63,10 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
targetFactory.getHandle(context, dependency, /* linked= */ true), targetKey);
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachable(
InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
targetFactory.getHandle(context, /* linked= */ true), targetKey));
}

@Override
Expand Down
7 changes: 3 additions & 4 deletions core/src/com/google/inject/internal/InitializableFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@
import com.google.errorprone.annotations.concurrent.LazyInit;
import com.google.inject.Provider;
import com.google.inject.spi.Dependency;
import java.lang.invoke.MethodHandle;

/**
* @author [email protected] (Bob Lee)
*/
final class InitializableFactory<T> implements InternalFactory<T> {
final class InitializableFactory<T> extends InternalFactory<T> {

private final Initializable<T> initializable;
// Cache the values here so we can optimize the behavior of Provider instances.
Expand All @@ -47,8 +46,8 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}

@Override
public MethodHandle getHandle(LinkageContext context, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.initializableFactoryGetHandle(initializable);
MethodHandleResult makeHandle(LinkageContext context, boolean linked) {
return makeCachable(InternalMethodHandles.initializableFactoryGetHandle(initializable));
}

@Override
Expand Down
2 changes: 0 additions & 2 deletions core/src/com/google/inject/internal/Initializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,6 @@ public T get(InternalContext context) throws InternalProvisionException {
default:
throw new IllegalStateException("Unknown state: " + state);
}
// TODO(b/366058184): Investigate a MethodHandle approach for this.

// if in Stage.TOOL, we only want to inject & notify toolable injection points.
// (otherwise we'll inject all of them)
try {
Expand Down
Loading