/*
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or
* data (collectively the "Software"), free of charge and under any and all
* copyright rights in the Software, and any and all patent rights owned or
* freely licensable by each licensor hereunder covering either (i) the
* unmodified Software as contributed to or provided by such licensor, or (ii)
* the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or at a
* minimum a reference to the UPL must be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.graalvm.wasm;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.FrameSlotKind;
import org.graalvm.wasm.collection.IntArrayList;
public final class WasmCodeEntry {
private static final Object STACK_LOCALS_SLOT_INDEX = 0;
private final WasmFunction function;
@CompilationFinal(dimensions = 1) private final byte[] data;
@CompilationFinal(dimensions = 1) private byte[] localTypes;
@CompilationFinal(dimensions = 1) private int[] intConstants;
@CompilationFinal(dimensions = 2) private int[][] branchTables;
@CompilationFinal(dimensions = 1) private int[] profileCounters;
@CompilationFinal private FrameSlot stackLocalsSlot;
@CompilationFinal private int maxStackSize;
public WasmCodeEntry(WasmFunction function, byte[] data) {
this.function = function;
this.data = data;
this.localTypes = null;
this.intConstants = null;
this.profileCounters = null;
}
public WasmFunction function() {
return function;
}
public byte[] data() {
return data;
}
public void initStackLocals(FrameDescriptor frameDescriptor, int maximumStackSize) {
this.stackLocalsSlot = frameDescriptor.addFrameSlot(STACK_LOCALS_SLOT_INDEX, FrameSlotKind.Object);
this.maxStackSize = maximumStackSize;
}
public int maxStackSize() {
return maxStackSize;
}
public FrameSlot stackLocalsSlot() {
return stackLocalsSlot;
}
public void setLocalTypes(byte[] localTypes) {
this.localTypes = localTypes;
}
public byte localType(int index) {
return localTypes[index];
}
@SuppressWarnings("unused")
public int intConstant(int index) {
return intConstants[index];
}
public void setIntConstants(int[] intConstants) {
this.intConstants = intConstants;
}
public int[] intConstants() {
return intConstants;
}
public int[] branchTable(int index) {
return branchTables[index];
}
public void setBranchTables(int[][] branchTables) {
this.branchTables = branchTables;
}
public void setProfileCount(int size) {
if (size > 0) {
this.profileCounters = new int[size];
} else {
this.profileCounters = IntArrayList.EMPTY_INT_ARRAY;
}
}
public int[] profileCounters() {
return profileCounters;
}
public int numLocals() {
return localTypes.length;
}
public int functionIndex() {
return function.index();
}
A constant holding the maximum value an int
can have, 215-1. The sum of
the true and false count must not overflow. This constant is used to check whether one of the
counts does not exceed the required maximum value.
/**
* A constant holding the maximum value an {@code int} can have, 2<sup>15</sup>-1. The sum of
* the true and false count must not overflow. This constant is used to check whether one of the
* counts does not exceed the required maximum value.
*/
public static final int CONDITION_COUNT_MAX_VALUE = 0x3fff;
Same logic as in ConditionProfile.profile
. Params: - index – Condition index
- condition – Condition value
Returns: condition
/**
* Same logic as in {@link com.oracle.truffle.api.profiles.ConditionProfile#profile}.
*
* @param index Condition index
* @param condition Condition value
* @return {@code condition}
*/
public static boolean profileCondition(int[] counters, int index, boolean condition) {
// locals required to guarantee no overflow in multi-threaded environments
int tf = counters[index];
int t = tf >>> 16;
int f = tf & 0xffff;
boolean val = condition;
if (val) {
if (!CompilerDirectives.inInterpreter()) {
if (t == 0) {
CompilerDirectives.transferToInterpreterAndInvalidate();
}
if (f == 0) {
// Make this branch fold during PE
val = true;
}
} else {
if (t < CONDITION_COUNT_MAX_VALUE) {
counters[index] = ((t + 1) << 16) | f;
}
}
} else {
if (!CompilerDirectives.inInterpreter()) {
if (f == 0) {
CompilerDirectives.transferToInterpreterAndInvalidate();
}
if (t == 0) {
// Make this branch fold during PE
val = false;
}
} else {
if (f < CONDITION_COUNT_MAX_VALUE) {
counters[index] = (t << 16) | (f + 1);
}
}
}
if (CompilerDirectives.inInterpreter()) {
// no branch probability calculation in the interpreter
return val;
} else {
int sum = t + f;
return CompilerDirectives.injectBranchProbability((double) t / (double) sum, val);
}
}
@Override
public String toString() {
return "wasm-code-entry:" + functionIndex();
}
}