mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Begin to implement variable mapping
This commit is contained in:
parent
dbb807efed
commit
bc911a661a
|
@ -1,16 +1,16 @@
|
||||||
package org.teavm.chromerdp;
|
package org.teavm.chromerdp;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.Exchanger;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import org.codehaus.jackson.JsonNode;
|
import org.codehaus.jackson.JsonNode;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.teavm.chromerdp.data.CallFrameDTO;
|
import org.teavm.chromerdp.data.*;
|
||||||
import org.teavm.chromerdp.data.LocationDTO;
|
|
||||||
import org.teavm.chromerdp.data.Message;
|
|
||||||
import org.teavm.chromerdp.data.Response;
|
|
||||||
import org.teavm.chromerdp.messages.*;
|
import org.teavm.chromerdp.messages.*;
|
||||||
import org.teavm.debugging.*;
|
import org.teavm.debugging.*;
|
||||||
|
|
||||||
|
@ -266,6 +266,37 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<RDPLocalVariable> getScope(String scopeId) {
|
||||||
|
if (exchange == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
Message message = new Message();
|
||||||
|
message.setId(messageIdGenerator.incrementAndGet());
|
||||||
|
message.setMethod("Runtime.getProperties");
|
||||||
|
GetPropertiesCommand params = new GetPropertiesCommand();
|
||||||
|
params.setObjectId(scopeId);
|
||||||
|
params.setOwnProperties(true);
|
||||||
|
message.setParams(mapper.valueToTree(params));
|
||||||
|
final Exchanger<List<RDPLocalVariable>> exchanger = new Exchanger<>();
|
||||||
|
responseHandlers.put(message.getId(), new ResponseHandler() {
|
||||||
|
@Override public void received(JsonNode node) throws IOException {
|
||||||
|
GetPropertiesResponse response = mapper.reader(GetPropertiesResponse.class).readValue(node);
|
||||||
|
// TODO: parse response
|
||||||
|
try {
|
||||||
|
exchanger.exchange(new ArrayList<RDPLocalVariable>());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sendMessage(message);
|
||||||
|
try {
|
||||||
|
return exchanger.exchange(null);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private <T> T parseJson(Class<T> type, JsonNode node) throws IOException {
|
private <T> T parseJson(Class<T> type, JsonNode node) throws IOException {
|
||||||
return mapper.reader(type).readValue(node);
|
return mapper.reader(type).readValue(node);
|
||||||
}
|
}
|
||||||
|
@ -282,7 +313,14 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
||||||
}
|
}
|
||||||
|
|
||||||
RDPCallFrame map(CallFrameDTO dto) {
|
RDPCallFrame map(CallFrameDTO dto) {
|
||||||
return new RDPCallFrame(dto.getCallFrameId(), map(dto.getLocation()));
|
String scopeId = null;
|
||||||
|
for (ScopeDTO scope : dto.getScopeChain()) {
|
||||||
|
if (scope.getType().equals("local")) {
|
||||||
|
scopeId = scope.getObject();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new RDPCallFrame(dto.getCallFrameId(), map(dto.getLocation()), new RDPScope(this, scopeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaScriptLocation map(LocationDTO dto) {
|
JavaScriptLocation map(LocationDTO dto) {
|
||||||
|
|
|
@ -15,8 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.chromerdp;
|
package org.teavm.chromerdp;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import org.teavm.debugging.JavaScriptCallFrame;
|
import org.teavm.debugging.JavaScriptCallFrame;
|
||||||
import org.teavm.debugging.JavaScriptLocation;
|
import org.teavm.debugging.JavaScriptLocation;
|
||||||
|
import org.teavm.debugging.JavaScriptVariable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -25,10 +28,13 @@ import org.teavm.debugging.JavaScriptLocation;
|
||||||
public class RDPCallFrame implements JavaScriptCallFrame {
|
public class RDPCallFrame implements JavaScriptCallFrame {
|
||||||
private String chromeId;
|
private String chromeId;
|
||||||
private JavaScriptLocation location;
|
private JavaScriptLocation location;
|
||||||
|
private Map<String, JavaScriptVariable> variables;
|
||||||
|
|
||||||
public RDPCallFrame(String chromeId, JavaScriptLocation location) {
|
public RDPCallFrame(String chromeId, JavaScriptLocation location,
|
||||||
|
Map<String, ? extends JavaScriptVariable> variables) {
|
||||||
this.chromeId = chromeId;
|
this.chromeId = chromeId;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
this.variables = Collections.unmodifiableMap(variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getChromeId() {
|
public String getChromeId() {
|
||||||
|
@ -39,4 +45,9 @@ public class RDPCallFrame implements JavaScriptCallFrame {
|
||||||
public JavaScriptLocation getLocation() {
|
public JavaScriptLocation getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, JavaScriptVariable> getVariables() {
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.teavm.chromerdp;
|
||||||
|
|
||||||
|
import org.teavm.debugging.JavaScriptValue;
|
||||||
|
import org.teavm.debugging.JavaScriptVariable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class RDPLocalVariable implements JavaScriptVariable {
|
||||||
|
private String name;
|
||||||
|
private RDPValue value;
|
||||||
|
|
||||||
|
public RDPLocalVariable(String name, RDPValue value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaScriptValue getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.teavm.chromerdp;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class RDPScope extends AbstractMap<String, RDPLocalVariable> {
|
||||||
|
private volatile Map<String, RDPLocalVariable> backingMap;
|
||||||
|
private ChromeRDPDebugger debugger;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public RDPScope(ChromeRDPDebugger debugger, String id) {
|
||||||
|
this.debugger = debugger;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Entry<String, RDPLocalVariable>> entrySet() {
|
||||||
|
initBackingMap();
|
||||||
|
return backingMap.entrySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
initBackingMap();
|
||||||
|
return backingMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RDPLocalVariable get(Object key) {
|
||||||
|
initBackingMap();
|
||||||
|
return backingMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initBackingMap() {
|
||||||
|
if (backingMap != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (id == null) {
|
||||||
|
backingMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
Map<String, RDPLocalVariable> newBackingMap = new HashMap<>();
|
||||||
|
for (RDPLocalVariable variable : debugger.getScope(id)) {
|
||||||
|
newBackingMap.put(variable.getName(), variable);
|
||||||
|
}
|
||||||
|
backingMap = newBackingMap;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.teavm.chromerdp;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.debugging.JavaScriptValue;
|
||||||
|
import org.teavm.debugging.JavaScriptVariable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class RDPValue implements JavaScriptValue {
|
||||||
|
private String representation;
|
||||||
|
|
||||||
|
public RDPValue(String representation) {
|
||||||
|
this.representation = representation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRepresentation() {
|
||||||
|
return representation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, JavaScriptVariable> getProperties() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
public class CallFrameDTO {
|
public class CallFrameDTO {
|
||||||
private String callFrameId;
|
private String callFrameId;
|
||||||
private LocationDTO location;
|
private LocationDTO location;
|
||||||
|
private ScopeDTO[] scopeChain;
|
||||||
|
|
||||||
public String getCallFrameId() {
|
public String getCallFrameId() {
|
||||||
return callFrameId;
|
return callFrameId;
|
||||||
|
@ -41,4 +42,12 @@ public class CallFrameDTO {
|
||||||
public void setLocation(LocationDTO location) {
|
public void setLocation(LocationDTO location) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScopeDTO[] getScopeChain() {
|
||||||
|
return scopeChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScopeChain(ScopeDTO[] scopeChain) {
|
||||||
|
this.scopeChain = scopeChain;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.teavm.chromerdp.data;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class PropertyDescriptorDTO {
|
||||||
|
private String name;
|
||||||
|
private RemoteObjectDTO value;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoteObjectDTO getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(RemoteObjectDTO value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.teavm.chromerdp.data;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.JsonNode;
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class RemoteObjectDTO {
|
||||||
|
private String className;
|
||||||
|
private String description;
|
||||||
|
private String objectId;
|
||||||
|
private String type;
|
||||||
|
private JsonNode value;
|
||||||
|
|
||||||
|
public String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassName(String className) {
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getObjectId() {
|
||||||
|
return objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjectId(String objectId) {
|
||||||
|
this.objectId = objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonNode getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(JsonNode value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.teavm.chromerdp.data;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class ScopeDTO {
|
||||||
|
private String object;
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public String getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObject(String object) {
|
||||||
|
this.object = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.teavm.chromerdp.messages;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class GetPropertiesCommand {
|
||||||
|
private String objectId;
|
||||||
|
private boolean ownProperties;
|
||||||
|
|
||||||
|
public String getObjectId() {
|
||||||
|
return objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObjectId(String objectId) {
|
||||||
|
this.objectId = objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwnProperties() {
|
||||||
|
return ownProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwnProperties(boolean ownProperties) {
|
||||||
|
this.ownProperties = ownProperties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.teavm.chromerdp.messages;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||||
|
import org.teavm.chromerdp.data.PropertyDescriptorDTO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class GetPropertiesResponse {
|
||||||
|
private PropertyDescriptorDTO[] properties;
|
||||||
|
|
||||||
|
public PropertyDescriptorDTO[] getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(PropertyDescriptorDTO[] properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,8 +33,8 @@ public class JavacSupport implements ClassHolderTransformer {
|
||||||
ValueType.object("javax.tools.JavaCompiler")));
|
ValueType.object("javax.tools.JavaCompiler")));
|
||||||
Program program = new Program();
|
Program program = new Program();
|
||||||
BasicBlock block = program.createBasicBlock();
|
BasicBlock block = program.createBasicBlock();
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable(null);
|
||||||
ConstructInstruction construct = new ConstructInstruction();
|
ConstructInstruction construct = new ConstructInstruction();
|
||||||
construct.setReceiver(var);
|
construct.setReceiver(var);
|
||||||
construct.setType("com.sun.tools.javac.api.JavacTool");
|
construct.setType("com.sun.tools.javac.api.JavacTool");
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.debugging;
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,10 +26,12 @@ import org.teavm.model.MethodReference;
|
||||||
public class CallFrame {
|
public class CallFrame {
|
||||||
private SourceLocation location;
|
private SourceLocation location;
|
||||||
private MethodReference method;
|
private MethodReference method;
|
||||||
|
private Map<String, LocalVariable> variables;
|
||||||
|
|
||||||
CallFrame(SourceLocation location, MethodReference method) {
|
CallFrame(SourceLocation location, MethodReference method, Map<String, LocalVariable> variables) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
this.variables = Collections.unmodifiableMap(variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation getLocation() {
|
public SourceLocation getLocation() {
|
||||||
|
@ -37,4 +41,8 @@ public class CallFrame {
|
||||||
public MethodReference getMethod() {
|
public MethodReference getMethod() {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, LocalVariable> getVariables() {
|
||||||
|
return variables;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,14 @@ public class DebugInformation {
|
||||||
Map<String, Integer> classNameMap;
|
Map<String, Integer> classNameMap;
|
||||||
String[] methods;
|
String[] methods;
|
||||||
Map<String, Integer> methodMap;
|
Map<String, Integer> methodMap;
|
||||||
|
String[] variableNames;
|
||||||
|
Map<String, Integer> variableNameMap;
|
||||||
FileDescription[] fileDescriptions;
|
FileDescription[] fileDescriptions;
|
||||||
Mapping fileMapping;
|
Mapping fileMapping;
|
||||||
Mapping classMapping;
|
Mapping classMapping;
|
||||||
Mapping methodMapping;
|
Mapping methodMapping;
|
||||||
Mapping lineMapping;
|
Mapping lineMapping;
|
||||||
|
Mapping[] variableMappings;
|
||||||
|
|
||||||
public String[] getCoveredSourceFiles() {
|
public String[] getCoveredSourceFiles() {
|
||||||
return fileNames.clone();
|
return fileNames.clone();
|
||||||
|
@ -99,6 +102,22 @@ public class DebugInformation {
|
||||||
return getMethodAt(new GeneratedLocation(line, column));
|
return getMethodAt(new GeneratedLocation(line, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getVariableMeaningAt(int line, int column, String variable) {
|
||||||
|
return getVariableMeaningAt(new GeneratedLocation(line, column), variable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVariableMeaningAt(GeneratedLocation location, String variable) {
|
||||||
|
Integer varIndex = variableNameMap.get(variable);
|
||||||
|
if (varIndex == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Mapping mapping = variableMappings[varIndex];
|
||||||
|
if (mapping == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return componentByKey(mapping, variableNames, location);
|
||||||
|
}
|
||||||
|
|
||||||
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
|
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
|
||||||
int keyIndex = indexByKey(mapping, location);
|
int keyIndex = indexByKey(mapping, location);
|
||||||
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
|
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
|
||||||
|
@ -124,6 +143,7 @@ public class DebugInformation {
|
||||||
fileNameMap = mapArray(fileNames);
|
fileNameMap = mapArray(fileNames);
|
||||||
classNameMap = mapArray(classNames);
|
classNameMap = mapArray(classNames);
|
||||||
methodMap = mapArray(methods);
|
methodMap = mapArray(methods);
|
||||||
|
variableNameMap = mapArray(variableNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Integer> mapArray(String[] array) {
|
private Map<String, Integer> mapArray(String[] array) {
|
||||||
|
|
|
@ -30,10 +30,12 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
private MappedList files = new MappedList();
|
private MappedList files = new MappedList();
|
||||||
private MappedList classes = new MappedList();
|
private MappedList classes = new MappedList();
|
||||||
private MappedList methods = new MappedList();
|
private MappedList methods = new MappedList();
|
||||||
|
private MappedList variableNames = new MappedList();
|
||||||
private Mapping fileMapping = new Mapping();
|
private Mapping fileMapping = new Mapping();
|
||||||
private Mapping lineMapping = new Mapping();
|
private Mapping lineMapping = new Mapping();
|
||||||
private Mapping classMapping = new Mapping();
|
private Mapping classMapping = new Mapping();
|
||||||
private Mapping methodMapping = new Mapping();
|
private Mapping methodMapping = new Mapping();
|
||||||
|
private Map<Integer, Mapping> variableMappings = new HashMap<>();
|
||||||
private MethodDescriptor currentMethod;
|
private MethodDescriptor currentMethod;
|
||||||
private String currentClass;
|
private String currentClass;
|
||||||
private String currentFileName;
|
private String currentFileName;
|
||||||
|
@ -82,6 +84,18 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitVariable(String sourceName, String generatedName) {
|
||||||
|
int sourceIndex = variableNames.index(sourceName);
|
||||||
|
int generatedIndex = variableNames.index(generatedName);
|
||||||
|
Mapping mapping = variableMappings.get(generatedIndex);
|
||||||
|
if (mapping == null) {
|
||||||
|
mapping = new Mapping();
|
||||||
|
variableMappings.put(generatedIndex, mapping);
|
||||||
|
}
|
||||||
|
mapping.add(locationProvider, sourceIndex);
|
||||||
|
}
|
||||||
|
|
||||||
public DebugInformation getDebugInformation() {
|
public DebugInformation getDebugInformation() {
|
||||||
if (debugInformation == null) {
|
if (debugInformation == null) {
|
||||||
debugInformation = new DebugInformation();
|
debugInformation = new DebugInformation();
|
||||||
|
@ -92,11 +106,18 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
debugInformation.classNameMap = classes.getIndexes();
|
debugInformation.classNameMap = classes.getIndexes();
|
||||||
debugInformation.methods = methods.getItems();
|
debugInformation.methods = methods.getItems();
|
||||||
debugInformation.methodMap = methods.getIndexes();
|
debugInformation.methodMap = methods.getIndexes();
|
||||||
|
debugInformation.variableNames = variableNames.getItems();
|
||||||
|
debugInformation.variableNameMap = variableNames.getIndexes();
|
||||||
|
|
||||||
debugInformation.fileMapping = fileMapping.build();
|
debugInformation.fileMapping = fileMapping.build();
|
||||||
debugInformation.lineMapping = lineMapping.build();
|
debugInformation.lineMapping = lineMapping.build();
|
||||||
debugInformation.classMapping = classMapping.build();
|
debugInformation.classMapping = classMapping.build();
|
||||||
debugInformation.methodMapping = methodMapping.build();
|
debugInformation.methodMapping = methodMapping.build();
|
||||||
|
debugInformation.variableMappings = new DebugInformation.Mapping[variableNames.list.size()];
|
||||||
|
for (int var : variableMappings.keySet()) {
|
||||||
|
Mapping mapping = variableMappings.get(var);
|
||||||
|
debugInformation.variableMappings[var] = mapping.build();
|
||||||
|
}
|
||||||
|
|
||||||
debugInformation.rebuildFileDescriptions();
|
debugInformation.rebuildFileDescriptions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,4 +30,6 @@ public interface DebugInformationEmitter {
|
||||||
void emitMethod(MethodDescriptor method);
|
void emitMethod(MethodDescriptor method);
|
||||||
|
|
||||||
void emitClass(String className);
|
void emitClass(String className);
|
||||||
|
|
||||||
|
void emitVariable(String sourceName, String generatedName);
|
||||||
}
|
}
|
|
@ -36,15 +36,30 @@ class DebugInformationReader {
|
||||||
debugInfo.fileNames = readStrings();
|
debugInfo.fileNames = readStrings();
|
||||||
debugInfo.classNames = readStrings();
|
debugInfo.classNames = readStrings();
|
||||||
debugInfo.methods = readStrings();
|
debugInfo.methods = readStrings();
|
||||||
|
debugInfo.variableNames = readStrings();
|
||||||
debugInfo.fileMapping = readMapping();
|
debugInfo.fileMapping = readMapping();
|
||||||
debugInfo.lineMapping = readMapping();
|
debugInfo.lineMapping = readMapping();
|
||||||
debugInfo.classMapping = readMapping();
|
debugInfo.classMapping = readMapping();
|
||||||
debugInfo.methodMapping = readMapping();
|
debugInfo.methodMapping = readMapping();
|
||||||
|
debugInfo.variableMappings = readVariableMappings(debugInfo.variableNames.length);
|
||||||
debugInfo.rebuildFileDescriptions();
|
debugInfo.rebuildFileDescriptions();
|
||||||
debugInfo.rebuildMaps();
|
debugInfo.rebuildMaps();
|
||||||
return debugInfo;
|
return debugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DebugInformation.Mapping[] readVariableMappings(int count) throws IOException {
|
||||||
|
DebugInformation.Mapping[] mappings = new DebugInformation.Mapping[count];
|
||||||
|
int varCount = readUnsignedNumber();
|
||||||
|
while (varCount-- > 0) {
|
||||||
|
int lastVar = 0;
|
||||||
|
for (int i = 0; i < mappings.length; ++i) {
|
||||||
|
lastVar += readUnsignedNumber();
|
||||||
|
mappings[lastVar] = readMapping();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mappings;
|
||||||
|
}
|
||||||
|
|
||||||
private int processSign(int number) {
|
private int processSign(int number) {
|
||||||
boolean negative = (number & 1) != 0;
|
boolean negative = (number & 1) != 0;
|
||||||
number >>>= 1;
|
number >>>= 1;
|
||||||
|
|
|
@ -34,11 +34,37 @@ class DebugInformationWriter {
|
||||||
writeStringArray(debugInfo.fileNames);
|
writeStringArray(debugInfo.fileNames);
|
||||||
writeStringArray(debugInfo.classNames);
|
writeStringArray(debugInfo.classNames);
|
||||||
writeStringArray(debugInfo.methods);
|
writeStringArray(debugInfo.methods);
|
||||||
|
writeStringArray(debugInfo.variableNames);
|
||||||
|
|
||||||
writeMapping(debugInfo.fileMapping);
|
writeMapping(debugInfo.fileMapping);
|
||||||
writeMapping(debugInfo.lineMapping);
|
writeMapping(debugInfo.lineMapping);
|
||||||
writeMapping(debugInfo.classMapping);
|
writeMapping(debugInfo.classMapping);
|
||||||
writeMapping(debugInfo.methodMapping);
|
writeMapping(debugInfo.methodMapping);
|
||||||
|
writeUnsignedNumber(nonNullVariableMappings(debugInfo));
|
||||||
|
writeVariableMappings(debugInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeVariableMappings(DebugInformation debugInfo) throws IOException {
|
||||||
|
int lastVar = 0;
|
||||||
|
for (int i = 0; i < debugInfo.variableMappings.length; ++i) {
|
||||||
|
DebugInformation.Mapping mapping = debugInfo.variableMappings[i];
|
||||||
|
if (mapping == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
writeUnsignedNumber(i - lastVar);
|
||||||
|
lastVar = i;
|
||||||
|
writeMapping(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nonNullVariableMappings(DebugInformation debugInfo) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < debugInfo.variableMappings.length; ++i) {
|
||||||
|
if (debugInfo.variableMappings[i] != null) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeStringArray(String[] array) throws IOException {
|
private void writeStringArray(String[] array) throws IOException {
|
||||||
|
|
|
@ -186,7 +186,7 @@ public class Debugger {
|
||||||
MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation().getLine(),
|
MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation().getLine(),
|
||||||
jsFrame.getLocation().getColumn()) : null;
|
jsFrame.getLocation().getColumn()) : null;
|
||||||
if (!empty || !wasEmpty) {
|
if (!empty || !wasEmpty) {
|
||||||
frames.add(new CallFrame(loc, method));
|
frames.add(new CallFrame(loc, method, new HashMap<String, LocalVariable>()));
|
||||||
}
|
}
|
||||||
wasEmpty = empty;
|
wasEmpty = empty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,10 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter {
|
||||||
public void emitClass(String className) {
|
public void emitClass(String className) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void emitVariable(String sourceName, String generatedName) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLocationProvider(LocationProvider locationProvider) {
|
public void setLocationProvider(LocationProvider locationProvider) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.debugging;
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface JavaScriptCallFrame {
|
public interface JavaScriptCallFrame {
|
||||||
JavaScriptLocation getLocation();
|
JavaScriptLocation getLocation();
|
||||||
|
|
||||||
|
Map<String, JavaScriptVariable> getVariables();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public interface JavaScriptValue {
|
||||||
|
String getRepresentation();
|
||||||
|
|
||||||
|
Map<String, JavaScriptVariable> getProperties();
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public interface JavaScriptVariable {
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
JavaScriptValue getValue();
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class LocalVariable {
|
||||||
|
private String name;
|
||||||
|
private WatchedValue value;
|
||||||
|
|
||||||
|
LocalVariable(String name, WatchedValue value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WatchedValue getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public abstract class WatchedValue {
|
||||||
|
public abstract String getRepresentation();
|
||||||
|
|
||||||
|
public abstract Map<String, LocalVariable> getProperties();
|
||||||
|
}
|
|
@ -268,6 +268,11 @@ public class Decompiler {
|
||||||
Optimizer optimizer = new Optimizer();
|
Optimizer optimizer = new Optimizer();
|
||||||
optimizer.optimize(methodNode, method.getProgram());
|
optimizer.optimize(methodNode, method.getProgram());
|
||||||
methodNode.getModifiers().addAll(mapModifiers(method.getModifiers()));
|
methodNode.getModifiers().addAll(mapModifiers(method.getModifiers()));
|
||||||
|
int paramCount = method.getSignature().length;
|
||||||
|
for (int i = 0; i < paramCount; ++i) {
|
||||||
|
Variable var = program.variableAt(i);
|
||||||
|
methodNode.getParameterDebugNames().add(var.getDebugName());
|
||||||
|
}
|
||||||
return methodNode;
|
return methodNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class NullPointerExceptionTransformer implements ClassHolderTransformer {
|
||||||
}
|
}
|
||||||
NullCheckInstruction nullCheck = new NullCheckInstruction();
|
NullCheckInstruction nullCheck = new NullCheckInstruction();
|
||||||
nullCheck.setValue(invoke.getInstance());
|
nullCheck.setValue(invoke.getInstance());
|
||||||
Variable var = block.getProgram().createVariable();
|
Variable var = block.getProgram().createVariable(null);
|
||||||
nullCheck.setReceiver(var);
|
nullCheck.setReceiver(var);
|
||||||
invoke.setInstance(var);
|
invoke.setInstance(var);
|
||||||
block.getInstructions().add(i++, nullCheck);
|
block.getInstructions().add(i++, nullCheck);
|
||||||
|
|
|
@ -518,6 +518,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
public void visit(RegularMethodNode method) {
|
public void visit(RegularMethodNode method) {
|
||||||
try {
|
try {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
|
for (int i = 0; i < method.getParameterDebugNames().size(); ++i) {
|
||||||
|
debugEmitter.emitVariable(method.getParameterDebugNames().get(i), variableName(i));
|
||||||
|
}
|
||||||
int variableCount = 0;
|
int variableCount = 0;
|
||||||
for (int var : method.getVariables()) {
|
for (int var : method.getVariables()) {
|
||||||
variableCount = Math.max(variableCount, var + 1);
|
variableCount = Math.max(variableCount, var + 1);
|
||||||
|
@ -601,6 +604,10 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
if (statement.getLocation() != null) {
|
if (statement.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
if (statement.getLeftValue() instanceof VariableExpr) {
|
||||||
|
VariableExpr receiver = (VariableExpr)statement.getLeftValue();
|
||||||
|
debugEmitter.emitVariable(statement.getDebugName(), variableName(receiver.getIndex()));
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO error occured", e);
|
throw new RenderingException("IO error occured", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,44 +48,44 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void visit(ClassConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void visit(NullConstantInstruction insn) {
|
||||||
assign(Expr.constant(null), insn.getReceiver().getIndex());
|
assign(Expr.constant(null), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void visit(LongConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void visit(FloatConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StringConstantInstruction insn) {
|
public void visit(StringConstantInstruction insn) {
|
||||||
assign(Expr.constant(insn.getConstant()), insn.getReceiver().getIndex());
|
assign(Expr.constant(insn.getConstant()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryInstruction insn) {
|
public void visit(BinaryInstruction insn) {
|
||||||
int first = insn.getFirstOperand().getIndex();
|
int first = insn.getFirstOperand().getIndex();
|
||||||
int second = insn.getSecondOperand().getIndex();
|
int second = insn.getSecondOperand().getIndex();
|
||||||
int result = insn.getReceiver().getIndex();
|
Variable result = insn.getReceiver();
|
||||||
switch (insn.getOperation()) {
|
switch (insn.getOperation()) {
|
||||||
case ADD:
|
case ADD:
|
||||||
switch (insn.getOperandType()) {
|
switch (insn.getOperandType()) {
|
||||||
|
@ -227,15 +227,15 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
switch (insn.getOperandType()) {
|
switch (insn.getOperandType()) {
|
||||||
case INT:
|
case INT:
|
||||||
assign(castToInteger(Expr.unary(UnaryOperation.NEGATE, Expr.var(insn.getOperand().getIndex()))),
|
assign(castToInteger(Expr.unary(UnaryOperation.NEGATE, Expr.var(insn.getOperand().getIndex()))),
|
||||||
insn.getReceiver().getIndex());
|
insn.getReceiver());
|
||||||
break;
|
break;
|
||||||
case LONG:
|
case LONG:
|
||||||
assign(Expr.unary(UnaryOperation.NEGATE_LONG, Expr.var(insn.getOperand().getIndex())),
|
assign(Expr.unary(UnaryOperation.NEGATE_LONG, Expr.var(insn.getOperand().getIndex())),
|
||||||
insn.getReceiver().getIndex());
|
insn.getReceiver());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assign(Expr.unary(UnaryOperation.NEGATE, Expr.var(insn.getOperand().getIndex())),
|
assign(Expr.unary(UnaryOperation.NEGATE, Expr.var(insn.getOperand().getIndex())),
|
||||||
insn.getReceiver().getIndex());
|
insn.getReceiver());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,13 +244,14 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
public void visit(AssignInstruction insn) {
|
public void visit(AssignInstruction insn) {
|
||||||
AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()),
|
AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()),
|
||||||
Expr.var(insn.getAssignee().getIndex()));
|
Expr.var(insn.getAssignee().getIndex()));
|
||||||
|
stmt.setDebugName(insn.getReceiver().getDebugName());
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastInstruction insn) {
|
public void visit(CastInstruction insn) {
|
||||||
assign(Expr.var(insn.getValue().getIndex()), insn.getReceiver().getIndex());
|
assign(Expr.var(insn.getValue().getIndex()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -292,7 +293,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assign(value, insn.getReceiver().getIndex());
|
assign(value, insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -323,7 +324,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assign(value, insn.getReceiver().getIndex());
|
assign(value, insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -459,13 +460,12 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
assign(Expr.createArray(insn.getItemType(), Expr.var(insn.getSize().getIndex())),
|
assign(Expr.createArray(insn.getItemType(), Expr.var(insn.getSize().getIndex())), insn.getReceiver());
|
||||||
insn.getReceiver().getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructInstruction insn) {
|
public void visit(ConstructInstruction insn) {
|
||||||
assign(Expr.createObject(insn.getType()), insn.getReceiver().getIndex());
|
assign(Expr.createObject(insn.getType()), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -474,7 +474,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
for (int i = 0; i < dimensionExprs.length; ++i) {
|
for (int i = 0; i < dimensionExprs.length; ++i) {
|
||||||
dimensionExprs[i] = Expr.var(insn.getDimensions().get(i).getIndex());
|
dimensionExprs[i] = Expr.var(insn.getDimensions().get(i).getIndex());
|
||||||
}
|
}
|
||||||
assign(Expr.createArray(insn.getItemType(), dimensionExprs), insn.getReceiver().getIndex());
|
assign(Expr.createArray(insn.getItemType(), dimensionExprs), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -509,28 +509,27 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
assign(Expr.unary(UnaryOperation.LENGTH, Expr.var(insn.getArray().getIndex())), insn.getReceiver().getIndex());
|
assign(Expr.unary(UnaryOperation.LENGTH, Expr.var(insn.getArray().getIndex())), insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayInstruction insn) {
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
UnwrapArrayExpr unwrapExpr = new UnwrapArrayExpr(insn.getElementType());
|
UnwrapArrayExpr unwrapExpr = new UnwrapArrayExpr(insn.getElementType());
|
||||||
unwrapExpr.setArray(Expr.var(insn.getArray().getIndex()));
|
unwrapExpr.setArray(Expr.var(insn.getArray().getIndex()));
|
||||||
assign(unwrapExpr, insn.getReceiver().getIndex());
|
assign(unwrapExpr, insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CloneArrayInstruction insn) {
|
public void visit(CloneArrayInstruction insn) {
|
||||||
MethodDescriptor cloneMethodDesc = new MethodDescriptor("clone", ValueType.object("java.lang.Object"));
|
MethodDescriptor cloneMethodDesc = new MethodDescriptor("clone", ValueType.object("java.lang.Object"));
|
||||||
MethodReference cloneMethod = new MethodReference("java.lang.Object", cloneMethodDesc);
|
MethodReference cloneMethod = new MethodReference("java.lang.Object", cloneMethodDesc);
|
||||||
assign(Expr.invoke(cloneMethod, Expr.var(insn.getArray().getIndex()), new Expr[0]),
|
assign(Expr.invoke(cloneMethod, Expr.var(insn.getArray().getIndex()), new Expr[0]), insn.getReceiver());
|
||||||
insn.getReceiver().getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(GetElementInstruction insn) {
|
public void visit(GetElementInstruction insn) {
|
||||||
assign(Expr.subscript(Expr.var(insn.getArray().getIndex()), Expr.var(insn.getIndex().getIndex())),
|
assign(Expr.subscript(Expr.var(insn.getArray().getIndex()), Expr.var(insn.getIndex().getIndex())),
|
||||||
insn.getReceiver().getIndex());
|
insn.getReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -559,7 +558,7 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
invocationExpr = Expr.invokeStatic(insn.getMethod(), exprArgs);
|
invocationExpr = Expr.invokeStatic(insn.getMethod(), exprArgs);
|
||||||
}
|
}
|
||||||
if (insn.getReceiver() != null) {
|
if (insn.getReceiver() != null) {
|
||||||
assign(invocationExpr, insn.getReceiver().getIndex());
|
assign(invocationExpr, insn.getReceiver());
|
||||||
} else {
|
} else {
|
||||||
AssignmentStatement stmt = Statement.assign(null, invocationExpr);
|
AssignmentStatement stmt = Statement.assign(null, invocationExpr);
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
|
@ -569,13 +568,13 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void visit(IsInstanceInstruction insn) {
|
||||||
assign(Expr.instanceOf(Expr.var(insn.getValue().getIndex()), insn.getType()),
|
assign(Expr.instanceOf(Expr.var(insn.getValue().getIndex()), insn.getType()), insn.getReceiver());
|
||||||
insn.getReceiver().getIndex());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assign(Expr source, int target) {
|
private void assign(Expr source, Variable target) {
|
||||||
AssignmentStatement stmt = Statement.assign(Expr.var(target), source);
|
AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source);
|
||||||
stmt.setLocation(currentLocation);
|
stmt.setLocation(currentLocation);
|
||||||
|
stmt.setDebugName(target.getDebugName());
|
||||||
statements.add(stmt);
|
statements.add(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,11 +598,11 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
return Expr.unary(UnaryOperation.LONG_TO_NUM, value);
|
return Expr.unary(UnaryOperation.LONG_TO_NUM, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void binary(int first, int second, int result, BinaryOperation op) {
|
private void binary(int first, int second, Variable result, BinaryOperation op) {
|
||||||
assign(Expr.binary(op, Expr.var(first), Expr.var(second)), result);
|
assign(Expr.binary(op, Expr.var(first), Expr.var(second)), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void intBinary(int first, int second, int result, BinaryOperation op) {
|
private void intBinary(int first, int second, Variable result, BinaryOperation op) {
|
||||||
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result);
|
assign(castToInteger(Expr.binary(op, Expr.var(first), Expr.var(second))), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,7 +656,6 @@ class StatementGenerator implements InstructionVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void visit(NullCheckInstruction insn) {
|
||||||
assign(Expr.unary(UnaryOperation.NULL_CHECK, Expr.var(insn.getValue().getIndex())),
|
assign(Expr.unary(UnaryOperation.NULL_CHECK, Expr.var(insn.getValue().getIndex())), insn.getReceiver());
|
||||||
insn.getReceiver().getIndex());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class AssignmentStatement extends Statement {
|
||||||
private Expr leftValue;
|
private Expr leftValue;
|
||||||
private Expr rightValue;
|
private Expr rightValue;
|
||||||
private NodeLocation location;
|
private NodeLocation location;
|
||||||
|
private String debugName;
|
||||||
|
|
||||||
public Expr getLeftValue() {
|
public Expr getLeftValue() {
|
||||||
return leftValue;
|
return leftValue;
|
||||||
|
@ -48,6 +49,14 @@ public class AssignmentStatement extends Statement {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDebugName() {
|
||||||
|
return debugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugName(String debugName) {
|
||||||
|
this.debugName = debugName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(StatementVisitor visitor) {
|
public void acceptVisitor(StatementVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.model.MethodReference;
|
||||||
public class RegularMethodNode extends MethodNode {
|
public class RegularMethodNode extends MethodNode {
|
||||||
private Statement body;
|
private Statement body;
|
||||||
private List<Integer> variables = new ArrayList<>();
|
private List<Integer> variables = new ArrayList<>();
|
||||||
|
private List<String> parameterDebugNames = new ArrayList<>();
|
||||||
|
|
||||||
public RegularMethodNode(MethodReference reference) {
|
public RegularMethodNode(MethodReference reference) {
|
||||||
super(reference);
|
super(reference);
|
||||||
|
@ -43,6 +44,10 @@ public class RegularMethodNode extends MethodNode {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getParameterDebugNames() {
|
||||||
|
return parameterDebugNames;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptVisitor(MethodNodeVisitor visitor) {
|
public void acceptVisitor(MethodNodeVisitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
|
|
|
@ -35,8 +35,8 @@ public class Program implements ProgramReader {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Variable createVariable() {
|
public Variable createVariable(String debugName) {
|
||||||
Variable variable = new Variable(this);
|
Variable variable = new Variable(this, debugName);
|
||||||
variable.setIndex(variables.size());
|
variable.setIndex(variables.size());
|
||||||
variables.add(variable);
|
variables.add(variable);
|
||||||
variable.setRegister(lastUsedRegister++);
|
variable.setRegister(lastUsedRegister++);
|
||||||
|
|
|
@ -23,9 +23,11 @@ public class Variable implements VariableReader {
|
||||||
private Program program;
|
private Program program;
|
||||||
private int index;
|
private int index;
|
||||||
private int register;
|
private int register;
|
||||||
|
private String debugName;
|
||||||
|
|
||||||
Variable(Program program) {
|
Variable(Program program, String debugName) {
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
this.debugName = debugName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,4 +56,13 @@ public class Variable implements VariableReader {
|
||||||
public void setRegister(int register) {
|
public void setRegister(int register) {
|
||||||
this.register = register;
|
this.register = register;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDebugName() {
|
||||||
|
return debugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugName(String debugName) {
|
||||||
|
this.debugName = debugName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,7 @@ public interface VariableReader {
|
||||||
|
|
||||||
ProgramReader getProgram();
|
ProgramReader getProgram();
|
||||||
|
|
||||||
|
String getDebugName();
|
||||||
|
|
||||||
int getRegister();
|
int getRegister();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public final class ProgramUtils {
|
||||||
InstructionCopyReader insnCopier = new InstructionCopyReader();
|
InstructionCopyReader insnCopier = new InstructionCopyReader();
|
||||||
insnCopier.programCopy = copy;
|
insnCopier.programCopy = copy;
|
||||||
for (int i = 0; i < program.variableCount(); ++i) {
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
copy.createVariable();
|
copy.createVariable(program.variableAt(i).getDebugName());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
copy.createBasicBlock();
|
copy.createBasicBlock();
|
||||||
|
|
|
@ -97,7 +97,7 @@ public class RegisterAllocator {
|
||||||
final Phi phi = incoming.getPhi();
|
final Phi phi = incoming.getPhi();
|
||||||
Program program = phi.getBasicBlock().getProgram();
|
Program program = phi.getBasicBlock().getProgram();
|
||||||
AssignInstruction copyInstruction = new AssignInstruction();
|
AssignInstruction copyInstruction = new AssignInstruction();
|
||||||
Variable firstCopy = program.createVariable();
|
Variable firstCopy = program.createVariable(incoming.getValue().getDebugName());
|
||||||
copyInstruction.setReceiver(firstCopy);
|
copyInstruction.setReceiver(firstCopy);
|
||||||
copyInstruction.setAssignee(incoming.getValue());
|
copyInstruction.setAssignee(incoming.getValue());
|
||||||
BasicBlock source = blockMap.get(incoming.getSource());
|
BasicBlock source = blockMap.get(incoming.getSource());
|
||||||
|
|
|
@ -179,7 +179,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
phi.getIncomings().remove(j--);
|
phi.getIncomings().remove(j--);
|
||||||
if (preheaderPhi == null) {
|
if (preheaderPhi == null) {
|
||||||
preheaderPhi = new Phi();
|
preheaderPhi = new Phi();
|
||||||
preheaderPhi.setReceiver(program.createVariable());
|
preheaderPhi.setReceiver(program.createVariable(null));
|
||||||
preheader.getPhis().add(preheaderPhi);
|
preheader.getPhis().add(preheaderPhi);
|
||||||
}
|
}
|
||||||
preheaderPhi.getIncomings().add(incoming);
|
preheaderPhi.getIncomings().add(incoming);
|
||||||
|
@ -391,7 +391,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void visit(ClassConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
ClassConstantInstruction copy = new ClassConstantInstruction();
|
ClassConstantInstruction copy = new ClassConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
@ -400,7 +400,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void visit(NullConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
NullConstantInstruction copy = new NullConstantInstruction();
|
NullConstantInstruction copy = new NullConstantInstruction();
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
this.copy = copy;
|
this.copy = copy;
|
||||||
|
@ -408,7 +408,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
IntegerConstantInstruction copy = new IntegerConstantInstruction();
|
IntegerConstantInstruction copy = new IntegerConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
@ -417,7 +417,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void visit(LongConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
LongConstantInstruction copy = new LongConstantInstruction();
|
LongConstantInstruction copy = new LongConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
@ -426,7 +426,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void visit(FloatConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
FloatConstantInstruction copy = new FloatConstantInstruction();
|
FloatConstantInstruction copy = new FloatConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
@ -435,7 +435,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
DoubleConstantInstruction copy = new DoubleConstantInstruction();
|
DoubleConstantInstruction copy = new DoubleConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
@ -444,7 +444,7 @@ public class LoopInvariantMotion implements MethodOptimization {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StringConstantInstruction insn) {
|
public void visit(StringConstantInstruction insn) {
|
||||||
var = program.createVariable();
|
var = program.createVariable(insn.getReceiver().getDebugName());
|
||||||
StringConstantInstruction copy = new StringConstantInstruction();
|
StringConstantInstruction copy = new StringConstantInstruction();
|
||||||
copy.setConstant(insn.getConstant());
|
copy.setConstant(insn.getConstant());
|
||||||
copy.setReceiver(var);
|
copy.setReceiver(var);
|
||||||
|
|
|
@ -40,11 +40,11 @@ public final class Parser {
|
||||||
Program program = programParser.parse(node, className);
|
Program program = programParser.parse(node, className);
|
||||||
new UnreachableBasicBlockEliminator().optimize(program);
|
new UnreachableBasicBlockEliminator().optimize(program);
|
||||||
SSATransformer ssaProducer = new SSATransformer();
|
SSATransformer ssaProducer = new SSATransformer();
|
||||||
ssaProducer.transformToSSA(program, method.getParameterTypes());
|
ssaProducer.transformToSSA(program, programParser, method.getParameterTypes());
|
||||||
method.setProgram(program);
|
method.setProgram(program);
|
||||||
parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
|
parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
|
||||||
while (program.variableCount() <= method.parameterCount()) {
|
while (program.variableCount() <= method.parameterCount()) {
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
}
|
}
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,14 @@ import org.objectweb.asm.*;
|
||||||
import org.objectweb.asm.tree.*;
|
import org.objectweb.asm.tree.*;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.instructions.*;
|
import org.teavm.model.instructions.*;
|
||||||
|
import org.teavm.model.util.DefinitionExtractor;
|
||||||
import org.teavm.model.util.InstructionTransitionExtractor;
|
import org.teavm.model.util.InstructionTransitionExtractor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class ProgramParser {
|
public class ProgramParser implements VariableDebugInformation {
|
||||||
static final byte ROOT = 0;
|
static final byte ROOT = 0;
|
||||||
static final byte SINGLE = 1;
|
static final byte SINGLE = 1;
|
||||||
static final byte DOUBLE_FIRST_HALF = 2;
|
static final byte DOUBLE_FIRST_HALF = 2;
|
||||||
|
@ -48,6 +49,9 @@ public class ProgramParser {
|
||||||
private int currentLineNumber;
|
private int currentLineNumber;
|
||||||
private boolean lineNumberChanged;
|
private boolean lineNumberChanged;
|
||||||
private InstructionLocation lastInsnLocation;
|
private InstructionLocation lastInsnLocation;
|
||||||
|
private Map<Integer, List<LocalVariableNode>> localVariableMap = new HashMap<>();
|
||||||
|
private Map<Instruction, String> variableDebugNames = new HashMap<>();
|
||||||
|
private Map<Integer, String> parameterNames = new HashMap<>();
|
||||||
|
|
||||||
private static class Step {
|
private static class Step {
|
||||||
public final int source;
|
public final int source;
|
||||||
|
@ -113,11 +117,29 @@ public class ProgramParser {
|
||||||
}
|
}
|
||||||
int signatureVars = countSignatureVariables(method.desc);
|
int signatureVars = countSignatureVariables(method.desc);
|
||||||
while (program.variableCount() <= signatureVars) {
|
while (program.variableCount() <= signatureVars) {
|
||||||
program.createVariable();
|
program.createVariable(getVariableDebugName(program.variableCount(), 0));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < signatureVars; ++i) {
|
||||||
|
parameterNames.put(i, getVariableDebugName(i, 0));
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getVariableDebugName(int var, int location) {
|
||||||
|
List<LocalVariableNode> nodes = localVariableMap.get(var);
|
||||||
|
if (nodes == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (LocalVariableNode node : nodes) {
|
||||||
|
int start = labelIndexes.get(node.start.getLabel());
|
||||||
|
int end = labelIndexes.get(node.end.getLabel());
|
||||||
|
if (location >= start && location < end) {
|
||||||
|
return node.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private int countSignatureVariables(String desc) {
|
private int countSignatureVariables(String desc) {
|
||||||
int count = 1;
|
int count = 1;
|
||||||
for (Type paramType : Type.getArgumentTypes(desc)) {
|
for (Type paramType : Type.getArgumentTypes(desc)) {
|
||||||
|
@ -159,6 +181,16 @@ public class ProgramParser {
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDefinitionDebugName(Instruction insn) {
|
||||||
|
return variableDebugNames.get(insn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParameterDebugName(int index) {
|
||||||
|
return parameterNames.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
private void prepare(MethodNode method) {
|
private void prepare(MethodNode method) {
|
||||||
InsnList instructions = method.instructions;
|
InsnList instructions = method.instructions;
|
||||||
minLocal = 0;
|
minLocal = 0;
|
||||||
|
@ -177,6 +209,14 @@ public class ProgramParser {
|
||||||
lineNumbers.put(lineNumberNode.start.getLabel(), lineNumberNode.line);
|
lineNumbers.put(lineNumberNode.start.getLabel(), lineNumberNode.line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (LocalVariableNode localVar : method.localVariables) {
|
||||||
|
List<LocalVariableNode> vars = localVariableMap.get(localVar.index);
|
||||||
|
if (vars == null) {
|
||||||
|
vars = new ArrayList<>();
|
||||||
|
localVariableMap.put(localVar.index, vars);
|
||||||
|
}
|
||||||
|
vars.add(localVar);
|
||||||
|
}
|
||||||
targetInstructions = new ArrayList<>(instructions.size());
|
targetInstructions = new ArrayList<>(instructions.size());
|
||||||
targetInstructions.addAll(Collections.<List<Instruction>>nCopies(instructions.size(), null));
|
targetInstructions.addAll(Collections.<List<Instruction>>nCopies(instructions.size(), null));
|
||||||
basicBlocks.addAll(Collections.<BasicBlock>nCopies(instructions.size(), null));
|
basicBlocks.addAll(Collections.<BasicBlock>nCopies(instructions.size(), null));
|
||||||
|
@ -250,6 +290,20 @@ public class ProgramParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assemble() {
|
private void assemble() {
|
||||||
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
|
for (int i = 0; i < targetInstructions.size(); ++i) {
|
||||||
|
List<Instruction> instructionList = targetInstructions.get(i);
|
||||||
|
for (Instruction insn : instructionList) {
|
||||||
|
insn.acceptVisitor(defExtractor);
|
||||||
|
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||||
|
String debugName = getVariableDebugName(var.getIndex(), i);
|
||||||
|
if (debugName != null) {
|
||||||
|
variableDebugNames.put(insn, debugName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BasicBlock basicBlock = null;
|
BasicBlock basicBlock = null;
|
||||||
for (int i = 0; i < basicBlocks.size(); ++i) {
|
for (int i = 0; i < basicBlocks.size(); ++i) {
|
||||||
BasicBlock newBasicBlock = basicBlocks.get(i);
|
BasicBlock newBasicBlock = basicBlocks.get(i);
|
||||||
|
@ -300,7 +354,7 @@ public class ProgramParser {
|
||||||
|
|
||||||
private Variable getVariable(int index) {
|
private Variable getVariable(int index) {
|
||||||
while (index >= program.variableCount()) {
|
while (index >= program.variableCount()) {
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
}
|
}
|
||||||
return program.variableAt(index);
|
return program.variableAt(index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,14 @@ public class SSATransformer {
|
||||||
private Phi[][] phiMap;
|
private Phi[][] phiMap;
|
||||||
private int[][] phiIndexMap;
|
private int[][] phiIndexMap;
|
||||||
private ValueType[] arguments;
|
private ValueType[] arguments;
|
||||||
|
private VariableDebugInformation variableDebugInfo;
|
||||||
|
|
||||||
public void transformToSSA(Program program, ValueType[] arguments) {
|
public void transformToSSA(Program program, VariableDebugInformation variableDebugInfo, ValueType[] arguments) {
|
||||||
if (program.basicBlockCount() == 0) {
|
if (program.basicBlockCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
this.variableDebugInfo = variableDebugInfo;
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
cfg = ProgramUtils.buildControlFlowGraphWithoutTryCatch(program);
|
cfg = ProgramUtils.buildControlFlowGraphWithoutTryCatch(program);
|
||||||
domTree = GraphUtils.buildDominatorTree(cfg);
|
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
|
@ -55,6 +57,9 @@ public class SSATransformer {
|
||||||
phiMap[i] = new Phi[program.variableCount()];
|
phiMap[i] = new Phi[program.variableCount()];
|
||||||
phiIndexMap[i] = new int[program.variableCount()];
|
phiIndexMap[i] = new int[program.variableCount()];
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < program.variableCount(); ++i) {
|
||||||
|
program.variableAt(i).setDebugName(variableDebugInfo.getParameterDebugName(i));
|
||||||
|
}
|
||||||
applySignature();
|
applySignature();
|
||||||
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
|
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
|
||||||
estimatePhis();
|
estimatePhis();
|
||||||
|
@ -136,16 +141,17 @@ public class SSATransformer {
|
||||||
processed[currentBlock.getIndex()] = true;
|
processed[currentBlock.getIndex()] = true;
|
||||||
variableMap = Arrays.copyOf(task.variables, task.variables.length);
|
variableMap = Arrays.copyOf(task.variables, task.variables.length);
|
||||||
for (Phi phi : currentBlock.getPhis()) {
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable(phi.getReceiver().getDebugName());
|
||||||
variableMap[phi.getReceiver().getIndex()] = var;
|
variableMap[phi.getReceiver().getIndex()] = var;
|
||||||
phi.setReceiver(var);
|
phi.setReceiver(var);
|
||||||
}
|
}
|
||||||
if (!caughtBlocks.get(currentBlock.getIndex()).isEmpty()) {
|
if (!caughtBlocks.get(currentBlock.getIndex()).isEmpty()) {
|
||||||
Phi phi = new Phi();
|
Phi phi = new Phi();
|
||||||
phi.setReceiver(program.createVariable());
|
phi.setReceiver(program.createVariable(null));
|
||||||
for (TryCatchBlock tryCatch : caughtBlocks.get(currentBlock.getIndex())) {
|
for (TryCatchBlock tryCatch : caughtBlocks.get(currentBlock.getIndex())) {
|
||||||
variableMap[tryCatch.getExceptionVariable().getIndex()] = phi.getReceiver();
|
variableMap[tryCatch.getExceptionVariable().getIndex()] = phi.getReceiver();
|
||||||
tryCatch.setExceptionVariable(program.createVariable());
|
tryCatch.setExceptionVariable(program.createVariable(
|
||||||
|
tryCatch.getExceptionVariable().getDebugName()));
|
||||||
Incoming incoming = new Incoming();
|
Incoming incoming = new Incoming();
|
||||||
incoming.setSource(tryCatch.getProtectedBlock());
|
incoming.setSource(tryCatch.getProtectedBlock());
|
||||||
incoming.setValue(tryCatch.getExceptionVariable());
|
incoming.setValue(tryCatch.getExceptionVariable());
|
||||||
|
@ -210,8 +216,8 @@ public class SSATransformer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable define(Variable var) {
|
private Variable define(Variable var, String debugName) {
|
||||||
Variable result = program.createVariable();
|
Variable result = program.createVariable(debugName);
|
||||||
variableMap[var.getIndex()] = result;
|
variableMap[var.getIndex()] = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -231,56 +237,56 @@ public class SSATransformer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ClassConstantInstruction insn) {
|
public void visit(ClassConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullConstantInstruction insn) {
|
public void visit(NullConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IntegerConstantInstruction insn) {
|
public void visit(IntegerConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(LongConstantInstruction insn) {
|
public void visit(LongConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(FloatConstantInstruction insn) {
|
public void visit(FloatConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(DoubleConstantInstruction insn) {
|
public void visit(DoubleConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(StringConstantInstruction insn) {
|
public void visit(StringConstantInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(BinaryInstruction insn) {
|
public void visit(BinaryInstruction insn) {
|
||||||
insn.setFirstOperand(use(insn.getFirstOperand()));
|
insn.setFirstOperand(use(insn.getFirstOperand()));
|
||||||
insn.setSecondOperand(use(insn.getSecondOperand()));
|
insn.setSecondOperand(use(insn.getSecondOperand()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(NegateInstruction insn) {
|
public void visit(NegateInstruction insn) {
|
||||||
insn.setOperand(use(insn.getOperand()));
|
insn.setOperand(use(insn.getOperand()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(AssignInstruction insn) {
|
public void visit(AssignInstruction insn) {
|
||||||
insn.setAssignee(use(insn.getAssignee()));
|
insn.setAssignee(use(insn.getAssignee()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -318,12 +324,12 @@ public class SSATransformer {
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructArrayInstruction insn) {
|
public void visit(ConstructArrayInstruction insn) {
|
||||||
insn.setSize(use(insn.getSize()));
|
insn.setSize(use(insn.getSize()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ConstructInstruction insn) {
|
public void visit(ConstructInstruction insn) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -332,7 +338,7 @@ public class SSATransformer {
|
||||||
for (int i = 0; i < dimensions.size(); ++i) {
|
for (int i = 0; i < dimensions.size(); ++i) {
|
||||||
dimensions.set(i, use(dimensions.get(i)));
|
dimensions.set(i, use(dimensions.get(i)));
|
||||||
}
|
}
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -340,7 +346,7 @@ public class SSATransformer {
|
||||||
if (insn.getInstance() != null) {
|
if (insn.getInstance() != null) {
|
||||||
insn.setInstance(use(insn.getInstance()));
|
insn.setInstance(use(insn.getInstance()));
|
||||||
}
|
}
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -355,7 +361,7 @@ public class SSATransformer {
|
||||||
public void visit(GetElementInstruction insn) {
|
public void visit(GetElementInstruction insn) {
|
||||||
insn.setArray(use(insn.getArray()));
|
insn.setArray(use(insn.getArray()));
|
||||||
insn.setIndex(use(insn.getIndex()));
|
insn.setIndex(use(insn.getIndex()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -375,50 +381,50 @@ public class SSATransformer {
|
||||||
insn.setInstance(use(insn.getInstance()));
|
insn.setInstance(use(insn.getInstance()));
|
||||||
}
|
}
|
||||||
if (insn.getReceiver() != null) {
|
if (insn.getReceiver() != null) {
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(IsInstanceInstruction insn) {
|
public void visit(IsInstanceInstruction insn) {
|
||||||
insn.setValue(use(insn.getValue()));
|
insn.setValue(use(insn.getValue()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastInstruction insn) {
|
public void visit(CastInstruction insn) {
|
||||||
insn.setValue(use(insn.getValue()));
|
insn.setValue(use(insn.getValue()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastNumberInstruction insn) {
|
public void visit(CastNumberInstruction insn) {
|
||||||
insn.setValue(use(insn.getValue()));
|
insn.setValue(use(insn.getValue()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CastIntegerInstruction insn) {
|
public void visit(CastIntegerInstruction insn) {
|
||||||
insn.setValue(use(insn.getValue()));
|
insn.setValue(use(insn.getValue()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(ArrayLengthInstruction insn) {
|
public void visit(ArrayLengthInstruction insn) {
|
||||||
insn.setArray(use(insn.getArray()));
|
insn.setArray(use(insn.getArray()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(UnwrapArrayInstruction insn) {
|
public void visit(UnwrapArrayInstruction insn) {
|
||||||
insn.setArray(use(insn.getArray()));
|
insn.setArray(use(insn.getArray()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(CloneArrayInstruction insn) {
|
public void visit(CloneArrayInstruction insn) {
|
||||||
insn.setArray(use(insn.getArray()));
|
insn.setArray(use(insn.getArray()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,7 +434,7 @@ public class SSATransformer {
|
||||||
@Override
|
@Override
|
||||||
public void visit(NullCheckInstruction insn) {
|
public void visit(NullCheckInstruction insn) {
|
||||||
insn.setValue(use(insn.getValue()));
|
insn.setValue(use(insn.getValue()));
|
||||||
insn.setReceiver(define(insn.getReceiver()));
|
insn.setReceiver(define(insn.getReceiver(), variableDebugInfo.getDefinitionDebugName(insn)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.teavm.parsing;
|
||||||
|
|
||||||
|
import org.teavm.model.Instruction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public interface VariableDebugInformation {
|
||||||
|
String getDefinitionDebugName(Instruction insn);
|
||||||
|
|
||||||
|
String getParameterDebugName(int index);
|
||||||
|
}
|
|
@ -44,13 +44,13 @@ public class JCLHacks implements ClassHolderTransformer {
|
||||||
MethodHolder method = new MethodHolder(desc);
|
MethodHolder method = new MethodHolder(desc);
|
||||||
Program program = new Program();
|
Program program = new Program();
|
||||||
for (int i = 0; i < desc.parameterCount(); ++i) {
|
for (int i = 0; i < desc.parameterCount(); ++i) {
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
}
|
}
|
||||||
if (!staticMethod) {
|
if (!staticMethod) {
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
}
|
}
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable(null);
|
||||||
BasicBlock block = program.createBasicBlock();
|
BasicBlock block = program.createBasicBlock();
|
||||||
ConstructInstruction cons = new ConstructInstruction();
|
ConstructInstruction cons = new ConstructInstruction();
|
||||||
cons.setType("java.lang.SecurityException");
|
cons.setType("java.lang.SecurityException");
|
||||||
|
@ -75,8 +75,8 @@ public class JCLHacks implements ClassHolderTransformer {
|
||||||
private MethodHolder createThreadSleep() {
|
private MethodHolder createThreadSleep() {
|
||||||
MethodHolder method = new MethodHolder("sleep", ValueType.LONG, ValueType.VOID);
|
MethodHolder method = new MethodHolder("sleep", ValueType.LONG, ValueType.VOID);
|
||||||
Program program = new Program();
|
Program program = new Program();
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
program.createVariable();
|
program.createVariable(null);
|
||||||
BasicBlock block = program.createBasicBlock();
|
BasicBlock block = program.createBasicBlock();
|
||||||
ExitInstruction exit = new ExitInstruction();
|
ExitInstruction exit = new ExitInstruction();
|
||||||
block.getInstructions().add(exit);
|
block.getInstructions().add(exit);
|
||||||
|
|
|
@ -81,7 +81,7 @@ class JavascriptNativeProcessor {
|
||||||
if (isProperGetter(method.getDescriptor())) {
|
if (isProperGetter(method.getDescriptor())) {
|
||||||
String propertyName = method.getName().charAt(0) == 'i' ? cutPrefix(method.getName(), 2) :
|
String propertyName = method.getName().charAt(0) == 'i' ? cutPrefix(method.getName(), 2) :
|
||||||
cutPrefix(method.getName(), 3);
|
cutPrefix(method.getName(), 3);
|
||||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
Variable result = invoke.getReceiver() != null ? program.createVariable(null) : null;
|
||||||
addPropertyGet(propertyName, invoke.getInstance(), result);
|
addPropertyGet(propertyName, invoke.getInstance(), result);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
result = unwrap(result, method.getResultType());
|
result = unwrap(result, method.getResultType());
|
||||||
|
@ -96,7 +96,7 @@ class JavascriptNativeProcessor {
|
||||||
}
|
}
|
||||||
} else if (method.getAnnotations().get(JSIndexer.class.getName()) != null) {
|
} else if (method.getAnnotations().get(JSIndexer.class.getName()) != null) {
|
||||||
if (isProperGetIndexer(method.getDescriptor())) {
|
if (isProperGetIndexer(method.getDescriptor())) {
|
||||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
Variable result = invoke.getReceiver() != null ? program.createVariable(null) : null;
|
||||||
addIndexerGet(invoke.getInstance(), wrap(invoke.getArguments().get(0),
|
addIndexerGet(invoke.getInstance(), wrap(invoke.getArguments().get(0),
|
||||||
method.parameterType(0)), result);
|
method.parameterType(0)), result);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
@ -143,7 +143,7 @@ class JavascriptNativeProcessor {
|
||||||
"a proper native JavaScript method or constructor declaration");
|
"a proper native JavaScript method or constructor declaration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
Variable result = invoke.getReceiver() != null ? program.createVariable(null) : null;
|
||||||
InvokeInstruction newInvoke = new InvokeInstruction();
|
InvokeInstruction newInvoke = new InvokeInstruction();
|
||||||
ValueType[] signature = new ValueType[method.parameterCount() + 3];
|
ValueType[] signature = new ValueType[method.parameterCount() + 3];
|
||||||
Arrays.fill(signature, ValueType.object(JSObject.class.getName()));
|
Arrays.fill(signature, ValueType.object(JSObject.class.getName()));
|
||||||
|
@ -226,7 +226,7 @@ class JavascriptNativeProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable addString(String str) {
|
private Variable addString(String str) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable(null);
|
||||||
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
||||||
nameInsn.setReceiver(var);
|
nameInsn.setReceiver(var);
|
||||||
nameInsn.setConstant(str);
|
nameInsn.setConstant(str);
|
||||||
|
@ -261,7 +261,7 @@ class JavascriptNativeProcessor {
|
||||||
} else if (className.equals("java.lang.String")) {
|
} else if (className.equals("java.lang.String")) {
|
||||||
return unwrap(var, "unwrapString", ValueType.object("java.lang.String"));
|
return unwrap(var, "unwrapString", ValueType.object("java.lang.String"));
|
||||||
} else {
|
} else {
|
||||||
Variable result = program.createVariable();
|
Variable result = program.createVariable(null);
|
||||||
CastInstruction castInsn = new CastInstruction();
|
CastInstruction castInsn = new CastInstruction();
|
||||||
castInsn.setReceiver(result);
|
castInsn.setReceiver(result);
|
||||||
castInsn.setValue(var);
|
castInsn.setValue(var);
|
||||||
|
@ -274,7 +274,7 @@ class JavascriptNativeProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable unwrap(Variable var, String methodName, ValueType resultType) {
|
private Variable unwrap(Variable var, String methodName, ValueType resultType) {
|
||||||
Variable result = program.createVariable();
|
Variable result = program.createVariable(null);
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setMethod(new MethodReference(JS.class.getName(), methodName, ValueType.object(JSObject.class.getName()),
|
insn.setMethod(new MethodReference(JS.class.getName(), methodName, ValueType.object(JSObject.class.getName()),
|
||||||
resultType));
|
resultType));
|
||||||
|
@ -301,7 +301,7 @@ class JavascriptNativeProcessor {
|
||||||
throw new RuntimeException("Wrong functor: " + type.getName());
|
throw new RuntimeException("Wrong functor: " + type.getName());
|
||||||
}
|
}
|
||||||
String name = type.getMethods().iterator().next().getName();
|
String name = type.getMethods().iterator().next().getName();
|
||||||
Variable functor = program.createVariable();
|
Variable functor = program.createVariable(null);
|
||||||
Variable nameVar = addStringWrap(addString(name));
|
Variable nameVar = addStringWrap(addString(name));
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setMethod(new MethodReference(JS.class.getName(), "function",
|
insn.setMethod(new MethodReference(JS.class.getName(), "function",
|
||||||
|
@ -321,7 +321,7 @@ class JavascriptNativeProcessor {
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Variable result = program.createVariable();
|
Variable result = program.createVariable(null);
|
||||||
InvokeInstruction insn = new InvokeInstruction();
|
InvokeInstruction insn = new InvokeInstruction();
|
||||||
insn.setMethod(new MethodReference(JS.class.getName(), "wrap", type,
|
insn.setMethod(new MethodReference(JS.class.getName(), "wrap", type,
|
||||||
ValueType.object(JSObject.class.getName())));
|
ValueType.object(JSObject.class.getName())));
|
||||||
|
|
|
@ -131,7 +131,7 @@ class ResourceProgramTransformer {
|
||||||
} else if (type instanceof ValueType.Object) {
|
} else if (type instanceof ValueType.Object) {
|
||||||
switch (((ValueType.Object)type).getClassName()) {
|
switch (((ValueType.Object)type).getClassName()) {
|
||||||
case "java.lang.String": {
|
case "java.lang.String": {
|
||||||
Variable resultVar = insn.getProgram().createVariable();
|
Variable resultVar = insn.getProgram().createVariable(null);
|
||||||
getProperty(insn, property, instructions, resultVar);
|
getProperty(insn, property, instructions, resultVar);
|
||||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||||
castInvoke.setType(InvocationType.SPECIAL);
|
castInvoke.setType(InvocationType.SPECIAL);
|
||||||
|
@ -143,7 +143,7 @@ class ResourceProgramTransformer {
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
Variable resultVar = insn.getProgram().createVariable();
|
Variable resultVar = insn.getProgram().createVariable(null);
|
||||||
getProperty(insn, property, instructions, resultVar);
|
getProperty(insn, property, instructions, resultVar);
|
||||||
CastInstruction castInsn = new CastInstruction();
|
CastInstruction castInsn = new CastInstruction();
|
||||||
castInsn.setReceiver(insn.getReceiver());
|
castInsn.setReceiver(insn.getReceiver());
|
||||||
|
@ -159,7 +159,7 @@ class ResourceProgramTransformer {
|
||||||
|
|
||||||
private void getProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
private void getProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
||||||
Variable resultVar) {
|
Variable resultVar) {
|
||||||
Variable nameVar = program.createVariable();
|
Variable nameVar = program.createVariable(null);
|
||||||
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
||||||
nameInsn.setConstant(property);
|
nameInsn.setConstant(property);
|
||||||
nameInsn.setReceiver(nameVar);
|
nameInsn.setReceiver(nameVar);
|
||||||
|
@ -176,7 +176,7 @@ class ResourceProgramTransformer {
|
||||||
|
|
||||||
private void getAndCastProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
private void getAndCastProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
||||||
Class<?> primitive) {
|
Class<?> primitive) {
|
||||||
Variable resultVar = program.createVariable();
|
Variable resultVar = program.createVariable(null);
|
||||||
getProperty(insn, property, instructions, resultVar);
|
getProperty(insn, property, instructions, resultVar);
|
||||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||||
castInvoke.setType(InvocationType.SPECIAL);
|
castInvoke.setType(InvocationType.SPECIAL);
|
||||||
|
@ -220,7 +220,7 @@ class ResourceProgramTransformer {
|
||||||
} else if (type instanceof ValueType.Object) {
|
} else if (type instanceof ValueType.Object) {
|
||||||
switch (((ValueType.Object)type).getClassName()) {
|
switch (((ValueType.Object)type).getClassName()) {
|
||||||
case "java.lang.String": {
|
case "java.lang.String": {
|
||||||
Variable castVar = insn.getProgram().createVariable();
|
Variable castVar = insn.getProgram().createVariable(null);
|
||||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||||
castInvoke.setType(InvocationType.SPECIAL);
|
castInvoke.setType(InvocationType.SPECIAL);
|
||||||
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castFromString",
|
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castFromString",
|
||||||
|
@ -242,7 +242,7 @@ class ResourceProgramTransformer {
|
||||||
|
|
||||||
private void setProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
private void setProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
||||||
Variable valueVar) {
|
Variable valueVar) {
|
||||||
Variable nameVar = program.createVariable();
|
Variable nameVar = program.createVariable(null);
|
||||||
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
||||||
nameInsn.setConstant(property);
|
nameInsn.setConstant(property);
|
||||||
nameInsn.setReceiver(nameVar);
|
nameInsn.setReceiver(nameVar);
|
||||||
|
@ -259,7 +259,7 @@ class ResourceProgramTransformer {
|
||||||
|
|
||||||
private void castAndSetProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
private void castAndSetProperty(InvokeInstruction insn, String property, List<Instruction> instructions,
|
||||||
Class<?> primitive) {
|
Class<?> primitive) {
|
||||||
Variable castVar = program.createVariable();
|
Variable castVar = program.createVariable(null);
|
||||||
InvokeInstruction castInvoke = new InvokeInstruction();
|
InvokeInstruction castInvoke = new InvokeInstruction();
|
||||||
castInvoke.setType(InvocationType.SPECIAL);
|
castInvoke.setType(InvocationType.SPECIAL);
|
||||||
String primitiveCapitalized = primitive.getName();
|
String primitiveCapitalized = primitive.getName();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user