/*
* Copyright (c) 2016, Oracle and/or its affiliates.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.oracle.truffle.llvm.runtime.global;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.llvm.runtime.LLVMAddress;
import com.oracle.truffle.llvm.runtime.LLVMBoxedPrimitive;
import com.oracle.truffle.llvm.runtime.LLVMFunction;
import com.oracle.truffle.llvm.runtime.LLVMTruffleObject;
import com.oracle.truffle.llvm.runtime.NativeAllocator;
import com.oracle.truffle.llvm.runtime.NativeResolver;
import com.oracle.truffle.llvm.runtime.memory.LLVMMemory;
import com.oracle.truffle.llvm.runtime.types.PointerType;
import com.oracle.truffle.llvm.runtime.types.Type;
abstract class Container {
private static final int CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC = 2;
protected final Type type;
Container(Type type) {
CompilerAsserts.neverPartOfCompilation();
this.type = type;
}
Type getType() {
return type;
}
abstract void destroy();
abstract LLVMAddress getNativeLocation(LLVMGlobalVariable global);
abstract void putI1(LLVMGlobalVariable global, boolean value);
abstract void putI8(LLVMGlobalVariable global, byte value);
abstract void putI16(LLVMGlobalVariable global, short value);
abstract void putI32(LLVMGlobalVariable global, int value);
abstract void putI64(LLVMGlobalVariable global, long value);
abstract void putFloat(LLVMGlobalVariable global, float value);
abstract void putDouble(LLVMGlobalVariable global, double value);
abstract void putAddress(LLVMGlobalVariable global, LLVMAddress value);
abstract void putTruffleObject(LLVMGlobalVariable global, TruffleObject value);
abstract void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value);
abstract void putFunction(LLVMGlobalVariable global, LLVMFunction value);
abstract void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value);
abstract void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value);
abstract Object get(LLVMGlobalVariable global);
abstract boolean getI1(LLVMGlobalVariable global);
abstract byte getI8(LLVMGlobalVariable global);
abstract short getI16(LLVMGlobalVariable global);
abstract int getI32(LLVMGlobalVariable global);
abstract long getI64(LLVMGlobalVariable global);
abstract float getFloat(LLVMGlobalVariable global);
abstract double getDouble(LLVMGlobalVariable global);
static final class UninitializedContainer extends Container {
private final NativeResolver resolver;
UninitializedContainer(Type type, NativeResolver resolver) {
super(type);
this.resolver = resolver;
}
@Override
LLVMAddress getNativeLocation(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getNativeLocation(global);
}
@Override
void putI1(LLVMGlobalVariable global, boolean value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putI1(global, value);
}
@Override
void putI8(LLVMGlobalVariable global, byte value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putI8(global, value);
}
@Override
void putI16(LLVMGlobalVariable global, short value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putI16(global, value);
}
@Override
void putI32(LLVMGlobalVariable global, int value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putI32(global, value);
}
@Override
void putI64(LLVMGlobalVariable global, long value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putI64(global, value);
}
@Override
void putFloat(LLVMGlobalVariable global, float value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putFloat(global, value);
}
@Override
void putDouble(LLVMGlobalVariable global, double value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putDouble(global, value);
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putAddress(global, value);
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Cannot store managed object to native memory");
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Cannot store managed object to native memory");
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putFunction(global, value);
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putBoxedPrimitive(global, value);
}
@Override
Object get(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().get(global);
}
@Override
boolean getI1(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getI1(global);
}
@Override
byte getI8(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getI8(global);
}
@Override
short getI16(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getI16(global);
}
@Override
int getI32(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getI32(global);
}
@Override
long getI64(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getI64(global);
}
@Override
float getFloat(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getFloat(global);
}
@Override
double getDouble(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
return global.getContainer().getDouble(global);
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
global.setContainer(new NativeContainer(type, resolver.resolve()));
global.getContainer().putGlobal(global, value);
}
@Override
void destroy() {
// nothing to do
}
}
static final class NativeContainer extends Container {
private final LLVMAddress address;
NativeContainer(Type type, LLVMAddress address) {
super(type);
this.address = address;
}
@Override
void destroy() {
LLVMMemory.free(address);
}
@Override
LLVMAddress getNativeLocation(LLVMGlobalVariable global) {
return address;
}
@Override
void putI1(LLVMGlobalVariable global, boolean value) {
LLVMMemory.putI1(address, value);
}
@Override
void putI8(LLVMGlobalVariable global, byte value) {
LLVMMemory.putI8(address, value);
}
@Override
void putI16(LLVMGlobalVariable global, short value) {
LLVMMemory.putI16(address, value);
}
@Override
void putI32(LLVMGlobalVariable global, int value) {
LLVMMemory.putI32(address, value);
}
@Override
void putI64(LLVMGlobalVariable global, long value) {
LLVMMemory.putI64(address, value);
}
@Override
void putFloat(LLVMGlobalVariable global, float value) {
LLVMMemory.putFloat(address, value);
}
@Override
void putDouble(LLVMGlobalVariable global, double value) {
LLVMMemory.putDouble(address, value);
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
LLVMMemory.putAddress(address, value);
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Cannot store managed object to native memory");
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Cannot store managed object to native memory");
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
LLVMMemory.putAddress(address, value.getFunctionPointer());
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
// do not store the boxed primitive to native memory.
// the boxed primitive was never converted to an address; when reading it would be
// interpreted as an address
CompilerDirectives.transferToInterpreter();
throw new IllegalStateException("Cannot store managed object to native memory");
}
@Override
Object get(LLVMGlobalVariable global) {
return LLVMMemory.getAddress(address);
}
@Override
boolean getI1(LLVMGlobalVariable global) {
return LLVMMemory.getI1(address);
}
@Override
byte getI8(LLVMGlobalVariable global) {
return LLVMMemory.getI8(address);
}
@Override
short getI16(LLVMGlobalVariable global) {
return LLVMMemory.getI16(address);
}
@Override
int getI32(LLVMGlobalVariable global) {
return LLVMMemory.getI32(address);
}
@Override
long getI64(LLVMGlobalVariable global) {
return LLVMMemory.getI64(address);
}
@Override
float getFloat(LLVMGlobalVariable global) {
return LLVMMemory.getFloat(address);
}
@Override
double getDouble(LLVMGlobalVariable global) {
return LLVMMemory.getDouble(address);
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
LLVMMemory.putAddress(address, value.getNativeLocation());
}
}
abstract static class AbstractManagedContainer extends Container {
protected final NativeAllocator allocator;
AbstractManagedContainer(Type type, NativeAllocator address) {
super(type);
this.allocator = address;
}
@Override
LLVMAddress getNativeLocation(LLVMGlobalVariable global) {
return transferToNativeWithCopy(global);
}
LLVMAddress transferToNativeNoCopy(LLVMGlobalVariable global) {
CompilerDirectives.transferToInterpreterAndInvalidate();
LLVMAddress address = allocator.allocate();
NativeContainer nativeContainer = new NativeContainer(type, address);
global.setContainer(nativeContainer);
return address;
}
LLVMAddress transferToNativeWithCopy(LLVMGlobalVariable global) {
LLVMAddress address = transferToNativeNoCopy(global);
copyToNative(address);
return address;
}
abstract void copyToNative(LLVMAddress a);
@Override
void putI1(LLVMGlobalVariable global, boolean value) {
transferToNativeNoCopy(global);
global.getContainer().putI1(global, value);
}
@Override
void putI8(LLVMGlobalVariable global, byte value) {
transferToNativeNoCopy(global);
global.getContainer().putI8(global, value);
}
@Override
void putI16(LLVMGlobalVariable global, short value) {
transferToNativeNoCopy(global);
global.getContainer().putI16(global, value);
}
@Override
void putI32(LLVMGlobalVariable global, int value) {
transferToNativeNoCopy(global);
global.getContainer().putI32(global, value);
}
@Override
void putI64(LLVMGlobalVariable global, long value) {
transferToNativeNoCopy(global);
global.getContainer().putI64(global, value);
}
@Override
void putFloat(LLVMGlobalVariable global, float value) {
transferToNativeNoCopy(global);
global.getContainer().putFloat(global, value);
}
@Override
void putDouble(LLVMGlobalVariable global, double value) {
transferToNativeNoCopy(global);
global.getContainer().putDouble(global, value);
}
@Override
boolean getI1(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getI1(global);
}
@Override
byte getI8(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getI8(global);
}
@Override
short getI16(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getI16(global);
}
@Override
int getI32(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getI32(global);
}
@Override
long getI64(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getI64(global);
}
@Override
float getFloat(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getFloat(global);
}
@Override
double getDouble(LLVMGlobalVariable global) {
transferToNativeWithCopy(global);
return global.getContainer().getDouble(global);
}
}
static final class UninitializedManagedContainer extends AbstractManagedContainer {
UninitializedManagedContainer(Type type, NativeAllocator address) {
super(type, address);
}
@Override
void destroy() {
// nothing to do
}
@Override
void copyToNative(LLVMAddress a) {
// nothing to do
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedLLVMAddressContainer newContainer = new CachedLLVMAddressContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, 0);
global.setContainer(newContainer);
}
@Override
Object get(LLVMGlobalVariable global) {
return LLVMAddress.nullPointer();
}
}
static final class CachedLLVMAddressContainer extends AbstractManagedContainer {
private final long address;
private int changes;
CachedLLVMAddressContainer(Type type, NativeAllocator allocator, LLVMAddress address, int changes) {
this(type, allocator, address.getVal(), changes);
}
CachedLLVMAddressContainer(Type type, NativeAllocator allocator, long ptr, int changes) {
super(type, allocator);
this.address = ptr;
this.changes = changes;
}
@Override
void destroy() {
// nothing to do
}
@Override
void copyToNative(LLVMAddress a) {
CompilerAsserts.neverPartOfCompilation();
assert type instanceof PointerType;
LLVMMemory.putAddress(a, address);
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
assert value != null;
if (value.getVal() != address) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericLLVMAddressContainer newContainer = new GenericLLVMAddressContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedLLVMAddressContainer newContainer = new CachedLLVMAddressContainer(type, allocator, value.getVal(), changes);
global.setContainer(newContainer);
}
}
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
Object get(LLVMGlobalVariable global) {
return LLVMAddress.fromLong(address);
}
}
static final class CachedManagedContainer extends AbstractManagedContainer {
private final Object managedValue;
private int changes;
CachedManagedContainer(Type type, NativeAllocator allocator, Object managedValue, int changes) {
super(type, allocator);
this.managedValue = managedValue;
this.changes = changes;
}
@Override
void destroy() {
// nothing to do
}
@Override
void copyToNative(LLVMAddress address) {
CompilerAsserts.neverPartOfCompilation();
assert type instanceof PointerType;
if (managedValue instanceof LLVMFunction) {
LLVMMemory.putAddress(address, ((LLVMFunction) managedValue).getFunctionPointer());
} else if (managedValue instanceof LLVMAddress) {
LLVMMemory.putAddress(address, (LLVMAddress) managedValue);
} else if (managedValue instanceof LLVMGlobalVariable) {
LLVMMemory.putAddress(address, ((LLVMGlobalVariable) managedValue).getNativeLocation());
} else if (managedValue instanceof TruffleObject || managedValue instanceof LLVMTruffleObject) {
throw new IllegalStateException("Cannot resolve address of a foreign TruffleObject: " + managedValue);
} else if (managedValue == null) {
// nothing to do
} else {
throw new AssertionError("Unknown type: " + managedValue.getClass());
}
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
assert !(managedValue instanceof LLVMAddress) && !value.equals(managedValue) : "there is a separate cached container class for LLVMAddress objects";
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericLLVMAddressContainer newContainer = new GenericLLVMAddressContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedLLVMAddressContainer newContainer = new CachedLLVMAddressContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
if (managedValue != value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
if (value != managedValue) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
if (value != managedValue) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
if (value != managedValue) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
if (value != managedValue) {
CompilerDirectives.transferToInterpreterAndInvalidate();
if (++changes >= CACHING_TRIES_BEFORE_SWITCHING_TO_GENERIC) {
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
} else {
CachedManagedContainer newContainer = new CachedManagedContainer(type, allocator, value, changes);
global.setContainer(newContainer);
}
}
}
@Override
Object get(LLVMGlobalVariable global) {
return managedValue;
}
}
static final class GenericLLVMAddressContainer extends AbstractManagedContainer {
private long address;
GenericLLVMAddressContainer(Type type, NativeAllocator allocator, LLVMAddress address) {
super(type, allocator);
this.address = address.getVal();
}
@Override
void destroy() {
// nothing to do
}
@Override
void copyToNative(LLVMAddress a) {
CompilerAsserts.neverPartOfCompilation();
LLVMMemory.putAddress(a, address);
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
this.address = value.getVal();
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
GenericManagedContainer newContainer = new GenericManagedContainer(type, allocator, value);
global.setContainer(newContainer);
}
@Override
Object get(LLVMGlobalVariable global) {
return LLVMAddress.fromLong(address);
}
}
/**
* This class is the most generic implementation and must not do any specializations. Otherwise,
* we would risk an endless deopt loop.
*/
static final class GenericManagedContainer extends AbstractManagedContainer {
private Object managedValue;
GenericManagedContainer(Type type, NativeAllocator allocator, Object managedValue) {
super(type, allocator);
this.managedValue = managedValue;
}
@Override
void destroy() {
// nothing to do
}
@Override
void copyToNative(LLVMAddress address) {
CompilerAsserts.neverPartOfCompilation();
assert type instanceof PointerType;
if (managedValue instanceof LLVMFunction) {
LLVMMemory.putAddress(address, ((LLVMFunction) managedValue).getFunctionPointer());
} else if (managedValue instanceof LLVMAddress) {
LLVMMemory.putAddress(address, (LLVMAddress) managedValue);
} else if (managedValue instanceof LLVMGlobalVariable) {
LLVMMemory.putAddress(address, ((LLVMGlobalVariable) managedValue).getNativeLocation());
} else if (managedValue instanceof TruffleObject || managedValue instanceof LLVMTruffleObject) {
throw new IllegalStateException("Cannot resolve address of a foreign TruffleObject: " + managedValue);
} else if (managedValue == null) {
// nothing to do
} else {
throw new AssertionError("Unknown type: " + managedValue.getClass());
}
}
@Override
void putAddress(LLVMGlobalVariable global, LLVMAddress value) {
this.managedValue = value;
}
@Override
void putTruffleObject(LLVMGlobalVariable global, TruffleObject value) {
this.managedValue = value;
}
@Override
void putLLVMTruffleObject(LLVMGlobalVariable global, LLVMTruffleObject value) {
this.managedValue = value;
}
@Override
void putFunction(LLVMGlobalVariable global, LLVMFunction value) {
this.managedValue = value;
}
@Override
void putBoxedPrimitive(LLVMGlobalVariable global, LLVMBoxedPrimitive value) {
this.managedValue = value;
}
@Override
Object get(LLVMGlobalVariable global) {
return managedValue;
}
@Override
void putGlobal(LLVMGlobalVariable global, LLVMGlobalVariable value) {
this.managedValue = value;
}
}
}