Преглед изворни кода

improve performance of JsonExpressions by compiling them to procesor instructions at runtime

Kolja Strohm пре 3 месеци
родитељ
комит
dc63b156e8

+ 5 - 0
FactoryCraft/Chunk.cpp

@@ -1261,6 +1261,11 @@ int Chunk::getBlockTypeAt(Framework::Vec3<int> location) const
     return blockIds[index(location)];
 }
 
+int Chunk::getBlockTypeAtWC(int x, int y, int z) const
+{
+    return blockIds[index(Dimension::chunkCoordinates({x, y, z}))];
+}
+
 void Chunk::onEntityEnters(Entity* zEntity, Chunk* lastChunk)
 {
     NetworkMessage* msg = 0;

+ 1 - 0
FactoryCraft/Chunk.h

@@ -90,6 +90,7 @@ public:
     void setLightData(
         Framework::Vec3<int> location, unsigned char* data, bool foreground);
     int getBlockTypeAt(Framework::Vec3<int> location) const;
+    int getBlockTypeAtWC(int x, int y, int z) const;
     void onEntityEnters(Entity* zEntity, Chunk* lastChunk);
     void onEntityLeaves(Entity* zEntity, Chunk* zNextChunk);
     bool hasObserver(int entityId) const;

+ 578 - 21
FactoryCraft/JsonExpression.cpp

@@ -33,6 +33,11 @@ float JExpressionMemory::getNoise(
     return 0.f;
 }
 
+Noise* JExpressionMemory::zNoiseP(Framework::Text name)
+{
+    return noises.z(name, name.getLength());
+}
+
 void JExpressionMemory::setNoise(Framework::Text name, Noise* noise)
 {
     noises.set(name, name.getLength(), noise);
@@ -49,6 +54,15 @@ float JExpressionMemory::getFloatVariable(const Framework::Text& name) const
     return floatVariables.get(name, name.getLength());
 }
 
+float* JExpressionMemory::getFloatVariableP(const Framework::Text& name)
+{
+    if (!floatVariables.contains(name, name.getLength()))
+    {
+        floatVariables.set(name, name.getLength(), 0.f);
+    }
+    return floatVariables.getP(name, name.getLength());
+}
+
 void JExpressionMemory::setFloatVariable(
     const Framework::Text& name, float value)
 {
@@ -60,6 +74,15 @@ bool JExpressionMemory::getBoolVariable(const Framework::Text& name) const
     return boolVariables.get(name, name.getLength());
 }
 
+bool* JExpressionMemory::getBoolVariableP(const Framework::Text& name)
+{
+    if (!boolVariables.contains(name, name.getLength()))
+    {
+        boolVariables.set(name, name.getLength(), 0);
+    }
+    return boolVariables.getP(name, name.getLength());
+}
+
 void JExpressionMemory::setBoolVariable(const Framework::Text& name, bool value)
 {
     return boolVariables.set(name, name.getLength(), value);
@@ -70,23 +93,91 @@ Chunk* JExpressionMemory::zCurrentChunk()
     return currentChunk;
 }
 
+Chunk** JExpressionMemory::zzCurrentChunk()
+{
+    return &currentChunk;
+}
+
 JFloatExpression::JFloatExpression()
-    : ReferenceCounter()
+    : ReferenceCounter(),
+      compiled(0)
 {}
 
+float JFloatExpression::getValue(JExpressionMemory* zMemory)
+{
+    FloatFunc func = compile(zMemory);
+    float result = func();
+    /* float old = getValueOld(zMemory);
+    if (result != old)
+    {
+        float x = func();
+        Framework::Logging::debug() << "fehler" << x << " != " << old;
+    }*/
+    return result;
+}
+
+FloatFunc JFloatExpression::compile(JExpressionMemory* zMemory)
+{
+    if (compiled)
+    {
+        if (zMemory != memory)
+        {
+            throw "Cannot compile the same expression for different memories";
+        }
+        return compiled;
+    }
+    memory = zMemory;
+    return compiled = buildAssembly(zMemory).compileToFunction<FloatFunc>();
+}
+
 JBoolExpression::JBoolExpression()
-    : ReferenceCounter()
+    : ReferenceCounter(),
+      compiled(0)
 {}
 
+bool JBoolExpression::getValue(JExpressionMemory* zMemory)
+{
+    bool result = compile(zMemory)();
+    /* bool old = getValueOld(zMemory);
+    if (result != old)
+    {
+        Framework::Logging::debug() << "fehler";
+    }*/
+    return result;
+}
+
+BoolFunc JBoolExpression::compile(JExpressionMemory* zMemory)
+{
+    if (compiled)
+    {
+        if (zMemory != memory)
+        {
+            throw "Cannot compile the same expression for different "
+                  "memories";
+        }
+        return compiled;
+    }
+    memory = zMemory;
+    return compiled = buildAssembly(zMemory).compileToFunction<BoolFunc>();
+}
+
 JVariableFloatExpression::JVariableFloatExpression()
     : JFloatExpression()
 {}
 
-float JVariableFloatExpression::getValue(JExpressionMemory* zMemory)
+float JVariableFloatExpression::getValueOld(JExpressionMemory* zMemory)
 {
     return zMemory->getFloatVariable(name);
 }
 
+Framework::Assembly::AssemblyBlock& JVariableFloatExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    codeBlock.addLoadValue(
+        zMemory->getFloatVariableP(name), Framework::Assembly::MM0);
+    return codeBlock;
+}
+
 void JVariableFloatExpression::setName(Framework::Text name)
 {
     this->name = name;
@@ -133,11 +224,19 @@ JVariableBoolExpression::JVariableBoolExpression()
     : JBoolExpression()
 {}
 
-bool JVariableBoolExpression::getValue(JExpressionMemory* zMemory)
+bool JVariableBoolExpression::getValueOld(JExpressionMemory* zMemory)
 {
     return zMemory->getBoolVariable(name);
 }
 
+Framework::Assembly::AssemblyBlock& JVariableBoolExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    codeBlock.addLoadValue(
+        (char*)zMemory->getBoolVariableP(name), Framework::Assembly::RAX);
+    return codeBlock;
+}
+
 void JVariableBoolExpression::setName(Framework::Text name)
 {
     this->name = name;
@@ -185,11 +284,18 @@ JConstantFloatExpression::JConstantFloatExpression()
       value(0)
 {}
 
-float JConstantFloatExpression::getValue(JExpressionMemory* zMemory)
+float JConstantFloatExpression::getValueOld(JExpressionMemory* zMemory)
 {
     return value;
 }
 
+Framework::Assembly::AssemblyBlock& JConstantFloatExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    codeBlock.addLoadValue(&value, Framework::Assembly::MM0);
+    return codeBlock;
+}
+
 void JConstantFloatExpression::setValue(float value)
 {
     this->value = value;
@@ -236,11 +342,18 @@ JConstantBoolExpression::JConstantBoolExpression()
     : JBoolExpression()
 {}
 
-bool JConstantBoolExpression::getValue(JExpressionMemory* zMemory)
+bool JConstantBoolExpression::getValueOld(JExpressionMemory* zMemory)
 {
     return value;
 }
 
+Framework::Assembly::AssemblyBlock& JConstantBoolExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    codeBlock.addMoveValue(Framework::Assembly::RAX, (char)(value ? 1 : 0));
+    return codeBlock;
+}
+
 void JConstantBoolExpression::setValue(bool value)
 {
     this->value = value;
@@ -297,10 +410,94 @@ JNoiseFloatExpression::~JNoiseFloatExpression()
     if (z) z->release();
 }
 
