Commits

ebo committed 6c0b96d

Prepared infrastructure for function inlineing.

Comments (0)

Files changed (1)

 new file mode 100644
 --- /dev/null
 +++ b/JIT/global_jit_data.h
-@@ -0,0 +1,172 @@
+@@ -0,0 +1,171 @@
 +// -*- C++ -*-
 +//
 +
 +
 +private:
 +  void do_trace(PyCodeObject *code, size_t start);
-+  bool verify_trace(std::vector<TraceEntry> &trace);
 +
 +private:
 +  bool active_;
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_tracer.cc
-@@ -0,0 +1,889 @@
+@@ -0,0 +1,986 @@
 +#include "Python.h"
 +#include "opcode.h"
 +
 +{
 +}
 +
-+bool
-+PyJITTracer::verify_trace(std::vector<TraceEntry> &trace)
++static bool
++verify_trace(std::vector<TraceEntry>::iterator &iter,
++             std::vector<TraceEntry>::iterator &end,
++             bool inlined=false)
 +{
-+  for (size_t i = 0; i < trace.size(); ++i) {
-+    int pc = trace[i].pc;
-+    int opcode = trace[i].opcode;
-+    int oparg = trace[i].oparg;
-+    int flag = trace[i].flag;
++  for (; iter != end; ++iter) {
++    int pc = iter->pc;
++    int opcode = iter->opcode;
++    int oparg = iter->oparg;
++    int flag = iter->flag;
++
 +    switch (opcode) {
++    case JIT_EXIT_FUNC:
++      return inlined;
++
 +    case POP_JUMP_IF_FALSE:
 +      if (flag != TR_STANDARD) {
 +        // if (flag != TR_STANDARD && flag != TR_JUMP_TAKEN) {
 +    case DUP_TOP:
 +    case DUP_TOP_TWO:
 +    case STORE_SUBSCR:
-+    case CALL_FUNCTION:
 +
 +    case INPLACE_ADD:
 +    case INPLACE_SUBTRACT:
 +      }
 +      break;
 +
++    case RETURN_VALUE:
++      {
++        if (flag != TR_STANDARD) {
++          return false;
++        }
++        if (iter + 1 == end) {
++          return false;
++        }
++
++        ++iter;
++        return iter->opcode == JIT_EXIT_FUNC;
++      }
++
++    case CALL_FUNCTION:
++      {
++        if (flag != TR_STANDARD) {
++          return false;
++        }
++
++        // int na = oparg & 0xff;
++        int nk = (oparg >> 8) & 0xff;
++
++        if (nk > 0)
++          return false;
++
++        if (iter + 1 == end) {
++          break;
++        }
++
++        std::vector<TraceEntry>::iterator next = iter + 1;
++        if (next->opcode == JIT_ENTER_FUNC) {
++          iter += 2;
++          bool result = verify_trace(iter, end, true);
++          if (!result)
++            return false;
++
++          if (iter == end || iter->opcode != JIT_EXIT_FUNC)
++            return false;
++          std::vector<TraceEntry>::iterator prev = iter - 1;
++          if (prev->opcode != RETURN_VALUE)
++            return false;
++        }
++
++        break;
++      }
++
 +    case COMPARE_OP:
 +      switch (oparg) {
 +      case PyCmp_IS:
 +      break;
 +    }
 +  }
-+  return true;
++  return !inlined;
 +}
 +
 +#define JIT_COMPILE_TIME
 +#endif
 +
 +  std::vector<TraceEntry> cut_trace(trace_.begin() + start, trace_.end());
-+  if (!this->verify_trace(cut_trace)) {
++  std::vector<TraceEntry>::iterator tr_begin = cut_trace.begin();
++  std::vector<TraceEntry>::iterator tr_end = cut_trace.end();
++  if (!verify_trace(tr_begin, tr_end)) {
 +    std::cout << "Trace contains unkown opcodes\n";
 +    unsuspend();
 +    return;
 +  }
 +
 +  jit::JITTraceAnalysis analysis;
-+  analysis.analyseTrace(cut_trace);
++  tr_begin = cut_trace.begin();
++  tr_end = cut_trace.end();
++  analysis.analyseTrace(tr_begin, tr_end);
 +  // std::cout << "-------------------------------\n";
 +  // analysis.dump();
 +  // std::cout << "-------------------------------\n";
 +  }
 +
 +  void
-+  JITTraceAnalysis::createCallFunctionOp(JITStack &stack, JITLocals &locals, TraceEntry &entry)
++  JITTraceAnalysis::createCallFunctionOp(JITStack &stack, JITLocals &locals,
++                                         std::vector<TraceEntry>::iterator &iter,
++                                         std::vector<TraceEntry>::iterator &end)
 +  {
-+    int oparg = entry.oparg;
-+    std::vector<JITValue *> args(oparg, NULL);
++    int oparg = iter->oparg;
++    int na = oparg & 0xff;
++    std::vector<JITValue *> args(na, NULL);
 +    while (--oparg >= 0) {
 +      args[oparg] = stack.Pop();
 +    }
 +    JITValue *func = stack.Pop();
 +    JITValue *res = this->createCallFunction(func, args, stack, locals);
-+    this->createGuardNull(res, BH_EXC_RAISED, entry.pc, stack, locals);
++    this->createGuardNull(res, BH_EXC_RAISED, iter->pc, stack, locals);
 +    stack.Push(res);
++
++    std::vector<TraceEntry>::iterator next = iter + 1;
++    if (next->opcode == JIT_ENTER_FUNC) {
++      iter = next;
++      swallowTrace(iter, end);
++    }
 +  }
 +
 +  void
-+  JITTraceAnalysis::analyseTrace(std::vector<TraceEntry> &trace)
++  JITTraceAnalysis::swallowTrace(std::vector<TraceEntry>::iterator &iter,
++                                 std::vector<TraceEntry>::iterator &end)
++  {
++    assert(iter->opcode == JIT_ENTER_FUNC);
++    ++iter;
++
++    for (; iter != end; ++iter) {
++      switch(iter->opcode) {
++      case CALL_FUNCTION:
++        {
++          std::vector<TraceEntry>::iterator next = iter + 1;
++          if (next->opcode == JIT_ENTER_FUNC) {
++            iter = next;
++            swallowTrace(iter, end);
++          }
++          continue;
++        }
++
++      case JIT_EXIT_FUNC:
++        return;
++
++      default:
++        continue;
++      }
++    }
++    assert(false);
++  }
++
++  void
++  JITTraceAnalysis::analyseTrace(std::vector<TraceEntry>::iterator &iter,
++                                 std::vector<TraceEntry>::iterator &end)
 +  {
 +    JITStack stack;
 +    JITLocals locals(0);
-+    for (size_t i = 0; i < trace.size(); ++i) {
-+      TraceEntry &entry = trace[i];
-+      int opcode = entry.opcode;
-+      int flag = entry.flag;
-+
-+      this->createOpcodeInfo(entry.pc, stack, locals);
++    for (; iter != end; ++iter) {
++      int pc = iter->pc;
++      int opcode = iter->opcode;
++      int oparg = iter->oparg;
++      int flag = iter->flag;
++      PyTypeObject* arg0 = iter->arg0;
++      PyTypeObject* arg1 = iter->arg1;
++
++      this->createOpcodeInfo(pc, stack, locals);
 +
 +      JITValue *w = NULL;
 +      JITValue *v = NULL;
 +      case POP_JUMP_IF_FALSE:
 +        v = stack.Pop();
 +        if (flag == TR_STANDARD) {
-+          this->createGuardTrue(v, BH_JUMP_ARG, entry.pc, stack, locals);
++          this->createGuardTrue(v, BH_JUMP_ARG, pc, stack, locals);
 +        }
 +        continue;
 +
 +      case CALL_FUNCTION:
-+        this->createCallFunctionOp(stack, locals, entry);
++        this->createCallFunctionOp(stack, locals, iter, end);
 +        continue;
 +
 +      case FOR_ITER:
 +        v = stack.Top();
 +        x = this->createForIter(v);
-+        this->createGuardNull(x, BH_FOR_ITER_EXC, entry.pc, stack, locals);
++        this->createGuardNull(x, BH_FOR_ITER_EXC, pc, stack, locals);
 +        stack.Push(x);
 +        continue;
 +
 +      case STORE_FAST:
-+        w = locals.Load(entry.oparg);
++        w = locals.Load(oparg);
 +        this->createXDecRef(w);
 +
 +        v = stack.Pop();
-+        if (entry.arg0 != NULL)
-+          v->registerStaticType(entry.arg0);
-+        locals.Store(entry.oparg, v);
++        if (arg0 != NULL)
++          v->registerStaticType(arg0);
++        locals.Store(oparg, v);
 +        continue;
 +
 +      case LOAD_FAST:
-+        v = locals.Load(entry.oparg);
-+        this->createGuardNull(v, BH_LOAD_FAST_FAIL, entry.pc, stack, locals);
++        v = locals.Load(oparg);
++        this->createGuardNull(v, BH_LOAD_FAST_FAIL, pc, stack, locals);
 +        this->createIncRef(v);
 +        stack.Push(v);
 +        continue;
 +
 +      case LOAD_CONST:
-+        v = this->createLoadConst(entry.oparg);
++        v = this->createLoadConst(oparg);
 +        this->createIncRef(v);
 +        stack.Push(v);
 +        continue;
 +
 +      case LOAD_GLOBAL:
-+        v = this->createLoadGlobal(entry.oparg);
-+        this->createGuardNull(v, BH_EXC_RAISED, entry.pc, stack, locals);
++        v = this->createLoadGlobal(oparg);
++        this->createGuardNull(v, BH_EXC_RAISED, pc, stack, locals);
 +        this->createIncRef(v);
 +        stack.Push(v);
 +        continue;
 +      case INPLACE_MULTIPLY:
 +      case INPLACE_FLOOR_DIVIDE:
 +      case INPLACE_TRUE_DIVIDE:
-+        this->createBinaryOp(true, stack, locals, entry);
++        this->createBinaryOp(true, stack, locals, *iter);
 +        continue;
 +
 +      case BINARY_ADD:
 +      case BINARY_FLOOR_DIVIDE:
 +      case BINARY_TRUE_DIVIDE:
 +      case BINARY_SUBSCR:
-+        this->createBinaryOp(false, stack, locals, entry);
++        this->createBinaryOp(false, stack, locals, *iter);
 +        continue;
 +
 +      case COMPARE_OP:
 +        w = stack.Pop();
 +        v = stack.Pop();
-+        if (entry.arg0 != NULL)
-+          v->registerStaticType(entry.arg0);
-+        if (entry.arg1 != NULL)
-+          w->registerStaticType(entry.arg1);
-+        x = this->createCompareOp(v, w, entry.oparg);
-+        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack, locals);
++        if (arg0 != NULL)
++          v->registerStaticType(arg0);
++        if (arg1 != NULL)
++          w->registerStaticType(arg1);
++        x = this->createCompareOp(v, w, oparg);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, pc, stack, locals);
 +        stack.Push(x);
 +        continue;
 +
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_tracer.h
-@@ -0,0 +1,945 @@
+@@ -0,0 +1,951 @@
 +// -*- C++ -*-
 +#ifndef PYTHON_JIT_TRACER_H_
 +#define PYTHON_JIT_TRACER_H_
 +
 +    JITTraceAnalysis();
 +
-+    void analyseTrace(std::vector<TraceEntry> &trace);
++    void analyseTrace(std::vector<TraceEntry>::iterator &iter,
++                      std::vector<TraceEntry>::iterator &end);
++
++    void swallowTrace(std::vector<TraceEntry>::iterator &iter,
++                      std::vector<TraceEntry>::iterator &end);
 +
 +    void dump()
 +    {
 +
 +    void createBinaryOp(bool inplace, JITStack &stack, JITLocals &locals, TraceEntry &entry);
 +
-+    void createCallFunctionOp(JITStack &stack, JITLocals &locals, TraceEntry &entry);
++    void createCallFunctionOp(JITStack &stack, JITLocals &locals,
++                              std::vector<TraceEntry>::iterator &iter,
++                              std::vector<TraceEntry>::iterator &end);
 +
 +    JITCallFunction *createCallFunction(JITValue *func, std::vector<JITValue *> &args,
 +                                        JITStack &stack, JITLocals &locals)
      Py_LeaveRecursiveCall();
      tstate->frame = f->f_back;
  
+@@ -4030,6 +4134,8 @@
+     PyObject **pfunc = (*pp_stack) - n - 1;
+     PyObject *func = *pfunc;
+     PyObject *x, *w;
++    PyJITTracer *trace = PyJITTracer_GET();
++    trace->setType(0, func->ob_type);
+ 
+     /* Always dispatch PyCFunction first, because these are
+        presumed to be the most frequent callable object.
 diff --git a/Python/pystate.c b/Python/pystate.c
 --- a/Python/pystate.c
 +++ b/Python/pystate.c
 new file mode 100644
 --- /dev/null
 +++ b/dotests.py
-@@ -0,0 +1,235 @@
+@@ -0,0 +1,248 @@
 +import unittest
 +import _jit
 +
 +        self.analyse(doit, self.seq_float)
 +        self.analyse(doit, self.seq_int)
 +
++    def testCallPythonFunc(self):
++        def doit(seq):
++            acc = 0.0
++            x = lambda v: v
++            for i in seq:
++                acc += x(i)
++            return acc
++
++        self.analyse(doit, self.seq_float)
++        self.analyse(doit, self.seq_int)
++        ftxt = doit.__code__._dump_jit()
++        self.assertTrue("PyObject_Call" in ftxt)
++
 +
 +class TestCompares(Utilities, unittest.TestCase):
 +    def testComparesSimple(self):