WIP ORC and ResOwner.
authorAndres Freund <andres@anarazel.de>
Tue, 14 Mar 2017 03:22:10 +0000 (20:22 -0700)
committerAndres Freund <andres@anarazel.de>
Tue, 14 Mar 2017 06:34:02 +0000 (23:34 -0700)
Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:

14 files changed:
configure
configure.in
src/backend/executor/execCompileExpr.c
src/backend/executor/execExpr.c
src/backend/executor/execInterpExpr.c
src/backend/executor/execMain.c
src/backend/executor/execTuples.c
src/backend/lib/llvmjit.c
src/backend/utils/resowner/resowner.c
src/include/executor/execExpr.h
src/include/executor/tuptable.h
src/include/lib/llvmjit.h
src/include/nodes/execnodes.h
src/include/utils/resowner_private.h

index 466b712f99aba7fdaf3e9cc0d6155deb62eff391..2049001ab4e1c1094cb1151bbb69c5776b487072 100755 (executable)
--- a/configure
+++ b/configure
@@ -6227,7 +6227,7 @@ done
         -L*) LDFLAGS="$LDFLAGS $pgac_option";;
       esac
     done
-    for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf perfjitevents`; do
+    for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf orcjit passes perfjitevents`; do
       case $pgac_option in
         -l*) LLVM_LIBS="$LLVM_LIBS $pgac_option";;
       esac
index cc867568497f2c91e793fa463880950866a15ae3..54d7643f7bb08d3930448828315494f8aca4c653 100644 (file)
@@ -863,7 +863,7 @@ if test "$with_llvm" = yes ; then
         -L*) LDFLAGS="$LDFLAGS $pgac_option";;
       esac
     done
-    for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf perfjitevents`; do
+    for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf orcjit passes perfjitevents`; do
       case $pgac_option in
         -l*) LLVM_LIBS="$LLVM_LIBS $pgac_option";;
       esac
index ba0d11d2c7a06a3b39bfefcfd699b414cbd9d815..3477a0f088bda040153e7e69497303aa0bbbad04 100644 (file)
@@ -185,7 +185,7 @@ create_EvalArrayRefCheckSubscript(LLVMModuleRef mod)
 }
 
 void
-ExecInstantiateCompiledExpr(ExprState *state)
+ExecInstantiateCompiledExpr(ExprState *state, PlanState *parent)
 {
    ExprEvalStep   *op;
    int i = 0;
@@ -277,8 +277,12 @@ ExecInstantiateCompiledExpr(ExprState *state)
    builder = LLVMCreateBuilder();
 
    /* Create the signature and function */
-   mod = LLVMModuleCreateWithName(funcname);
+   mod = LLVMModuleCreateWithName("frak");
+   LLVMSetTarget(mod, "x86_64-unknown-linux-gnu");
+
+#if 0
    LLVMAddModule(llvm_engine, mod);
+#endif
 
    {
        LLVMTypeRef param_types[] = {
@@ -288,7 +292,8 @@ ExecInstantiateCompiledExpr(ExprState *state)
        eval_sig = LLVMFunctionType(TypeSizeT, param_types, lengthof(param_types), 0);
    }
    eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
-   LLVMSetLinkage(eval_fn, LLVMInternalLinkage);
+   LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
+   LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
    entry = LLVMAppendBasicBlock(eval_fn, "entry");
 
    /* build referenced functions */
@@ -2327,12 +2332,24 @@ ExecInstantiateCompiledExpr(ExprState *state)
        }
    }
 
+#if 0
    llvm_add_module(mod, funcname);
 
-   state->cb = (ExecEvalExprCB) llvm_get_function(funcname);
+   state->cb = (ExprStateEvalFunc) llvm_get_function(funcname);
 
    LLVMDisposeBuilder(builder);
    llvm_dispose_module(mod, funcname);
+#else
+   {
+       int handle;
+       state->cb = (ExprStateEvalFunc) llvm_get_function2(mod, funcname, &handle);
+       if (parent && parent->state)
+       {
+           parent->state->es_handles = lappend_int(parent->state->es_handles, handle);
+       }
+       LLVMDisposeBuilder(builder);
+   }
+#endif
 }
 
 #endif
index d6e5337bf2d0e9e196f88c4364819ca63b736c1c..a043c8d06e55f1ee3203dab1f3bef878f5055823 100644 (file)
@@ -78,9 +78,9 @@
 /*
  * Support for building execution state.
  */
-static void ExecInstantiateExpr(ExprState *state);
-static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
-               Datum *resv, bool *resnull);
+static void ExecInstantiateExpr(ExprState *state, PlanState *parent);
+static void ExecInitExprRec(Expr *node, PlanState *parent,
+               ExprState *state, Datum *resv, bool *resnull);
 static void ExprEvalPushStep(ExprState *es, ExprEvalStep *s);
 static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
             Oid funcid, Oid inputcollid, PlanState *parent,
