mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -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())) {
|
|| methodInjectors.containsKey(method.getReference())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!method.hasModifier(ElementModifier.NATIVE) && method.getProgram() == null) {
|
if (!method.hasModifier(ElementModifier.NATIVE) && !method.hasProgram()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.cache;
|
package org.teavm.cache;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -26,6 +29,9 @@ import org.teavm.model.ProgramCache;
|
||||||
public class InMemoryProgramCache implements ProgramCache {
|
public class InMemoryProgramCache implements ProgramCache {
|
||||||
private Map<MethodReference, Item> cache = new HashMap<>();
|
private Map<MethodReference, Item> cache = new HashMap<>();
|
||||||
private Map<MethodReference, Item> newItems = 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
|
@Override
|
||||||
public Program get(MethodReference method, CacheStatus cacheStatus) {
|
public Program get(MethodReference method, CacheStatus cacheStatus) {
|
||||||
|
@ -37,13 +43,23 @@ public class InMemoryProgramCache implements ProgramCache {
|
||||||
if (Arrays.stream(item.dependencies).anyMatch(cacheStatus::isStaleClass)) {
|
if (Arrays.stream(item.dependencies).anyMatch(cacheStatus::isStaleClass)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
return item.program;
|
ByteArrayInputStream input = new ByteArrayInputStream(item.program);
|
||||||
|
return io.read(input);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void store(MethodReference method, Program program, Supplier<String[]> dependencies) {
|
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() {
|
public void commit() {
|
||||||
|
@ -62,13 +78,15 @@ public class InMemoryProgramCache implements ProgramCache {
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
cache.clear();
|
cache.clear();
|
||||||
newItems.clear();
|
newItems.clear();
|
||||||
|
symbolTable.invalidate();
|
||||||
|
fileSymbolTable.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class Item {
|
static final class Item {
|
||||||
final Program program;
|
final byte[] program;
|
||||||
final String[] dependencies;
|
final String[] dependencies;
|
||||||
|
|
||||||
Item(Program program, String[] dependencies) {
|
Item(byte[] program, String[] dependencies) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.dependencies = dependencies;
|
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() {
|
public Program getProgram() {
|
||||||
if (program == null && programSupplier != null) {
|
if (program == null && programSupplier != null) {
|
||||||
program = programSupplier.apply(this);
|
program = programSupplier.apply(this);
|
||||||
if (program != null) {
|
|
||||||
program.setMethod(this);
|
|
||||||
}
|
|
||||||
programSupplier = null;
|
programSupplier = null;
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgram(Program program) {
|
public void setProgram(Program program) {
|
||||||
if (this.program != null) {
|
|
||||||
this.program.setMethod(null);
|
|
||||||
}
|
|
||||||
this.program = program;
|
this.program = program;
|
||||||
this.programSupplier = null;
|
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) {
|
public void setProgramSupplier(Function<MethodHolder, Program> programSupplier) {
|
||||||
if (this.program != null) {
|
|
||||||
this.program.setMethod(null);
|
|
||||||
}
|
|
||||||
this.program = null;
|
this.program = null;
|
||||||
this.programSupplier = programSupplier;
|
this.programSupplier = programSupplier;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.List;
|
||||||
public class Program implements ProgramReader {
|
public class Program implements ProgramReader {
|
||||||
private List<BasicBlock> basicBlocks = new ArrayList<>(2);
|
private List<BasicBlock> basicBlocks = new ArrayList<>(2);
|
||||||
private List<Variable> variables = new ArrayList<>();
|
private List<Variable> variables = new ArrayList<>();
|
||||||
private MethodHolder method;
|
|
||||||
private boolean packed;
|
private boolean packed;
|
||||||
private int lastUsedRegister;
|
private int lastUsedRegister;
|
||||||
|
|
||||||
|
@ -150,17 +149,4 @@ public class Program implements ProgramReader {
|
||||||
}
|
}
|
||||||
return variables.get(index);
|
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();
|
int variableCount();
|
||||||
|
|
||||||
VariableReader variableAt(int index);
|
VariableReader variableAt(int index);
|
||||||
|
|
||||||
MethodReference getMethodReference();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,6 @@ import static org.junit.Assert.assertThat;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
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.junit.Test;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
|
@ -171,25 +167,4 @@ public class ProgramIOTest {
|
||||||
throw new AssertionError("This exception should not be thrown", e);
|
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