-float JNoiseFloatExpression::getValue(JExpressionMemory* zMemory)
+float JNoiseFloatExpression::getValueOld(JExpressionMemory* zMemory)
 {
-    return zMemory->getNoise(
-        name, x->getValue(zMemory), y->getValue(zMemory), z->getValue(zMemory));
+    return zMemory->getNoise(name,
+        x->getValueOld(zMemory),
+        y->getValueOld(zMemory),
+        z->getValueOld(zMemory));
+}
+
+Framework::Assembly::AssemblyBlock& JNoiseFloatExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    Noise* noise = zMemory->zNoiseP(name);
+    if (!noise)
+    {
+        Framework::Logging::error() << "no noise with name '" << name.getText()
+                                    << "' found, behavior is undefined\n";
+        return codeBlock;
+    }
+    Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory);
+    Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory);
+    Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory);
+    Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0;
+    if (xBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM1))
+    {
+        xBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM1);
+        xTarget = Framework::Assembly::MM1;
+    }
+    Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0;
+    if (yBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM2))
+    {
+        yBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM2);
+        yTarget = Framework::Assembly::MM2;
+    }
+    Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0;
+    if (zBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM3))
+    {
+        zBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM3);
+        zTarget = Framework::Assembly::MM3;
+    }
+    codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget);
+    if (zTarget != Framework::Assembly::MM3)
+    {
+        codeBlock.addMoveValue(Framework::Assembly::MM3,
+            zTarget,
+            Framework::Assembly::SINGLE_FLOAT,
+            Framework::Assembly::X);
+    }
+    codeBlock.addBlock(&yBlock,
+        {},
+        {Framework::Assembly::MM3},
+        {Framework::Assembly::SINGLE_FLOAT},
+        0,
+        &yTarget);
+    if (yTarget != Framework::Assembly::MM2)
+    {
+        codeBlock.addMoveValue(Framework::Assembly::MM2,
+            yTarget,
+            Framework::Assembly::SINGLE_FLOAT,
+            Framework::Assembly::X);
+    }
+    codeBlock.addBlock(&xBlock,
+        {},
+        {Framework::Assembly::MM2, Framework::Assembly::MM3},
+        {Framework::Assembly::SINGLE_FLOAT, Framework::Assembly::SINGLE_FLOAT},
+        0,
+        &xTarget);
+    if (xTarget != Framework::Assembly::MM1)
+    {
+        codeBlock.addMoveValue(Framework::Assembly::MM1,
+            xTarget,
+            Framework::Assembly::SINGLE_FLOAT,
+            Framework::Assembly::X);
+    }
+    codeBlock.addLoadAddress(noise, Framework::Assembly::RCX);
+    codeBlock.addMemberCall<float (Noise::*)(float, float, float)>(
+        &Noise::getNoise,
+        Framework::Assembly::FLOAT_VALUE,
+        {Framework::Assembly::RCX},
+        {Framework::Assembly::MM1,
+            Framework::Assembly::MM2,
+            Framework::Assembly::MM3});
+    return codeBlock;
 }
 
 void JNoiseFloatExpression::setName(Framework::Text name)
@@ -402,7 +599,7 @@ JOperatorFloatExpression::JOperatorFloatExpression()
       accumulator([](float a, float b) { return 0.f; })
 {}
 
-float JOperatorFloatExpression::getValue(JExpressionMemory* zMemory)
+float JOperatorFloatExpression::getValueOld(JExpressionMemory* zMemory)
 {
     bool first = 1;
     float val = 0.f;
@@ -411,16 +608,88 @@ float JOperatorFloatExpression::getValue(JExpressionMemory* zMemory)
         if (first)
         {
             first = 0;
-            val = expression->getValue(zMemory);
+            val = expression->getValueOld(zMemory);
         }
         else
         {
-            val = accumulator(val, expression->getValue(zMemory));
+            val = accumulator(val, expression->getValueOld(zMemory));
         }
     }
     return val;
 }
 
+Framework::Assembly::AssemblyBlock& JOperatorFloatExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    if (!values.getEintragAnzahl())
+    {
+        codeBlock.addMoveValue(Framework::Assembly::MM0, 0.f);
+    }
+    for (JFloatExpression* expression : values)
+    {
+        if (first)
+        {
+            first = 0;
+            codeBlock.addBlock(
+                &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
+        }
+        else
+        {
+            Framework::Assembly::AssemblyBlock& exprBlock
+                = expression->buildAssembly(zMemory);
+            if (exprBlock.isReplacementPossible(
+                    Framework::Assembly::MM0, Framework::Assembly::MM1))
+            {
+                exprBlock.replaceRegister(
+                    Framework::Assembly::MM0, Framework::Assembly::MM1);
+            }
+            else
+            {
+                exprBlock.addMoveValue(Framework::Assembly::MM1,
+                    Framework::Assembly::MM0,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::X);
+            }
+            codeBlock.addBlock(&exprBlock,
+                {},
+                {Framework::Assembly::MM0},
+                {Framework::Assembly::SINGLE_FLOAT},
+                0,
+                0);
+            if (op.istGleich("+"))
+            {
+                codeBlock.addAddition(Framework::Assembly::MM0,
+                    Framework::Assembly::MM1,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::X);
+            }
+            else if (op.istGleich("-"))
+            {
+                codeBlock.addSubtraction(Framework::Assembly::MM0,
+                    Framework::Assembly::MM1,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::X);
+            }
+            else if (op.istGleich("*"))
+            {
+                codeBlock.addMultiplication(Framework::Assembly::MM0,
+                    Framework::Assembly::MM1,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::X);
+            }
+            else if (op.istGleich("/"))
+            {
+                codeBlock.addDivision(Framework::Assembly::MM0,
+                    Framework::Assembly::MM1,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::X);
+            }
+        }
+    }
+    return codeBlock;
+}
+
 void JOperatorFloatExpression::setOperator(
     Framework::Text op, std::function<float(float a, float b)> accumulator)
 {
@@ -516,7 +785,7 @@ JBoolOperatorBoolExpression::JBoolOperatorBoolExpression()
     : JBoolExpression()
 {}
 
-bool JBoolOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
+bool JBoolOperatorBoolExpression::getValueOld(JExpressionMemory* zMemory)
 {
     bool first = 1;
     bool val = 0;
@@ -525,16 +794,67 @@ bool JBoolOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
         if (first)
         {
             first = 0;
-            val = expression->getValue(zMemory);
+            val = expression->getValueOld(zMemory);
         }
         else
         {
-            val = accumulator(val, expression->getValue(zMemory));
+            val = accumulator(val, expression->getValueOld(zMemory));
         }
     }
     return val;
 }
 
