Add CALLSTATELESS - POST queue and no fee for zero size memory increase
This commit is contained in:
parent
70479bdd02
commit
57f9db3969
|
@ -17,10 +17,8 @@ public class MessageCall {
|
||||||
|
|
||||||
/** gas to pay for the call, remaining gas will be refunded to the caller */
|
/** gas to pay for the call, remaining gas will be refunded to the caller */
|
||||||
private DataWord gas;
|
private DataWord gas;
|
||||||
/** address to call */
|
/** address of account which code to call */
|
||||||
private DataWord toAddress;
|
private DataWord codeAddress;
|
||||||
/** address of the storage to use */
|
|
||||||
private DataWord storageAddress;
|
|
||||||
/** the value that can be transfer along with the code execution */
|
/** the value that can be transfer along with the code execution */
|
||||||
private DataWord endowment;
|
private DataWord endowment;
|
||||||
/** start of memory to be input data to the call */
|
/** start of memory to be input data to the call */
|
||||||
|
@ -32,23 +30,20 @@ public class MessageCall {
|
||||||
/** size of memory to be output data to the call */
|
/** size of memory to be output data to the call */
|
||||||
private DataWord outDataSize;
|
private DataWord outDataSize;
|
||||||
|
|
||||||
public MessageCall(MsgType type, DataWord gas, DataWord toAddress,
|
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
|
||||||
DataWord storageAddress, DataWord endowment,
|
DataWord endowment, DataWord inDataOffs, DataWord inDataSize) {
|
||||||
DataWord inDataOffs, DataWord inDataSize) {
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.gas = gas;
|
this.gas = gas;
|
||||||
this.toAddress = toAddress;
|
this.codeAddress = codeAddress;
|
||||||
this.storageAddress = (type == MsgType.STATELESS) ? storageAddress: toAddress;
|
|
||||||
this.endowment = endowment;
|
this.endowment = endowment;
|
||||||
this.inDataOffs = inDataOffs;
|
this.inDataOffs = inDataOffs;
|
||||||
this.inDataSize = inDataSize;
|
this.inDataSize = inDataSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageCall(MsgType type, DataWord gas, DataWord toAddress,
|
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
|
||||||
DataWord storageAddress, DataWord endowment,
|
DataWord endowment, DataWord inDataOffs, DataWord inDataSize,
|
||||||
DataWord inDataOffs, DataWord inDataSize, DataWord outDataOffs,
|
DataWord outDataOffs, DataWord outDataSize) {
|
||||||
DataWord outDataSize) {
|
this(type, gas, codeAddress, endowment, inDataOffs, inDataSize);
|
||||||
this(type, gas, toAddress, storageAddress, endowment, inDataOffs, inDataSize);
|
|
||||||
this.outDataOffs = outDataOffs;
|
this.outDataOffs = outDataOffs;
|
||||||
this.outDataSize = outDataSize;
|
this.outDataSize = outDataSize;
|
||||||
}
|
}
|
||||||
|
@ -61,12 +56,8 @@ public class MessageCall {
|
||||||
return gas;
|
return gas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataWord getToAddress() {
|
public DataWord getCodeAddress() {
|
||||||
return toAddress;
|
return codeAddress;
|
||||||
}
|
|
||||||
|
|
||||||
public DataWord getStorageAddress() {
|
|
||||||
return storageAddress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataWord getEndowment() {
|
public DataWord getEndowment() {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.ethereum.db.ContractDetails;
|
||||||
import org.ethereum.facade.Repository;
|
import org.ethereum.facade.Repository;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
import org.ethereum.util.Utils;
|
import org.ethereum.util.Utils;
|
||||||
|
import org.ethereum.vm.MessageCall.MsgType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
@ -17,6 +18,7 @@ import java.util.Collections;
|
||||||
import java.util.EmptyStackException;
|
import java.util.EmptyStackException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,7 +33,13 @@ public class Program {
|
||||||
private int invokeHash;
|
private int invokeHash;
|
||||||
private ProgramListener listener;
|
private ProgramListener listener;
|
||||||
|
|
||||||
private static LinkedList<MessageCall> postQueue = new LinkedList<>();
|
/**
|
||||||
|
* Instead of immediately executing a POST message call,
|
||||||
|
* it is added to a post-queue, to be executed after everything else
|
||||||
|
* (including prior-created posts) within the scope
|
||||||
|
* of that transaction execution is executed.
|
||||||
|
*/
|
||||||
|
private static Queue<MessageCall> messageQueue = new LinkedList<>();
|
||||||
|
|
||||||
Stack<DataWord> stack = new Stack<>();
|
Stack<DataWord> stack = new Stack<>();
|
||||||
ByteBuffer memory = null;
|
ByteBuffer memory = null;
|
||||||
|
@ -239,8 +247,9 @@ public class Program {
|
||||||
*/
|
*/
|
||||||
protected void allocateMemory(int offset, int size) {
|
protected void allocateMemory(int offset, int size) {
|
||||||
|
|
||||||
int memSize = memory != null ? memory.limit(): 0;
|
int memSize = memory != null ? memory.limit() : 0;
|
||||||
double newMemSize = Math.max(memSize, Math.ceil((double)(offset + size) / 32) * 32);
|
double newMemSize = Math.max(memSize, size != 0 ?
|
||||||
|
Math.ceil((double) (offset + size) / 32) * 32 : 0);
|
||||||
ByteBuffer tmpMem = ByteBuffer.allocate((int)newMemSize);
|
ByteBuffer tmpMem = ByteBuffer.allocate((int)newMemSize);
|
||||||
if (memory != null)
|
if (memory != null)
|
||||||
tmpMem.put(memory.array(), 0, memory.limit());
|
tmpMem.put(memory.array(), 0, memory.limit());
|
||||||
|
@ -344,47 +353,40 @@ public class Program {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public Queue<MessageCall> getMessageQueue() {
|
||||||
* Instead of immediately executing a message call, it is
|
return messageQueue;
|
||||||
* added to a post-queue, to be executed after everything else
|
|
||||||
* (including prior-created posts) within the scope
|
|
||||||
* of that transaction execution is executed.
|
|
||||||
*
|
|
||||||
* @param msg is the message call object
|
|
||||||
*/
|
|
||||||
public void queue(MessageCall msg) {
|
|
||||||
postQueue.push(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That method is for internal code invocations
|
* That method is for internal code invocations
|
||||||
*
|
*
|
||||||
|
* - Normal calls invoke a specified contract which updates itself
|
||||||
|
* - Stateless calls invoke another contract, within the context of the caller
|
||||||
|
*
|
||||||
* @param msg is the message call object
|
* @param msg is the message call object
|
||||||
*/
|
*/
|
||||||
public void callToAddress(MessageCall msg) {
|
public void callToAddress(MessageCall msg) {
|
||||||
|
|
||||||
// TODO: update code for CALLSTATELESS
|
|
||||||
|
|
||||||
ByteBuffer data = memoryChunk(msg.getInDataOffs(), msg.getInDataSize());
|
ByteBuffer data = memoryChunk(msg.getInDataOffs(), msg.getInDataSize());
|
||||||
|
|
||||||
// FETCH THE SAVED STORAGE
|
// FETCH THE SAVED STORAGE
|
||||||
byte[] toAddress = msg.getToAddress().getLast20Bytes();
|
byte[] codeAddress = msg.getCodeAddress().getLast20Bytes();
|
||||||
|
byte[] senderAddress = this.getOwnerAddress().getLast20Bytes();
|
||||||
|
byte[] contextAddress = msg.getType() == MsgType.STATELESS ? senderAddress : codeAddress;
|
||||||
|
|
||||||
// FETCH THE CODE
|
// FETCH THE CODE
|
||||||
byte[] programCode = this.result.getRepository().getCode(toAddress);
|
byte[] programCode = this.result.getRepository().getCode(codeAddress);
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
if (logger.isInfoEnabled())
|
||||||
logger.info("calling for existing contract: address: [ {} ], outDataOffs: [ {} ], outDataSize: [ {} ] ",
|
logger.info(msg.getType().name() + " for existing contract: address: [ {} ], outDataOffs: [ {} ], outDataSize: [ {} ] ",
|
||||||
Hex.toHexString(toAddress), msg.getOutDataOffs().longValue(), msg.getOutDataSize().longValue());
|
Hex.toHexString(contextAddress), msg.getOutDataOffs().longValue(), msg.getOutDataSize().longValue());
|
||||||
|
|
||||||
byte[] senderAddress = this.getOwnerAddress().getLast20Bytes();
|
|
||||||
|
|
||||||
// 2.1 PERFORM THE GAS VALUE TX
|
// 2.1 PERFORM THE GAS VALUE TX
|
||||||
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
// (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION)
|
||||||
if (this.getGas().longValue() - msg.getGas().longValue() < 0 ) {
|
if (this.getGas().longValue() - msg.getGas().longValue() < 0 ) {
|
||||||
logger.info("No gas for the internal call, \n" +
|
logger.info("No gas for the internal call, \n" +
|
||||||
"fromAddress={}, toAddress={}",
|
"fromAddress={}, codeAddress={}",
|
||||||
Hex.toHexString(senderAddress), Hex.toHexString(toAddress));
|
Hex.toHexString(senderAddress), Hex.toHexString(contextAddress));
|
||||||
this.stackPushZero();
|
this.stackPushZero();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -403,7 +405,7 @@ public class Program {
|
||||||
stackPushOne();
|
stackPushOne();
|
||||||
|
|
||||||
this.getResult().addCallCreate(data.array(),
|
this.getResult().addCallCreate(data.array(),
|
||||||
msg.getToAddress().getLast20Bytes(),
|
msg.getCodeAddress().getLast20Bytes(),
|
||||||
msg.getGas().getNoLeadZeroesData(),
|
msg.getGas().getNoLeadZeroesData(),
|
||||||
msg.getEndowment().getNoLeadZeroesData());
|
msg.getEndowment().getNoLeadZeroesData());
|
||||||
|
|
||||||
|
@ -415,11 +417,11 @@ public class Program {
|
||||||
|
|
||||||
Repository trackRepository = result.getRepository().getTrack();
|
Repository trackRepository = result.getRepository().getTrack();
|
||||||
trackRepository.startTracking();
|
trackRepository.startTracking();
|
||||||
trackRepository.addBalance(toAddress, msg.getEndowment().value());
|
trackRepository.addBalance(contextAddress, msg.getEndowment().value());
|
||||||
|
|
||||||
ProgramInvoke programInvoke =
|
ProgramInvoke programInvoke =
|
||||||
ProgramInvokeFactory.createProgramInvoke(this, msg.getToAddress(),
|
ProgramInvokeFactory.createProgramInvoke(this, msg.getCodeAddress(),
|
||||||
msg.getEndowment(), msg.getGas(), result.getRepository().getBalance(toAddress),
|
msg.getEndowment(), msg.getGas(), result.getRepository().getBalance(contextAddress),
|
||||||
data.array(),
|
data.array(),
|
||||||
trackRepository, this.invokeData.getCallDeep() + 1);
|
trackRepository, this.invokeData.getCallDeep() + 1);
|
||||||
|
|
||||||
|
@ -436,7 +438,7 @@ public class Program {
|
||||||
if (result != null &&
|
if (result != null &&
|
||||||
result.getException() != null &&
|
result.getException() != null &&
|
||||||
result.getException() instanceof Program.OutOfGasException) {
|
result.getException() instanceof Program.OutOfGasException) {
|
||||||
logger.info("contract run halted by OutOfGas: contract={}" , Hex.toHexString(toAddress));
|
logger.info("contract run halted by OutOfGas: contract={}" , Hex.toHexString(contextAddress));
|
||||||
|
|
||||||
trackRepository.rollback();
|
trackRepository.rollback();
|
||||||
stackPushZero();
|
stackPushZero();
|
||||||
|
|
|
@ -98,14 +98,13 @@ public class VM {
|
||||||
break;
|
break;
|
||||||
case SSTORE:
|
case SSTORE:
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
// for gas calculations [YP 9.2]
|
|
||||||
DataWord newValue = stack.get(stack.size()-2);
|
DataWord newValue = stack.get(stack.size()-2);
|
||||||
DataWord oldValue = program.storageLoad(stack.peek());
|
DataWord oldValue = program.storageLoad(stack.peek());
|
||||||
if (oldValue == null && !newValue.isZero()) {
|
if (oldValue == null && !newValue.isZero())
|
||||||
gasCost = GasCost.SSTORE * 2;
|
gasCost = GasCost.SSTORE * 2;
|
||||||
} else if (oldValue != null && newValue.isZero()) {
|
else if (oldValue != null && newValue.isZero())
|
||||||
gasCost = GasCost.SSTORE * 0;
|
gasCost = GasCost.SSTORE * 0;
|
||||||
} else
|
else
|
||||||
gasCost = GasCost.SSTORE;
|
gasCost = GasCost.SSTORE;
|
||||||
break;
|
break;
|
||||||
case SLOAD:
|
case SLOAD:
|
||||||
|
@ -118,36 +117,36 @@ public class VM {
|
||||||
// These all operate on memory and therefore potentially expand it:
|
// These all operate on memory and therefore potentially expand it:
|
||||||
case MSTORE:
|
case MSTORE:
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
newMemSize = stack.peek().value().add(BigInteger.valueOf(32));
|
newMemSize = memNeeded(stack.peek(), new DataWord(32));
|
||||||
break;
|
break;
|
||||||
case MSTORE8:
|
case MSTORE8:
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
newMemSize = stack.peek().value().add(BigInteger.ONE);
|
newMemSize = memNeeded(stack.peek(), new DataWord(1));
|
||||||
break;
|
break;
|
||||||
case MLOAD:
|
case MLOAD:
|
||||||
program.stackRequire(1);
|
program.stackRequire(1);
|
||||||
newMemSize = stack.peek().value().add(BigInteger.valueOf(32));
|
newMemSize = memNeeded(stack.peek(), new DataWord(32));
|
||||||
break;
|
break;
|
||||||
case RETURN:
|
case RETURN:
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
newMemSize = stack.peek().value().add(stack.get(stack.size()-2).value());
|
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-2));
|
||||||
break;
|
break;
|
||||||
case SHA3:
|
case SHA3:
|
||||||
program.stackRequire(2);
|
program.stackRequire(2);
|
||||||
gasCost = GasCost.SHA3;
|
gasCost = GasCost.SHA3;
|
||||||
newMemSize = stack.peek().value().add(stack.get(stack.size()-2).value());
|
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-2));
|
||||||
break;
|
break;
|
||||||
case CALLDATACOPY:
|
case CALLDATACOPY:
|
||||||
program.stackRequire(3);
|
program.stackRequire(3);
|
||||||
newMemSize = stack.peek().value().add(stack.get(stack.size()-3).value());
|
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-3));
|
||||||
break;
|
break;
|
||||||
case CODECOPY:
|
case CODECOPY:
|
||||||
program.stackRequire(3);
|
program.stackRequire(3);
|
||||||
newMemSize = stack.peek().value().add(stack.get(stack.size()-3).value());
|
newMemSize = memNeeded(stack.peek(), stack.get(stack.size()-3));
|
||||||
break;
|
break;
|
||||||
case EXTCODECOPY:
|
case EXTCODECOPY:
|
||||||
program.stackRequire(4);
|
program.stackRequire(4);
|
||||||
newMemSize = stack.get(stack.size()-2).value().add(stack.get(stack.size()-4).value());
|
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-4));
|
||||||
break;
|
break;
|
||||||
case CALL: case CALLSTATELESS:
|
case CALL: case CALLSTATELESS:
|
||||||
program.stackRequire(7);
|
program.stackRequire(7);
|
||||||
|
@ -157,9 +156,9 @@ public class VM {
|
||||||
throw program.new OutOfGasException();
|
throw program.new OutOfGasException();
|
||||||
}
|
}
|
||||||
callGas = callGasWord.longValue();
|
callGas = callGasWord.longValue();
|
||||||
BigInteger x = stack.get(stack.size()-4).value().add(stack.get(stack.size()-5).value()); // in offset+size
|
BigInteger in = memNeeded(stack.get(stack.size()-4), stack.get(stack.size()-5)); // in offset+size
|
||||||
BigInteger y = stack.get(stack.size()-6).value().add(stack.get(stack.size()-7).value()); // out offset+size
|
BigInteger out = memNeeded(stack.get(stack.size()-6), stack.get(stack.size()-7)); // out offset+size
|
||||||
newMemSize = x.max(y);
|
newMemSize = in.max(out);
|
||||||
break;
|
break;
|
||||||
case POST:
|
case POST:
|
||||||
program.stackRequire(5);
|
program.stackRequire(5);
|
||||||
|
@ -168,7 +167,7 @@ public class VM {
|
||||||
case CREATE:
|
case CREATE:
|
||||||
program.stackRequire(3);
|
program.stackRequire(3);
|
||||||
gasCost = GasCost.CREATE;
|
gasCost = GasCost.CREATE;
|
||||||
newMemSize = stack.get(stack.size()-2).value().add(stack.get(stack.size()-3).value());
|
newMemSize = memNeeded(stack.get(stack.size()-2), stack.get(stack.size()-3));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -877,7 +876,7 @@ public class VM {
|
||||||
} break;
|
} break;
|
||||||
case CALL: case CALLSTATELESS: {
|
case CALL: case CALLSTATELESS: {
|
||||||
DataWord gas = program.stackPop();
|
DataWord gas = program.stackPop();
|
||||||
DataWord toAddress = program.stackPop();
|
DataWord codeAddress = program.stackPop();
|
||||||
DataWord value = program.stackPop();
|
DataWord value = program.stackPop();
|
||||||
|
|
||||||
DataWord inDataOffs = program.stackPop();
|
DataWord inDataOffs = program.stackPop();
|
||||||
|
@ -887,7 +886,7 @@ public class VM {
|
||||||
DataWord outDataSize = program.stackPop();
|
DataWord outDataSize = program.stackPop();
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
hint = "addr: " + Hex.toHexString(toAddress.getLast20Bytes())
|
hint = "addr: " + Hex.toHexString(codeAddress.getLast20Bytes())
|
||||||
+ " gas: " + gas.shortHex()
|
+ " gas: " + gas.shortHex()
|
||||||
+ " inOff: " + inDataOffs.shortHex()
|
+ " inOff: " + inDataOffs.shortHex()
|
||||||
+ " inSize: " + inDataSize.shortHex();
|
+ " inSize: " + inDataSize.shortHex();
|
||||||
|
@ -899,8 +898,8 @@ public class VM {
|
||||||
|
|
||||||
MessageCall msg = new MessageCall(
|
MessageCall msg = new MessageCall(
|
||||||
op.equals(CALL) ? MsgType.CALL : MsgType.STATELESS,
|
op.equals(CALL) ? MsgType.CALL : MsgType.STATELESS,
|
||||||
gas, toAddress, program.getOwnerAddress(), value,
|
gas, codeAddress, value, inDataOffs, inDataSize,
|
||||||
inDataOffs, inDataSize, outDataOffs, outDataSize);
|
outDataOffs, outDataSize);
|
||||||
program.callToAddress(msg);
|
program.callToAddress(msg);
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
|
@ -908,14 +907,14 @@ public class VM {
|
||||||
case POST:{
|
case POST:{
|
||||||
program.stackRequire(5);
|
program.stackRequire(5);
|
||||||
DataWord gas = program.stackPop();
|
DataWord gas = program.stackPop();
|
||||||
DataWord toAddress = program.stackPop();
|
DataWord codeAddress= program.stackPop();
|
||||||
DataWord value = program.stackPop();
|
DataWord value = program.stackPop();
|
||||||
|
|
||||||
DataWord inDataOffs = program.stackPop();
|
DataWord inDataOffs = program.stackPop();
|
||||||
DataWord inDataSize = program.stackPop();
|
DataWord inDataSize = program.stackPop();
|
||||||
|
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
hint = "addr: " + Hex.toHexString(toAddress.getLast20Bytes())
|
hint = "addr: " + Hex.toHexString(codeAddress.getLast20Bytes())
|
||||||
+ " gas: " + gas.shortHex()
|
+ " gas: " + gas.shortHex()
|
||||||
+ " inOff: " + inDataOffs.shortHex()
|
+ " inOff: " + inDataOffs.shortHex()
|
||||||
+ " inSize: " + inDataSize.shortHex();
|
+ " inSize: " + inDataSize.shortHex();
|
||||||
|
@ -925,9 +924,9 @@ public class VM {
|
||||||
program.invokeData.getCallDeep(), hint);
|
program.invokeData.getCallDeep(), hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageCall msgCall = new MessageCall(MsgType.POST, gas, toAddress,
|
MessageCall msgCall = new MessageCall(MsgType.POST, gas,
|
||||||
program.getOwnerAddress(), value, inDataOffs, inDataSize);
|
codeAddress, value, inDataOffs, inDataSize);
|
||||||
program.queue(msgCall);
|
program.getMessageQueue().add(msgCall);
|
||||||
|
|
||||||
program.step();
|
program.step();
|
||||||
} break;
|
} break;
|
||||||
|
@ -997,6 +996,20 @@ public class VM {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to calculate new total memory size needed for an operation.
|
||||||
|
* <br/> Basically just offset + size, unless size is 0, in which case the result is also 0.
|
||||||
|
*
|
||||||
|
* @param offset starting position of the memory
|
||||||
|
* @param size number of bytes needed
|
||||||
|
* @return offset + size, unless size is 0. In that case memNeeded is also 0.
|
||||||
|
*/
|
||||||
|
private BigInteger memNeeded(DataWord offset, DataWord size) {
|
||||||
|
if (size.isZero())
|
||||||
|
return BigInteger.ZERO;
|
||||||
|
return offset.value().add(size.value());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dumping the VM state at the current operation in various styles
|
* Dumping the VM state at the current operation in various styles
|
||||||
* - standard Not Yet Implemented
|
* - standard Not Yet Implemented
|
||||||
|
|
|
@ -148,7 +148,7 @@ public class ProgramMemoryTest {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
program.memory = memory;
|
program.memory = memory;
|
||||||
program.allocateMemory(offset, size);
|
program.allocateMemory(offset, size);
|
||||||
assertEquals(96, program.getMemSize());
|
assertEquals(64, program.getMemSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************/
|
/************************************************/
|
||||||
|
@ -162,7 +162,7 @@ public class ProgramMemoryTest {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
program.memory = memory;
|
program.memory = memory;
|
||||||
program.allocateMemory(offset, size);
|
program.allocateMemory(offset, size);
|
||||||
assertEquals(32, program.getMemSize());
|
assertEquals(0, program.getMemSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue