Impl( AssemblyItem* assembly_item, Assembly* assembly, Scene& scene, ProjectBuilder& project_builder, ParamArray& settings) : m_assembly_item(assembly_item) , m_assembly(assembly) , m_scene(scene) , m_project_builder(project_builder) { m_color_collection_item = add_single_model_collection_item<ColorEntity>(assembly->colors()); m_assembly_item->addChild( m_texture_collection_item = new TextureCollectionItem( *m_assembly, assembly->textures(), m_project_builder, settings)); m_texture_instance_collection_item = add_single_model_collection_item<TextureInstance>(assembly->texture_instances()); m_texture_instance_collection_item->set_allow_creation(false); m_bsdf_collection_item = add_multi_model_collection_item<BSDF>(assembly->bsdfs()); m_edf_collection_item = add_multi_model_collection_item<EDF>(assembly->edfs()); m_surface_shader_collection_item = add_multi_model_collection_item<SurfaceShader>(assembly->surface_shaders()); m_material_collection_item = add_single_model_collection_item<Material>(assembly->materials()); m_light_collection_item = add_multi_model_collection_item<Light>(assembly->lights()); m_assembly_item->addChild( m_object_collection_item = new ObjectCollectionItem( *m_assembly, assembly->objects(), m_project_builder, settings)); m_object_instance_collection_item = add_collection_item(assembly->object_instances()); }
typename ItemTypeMap<EntityContainer>::T* add_collection_item(EntityContainer& entities) { typedef typename ItemTypeMap<EntityContainer>::T ItemType; ItemType* item = new ItemType( *m_assembly, entities, m_project_builder); m_assembly_item->addChild(item); return item; }
CollectionItem<Entity, Assembly>* add_multi_model_collection_item(EntityContainer& entities) { CollectionItem<Entity, Assembly>* item = new MultiModelCollectionItem<Entity, Assembly>( new_guid(), EntityTraits<Entity>::get_human_readable_collection_type_name(), *m_assembly, m_project_builder); item->add_items(entities); m_assembly_item->addChild(item); return item; }
GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item) { GasConsumption gas; switch (_item.type()) { case Push: case PushTag: case PushData: case PushString: case PushSub: case PushSubSize: case PushProgramSize: case PushLibraryAddress: gas = runGas(Instruction::PUSH1); break; case Tag: gas = runGas(Instruction::JUMPDEST); break; case Operation: { ExpressionClasses& classes = m_state->expressionClasses(); gas = runGas(_item.instruction()); switch (_item.instruction()) { case Instruction::SSTORE: { ExpressionClasses::Id slot = m_state->relativeStackElement(0); ExpressionClasses::Id value = m_state->relativeStackElement(-1); if (classes.knownZero(value) || ( m_state->storageContent().count(slot) && classes.knownNonZero(m_state->storageContent().at(slot)) )) gas += GasCosts::sstoreResetGas; //@todo take refunds into account else gas += GasCosts::sstoreSetGas; break; } case Instruction::SLOAD: gas += GasCosts::sloadGas; break; case Instruction::RETURN: gas += memoryGas(0, -1); break; case Instruction::MLOAD: case Instruction::MSTORE: gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(32)) })); break; case Instruction::MSTORE8: gas += memoryGas(classes.find(Instruction::ADD, { m_state->relativeStackElement(0), classes.find(AssemblyItem(1)) })); break; case Instruction::SHA3: gas = GasCosts::sha3Gas; gas += wordGas(GasCosts::sha3WordGas, m_state->relativeStackElement(-1)); gas += memoryGas(0, -1); break; case Instruction::CALLDATACOPY: case Instruction::CODECOPY: gas += memoryGas(0, -2); gas += wordGas(GasCosts::copyGas, m_state->relativeStackElement(-2)); break; case Instruction::EXTCODECOPY: gas += memoryGas(-1, -3); gas += wordGas(GasCosts::copyGas, m_state->relativeStackElement(-3)); break; case Instruction::LOG0: case Instruction::LOG1: case Instruction::LOG2: case Instruction::LOG3: case Instruction::LOG4: { unsigned n = unsigned(_item.instruction()) - unsigned(Instruction::LOG0); gas = GasCosts::logGas + GasCosts::logTopicGas * n; gas += memoryGas(0, -1); if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(-1))) gas += GasCosts::logDataGas * (*value); else gas = GasConsumption::infinite(); break; } case Instruction::CALL: case Instruction::CALLCODE: case Instruction::DELEGATECALL: { gas = GasCosts::callGas; if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(0))) gas += (*value); else gas = GasConsumption::infinite(); if (_item.instruction() == Instruction::CALL) gas += GasCosts::callNewAccountGas; // We very rarely know whether the address exists. int valueSize = _item.instruction() == Instruction::DELEGATECALL ? 0 : 1; if (!classes.knownZero(m_state->relativeStackElement(-1 - valueSize))) gas += GasCosts::callValueTransferGas; gas += memoryGas(-2 - valueSize, -3 - valueSize); gas += memoryGas(-4 - valueSize, -5 - valueSize); break; } case Instruction::CREATE: gas = GasCosts::createGas; gas += memoryGas(-1, -2); break; case Instruction::EXP: gas = GasCosts::expGas; if (u256 const* value = classes.knownConstant(m_state->relativeStackElement(-1))) gas += GasCosts::expByteGas * (32 - (h256(*value).firstBitSet() / 8)); else gas += GasCosts::expByteGas * 32; break; default: break; } break; } default: gas = GasConsumption::infinite(); break; } m_state->feedItem(_item); return gas; }
void CSECodeGenerator::appendItem(AssemblyItem const& _item) { m_generatedItems.push_back(_item); m_stackHeight += _item.deposit(); }
KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool _copyItem) { StoreOperation op; if (_item.type() == Tag) { // can be ignored } else if (_item.type() != Operation) { assertThrow(_item.deposit() == 1, InvalidDeposit, ""); if (_item.pushedValue()) // only available after assembly stage, should not be used for optimisation setStackElement(++m_stackHeight, m_expressionClasses->find(*_item.pushedValue())); else setStackElement(++m_stackHeight, m_expressionClasses->find(_item, {}, _copyItem)); } else { Instruction instruction = _item.instruction(); InstructionInfo info = instructionInfo(instruction); if (SemanticInformation::isDupInstruction(_item)) setStackElement( m_stackHeight + 1, stackElement( m_stackHeight - int(instruction) + int(Instruction::DUP1), _item.getLocation() ) ); else if (SemanticInformation::isSwapInstruction(_item)) swapStackElements( m_stackHeight, m_stackHeight - 1 - int(instruction) + int(Instruction::SWAP1), _item.getLocation() ); else if (instruction != Instruction::POP) { vector<Id> arguments(info.args); for (int i = 0; i < info.args; ++i) arguments[i] = stackElement(m_stackHeight - i, _item.getLocation()); if (_item.instruction() == Instruction::SSTORE) op = storeInStorage(arguments[0], arguments[1], _item.getLocation()); else if (_item.instruction() == Instruction::SLOAD) setStackElement( m_stackHeight + _item.deposit(), loadFromStorage(arguments[0], _item.getLocation()) ); else if (_item.instruction() == Instruction::MSTORE) op = storeInMemory(arguments[0], arguments[1], _item.getLocation()); else if (_item.instruction() == Instruction::MLOAD) setStackElement( m_stackHeight + _item.deposit(), loadFromMemory(arguments[0], _item.getLocation()) ); else if (_item.instruction() == Instruction::SHA3) setStackElement( m_stackHeight + _item.deposit(), applySha3(arguments.at(0), arguments.at(1), _item.getLocation()) ); else { if (SemanticInformation::invalidatesMemory(_item.instruction())) resetMemory(); if (SemanticInformation::invalidatesStorage(_item.instruction())) resetStorage(); assertThrow(info.ret <= 1, InvalidDeposit, ""); if (info.ret == 1) setStackElement( m_stackHeight + _item.deposit(), m_expressionClasses->find(_item, arguments, _copyItem) ); } } m_stackElements.erase( m_stackElements.upper_bound(m_stackHeight + _item.deposit()), m_stackElements.end() ); m_stackHeight += _item.deposit(); } return op; }