+Framework::Assembly::AssemblyBlock& JBoolOperatorBoolExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    if (!values.getEintragAnzahl())
+    {
+        codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
+    }
+    for (JBoolExpression* expression : values)
+    {
+        if (first)
+        {
+            first = 0;
+            codeBlock.addBlock(
+                &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
+        }
+        else
+        {
+            Framework::Assembly::AssemblyBlock& exprBlock
+                = expression->buildAssembly(zMemory);
+            if (exprBlock.isReplacementPossible(
+                    Framework::Assembly::RAX, Framework::Assembly::RCX))
+            {
+                exprBlock.replaceRegister(
+                    Framework::Assembly::RAX, Framework::Assembly::RCX);
+            }
+            else
+            {
+                exprBlock.addMoveValue(Framework::Assembly::RCX,
+                    Framework::Assembly::RAX,
+                    Framework::Assembly::LOWER8);
+            }
+            codeBlock.addBlock(
+                &exprBlock, {Framework::Assembly::RAX}, {}, {}, 0, 0);
+            if (op.istGleich("&&"))
+            {
+                codeBlock.addAnd(Framework::Assembly::RAX,
+                    Framework::Assembly::RCX,
+                    Framework::Assembly::LOWER8);
+            }
+            else if (op.istGleich("||"))
+            {
+                codeBlock.addOr(Framework::Assembly::RAX,
+                    Framework::Assembly::RCX,
+                    Framework::Assembly::LOWER8);
+            }
+        }
+    }
+    return codeBlock;
+}
+
 void JBoolOperatorBoolExpression::setOperator(
     Framework::Text op, std::function<float(float a, float b)> accumulator)
 {
@@ -622,14 +942,14 @@ JFloatOperatorBoolExpression::JFloatOperatorBoolExpression()
     : JBoolExpression()
 {}
 
-bool JFloatOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
+bool JFloatOperatorBoolExpression::getValueOld(JExpressionMemory* zMemory)
 {
     bool first = 1;
     bool val = 1;
     float last = 0.f;
     for (JFloatExpression* expression : values)
     {
-        float current = expression->getValue(zMemory);
+        float current = expression->getValueOld(zMemory);
         if (!first) val &= accumulator(last, current);
         first = 0;
         last = current;
@@ -638,6 +958,136 @@ bool JFloatOperatorBoolExpression::getValue(JExpressionMemory* zMemory)
     return val;
 }
 
+Framework::Assembly::AssemblyBlock& JFloatOperatorBoolExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    bool first = 1;
+    Framework::Assembly::FPRegister lastResultSorage = Framework::Assembly::MM0;
+    for (JFloatExpression* expression : values)
+    {
+        if (first)
+        {
+            first = 0;
+            codeBlock.addBlock(
+                &expression->buildAssembly(zMemory), {}, {}, {}, 0, 0);
+        }
+        else
+        {
+            Framework::Assembly::FPRegister currentResultSorage
+                = lastResultSorage == Framework::Assembly::MM0
+                    ? Framework::Assembly::MM1
+                    : Framework::Assembly::MM0;
+            Framework::Assembly::AssemblyBlock& exprBlock
+                = expression->buildAssembly(zMemory);
+            if (currentResultSorage != Framework::Assembly::MM0)
+            {
+                if (exprBlock.isReplacementPossible(
+                        Framework::Assembly::MM0, currentResultSorage))
+                {
+                    exprBlock.replaceRegister(
+                        Framework::Assembly::MM0, currentResultSorage);
+                }
+                else
+                {
+                    exprBlock.addMoveValue(currentResultSorage,
+                        Framework::Assembly::MM0,
+                        Framework::Assembly::SINGLE_FLOAT,
+                        Framework::Assembly::X);
+                }
+            }
+            codeBlock.addBlock(&exprBlock,
+                {},
+                {lastResultSorage},
+                {Framework::Assembly::SINGLE_FLOAT},
+                0,
+                0);
+            Framework::Assembly::Operation jumpOp = Framework::Assembly::NOP;
+            bool needConversion = false;
+            if (op.istGleich(">"))
+            {
+                jumpOp = Framework::Assembly::JBE; // jump if below or equal
+            }
+            else if (op.istGleich("<"))
+            {
+                jumpOp = Framework::Assembly::JNB; // jump if not below
+            }
+            else if (op.istGleich(">="))
+            {
+                jumpOp = Framework::Assembly::JB; // jump if below
+            }
+            else if (op.istGleich("<="))
+            {
+                jumpOp = Framework::Assembly::JA; // jump if above
+            }
+            else if (op.istGleich("=="))
+            {
+                jumpOp = Framework::Assembly::JNE; // jump if not equal
+            }
+            else if (op.istGleich("!="))
+            {
+                jumpOp = Framework::Assembly::JE; // jump if equal
+            }
+            else
+            {
+                needConversion = true;
+                if (op.istGleich(">i"))
+                {
+                    jumpOp = Framework::Assembly::JLE; // jump if less or equal
+                }
+                else if (op.istGleich("<i"))
+                {
+                    jumpOp = Framework::Assembly::JGE; // jump if greater or
+                                                       // equal
+                }
+                else if (op.istGleich(">=i"))
+                {
+                    jumpOp = Framework::Assembly::JL; // jump if less
+                }
+                else if (op.istGleich("<=i"))
+                {
+                    jumpOp = Framework::Assembly::JG; // jump if greater
+                }
+                else if (op.istGleich("==i"))
+                {
+                    jumpOp = Framework::Assembly::JNE; // jump if not equal
+                }
+                else if (op.istGleich("!=i"))
+                {
+                    jumpOp = Framework::Assembly::JE; // jump if equal
+                }
+            }
+            if (needConversion)
+            {
+                codeBlock.addConversion(Framework::Assembly::RAX,
+                    lastResultSorage,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::LOWER32);
+                codeBlock.addConversion(Framework::Assembly::RCX,
+                    currentResultSorage,
+                    Framework::Assembly::SINGLE_FLOAT,
+                    Framework::Assembly::LOWER32);
+                codeBlock.addCompare(Framework::Assembly::RAX,
+                    Framework::Assembly::RCX,
+                    Framework::Assembly::LOWER32);
+            }
+            else
+            {
+                codeBlock.addCompare(lastResultSorage,
+                    currentResultSorage,
+                    Framework::Assembly::SINGLE_FLOAT);
+            }
+            codeBlock.addJump(jumpOp, "end_false");
+            lastResultSorage = currentResultSorage;
+        }
+    }
+    codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1);
+    codeBlock.addJump(Framework::Assembly::JMP, "end");
+    codeBlock.defineJumpTarget("end_false");
+    codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
+    codeBlock.defineJumpTarget("end");
+    return codeBlock;
+}
+
 void JFloatOperatorBoolExpression::setOperator(
     Framework::Text op, std::function<bool(float a, float b)> accumulator)
 {
@@ -794,11 +1244,18 @@ JBlockTypeBoolExpression ::~JBlockTypeBoolExpression()
     if (z) z->release();
 }
 
