mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Decrease memory consumption
This commit is contained in:
parent
94322e5f6e
commit
a8226ef6a3
|
@ -354,7 +354,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
renderingContext.setMinifying(minifying);
|
renderingContext.setMinifying(minifying);
|
||||||
Renderer renderer = new Renderer(sourceWriter, asyncMethods, asyncFamilyMethods,
|
Renderer renderer = new Renderer(sourceWriter, asyncMethods, asyncFamilyMethods,
|
||||||
controller.getDiagnostics(), renderingContext);
|
controller.getDiagnostics(), renderingContext);
|
||||||
RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, sourceWriter);
|
RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, sourceWriter);
|
||||||
renderer.setProperties(controller.getProperties());
|
renderer.setProperties(controller.getProperties());
|
||||||
renderer.setMinifying(minifying);
|
renderer.setMinifying(minifying);
|
||||||
renderer.setProgressConsumer(controller::reportProgress);
|
renderer.setProgressConsumer(controller::reportProgress);
|
||||||
|
|
40
core/src/main/java/org/teavm/cache/CachedAnnotation.java
vendored
Normal file
40
core/src/main/java/org/teavm/cache/CachedAnnotation.java
vendored
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* 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.Map;
|
||||||
|
import org.teavm.model.AnnotationReader;
|
||||||
|
import org.teavm.model.AnnotationValue;
|
||||||
|
|
||||||
|
class CachedAnnotation implements AnnotationReader {
|
||||||
|
String type;
|
||||||
|
Map<String, AnnotationValue> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationValue getValue(String fieldName) {
|
||||||
|
return fields.get(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<String> getAvailableFields() {
|
||||||
|
return fields.keySet();
|
||||||
|
}
|
||||||
|
}
|
38
core/src/main/java/org/teavm/cache/CachedAnnotations.java
vendored
Normal file
38
core/src/main/java/org/teavm/cache/CachedAnnotations.java
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.Map;
|
||||||
|
import org.teavm.model.AnnotationContainerReader;
|
||||||
|
import org.teavm.model.AnnotationReader;
|
||||||
|
|
||||||
|
class CachedAnnotations implements AnnotationContainerReader {
|
||||||
|
private Map<String, CachedAnnotation> data;
|
||||||
|
|
||||||
|
public CachedAnnotations(Map<String, CachedAnnotation> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationReader get(String type) {
|
||||||
|
return data.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends AnnotationReader> all() {
|
||||||
|
return data.values();
|
||||||
|
}
|
||||||
|
}
|
67
core/src/main/java/org/teavm/cache/CachedClassReader.java
vendored
Normal file
67
core/src/main/java/org/teavm/cache/CachedClassReader.java
vendored
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.FieldReader;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
|
|
||||||
|
class CachedClassReader extends CachedElement implements ClassReader {
|
||||||
|
String parent;
|
||||||
|
String owner;
|
||||||
|
Set<String> interfaces;
|
||||||
|
Map<MethodDescriptor, CachedMethod> methods;
|
||||||
|
Map<String, CachedField> fields;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getInterfaces() {
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodReader getMethod(MethodDescriptor method) {
|
||||||
|
return methods.get(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends MethodReader> getMethods() {
|
||||||
|
return methods.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldReader getField(String name) {
|
||||||
|
return fields.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends FieldReader> getFields() {
|
||||||
|
return fields.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnerName() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
}
|
54
core/src/main/java/org/teavm/cache/CachedElement.java
vendored
Normal file
54
core/src/main/java/org/teavm/cache/CachedElement.java
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.EnumSet;
|
||||||
|
import org.teavm.model.AccessLevel;
|
||||||
|
import org.teavm.model.AnnotationContainerReader;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
|
import org.teavm.model.ElementReader;
|
||||||
|
|
||||||
|
class CachedElement implements ElementReader {
|
||||||
|
EnumSet<ElementModifier> modifiers;
|
||||||
|
CachedAnnotations annotations;
|
||||||
|
AccessLevel level;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AccessLevel getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnumSet<ElementModifier> readModifiers() {
|
||||||
|
return modifiers.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasModifier(ElementModifier modifier) {
|
||||||
|
return modifiers.contains(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationContainerReader getAnnotations() {
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
}
|
41
core/src/main/java/org/teavm/cache/CachedField.java
vendored
Normal file
41
core/src/main/java/org/teavm/cache/CachedField.java
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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 org.teavm.model.FieldReader;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
class CachedField extends CachedMember implements FieldReader {
|
||||||
|
ValueType type;
|
||||||
|
Object initialValue;
|
||||||
|
FieldReference reference;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getInitialValue() {
|
||||||
|
return initialValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FieldReference getReference() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
}
|
27
core/src/main/java/org/teavm/cache/CachedMember.java
vendored
Normal file
27
core/src/main/java/org/teavm/cache/CachedMember.java
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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 org.teavm.model.MemberReader;
|
||||||
|
|
||||||
|
class CachedMember extends CachedElement implements MemberReader {
|
||||||
|
String ownerName;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOwnerName() {
|
||||||
|
return ownerName;
|
||||||
|
}
|
||||||
|
}
|
97
core/src/main/java/org/teavm/cache/CachedMethod.java
vendored
Normal file
97
core/src/main/java/org/teavm/cache/CachedMethod.java
vendored
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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.lang.ref.WeakReference;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import org.teavm.model.AnnotationContainerReader;
|
||||||
|
import org.teavm.model.AnnotationValue;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ProgramReader;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
|
class CachedMethod extends CachedMember implements MethodReader {
|
||||||
|
MethodReference reference;
|
||||||
|
CachedAnnotations[] parameterAnnotations;
|
||||||
|
AnnotationValue annotationDefault;
|
||||||
|
WeakReference<ProgramReader> program;
|
||||||
|
Supplier<ProgramReader> programSupplier;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType getResultType() {
|
||||||
|
return reference.getReturnType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int parameterCount() {
|
||||||
|
return reference.parameterCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType[] getSignature() {
|
||||||
|
return reference.getSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType parameterType(int index) {
|
||||||
|
return reference.parameterType(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValueType[] getParameterTypes() {
|
||||||
|
return reference.getParameterTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationContainerReader parameterAnnotation(int index) {
|
||||||
|
return parameterAnnotations[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationContainerReader[] getParameterAnnotations() {
|
||||||
|
return parameterAnnotations.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodDescriptor getDescriptor() {
|
||||||
|
return reference.getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodReference getReference() {
|
||||||
|
return reference;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProgramReader getProgram() {
|
||||||
|
if (programSupplier == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ProgramReader program = this.program != null ? this.program.get() : null;
|
||||||
|
if (program == null) {
|
||||||
|
program = programSupplier.get();
|
||||||
|
this.program = new WeakReference<>(program);
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnotationValue getAnnotationDefault() {
|
||||||
|
return annotationDefault;
|
||||||
|
}
|
||||||
|
}
|
160
core/src/main/java/org/teavm/cache/ClassIO.java
vendored
160
core/src/main/java/org/teavm/cache/ClassIO.java
vendored
|
@ -15,43 +15,51 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.cache;
|
package org.teavm.cache;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.model.AccessLevel;
|
import org.teavm.model.AccessLevel;
|
||||||
import org.teavm.model.AnnotationContainer;
|
import org.teavm.model.AnnotationContainerReader;
|
||||||
import org.teavm.model.AnnotationHolder;
|
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
import org.teavm.model.AnnotationValue;
|
import org.teavm.model.AnnotationValue;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldHolder;
|
import org.teavm.model.FieldReader;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.ReferenceCache;
|
import org.teavm.model.ReferenceCache;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class ClassIO {
|
public class ClassIO {
|
||||||
private static AccessLevel[] accessLevels = AccessLevel.values();
|
private static AccessLevel[] accessLevels = AccessLevel.values();
|
||||||
private static ElementModifier[] elementModifiers = ElementModifier.values();
|
private static ElementModifier[] elementModifiers = ElementModifier.values();
|
||||||
|
private ReferenceCache referenceCache;
|
||||||
private SymbolTable symbolTable;
|
private SymbolTable symbolTable;
|
||||||
private ProgramIO programIO;
|
private ProgramIO programIO;
|
||||||
|
|
||||||
public ClassIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable,
|
public ClassIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable,
|
||||||
SymbolTable varTable) {
|
SymbolTable varTable) {
|
||||||
|
this.referenceCache = referenceCache;
|
||||||
this.symbolTable = symbolTable;
|
this.symbolTable = symbolTable;
|
||||||
programIO = new ProgramIO(referenceCache, symbolTable, fileTable, varTable);
|
programIO = new ProgramIO(referenceCache, symbolTable, fileTable, varTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeClass(OutputStream stream, ClassHolder cls) throws IOException {
|
public void writeClass(OutputStream stream, ClassReader cls) throws IOException {
|
||||||
VarDataOutput output = new VarDataOutput(stream);
|
VarDataOutput output = new VarDataOutput(stream);
|
||||||
output.writeUnsigned(cls.getLevel().ordinal());
|
output.writeUnsigned(cls.getLevel().ordinal());
|
||||||
output.writeUnsigned(packModifiers(cls.getModifiers()));
|
output.writeUnsigned(packModifiers(cls.readModifiers()));
|
||||||
output.writeUnsigned(cls.getParent() != null ? symbolTable.lookup(cls.getParent()) + 1 : 0);
|
output.writeUnsigned(cls.getParent() != null ? symbolTable.lookup(cls.getParent()) + 1 : 0);
|
||||||
output.writeUnsigned(cls.getOwnerName() != null ? symbolTable.lookup(cls.getOwnerName()) + 1 : 0);
|
output.writeUnsigned(cls.getOwnerName() != null ? symbolTable.lookup(cls.getOwnerName()) + 1 : 0);
|
||||||
output.writeUnsigned(cls.getInterfaces().size());
|
output.writeUnsigned(cls.getInterfaces().size());
|
||||||
|
@ -60,56 +68,71 @@ public class ClassIO {
|
||||||
}
|
}
|
||||||
writeAnnotations(output, cls.getAnnotations());
|
writeAnnotations(output, cls.getAnnotations());
|
||||||
output.writeUnsigned(cls.getFields().size());
|
output.writeUnsigned(cls.getFields().size());
|
||||||
for (FieldHolder field : cls.getFields()) {
|
for (FieldReader field : cls.getFields()) {
|
||||||
writeField(output, field);
|
writeField(output, field);
|
||||||
}
|
}
|
||||||
output.writeUnsigned(cls.getMethods().size());
|
output.writeUnsigned(cls.getMethods().size());
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodReader method : cls.getMethods()) {
|
||||||
writeMethod(output, method);
|
writeMethod(output, method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassHolder readClass(InputStream stream, String name) throws IOException {
|
public ClassReader readClass(InputStream stream, String name) throws IOException {
|
||||||
VarDataInput input = new VarDataInput(stream);
|
VarDataInput input = new VarDataInput(stream);
|
||||||
ClassHolder cls = new ClassHolder(name);
|
CachedClassReader cls = new CachedClassReader();
|
||||||
cls.setLevel(accessLevels[input.readUnsigned()]);
|
cls.name = name;
|
||||||
cls.getModifiers().addAll(unpackModifiers(input.readUnsigned()));
|
cls.level = accessLevels[input.readUnsigned()];
|
||||||
|
cls.modifiers = unpackModifiers(input.readUnsigned());
|
||||||
int parentIndex = input.readUnsigned();
|
int parentIndex = input.readUnsigned();
|
||||||
cls.setParent(parentIndex > 0 ? symbolTable.at(parentIndex - 1) : null);
|
cls.parent = parentIndex > 0 ? referenceCache.getCached(symbolTable.at(parentIndex - 1)) : null;
|
||||||
int ownerIndex = input.readUnsigned();
|
int ownerIndex = input.readUnsigned();
|
||||||
cls.setOwnerName(ownerIndex > 0 ? symbolTable.at(ownerIndex - 1) : null);
|
cls.owner = ownerIndex > 0 ? referenceCache.getCached(symbolTable.at(ownerIndex - 1)) : null;
|
||||||
int ifaceCount = input.readUnsigned();
|
int ifaceCount = input.readUnsigned();
|
||||||
|
Set<String> interfaces = new LinkedHashSet<>();
|
||||||
for (int i = 0; i < ifaceCount; ++i) {
|
for (int i = 0; i < ifaceCount; ++i) {
|
||||||
cls.getInterfaces().add(symbolTable.at(input.readUnsigned()));
|
interfaces.add(referenceCache.getCached(symbolTable.at(input.readUnsigned())));
|
||||||
}
|
}
|
||||||
readAnnotations(input, cls.getAnnotations());
|
cls.interfaces = Collections.unmodifiableSet(interfaces);
|
||||||
|
cls.annotations = readAnnotations(input);
|
||||||
|
|
||||||
|
Map<String, CachedField> fields = new LinkedHashMap<>();
|
||||||
int fieldCount = input.readUnsigned();
|
int fieldCount = input.readUnsigned();
|
||||||
for (int i = 0; i < fieldCount; ++i) {
|
for (int i = 0; i < fieldCount; ++i) {
|
||||||
cls.addField(readField(input));
|
CachedField field = readField(name, input);
|
||||||
|
fields.put(field.name, field);
|
||||||
}
|
}
|
||||||
|
cls.fields = fields;
|
||||||
|
|
||||||
|
Map<MethodDescriptor, CachedMethod> methods = new LinkedHashMap<>();
|
||||||
int methodCount = input.readUnsigned();
|
int methodCount = input.readUnsigned();
|
||||||
for (int i = 0; i < methodCount; ++i) {
|
for (int i = 0; i < methodCount; ++i) {
|
||||||
cls.addMethod(readMethod(input));
|
CachedMethod method = readMethod(cls.name, input);
|
||||||
|
methods.put(method.reference.getDescriptor(), method);
|
||||||
}
|
}
|
||||||
|
cls.methods = methods;
|
||||||
|
|
||||||
return cls;
|
return cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeField(VarDataOutput output, FieldHolder field) throws IOException {
|
private void writeField(VarDataOutput output, FieldReader field) throws IOException {
|
||||||
output.writeUnsigned(symbolTable.lookup(field.getName()));
|
output.writeUnsigned(symbolTable.lookup(field.getName()));
|
||||||
output.writeUnsigned(symbolTable.lookup(field.getType().toString()));
|
output.writeUnsigned(symbolTable.lookup(field.getType().toString()));
|
||||||
output.writeUnsigned(field.getLevel().ordinal());
|
output.writeUnsigned(field.getLevel().ordinal());
|
||||||
output.writeUnsigned(packModifiers(field.getModifiers()));
|
output.writeUnsigned(packModifiers(field.readModifiers()));
|
||||||
writeFieldValue(output, field.getInitialValue());
|
writeFieldValue(output, field.getInitialValue());
|
||||||
writeAnnotations(output, field.getAnnotations());
|
writeAnnotations(output, field.getAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldHolder readField(VarDataInput input) throws IOException {
|
private CachedField readField(String className, VarDataInput input) throws IOException {
|
||||||
FieldHolder field = new FieldHolder(symbolTable.at(input.readUnsigned()));
|
CachedField field = new CachedField();
|
||||||
field.setType(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
field.name = referenceCache.getCached(symbolTable.at(input.readUnsigned()));
|
||||||
field.setLevel(accessLevels[input.readUnsigned()]);
|
field.type = referenceCache.getCached(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
||||||
field.getModifiers().addAll(unpackModifiers(input.readUnsigned()));
|
field.level = accessLevels[input.readUnsigned()];
|
||||||
field.setInitialValue(readFieldValue(input));
|
field.modifiers = unpackModifiers(input.readUnsigned());
|
||||||
readAnnotations(input, field.getAnnotations());
|
field.initialValue = readFieldValue(input);
|
||||||
|
field.annotations = readAnnotations(input);
|
||||||
|
field.ownerName = className;
|
||||||
|
field.reference = referenceCache.getCached(new FieldReference(className, field.name));
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,13 +177,13 @@ public class ClassIO {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeMethod(VarDataOutput output, MethodHolder method) throws IOException {
|
private void writeMethod(VarDataOutput output, MethodReader method) throws IOException {
|
||||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||||
output.writeUnsigned(method.getLevel().ordinal());
|
output.writeUnsigned(method.getLevel().ordinal());
|
||||||
output.writeUnsigned(packModifiers(method.getModifiers()));
|
output.writeUnsigned(packModifiers(method.readModifiers()));
|
||||||
writeAnnotations(output, method.getAnnotations());
|
writeAnnotations(output, method.getAnnotations());
|
||||||
|
|
||||||
for (AnnotationContainer parameterAnnotation : method.getParameterAnnotations()) {
|
for (AnnotationContainerReader parameterAnnotation : method.getParameterAnnotations()) {
|
||||||
writeAnnotations(output, parameterAnnotation);
|
writeAnnotations(output, parameterAnnotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,49 +196,68 @@ public class ClassIO {
|
||||||
|
|
||||||
if (method.getProgram() != null) {
|
if (method.getProgram() != null) {
|
||||||
output.writeUnsigned(1);
|
output.writeUnsigned(1);
|
||||||
programIO.write(method.getProgram(), output);
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
VarDataOutput programOutput = new VarDataOutput(buffer);
|
||||||
|
programIO.write(method.getProgram(), programOutput);
|
||||||
|
output.writeBytes(buffer.toByteArray());
|
||||||
} else {
|
} else {
|
||||||
output.writeUnsigned(0);
|
output.writeUnsigned(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodHolder readMethod(VarDataInput input) throws IOException {
|
private CachedMethod readMethod(String className, VarDataInput input) throws IOException {
|
||||||
MethodHolder method = new MethodHolder(MethodDescriptor.parse(symbolTable.at(input.readUnsigned())));
|
CachedMethod method = new CachedMethod();
|
||||||
method.setLevel(accessLevels[input.readUnsigned()]);
|
MethodDescriptor descriptor = referenceCache.getCached(
|
||||||
method.getModifiers().addAll(unpackModifiers(input.readUnsigned()));
|
MethodDescriptor.parse(symbolTable.at(input.readUnsigned())));
|
||||||
readAnnotations(input, method.getAnnotations());
|
method.reference = referenceCache.getCached(className, descriptor);
|
||||||
|
method.level = accessLevels[input.readUnsigned()];
|
||||||
|
method.modifiers = unpackModifiers(input.readUnsigned());
|
||||||
|
method.annotations = readAnnotations(input);
|
||||||
|
method.ownerName = className;
|
||||||
|
method.name = descriptor.getName();
|
||||||
|
|
||||||
|
method.parameterAnnotations = new CachedAnnotations[descriptor.parameterCount()];
|
||||||
for (int i = 0; i < method.parameterCount(); ++i) {
|
for (int i = 0; i < method.parameterCount(); ++i) {
|
||||||
readAnnotations(input, method.parameterAnnotation(i));
|
method.parameterAnnotations[i] = readAnnotations(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.readUnsigned() != 0) {
|
if (input.readUnsigned() != 0) {
|
||||||
method.setAnnotationDefault(readAnnotationValue(input));
|
method.annotationDefault = readAnnotationValue(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.readUnsigned() != 0) {
|
if (input.readUnsigned() != 0) {
|
||||||
method.setProgram(programIO.read(input));
|
byte[] programData = input.readBytes();
|
||||||
|
method.programSupplier = () -> {
|
||||||
|
VarDataInput programInput = new VarDataInput(new ByteArrayInputStream(programData));
|
||||||
|
try {
|
||||||
|
return programIO.read(programInput);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAnnotations(VarDataOutput output, AnnotationContainer annotations) throws IOException {
|
private void writeAnnotations(VarDataOutput output, AnnotationContainerReader annotations) throws IOException {
|
||||||
List<AnnotationHolder> annotationList = new ArrayList<>();
|
List<AnnotationReader> annotationList = new ArrayList<>();
|
||||||
for (AnnotationHolder annot : annotations.all()) {
|
for (AnnotationReader annot : annotations.all()) {
|
||||||
annotationList.add(annot);
|
annotationList.add(annot);
|
||||||
}
|
}
|
||||||
output.writeUnsigned(annotationList.size());
|
output.writeUnsigned(annotationList.size());
|
||||||
for (AnnotationHolder annot : annotationList) {
|
for (AnnotationReader annot : annotationList) {
|
||||||
writeAnnotation(output, annot);
|
writeAnnotation(output, annot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readAnnotations(VarDataInput input, AnnotationContainer annotations) throws IOException {
|
private CachedAnnotations readAnnotations(VarDataInput input) throws IOException {
|
||||||
|
Map<String, CachedAnnotation> annotations = new HashMap<>();
|
||||||
int annotCount = input.readUnsigned();
|
int annotCount = input.readUnsigned();
|
||||||
for (int i = 0; i < annotCount; ++i) {
|
for (int i = 0; i < annotCount; ++i) {
|
||||||
AnnotationHolder annot = readAnnotation(input);
|
CachedAnnotation annot = readAnnotation(input);
|
||||||
annotations.add(annot);
|
annotations.put(annot.type, annot);
|
||||||
}
|
}
|
||||||
|
return new CachedAnnotations(annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAnnotation(VarDataOutput output, AnnotationReader annotation) throws IOException {
|
private void writeAnnotation(VarDataOutput output, AnnotationReader annotation) throws IOException {
|
||||||
|
@ -231,14 +273,17 @@ public class ClassIO {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AnnotationHolder readAnnotation(VarDataInput input) throws IOException {
|
private CachedAnnotation readAnnotation(VarDataInput input) throws IOException {
|
||||||
AnnotationHolder annotation = new AnnotationHolder(symbolTable.at(input.readUnsigned()));
|
CachedAnnotation annotation = new CachedAnnotation();
|
||||||
|
annotation.type = referenceCache.getCached(symbolTable.at(input.readUnsigned()));
|
||||||
int valueCount = input.readUnsigned();
|
int valueCount = input.readUnsigned();
|
||||||
|
Map<String, AnnotationValue> fields = new HashMap<>();
|
||||||
for (int i = 0; i < valueCount; ++i) {
|
for (int i = 0; i < valueCount; ++i) {
|
||||||
String name = symbolTable.at(input.readUnsigned());
|
String name = referenceCache.getCached(symbolTable.at(input.readUnsigned()));
|
||||||
AnnotationValue value = readAnnotationValue(input);
|
AnnotationValue value = readAnnotationValue(input);
|
||||||
annotation.getValues().put(name, value);
|
fields.put(name, value);
|
||||||
}
|
}
|
||||||
|
annotation.fields = fields;
|
||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,13 +345,14 @@ public class ClassIO {
|
||||||
case AnnotationValue.BYTE:
|
case AnnotationValue.BYTE:
|
||||||
return new AnnotationValue((byte) input.readSigned());
|
return new AnnotationValue((byte) input.readSigned());
|
||||||
case AnnotationValue.CLASS:
|
case AnnotationValue.CLASS:
|
||||||
return new AnnotationValue(ValueType.parse(symbolTable.at(input.readUnsigned())));
|
return new AnnotationValue(referenceCache.getCached(ValueType.parse(
|
||||||
|
symbolTable.at(input.readUnsigned()))));
|
||||||
case AnnotationValue.DOUBLE:
|
case AnnotationValue.DOUBLE:
|
||||||
return new AnnotationValue(input.readDouble());
|
return new AnnotationValue(input.readDouble());
|
||||||
case AnnotationValue.ENUM: {
|
case AnnotationValue.ENUM: {
|
||||||
String className = symbolTable.at(input.readUnsigned());
|
String className = referenceCache.getCached(symbolTable.at(input.readUnsigned()));
|
||||||
String fieldName = symbolTable.at(input.readUnsigned());
|
String fieldName = referenceCache.getCached(symbolTable.at(input.readUnsigned()));
|
||||||
return new AnnotationValue(new FieldReference(className, fieldName));
|
return new AnnotationValue(referenceCache.getCached(new FieldReference(className, fieldName)));
|
||||||
}
|
}
|
||||||
case AnnotationValue.FLOAT:
|
case AnnotationValue.FLOAT:
|
||||||
return new AnnotationValue(input.readFloat());
|
return new AnnotationValue(input.readFloat());
|
||||||
|
@ -339,8 +385,8 @@ public class ClassIO {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<ElementModifier> unpackModifiers(int packed) {
|
private EnumSet<ElementModifier> unpackModifiers(int packed) {
|
||||||
Set<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class);
|
EnumSet<ElementModifier> modifiers = EnumSet.noneOf(ElementModifier.class);
|
||||||
while (packed != 0) {
|
while (packed != 0) {
|
||||||
int n = Integer.numberOfTrailingZeros(packed);
|
int n = Integer.numberOfTrailingZeros(packed);
|
||||||
packed ^= 1 << n;
|
packed ^= 1 << n;
|
||||||
|
|
|
@ -28,13 +28,14 @@ import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.model.ClassHolder;
|
|
||||||
import org.teavm.model.ClassHolderSource;
|
import org.teavm.model.ClassHolderSource;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ReferenceCache;
|
import org.teavm.model.ReferenceCache;
|
||||||
import org.teavm.parsing.ClassDateProvider;
|
import org.teavm.parsing.ClassDateProvider;
|
||||||
|
|
||||||
public class DiskCachedClassHolderSource implements ClassHolderSource, CacheStatus {
|
public class DiskCachedClassReaderSource implements ClassReaderSource, CacheStatus {
|
||||||
private File directory;
|
private File directory;
|
||||||
private ClassHolderSource innerSource;
|
private ClassHolderSource innerSource;
|
||||||
private ClassDateProvider classDateProvider;
|
private ClassDateProvider classDateProvider;
|
||||||
|
@ -42,7 +43,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource, CacheStat
|
||||||
private Set<String> newClasses = new HashSet<>();
|
private Set<String> newClasses = new HashSet<>();
|
||||||
private ClassIO classIO;
|
private ClassIO classIO;
|
||||||
|
|
||||||
public DiskCachedClassHolderSource(File directory, ReferenceCache referenceCache, SymbolTable symbolTable,
|
public DiskCachedClassReaderSource(File directory, ReferenceCache referenceCache, SymbolTable symbolTable,
|
||||||
SymbolTable fileTable, SymbolTable variableTable, ClassHolderSource innerSource,
|
SymbolTable fileTable, SymbolTable variableTable, ClassHolderSource innerSource,
|
||||||
ClassDateProvider classDateProvider) {
|
ClassDateProvider classDateProvider) {
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
|
@ -52,7 +53,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource, CacheStat
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassHolder get(String name) {
|
public ClassReader get(String name) {
|
||||||
return getItemFromCache(name).cls;
|
return getItemFromCache(name).cls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ public class DiskCachedClassHolderSource implements ClassHolderSource, CacheStat
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Item {
|
private static class Item {
|
||||||
ClassHolder cls;
|
ClassReader cls;
|
||||||
boolean dirty;
|
boolean dirty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,12 @@ package org.teavm.cache;
|
||||||
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.lang.ref.WeakReference;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import org.teavm.model.ClassHolder;
|
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -33,7 +31,7 @@ import org.teavm.model.ReferenceCache;
|
||||||
|
|
||||||
public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheStatus {
|
public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheStatus {
|
||||||
private Map<String, Entry> cache = new HashMap<>();
|
private Map<String, Entry> cache = new HashMap<>();
|
||||||
private Function<String, ClassHolder> provider;
|
private Function<String, ClassReader> provider;
|
||||||
private ClassIO classIO;
|
private ClassIO classIO;
|
||||||
private final Set<String> freshClasses = new HashSet<>();
|
private final Set<String> freshClasses = new HashSet<>();
|
||||||
|
|
||||||
|
@ -42,7 +40,7 @@ public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheSt
|
||||||
classIO = new ClassIO(referenceCache, symbolTable, fileTable, varTable);
|
classIO = new ClassIO(referenceCache, symbolTable, fileTable, varTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProvider(Function<String, ClassHolder> provider) {
|
public void setProvider(Function<String, ClassReader> provider) {
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +54,33 @@ public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheSt
|
||||||
return isStaleClass(method.getClassName());
|
return isStaleClass(method.getClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void populate(String name) {
|
||||||
|
getEntry(name);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassReader get(String name) {
|
public ClassReader get(String name) {
|
||||||
Entry entry = cache.computeIfAbsent(name, className -> {
|
Entry entry = getEntry(name);
|
||||||
ClassHolder cls = provider.apply(name);
|
if (entry.data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassReader cls = entry.reader;
|
||||||
|
if (cls == null) {
|
||||||
|
ByteArrayInputStream input = new ByteArrayInputStream(entry.data);
|
||||||
|
try {
|
||||||
|
cls = classIO.readClass(input, name);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
entry.reader = cls;
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Entry getEntry(String name) {
|
||||||
|
return cache.computeIfAbsent(name, className -> {
|
||||||
|
ClassReader cls = provider.apply(className);
|
||||||
Entry en = new Entry();
|
Entry en = new Entry();
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
@ -69,26 +90,9 @@ public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheSt
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
en.data = output.toByteArray();
|
en.data = output.toByteArray();
|
||||||
en.reader = new WeakReference<>(cls);
|
|
||||||
}
|
}
|
||||||
return en;
|
return en;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (entry.data == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassReader cls = entry.reader.get();
|
|
||||||
if (cls == null) {
|
|
||||||
ByteArrayInputStream input = new ByteArrayInputStream(entry.data);
|
|
||||||
try {
|
|
||||||
cls = classIO.readClass(input, name);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
entry.reader = new WeakReference<>(cls);
|
|
||||||
}
|
|
||||||
return cls;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void commit() {
|
public void commit() {
|
||||||
|
@ -107,6 +111,6 @@ public class MemoryCachedClassReaderSource implements ClassReaderSource, CacheSt
|
||||||
|
|
||||||
class Entry {
|
class Entry {
|
||||||
byte[] data;
|
byte[] data;
|
||||||
WeakReference<ClassReader> reader;
|
ClassReader reader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
415
core/src/main/java/org/teavm/cache/ProgramIO.java
vendored
415
core/src/main/java/org/teavm/cache/ProgramIO.java
vendored
|
@ -18,23 +18,29 @@ package org.teavm.cache;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Objects;
|
import java.util.List;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
|
import org.teavm.model.BasicBlockReader;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
|
import org.teavm.model.IncomingReader;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.InvokeDynamicInstruction;
|
import org.teavm.model.InvokeDynamicInstruction;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodHandle;
|
import org.teavm.model.MethodHandle;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
|
import org.teavm.model.PhiReader;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
|
import org.teavm.model.ProgramReader;
|
||||||
import org.teavm.model.ReferenceCache;
|
import org.teavm.model.ReferenceCache;
|
||||||
import org.teavm.model.RuntimeConstant;
|
import org.teavm.model.RuntimeConstant;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.TryCatchBlock;
|
import org.teavm.model.TryCatchBlock;
|
||||||
|
import org.teavm.model.TryCatchBlockReader;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
|
import org.teavm.model.VariableReader;
|
||||||
import org.teavm.model.instructions.ArrayElementType;
|
import org.teavm.model.instructions.ArrayElementType;
|
||||||
import org.teavm.model.instructions.ArrayLengthInstruction;
|
import org.teavm.model.instructions.ArrayLengthInstruction;
|
||||||
import org.teavm.model.instructions.AssignInstruction;
|
import org.teavm.model.instructions.AssignInstruction;
|
||||||
|
@ -60,7 +66,7 @@ import org.teavm.model.instructions.FloatConstantInstruction;
|
||||||
import org.teavm.model.instructions.GetElementInstruction;
|
import org.teavm.model.instructions.GetElementInstruction;
|
||||||
import org.teavm.model.instructions.GetFieldInstruction;
|
import org.teavm.model.instructions.GetFieldInstruction;
|
||||||
import org.teavm.model.instructions.InitClassInstruction;
|
import org.teavm.model.instructions.InitClassInstruction;
|
||||||
import org.teavm.model.instructions.InstructionVisitor;
|
import org.teavm.model.instructions.InstructionReader;
|
||||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||||
import org.teavm.model.instructions.IntegerSubtype;
|
import org.teavm.model.instructions.IntegerSubtype;
|
||||||
import org.teavm.model.instructions.InvocationType;
|
import org.teavm.model.instructions.InvocationType;
|
||||||
|
@ -80,6 +86,7 @@ import org.teavm.model.instructions.RaiseInstruction;
|
||||||
import org.teavm.model.instructions.StringConstantInstruction;
|
import org.teavm.model.instructions.StringConstantInstruction;
|
||||||
import org.teavm.model.instructions.SwitchInstruction;
|
import org.teavm.model.instructions.SwitchInstruction;
|
||||||
import org.teavm.model.instructions.SwitchTableEntry;
|
import org.teavm.model.instructions.SwitchTableEntry;
|
||||||
|
import org.teavm.model.instructions.SwitchTableEntryReader;
|
||||||
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||||
|
|
||||||
public class ProgramIO {
|
public class ProgramIO {
|
||||||
|
@ -103,62 +110,42 @@ public class ProgramIO {
|
||||||
this.variableTable = variableTable;
|
this.variableTable = variableTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(Program program, OutputStream output) throws IOException {
|
public void write(ProgramReader program, OutputStream output) throws IOException {
|
||||||
write(program, new VarDataOutput(output));
|
write(program, new VarDataOutput(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(Program program, VarDataOutput data) throws IOException {
|
public void write(ProgramReader program, VarDataOutput data) throws IOException {
|
||||||
data.writeUnsigned(program.variableCount());
|
data.writeUnsigned(program.variableCount());
|
||||||
data.writeUnsigned(program.basicBlockCount());
|
data.writeUnsigned(program.basicBlockCount());
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
Variable var = program.variableAt(i);
|
VariableReader var = program.variableAt(i);
|
||||||
data.writeUnsigned(var.getRegister());
|
data.writeUnsigned(var.getRegister());
|
||||||
data.writeUnsigned(var.getDebugName() != null ? variableTable.lookup(var.getDebugName()) + 1 : 0);
|
data.writeUnsigned(var.getDebugName() != null ? variableTable.lookup(var.getDebugName()) + 1 : 0);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock basicBlock = program.basicBlockAt(i);
|
BasicBlockReader basicBlock = program.basicBlockAt(i);
|
||||||
data.writeUnsigned(basicBlock.getExceptionVariable() != null
|
data.writeUnsigned(basicBlock.getExceptionVariable() != null
|
||||||
? basicBlock.getExceptionVariable().getIndex() + 1 : 0);
|
? basicBlock.getExceptionVariable().getIndex() + 1 : 0);
|
||||||
data.writeUnsigned(basicBlock.getPhis().size());
|
data.writeUnsigned(basicBlock.readPhis().size());
|
||||||
data.writeUnsigned(basicBlock.getTryCatchBlocks().size());
|
data.writeUnsigned(basicBlock.readTryCatchBlocks().size());
|
||||||
for (Phi phi : basicBlock.getPhis()) {
|
for (PhiReader phi : basicBlock.readPhis()) {
|
||||||
data.writeUnsigned(phi.getReceiver().getIndex());
|
data.writeUnsigned(phi.getReceiver().getIndex());
|
||||||
data.writeUnsigned(phi.getIncomings().size());
|
data.writeUnsigned(phi.readIncomings().size());
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
for (IncomingReader incoming : phi.readIncomings()) {
|
||||||
data.writeUnsigned(incoming.getSource().getIndex());
|
data.writeUnsigned(incoming.getSource().getIndex());
|
||||||
data.writeUnsigned(incoming.getValue().getIndex());
|
data.writeUnsigned(incoming.getValue().getIndex());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (TryCatchBlock tryCatch : basicBlock.getTryCatchBlocks()) {
|
for (TryCatchBlockReader tryCatch : basicBlock.readTryCatchBlocks()) {
|
||||||
data.writeUnsigned(tryCatch.getExceptionType() != null ? symbolTable.lookup(
|
data.writeUnsigned(tryCatch.getExceptionType() != null ? symbolTable.lookup(
|
||||||
tryCatch.getExceptionType()) + 1 : 0);
|
tryCatch.getExceptionType()) + 1 : 0);
|
||||||
data.writeUnsigned(tryCatch.getHandler().getIndex());
|
data.writeUnsigned(tryCatch.getHandler().getIndex());
|
||||||
}
|
}
|
||||||
TextLocation location = null;
|
|
||||||
InstructionWriter insnWriter = new InstructionWriter(data);
|
InstructionWriter insnWriter = new InstructionWriter(data);
|
||||||
for (Instruction insn : basicBlock) {
|
try {
|
||||||
try {
|
basicBlock.readAllInstructions(insnWriter);
|
||||||
if (!Objects.equals(location, insn.getLocation())) {
|
} catch (IOExceptionWrapper e) {
|
||||||
TextLocation newLocation = insn.getLocation();
|
throw (IOException) e.getCause();
|
||||||
if (newLocation == null || newLocation.getFileName() == null || newLocation.getLine() < 0) {
|
|
||||||
data.writeUnsigned(1);
|
|
||||||
location = null;
|
|
||||||
} else {
|
|
||||||
if (location != null && location.getFileName().equals(newLocation.getFileName())) {
|
|
||||||
data.writeUnsigned(127);
|
|
||||||
data.writeSigned(newLocation.getLine() - location.getLine());
|
|
||||||
} else {
|
|
||||||
data.writeUnsigned(2);
|
|
||||||
data.writeUnsigned(fileTable.lookup(newLocation.getFileName()));
|
|
||||||
data.writeUnsigned(newLocation.getLine());
|
|
||||||
}
|
|
||||||
location = newLocation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insn.acceptVisitor(insnWriter);
|
|
||||||
} catch (IOExceptionWrapper e) {
|
|
||||||
throw (IOException) e.getCause();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
data.writeUnsigned(0);
|
data.writeUnsigned(0);
|
||||||
}
|
}
|
||||||
|
@ -246,15 +233,38 @@ public class ProgramIO {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InstructionWriter implements InstructionVisitor {
|
private class InstructionWriter implements InstructionReader {
|
||||||
private VarDataOutput output;
|
private VarDataOutput output;
|
||||||
|
TextLocation location;
|
||||||
|
|
||||||
InstructionWriter(VarDataOutput output) {
|
InstructionWriter(VarDataOutput output) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(EmptyInstruction insn) {
|
public void location(TextLocation newLocation) {
|
||||||
|
try {
|
||||||
|
if (newLocation == null || newLocation.getFileName() == null || newLocation.getLine() < 0) {
|
||||||
|
output.writeUnsigned(1);
|
||||||
|
location = null;
|
||||||
|
} else {
|
||||||
|
if (location != null && location.getFileName().equals(newLocation.getFileName())) {
|
||||||
|
output.writeUnsigned(127);
|
||||||
|
output.writeSigned(newLocation.getLine() - location.getLine());
|
||||||
|
} else {
|
||||||
|
output.writeUnsigned(2);
|
||||||
|
output.writeUnsigned(fileTable.lookup(newLocation.getFileName()));
|
||||||
|
output.writeUnsigned(newLocation.getLine());
|
||||||
|
}
|
||||||
|
location = newLocation;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IOExceptionWrapper(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nop() {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(3);
|
output.writeUnsigned(3);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -263,196 +273,202 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void classConstant(VariableReader receiver, ValueType cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(4);
|
output.writeUnsigned(4);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getConstant().toString()));
|
output.writeUnsigned(symbolTable.lookup(cst.toString()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void nullConstant(VariableReader receiver) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(5);
|
output.writeUnsigned(5);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void integerConstant(VariableReader receiver, int cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(6);
|
output.writeUnsigned(6);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeSigned(insn.getConstant());
|
output.writeSigned(cst);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void longConstant(VariableReader receiver, long cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(7);
|
output.writeUnsigned(7);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeSigned(insn.getConstant());
|
output.writeSigned(cst);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void floatConstant(VariableReader receiver, float cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(8);
|
output.writeUnsigned(8);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeFloat(insn.getConstant());
|
output.writeFloat(cst);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void doubleConstant(VariableReader receiver, double cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(9);
|
output.writeUnsigned(9);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeDouble(insn.getConstant());
|
output.writeDouble(cst);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StringConstantInstruction insn) {
|
public void stringConstant(VariableReader receiver, String cst) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(10);
|
output.writeUnsigned(10);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.write(insn.getConstant());
|
output.write(cst);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryInstruction insn) {
|
public void binary(BinaryOperation op, VariableReader receiver, VariableReader first, VariableReader second,
|
||||||
|
NumericOperandType type) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(11 + insn.getOperation().ordinal());
|
output.writeUnsigned(11 + op.ordinal());
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getOperandType().ordinal());
|
output.writeUnsigned(type.ordinal());
|
||||||
output.writeUnsigned(insn.getFirstOperand().getIndex());
|
output.writeUnsigned(first.getIndex());
|
||||||
output.writeUnsigned(insn.getSecondOperand().getIndex());
|
output.writeUnsigned(second.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NegateInstruction insn) {
|
public void negate(VariableReader receiver, VariableReader operand, NumericOperandType type) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(23);
|
output.writeUnsigned(23);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getOperandType().ordinal());
|
output.writeUnsigned(type.ordinal());
|
||||||
output.writeUnsigned(insn.getOperand().getIndex());
|
output.writeUnsigned(operand.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignInstruction insn) {
|
public void assign(VariableReader receiver, VariableReader assignee) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(24);
|
output.writeUnsigned(24);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getAssignee().getIndex());
|
output.writeUnsigned(assignee.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(25);
|
output.writeUnsigned(25);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getTargetType().toString()));
|
output.writeUnsigned(symbolTable.lookup(targetType.toString()));
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastNumberInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, NumericOperandType sourceType,
|
||||||
|
NumericOperandType targetType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(26);
|
output.writeUnsigned(26);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getSourceType().ordinal() | (insn.getTargetType().ordinal() << 2));
|
output.writeUnsigned(sourceType.ordinal() | (targetType.ordinal() << 2));
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastIntegerInstruction insn) {
|
public void cast(VariableReader receiver, VariableReader value, IntegerSubtype type,
|
||||||
|
CastIntegerDirection direction) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(27);
|
output.writeUnsigned(27);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getDirection().ordinal() | (insn.getTargetType().ordinal() << 1));
|
output.writeUnsigned(direction.ordinal() | (type.ordinal() << 1));
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BranchingInstruction insn) {
|
public void jumpIf(BranchingCondition cond, VariableReader operand, BasicBlockReader consequent,
|
||||||
|
BasicBlockReader alternative) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(28 + insn.getCondition().ordinal());
|
output.writeUnsigned(28 + cond.ordinal());
|
||||||
output.writeUnsigned(insn.getOperand().getIndex());
|
output.writeUnsigned(operand.getIndex());
|
||||||
output.writeUnsigned(insn.getConsequent().getIndex());
|
output.writeUnsigned(consequent.getIndex());
|
||||||
output.writeUnsigned(insn.getAlternative().getIndex());
|
output.writeUnsigned(alternative.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryBranchingInstruction insn) {
|
public void jumpIf(BinaryBranchingCondition cond, VariableReader first, VariableReader second,
|
||||||
|
BasicBlockReader consequent, BasicBlockReader alternative) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(36 + insn.getCondition().ordinal());
|
output.writeUnsigned(36 + cond.ordinal());
|
||||||
output.writeUnsigned(insn.getFirstOperand().getIndex());
|
output.writeUnsigned(first.getIndex());
|
||||||
output.writeUnsigned(insn.getSecondOperand().getIndex());
|
output.writeUnsigned(second.getIndex());
|
||||||
output.writeUnsigned(insn.getConsequent().getIndex());
|
output.writeUnsigned(consequent.getIndex());
|
||||||
output.writeUnsigned(insn.getAlternative().getIndex());
|
output.writeUnsigned(alternative.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(JumpInstruction insn) {
|
public void jump(BasicBlockReader target) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(40);
|
output.writeUnsigned(40);
|
||||||
output.writeUnsigned(insn.getTarget().getIndex());
|
output.writeUnsigned(target.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(SwitchInstruction insn) {
|
public void choose(VariableReader condition, List<? extends SwitchTableEntryReader> table,
|
||||||
|
BasicBlockReader defaultTarget) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(41);
|
output.writeUnsigned(41);
|
||||||
output.writeUnsigned(insn.getCondition().getIndex());
|
output.writeUnsigned(condition.getIndex());
|
||||||
output.writeUnsigned(insn.getDefaultTarget().getIndex());
|
output.writeUnsigned(defaultTarget.getIndex());
|
||||||
output.writeUnsigned(insn.getEntries().size());
|
output.writeUnsigned(table.size());
|
||||||
for (SwitchTableEntry entry : insn.getEntries()) {
|
for (SwitchTableEntryReader entry : table) {
|
||||||
output.writeSigned(entry.getCondition());
|
output.writeSigned(entry.getCondition());
|
||||||
output.writeUnsigned(entry.getTarget().getIndex());
|
output.writeUnsigned(entry.getTarget().getIndex());
|
||||||
}
|
}
|
||||||
|
@ -462,11 +478,11 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ExitInstruction insn) {
|
public void exit(VariableReader valueToReturn) {
|
||||||
try {
|
try {
|
||||||
if (insn.getValueToReturn() != null) {
|
if (valueToReturn != null) {
|
||||||
output.writeUnsigned(42);
|
output.writeUnsigned(42);
|
||||||
output.writeUnsigned(insn.getValueToReturn().getIndex());
|
output.writeUnsigned(valueToReturn.getIndex());
|
||||||
} else {
|
} else {
|
||||||
output.writeUnsigned(43);
|
output.writeUnsigned(43);
|
||||||
}
|
}
|
||||||
|
@ -476,46 +492,36 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(RaiseInstruction insn) {
|
public void raise(VariableReader exception) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(44);
|
output.writeUnsigned(44);
|
||||||
output.writeUnsigned(insn.getException().getIndex());
|
output.writeUnsigned(exception.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void createArray(VariableReader receiver, ValueType itemType, VariableReader size) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(45);
|
output.writeUnsigned(45);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getItemType().toString()));
|
output.writeUnsigned(symbolTable.lookup(itemType.toString()));
|
||||||
output.writeUnsigned(insn.getSize().getIndex());
|
output.writeUnsigned(size.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructInstruction insn) {
|
public void createArray(VariableReader receiver, ValueType itemType,
|
||||||
try {
|
List<? extends VariableReader> dimensions) {
|
||||||
output.writeUnsigned(46);
|
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getType()));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IOExceptionWrapper(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visit(ConstructMultiArrayInstruction insn) {
|
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(47);
|
output.writeUnsigned(47);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getItemType().toString()));
|
output.writeUnsigned(symbolTable.lookup(itemType.toString()));
|
||||||
output.writeUnsigned(insn.getDimensions().size());
|
output.writeUnsigned(dimensions.size());
|
||||||
for (Variable dimension : insn.getDimensions()) {
|
for (VariableReader dimension : dimensions) {
|
||||||
output.writeUnsigned(dimension.getIndex());
|
output.writeUnsigned(dimension.getIndex());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -524,113 +530,128 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetFieldInstruction insn) {
|
public void create(VariableReader receiver, String type) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(insn.getInstance() != null ? 48 : 49);
|
output.writeUnsigned(46);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
if (insn.getInstance() != null) {
|
output.writeUnsigned(symbolTable.lookup(type));
|
||||||
output.writeUnsigned(insn.getInstance().getIndex());
|
|
||||||
}
|
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getField().getClassName()));
|
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getField().getFieldName()));
|
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getFieldType().toString()));
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutFieldInstruction insn) {
|
public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
|
||||||
|
ValueType fieldType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(insn.getInstance() != null ? 50 : 51);
|
output.writeUnsigned(instance != null ? 48 : 49);
|
||||||
if (insn.getInstance() != null) {
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getInstance().getIndex());
|
if (instance != null) {
|
||||||
|
output.writeUnsigned(instance.getIndex());
|
||||||
}
|
}
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getField().getClassName()));
|
output.writeUnsigned(symbolTable.lookup(field.getClassName()));
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getField().getFieldName()));
|
output.writeUnsigned(symbolTable.lookup(field.getFieldName()));
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getFieldType().toString()));
|
output.writeUnsigned(symbolTable.lookup(fieldType.toString()));
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void putField(VariableReader instance, FieldReference field, VariableReader value, ValueType fieldType) {
|
||||||
|
try {
|
||||||
|
output.writeUnsigned(instance != null ? 50 : 51);
|
||||||
|
if (instance != null) {
|
||||||
|
output.writeUnsigned(instance.getIndex());
|
||||||
|
}
|
||||||
|
output.writeUnsigned(symbolTable.lookup(field.getClassName()));
|
||||||
|
output.writeUnsigned(symbolTable.lookup(field.getFieldName()));
|
||||||
|
output.writeUnsigned(symbolTable.lookup(fieldType.toString()));
|
||||||
|
output.writeUnsigned(value.getIndex());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IOExceptionWrapper(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void arrayLength(VariableReader receiver, VariableReader array) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(52);
|
output.writeUnsigned(52);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getArray().getIndex());
|
output.writeUnsigned(array.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CloneArrayInstruction insn) {
|
public void cloneArray(VariableReader receiver, VariableReader array) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(53);
|
output.writeUnsigned(53);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getArray().getIndex());
|
output.writeUnsigned(array.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayInstruction insn) {
|
public void unwrapArray(VariableReader receiver, VariableReader array, ArrayElementType elementType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(54 + insn.getElementType().ordinal());
|
output.writeUnsigned(54 + elementType.ordinal());
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getArray().getIndex());
|
output.writeUnsigned(array.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetElementInstruction insn) {
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
|
||||||
|
ArrayElementType elementType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(62 + insn.getType().ordinal());
|
output.writeUnsigned(62 + elementType.ordinal());
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getArray().getIndex());
|
output.writeUnsigned(array.getIndex());
|
||||||
output.writeUnsigned(insn.getIndex().getIndex());
|
output.writeUnsigned(index.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(PutElementInstruction insn) {
|
public void putElement(VariableReader array, VariableReader index, VariableReader value,
|
||||||
|
ArrayElementType elementType) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(70 + insn.getType().ordinal());
|
output.writeUnsigned(70 + elementType.ordinal());
|
||||||
output.writeUnsigned(insn.getArray().getIndex());
|
output.writeUnsigned(array.getIndex());
|
||||||
output.writeUnsigned(insn.getIndex().getIndex());
|
output.writeUnsigned(index.getIndex());
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeInstruction insn) {
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
|
List<? extends VariableReader> arguments, InvocationType type) {
|
||||||
try {
|
try {
|
||||||
switch (insn.getType()) {
|
switch (type) {
|
||||||
case SPECIAL:
|
case SPECIAL:
|
||||||
output.writeUnsigned(insn.getInstance() == null ? 78 : 79);
|
output.writeUnsigned(instance == null ? 78 : 79);
|
||||||
break;
|
break;
|
||||||
case VIRTUAL:
|
case VIRTUAL:
|
||||||
output.writeUnsigned(80);
|
output.writeUnsigned(80);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
output.writeUnsigned(insn.getReceiver() != null ? insn.getReceiver().getIndex() + 1 : 0);
|
output.writeUnsigned(receiver != null ? receiver.getIndex() + 1 : 0);
|
||||||
if (insn.getInstance() != null) {
|
if (instance != null) {
|
||||||
output.writeUnsigned(insn.getInstance().getIndex());
|
output.writeUnsigned(instance.getIndex());
|
||||||
}
|
}
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getMethod().getClassName()));
|
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getMethod().getDescriptor().toString()));
|
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||||
for (int i = 0; i < insn.getArguments().size(); ++i) {
|
for (int i = 0; i < arguments.size(); ++i) {
|
||||||
output.writeUnsigned(insn.getArguments().get(i).getIndex());
|
output.writeUnsigned(arguments.get(i).getIndex());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
|
@ -638,19 +659,21 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InvokeDynamicInstruction insn) {
|
public void invokeDynamic(VariableReader receiver, VariableReader instance, MethodDescriptor method,
|
||||||
|
List<? extends VariableReader> arguments, MethodHandle bootstrapMethod,
|
||||||
|
List<RuntimeConstant> bootstrapArguments) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(81);
|
output.writeUnsigned(81);
|
||||||
output.writeUnsigned(insn.getReceiver() != null ? insn.getReceiver().getIndex() + 1 : 0);
|
output.writeUnsigned(receiver != null ? receiver.getIndex() + 1 : 0);
|
||||||
output.writeUnsigned(insn.getInstance() != null ? insn.getInstance().getIndex() + 1 : 0);
|
output.writeUnsigned(instance != null ? instance.getIndex() + 1 : 0);
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getMethod().toString()));
|
output.writeUnsigned(symbolTable.lookup(method.toString()));
|
||||||
for (int i = 0; i < insn.getArguments().size(); ++i) {
|
for (int i = 0; i < arguments.size(); ++i) {
|
||||||
output.writeUnsigned(insn.getArguments().get(i).getIndex());
|
output.writeUnsigned(arguments.get(i).getIndex());
|
||||||
}
|
}
|
||||||
write(insn.getBootstrapMethod());
|
write(bootstrapMethod);
|
||||||
output.writeUnsigned(insn.getBootstrapArguments().size());
|
output.writeUnsigned(bootstrapArguments.size());
|
||||||
for (int i = 0; i < insn.getBootstrapArguments().size(); ++i) {
|
for (int i = 0; i < bootstrapArguments.size(); ++i) {
|
||||||
write(insn.getBootstrapArguments().get(i));
|
write(bootstrapArguments.get(i));
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
|
@ -658,53 +681,53 @@ public class ProgramIO {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void isInstance(VariableReader receiver, VariableReader value, ValueType type) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(82);
|
output.writeUnsigned(82);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getType().toString()));
|
output.writeUnsigned(symbolTable.lookup(type.toString()));
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InitClassInstruction insn) {
|
public void initClass(String className) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(83);
|
output.writeUnsigned(83);
|
||||||
output.writeUnsigned(symbolTable.lookup(insn.getClassName()));
|
output.writeUnsigned(symbolTable.lookup(className));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void nullCheck(VariableReader receiver, VariableReader value) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(84);
|
output.writeUnsigned(84);
|
||||||
output.writeUnsigned(insn.getReceiver().getIndex());
|
output.writeUnsigned(receiver.getIndex());
|
||||||
output.writeUnsigned(insn.getValue().getIndex());
|
output.writeUnsigned(value.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorEnterInstruction insn) {
|
public void monitorEnter(VariableReader objectRef) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(85);
|
output.writeUnsigned(85);
|
||||||
output.writeUnsigned(insn.getObjectRef().getIndex());
|
output.writeUnsigned(objectRef.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(MonitorExitInstruction insn) {
|
public void monitorExit(VariableReader objectRef) {
|
||||||
try {
|
try {
|
||||||
output.writeUnsigned(86);
|
output.writeUnsigned(86);
|
||||||
output.writeUnsigned(insn.getObjectRef().getIndex());
|
output.writeUnsigned(objectRef.getIndex());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOExceptionWrapper(e);
|
throw new IOExceptionWrapper(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,4 +124,24 @@ public class VarDataInput {
|
||||||
}
|
}
|
||||||
return new String(chars);
|
return new String(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] readBytes() throws IOException {
|
||||||
|
byte[] buf = new byte[readUnsigned()];
|
||||||
|
int off = 0;
|
||||||
|
while (true) {
|
||||||
|
int toRead = buf.length - off;
|
||||||
|
if (toRead == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int read = input.read(buf, off, toRead);
|
||||||
|
if (read < 0) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
if (read == toRead) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
off += read;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,11 @@ public class VarDataOutput implements Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void writeBytes(byte[] data) throws IOException {
|
||||||
|
writeUnsigned(data.length);
|
||||||
|
output.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
output.close();
|
output.close();
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class ClassDependency implements ClassDependencyInfo {
|
||||||
private DependencyAnalyzer analyzer;
|
private DependencyAnalyzer analyzer;
|
||||||
private String className;
|
private String className;
|
||||||
private ClassReader classReader;
|
private ClassReader classReader;
|
||||||
|
boolean present;
|
||||||
boolean activated;
|
boolean activated;
|
||||||
|
|
||||||
ClassDependency(DependencyAnalyzer analyzer, String className, ClassReader classReader) {
|
ClassDependency(DependencyAnalyzer analyzer, String className, ClassReader classReader) {
|
||||||
|
@ -37,7 +38,7 @@ public class ClassDependency implements ClassDependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMissing() {
|
public boolean isMissing() {
|
||||||
return classReader == null;
|
return classReader == null && !present;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassReader getClassReader() {
|
public ClassReader getClassReader() {
|
||||||
|
@ -49,4 +50,11 @@ public class ClassDependency implements ClassDependencyInfo {
|
||||||
analyzer.initClass(this, location);
|
analyzer.initClass(this, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
if (classReader != null) {
|
||||||
|
present = true;
|
||||||
|
classReader = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* 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.dependency;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
|
public interface ClassSourcePacker {
|
||||||
|
ClassReaderSource pack(ClassReaderSource classSource, Collection<? extends String> classNames);
|
||||||
|
}
|
|
@ -80,7 +80,7 @@ public class DependencyAgent implements DependencyInfo, ServiceRepository {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return analyzer.getClassSource();
|
return analyzer.agentClassSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -82,8 +83,10 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
private int classNameSuffix;
|
private int classNameSuffix;
|
||||||
private ClassReaderSource unprocessedClassSource;
|
private ClassReaderSource unprocessedClassSource;
|
||||||
private DependencyClassSource classSource;
|
private DependencyClassSource classSource;
|
||||||
|
ClassReaderSource agentClassSource;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private Map<String, Map<MethodDescriptor, Optional<MethodHolder>>> methodReaderCache = new HashMap<>(1000, 0.5f);
|
private Map<String, Map<MethodDescriptor, Optional<MethodHolder>>> methodReaderCache = new HashMap<>(1000, 0.5f);
|
||||||
|
private Map<MethodReference, MethodDependency> implementationCache = new HashMap<>();
|
||||||
private Function<FieldReference, FieldHolder> fieldReaderCache;
|
private Function<FieldReference, FieldHolder> fieldReaderCache;
|
||||||
private Map<String, Map<MethodDescriptor, MethodDependency>> methodCache = new HashMap<>();
|
private Map<String, Map<MethodDescriptor, MethodDependency>> methodCache = new HashMap<>();
|
||||||
private Set<MethodReference> reachedMethods = new LinkedHashSet<>();
|
private Set<MethodReference> reachedMethods = new LinkedHashSet<>();
|
||||||
|
@ -111,6 +114,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
IncrementalCache incrementalCache = new IncrementalCache();
|
IncrementalCache incrementalCache = new IncrementalCache();
|
||||||
boolean asyncSupported;
|
boolean asyncSupported;
|
||||||
private ReferenceCache referenceCache;
|
private ReferenceCache referenceCache;
|
||||||
|
private Set<String> generatedClassNames = new HashSet<>();
|
||||||
|
|
||||||
DependencyAnalyzer(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
DependencyAnalyzer(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
||||||
Diagnostics diagnostics, ReferenceCache referenceCache) {
|
Diagnostics diagnostics, ReferenceCache referenceCache) {
|
||||||
|
@ -118,6 +122,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.referenceCache = referenceCache;
|
this.referenceCache = referenceCache;
|
||||||
this.classSource = new DependencyClassSource(classSource, diagnostics, incrementalCache);
|
this.classSource = new DependencyClassSource(classSource, diagnostics, incrementalCache);
|
||||||
|
agentClassSource = this.classSource;
|
||||||
classHierarchy = new ClassHierarchy(this.classSource);
|
classHierarchy = new ClassHierarchy(this.classSource);
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
this.services = services;
|
this.services = services;
|
||||||
|
@ -206,11 +211,11 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource != null ? classSource : agentClassSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSynthesizedClass(String className) {
|
public boolean isSynthesizedClass(String className) {
|
||||||
return classSource.isGeneratedClass(className);
|
return classSource != null ? classSource.isGeneratedClass(className) : generatedClassNames.contains(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassHierarchy getClassHierarchy() {
|
public ClassHierarchy getClassHierarchy() {
|
||||||
|
@ -608,8 +613,10 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MethodDependency getMethodImplementation(MethodReference methodRef) {
|
public MethodDependency getMethodImplementation(MethodReference methodRef) {
|
||||||
MethodReader method = getMethodHolder(methodRef.getClassName(), methodRef.getDescriptor());
|
return implementationCache.computeIfAbsent(methodRef, m -> {
|
||||||
return method != null ? getMethod(method.getReference()) : null;
|
MethodReader resolved = agentClassSource.resolveImplementation(m);
|
||||||
|
return resolved != null ? getMethod(resolved.getReference()) : null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodHolder getMethodHolder(String className, MethodDescriptor descriptor) {
|
private MethodHolder getMethodHolder(String className, MethodDescriptor descriptor) {
|
||||||
|
@ -726,7 +733,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
System.out.println("Total domains: " + domainCount);
|
System.out.println("Total domains: " + domainCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup(ClassSourcePacker classSourcePacker) {
|
||||||
for (DependencyNode node : allNodes) {
|
for (DependencyNode node : allNodes) {
|
||||||
node.followers = null;
|
node.followers = null;
|
||||||
node.transitions = null;
|
node.transitions = null;
|
||||||
|
@ -744,6 +751,7 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
for (MethodDependency methodDependency : map.values()) {
|
for (MethodDependency methodDependency : map.values()) {
|
||||||
methodDependency.locationListeners = null;
|
methodDependency.locationListeners = null;
|
||||||
methodDependency.locations = null;
|
methodDependency.locations = null;
|
||||||
|
methodDependency.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,15 +760,30 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
field.locationListeners = null;
|
field.locationListeners = null;
|
||||||
field.locations = null;
|
field.locations = null;
|
||||||
|
field.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String className : classCache.getCachedPreimages()) {
|
||||||
|
ClassDependency cls = classCache.getKnown(className);
|
||||||
|
cls.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
allNodes.clear();
|
allNodes.clear();
|
||||||
classSource.cleanup();
|
classSource.cleanup();
|
||||||
agent.cleanup();
|
agent.cleanup();
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
unprocessedClassSource = null;
|
unprocessedClassSource = null;
|
||||||
classSource.innerHierarchy = null;
|
classSource.innerHierarchy = null;
|
||||||
|
|
||||||
|
agentClassSource = classSourcePacker.pack(classSource, classSource.cache.keySet());
|
||||||
|
if (classSource != agentClassSource) {
|
||||||
|
classHierarchy = new ClassHierarchy(agentClassSource);
|
||||||
|
generatedClassNames.addAll(classSource.getGeneratedClassNames());
|
||||||
|
}
|
||||||
|
classSource = null;
|
||||||
|
methodReaderCache = null;
|
||||||
|
fieldReaderCache = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupTypes() {
|
public void cleanupTypes() {
|
||||||
|
|
|
@ -41,7 +41,7 @@ class DependencyClassSource implements ClassHolderSource {
|
||||||
private IncrementalDependencyRegistration dependencyRegistration;
|
private IncrementalDependencyRegistration dependencyRegistration;
|
||||||
private Map<String, ClassHolder> generatedClasses = new LinkedHashMap<>();
|
private Map<String, ClassHolder> generatedClasses = new LinkedHashMap<>();
|
||||||
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
private List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||||
private Map<String, Optional<ClassHolder>> cache = new LinkedHashMap<>(1000, 0.5f);
|
Map<String, Optional<ClassHolder>> cache = new LinkedHashMap<>(1000, 0.5f);
|
||||||
|
|
||||||
DependencyClassSource(ClassReaderSource innerSource, Diagnostics diagnostics,
|
DependencyClassSource(ClassReaderSource innerSource, Diagnostics diagnostics,
|
||||||
IncrementalDependencyRegistration dependencyRegistration) {
|
IncrementalDependencyRegistration dependencyRegistration) {
|
||||||
|
@ -93,6 +93,10 @@ class DependencyClassSource implements ClassHolderSource {
|
||||||
return generatedClasses.get(name);
|
return generatedClasses.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collection<String> getGeneratedClassNames() {
|
||||||
|
return generatedClasses.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
public Collection<ClassHolder> getGeneratedClasses() {
|
public Collection<ClassHolder> getGeneratedClasses() {
|
||||||
return generatedClasses.values();
|
return generatedClasses.values();
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,9 +191,9 @@ public class FastDependencyAnalyzer extends DependencyAnalyzer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanup() {
|
public void cleanup(ClassSourcePacker classSourcePacker) {
|
||||||
virtualCallConsumers.clear();
|
virtualCallConsumers.clear();
|
||||||
subtypeNodes.clear();
|
subtypeNodes.clear();
|
||||||
super.cleanup();
|
super.cleanup(classSourcePacker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.model.FieldReference;
|
||||||
public class FieldDependency implements FieldDependencyInfo {
|
public class FieldDependency implements FieldDependencyInfo {
|
||||||
DependencyNode value;
|
DependencyNode value;
|
||||||
private FieldReader field;
|
private FieldReader field;
|
||||||
|
private boolean present;
|
||||||
private FieldReference reference;
|
private FieldReference reference;
|
||||||
List<LocationListener> locationListeners;
|
List<LocationListener> locationListeners;
|
||||||
Set<CallLocation> locations;
|
Set<CallLocation> locations;
|
||||||
|
@ -53,7 +54,7 @@ public class FieldDependency implements FieldDependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMissing() {
|
public boolean isMissing() {
|
||||||
return field == null;
|
return field == null && !present;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldDependency addLocation(CallLocation location) {
|
public FieldDependency addLocation(CallLocation location) {
|
||||||
|
@ -83,4 +84,11 @@ public class FieldDependency implements FieldDependencyInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
if (field != null) {
|
||||||
|
field = null;
|
||||||
|
present = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
DependencyNode resultNode;
|
DependencyNode resultNode;
|
||||||
DependencyNode thrown;
|
DependencyNode thrown;
|
||||||
MethodHolder method;
|
MethodHolder method;
|
||||||
|
boolean present;
|
||||||
private MethodReference reference;
|
private MethodReference reference;
|
||||||
boolean used;
|
boolean used;
|
||||||
boolean external;
|
boolean external;
|
||||||
|
@ -101,7 +102,7 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isMissing() {
|
public boolean isMissing() {
|
||||||
return method == null;
|
return method == null && !present;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -179,4 +180,12 @@ public class MethodDependency implements MethodDependencyInfo {
|
||||||
public boolean isCalled() {
|
public boolean isCalled() {
|
||||||
return external;
|
return external;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
if (method != null) {
|
||||||
|
present = true;
|
||||||
|
method = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.teavm.cache.EmptyProgramCache;
|
||||||
import org.teavm.cache.ProgramDependencyExtractor;
|
import org.teavm.cache.ProgramDependencyExtractor;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
||||||
|
import org.teavm.dependency.ClassSourcePacker;
|
||||||
import org.teavm.dependency.DependencyAnalyzer;
|
import org.teavm.dependency.DependencyAnalyzer;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.dependency.DependencyListener;
|
import org.teavm.dependency.DependencyListener;
|
||||||
|
@ -152,10 +153,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
private int compileProgressReportLimit;
|
private int compileProgressReportLimit;
|
||||||
private int compileProgressLimit;
|
private int compileProgressLimit;
|
||||||
private int compileProgressValue;
|
private int compileProgressValue;
|
||||||
|
private ClassSourcePacker classSourcePacker;
|
||||||
|
|
||||||
TeaVM(TeaVMBuilder builder) {
|
TeaVM(TeaVMBuilder builder) {
|
||||||
target = builder.target;
|
target = builder.target;
|
||||||
classLoader = builder.classLoader;
|
classLoader = builder.classLoader;
|
||||||
|
classSourcePacker = builder.classSourcePacker;
|
||||||
dependencyAnalyzer = builder.dependencyAnalyzerFactory.create(builder.classSource, classLoader,
|
dependencyAnalyzer = builder.dependencyAnalyzerFactory.create(builder.classSource, classLoader,
|
||||||
this, diagnostics, builder.referenceCache);
|
this, diagnostics, builder.referenceCache);
|
||||||
progressListener = new TeaVMProgressListener() {
|
progressListener = new TeaVMProgressListener() {
|
||||||
|
@ -348,8 +351,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
* @param outputName name of output file within buildTarget. Should not be null.
|
* @param outputName name of output file within buildTarget. Should not be null.
|
||||||
*/
|
*/
|
||||||
public void build(BuildTarget buildTarget, String outputName) {
|
public void build(BuildTarget buildTarget, String outputName) {
|
||||||
target.setController(targetController);
|
|
||||||
|
|
||||||
// Check dependencies
|
// Check dependencies
|
||||||
reportPhase(TeaVMPhase.DEPENDENCY_ANALYSIS, lastKnownClasses > 0 ? lastKnownClasses : 1);
|
reportPhase(TeaVMPhase.DEPENDENCY_ANALYSIS, lastKnownClasses > 0 ? lastKnownClasses : 1);
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
|
@ -368,11 +369,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyAnalyzer.setInterruptor(null);
|
||||||
|
dependencyAnalyzer.cleanup(classSourcePacker);
|
||||||
cacheStatus = new AnnotationAwareCacheStatus(rawCacheStatus, dependencyAnalyzer.getIncrementalDependencies(),
|
cacheStatus = new AnnotationAwareCacheStatus(rawCacheStatus, dependencyAnalyzer.getIncrementalDependencies(),
|
||||||
dependencyAnalyzer.getClassSource());
|
dependencyAnalyzer.getClassSource());
|
||||||
cacheStatus.addSynthesizedClasses(dependencyAnalyzer::isSynthesizedClass);
|
cacheStatus.addSynthesizedClasses(dependencyAnalyzer::isSynthesizedClass);
|
||||||
dependencyAnalyzer.setInterruptor(null);
|
target.setController(targetController);
|
||||||
dependencyAnalyzer.cleanup();
|
|
||||||
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.vm;
|
package org.teavm.vm;
|
||||||
|
|
||||||
|
import org.teavm.dependency.ClassSourcePacker;
|
||||||
import org.teavm.dependency.DependencyAnalyzerFactory;
|
import org.teavm.dependency.DependencyAnalyzerFactory;
|
||||||
import org.teavm.dependency.PreciseDependencyAnalyzer;
|
import org.teavm.dependency.PreciseDependencyAnalyzer;
|
||||||
import org.teavm.interop.PlatformMarker;
|
import org.teavm.interop.PlatformMarker;
|
||||||
|
@ -28,6 +29,7 @@ public class TeaVMBuilder {
|
||||||
ClassLoader classLoader;
|
ClassLoader classLoader;
|
||||||
ReferenceCache referenceCache = new ReferenceCache();
|
ReferenceCache referenceCache = new ReferenceCache();
|
||||||
DependencyAnalyzerFactory dependencyAnalyzerFactory = PreciseDependencyAnalyzer::new;
|
DependencyAnalyzerFactory dependencyAnalyzerFactory = PreciseDependencyAnalyzer::new;
|
||||||
|
ClassSourcePacker classSourcePacker = (src, names) -> src;
|
||||||
|
|
||||||
public TeaVMBuilder(TeaVMTarget target) {
|
public TeaVMBuilder(TeaVMTarget target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
@ -67,6 +69,11 @@ public class TeaVMBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TeaVMBuilder setClassSourcePacker(ClassSourcePacker classSourcePacker) {
|
||||||
|
this.classSourcePacker = classSourcePacker;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TeaVM build() {
|
public TeaVM build() {
|
||||||
return new TeaVM(this);
|
return new TeaVM(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ public class IncrementalTest {
|
||||||
public boolean isStaleClass(String className) {
|
public boolean isStaleClass(String className) {
|
||||||
ClassReader cls = underlying.get(className);
|
ClassReader cls = underlying.get(className);
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cls.getAnnotations().get(Update.class.getName()) != null;
|
return cls.getAnnotations().get(Update.class.getName()) != null;
|
||||||
|
|
|
@ -38,7 +38,7 @@ import org.teavm.backend.wasm.WasmTarget;
|
||||||
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
import org.teavm.backend.wasm.render.WasmBinaryVersion;
|
||||||
import org.teavm.cache.AlwaysStaleCacheStatus;
|
import org.teavm.cache.AlwaysStaleCacheStatus;
|
||||||
import org.teavm.cache.CacheStatus;
|
import org.teavm.cache.CacheStatus;
|
||||||
import org.teavm.cache.DiskCachedClassHolderSource;
|
import org.teavm.cache.DiskCachedClassReaderSource;
|
||||||
import org.teavm.cache.DiskMethodNodeCache;
|
import org.teavm.cache.DiskMethodNodeCache;
|
||||||
import org.teavm.cache.DiskProgramCache;
|
import org.teavm.cache.DiskProgramCache;
|
||||||
import org.teavm.cache.EmptyProgramCache;
|
import org.teavm.cache.EmptyProgramCache;
|
||||||
|
@ -83,7 +83,7 @@ public class TeaVMTool {
|
||||||
private List<String> classesToPreserve = new ArrayList<>();
|
private List<String> classesToPreserve = new ArrayList<>();
|
||||||
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
private TeaVMToolLog log = new EmptyTeaVMToolLog();
|
||||||
private ClassLoader classLoader = TeaVMTool.class.getClassLoader();
|
private ClassLoader classLoader = TeaVMTool.class.getClassLoader();
|
||||||
private DiskCachedClassHolderSource cachedClassSource;
|
private DiskCachedClassReaderSource cachedClassSource;
|
||||||
private DiskProgramCache programCache;
|
private DiskProgramCache programCache;
|
||||||
private DiskMethodNodeCache astCache;
|
private DiskMethodNodeCache astCache;
|
||||||
private FileSymbolTable symbolTable;
|
private FileSymbolTable symbolTable;
|
||||||
|
@ -340,7 +340,7 @@ public class TeaVMTool {
|
||||||
ClasspathClassHolderSource innerClassSource = new ClasspathClassHolderSource(classLoader,
|
ClasspathClassHolderSource innerClassSource = new ClasspathClassHolderSource(classLoader,
|
||||||
referenceCache);
|
referenceCache);
|
||||||
ClassHolderSource classSource = new PreOptimizingClassHolderSource(innerClassSource);
|
ClassHolderSource classSource = new PreOptimizingClassHolderSource(innerClassSource);
|
||||||
cachedClassSource = new DiskCachedClassHolderSource(cacheDirectory, referenceCache, symbolTable,
|
cachedClassSource = new DiskCachedClassReaderSource(cacheDirectory, referenceCache, symbolTable,
|
||||||
fileTable, variableTable, classSource, innerClassSource);
|
fileTable, variableTable, classSource, innerClassSource);
|
||||||
programCache = new DiskProgramCache(cacheDirectory, referenceCache, symbolTable, fileTable,
|
programCache = new DiskProgramCache(cacheDirectory, referenceCache, symbolTable, fileTable,
|
||||||
variableTable);
|
variableTable);
|
||||||
|
|
|
@ -77,6 +77,7 @@ import org.teavm.debugging.information.DebugInformationBuilder;
|
||||||
import org.teavm.dependency.FastDependencyAnalyzer;
|
import org.teavm.dependency.FastDependencyAnalyzer;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.PreOptimizingClassHolderSource;
|
import org.teavm.model.PreOptimizingClassHolderSource;
|
||||||
import org.teavm.model.ReferenceCache;
|
import org.teavm.model.ReferenceCache;
|
||||||
import org.teavm.parsing.ClasspathResourceMapper;
|
import org.teavm.parsing.ClasspathResourceMapper;
|
||||||
|
@ -713,12 +714,16 @@ public class CodeServlet extends HttpServlet {
|
||||||
private void initBuilder() throws IOException {
|
private void initBuilder() throws IOException {
|
||||||
watcher = new FileSystemWatcher(classPath);
|
watcher = new FileSystemWatcher(classPath);
|
||||||
|
|
||||||
classSource = new MemoryCachedClassReaderSource(referenceCache, symbolTable, fileSymbolTable,
|
classSource = createCachedSource();
|
||||||
variableSymbolTable);
|
|
||||||
astCache = new InMemoryMethodNodeCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
astCache = new InMemoryMethodNodeCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||||
programCache = new InMemoryProgramCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
programCache = new InMemoryProgramCache(referenceCache, symbolTable, fileSymbolTable, variableSymbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MemoryCachedClassReaderSource createCachedSource() {
|
||||||
|
return new MemoryCachedClassReaderSource(referenceCache, symbolTable, fileSymbolTable,
|
||||||
|
variableSymbolTable);
|
||||||
|
}
|
||||||
|
|
||||||
private void shutdownBuilder() {
|
private void shutdownBuilder() {
|
||||||
try {
|
try {
|
||||||
watcher.dispose();
|
watcher.dispose();
|
||||||
|
@ -757,6 +762,7 @@ public class CodeServlet extends HttpServlet {
|
||||||
.setClassLoader(classLoader)
|
.setClassLoader(classLoader)
|
||||||
.setClassSource(classSource)
|
.setClassSource(classSource)
|
||||||
.setDependencyAnalyzerFactory(FastDependencyAnalyzer::new)
|
.setDependencyAnalyzerFactory(FastDependencyAnalyzer::new)
|
||||||
|
.setClassSourcePacker(this::packClasses)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
jsTarget.setStackTraceIncluded(true);
|
jsTarget.setStackTraceIncluded(true);
|
||||||
|
@ -784,6 +790,16 @@ public class CodeServlet extends HttpServlet {
|
||||||
postBuild(vm, startTime);
|
postBuild(vm, startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ClassReaderSource packClasses(ClassReaderSource source, Collection<? extends String> classNames) {
|
||||||
|
MemoryCachedClassReaderSource packedSource = createCachedSource();
|
||||||
|
packedSource.setProvider(source::get);
|
||||||
|
for (String className : classNames) {
|
||||||
|
packedSource.populate(className);
|
||||||
|
}
|
||||||
|
packedSource.setProvider(null);
|
||||||
|
return packedSource;
|
||||||
|
}
|
||||||
|
|
||||||
private void addIndicator() {
|
private void addIndicator() {
|
||||||
String script = getIndicatorScript(false);
|
String script = getIndicatorScript(false);
|
||||||
try (Writer writer = new OutputStreamWriter(buildTarget.appendToResource(fileName), StandardCharsets.UTF_8)) {
|
try (Writer writer = new OutputStreamWriter(buildTarget.appendToResource(fileName), StandardCharsets.UTF_8)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user