| 344 | } |
| 345 | |
| 346 | void ArrayUtils::clearArray(ArrayType const& _typeIn) const |
| 347 | { |
| 348 | Type const* type = &_typeIn; |
| 349 | m_context.callLowLevelFunction( |
| 350 | "$clearArray_" + _typeIn.identifier(), |
| 351 | 2, |
| 352 | 0, |
| 353 | [type](CompilerContext& _context) |
| 354 | { |
| 355 | ArrayType const& _type = dynamic_cast<ArrayType const&>(*type); |
| 356 | unsigned stackHeightStart = _context.stackHeight(); |
| 357 | solAssert(_type.location() == DataLocation::Storage, ""); |
| 358 | if (_type.baseType()->storageBytes() < 32) |
| 359 | { |
| 360 | solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type."); |
| 361 | solAssert(_type.baseType()->storageSize() <= 1, "Invalid storage size for type."); |
| 362 | } |
| 363 | if (_type.baseType()->isValueType()) |
| 364 | solAssert(_type.baseType()->storageSize() <= 1, "Invalid size for value type."); |
| 365 | |
| 366 | _context << Instruction::POP; // remove byte offset |
| 367 | if (_type.isDynamicallySized()) |
| 368 | ArrayUtils(_context).clearDynamicArray(_type); |
| 369 | else if (_type.length() == 0 || _type.baseType()->category() == Type::Category::Mapping) |
| 370 | _context << Instruction::POP; |
| 371 | else if (_type.baseType()->isValueType() && _type.storageSize() <= 5) |
| 372 | { |
| 373 | // unroll loop for small arrays @todo choose a good value |
| 374 | // Note that we loop over storage slots here, not elements. |
| 375 | for (unsigned i = 1; i < _type.storageSize(); ++i) |
| 376 | _context |
| 377 | << u256(0) << Instruction::DUP2 << Instruction::SSTORE |
| 378 | << u256(1) << Instruction::ADD; |
| 379 | _context << u256(0) << Instruction::SWAP1 << Instruction::SSTORE; |
| 380 | } |
| 381 | else if (!_type.baseType()->isValueType() && _type.length() <= 4) |
| 382 | { |
| 383 | // unroll loop for small arrays @todo choose a good value |
| 384 | solAssert(_type.baseType()->storageBytes() >= 32, "Invalid storage size."); |
| 385 | for (unsigned i = 1; i < _type.length(); ++i) |
| 386 | { |
| 387 | _context << u256(0); |
| 388 | StorageItem(_context, *_type.baseType()).setToZero(SourceLocation(), false); |
| 389 | _context |
| 390 | << Instruction::POP |
| 391 | << u256(_type.baseType()->storageSize()) << Instruction::ADD; |
| 392 | } |
| 393 | _context << u256(0); |
| 394 | StorageItem(_context, *_type.baseType()).setToZero(SourceLocation(), true); |
| 395 | } |
| 396 | else |
| 397 | { |
| 398 | _context << _type.length(); |
| 399 | ArrayUtils(_context).convertLengthToSize(_type); |
| 400 | // stack: storage_ref slot_count |
| 401 | if (_type.baseType()->storageBytes() < 32) |
| 402 | ArrayUtils(_context).clearStorageLoop(TypeProvider::uint256()); |
| 403 | else |
no test coverage detected