-bool JBlockTypeBoolExpression::getValue(JExpressionMemory* zMemory)
+bool JBlockTypeBoolExpression::isValidPosition(
+    int x, int y, Chunk* currentChunk)
 {
-    int x = (int)(round(this->x->getValue(zMemory)));
-    int y = (int)(round(this->y->getValue(zMemory)));
-    int z = (int)(round(this->z->getValue(zMemory)));
+    return currentChunk
+        && Game::getChunkCenter(x, y) == currentChunk->getCenter();
+}
+
+bool JBlockTypeBoolExpression::getValueOld(JExpressionMemory* zMemory)
+{
+    int x = (int)(round(this->x->getValueOld(zMemory)));
+    int y = (int)(round(this->y->getValueOld(zMemory)));
+    int z = (int)(round(this->z->getValueOld(zMemory)));
     if (z < 0 || z >= WORLD_HEIGHT || !zMemory->zCurrentChunk()
         || Game::getChunkCenter(x, y) != zMemory->zCurrentChunk()->getCenter())
     {
@@ -809,6 +1266,106 @@ bool JBlockTypeBoolExpression::getValue(JExpressionMemory* zMemory)
         == typeId;
 }
 
+Framework::Assembly::AssemblyBlock& JBlockTypeBoolExpression::buildAssembly(
+    JExpressionMemory* zMemory)
+{
+    Framework::Assembly::AssemblyBlock& xBlock = x->buildAssembly(zMemory);
+    Framework::Assembly::AssemblyBlock& yBlock = y->buildAssembly(zMemory);
+    Framework::Assembly::AssemblyBlock& zBlock = z->buildAssembly(zMemory);
+    Framework::Assembly::FPRegister xTarget = Framework::Assembly::MM0;
+    if (xBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM1))
+    {
+        xBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM1);
+        xTarget = Framework::Assembly::MM1;
+    }
+    Framework::Assembly::FPRegister yTarget = Framework::Assembly::MM0;
+    if (yBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM2))
+    {
+        yBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM2);
+        yTarget = Framework::Assembly::MM2;
+    }
+    Framework::Assembly::FPRegister zTarget = Framework::Assembly::MM0;
+    if (zBlock.isReplacementPossible(
+            Framework::Assembly::MM0, Framework::Assembly::MM3))
+    {
+        zBlock.replaceRegister(
+            Framework::Assembly::MM0, Framework::Assembly::MM3);
+        zTarget = Framework::Assembly::MM3;
+    }
+    codeBlock.addBlock(&zBlock, {}, {}, {}, 0, &zTarget);
+    codeBlock.addConversion(Framework::Assembly::R9,
+        zTarget,
+        Framework::Assembly::SINGLE_FLOAT,
+        Framework::Assembly::LOWER32,
+        1);
+    codeBlock.addTest(Framework::Assembly::R9,
+        Framework::Assembly::R9,
+        Framework::Assembly::LOWER32);
+    codeBlock.addJump(Framework::Assembly::JL, "end_false");
+    codeBlock.addCompare(Framework::Assembly::R9, WORLD_HEIGHT);
+    codeBlock.addJump(Framework::Assembly::JGE, "end_false");
+    codeBlock.addBlock(&yBlock, {Framework::Assembly::R9}, {}, {}, 0, &yTarget);
+    codeBlock.addConversion(Framework::Assembly::R8,
+        yTarget,
+        Framework::Assembly::SINGLE_FLOAT,
+        Framework::Assembly::LOWER32,
+        1);
+    codeBlock.addBlock(&xBlock,
+        {Framework::Assembly::R8, Framework::Assembly::R9},
+        {},
+        {},
+        0,
+        &xTarget);
+    codeBlock.addConversion(Framework::Assembly::RDX,
+        xTarget,
+        Framework::Assembly::SINGLE_FLOAT,
+        Framework::Assembly::LOWER32,
+        1);
+    codeBlock.addLoadAddress(this, Framework::Assembly::RCX);
+    codeBlock.addPush(Framework::Assembly::RDX, Framework::Assembly::LOWER32);
+    codeBlock.addPush(Framework::Assembly::R8, Framework::Assembly::LOWER32);
+    codeBlock.addPush(Framework::Assembly::R9, Framework::Assembly::LOWER32);
+    codeBlock.addLoadValue(
+        (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::R9);
+    codeBlock
+        .addMemberCall<bool (JBlockTypeBoolExpression::*)(int, int, Chunk*)>(
+            &JBlockTypeBoolExpression::isValidPosition,
+            Framework::Assembly::INT_VALUE,
+            {Framework::Assembly::R9},
+            {});
+    codeBlock.addPop(Framework::Assembly::R9, Framework::Assembly::LOWER32);
+    codeBlock.addPop(Framework::Assembly::R8, Framework::Assembly::LOWER32);
+    codeBlock.addPop(Framework::Assembly::RDX, Framework::Assembly::LOWER32);
+    codeBlock.addTest(Framework::Assembly::RAX,
+        Framework::Assembly::RAX,
+        Framework::Assembly::LOWER8);
+    codeBlock.addJump(Framework::Assembly::JZ, "end");
+    codeBlock.addLoadValue(
+        (__int64*)zMemory->zzCurrentChunk(), Framework::Assembly::RCX);
+    codeBlock.addMemberCall<int (Chunk::*)(int, int, int) const>(
+        &Chunk::getBlockTypeAtWC,
+        Framework::Assembly::INT_VALUE,
+        {Framework::Assembly::RCX,
+            Framework::Assembly::RDX,
+            Framework::Assembly::R8,
+            Framework::Assembly::R9},
+        {});
+    codeBlock.addCompare(Framework::Assembly::RAX,
+        Framework::Assembly::RCX,
+        Framework::Assembly::LOWER32);
+    codeBlock.addJump(Framework::Assembly::JNE, "end_false");
+    codeBlock.addMoveValue(Framework::Assembly::RAX, (char)1);
+    codeBlock.addJump(Framework::Assembly::JMP, "end");
+    codeBlock.defineJumpTarget("end_false");
+    codeBlock.addMoveValue(Framework::Assembly::RAX, (char)0);
+    codeBlock.defineJumpTarget("end");
+    return codeBlock;
+}
+
 void JBlockTypeBoolExpression::setTypeId(int typeId)
 {
     this->typeId = typeId;

+ 63 - 11
FactoryCraft/JsonExpression.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include <Array.h>
+#include <Assembly.h>
 #include <Critical.h>
 #include <functional>
 #include <JSON.h>
@@ -31,32 +32,60 @@ public:
     void unlock();
 
     float getNoise(Framework::Text name, float x, float y, float z) const;
+    Noise* zNoiseP(Framework::Text name);
     void setNoise(Framework::Text name, Noise* noise);
     void setCurrentChunk(Chunk* chunk);
 
     float getFloatVariable(const Framework::Text& name) const;
+    float* getFloatVariableP(const Framework::Text& name);
     void setFloatVariable(const Framework::Text& name, float value);
     bool getBoolVariable(const Framework::Text& name) const;
+    bool* getBoolVariableP(const Framework::Text& name);
     void setBoolVariable(const Framework::Text& name, bool value);
     Chunk* zCurrentChunk();
+    Chunk** zzCurrentChunk();
 };
 