@@ -144,7 +144,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
    scratch.opcode = EEO_DONE;
    ExprEvalPushStep(state, &scratch);
 
-   ExecInstantiateExpr(state);
+   ExecInstantiateExpr(state, parent);
 
    return state;
 }
@@ -215,7 +215,7 @@ ExecInitQual(List *qual, PlanState *parent)
    scratch.opcode = EEO_DONE;
    ExprEvalPushStep(state, &scratch);
 
-   ExecInstantiateExpr(state);
+   ExecInstantiateExpr(state, parent);
 
    return state;
 }
@@ -370,7 +370,7 @@ ExecBuildProjectionInfo(List *targetList,
    scratch.opcode = EEO_DONE;
    ExprEvalPushStep(state, &scratch);
 
-   ExecInstantiateExpr(state);
+   ExecInstantiateExpr(state, parent);
 
    return projInfo;
 }
@@ -521,15 +521,15 @@ ExecCheck(ExprState *state, ExprContext *econtext)
  * Therefore this should be used instead of ExecInstantiateInterpretedExpr().
  */
 static void
-ExecInstantiateExpr(ExprState *state)
+ExecInstantiateExpr(ExprState *state, PlanState *parent)
 {
 #ifdef USE_LLVM
-   ExecInstantiateCompiledExpr(state);
+   ExecInstantiateCompiledExpr(state, parent);
 
    if (!state->cb)
 #endif
    {
-       ExecInstantiateInterpretedExpr(state);
+       ExecInstantiateInterpretedExpr(state, parent);
    }
 
 }
index 21388f4086e01a849160dc6c28f205f1a95e66da..d1d714bf8591ea28422e2f8b272149baf423b2b8 100644 (file)
@@ -125,7 +125,7 @@ static Datum ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool
  * Prepare ExprState for interpreted execution.
  */
 void
-ExecInstantiateInterpretedExpr(ExprState *state)
+ExecInstantiateInterpretedExpr(ExprState *state, PlanState *parent)
 {
    ExecPrepareInterp();
 
index ede675fa61b2b2e1ca879bf7f2d7557d61068351..f19b9b26a7528fec5969f4b20b0e5cb6d2b8d95c 100644 (file)
@@ -1519,6 +1519,8 @@ ExecEndPlan(PlanState *planstate, EState *estate)
     */
    ExecResetTupleTable(estate->es_tupleTable, false);
 
+   ExecResetExpressions(estate->es_handles);
+
    /*
     * close the result relation(s) if any, but hold locks until xact commit.
     */
index f002ee2561fc1ca4cd0bf33365496c0b74a002d6..e6d8ab86f5c450a9eb63410bcea47bd99469c0cf 100644 (file)
@@ -186,6 +186,19 @@ ExecResetTupleTable(List *tupleTable,  /* tuple table */
        list_free(tupleTable);
 }
 
+#include "lib/llvmjit.h"
+
+void
+ExecResetExpressions(List *exprTable)
+{
+   ListCell *lc;
+
+   foreach(lc, exprTable)
+   {
+       llvm_release_handle(CurrentResourceOwner, lfirst_int(lc));
+   }
+}
+
 /* --------------------------------
  *     MakeSingleTupleTableSlot
  *
index a70fe8a5eb385e6d8d45d8f33bfaa6b767b5470b..801598efc02066aa17b9dde6751caab0d5e3cda7 100644 (file)
@@ -8,6 +8,9 @@
 
 #include "lib/llvmjit.h"
 
+#include "utils/memutils.h"
+#include "utils/resowner_private.h"
+
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <llvm-c/Target.h>
 #include <llvm-c/Analysis.h>
 #include <llvm-c/BitWriter.h>
+#include <llvm-c/OrcBindings.h>
+#include <llvm-c/Support.h>
+#include <llvm-c/Transforms/PassManagerBuilder.h>
 
-#include "utils/memutils.h"
 
 /* GUCs */
 bool jit_log_ir = 0;
@@ -39,6 +44,11 @@ LLVMTypeRef StructItemPointerData;
 LLVMTypeRef StructBlockId;
 LLVMTypeRef StructTupleTableSlot;
 
+static char *llvm_triple = NULL;
+static LLVMTargetRef llvm_targetref;
+static LLVMTargetMachineRef llvm_targetmachine;
+static LLVMOrcJITStackRef llvm_orc;
+
 static void
 shutdown_perf(void)
 {
@@ -63,6 +73,32 @@ llvm_initialize(void)
    LLVMInitializeNativeAsmPrinter();
    LLVMInitializeNativeAsmParser();
 
+   llvm_triple = LLVMGetDefaultTargetTriple();
+
+   if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
+   {
+       fprintf(stderr, "failed to create targetref: %s\n", error);
+       abort();
+   }
+
+   llvm_targetmachine =
+       LLVMCreateTargetMachine(llvm_targetref, llvm_triple, NULL, NULL,
+                               LLVMCodeGenLevelAggressive,
+                               LLVMRelocDefault,
+                               LLVMCodeModelJITDefault);
+
+   {
+       LLVMPassManagerRef pm = LLVMCreatePassManager();
+       LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
+       LLVMPassManagerBuilderSetOptLevel(pmb, 3);
+
+       LLVMPassManagerBuilderPopulateModulePassManager(pmb, pm);
+
+       LLVMAddAnalysisPasses(llvm_targetmachine, pm);
+   }
+
+   llvm_orc = LLVMOrcCreateInstance(llvm_targetmachine);
+
    llvm_mod = LLVMModuleCreateWithName("top_module");
    LLVMSetTarget(llvm_mod, "x86_64-unknown-linux-gnu");
 
@@ -224,4 +260,65 @@ llvm_dispose_module(LLVMModuleRef mod, const char *funcname)
    }
 }
 
