mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #1104 from ethereum/fixmemcosts
Fix memory resize costs during call
This commit is contained in:
		
						commit
						212e016091
					
				| @ -2,6 +2,8 @@ | ||||
| 
 | ||||
|  * Code Generator: Fix library functions being called from payable functions. | ||||
|  * Type Checker: Fixed a crash about invalid array types. | ||||
|  * Code Generator: Fixed a call gas bug that became visible after | ||||
|    version 0.4.0 for calls where the output is larger than the input. | ||||
| 
 | ||||
| ### 0.4.1 (2016-09-09) | ||||
| 
 | ||||
|  | ||||
| @ -1476,6 +1476,18 @@ void ExpressionCompiler::appendExternalFunctionCall( | ||||
| 		utils().storeFreeMemoryPointer(); | ||||
| 	} | ||||
| 
 | ||||
| 	// Touch the end of the output area so that we do not pay for memory resize during the call
 | ||||
| 	// (which we would have to subtract from the gas left)
 | ||||
| 	// We could also just use MLOAD; POP right before the gas calculation, but the optimizer
 | ||||
| 	// would remove that, so we use MSTORE here.
 | ||||
| 	if (!_functionType.gasSet() && retSize > 0) | ||||
| 	{ | ||||
| 		m_context << u256(0); | ||||
| 		utils().fetchFreeMemoryPointer(); | ||||
| 		// This touches too much, but that way we save some rounding arithmetics
 | ||||
| 		m_context << u256(retSize) << Instruction::ADD << Instruction::MSTORE; | ||||
| 	} | ||||
| 
 | ||||
| 	// Copy function identifier to memory.
 | ||||
| 	utils().fetchFreeMemoryPointer(); | ||||
| 	if (!_functionType.isBareCall() || manualFunctionId) | ||||
| @ -1551,10 +1563,7 @@ void ExpressionCompiler::appendExternalFunctionCall( | ||||
| 			gasNeededByCaller += eth::GasCosts::callValueTransferGas; | ||||
| 		if (!isCallCode && !isDelegateCall && !existenceChecked) | ||||
| 			gasNeededByCaller += eth::GasCosts::callNewAccountGas; // we never know
 | ||||
| 		m_context << | ||||
| 			gasNeededByCaller << | ||||
| 			Instruction::GAS << | ||||
| 			Instruction::SUB; | ||||
| 		m_context << gasNeededByCaller << Instruction::GAS << Instruction::SUB; | ||||
| 	} | ||||
| 	if (isDelegateCall) | ||||
| 		m_context << Instruction::DELEGATECALL; | ||||
|  | ||||
| @ -7203,6 +7203,33 @@ BOOST_AUTO_TEST_CASE(no_nonpayable_circumvention_by_modifier) | ||||
| 	BOOST_CHECK_EQUAL(balanceAt(m_contractAddress), 0); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) | ||||
| { | ||||
| 	// This tests that memory resize for return values is not paid during the call, which would
 | ||||
| 	// make the gas calculation overly complex. We access the end of the output area before
 | ||||
| 	// the call is made.
 | ||||
| 	// Tests that this also survives the optimizer.
 | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract C { | ||||
| 			function f() returns (uint[200]) {} | ||||
| 		} | ||||
| 		contract D { | ||||
| 			function f(C c) returns (uint) { c.f(); return 7; } | ||||
| 		} | ||||
| 	)"; | ||||
| 
 | ||||
| 	compileAndRun(sourceCode, 0, "C"); | ||||
| 	u160 cAddr = m_contractAddress; | ||||
| 	compileAndRun(sourceCode, 0, "D"); | ||||
| 	BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); | ||||
| 
 | ||||
| 	m_optimize = true; | ||||
| 
 | ||||
| 	compileAndRun(sourceCode, 0, "C"); | ||||
| 	u160 cAddrOpt = m_contractAddress; | ||||
| 	compileAndRun(sourceCode, 0, "D"); | ||||
| 	BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7))); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user