mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
Work on intrinsics
This commit is contained in:
parent
f62a80a1d8
commit
5c25eac049
|
@ -47,6 +47,7 @@ import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsics;
|
|||
import org.teavm.backend.wasm.model.WasmCustomSection;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmMemorySegment;
|
||||
import org.teavm.backend.wasm.model.WasmModule;
|
||||
import org.teavm.backend.wasm.model.WasmTag;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
|
@ -99,6 +100,9 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
|||
private List<WasmGCCustomGeneratorFactory> customGeneratorFactories = new ArrayList<>();
|
||||
private EntryPointTransformation entryPointTransformation = new EntryPointTransformation();
|
||||
private List<WasmGCClassConsumer> classConsumers = new ArrayList<>();
|
||||
private boolean enableDirectMallocSupport = false;
|
||||
private int directMallocMinHeapSize = 0x10000;
|
||||
private int directMallocMaxHeapSize = 0x10000000;
|
||||
|
||||
public void setObfuscated(boolean obfuscated) {
|
||||
this.obfuscated = obfuscated;
|
||||
|
@ -128,6 +132,18 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
|||
this.sourceMapLocation = sourceMapLocation;
|
||||
}
|
||||
|
||||
public void setEnableDirectMallocSupport(boolean enable) {
|
||||
this.enableDirectMallocSupport = enable;
|
||||
}
|
||||
|
||||
public void setDirectMallocMinHeapSize(int minHeapSize) {
|
||||
this.directMallocMinHeapSize = WasmRuntime.align(minHeapSize, WasmHeap.PAGE_SIZE);
|
||||
}
|
||||
|
||||
public void setDirectMallocMaxHeapSize(int maxHeapSize) {
|
||||
this.directMallocMaxHeapSize = WasmRuntime.align(maxHeapSize, WasmHeap.PAGE_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIntrinsicFactory(WasmGCIntrinsicFactory intrinsicFactory) {
|
||||
intrinsicFactories.add(intrinsicFactory);
|
||||
|
@ -194,6 +210,9 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
|||
var deps = new WasmGCDependencies(dependencyAnalyzer);
|
||||
deps.contribute();
|
||||
deps.contributeStandardExports();
|
||||
if(enableDirectMallocSupport) {
|
||||
deps.contributeDirectMalloc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,6 +304,17 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
|||
moduleGenerator.generate();
|
||||
customGenerators.contributeToModule(module);
|
||||
generateExceptionExports(declarationsGenerator);
|
||||
if(enableDirectMallocSupport) {
|
||||
var heapSegment = new WasmMemorySegment();
|
||||
if (!module.getSegments().isEmpty()) {
|
||||
var lastSegment = module.getSegments().get(module.getSegments().size() - 1);
|
||||
heapSegment.setOffset(WasmRuntime.align(lastSegment.getOffset() + lastSegment.getLength(), WasmHeap.PAGE_SIZE));
|
||||
}
|
||||
heapSegment.setLength(directMallocMinHeapSize);
|
||||
module.getSegments().add(heapSegment);
|
||||
intrinsics.setupLaxMallocHeap(heapSegment.getOffset(), heapSegment.getOffset() + directMallocMinHeapSize,
|
||||
heapSegment.getOffset() + directMallocMaxHeapSize);
|
||||
}
|
||||
adjustModuleMemory(module);
|
||||
|
||||
emitWasmFile(module, buildTarget, outputName, debugInfoBuilder);
|
||||
|
@ -390,10 +420,17 @@ public class WasmGCTarget implements TeaVMTarget, TeaVMWasmGCHost {
|
|||
return;
|
||||
}
|
||||
|
||||
if(enableDirectMallocSupport) {
|
||||
var minPages = (memorySize - 1) / WasmHeap.PAGE_SIZE + 1;
|
||||
var maxPages = (memorySize - directMallocMinHeapSize + directMallocMaxHeapSize - 1) / WasmHeap.PAGE_SIZE + 1;
|
||||
module.setMinMemorySize(minPages);
|
||||
module.setMaxMemorySize(maxPages);
|
||||
}else {
|
||||
var pages = (memorySize - 1) / WasmHeap.PAGE_SIZE + 1;
|
||||
module.setMinMemorySize(pages);
|
||||
module.setMaxMemorySize(pages);
|
||||
}
|
||||
}
|
||||
|
||||
private void emitWasmFile(WasmModule module, BuildTarget buildTarget, String outputName,
|
||||
GCDebugInfoBuilder debugInfoBuilder) throws IOException {
|
||||
|
|
|
@ -22,7 +22,9 @@ import org.teavm.backend.wasm.runtime.gc.WasmGCSupport;
|
|||
import org.teavm.dependency.AbstractDependencyListener;
|
||||
import org.teavm.dependency.DependencyAgent;
|
||||
import org.teavm.dependency.DependencyAnalyzer;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.runtime.LaxMalloc;
|
||||
|
||||
public class WasmGCDependencies {
|
||||
private DependencyAnalyzer analyzer;
|
||||
|
@ -127,4 +129,10 @@ public class WasmGCDependencies {
|
|||
private void contributeString() {
|
||||
analyzer.addDependencyListener(new StringInternDependencySupport());
|
||||
}
|
||||
|
||||
public void contributeDirectMalloc() {
|
||||
analyzer.linkMethod(new MethodReference(LaxMalloc.class, "laxMalloc", int.class, Address.class)).use();
|
||||
analyzer.linkMethod(new MethodReference(LaxMalloc.class, "laxCalloc", int.class, Address.class)).use();
|
||||
analyzer.linkMethod(new MethodReference(LaxMalloc.class, "laxFree", Address.class, void.class)).use();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2024 lax1dude.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.backend.wasm.intrinsics.gc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.backend.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmMemoryGrow;
|
||||
|
||||
public class LaxMallocIntrinsic implements WasmGCIntrinsic {
|
||||
|
||||
private final List<LaxMallocHeapMapper> addressList = new ArrayList<>();
|
||||
private final List<WasmInt32Constant> minAddrConstants = new ArrayList<>();
|
||||
private final List<WasmInt32Constant> maxAddrConstants = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "addrHeap": {
|
||||
WasmExpression value = context.generate(invocation.getArguments().get(0));
|
||||
if(value instanceof WasmInt32Constant) {
|
||||
// if addrHeap is passed a constant i32, add the heap offset at compile time
|
||||
final int memOffset = ((WasmInt32Constant)value).getValue();
|
||||
WasmInt32Constant ret = new WasmInt32Constant(0);
|
||||
addressList.add((heapLoc) -> {
|
||||
ret.setValue(heapLoc + memOffset);
|
||||
});
|
||||
return ret;
|
||||
}else {
|
||||
WasmInt32Constant heapLocConst = new WasmInt32Constant(0);
|
||||
WasmExpression calcOffset = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, heapLocConst, value);
|
||||
addressList.add(heapLocConst::setValue);
|
||||
return calcOffset;
|
||||
}
|
||||
}
|
||||
case "growHeapOuter": {
|
||||
return new WasmMemoryGrow(context.generate(invocation.getArguments().get(0)));
|
||||
}
|
||||
case "getHeapMinAddr": {
|
||||
WasmInt32Constant ret = new WasmInt32Constant(0);
|
||||
minAddrConstants.add(ret);
|
||||
return ret;
|
||||
}
|
||||
case "getHeapMaxAddr": {
|
||||
WasmInt32Constant ret = new WasmInt32Constant(0);
|
||||
maxAddrConstants.add(ret);
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void setHeapLocation(int heapLoc) {
|
||||
for(LaxMallocHeapMapper mapper : addressList) {
|
||||
mapper.setHeapLocation(heapLoc);
|
||||
}
|
||||
}
|
||||
|
||||
private static interface LaxMallocHeapMapper {
|
||||
void setHeapLocation(int heapLoc);
|
||||
}
|
||||
|
||||
public void setHeapMinAddr(int heapSegmentMinAddr) {
|
||||
for(WasmInt32Constant ct : minAddrConstants) {
|
||||
ct.setValue(heapSegmentMinAddr);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHeapMaxAddr(int heapSegmentMaxAddr) {
|
||||
for(WasmInt32Constant ct : maxAddrConstants) {
|
||||
ct.setValue(heapSegmentMaxAddr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -30,12 +30,14 @@ import org.teavm.interop.DirectMalloc;
|
|||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.runtime.LaxMalloc;
|
||||
|
||||
public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
||||
private Map<MethodReference, IntrinsicContainer> intrinsics = new HashMap<>();
|
||||
private List<WasmGCIntrinsicFactory> factories;
|
||||
private ClassReaderSource classes;
|
||||
private ServiceRepository services;
|
||||
private LaxMallocIntrinsic laxMallocIntrinsic;
|
||||
|
||||
public WasmGCIntrinsics(ClassReaderSource classes, ServiceRepository services,
|
||||
List<WasmGCIntrinsicFactory> factories, Map<MethodReference, WasmGCIntrinsic> customIntrinsics) {
|
||||
|
@ -54,6 +56,7 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
fillString();
|
||||
fillResources();
|
||||
fillDirectMalloc();
|
||||
fillLaxMalloc();
|
||||
fillAddress();
|
||||
for (var entry : customIntrinsics.entrySet()) {
|
||||
add(entry.getKey(), entry.getValue());
|
||||
|
@ -180,6 +183,15 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
add(new MethodReference(DirectMalloc.class, "zmemset", Address.class, int.class, void.class), intrinsic);
|
||||
}
|
||||
|
||||
private void fillLaxMalloc() {
|
||||
laxMallocIntrinsic = new LaxMallocIntrinsic();
|
||||
add(new MethodReference(LaxMalloc.class, "laxMalloc", int.class, Address.class), laxMallocIntrinsic);
|
||||
add(new MethodReference(LaxMalloc.class, "laxCalloc", int.class, Address.class), laxMallocIntrinsic);
|
||||
add(new MethodReference(LaxMalloc.class, "laxFree", Address.class, void.class), laxMallocIntrinsic);
|
||||
add(new MethodReference(LaxMalloc.class, "getHeapMinSize", int.class), laxMallocIntrinsic);
|
||||
add(new MethodReference(LaxMalloc.class, "getHeapMaxSize", int.class), laxMallocIntrinsic);
|
||||
}
|
||||
|
||||
private void fillAddress() {
|
||||
var intrinsic = new AddressIntrinsic();
|
||||
add(new MethodReference(Address.class, "add", int.class, Address.class), intrinsic);
|
||||
|
@ -233,6 +245,12 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
|
|||
return result.intrinsic;
|
||||
}
|
||||
|
||||
public void setupLaxMallocHeap(int heapAddr, int heapSegmentMinAddr, int heapSegmentMaxAddr) {
|
||||
laxMallocIntrinsic.setHeapLocation(heapAddr);
|
||||
laxMallocIntrinsic.setHeapMinAddr(heapSegmentMinAddr);
|
||||
laxMallocIntrinsic.setHeapMaxAddr(heapSegmentMaxAddr);
|
||||
}
|
||||
|
||||
static class IntrinsicContainer {
|
||||
final WasmGCIntrinsic intrinsic;
|
||||
|
||||
|
|
|
@ -50,12 +50,23 @@ public final class LaxMalloc {
|
|||
private static final int ADDR_HEAP_BUCKETS_START = 16; // Address to the list of 64 pointers to the beginnings of the 64 buckets
|
||||
private static final int ADDR_HEAP_DATA_START = 272; // Beginning of the first chunk of the heap
|
||||
|
||||
private static native Address addrHeap(int offset); // Intrinsic function to get an address in the heap segment
|
||||
|
||||
private static native int growHeapOuter(int bytes); // Intrinsic function to grow the heap segment
|
||||
|
||||
private static native Address getHeapMinAddr(); // Intrinsic function to get the minimum direct malloc heap segment ending address
|
||||
|
||||
private static native Address getHeapMaxAddr(); // Intrinsic function to get the maximum direct malloc heap segment ending address
|
||||
|
||||
@Import(name = "teavm_notifyHeapResized")
|
||||
private static native void notifyHeapResized();
|
||||
|
||||
static {
|
||||
// zero out the control region
|
||||
DirectMalloc.zmemset(Address.fromInt(0), ADDR_HEAP_DATA_START);
|
||||
DirectMalloc.zmemset(addrHeap(0), ADDR_HEAP_DATA_START);
|
||||
// initialize heap limit
|
||||
Address.fromInt(ADDR_HEAP_INNER_LIMIT).putInt(ADDR_HEAP_DATA_START);
|
||||
Address.fromInt(ADDR_HEAP_OUTER_LIMIT).putInt(0x10000);
|
||||
addrHeap(ADDR_HEAP_INNER_LIMIT).putAddress(addrHeap(ADDR_HEAP_DATA_START));
|
||||
addrHeap(ADDR_HEAP_OUTER_LIMIT).putAddress(getHeapMinAddr());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,7 +107,7 @@ public final class LaxMalloc {
|
|||
}
|
||||
|
||||
// load bitmask of buckets with free chunks
|
||||
long bucketMask = Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
long bucketMask = addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
|
||||
// mask away the buckets that we know are too small for this allocation
|
||||
bucketMask = (bucketMask & (0xFFFFFFFFFFFFFFFFL << bucket));
|
||||
|
@ -125,7 +136,7 @@ public final class LaxMalloc {
|
|||
// quickly determine which bucket it is with bit hacks
|
||||
int availableBucket = Long.numberOfTrailingZeros(bucketMask);
|
||||
|
||||
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(availableBucket << SIZEOF_PTR_SH);
|
||||
Address bucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(availableBucket << SIZEOF_PTR_SH);
|
||||
Address chunkPtr = bucketStartAddr.getAddress();
|
||||
int chunkSize = readChunkSizeStatus(chunkPtr);
|
||||
Address itrChunkStart = Address.fromInt(0);
|
||||
|
@ -149,7 +160,7 @@ public final class LaxMalloc {
|
|||
if(bucketMask != 0l) {
|
||||
// there is a bucket with a larger chunk
|
||||
int availableLargerBucket = Long.numberOfTrailingZeros(bucketMask);
|
||||
Address largerBucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(availableLargerBucket << SIZEOF_PTR_SH);
|
||||
Address largerBucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(availableLargerBucket << SIZEOF_PTR_SH);
|
||||
Address largerChunkPtr = largerBucketStartAddr.getAddress();
|
||||
int largerChunkSize = readChunkSizeStatus(largerChunkPtr);
|
||||
|
||||
|
@ -234,10 +245,10 @@ public final class LaxMalloc {
|
|||
private static Address laxHugeAlloc(int sizeBytes, boolean cleared) {
|
||||
|
||||
// check the bucket mask if bucket 63 has any chunks
|
||||
if((Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).getLong() & 0x8000000000000000L) != 0) {
|
||||
if((addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).getLong() & 0x8000000000000000L) != 0) {
|
||||
|
||||
// bucket 63 address
|
||||
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(63 << SIZEOF_PTR_SH);
|
||||
Address bucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(63 << SIZEOF_PTR_SH);
|
||||
Address chunkPtr = bucketStartAddr.getAddress();
|
||||
|
||||
// iterate all free huge chunks
|
||||
|
@ -302,7 +313,7 @@ public final class LaxMalloc {
|
|||
// set the chunk no longer in use
|
||||
chunkSize &= 0x7FFFFFFF;
|
||||
|
||||
if(Address.fromInt(ADDR_HEAP_DATA_START).isLessThan(chunkPtr)) {
|
||||
if(addrHeap(ADDR_HEAP_DATA_START).isLessThan(chunkPtr)) {
|
||||
// check if we can merge with the previous chunk, and move it to another bucket
|
||||
Address prevChunkPtr = chunkPtr.add(-(chunkPtr.add(-4).getInt()));
|
||||
int prevChunkSize = readChunkSizeStatus(prevChunkPtr);
|
||||
|
@ -320,7 +331,7 @@ public final class LaxMalloc {
|
|||
}
|
||||
|
||||
Address nextChunkPtr = chunkPtr.add(chunkSize);
|
||||
if(Address.fromInt(ADDR_HEAP_INNER_LIMIT).getAddress().isLessThan(nextChunkPtr)) {
|
||||
if(addrHeap(ADDR_HEAP_INNER_LIMIT).getAddress().isLessThan(nextChunkPtr)) {
|
||||
// check if we can merge with the next chunk as well
|
||||
int nextChunkSize = readChunkSizeStatus(nextChunkPtr);
|
||||
if((nextChunkSize & 0x80000000) == 0) {
|
||||
|
@ -388,8 +399,8 @@ public final class LaxMalloc {
|
|||
private static void linkChunkInFreeList(Address chunkPtr, int chunkSize) {
|
||||
int bucket = getListBucket(chunkSize - 8); // size - 2 ints
|
||||
|
||||
long bucketMask = Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(bucket << SIZEOF_PTR_SH);
|
||||
long bucketMask = addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
Address bucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(bucket << SIZEOF_PTR_SH);
|
||||
|
||||
// test the bucket mask if the bucket is empty
|
||||
if((bucketMask & (1L << bucket)) == 0l) {
|
||||
|
@ -401,7 +412,7 @@ public final class LaxMalloc {
|
|||
|
||||
// set the free bit in bucket mask
|
||||
bucketMask |= (1L << bucket);
|
||||
Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).putLong(bucketMask);
|
||||
addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).putLong(bucketMask);
|
||||
|
||||
}else {
|
||||
|
||||
|
@ -434,13 +445,13 @@ public final class LaxMalloc {
|
|||
|
||||
int chunkBucket = getListBucket(chunkSize - 8); // size - 2 ints
|
||||
|
||||
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(chunkBucket << SIZEOF_PTR_SH);
|
||||
Address bucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(chunkBucket << SIZEOF_PTR_SH);
|
||||
bucketStartAddr.putAddress(Address.fromInt(0)); // remove chunk from the bucket
|
||||
|
||||
// clear the bit in the free buckets bitmask
|
||||
long bucketsFreeMask = Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
long bucketsFreeMask = addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).getLong();
|
||||
bucketsFreeMask &= ~(1L << chunkBucket);
|
||||
Address.fromInt(ADDR_HEAP_BUCKETS_FREE_MASK).putLong(bucketsFreeMask);
|
||||
addrHeap(ADDR_HEAP_BUCKETS_FREE_MASK).putLong(bucketsFreeMask);
|
||||
|
||||
}else {
|
||||
// there are other chunks in this bucket
|
||||
|
@ -450,7 +461,7 @@ public final class LaxMalloc {
|
|||
writeChunkPrevFreeAddr(nextChunkPtr, prevChunkPtr);
|
||||
|
||||
int chunkBucket = getListBucket(chunkSize - 8); // size - 2 ints
|
||||
Address bucketStartAddr = Address.fromInt(ADDR_HEAP_BUCKETS_START).add(chunkBucket << SIZEOF_PTR_SH);
|
||||
Address bucketStartAddr = addrHeap(ADDR_HEAP_BUCKETS_START).add(chunkBucket << SIZEOF_PTR_SH);
|
||||
Address bucketStartChunk = bucketStartAddr.getAddress();
|
||||
|
||||
// chunk is the first in the bucket, so we also need to
|
||||
|
@ -480,28 +491,27 @@ public final class LaxMalloc {
|
|||
* This is our sbrk
|
||||
*/
|
||||
private static Address growHeap(int amount) {
|
||||
Address heapInnerLimit = Address.fromInt(ADDR_HEAP_INNER_LIMIT).getAddress();
|
||||
Address heapOuterLimit = Address.fromInt(ADDR_HEAP_OUTER_LIMIT).getAddress();
|
||||
Address heapInnerLimit = addrHeap(ADDR_HEAP_INNER_LIMIT).getAddress();
|
||||
Address heapOuterLimit = addrHeap(ADDR_HEAP_OUTER_LIMIT).getAddress();
|
||||
Address newHeapInnerLimit = heapInnerLimit.add(amount);
|
||||
if(heapOuterLimit.isLessThan(newHeapInnerLimit)) {
|
||||
int bytesNeeded = newHeapInnerLimit.toInt() - heapOuterLimit.toInt();
|
||||
bytesNeeded = (bytesNeeded + 0xFFFF) & 0xFFFF0000;
|
||||
if(growHeapOuter(bytesNeeded)) {
|
||||
Address.fromInt(ADDR_HEAP_INNER_LIMIT).putAddress(newHeapInnerLimit);
|
||||
Address.fromInt(ADDR_HEAP_OUTER_LIMIT).putAddress(heapOuterLimit.add(bytesNeeded));
|
||||
Address newHeapOuterLimit = heapOuterLimit.add(bytesNeeded);
|
||||
if(!getHeapMaxAddr().isLessThan(newHeapOuterLimit) && growHeapOuter(bytesNeeded >> 16) != -1) {
|
||||
addrHeap(ADDR_HEAP_INNER_LIMIT).putAddress(newHeapInnerLimit);
|
||||
addrHeap(ADDR_HEAP_OUTER_LIMIT).putAddress(newHeapOuterLimit);
|
||||
notifyHeapResized();
|
||||
return newHeapInnerLimit;
|
||||
}else {
|
||||
return Address.fromInt(0);
|
||||
}
|
||||
}else {
|
||||
Address.fromInt(ADDR_HEAP_INNER_LIMIT).putAddress(newHeapInnerLimit);
|
||||
addrHeap(ADDR_HEAP_INNER_LIMIT).putAddress(newHeapInnerLimit);
|
||||
return newHeapInnerLimit;
|
||||
}
|
||||
}
|
||||
|
||||
@Import(name = "teavm_growHeap")
|
||||
private static native boolean growHeapOuter(int bytes);
|
||||
|
||||
/**
|
||||
* Note that on a free chunk, this is the size, because the status bit is 0
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user