+typedef float (*FloatFunc)();
+
 class JFloatExpression : public virtual Framework::ReferenceCounter
 {
 private:
+    FloatFunc compiled;
+    JExpressionMemory* memory;
+
+protected:
+    Framework::Assembly::AssemblyBlock codeBlock;
 
 public:
     JFloatExpression();
-    virtual float getValue(JExpressionMemory* zMemory) = 0;
+    virtual Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory)
+        = 0;
+    virtual float getValueOld(JExpressionMemory* zMemory) = 0;
+    float getValue(JExpressionMemory* zMemory);
+    FloatFunc compile(JExpressionMemory* zMemory);
 };
 
+typedef bool (*BoolFunc)();
+
 class JBoolExpression : public virtual Framework::ReferenceCounter
 {
 private:
+    BoolFunc compiled;
+    JExpressionMemory* memory;
+
+protected:
+    Framework::Assembly::AssemblyBlock codeBlock;
 
 public:
     JBoolExpression();
-    virtual bool getValue(JExpressionMemory* zMemory) = 0;
+    virtual Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory)
+        = 0;
+    virtual bool getValueOld(JExpressionMemory* zMemory) = 0;
+    bool getValue(JExpressionMemory* zMemory);
+    BoolFunc compile(JExpressionMemory* zMemory);
 };
 
 class JVariableFloatExpression : public JFloatExpression
