mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Reduce memory consumption of incremental compilation on dev server
This commit is contained in:
parent
35730d665f
commit
573c5f6064
|
@ -525,7 +525,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
|| methodInjectors.containsKey(method.getReference())) {
|
||||
continue;
|
||||
}
|
||||
if (!method.hasModifier(ElementModifier.NATIVE) && method.getProgram() == null) {
|
||||
if (!method.hasModifier(ElementModifier.NATIVE) && !method.hasProgram()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package org.teavm.cache;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -26,6 +29,9 @@ import org.teavm.model.ProgramCache;
|
|||
public class InMemoryProgramCache implements ProgramCache {
|
||||
private Map<MethodReference, Item> cache = new HashMap<>();
|
||||
private Map<MethodReference, Item> newItems = new HashMap<>();
|
||||
private InMemorySymbolTable symbolTable = new InMemorySymbolTable();
|
||||
private InMemorySymbolTable fileSymbolTable = new InMemorySymbolTable();
|
||||
private ProgramIO io = new ProgramIO(new InMemorySymbolTable(), new InMemorySymbolTable());
|
||||
|
||||
@Override
|
||||
public Program get(MethodReference method, CacheStatus cacheStatus) {
|
||||
|
@ -37,13 +43,23 @@ public class InMemoryProgramCache implements ProgramCache {
|
|||
if (Arrays.stream(item.dependencies).anyMatch(cacheStatus::isStaleClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return item.program;
|
||||
try {
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(item.program);
|
||||
return io.read(input);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(MethodReference method, Program program, Supplier<String[]> dependencies) {
|
||||
newItems.put(method, new Item(program, dependencies.get().clone()));
|
||||
try {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
io.write(program, output);
|
||||
newItems.put(method, new Item(output.toByteArray(), dependencies.get().clone()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
|
@ -62,13 +78,15 @@ public class InMemoryProgramCache implements ProgramCache {
|
|||
public void invalidate() {
|
||||
cache.clear();
|
||||
newItems.clear();
|
||||
symbolTable.invalidate();
|
||||
fileSymbolTable.invalidate();
|
||||
}
|
||||
|
||||
static final class Item {
|
||||
final Program program;
|
||||
final byte[] program;
|
||||
final String[] dependencies;
|
||||
|
||||
Item(Program program, String[] dependencies) {
|
||||
Item(byte[] program, String[] dependencies) {
|
||||
this.program = program;
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
|
|
47
core/src/main/java/org/teavm/cache/InMemorySymbolTable.java
vendored
Normal file
47
core/src/main/java/org/teavm/cache/InMemorySymbolTable.java
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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.cache;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class InMemorySymbolTable implements SymbolTable {
|
||||
private List<String> symbols = new ArrayList<>();
|
||||
private Map<String, Integer> indexes = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String at(int index) {
|
||||
return symbols.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lookup(String symbol) {
|
||||
Integer index = indexes.get(symbol);
|
||||
if (index == null) {
|
||||
index = symbols.size();
|
||||
symbols.add(symbol);
|
||||
indexes.put(symbol, index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
symbols.clear();
|
||||
indexes.clear();
|
||||
}
|
||||
}
|
881
core/src/main/java/org/teavm/cache/ProgramIO.java
vendored
881
core/src/main/java/org/teavm/cache/ProgramIO.java
vendored
File diff suppressed because it is too large
Load Diff
100
core/src/main/java/org/teavm/cache/VarDataInput.java
vendored
Normal file
100
core/src/main/java/org/teavm/cache/VarDataInput.java
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class VarDataInput {
|
||||
private static final int DATA = 0x7F;
|
||||
private static final int NEXT = 0x80;
|
||||
private InputStream input;
|
||||
|
||||
public VarDataInput(InputStream input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public int readUnsigned() throws IOException {
|
||||
int value = 0;
|
||||
int pos = 0;
|
||||
int b;
|
||||
do {
|
||||
b = input.read();
|
||||
value |= (b & DATA) << pos;
|
||||
pos += 7;
|
||||
} while ((b & NEXT) != 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public int readSigned() throws IOException {
|
||||
int value = readUnsigned();
|
||||
return (value & 1) == 0 ? (value >> 1) : -(value >> 1);
|
||||
}
|
||||
|
||||
public long readUnsignedLong() throws IOException {
|
||||
long value = 0;
|
||||
int pos = 0;
|
||||
int b;
|
||||
do {
|
||||
b = input.read();
|
||||
value |= ((long) b & DATA) << pos;
|
||||
pos += 7;
|
||||
} while ((b & NEXT) != 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public long readSignedLong() throws IOException {
|
||||
long value = readUnsignedLong();
|
||||
return (value & 1) == 0 ? (value >> 1) : -(value >> 1);
|
||||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
int exponent = readSigned() + 127;
|
||||
int mantissa = Integer.reverse(readUnsigned()) >>> 8;
|
||||
boolean sign = (mantissa & (1 << 23)) != 0;
|
||||
|
||||
int bits = mantissa & ((1 << 23) - 1);
|
||||
bits |= exponent << 23;
|
||||
if (sign) {
|
||||
bits |= 1 << 31;
|
||||
}
|
||||
|
||||
return Float.intBitsToFloat(bits);
|
||||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
int exponent = readSigned() + 1023;
|
||||
long mantissa = Long.reverse(readUnsignedLong()) >>> 11;
|
||||
boolean sign = (mantissa & (1L << 52)) != 0;
|
||||
|
||||
long bits = mantissa & ((1L << 52) - 1);
|
||||
bits |= (long) exponent << 52;
|
||||
if (sign) {
|
||||
bits |= 1L << 53;
|
||||
}
|
||||
|
||||
return Double.longBitsToDouble(bits);
|
||||
}
|
||||
|
||||
public String read() throws IOException {
|
||||
int sz = readUnsigned();
|
||||
char[] chars = new char[sz];
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
chars[i] = (char) readUnsigned();
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
}
|
84
core/src/main/java/org/teavm/cache/VarDataOutput.java
vendored
Normal file
84
core/src/main/java/org/teavm/cache/VarDataOutput.java
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* 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.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class VarDataOutput {
|
||||
private static final int DATA = 0x7F;
|
||||
private static final int NEXT = 0x80;
|
||||
private OutputStream output;
|
||||
|
||||
public VarDataOutput(OutputStream output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public void writeUnsigned(int value) throws IOException {
|
||||
while ((value & DATA) != value) {
|
||||
output.write((value & DATA) | NEXT);
|
||||
value >>>= 7;
|
||||
}
|
||||
output.write(value);
|
||||
}
|
||||
|
||||
public void writeSigned(int value) throws IOException {
|
||||
writeUnsigned(value < 0 ? ((-value) << 1) | 1 : value << 1);
|
||||
}
|
||||
|
||||
public void writeUnsigned(long value) throws IOException {
|
||||
while ((value & DATA) != value) {
|
||||
output.write((int) (value & DATA) | NEXT);
|
||||
value >>>= 7;
|
||||
}
|
||||
output.write((int) value);
|
||||
}
|
||||
|
||||
public void writeSigned(long value) throws IOException {
|
||||
writeUnsigned(value < 0 ? ((-value) << 1) | 1 : value << 1);
|
||||
}
|
||||
|
||||
public void writeFloat(float value) throws IOException {
|
||||
int bits = Float.floatToRawIntBits(value);
|
||||
boolean sign = (bits & (1 << 31)) != 0;
|
||||
int exponent = (bits >> 23) & ((1 << 8) - 1);
|
||||
int mantissa = bits & ((1 << 23) - 1);
|
||||
if (sign) {
|
||||
mantissa |= 1 << 23;
|
||||
}
|
||||
writeSigned(exponent - 127);
|
||||
writeUnsigned(Integer.reverse(mantissa << 8));
|
||||
}
|
||||
|
||||
public void writeDouble(double value) throws IOException {
|
||||
long bits = Double.doubleToRawLongBits(value);
|
||||
boolean sign = (bits & (1L << 63)) != 0;
|
||||
int exponent = (int) (bits >> 52) & ((1 << 11) - 1);
|
||||
long mantissa = bits & ((1L << 52) - 1);
|
||||
if (sign) {
|
||||
mantissa |= 1L << 52;
|
||||
}
|
||||
writeSigned(exponent - 1023);
|
||||
writeUnsigned(Long.reverse(mantissa << 11));
|
||||
}
|
||||
|
||||
public void write(String s) throws IOException {
|
||||
writeUnsigned(s.length());
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
writeUnsigned(s.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,29 +115,21 @@ public class MethodHolder extends MemberHolder implements MethodReader {
|
|||
public Program getProgram() {
|
||||
if (program == null && programSupplier != null) {
|
||||
program = programSupplier.apply(this);
|
||||
if (program != null) {
|
||||
program.setMethod(this);
|
||||
}
|
||||
programSupplier = null;
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
public void setProgram(Program program) {
|
||||
if (this.program != null) {
|
||||
this.program.setMethod(null);
|
||||
}
|
||||
this.program = program;
|
||||
this.programSupplier = null;
|
||||
if (this.program != null) {
|
||||
this.program.setMethod(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasProgram() {
|
||||
return program != null || programSupplier != null;
|
||||
}
|
||||
|
||||
public void setProgramSupplier(Function<MethodHolder, Program> programSupplier) {
|
||||
if (this.program != null) {
|
||||
this.program.setMethod(null);
|
||||
}
|
||||
this.program = null;
|
||||
this.programSupplier = programSupplier;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
|||
public class Program implements ProgramReader {
|
||||
private List<BasicBlock> basicBlocks = new ArrayList<>(2);
|
||||
private List<Variable> variables = new ArrayList<>();
|
||||
private MethodHolder method;
|
||||
private boolean packed;
|
||||
private int lastUsedRegister;
|
||||
|
||||
|
@ -150,17 +149,4 @@ public class Program implements ProgramReader {
|
|||
}
|
||||
return variables.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodReference getMethodReference() {
|
||||
return method != null ? method.getReference() : null;
|
||||
}
|
||||
|
||||
MethodHolder getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
void setMethod(MethodHolder method) {
|
||||
this.method = method;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,4 @@ public interface ProgramReader {
|
|||
int variableCount();
|
||||
|
||||
VariableReader variableAt(int index);
|
||||
|
||||
MethodReference getMethodReference();
|
||||
}
|
||||
|
|
|
@ -21,10 +21,6 @@ import static org.junit.Assert.assertThat;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Instruction;
|
||||
|
@ -171,25 +167,4 @@ public class ProgramIOTest {
|
|||
throw new AssertionError("This exception should not be thrown", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class InMemorySymbolTable implements SymbolTable {
|
||||
private List<String> symbols = new ArrayList<>();
|
||||
private Map<String, Integer> indexes = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public String at(int index) {
|
||||
return symbols.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lookup(String symbol) {
|
||||
Integer index = indexes.get(symbol);
|
||||
if (index == null) {
|
||||
index = symbols.size();
|
||||
symbols.add(symbol);
|
||||
indexes.put(symbol, index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user