+#include "executor/tuptable.h"
+static uint64_t
+resolver(const char *name, void *ctx)
+{
+   return (uint64_t) LLVMSearchForAddressOfSymbol(name);
+   if (strcmp(name, "slot_getsomeattrs") == 0)
+       return (uint64_t) slot_getsomeattrs;
+   //elog(ERROR, "resolvin %s", name);
+   return 0;
+}
+
+void *
+llvm_get_function2(LLVMModuleRef mod, const char *funcname, int *handle)
+{
+   void *addr;
+   char *mangled;
+
+   if (jit_log_ir)
+   {
+       LLVMDumpModule(mod);
+   }
+
+
+   LLVMOrcGetMangledSymbol(llvm_orc, &mangled, funcname);
+
+   *handle =
+       LLVMOrcAddEagerlyCompiledIR(llvm_orc, mod,
+                                   resolver, NULL);
+
+   ResourceOwnerEnlargeJIT(CurrentResourceOwner);
+   ResourceOwnerRememberJIT(CurrentResourceOwner, *handle);
+
+   addr = (void *) LLVMOrcGetSymbolAddress(llvm_orc, mangled);
+
+   if (!addr)
+       elog(ERROR, "failed to JIT: %s %s", funcname, mangled);
+
+   return addr;
+}
+
 #endif /* USE_LLVM */
+
+
+#ifdef USE_LLVM
+
+extern void
+llvm_release_handle(ResourceOwner resowner, Datum handle)
+{
+   LLVMOrcRemoveModule(llvm_orc, handle);
+
+   ResourceOwnerForgetJIT(resowner, handle);
+
+}
+
+#else
+
+extern void
+llvm_release_handle(ResourceOwner resowner, Datum handle)
+{
+}
+
+#endif
index af46d781253e2834e0c330e7fc83776710e53847..8f51b21ec60333c6724fbb1cb252b90a6f1a9595 100644 (file)
@@ -27,6 +27,7 @@
 #include "utils/rel.h"
 #include "utils/resowner_private.h"
 #include "utils/snapmgr.h"
+#include "lib/llvmjit.h"
 
 
 /*
@@ -124,6 +125,7 @@ typedef struct ResourceOwnerData
    ResourceArray snapshotarr;  /* snapshot references */
    ResourceArray filearr;      /* open temporary files */
    ResourceArray dsmarr;       /* dynamic shmem segments */
+   ResourceArray jitarr;       /* JIT handles */
 
    /* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
    int         nlocks;         /* number of owned locks */
@@ -437,6 +439,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name)
    ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL));
    ResourceArrayInit(&(owner->filearr), FileGetDatum(-1));
    ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
+   ResourceArrayInit(&(owner->jitarr), Int32GetDatum(-1));
 
    return owner;
 }
@@ -552,6 +555,13 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
                PrintDSMLeakWarning(res);
            dsm_detach(res);
        }