@@ -66,7 +95,9 @@ private:
 
 public:
     JVariableFloatExpression();
-    float getValue(JExpressionMemory* zMemory) override;
+    float getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setName(Framework::Text name);
     Framework::Text getName() const;
@@ -93,7 +124,9 @@ private:
 
 public:
     JVariableBoolExpression();
-    bool getValue(JExpressionMemory* zMemory) override;
+    bool getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setName(Framework::Text name);
     Framework::Text getName() const;
@@ -120,7 +153,9 @@ private:
 
 public:
     JConstantFloatExpression();
-    float getValue(JExpressionMemory* zMemory) override;
+    float getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setValue(float value);
     float getValue() const;
@@ -147,7 +182,9 @@ private:
 
 public:
     JConstantBoolExpression();
-    bool getValue(JExpressionMemory* zMemory) override;
+    bool getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setValue(bool value);
     bool getValue() const;
@@ -178,7 +215,9 @@ private:
 public:
     JNoiseFloatExpression();
     ~JNoiseFloatExpression();
-    float getValue(JExpressionMemory* zMemory) override;
+    float getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setName(Framework::Text name);
     Framework::Text getName() const;
@@ -213,7 +252,9 @@ private:
 
 public:
     JOperatorFloatExpression();
-    float getValue(JExpressionMemory* zMemory) override;
+    float getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setOperator(
         Framework::Text op, std::function<float(float a, float b)> accumulator);
