Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.oracle.truffle.api.frame.FrameDescriptor Maven / Gradle / Ivy
Go to download
Truffle is a multi-language framework for executing dynamic languages
that achieves high performance when combined with Graal.
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.frame;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.impl.Accessor;
import com.oracle.truffle.api.impl.TVMCI;
/**
* Descriptor of the slots of frame objects. Multiple frame instances are associated with one such
* descriptor.
*
* @since 0.8 or earlier
*/
public final class FrameDescriptor implements Cloneable {
private final Object defaultValue;
private final ArrayList slots;
private final HashMap identifierToSlotMap;
private Assumption version;
private HashMap identifierToNotInFrameAssumptionMap;
/**
* Flag that can be used by the runtime to track that {@link Frame#materialize()} was called on
* a frame that has this descriptor. Since the flag is not public API, access is encapsulated
* via {@link TVMCI}.
*
* @since 0.14
*/
boolean materializeCalled;
private static final String NEVER_PART_OF_COMPILATION_MESSAGE = "interpreter-only. includes hashmap operations.";
/**
* Constructs empty descriptor. The {@link #getDefaultValue()} is null
.
*
* @since 0.8 or earlier
*/
public FrameDescriptor() {
this(null);
}
/**
* Constructs new descriptor with specified {@link #getDefaultValue()}.
*
* @param defaultValue to be returned from {@link #getDefaultValue()}
* @since 0.8 or earlier
*/
public FrameDescriptor(Object defaultValue) {
CompilerAsserts.neverPartOfCompilation("do not create a FrameDescriptor from compiled code");
this.defaultValue = defaultValue;
slots = new ArrayList<>();
identifierToSlotMap = new HashMap<>();
version = createVersion();
}
/**
* Use {@link #FrameDescriptor()}.
*
* @return new instance of the descriptor
* @deprecated
* @since 0.8 or earlier
*/
@Deprecated
public static FrameDescriptor create() {
return new FrameDescriptor();
}
/**
* Use {@link #FrameDescriptor(java.lang.Object) }.
*
* @return new instance of the descriptor
* @deprecated
* @since 0.8 or earlier
*/
@Deprecated
public static FrameDescriptor create(Object defaultValue) {
return new FrameDescriptor(defaultValue);
}
/**
* Adds frame slot. Delegates to
* {@link #addFrameSlot(java.lang.Object, java.lang.Object, com.oracle.truffle.api.frame.FrameSlotKind)
* addFrameSlot}(identifier, null
, {@link FrameSlotKind#Illegal}). This is a slow
* operation that switches to interpreter mode.
*
* @param identifier key for the slot
* @return the newly created slot
* @since 0.8 or earlier
*/
public FrameSlot addFrameSlot(Object identifier) {
return addFrameSlot(identifier, null, FrameSlotKind.Illegal);
}
/**
* Adds frame slot. Delegates to
* {@link #addFrameSlot(java.lang.Object, java.lang.Object, com.oracle.truffle.api.frame.FrameSlotKind)
* addFrameSlot}(identifier, null
, kind
). This is a slow operation
* that switches to interpreter mode.
*
* @param identifier key for the slot
* @param kind the kind of the new slot
* @return the newly created slot
* @since 0.8 or earlier
*/
public FrameSlot addFrameSlot(Object identifier, FrameSlotKind kind) {
return addFrameSlot(identifier, null, kind);
}
/**
* Adds new frame slot to {@link #getSlots()} list. This is a slow operation that switches to
* interpreter mode.
*
* @param identifier key for the slot - it needs proper {@link #equals(java.lang.Object)} and
* {@link Object#hashCode()} implementations
* @param info additional {@link FrameSlot#getInfo() information for the slot}
* @param kind the kind of the new slot
* @return the newly created slot
* @throws IllegalArgumentException if a frame slot with the same identifier exists
* @since 0.8 or earlier
*/
public FrameSlot addFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
CompilerAsserts.neverPartOfCompilation(NEVER_PART_OF_COMPILATION_MESSAGE);
if (identifierToSlotMap.containsKey(identifier)) {
throw new IllegalArgumentException("duplicate frame slot: " + identifier);
}
FrameSlot slot = new FrameSlot(this, identifier, info, kind, slots.size());
slots.add(slot);
identifierToSlotMap.put(identifier, slot);
updateVersion();
invalidateNotInFrameAssumption(identifier);
return slot;
}
/**
* Finds an existing slot. This is a slow operation.
*
* @param identifier the key of the slot to search for
* @return the slot or null
* @since 0.8 or earlier
*/
public FrameSlot findFrameSlot(Object identifier) {
CompilerAsserts.neverPartOfCompilation(NEVER_PART_OF_COMPILATION_MESSAGE);
return identifierToSlotMap.get(identifier);
}
/**
* Finds an existing slot or creates new one. This is a slow operation.
*
* @param identifier the key of the slot to search for
* @return the slot
* @since 0.8 or earlier
*/
public FrameSlot findOrAddFrameSlot(Object identifier) {
FrameSlot result = findFrameSlot(identifier);
if (result != null) {
return result;
}
return addFrameSlot(identifier);
}
/**
* Finds an existing slot or creates new one. This is a slow operation.
*
* @param identifier the key of the slot to search for
* @param kind the kind for the newly created slot
* @return the found or newly created slot
* @since 0.8 or earlier
*/
public FrameSlot findOrAddFrameSlot(Object identifier, FrameSlotKind kind) {
FrameSlot result = findFrameSlot(identifier);
if (result != null) {
return result;
}
return addFrameSlot(identifier, kind);
}
/**
* Finds an existing slot or creates new one. This is a slow operation.
*
* @param identifier the key of the slot to search for
* @param info info for the newly created slot
* @param kind the kind for the newly created slot
* @return the found or newly created slot
* @since 0.8 or earlier
*/
public FrameSlot findOrAddFrameSlot(Object identifier, Object info, FrameSlotKind kind) {
FrameSlot result = findFrameSlot(identifier);
if (result != null) {
return result;
}
return addFrameSlot(identifier, info, kind);
}
/**
* Removes a slot. If the identifier is found, its slot is removed from this descriptor. This is
* a slow operation.
*
* @param identifier identifies the slot to remove
* @throws IllegalArgumentException if no such frame slot exists
* @since 0.8 or earlier
*/
public void removeFrameSlot(Object identifier) {
CompilerAsserts.neverPartOfCompilation(NEVER_PART_OF_COMPILATION_MESSAGE);
if (!identifierToSlotMap.containsKey(identifier)) {
throw new IllegalArgumentException("no such frame slot: " + identifier);
}
slots.remove(identifierToSlotMap.get(identifier));
identifierToSlotMap.remove(identifier);
updateVersion();
getNotInFrameAssumption(identifier);
}
/**
* Returns number of slots in the descriptor.
*
* @return the same value as {@link #getSlots()}.{@link List#size()} would return
* @since 0.8 or earlier
*/
public int getSize() {
return slots.size();
}
/**
* Current set of slots in the descriptor.
*
* @return unmodifiable list of {@link FrameSlot}
* @since 0.8 or earlier
*/
public List extends FrameSlot> getSlots() {
return Collections.unmodifiableList(slots);
}
/**
* Retrieve the list of all the identifiers associated with this frame descriptor.
*
* @return the list of all the identifiers in this frame descriptor
* @since 0.8 or earlier
*/
public Set getIdentifiers() {
return Collections.unmodifiableSet(identifierToSlotMap.keySet());
}
/**
* Deeper copy of the descriptor. Copies all slots in the descriptor, but only their
* {@linkplain FrameSlot#getIdentifier() identifier} and {@linkplain FrameSlot#getInfo() info}
* but not their {@linkplain FrameSlot#getKind() kind}!
*
* @return new instance of a descriptor with copies of values from this one
* @since 0.8 or earlier
*/
public FrameDescriptor copy() {
FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
for (int i = 0; i < slots.size(); i++) {
FrameSlot slot = slots.get(i);
clonedFrameDescriptor.addFrameSlot(slot.getIdentifier(), slot.getInfo(), FrameSlotKind.Illegal);
}
return clonedFrameDescriptor;
}
/**
* Shallow copy of the descriptor. Re-uses the existing slots in new descriptor. As a result, if
* you {@link FrameSlot#setKind(com.oracle.truffle.api.frame.FrameSlotKind) change kind} of one
* of the slots it is changed in the original as well as in the shallow copy.
*
* @return new instance of a descriptor with copies of values from this one
* @since 0.8 or earlier
*/
public FrameDescriptor shallowCopy() {
FrameDescriptor clonedFrameDescriptor = new FrameDescriptor(this.defaultValue);
clonedFrameDescriptor.slots.addAll(slots);
clonedFrameDescriptor.identifierToSlotMap.putAll(identifierToSlotMap);
return clonedFrameDescriptor;
}
/**
* Invalidates the current, and create a new version assumption.
*/
void updateVersion() {
version.invalidate();
version = createVersion();
}
/**
* Returns an assumption reflecting the frame's current version, which is updated every time a
* slot is added or removed, or an existing slot's kind is changed. This assumption is
* associated with compiled code that depends on the internal frame layout.
*
* @return an assumption invalidated when a slot is added or removed, or a slot kind changed.
* @since 0.8 or earlier
*/
public Assumption getVersion() {
return version;
}
private static Assumption createVersion() {
return Truffle.getRuntime().createAssumption("frame version");
}
/**
* Default value for the created slots.
*
* @return value provided to {@link #FrameDescriptor(java.lang.Object)}
* @since 0.8 or earlier
*/
public Object getDefaultValue() {
return defaultValue;
}
/**
* Make an assumption that no slot with the specified identifier is present in this frame
* descriptor. Invalidated when a frame slot with the identifier is added.
*
* @param identifier frame slot identifier
* @return an assumption that this frame descriptor does not contain a slot with the identifier
* @throws IllegalArgumentException if the frame descriptor contains a slot with the identifier
* @since 0.8 or earlier
*/
public Assumption getNotInFrameAssumption(Object identifier) {
if (identifierToSlotMap.containsKey(identifier)) {
throw new IllegalArgumentException("Cannot get not-in-frame assumption for existing frame slot!");
}
if (identifierToNotInFrameAssumptionMap == null) {
identifierToNotInFrameAssumptionMap = new HashMap<>();
} else {
Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
if (assumption != null) {
return assumption;
}
}
Assumption assumption = Truffle.getRuntime().createAssumption("identifier not in frame");
identifierToNotInFrameAssumptionMap.put(identifier, assumption);
return assumption;
}
private void invalidateNotInFrameAssumption(Object identifier) {
if (identifierToNotInFrameAssumptionMap != null) {
Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier);
if (assumption != null) {
assumption.invalidate();
identifierToNotInFrameAssumptionMap.remove(identifier);
}
}
}
/** @since 0.8 or earlier */
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("FrameDescriptor@").append(Integer.toHexString(hashCode()));
sb.append("{");
boolean comma = false;
for (FrameSlot slot : slots) {
if (comma) {
sb.append(", ");
} else {
comma = true;
}
sb.append(slot.getIndex()).append(":").append(slot.getIdentifier());
}
sb.append("}");
return sb.toString();
}
/** @since 0.14 */
static final class AccessorFrames extends Accessor {
@Override
protected Frames framesSupport() {
return new FramesImpl();
}
static final class FramesImpl extends Frames {
@Override
protected void markMaterializeCalled(FrameDescriptor descriptor) {
descriptor.materializeCalled = true;
}
@Override
protected boolean getMaterializeCalled(FrameDescriptor descriptor) {
return descriptor.materializeCalled;
}
}
}
static {
// registers into Accessor.FRAMES
@SuppressWarnings("unused")
AccessorFrames unused = new AccessorFrames();
}
}