Browse Source

Gas estimation

cl-refactor
yann300 10 years ago
parent
commit
2d2efc070a
  1. 49
      mix/CodeModel.cpp
  2. 25
      mix/CodeModel.h
  3. 4
      mix/qml/CodeEditorView.qml
  4. 8
      mix/qml/WebCodeEditor.qml
  5. 4
      mix/qml/html/cm/solarized.css
  6. 23
      mix/qml/html/codeeditor.js

49
mix/CodeModel.cpp

@ -33,6 +33,8 @@
#include <libsolidity/CompilerStack.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libsolidity/InterfaceHandler.h>
#include <libsolidity/StructuralGasEstimator.h>
#include <libsolidity/SourceReferenceFormatter.h>
#include <libevmcore/Instruction.h>
#include <libethcore/CommonJS.h>
#include "QContractDefinition.h"
@ -41,6 +43,7 @@
#include "CodeHighlighter.h"
#include "FileIo.h"
#include "CodeModel.h"
#include "QBigInt.h"
using namespace dev::mix;
@ -50,6 +53,7 @@ const std::set<std::string> c_predefinedContracts =
namespace
{
using namespace dev::eth;
using namespace dev::solidity;
class CollectLocalsVisitor: public ASTConstVisitor
@ -185,6 +189,7 @@ CodeModel::CodeModel():
qRegisterMetaType<QContractDefinition*>("QContractDefinition*");
qRegisterMetaType<QFunctionDefinition*>("QFunctionDefinition*");
qRegisterMetaType<QVariableDeclaration*>("QVariableDeclaration*");
//qRegisterMetaType<GasMap>("GasMap");
qmlRegisterType<QFunctionDefinition>("org.ethereum.qml", 1, 0, "QFunctionDefinition");
qmlRegisterType<QVariableDeclaration>("org.ethereum.qml", 1, 0, "QVariableDeclaration");
}
@ -292,6 +297,7 @@ void CodeModel::runCompilationJob(int _jobId)
}
}
cs.compile(false);
gasEstimation(cs);
collectContracts(cs, sourceNames);
}
catch (dev::Exception const& _exception)
@ -314,6 +320,49 @@ void CodeModel::runCompilationJob(int _jobId)
emit stateChanged();
}
void CodeModel::gasEstimation(solidity::CompilerStack const& _cs)
{
m_gasCostsMaps.clear();
for (std::string n: _cs.getContractNames())
{
ContractDefinition const& contractDefinition = _cs.getContractDefinition(n);
QString sourceName = QString::fromStdString(*contractDefinition.getLocation().sourceName);
if (!m_gasCostsMaps.contains(sourceName))
m_gasCostsMaps.insert(sourceName, QVariantList());
if (!contractDefinition.isFullyImplemented())
continue;
dev::solidity::SourceUnit const& sourceUnit = _cs.getAST(*contractDefinition.getLocation().sourceName);
AssemblyItems const* items = _cs.getRuntimeAssemblyItems(n);
StructuralGasEstimator estimator;
std::map<ASTNode const*, GasMeter::GasConsumption> gasCosts = estimator.breakToStatementLevel(estimator.performEstimation(*items, std::vector<ASTNode const*>({&sourceUnit})), {&sourceUnit});
for (auto gasIte = gasCosts.begin(); gasIte != gasCosts.end(); ++gasIte)
{
SourceLocation location = gasIte->first->getLocation();
GasMeter::GasConsumption cost = gasIte->second;
GasMap* gas = new GasMap(location.start, location.end, (new QBigInt(cost.value))->value());
m_gasCostsMaps.find(sourceName).value().push_back(QVariant::fromValue(gas));
}
}
}
QVariantList CodeModel::gasCostByDocumentId(QString const& _documentId) const
{
if (m_gasCostsMaps.contains(_documentId))
{
auto sourceMapIter = m_gasCostsMaps.find(_documentId);
int gg = sourceMapIter.value().size();
Q_UNUSED(gg);
return sourceMapIter.value();
}
else
return QVariantList();
}
void CodeModel::collectContracts(dev::solidity::CompilerStack const& _cs, std::vector<std::string> const& _sourceNames)
{
Guard pl(x_pendingContracts);

25
mix/CodeModel.h

@ -32,6 +32,7 @@
#include <libdevcore/Guards.h>
#include <libevmasm/Assembly.h>
#include "SolidityType.h"
#include "QBigInt.h"
class QTextDocument;
@ -126,7 +127,24 @@ struct SourceMap
LocationMap functions;
};
class GasMap: public QObject
{
Q_OBJECT
Q_PROPERTY(int start MEMBER m_start CONSTANT)
Q_PROPERTY(int end MEMBER m_end CONSTANT)
Q_PROPERTY(QString gas MEMBER m_gas CONSTANT)
public:
GasMap(int _start, int _end, QString _gas): m_start(_start), m_end(_end), m_gas(_gas) {}
int m_start;
int m_end;
QString m_gas;
};
using SourceMaps = QMap<QString, SourceMap>; //by source id
using GasCostsMaps = QMap<QString, QVariantList/* QList<GasMap>*/>; //gas cost by contract name
/// Code compilation model. Compiles contracts in background an provides compiled contract data
class CodeModel: public QObject
@ -166,6 +184,10 @@ public:
bool isContractOrFunctionLocation(dev::SourceLocation const& _location);
/// Get funciton name by location
QString resolveFunctionName(dev::SourceLocation const& _location);
/// Gas estimation for compiled sources
void gasEstimation(solidity::CompilerStack const& _cs);
/// Gas cost by doc id
Q_INVOKABLE QVariantList gasCostByDocumentId(QString const& _documentId) const;
signals:
/// Emited on compilation state change
@ -201,6 +223,7 @@ private:
mutable dev::Mutex x_contractMap;
ContractMap m_contractMap;
SourceMaps m_sourceMaps;
GasCostsMaps m_gasCostsMaps;
std::unique_ptr<CodeHighlighterSettings> m_codeHighlighterSettings;
QThread m_backgroundThread;
BackgroundWorker m_backgroundWorker;
@ -214,3 +237,5 @@ private:
}
}
//Q_DECLARE_METATYPE(dev::mix::GasMap)

