Skip to content
Merged
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
7 changes: 7 additions & 0 deletions core/src/com/google/inject/internal/ConstantFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

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

/**
* @author crazybob@google.com (Bob Lee)
Expand Down Expand Up @@ -65,6 +67,11 @@ public Provider<T> makeProvider(InjectorImpl injector, Dependency<?> dependency)
return InternalFactory.makeProviderFor(instance, this);
}

@Override
public MethodHandle getHandle(InjectorOptions options, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.constantFactoryGetHandle(dependency, instance);
}

@Override
public String toString() {
return MoreObjects.toStringHelper(ConstantFactory.class).add("value", instance).toString();
Expand Down
8 changes: 8 additions & 0 deletions core/src/com/google/inject/internal/ExposedKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
package com.google.inject.internal;

import com.google.inject.Key;
import com.google.inject.internal.InjectorImpl.InjectorOptions;
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
Expand Down Expand Up @@ -63,4 +65,10 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
throw ipe.addSource(source);
}
}

@Override
public MethodHandle getHandle(InjectorOptions options, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.catchInternalProvisionExceptionAndRethrowWithSource(
this.delegate.getHandle(options, dependency, linked), source);
}
}
8 changes: 8 additions & 0 deletions core/src/com/google/inject/internal/FactoryProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

import com.google.common.base.MoreObjects;
import com.google.inject.Key;
import com.google.inject.internal.InjectorImpl.InjectorOptions;
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
Expand Down Expand Up @@ -62,6 +64,12 @@ public T get(InternalContext context, Dependency<?> dependency, boolean linked)
}
}

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

@Override
public String toString() {
return MoreObjects.toStringHelper(FactoryProxy.class)
Expand Down
10 changes: 9 additions & 1 deletion core/src/com/google/inject/internal/InjectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.google.inject.spi.TypeConverterBinding;
import com.google.inject.util.Providers;
import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
Expand Down Expand Up @@ -389,7 +390,7 @@ private static class SyntheticProviderBindingImpl<T> extends BindingImpl<Provide
}

static <T> InternalFactory<Provider<T>> createInternalFactory(Binding<T> providedBinding) {
// Defer calling `getProvider` until we need it, Bindingimple has an internal cache and by
// Defer calling `getProvider` until we need it, BindingImpl has an internal cache and by
// delaying we can ensure we link to an optimized provider instance.
return new InternalFactory<Provider<T>>() {
@Override
Expand All @@ -401,6 +402,13 @@ public Provider<T> get(InternalContext context, Dependency<?> dependency, boolea
public Provider<Provider<T>> makeProvider(InjectorImpl injector, Dependency<?> dependency) {
return InternalFactory.makeProviderFor(providedBinding.getProvider(), this);
}

@Override
public MethodHandle getHandle(
InjectorOptions options, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.constantFactoryGetHandle(
Provider.class, providedBinding.getProvider());
}
};
}

Expand Down
13 changes: 13 additions & 0 deletions core/src/com/google/inject/internal/InjectorShell.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import com.google.inject.spi.PrivateElements;
import com.google.inject.spi.ProvisionListenerBinding;
import com.google.inject.spi.TypeListenerBinding;
import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.Optional;
import java.util.logging.Logger;
Expand Down Expand Up @@ -282,6 +283,12 @@ public Provider<Injector> makeProvider(InjectorImpl injector, Dependency<?> depe
return InternalFactory.makeProviderFor(injector, this);
}

@Override
public MethodHandle getHandle(
InjectorOptions options, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.constantFactoryGetHandle(dependency, injector);
}

@Override
public String toString() {
return "Provider<Injector>";
Expand Down Expand Up @@ -325,6 +332,12 @@ public Provider<Logger> makeProvider(InjectorImpl injector, Dependency<?> depend
return InternalFactory.makeProviderFor(makeLogger(dependency), this);
}

@Override
public MethodHandle getHandle(
InjectorOptions options, Dependency<?> dependency, boolean linked) {
return InternalMethodHandles.constantFactoryGetHandle(dependency, makeLogger(dependency));
}

private static Logger makeLogger(Dependency<?> dependency) {
InjectionPoint injectionPoint = dependency.getInjectionPoint();
return injectionPoint == null
Expand Down
46 changes: 46 additions & 0 deletions core/src/com/google/inject/internal/InternalMethodHandles.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,52 @@ static MethodHandle findConstructorOrDie(Class<?> clazz, MethodType type) {
}
}

/**
* Returns a method handle with the signature {@code (InternalContext) -> T} that returns the
* given instance.
*/
static MethodHandle constantFactoryGetHandle(Dependency<?> dependency, Object instance) {
return constantFactoryGetHandle(dependency.getKey().getTypeLiteral().getRawType(), instance);
}

/**
* Returns a method handle with the signature {@code (InternalContext) -> T} that returns the
* given instance.
*/
static MethodHandle constantFactoryGetHandle(Class<?> forType, Object instance) {
var constant = MethodHandles.constant(forType, instance);
return MethodHandles.dropArguments(constant, 0, InternalContext.class);
}

private static final MethodHandle INTERNAL_PROVISION_EXCEPTION_ADD_SOURCE_HANDLE =
findVirtualOrDie(
InternalProvisionException.class,
"addSource",
methodType(InternalProvisionException.class, Object.class));

/**
* Surrounds the delegate with a catch block that rethrows the exception with the given source.
*
* <pre>{@code
* try {
* return delegate(...);
* } catch (InternalProvisionException ipe) {
* throw ipe.addSource(source);
* }
* }</pre>
*/
static MethodHandle catchInternalProvisionExceptionAndRethrowWithSource(
MethodHandle delegate, Object source) {
var addSourceAndRethrow =
MethodHandles.filterReturnValue(
MethodHandles.insertArguments(
InternalMethodHandles.INTERNAL_PROVISION_EXCEPTION_ADD_SOURCE_HANDLE, 1, source),
MethodHandles.throwException(
delegate.type().returnType(), InternalProvisionException.class));
return MethodHandles.catchException(
delegate, InternalProvisionException.class, addSourceAndRethrow);
}

/**
* Generates a provider instance that delegates to the given factory.
*
Expand Down