+
+               /* Ditto for dynamic shared memory segments */
+       while (ResourceArrayGetAny(&(owner->jitarr), &foundres))
+       {
+           llvm_release_handle(owner, foundres);
+       }
+
    }
    else if (phase == RESOURCE_RELEASE_LOCKS)
    {
@@ -699,6 +709,7 @@ ResourceOwnerDelete(ResourceOwner owner)
    Assert(owner->snapshotarr.nitems == 0);
    Assert(owner->filearr.nitems == 0);
    Assert(owner->dsmarr.nitems == 0);
+   Assert(owner->jitarr.nitems == 0);
    Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1);
 
    /*
@@ -725,6 +736,7 @@ ResourceOwnerDelete(ResourceOwner owner)
    ResourceArrayFree(&(owner->snapshotarr));
    ResourceArrayFree(&(owner->filearr));
    ResourceArrayFree(&(owner->dsmarr));
+   ResourceArrayFree(&(owner->jitarr));
 
    pfree(owner);
 }
@@ -1267,3 +1279,23 @@ PrintDSMLeakWarning(dsm_segment *seg)
    elog(WARNING, "dynamic shared memory leak: segment %u still referenced",
         dsm_segment_handle(seg));
 }
+
+void
+ResourceOwnerEnlargeJIT(ResourceOwner owner)
+{
+   ResourceArrayEnlarge(&(owner->jitarr));
+}
+
+void
+ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
+{
+   ResourceArrayAdd(&(owner->jitarr), handle);
+}
+
+void
+ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
+{
+   if (!ResourceArrayRemove(&(owner->jitarr), handle))
+       elog(ERROR, "jit %lu is not owned by resource owner %s",
+            handle, owner->name);
+}
index 62adc5bfdf6d0c6e1bccf24a71905dbf1bc48fc3..7843d77e6f0306d161e3f1193b4ca970ef2ac68a 100644 (file)
@@ -417,8 +417,8 @@ typedef struct ArrayRefState
    bool        prevnull;
 }  ArrayRefState;
 
-extern void ExecInstantiateInterpretedExpr(ExprState *state);
-extern void ExecInstantiateCompiledExpr(ExprState *state);
+extern void ExecInstantiateInterpretedExpr(ExprState *state, PlanState *parent);
+extern void ExecInstantiateCompiledExpr(ExprState *state, PlanState *parent);
 
 extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
 
index 32489ef9bde05519f3defbb334d7ff6b14e52819..e1a2a2d1a3d1b8dd4645e3266f654ae7d08ac4e6 100644 (file)
@@ -142,6 +142,7 @@ typedef struct TupleTableSlot
 extern TupleTableSlot *MakeTupleTableSlot(void);
 extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable);
 extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
+extern void ExecResetExpressions(List *exprTable);
 extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
 extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
 extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
index 678320485ad03aad7594c9cac1d786cb054b471b..79ce569390e4bf7e03beed262dd1aab178d087f9 100644 (file)
@@ -1,5 +1,8 @@
 #ifndef LLVMJIT_H
 #define LLVMJIT_H
+
+#include "utils/resowner.h"
+
 #ifdef USE_LLVM
 
 #undef PM
@@ -29,8 +32,14 @@ extern void llvm_add_module(LLVMModuleRef mod, const char *funcname);
 extern void * llvm_get_function(const char *funcname);
 extern void llvm_dispose_module(LLVMModuleRef mod, const char *funcname);
 
+extern void * llvm_get_function2(LLVMModuleRef mod, const char *funcname, int *handle);
+
+
 extern void llvm_perf_support(LLVMExecutionEngineRef EE);
 extern void llvm_shutdown_perf_support(LLVMExecutionEngineRef EE);
 
 #endif /* USE_LLVM */
+
+extern void llvm_release_handle(ResourceOwner resowner, Datum handle);
+
 #endif /* LLVMJIT_H */
index 8d303827466fee70ae8f194c5d1b50953e8e31b1..b08ba73749f99890de5f026b1417795650ee56e6 100644 (file)
@@ -445,7 +445,10 @@ typedef struct EState
    bool       *es_epqScanDone; /* true if EPQ tuple has been fetched */
 
    /* The per-query shared memory area to use for parallel execution. */
-   struct dsa_area *es_query_dsa;
+   struct dsa_area   *es_query_dsa;
+
+   List       *es_handles;
+
 } EState;
 
 
index 411d08ff0b20bc9798f471154947e8011bf0deb8..e45d3b0aa9c3efe70c3bc16865ef3ea464687aea 100644 (file)
@@ -88,4 +88,11 @@ extern void ResourceOwnerRememberDSM(ResourceOwner owner,
 extern void ResourceOwnerForgetDSM(ResourceOwner owner,
                       dsm_segment *);
 
+/* support for JITed functions */
+extern void ResourceOwnerEnlargeJIT(ResourceOwner owner);
+extern void ResourceOwnerRememberJIT(ResourceOwner owner,
+                                    Datum handle);
+extern void ResourceOwnerForgetJIT(ResourceOwner owner,
+                                  Datum handle);
+
 #endif   /* RESOWNER_PRIVATE_H */