4
mix/qml/CodeEditorView.qml

@ -177,6 +177,10 @@ Item {
}
onCompilationComplete: {
sourceInError = "";
var gasCosts = codeModel.gasCostByDocumentId(currentDocumentId);
var editor = getEditor(currentDocumentId);
if (editor)
editor.displayGasCosts(gasCosts);
}
}

8
mix/qml/WebCodeEditor.qml

@ -83,6 +83,14 @@ Item {
editorBrowser.runJavaScript("setFontSize(" + size + ")", function(result) {});
}
function displayGasCosts(gasCosts) {
//console.log(gasCosts);
//console.log(JSON.stringify(gasCosts));
if (initialized && editorBrowser)
editorBrowser.runJavaScript("displayGasCosts('" + JSON.stringify(gasCosts) + "')", function(result) {});
}
Clipboard
{
id: clipboard

4
mix/qml/html/cm/solarized.css

@ -189,3 +189,7 @@ view-port
}
span.CodeMirror-selectedtext { color: #586e75 !important; }
.gasCost {
background: #b58900 !important;
}

23
mix/qml/html/codeeditor.js

@ -3,7 +3,7 @@ var editor = CodeMirror(document.body, {
//styleActiveLine: true,
matchBrackets: true,
autofocus: true,
gutters: ["CodeMirror-linenumbers", "breakpoints"],
gutters: ["CodeMirror-linenumbers", "breakpoints", "gasCost"],
autoCloseBrackets: true,
styleSelectedText: true
});
@ -203,5 +203,26 @@ setFontSize = function(size)
editor.refresh();
}
makeGasCostMarker = function(value) {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = value;
return marker;
};
displayGasCosts = function(gasCosts)
{
gasCosts = JSON.parse(gasCosts);
for (var i in gasCosts)
{
var line = editor.posFromIndex(gasCosts[i].start);
console.log("___________")
console.log(line.line);
console.log(gasCosts[i].start);
//editor.setGutterMarker(line.line, "gasCost", makeGasCostMarker(gasCosts[i].gas));
editor.markText(editor.posFromIndex(gasCosts[i].start), editor.posFromIndex(gasCosts[i].end), { className: "gasCost" });
}
}
editor.setOption("extraKeys", extraKeys);

Loading…
Cancel
Save