@@ -245,7 +286,9 @@ private:
 
 public:
     JBoolOperatorBoolExpression();
-    bool getValue(JExpressionMemory* zMemory) override;
+    bool getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setOperator(
         Framework::Text op, std::function<float(float a, float b)> accumulator);
@@ -277,7 +320,9 @@ private:
 
 public:
     JFloatOperatorBoolExpression();
-    bool getValue(JExpressionMemory* zMemory) override;
+    bool getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setOperator(
         Framework::Text op, std::function<bool(float a, float b)> accumulator);
@@ -311,7 +356,14 @@ private:
 public:
     JBlockTypeBoolExpression();
     ~JBlockTypeBoolExpression();
-    bool getValue(JExpressionMemory* zMemory) override;
+
+private:
+    bool isValidPosition(int x, int y, Chunk* currentChunk);
+
+public:
+    bool getValueOld(JExpressionMemory* zMemory) override;
+    Framework::Assembly::AssemblyBlock& buildAssembly(
+        JExpressionMemory* zMemory) override;
 
     void setTypeId(int typeId);
     int getTypeId() const;

+ 6 - 1
FactoryCraft/Noise.cpp

@@ -7,4 +7,9 @@ Noise::Noise()
 double Noise::getNoise(Framework::Vec3<double>& pos)
 {
     return getNoise(pos.x, pos.y, pos.z);
-}
+}
+
+float Noise::getNoise(float x, float y, float z)
+{
+    return (float)getNoise((double)x, (double)y, (double)z);
+}

+ 1 - 0
FactoryCraft/Noise.h

@@ -17,4 +17,5 @@ public:
     /// <returns>the noise value scaled to a range from 0 to 1</returns>
     virtual double getNoise(double x, double y, double z) = 0;
     double getNoise(Framework::Vec3<double>& pos);
+    float getNoise(float x, float y, float z);
 };

+ 0 - 1
FactoryCraft/Start.cpp

@@ -112,7 +112,6 @@ int main()
     SetUnhandledExceptionFilter(exceptionHandler);
 #endif
     Framework::initFramework();
-
     Game::consoleHandler = new ConsoleHandler();
 
 #ifndef _WINDOWS

+ 4 - 2
FactoryCraft/WormCaveGenerator.cpp

@@ -208,7 +208,8 @@ NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
     {
         if (p.x == x && p.y == y) return 0;
     }
-    float cNoise = (float)wormStartNoise->getNoise(x, y, 0);
+    float cNoise
+        = (float)wormStartNoise->getNoise((double)x, (double)y, (double)0);
     if (cNoise < cavePosibillity)
     {
         FastNoiseLite* noise = new FastNoiseLite(seed + x * y + y + x);
@@ -235,7 +236,8 @@ NoiseWorm3D* WormCaveGenerator::zWormOfChunk(int x, int y)
             yaw,
             size,
             start,
-            (int)(wormStartNoise->getNoise(start.x, start.y, start.z)
+            (int)(wormStartNoise->getNoise(
+                      (double)start.x, (double)start.y, (double)start.z)
                       * (maxDistant - minDistant)
                   + minDistant),
             minRadius,

+ 1 - 0
Windows Version/Windows Version.vcxproj

@@ -141,6 +141,7 @@ copy ..\..\..\..\..\Allgemein\Framework\x64\debug\Framework.dll Framework.dll</C
       <PreprocessorDefinitions>NDEBUG;_CONSOLE;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <LanguageStandard>stdcpp20</LanguageStandard>
+      <WholeProgramOptimization>true</WholeProgramOptimization>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>