ebo avatar ebo committed fa30ce1

Initial commit.

Comments (0)

Files changed (4)

+^\.hg
+^\.mq
+syntax: glob
+status
+guards
+# HG changeset patch
+# Parent 7b530b3ed07bbc09b6ea3ef291ce796f06f54f0b
+
+diff --git a/JIT/global_jit_data.cc b/JIT/global_jit_data.cc
+--- a/JIT/global_jit_data.cc
++++ b/JIT/global_jit_data.cc
+@@ -50,7 +50,6 @@
+     llvm::StringRef elem = sys_path[i];
+     path = elem;
+     path.appendComponent(LIBPYTHON_BC);
+-    std::cout << path.str() << "\n";
+     llvm::OwningPtr<llvm::MemoryBuffer> stdlib_file;
+     if(!llvm::MemoryBuffer::getFile(path.str(), stdlib_file)) {
+       return stdlib_file.take();
+@@ -60,7 +59,6 @@
+     llvm::StringRef elem = "./Modules";
+     path = elem;
+     path.appendComponent(LIBPYTHON_BC);
+-    std::cout << path.str() << "\n";
+     llvm::OwningPtr<llvm::MemoryBuffer> stdlib_file;
+     if(!llvm::MemoryBuffer::getFile(path.str(), stdlib_file)) {
+       return stdlib_file.take();
+diff --git a/JIT/global_jit_data.h b/JIT/global_jit_data.h
+--- a/JIT/global_jit_data.h
++++ b/JIT/global_jit_data.h
+@@ -114,11 +114,15 @@
+     if (!active_ || suspended_)
+       return;
+     TraceEntry &entry = trace_.back();
+-    if (pos == 0) {
++    switch (pos) {
++    case 0:
+       entry.arg0 = type;
+-    }
+-    else {
++      break;
++    case 1:
+       entry.arg1 = type;
++      break;
++    default:
++      break;
+     }
+   }
+ 
+diff --git a/JIT/global_jit_data_fwd.h b/JIT/global_jit_data_fwd.h
+--- a/JIT/global_jit_data_fwd.h
++++ b/JIT/global_jit_data_fwd.h
+@@ -17,6 +17,9 @@
+ void PyJITTracer_Clear(struct PyJITTracer *);
+ void PyJITTracer_Free(struct PyJITTracer *);
+ 
++struct _JITFunction;
++void PyJITFunction_Free(struct _JITFunction* obj);
++
+ int _PyJIT_Init(void);
+ void _PyJIT_Fini(void);
+ 
+diff --git a/JIT/jit_tracer.cc b/JIT/jit_tracer.cc
+--- a/JIT/jit_tracer.cc
++++ b/JIT/jit_tracer.cc
+@@ -66,7 +66,7 @@
+   std::vector<TraceEntry> cut_trace(trace_.begin() + start, trace_.end());
+   bool verified = true;
+   for (size_t i = 0; i < cut_trace.size(); ++i) {
+-    // int pc = trace_[i].pc;
++    int pc = cut_trace[i].pc;
+     int opcode = cut_trace[i].opcode;
+     int oparg = cut_trace[i].oparg;
+     int flag = cut_trace[i].flag;
+@@ -109,13 +109,14 @@
+       break;
+ 
+     default:
+-      std::cout << opcode << " ";
++      std::cout << "(" << pc << " " << opcode << ") ";
+       verified = false;
+       break;
+     }
+   }
+   if (!verified) {
+     std::cout << "Trace contains unkown opcodes\n";
++    unsuspend();
+     return;
+   }
+ 
+@@ -160,7 +161,8 @@
+ }
+ 
+ void
+-PyJITTracer::trace(PyCodeObject *code, int pc, int opcode, int oparg)
++PyJITTracer::trace(PyCodeObject *code,
++                   int pc, int opcode, int oparg)
+ {
+   if (!active_)
+     return;
+@@ -207,11 +209,11 @@
+   }
+ 
+   JITValue *
+-  JITTraceAnalysis::Pop()
++  JITTraceAnalysis::Pop(stack_t &stack)
+   {
+-    if (stack_.size() > 0) {
+-      JITValue *v = stack_.back();
+-      stack_.pop_back();
++    if (stack.size() > 0) {
++      JITValue *v = stack.back();
++      stack.pop_back();
+       return v;
+     }
+ 
+@@ -221,22 +223,23 @@
+   }
+ 
+   JITValue *
+-  JITTraceAnalysis::Top()
++  JITTraceAnalysis::Top(stack_t &stack)
+   {
+-    JITValue *v = this->Pop();
+-    this->Push(v);
++    JITValue *v = this->Pop(stack);
++    this->Push(stack, v);
+     return v;
+   }
+ 
+   void
+-  JITTraceAnalysis::Push(JITValue *value)
++  JITTraceAnalysis::Push(stack_t &stack, JITValue *value)
+   {
+-    stack_.push_back(value);
++    stack.push_back(value);
+   }
+ 
+   void
+   JITTraceAnalysis::analyseTrace(std::vector<TraceEntry> &trace)
+   {
++    stack_t stack;
+     for (size_t i = 0; i < trace.size(); ++i) {
+       TraceEntry &entry = trace[i];
+       int opcode = entry.opcode;
+@@ -249,87 +252,113 @@
+ 
+ 
+       case POP_JUMP_IF_FALSE:
+-        v = this->Pop();
++        v = this->Pop(stack);
+         if (flag == TR_STANDARD) {
+-          this->createGuardTrue(v, BH_JUMP_ARG, entry.pc);
++          this->createGuardTrue(v, BH_JUMP_ARG, entry.pc, stack);
+         }
+         continue;
+ 
+       case FOR_ITER:
+-        v = this->Top();
++        v = this->Top(stack);
+         x = this->createForIter(v);
+-        this->createGuardNull(x, BH_FOR_ITER_EXC, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_FOR_ITER_EXC, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case STORE_FAST:
+-        v = this->Pop();
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
+         this->createStoreFast(v, entry.oparg);
+         continue;
+ 
+       case LOAD_FAST:
+         v = this->createLoadFast(entry.oparg);
+-        this->createGuardNull(v, BH_LOAD_FAST_FAIL, entry.pc);
++        this->createGuardNull(v, BH_LOAD_FAST_FAIL, entry.pc, stack);
+         this->createIncRef(v);
+-        this->Push(v);
++        this->Push(stack, v);
+         continue;
+ 
+       case LOAD_CONST:
+         v = this->createLoadConst(entry.oparg);
+         this->createIncRef(v);
+-        this->Push(v);
++        this->Push(stack, v);
+         continue;
+ 
+       case INPLACE_ADD:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
++        if (entry.arg1 != NULL)
++          w->registerStaticType(entry.arg1);
+         x = this->createInplaceAdd(v, w);
+-        this->createGuardNull(x, BH_INPLACE_ADD_FAIL, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_INPLACE_ADD_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case BINARY_ADD:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
++        if (entry.arg1 != NULL)
++          w->registerStaticType(entry.arg1);
+         x = this->createBinaryAdd(v, w);
+-        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case BINARY_SUBTRACT:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
++        if (entry.arg1 != NULL)
++          w->registerStaticType(entry.arg1);
+         x = this->createBinarySubtract(v, w);
+-        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case BINARY_MULTIPLY:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
++        if (entry.arg1 != NULL)
++          w->registerStaticType(entry.arg1);
+         x = this->createBinaryMultiply(v, w);
+-        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case BINARY_FLOOR_DIVIDE:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        if (entry.arg0 != NULL)
++          v->registerStaticType(entry.arg0);
++        if (entry.arg1 != NULL)
++          w->registerStaticType(entry.arg1);
+         x = this->createBinaryDivide(v, w);
+-        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc);
+-        this->Push(x);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+ 
+       case COMPARE_OP:
+-        w = this->Pop();
+-        v = this->Pop();
++        w = this->Pop(stack);
++        v = this->Pop(stack);
++        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);
+-        this->Push(x);
++        this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++        this->Push(stack, x);
+         continue;
+       }
+     }
+-    this->createTraceEnd();
++    this->createTraceEnd(stack);
+   }
+ 
+ 
+@@ -337,6 +366,7 @@
+   JITStackValue::emit(JITFunctionBuilder &builder)
+   {
+     value_ = builder.Pop();
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -351,6 +381,7 @@
+                          "tp_iternext");
+ 
+     value_ = fbuilder.getState()->CreateCall(tp_iternext, v);
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -370,6 +401,7 @@
+     JITFunctionState::BuilderT &builder = fbuilder.builder();
+     llvm::Value *localptr = fbuilder.LocalPtr(oparg_);
+     value_ = builder.CreateLoad(localptr);
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -378,6 +410,7 @@
+     JITFunctionState::BuilderT &builder = fbuilder.builder();
+     llvm::Value *localptr = fbuilder.ConstPtr(oparg_);
+     value_ = builder.CreateLoad(localptr);
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -385,12 +418,25 @@
+   {
+     JITFunctionState *state = fbuilder.getState();
+ 
++    if (arg0_->getStaticType()->isFloat() &&
++        arg1_->getStaticType()->isFloat() &&
++        this->getStaticType()->isFloat()) {
++      std::cout << "InplaceAdd may be specialized\n";
++      JITType *type0 = arg0_->getStaticType();
++      JITType *type1 = arg1_->getStaticType();
++
++      llvm::Value *naked0 = type0->getNakedValue(fbuilder);
++      llvm::Value *naked1 = type0->getNakedValue(fbuilder);
++
++    }
++
+     Value *func = state->GetGlobalFunction<PyObject*(PyObject*, PyObject*)>("PyNumber_InPlaceAdd");
+     value_ = state->CreateCall(func,
+                                arg0_->getValue(),
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -404,6 +450,7 @@
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -417,6 +464,7 @@
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -430,6 +478,7 @@
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -443,6 +492,7 @@
+                                arg1_->getValue());
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+@@ -457,6 +507,7 @@
+ 
+     state->DecRef(arg0_->getValue());
+     state->DecRef(arg1_->getValue());
++    this->getStaticType()->init(value_);
+   }
+ 
+   void
+diff --git a/JIT/jit_tracer.h b/JIT/jit_tracer.h
+--- a/JIT/jit_tracer.h
++++ b/JIT/jit_tracer.h
+@@ -9,24 +9,57 @@
+ #include "JIT/global_jit_data.h"
+ #include "JIT/jit_blackhole.h"
+ #include "JIT/jit_fbuilder.h"
++#include "JIT/jit_types.h"
+ 
+ #include <vector>
+ #include <iostream>
+ 
+ namespace jit {
+ 
+-  class JITValue {
++  class JITOpcode {
+   public:
+     virtual void dump() = 0;
+     virtual void emit(JITFunctionBuilder &builder) = 0;
++  };
++
++  class JITValue : public JITOpcode {
++  public:
++    // virtual llvm::Value *getOrMaterializeValue(JITFunctionBuilder &builder) = 0;
+     virtual llvm::Value *getValue() const = 0;
++    virtual JITType *getStaticType() const = 0;
++    virtual void registerStaticType(const PyTypeObject *) = 0;
++  };
++
++  class JITOpcodeInfo : public JITOpcode {
++  public:
++    JITOpcodeInfo(int lasti, std::vector<JITValue *> &stack)
++      : lasti_(lasti), stack_(stack)
++    {
++    }
++
++    virtual void dump()
++    {
++      std::cout << "OPCODE_INFO\n";
++    }
++
++    virtual void emit(JITFunctionBuilder &)
++    {}
++
++  private:
++    int lasti_;
++    std::vector<JITValue *> stack_;
+   };
+ 
+   class JITStackValue : public JITValue {
+   public:
+     JITStackValue()
+-      : value_(NULL)
++      : value_(NULL), type_(new JITOpaqueObject)
+     {}
++    ~JITStackValue()
++    {
++      delete type_;
++    }
++
+     virtual void dump()
+     {
+       std::cout << "Stack Value\n";
+@@ -34,16 +67,39 @@
+     virtual void emit(JITFunctionBuilder &builder);
+     virtual llvm::Value *getValue() const
+     {
+-      return value_;
++      return getStaticType()->getValue();
++    }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *t)
++    {
++      if (type_ == NULL || type_->canSpecialize(t)) {
++        JITType *new_type = JITType::createBoxedType(t);
++        if (new_type != NULL) {
++          JITType *old_type = type_;
++          type_ = new_type;
++          delete old_type;
++        }
++      }
++      else {
++        if (!type_->matchesType(t)) {
++          std::cout << "Trace Type mismatch\n";
++        }
++      }
+     }
+ 
+   private:
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITForIter : public JITValue {
+   public:
+-    JITForIter(JITValue *arg) : arg_(arg), value_(NULL)
++    JITForIter(JITValue *arg) : arg_(arg), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -55,17 +111,41 @@
+ 
+     virtual llvm::Value *getValue() const
+     {
+-      return value_;
++      return getStaticType()->getValue();
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *t)
++    {
++      if (type_ == NULL || type_->canSpecialize(t)) {
++        JITType *new_type = JITType::createBoxedType(t);
++        if (new_type != NULL) {
++          JITType *old_type = type_;
++          type_ = new_type;
++          delete old_type;
++        }
++      }
++      else {
++        if (!type_->matchesType(t)) {
++          std::cout << "Trace Type mismatch\n";
++        }
++      }
++    }
++
+   private:
+     JITValue *arg_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+-  class JITStoreFast : public JITValue {
++  class JITStoreFast : public JITOpcode {
+   public:
+     JITStoreFast(JITValue *arg, int oparg)
+-      : arg_(arg), oparg_(oparg), value_(NULL)
++      : arg_(arg), oparg_(oparg)
+     {}
+ 
+     virtual void dump()
+@@ -75,20 +155,15 @@
+ 
+     virtual void emit(JITFunctionBuilder &builder);
+ 
+-    virtual llvm::Value *getValue() const
+-    {
+-      return value_;
+-    }
+   private:
+     JITValue *arg_;
+     int oparg_;
+-    llvm::Value *value_;
+   };
+ 
+   class JITLoadFast : public JITValue {
+   public:
+     JITLoadFast(int oparg)
+-      : oparg_(oparg), value_(NULL)
++      : oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -100,17 +175,41 @@
+ 
+     virtual llvm::Value *getValue() const
+     {
+-      return value_;
++      return getStaticType()->getValue();
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *t)
++    {
++      if (type_ == NULL || type_->canSpecialize(t)) {
++        JITType *new_type = JITType::createBoxedType(t);
++        if (new_type != NULL) {
++          JITType *old_type = type_;
++          type_ = new_type;
++          delete old_type;
++        }
++      }
++      else {
++        if (!type_->matchesType(t)) {
++          std::cout << "Trace Type mismatch\n";
++        }
++      }
++    }
++
+   private:
+     int oparg_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITLoadConst : public JITValue {
+   public:
+     JITLoadConst(int oparg)
+-      : oparg_(oparg), value_(NULL)
++      : oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -124,15 +223,26 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     int oparg_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITInplaceAdd : public JITValue {
+   public:
+     JITInplaceAdd(JITValue *arg0, JITValue *arg1)
+-      : arg0_(arg0), arg1_(arg1), value_(NULL)
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -144,18 +254,42 @@
+ 
+     virtual llvm::Value *getValue() const
+     {
+-      return value_;
++      return getStaticType()->getValue();
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *t)
++    {
++      if (type_ == NULL || type_->canSpecialize(t)) {
++        JITType *new_type = JITType::createBoxedType(t);
++        if (new_type != NULL) {
++          JITType *old_type = type_;
++          type_ = new_type;
++          delete old_type;
++        }
++      }
++      else {
++        if (!type_->matchesType(t)) {
++          std::cout << "Trace Type mismatch\n";
++        }
++      }
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITBinaryAdd : public JITValue {
+   public:
+     JITBinaryAdd(JITValue *arg0, JITValue *arg1)
+-      : arg0_(arg0), arg1_(arg1), value_(NULL)
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -169,16 +303,27 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITBinarySubtract : public JITValue {
+   public:
+     JITBinarySubtract(JITValue *arg0, JITValue *arg1)
+-      : arg0_(arg0), arg1_(arg1), value_(NULL)
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -192,16 +337,27 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITBinaryMultiply : public JITValue {
+   public:
+     JITBinaryMultiply(JITValue *arg0, JITValue *arg1)
+-      : arg0_(arg0), arg1_(arg1), value_(NULL)
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -215,16 +371,27 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITBinaryDivide : public JITValue {
+   public:
+     JITBinaryDivide(JITValue *arg0, JITValue *arg1)
+-      : arg0_(arg0), arg1_(arg1), value_(NULL)
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -238,17 +405,28 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+   class JITCompareOp : public JITValue {
+   public:
+     JITCompareOp(JITValue *arg0, JITValue *arg1, int oparg)
+       : arg0_(arg0), arg1_(arg1),
+-        oparg_(oparg), value_(NULL)
++        oparg_(oparg), value_(NULL), type_(new JITOpaqueObject)
+     {}
+ 
+     virtual void dump()
+@@ -262,16 +440,27 @@
+     {
+       return value_;
+     }
++
++    virtual JITType *getStaticType() const
++    {
++      return type_;
++    }
++
++    virtual void registerStaticType(const PyTypeObject *)
++    {
++    }
++
+   private:
+     JITValue *arg0_;
+     JITValue *arg1_;
+     int oparg_;
+     llvm::Value *value_;
++    JITType *type_;
+   };
+ 
+-  class JITIncRef : public JITValue {
++  class JITIncRef : public JITOpcode {
+   public:
+-    JITIncRef(JITValue *arg) : arg_(arg), value_(NULL)
++    JITIncRef(JITValue *arg) : arg_(arg)
+     {}
+ 
+     virtual void dump()
+@@ -281,21 +470,16 @@
+ 
+     virtual void emit(JITFunctionBuilder &builder);
+ 
+-    virtual llvm::Value *getValue() const
+-    {
+-      return value_;
+-    }
+   private:
+     JITValue *arg_;
+-    llvm::Value *value_;
+   };
+ 
+-  class JITGuardNull : public JITValue {
++  class JITGuardNull : public JITOpcode {
+   public:
+     JITGuardNull(JITValue *arg, BLACKHOLE reason, int lasti,
+                  std::vector<JITValue *> &stack)
+       : arg_(arg), reason_(reason), lasti_(lasti),
+-        stack_(stack), value_(NULL)
++        stack_(stack)
+     {}
+ 
+     virtual void dump()
+@@ -305,24 +489,19 @@
+ 
+     virtual void emit(JITFunctionBuilder &builder);
+ 
+-    virtual llvm::Value *getValue() const
+-    {
+-      return value_;
+-    }
+   private:
+     JITValue *arg_;
+     BLACKHOLE reason_;
+     int lasti_;
+     std::vector<JITValue *> stack_;
+-    llvm::Value *value_;
+   };
+ 
+-  class JITGuardTrue : public JITValue {
++  class JITGuardTrue : public JITOpcode {
+   public:
+     JITGuardTrue(JITValue *arg, BLACKHOLE reason, int lasti,
+                  std::vector<JITValue *> &stack)
+       : arg_(arg), reason_(reason), lasti_(lasti),
+-        stack_(stack), value_(NULL)
++        stack_(stack)
+     {}
+ 
+     virtual void dump()
+@@ -332,22 +511,17 @@
+ 
+     virtual void emit(JITFunctionBuilder &builder);
+ 
+-    virtual llvm::Value *getValue() const
+-    {
+-      return value_;
+-    }
+   private:
+     JITValue *arg_;
+     BLACKHOLE reason_;
+     int lasti_;
+     std::vector<JITValue *> stack_;
+-    llvm::Value *value_;
+   };
+ 
+-  class JITTraceEnd : public JITValue {
++  class JITTraceEnd : public JITOpcode {
+   public:
+     JITTraceEnd(std::vector<JITValue *> &stack)
+-      : stack_(stack), value_(NULL)
++      : stack_(stack)
+     {}
+ 
+     virtual void dump()
+@@ -357,23 +531,20 @@
+ 
+     virtual void emit(JITFunctionBuilder &builder);
+ 
+-    virtual llvm::Value *getValue() const
+-    {
+-      return value_;
+-    }
+   private:
+     std::vector<JITValue *> stack_;
+-    llvm::Value *value_;
+   };
+ 
+   struct JITTraceAnalysis {
++    typedef std::vector<JITValue *> stack_t;
++
+     JITTraceAnalysis();
+ 
+     void analyseTrace(std::vector<TraceEntry> &trace);
+ 
+-    void Push(JITValue *value);
+-    JITValue *Pop();
+-    JITValue *Top();
++    void Push(stack_t &stack, JITValue *value);
++    JITValue *Pop(stack_t &stack);
++    JITValue *Top(stack_t &stack);
+ 
+     void dump()
+     {
+@@ -387,6 +558,13 @@
+ 
+     void emit(JITFunctionState &state);
+ 
++    JITOpcodeInfo *createOpcodeInfo(int lasti, stack_t &stack)
++    {
++      JITOpcodeInfo *r = new JITOpcodeInfo(lasti, stack);
++      trace_.push_back(r);
++      return r;
++    }
++
+     JITForIter *createForIter(JITValue *v)
+     {
+       JITForIter *r = new JITForIter(v);
+@@ -436,16 +614,16 @@
+       return r;
+     }
+ 
+-    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti)
++    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti, stack_t &stack)
+     {
+-      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack_);
++      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack);
+       trace_.push_back(r);
+       return r;
+     }
+ 
+-    JITGuardTrue *createGuardTrue(JITValue *v, BLACKHOLE reason, int lasti)
++    JITGuardTrue *createGuardTrue(JITValue *v, BLACKHOLE reason, int lasti, stack_t &stack)
+     {
+-      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack_);
++      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack);
+       trace_.push_back(r);
+       return r;
+     }
+@@ -478,19 +656,18 @@
+       return r;
+     }
+ 
+-    JITTraceEnd *createTraceEnd()
++    JITTraceEnd *createTraceEnd(stack_t &stack)
+     {
+-      JITTraceEnd *r = new JITTraceEnd(stack_);
++      JITTraceEnd *r = new JITTraceEnd(stack);
+       trace_.push_back(r);
+       return r;
+     }
+ 
+   private:
+     std::vector<JITStackValue *> loaded_stack_;
+-    std::vector<JITValue *> stack_;
+     int stack_counter_;
+ 
+-    std::vector<JITValue *> trace_;
++    std::vector<JITOpcode *> trace_;
+   };
+ 
+ 
+diff --git a/JIT/jit_types.cc b/JIT/jit_types.cc
+new file mode 100644
+--- /dev/null
++++ b/JIT/jit_types.cc
+@@ -0,0 +1,48 @@
++#include "JIT/jit_types.h"
++
++namespace jit {
++
++  JITType *
++  JITType::createBoxedType(const PyTypeObject *t)
++  {
++    if (t == &PyFloat_Type) {
++      return new JITBoxedFloat;
++    }
++    return NULL;
++  }
++
++
++  JITType *
++  JITType::createNakedType(const PyTypeObject *t)
++  {
++    if (t == &PyFloat_Type) {
++      return new JITNakedFloat;
++    }
++    return NULL;
++  }
++
++  llvm::Value *
++  JITBoxedFloat::ensureGuard(JITFunctionBuilder &fbuilder)
++  {
++    if (has_guard_)
++      return NULL;
++
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++    JITFunctionState *state = fbuilder.getState();
++
++    llvm::Value *ob_type =
++      builder.CreateLoad(ObjectTy::ob_type(builder, this->value_));
++    llvm::Value *float_type = state->EmbedPointer<PyTypeObject*>(&PyFloat_Type);
++    llvm::Value *check = builder.CreateICmpEQ(ob_type, float_type);
++
++    return check;
++  }
++
++  llvm::Value *
++  JITBoxedFloat::getNakedValue(JITFunctionBuilder &fbuilder)
++  {
++    return NULL;
++  }
++
++
++}
+diff --git a/JIT/jit_types.h b/JIT/jit_types.h
+new file mode 100644
+--- /dev/null
++++ b/JIT/jit_types.h
+@@ -0,0 +1,163 @@
++// -*- C++ -*-
++#ifndef PYTHON_JIT_TYPES_H_
++#define PYTHON_JIT_TYPES_H_
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++#include "Python.h"
++
++#include "JIT/jit_fbuilder.h"
++
++namespace jit {
++
++  class JITType {
++  public:
++    static JITType *createBoxedType(const PyTypeObject *);
++    static JITType *createNakedType(const PyTypeObject *);
++
++    virtual void init(llvm::Value *v) = 0;
++    virtual bool matchesType(const PyTypeObject *) const = 0;
++    virtual bool canSpecialize(const PyTypeObject *) const = 0;
++
++    virtual llvm::Value *getValue() const = 0;
++
++    virtual bool isFloat() const
++    {
++      return false;
++    }
++
++    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder) = 0;
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder) = 0;
++  };
++
++  class JITOpaqueObject : public JITType {
++  public:
++    JITOpaqueObject()
++      : value_(NULL)
++    {
++    }
++
++    virtual void init(llvm::Value *v)
++    {
++      value_ = v;
++    }
++
++    virtual bool matchesType(const PyTypeObject *) const
++    {
++      return true;
++    }
++
++    virtual bool canSpecialize(const PyTypeObject *) const
++    {
++      return true;
++    }
++
++    virtual llvm::Value *getValue() const
++    {
++      return value_;
++    }
++
++    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder)
++    {
++      return NULL;
++    }
++
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
++    {
++      return NULL;
++    }
++
++  private:
++    llvm::Value *value_;
++  };
++
++  class JITBoxedFloat : public JITType {
++  public:
++    JITBoxedFloat()
++      : value_(NULL), naked_value_(NULL), has_guard_(false)
++    {
++    }
++
++    virtual void init(llvm::Value *v)
++    {
++      value_ = v;
++    }
++
++    virtual bool matchesType(const PyTypeObject *t) const
++    {
++      return PyFloat_CheckExact(t);
++    }
++    virtual bool canSpecialize(const PyTypeObject *) const
++    {
++      return false;
++    }
++
++    virtual bool isFloat() const
++    {
++      return true;
++    }
++
++    virtual llvm::Value *getValue() const
++    {
++      return value_;
++    }
++
++    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder);
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder);
++
++  private:
++    llvm::Value *value_;
++    llvm::Value *naked_value_;
++    bool has_guard_;
++  };
++
++  class JITNakedFloat : public JITType {
++  public:
++    JITNakedFloat()
++      : value_(NULL)
++    {
++    }
++
++    virtual void init(llvm::Value *v)
++    {
++      value_ = v;
++    }
++
++    virtual bool matchesType(const PyTypeObject *t) const
++    {
++      return PyFloat_CheckExact(t);
++    }
++    virtual bool canSpecialize(const PyTypeObject *) const
++    {
++      return false;
++    }
++
++    virtual bool isFloat() const
++    {
++      return true;
++    }
++
++    virtual llvm::Value *getValue() const
++    {
++      return NULL;
++    }
++
++    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder)
++    {
++      return NULL;
++    }
++
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
++    {
++      return NULL;
++    }
++
++  private:
++    llvm::Value *value_;
++  };
++
++}
++
++#endif
+diff --git a/Makefile.pre.in b/Makefile.pre.in
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -73,7 +73,7 @@
+ # command line to append to these values without stomping the pre-set
+ # values.
+ PY_CFLAGS=	$(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)
+-PY_CXXFLAGS=    $(BASECFLAGS) $(CXX_OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)
++PY_CXXFLAGS=    $(BASECFLAGS) $(CXX_OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -Wno-write-strings
+ # Both CPPFLAGS and LDFLAGS need to contain the shell's value for setup.py to
+ # be able to build extension modules using the directories specified in the
+ # environment variables
+@@ -332,7 +332,7 @@
+ 		Python/asdl.o \
+ 		Python/ast.o \
+ 		Python/bltinmodule.o \
+-		Python/ceval.o \
++		Python/eval.o \
+ 		Python/compile.o \
+ 		Python/codecs.o \
+ 		Python/dynamic_annotations.o \
+@@ -379,6 +379,7 @@
+ PYTHON_OBJS+=	\
+ 		JIT/global_jit_data.o \
+ 		JIT/jit_tracer.o \
++		JIT/jit_types.o \
+ 		JIT/PyTypeBuilder.o \
+ 		JIT/SingleFunctionInliner.o \
+ 		JIT/jit_blackhole.o \
+@@ -730,7 +731,7 @@
+ $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
+ 	$(OPCODETARGETGEN) $(OPCODETARGETS_H)
+ 
+-Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h
++Python/eval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h
+ 
+ Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
+ 				$(BYTESTR_DEPS)
+@@ -832,6 +833,7 @@
+ 		$(srcdir)/JIT/global_jit_data_fwd.h \
+ 		$(srcdir)/JIT/jit_fstate.h \
+ 		$(srcdir)/JIT/jit_tracer.h \
++		$(srcdir)/JIT/jit_types.h \
+ 		$(srcdir)/JIT/jit_fbuilder.h \
+ 		$(srcdir)/JIT/jit_blackhole.h \
+ 		$(srcdir)/JIT/PyTypeBuilder.h \
+diff --git a/Objects/codeobject.c b/Objects/codeobject.c
+--- a/Objects/codeobject.c
++++ b/Objects/codeobject.c
+@@ -147,6 +147,7 @@
+     co->co_lnotab = lnotab;
+     co->co_zombieframe = NULL;
+     co->co_weakreflist = NULL;
++    co->co_jit = NULL;
+     return co;
+ }
+ 
+@@ -371,6 +372,8 @@
+         PyObject_GC_Del(co->co_zombieframe);
+     if (co->co_weakreflist != NULL)
+         PyObject_ClearWeakRefs((PyObject*)co);
++    if (co->co_jit != NULL)
++        PyJITFunction_Free(co->co_jit);
+     PyObject_DEL(co);
+ }
+ 
+diff --git a/Python/ceval.c b/Python/eval.cc
+rename from Python/ceval.c
+rename to Python/eval.cc
+--- a/Python/ceval.c
++++ b/Python/eval.cc
+@@ -16,6 +16,9 @@
+ #include "opcode.h"
+ #include "structmember.h"
+ 
++#include "JIT/global_jit_data.h"
++#include "JIT/jit_blackhole.h"
++
+ #include <ctype.h>
+ 
+ #ifndef WITH_TSC
+@@ -808,6 +811,7 @@
+     PyObject *retval = NULL;            /* Return value */
+     PyThreadState *tstate = PyThreadState_GET();
+     PyCodeObject *co;
++    PyJITTracer *trace = NULL;
+ 
+     /* when tracing we set things up so that
+ 
+@@ -893,6 +897,7 @@
+         opcode = op; \
+         if (HAS_ARG(op)) \
+             oparg = NEXTARG(); \
++        trace->trace(co, f->f_lasti, opcode, oparg);  \
+     case op: \
+         goto impl; \
+ 
+@@ -901,6 +906,7 @@
+         opcode = op; \
+         if (HAS_ARG(op)) \
+             oparg = NEXTARG(); \
++        trace->trace(co, f->f_lasti, opcode, oparg);  \
+     case op:
+ 
+ 
+@@ -1028,15 +1034,15 @@
+ 
+ */
+ 
+-#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
++// #if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
+ #define PREDICT(op)             if (0) goto PRED_##op
+ #define PREDICTED(op)           PRED_##op:
+ #define PREDICTED_WITH_ARG(op)  PRED_##op:
+-#else
+-#define PREDICT(op)             if (*next_instr == op) goto PRED_##op
+-#define PREDICTED(op)           PRED_##op: next_instr++
+-#define PREDICTED_WITH_ARG(op)  PRED_##op: oparg = PEEKARG(); next_instr += 3
+-#endif
++// #else
++// #define PREDICT(op)             if (*next_instr == op) goto PRED_##op
++// #define PREDICTED(op)           PRED_##op: next_instr++
++// #define PREDICTED_WITH_ARG(op)  PRED_##op: oparg = PEEKARG(); next_instr += 3
++// #endif
+ 
+ 
+ /* Stack manipulation macros */
+@@ -1205,6 +1211,7 @@
+     lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL;
+ #endif
+ 
++    trace = PyJITTracer_GET();
+     why = WHY_NOT;
+     err = 0;
+     x = Py_None;        /* Not a reference, just anything non-NULL */
+@@ -1315,11 +1322,31 @@
+ 
+         /* Extract opcode and argument */
+ 
++        if (co->co_jit && f->f_lasti == co->co_jit->opcode) {
++          f->f_stacktop = stack_pointer;
++          int reason = co->co_jit->trace(f);
++          int val = jit::PyJIT_BlackHoleEval(f, reason);
++          stack_pointer = f->f_stacktop;
++          f->f_stacktop = NULL;
++          next_instr = first_instr + f->f_lasti;
++
++          std::cout << "Finished Trace " << f->f_lasti << " " << val << std::endl;
++
++          if (val == jit::BH_EXC) {
++            x = 0;
++            goto on_error;
++          }
++          x = Py_None;
++        }
++
+         opcode = NEXTOP();
+         oparg = 0;   /* allows oparg to be stored in a register because
+             it doesn't have to be remembered across a full loop */
+         if (HAS_ARG(opcode))
+             oparg = NEXTARG();
++
++        trace->trace(co, f->f_lasti, opcode, oparg);
++
+     dispatch_opcode:
+ #ifdef DYNAMIC_EXECUTION_PROFILE
+ #ifdef DXPAIRS
+@@ -1364,6 +1391,7 @@
+                 PUSH(x);
+                 FAST_DISPATCH();
+             }
++            trace->setFlag(TR_EXCEPTION);
+             format_exc_check_arg(PyExc_UnboundLocalError,
+                 UNBOUNDLOCAL_ERROR_MSG,
+                 PyTuple_GetItem(co->co_varnames, oparg));
+@@ -1378,6 +1406,7 @@
+         PREDICTED_WITH_ARG(STORE_FAST);
+         TARGET(STORE_FAST)
+             v = POP();
++            trace->setType(0, v->ob_type);
+             SETLOCAL(oparg, v);
+             FAST_DISPATCH();
+ 
+@@ -1468,41 +1497,53 @@
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_MULTIPLY)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             x = PyNumber_Multiply(v, w);
+             Py_DECREF(v);
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_TRUE_DIVIDE)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             x = PyNumber_TrueDivide(v, w);
+             Py_DECREF(v);
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_FLOOR_DIVIDE)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             x = PyNumber_FloorDivide(v, w);
+             Py_DECREF(v);
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_MODULO)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             if (PyUnicode_CheckExact(v))
+                 x = PyUnicode_Format(v, w);
+             else
+@@ -1511,11 +1552,14 @@
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_ADD)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             if (PyUnicode_CheckExact(v) &&
+                      PyUnicode_CheckExact(w)) {
+                 x = unicode_concatenate(v, w, f, next_instr);
+@@ -1530,26 +1574,33 @@
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_SUBTRACT)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             x = PyNumber_Subtract(v, w);
+             Py_DECREF(v);
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_SUBSCR)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             x = PyObject_GetItem(v, w);
+             Py_DECREF(v);
+             Py_DECREF(w);
+             SET_TOP(x);
+             if (x != NULL) DISPATCH();
++            trace->setFlag(TR_EXCEPTION);
+             break;
+ 
+         TARGET(BINARY_LSHIFT)
+@@ -1677,6 +1728,8 @@
+         TARGET(INPLACE_ADD)
+             w = POP();
+             v = TOP();
++            trace->setType(0, v->ob_type);
++            trace->setType(1, w->ob_type);
+             if (PyUnicode_CheckExact(v) &&
+                      PyUnicode_CheckExact(w)) {
+                 x = unicode_concatenate(v, w, f, next_instr);
+@@ -2382,16 +2435,22 @@
+             if (w == Py_False) {
+                 Py_DECREF(w);
+                 JUMPTO(oparg);
++                trace->setFlag(TR_JUMP_TAKEN);
+                 FAST_DISPATCH();
+             }
+             err = PyObject_IsTrue(w);
+             Py_DECREF(w);
+-            if (err > 0)
++            if (err > 0) {
+                 err = 0;
+-            else if (err == 0)
++            }
++            else if (err == 0) {
+                 JUMPTO(oparg);
+-            else
++                trace->setFlag(TR_JUMP_TAKEN);
++            }
++            else {
++              trace->setFlag(TR_EXCEPTION);
+                 break;
++            }
+             DISPATCH();
+ 
+         PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
+@@ -2468,6 +2527,8 @@
+         PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
+         TARGET(JUMP_ABSOLUTE)
+             JUMPTO(oparg);
++            if (co->co_jit && INSTR_OFFSET() == co->co_jit->opcode)
++                goto fast_next_opcode;
+ #if FAST_LOOPS
+             /* Enabling this path speeds-up all while and for-loops by bypassing
+                the per-loop checks for signals.  By default, this should be turned-off
+@@ -2507,11 +2568,14 @@
+             }
+             if (PyErr_Occurred()) {
+                 if (!PyErr_ExceptionMatches(
+-                                PyExc_StopIteration))
++                                PyExc_StopIteration)) {
++                    trace->setFlag(TR_EXCEPTION);
+                     break;
++                }
+                 PyErr_Clear();
+             }
+             /* iterator ended normally */
++            trace->setFlag(TR_JUMP_TAKEN);
+             x = v = POP();
+             Py_DECREF(v);
+             JUMPBY(oparg);
+# HG changeset patch
+# Parent 7bacccd889c2fad1514f19d88e1f1a695e080b7f
+
+diff -r 7bacccd889c2 .hgignore
+--- a/.hgignore	Sat Apr 28 00:25:34 2012 +0200
++++ b/.hgignore	Sat May 26 17:18:24 2012 +0200
+@@ -73,3 +73,4 @@
+ .coverage
+ coverage/
+ htmlcov/
++build*/
+\ No newline at end of file
+diff -r 7bacccd889c2 Include/Python.h
+--- a/Include/Python.h	Sat Apr 28 00:25:34 2012 +0200
++++ b/Include/Python.h	Sat May 26 17:18:24 2012 +0200
+@@ -102,6 +102,8 @@
+ #include "weakrefobject.h"
+ #include "structseq.h"
+ 
++#include "JIT/global_jit_data_fwd.h"
++
+ #include "codecs.h"
+ #include "pyerrors.h"
+ 
+diff -r 7bacccd889c2 Include/code.h
+--- a/Include/code.h	Sat Apr 28 00:25:34 2012 +0200
++++ b/Include/code.h	Sat May 26 17:18:24 2012 +0200
+@@ -7,6 +7,8 @@
+ extern "C" {
+ #endif
+ 
++typedef struct _JITFunction _JITFunction;
++
+ /* Bytecode object */
+ typedef struct {
+     PyObject_HEAD
+@@ -30,6 +32,7 @@
+ 				   Objects/lnotab_notes.txt for details. */
+     void *co_zombieframe;     /* for optimization only (see frameobject.c) */
+     PyObject *co_weakreflist;   /* to support weakrefs to code objects */
++    _JITFunction *co_jit;
+ } PyCodeObject;
+ 
+ /* Masks for co_flags above */
+diff -r 7bacccd889c2 Include/pystate.h
+--- a/Include/pystate.h	Sat Apr 28 00:25:34 2012 +0200
++++ b/Include/pystate.h	Sat May 26 17:18:24 2012 +0200
+@@ -34,6 +34,7 @@
+     int codecs_initialized;
+     int fscodec_initialized;
+ 
++    struct PyGlobalJITData *global_jit_data;
+ 
+ #ifdef HAVE_DLOPEN
+     int dlopenflags;
+@@ -100,6 +101,8 @@
+ 
+     PyObject *dict;  /* Stores per-thread state */
+ 
++    struct PyJITTracer *jit_tracer;
++
+     /* XXX doesn't mean anything anymore (the comment below is obsolete)
+        => deprecate or remove? */
+     /* tick_counter is incremented whenever the check_interval ticker
+diff -r 7bacccd889c2 JIT/PyTypeBuilder.cc
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/PyTypeBuilder.cc	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,18 @@
++#include "JIT/PyTypeBuilder.h"
++#include "JIT/global_jit_data.h"
++
++#include "llvm/ExecutionEngine/ExecutionEngine.h"
++#include "llvm/Target/TargetData.h"
++
++unsigned int
++_PyTypeBuilder_GetFieldIndexFromOffset(
++    llvm::StructType *type, size_t offset)
++{
++    const llvm::TargetData *target_data =
++        PyGlobalJITData::Get()->getExecutionEngine()->getTargetData();
++    const llvm::StructLayout *layout = target_data->getStructLayout(type);
++    unsigned int index = layout->getElementContainingOffset(offset);
++    assert(layout->getElementOffset(index) == offset &&
++           "offset must be at start of element");
++    return index;
++}
+diff -r 7bacccd889c2 JIT/PyTypeBuilder.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/PyTypeBuilder.h	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,236 @@
++// -*- C++ -*-
++#ifndef PYTHON_PYTYPEBUILDER_H_
++#define PYTHON_PYTYPEBUILDER_H_
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++#include "Python.h"
++#include "frameobject.h"
++
++#include "global_jit_data.h"
++
++#include "llvm/Module.h"
++#include "llvm/Support/IRBuilder.h"
++#include "llvm/Support/TypeBuilder.h"
++
++template<typename T>
++class PyTypeBuilder : public llvm::TypeBuilder<T, false> {};
++
++// This function uses the JIT compiler's TargetData object to convert
++// from a byte offset inside a type to a GEP index referring to the
++// field of the type.  This should be called like
++//   _PyTypeBuilder_GetFieldIndexFromOffset(
++//       PyTypeBuilder<PySomethingType>::get(context),
++//       offsetof(PySomethingType, field));
++// It will only work if PySomethingType is a POD type.
++unsigned int
++_PyTypeBuilder_GetFieldIndexFromOffset(llvm::StructType *type, size_t offset);
++
++namespace llvm {
++
++// Defines a static member function FIELD_NAME(ir_builder, ptr) to
++// access TYPE::FIELD_NAME inside ptr.  GetElementPtr instructions
++// require the index of the field within the type, but padding makes
++// it hard to predict that index from the list of fields in the type.
++// Because the compiler building this file knows the byte offset of
++// the field, we can use llvm::TargetData to compute the index.  This
++// has the extra benefit that it's more resilient to changes in the
++// set or order of fields in a type.
++#define DEFINE_FIELD(TYPE, FIELD_NAME) \
++    static unsigned FIELD_NAME##_index(LLVMContext &context) { \
++        static const unsigned int index = \
++            _PyTypeBuilder_GetFieldIndexFromOffset( \
++                PyTypeBuilder<TYPE>::get(context), \
++                offsetof(TYPE, FIELD_NAME)); \
++        return index; \
++    } \
++    template<bool preserveNames, typename Folder> \
++    static Value *FIELD_NAME(IRBuilder<preserveNames, Folder> &builder, \
++                             Value *ptr) { \
++        assert(ptr->getType() == PyTypeBuilder<TYPE*>::get(ptr->getContext()) \
++               && "*ptr must be of type " #TYPE); \
++        return builder.CreateStructGEP( \
++            ptr, FIELD_NAME##_index(ptr->getContext()), #FIELD_NAME); \
++    }
++
++#ifdef Py_TRACE_REFS
++#define DEFINE_OBJECT_HEAD_FIELDS(TYPE) \
++    DEFINE_FIELD(TYPE, _ob_next) \
++    DEFINE_FIELD(TYPE, _ob_prev) \
++    DEFINE_FIELD(TYPE, ob_refcnt) \
++    DEFINE_FIELD(TYPE, ob_type)
++#else
++#define DEFINE_OBJECT_HEAD_FIELDS(TYPE) \
++    DEFINE_FIELD(TYPE, ob_refcnt) \
++    DEFINE_FIELD(TYPE, ob_type)
++#endif
++
++  template<> class TypeBuilder<PyObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++        PyGlobalJITData::Get()->module()->getTypeByName(
++          // Clang's name for the PyObject struct.
++          "struct._object"));
++    }
++    DEFINE_OBJECT_HEAD_FIELDS(PyObject)
++  };
++
++  template<> class TypeBuilder<PyFrameObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++        PyGlobalJITData::Get()->module()->getTypeByName(
++          // Clang's name for the PyFrameObject struct.
++          "struct._frame"));
++    }
++    // DEFINE_OBJECT_HEAD_FIELDS(PyFrameObject)
++    // DEFINE_FIELD(PyFrameObject, ob_size)
++    DEFINE_FIELD(PyFrameObject, f_back)
++    DEFINE_FIELD(PyFrameObject, f_code)
++    DEFINE_FIELD(PyFrameObject, f_builtins)
++    DEFINE_FIELD(PyFrameObject, f_globals)
++    DEFINE_FIELD(PyFrameObject, f_locals)
++    DEFINE_FIELD(PyFrameObject, f_valuestack)
++    DEFINE_FIELD(PyFrameObject, f_stacktop)
++    DEFINE_FIELD(PyFrameObject, f_trace)
++    DEFINE_FIELD(PyFrameObject, f_exc_type)
++    DEFINE_FIELD(PyFrameObject, f_exc_value)
++    DEFINE_FIELD(PyFrameObject, f_exc_traceback)
++    DEFINE_FIELD(PyFrameObject, f_tstate)
++    DEFINE_FIELD(PyFrameObject, f_lasti)
++    DEFINE_FIELD(PyFrameObject, f_lineno)
++    DEFINE_FIELD(PyFrameObject, f_iblock)
++    DEFINE_FIELD(PyFrameObject, f_blockstack)
++    DEFINE_FIELD(PyFrameObject, f_localsplus)
++  };
++
++  template<> class TypeBuilder<PyTypeObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++         PyGlobalJITData::Get()->module()->getTypeByName(
++           // Clang's name for the PyTypeObject struct.
++           "struct._typeobject"));
++    }
++
++    // DEFINE_OBJECT_HEAD_FIELDS(PyTypeObject)
++    // DEFINE_FIELD(PyTypeObject, ob_size)
++    DEFINE_FIELD(PyTypeObject, tp_name)
++    DEFINE_FIELD(PyTypeObject, tp_basicsize)
++    DEFINE_FIELD(PyTypeObject, tp_itemsize)
++    DEFINE_FIELD(PyTypeObject, tp_dealloc)
++    DEFINE_FIELD(PyTypeObject, tp_print)
++    DEFINE_FIELD(PyTypeObject, tp_getattr)
++    DEFINE_FIELD(PyTypeObject, tp_setattr)
++    // DEFINE_FIELD(PyTypeObject, tp_compare)
++    DEFINE_FIELD(PyTypeObject, tp_repr)
++    DEFINE_FIELD(PyTypeObject, tp_as_number)
++    DEFINE_FIELD(PyTypeObject, tp_as_sequence)
++    DEFINE_FIELD(PyTypeObject, tp_as_mapping)
++    DEFINE_FIELD(PyTypeObject, tp_hash)
++    DEFINE_FIELD(PyTypeObject, tp_call)
++    DEFINE_FIELD(PyTypeObject, tp_str)
++    DEFINE_FIELD(PyTypeObject, tp_getattro)
++    DEFINE_FIELD(PyTypeObject, tp_setattro)
++    DEFINE_FIELD(PyTypeObject, tp_as_buffer)
++    DEFINE_FIELD(PyTypeObject, tp_flags)
++    DEFINE_FIELD(PyTypeObject, tp_doc)
++    DEFINE_FIELD(PyTypeObject, tp_traverse)
++    DEFINE_FIELD(PyTypeObject, tp_clear)
++    DEFINE_FIELD(PyTypeObject, tp_richcompare)
++    DEFINE_FIELD(PyTypeObject, tp_weaklistoffset)
++    DEFINE_FIELD(PyTypeObject, tp_iter)
++    DEFINE_FIELD(PyTypeObject, tp_iternext)
++    DEFINE_FIELD(PyTypeObject, tp_methods)
++    DEFINE_FIELD(PyTypeObject, tp_members)
++    DEFINE_FIELD(PyTypeObject, tp_getset)
++    DEFINE_FIELD(PyTypeObject, tp_base)
++    DEFINE_FIELD(PyTypeObject, tp_dict)
++    DEFINE_FIELD(PyTypeObject, tp_descr_get)
++    DEFINE_FIELD(PyTypeObject, tp_descr_set)
++    DEFINE_FIELD(PyTypeObject, tp_dictoffset)
++    DEFINE_FIELD(PyTypeObject, tp_init)
++    DEFINE_FIELD(PyTypeObject, tp_alloc)
++    DEFINE_FIELD(PyTypeObject, tp_new)
++    DEFINE_FIELD(PyTypeObject, tp_free)
++    DEFINE_FIELD(PyTypeObject, tp_is_gc)
++    DEFINE_FIELD(PyTypeObject, tp_bases)
++    DEFINE_FIELD(PyTypeObject, tp_mro)
++    DEFINE_FIELD(PyTypeObject, tp_cache)
++    DEFINE_FIELD(PyTypeObject, tp_subclasses)
++    DEFINE_FIELD(PyTypeObject, tp_weaklist)
++    DEFINE_FIELD(PyTypeObject, tp_del)
++    DEFINE_FIELD(PyTypeObject, tp_version_tag)
++#ifdef COUNT_ALLOCS
++    DEFINE_FIELD(PyTypeObject, tp_allocs)
++    DEFINE_FIELD(PyTypeObject, tp_frees)
++    DEFINE_FIELD(PyTypeObject, tp_maxalloc)
++    DEFINE_FIELD(PyTypeObject, tp_prev)
++    DEFINE_FIELD(PyTypeObject, tp_next)
++#endif
++  };
++
++  template<> class TypeBuilder<PyCodeObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++        PyGlobalJITData::Get()->module()->getTypeByName(
++          // Clang's name for the PyCodeObject struct.
++          "struct.PyCodeObject"));
++    }
++
++    // DEFINE_OBJECT_HEAD_FIELDS(PyCodeObject)
++    DEFINE_FIELD(PyCodeObject, co_argcount)
++    DEFINE_FIELD(PyCodeObject, co_nlocals)
++    DEFINE_FIELD(PyCodeObject, co_stacksize)
++    DEFINE_FIELD(PyCodeObject, co_flags)
++    DEFINE_FIELD(PyCodeObject, co_code)
++    DEFINE_FIELD(PyCodeObject, co_consts)
++    DEFINE_FIELD(PyCodeObject, co_names)
++    DEFINE_FIELD(PyCodeObject, co_varnames)
++    DEFINE_FIELD(PyCodeObject, co_freevars)
++    DEFINE_FIELD(PyCodeObject, co_cellvars)
++    DEFINE_FIELD(PyCodeObject, co_filename)
++    DEFINE_FIELD(PyCodeObject, co_name)
++    DEFINE_FIELD(PyCodeObject, co_firstlineno)
++    DEFINE_FIELD(PyCodeObject, co_lnotab)
++    DEFINE_FIELD(PyCodeObject, co_zombieframe)
++  };
++
++  template<> class TypeBuilder<PyTupleObject, false> {
++  public:
++    static StructType *get(llvm::LLVMContext &context) {
++      return cast<StructType>(
++        PyGlobalJITData::Get()->module()->getTypeByName(
++          // Clang's name for the PyTupleObject struct.
++          "struct.PyTupleObject"));
++    }
++
++    // DEFINE_OBJECT_HEAD_FIELDS(PyTupleObject)
++    // DEFINE_FIELD(PyTupleObject, ob_size)
++    DEFINE_FIELD(PyTupleObject, ob_item)
++  };
++
++}
++
++namespace jit {
++  typedef PyTypeBuilder<PyObject> ObjectTy;
++  typedef PyTypeBuilder<PyVarObject> VarObjectTy;
++  // typedef PyTypeBuilder<PyStringObject> StringTy;
++  // typedef PyTypeBuilder<PyIntObject> IntTy;
++  typedef PyTypeBuilder<PyTupleObject> TupleTy;
++  typedef PyTypeBuilder<PyListObject> ListTy;
++  typedef PyTypeBuilder<PyTypeObject> TypeTy;
++  typedef PyTypeBuilder<PyCodeObject> CodeTy;
++  typedef PyTypeBuilder<PyFunctionObject> FunctionTy;
++  typedef PyTypeBuilder<PyMethodObject> MethodTy;
++  typedef PyTypeBuilder<PyFrameObject> FrameTy;
++  typedef PyTypeBuilder<PyThreadState> ThreadStateTy;
++  typedef PyTypeBuilder<PyCFunctionObject> CFunctionTy;
++  typedef PyTypeBuilder<PyMethodDef> MethodDefTy;
++}
++
++#endif
+diff -r 7bacccd889c2 JIT/SingleFunctionInliner.cc
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/SingleFunctionInliner.cc	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,81 @@
++#include "JIT/SingleFunctionInliner.h"
++
++#include "llvm/Attributes.h"
++#include "llvm/BasicBlock.h"
++#include "llvm/Function.h"
++#include "llvm/Instructions.h"
++#include "llvm/Module.h"
++#include "llvm/Pass.h"
++#include "llvm/Transforms/Utils/Cloning.h"
++
++namespace {
++
++namespace Attribute = llvm::Attribute;
++using llvm::BasicBlock;
++using llvm::CallInst;
++using llvm::Function;
++using llvm::FunctionPass;
++using llvm::InvokeInst;
++using llvm::Module;
++using llvm::dyn_cast;
++using llvm::isa;
++
++// This class is derived from llvm's Inliner pass, but is tweaked to
++// work one function at a time and to inline things according to
++// Python-specific rules.
++class SingleFunctionInliner : public FunctionPass {
++public:
++    static char ID;
++    SingleFunctionInliner()
++        : FunctionPass(ID) {}
++
++    virtual bool runOnFunction(Function &f)
++    {
++        bool changed = false;
++        // Scan through and identify all call sites ahead of time so
++        // that we only inline call sites in the original functions,
++        // not call sites that result from inlining other functions.
++        std::vector<CallInst*> call_sites;
++        for (Function::iterator bb = f.begin(), e = f.end(); bb != e; ++bb) {
++            for (BasicBlock::iterator inst = bb->begin(); inst != bb->end();
++                 ++inst) {
++                assert(!isa<InvokeInst>(inst) &&
++                       "We don't expect any invoke instructions in Python.");
++                CallInst *call = dyn_cast<CallInst>(inst);
++                if (call == NULL)
++                    continue;
++                // This may miss inlining indirect calls that become
++                // direct after inlining something else.
++                Function *called_function = call->getCalledFunction();
++                if (called_function == NULL)
++                    continue;
++                if (called_function->isMaterializable()) {
++                    if (called_function->Materialize())
++                        continue;
++                }
++                if (!called_function->isDeclaration() &&
++                    called_function->hasFnAttr(Attribute::AlwaysInline)) {
++                    call_sites.push_back(call);
++                }
++            }
++        }
++
++        llvm::InlineFunctionInfo info;
++        // Actually inline the calls we found.
++        for (size_t i = 0; i != call_sites.size(); ++i) {
++          changed |= InlineFunction(call_sites[i], info);
++        }
++        return changed;
++    }
++};
++
++// The address of this variable identifies the pass.  See
++// http://llvm.org/docs/WritingAnLLVMPass.html#basiccode.
++char SingleFunctionInliner::ID = 0;
++
++}  // anonymous namespace
++
++FunctionPass *PyCreateSingleFunctionInliningPass()
++{
++    return new SingleFunctionInliner();
++}
+diff -r 7bacccd889c2 JIT/SingleFunctionInliner.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/SingleFunctionInliner.h	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,18 @@
++// -*- C++ -*-
++#ifndef UTIL_SINGLEFUNCTIONINLINER_H
++#define UTIL_SINGLEFUNCTIONINLINER_H
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++namespace llvm {
++class FunctionPass;
++class ModuleProvider;
++}
++
++// Inlines calls into the active function according to Python-specific
++// rules.  For now, this only inlines always-inline functions.
++llvm::FunctionPass *PyCreateSingleFunctionInliningPass();
++
++#endif  // UTIL_SINGLEFUNCTIONINLINER_H
+diff -r 7bacccd889c2 JIT/_jitfunctionobject.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/_jitfunctionobject.h	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,14 @@
++#ifndef PY_JITFUNCTIONOBJECT_H_
++#define PY_JITFUNCTIONOBJECT_H_
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++  struct _JITFunction {
++  };
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PY_JITFUNCTION_OBJECT_H_ */
+diff -r 7bacccd889c2 JIT/global_jit_data.cc
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/global_jit_data.cc	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,184 @@
++#include "Python.h"
++
++#include "osdefs.h"
++#undef MAXPATHLEN  /* Conflicts with definition in LLVM's config.h */
++
++#include "global_jit_data.h"
++#include "JIT/PyTypeBuilder.h"
++#include "JIT/SingleFunctionInliner.h"
++
++#include "llvm/Module.h"
++#include <llvm/Support/TargetSelect.h>
++#include <llvm/ExecutionEngine/ExecutionEngine.h>
++#include <llvm/Support/MemoryBuffer.h>
++#include "llvm/ExecutionEngine/JIT.h"
++#include "llvm/Bitcode/ReaderWriter.h"
++#include "llvm/Support/Path.h"
++#include "llvm/ADT/StringRef.h"
++#include "llvm/ADT/OwningPtr.h"
++#include "llvm/Support/system_error.h"
++#include "llvm/Target/TargetData.h"
++#include "llvm/Function.h"
++#include "llvm/Transforms/Scalar.h"
++#include "llvm/Analysis/Passes.h"
++#include "llvm/Analysis/Verifier.h"
++
++#include <string>
++
++#define STRINGIFY(X) STRINGIFY2(X)
++#define STRINGIFY2(X) #X
++
++#define LIBPYTHON_BC "libpython" STRINGIFY(PY_MAJOR_VERSION) "." \
++  STRINGIFY(PY_MINOR_VERSION) ".bc"
++
++// Searches for the bitcode file holding the Python standard library.
++// If one is found, returns its contents in a MemoryBuffer.  If not,
++// dies with a fatal error.
++static llvm::MemoryBuffer *
++find_stdlib_bc()
++{
++  llvm::sys::Path path;
++  llvm::SmallVector<llvm::StringRef, 8> sys_path;
++  const char delim[] = { DELIM, '\0' };
++  std::wstring path_obj = Py_GetPath();
++  std::string path_obj2(path_obj.begin(), path_obj.end());
++
++  // std::cout << path_obj2 << "\n";
++  llvm::StringRef(path_obj2.c_str()).split(sys_path, delim);
++
++  for (ssize_t i = 0, size = sys_path.size(); i < size; ++i) {
++    llvm::StringRef elem = sys_path[i];
++    path = elem;
++    path.appendComponent(LIBPYTHON_BC);
++    std::cout << path.str() << "\n";
++    llvm::OwningPtr<llvm::MemoryBuffer> stdlib_file;
++    if(!llvm::MemoryBuffer::getFile(path.str(), stdlib_file)) {
++      return stdlib_file.take();
++    }
++  }
++  {
++    llvm::StringRef elem = "./Modules";
++    path = elem;
++    path.appendComponent(LIBPYTHON_BC);
++    std::cout << path.str() << "\n";
++    llvm::OwningPtr<llvm::MemoryBuffer> stdlib_file;
++    if(!llvm::MemoryBuffer::getFile(path.str(), stdlib_file)) {
++      return stdlib_file.take();
++    }
++  }
++  Py_FatalError("Could not find " LIBPYTHON_BC " on sys.path");
++  return NULL;
++}
++
++PyGlobalJITData *
++PyGlobalJITData_New()
++{
++  return new PyGlobalJITData;
++}
++
++void
++PyGlobalJITData_Clear(struct PyGlobalJITData *)
++{
++  // Do nothing.
++}
++
++void
++PyGlobalJITData_Free(struct PyGlobalJITData *global_data)
++{
++  delete global_data;
++}
++
++
++PyGlobalJITData *
++PyGlobalJITData::Get()
++{
++  return PyThreadState_GET()->interp->global_jit_data;
++}
++
++PyGlobalJITData::PyGlobalJITData()
++{
++  llvm::InitializeNativeTarget();
++
++  std::string error;
++  llvm::MemoryBuffer *stdlib_file = find_stdlib_bc();
++  this->module_ = llvm::getLazyBitcodeModule(stdlib_file, llvm::getGlobalContext(), &error);
++  if (module_ == NULL) {
++    Py_FatalError(error.c_str());
++    return;
++  }
++
++  this->engine_ = llvm::EngineBuilder(this->module_)
++    .setErrorStr(&error)
++    .setEngineKind(llvm::EngineKind::JIT)
++    // .setUseMCJIT(true)
++    .create();
++
++  if (engine_ == NULL) {
++    Py_FatalError(error.c_str());
++    return;
++  }
++  this->engine_->DisableLazyCompilation();
++
++  this->opt_ = new llvm::FunctionPassManager(this->module_);
++  this->opt_->add(new llvm::TargetData(*engine_->getTargetData()));
++  // this->opt_->add(PyCreateSingleFunctionInliningPass());
++  this->opt_->add(llvm::createPromoteMemoryToRegisterPass());
++  this->opt_->add(llvm::createInstructionCombiningPass());
++  this->opt_->add(llvm::createCFGSimplificationPass());
++  this->opt_->add(llvm::createVerifierPass());
++
++  // this->opt_->add(new llvm::TargetData(*engine_->getTargetData()));
++  // this->opt_->add(llvm::createCFGSimplificationPass());
++  // this->opt_->add(PyCreateSingleFunctionInliningPass());
++  // this->opt_->add(llvm::createJumpThreadingPass());
++  // this->opt_->add(llvm::createPromoteMemoryToRegisterPass());
++  // this->opt_->add(llvm::createInstructionCombiningPass());
++  // this->opt_->add(llvm::createCFGSimplificationPass());
++  // this->opt_->add(llvm::createScalarReplAggregatesPass());
++  // this->opt_->add(llvm::createLICMPass());
++  // this->opt_->add(llvm::createJumpThreadingPass());
++  // this->opt_->add(llvm::createGVNPass());
++  // this->opt_->add(llvm::createSCCPPass());
++  // this->opt_->add(llvm::createAggressiveDCEPass());
++  // this->opt_->add(llvm::createCFGSimplificationPass());
++  // this->opt_->add(llvm::createVerifierPass());
++}
++
++void
++PyGlobalJITData::optimize(llvm::Function *func)
++{
++  this->opt_->run(*func);
++}
++
++PyGlobalJITData::~PyGlobalJITData()
++{
++  delete this->engine_;
++}
++
++int
++_PyJIT_Init()
++{
++  if (0) {
++    PyJITTracer_On();
++    PyJITTracer_Off();
++  }
++  return 1;
++}
++
++void
++_PyJIT_Fini()
++{
++}
++
++void
++PyJITFunction_Free(struct _JITFunction* obj)
++{
++  if (!obj)
++    return;
++
++  if (obj->func) {
++    obj->func->eraseFromParent();
++  }
++
++  delete obj;
++}
+diff -r 7bacccd889c2 JIT/global_jit_data.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/global_jit_data.h	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,145 @@
++// -*- C++ -*-
++//
++
++#ifndef PYTHON_GLOBAL_JIT_DATA_H
++#define PYTHON_GLOBAL_JIT_DATA_H
++
++#ifndef __cplusplus
++#error This header expects to be included only in C++ source
++#endif
++
++#include "Python.h"
++#include "frameobject.h"
++#include "global_jit_data_fwd.h"
++
++#include "llvm/LLVMContext.h"
++#include "llvm/PassManager.h"
++
++#include <vector>
++#include <iostream>
++
++namespace llvm {
++class ExecutionEngine;
++}
++
++struct PyGlobalJITData {
++public:
++  static PyGlobalJITData *Get();
++
++  PyGlobalJITData();
++  ~PyGlobalJITData();
++
++  llvm::ExecutionEngine *getExecutionEngine() { return this->engine_; }
++  llvm::LLVMContext &context() const { return llvm::getGlobalContext(); }
++  llvm::Module *module() const { return this->module_; }
++
++  void optimize(llvm::Function *func);
++
++private:
++  llvm::Module *module_;
++  llvm::ExecutionEngine *engine_;
++
++  llvm::FunctionPassManager *opt_;
++
++};
++
++enum TRACE {
++  TR_STANDARD = 0,
++  TR_JUMP_TAKEN,
++  TR_EXCEPTION,
++};
++
++struct TraceEntry {
++  TraceEntry(PyCodeObject *c, int p, int op, int arg)
++    : code(c), pc(p), opcode(op), oparg(arg), flag(TR_STANDARD),
++      arg0(NULL), arg1(NULL)
++  {}
++
++  bool operator==(const TraceEntry &o)
++  {
++    return (code == o.code && pc == o.pc &&
++            opcode == o.opcode && oparg == o.oparg);
++  }
++
++  PyCodeObject *code;
++  int pc;
++  int opcode;
++  int oparg;
++  int flag;
++  PyTypeObject *arg0;
++  PyTypeObject *arg1;
++};
++
++struct PyJITTracer {
++public:
++  static PyJITTracer *Get();
++
++  PyJITTracer();
++  ~PyJITTracer();
++
++  void on()
++  {
++    active_ = true;
++    suspended_ = false;
++    unsuspend();
++  }
++  void off()
++  {
++    active_ = false;
++    suspended_ = true;
++  }
++
++  void unsuspend()
++  {
++    suspended_ = false;
++    trace_.clear();
++  }
++
++  void suspend()
++  {
++    suspended_ = true;
++  }
++
++  void trace(PyCodeObject *code, int pc, int opcode, int oparg);
++  void setFlag(TRACE flag)
++  {
++    if (!active_ || suspended_)
++      return;
++    TraceEntry &entry = trace_.back();
++    entry.flag = flag;
++  }
++
++  void setType(int pos, PyTypeObject* type)
++  {
++    if (!active_ || suspended_)
++      return;
++    TraceEntry &entry = trace_.back();
++    if (pos == 0) {
++      entry.arg0 = type;
++    }
++    else {
++      entry.arg1 = type;
++    }
++  }
++
++private:
++  void do_trace(PyCodeObject *code, size_t start);
++
++
++private:
++  bool active_;
++  bool suspended_;
++
++  std::vector<TraceEntry> trace_;
++};
++
++struct _JITFunction {
++  typedef int(*pyfunc_t)(PyFrameObject*);
++
++  int opcode;
++  llvm::Function *func;
++  pyfunc_t trace;
++};
++
++
++#endif
+diff -r 7bacccd889c2 JIT/global_jit_data_fwd.h
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/global_jit_data_fwd.h	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,33 @@
++#ifndef PYTHON_GLOBAL_JIT_FWD_H
++#define PYTHON_GLOBAL_JIT_FWD_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++
++#define PyGlobalJITData_GET() (PyThreadState_GET()->interp->global_jit_data)
++
++struct PyGlobalJITData *PyGlobalJITData_New(void);
++void PyGlobalJITData_Clear(struct PyGlobalJITData *);
++void PyGlobalJITData_Free(struct PyGlobalJITData *);
++
++#define PyJITTracer_GET() (PyThreadState_GET()->jit_tracer)
++struct PyJITTracer *PyJITTracer_New(void);
++void PyJITTracer_Clear(struct PyJITTracer *);
++void PyJITTracer_Free(struct PyJITTracer *);
++
++int _PyJIT_Init(void);
++void _PyJIT_Fini(void);
++
++PyAPI_FUNC(void) _PyJITTracer_On(void);
++PyAPI_FUNC(void) _PyJITTracer_Off(void);
++
++PyAPI_FUNC(void) PyJITTracer_On(void);
++PyAPI_FUNC(void) PyJITTracer_Off(void);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff -r 7bacccd889c2 JIT/jit_blackhole.cc
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/JIT/jit_blackhole.cc	Sat May 26 17:18:24 2012 +0200
+@@ -0,0 +1,70 @@
++#include "Python.h"
++#include "frameobject.h"
++#include "opcode.h"
++
++#include "JIT/jit_blackhole.h"
++
++#define INSTR_OFFSET()  ((int)(next_instr - first_instr))
++#define NEXTOP()        (*next_instr++)
++#define NEXTARG()       (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
++
++#define POP()           (*--(frame->f_stacktop))
++
++namespace jit {
++
++  int
++  PyJIT_BlackHoleEval(PyFrameObject *frame, int reason)
++  {
++    PyCodeObject *co = frame->f_code;
++    unsigned char* first_instr = (unsigned char*) PyBytes_AS_STRING(co->co_code);
++    unsigned char* next_instr = first_instr + frame->f_lasti;
++
++    int opcode;
++    int oparg;
++    PyObject *u, *v, *w;
++
++    switch (reason) {
++    case BH_FOR_ITER_EXC:
++      opcode = NEXTOP();
++      oparg = NEXTARG();
++      if (PyErr_Occurred()) {
++        if (!PyErr_ExceptionMatches(PyExc_StopIteration))
++          return BH_EXC;
++        PyErr_Clear();
++      }
++      next_instr += oparg;
++      frame->f_lasti = INSTR_OFFSET();
++      v = POP();
++      Py_DECREF(v);
++      return BH_CONTINUE;
++
++    case BH_LOAD_FAST_FAIL:
++      return BH_CONTINUE;
++
++    case BH_BINARY_OP_FAIL:
++    case BH_INPLACE_ADD_FAIL:
++      return BH_EXC;
++
++    case BH_NEXT_OPCODE:
++      opcode = NEXTOP();
++      if (HAS_ARG(opcode))
++        oparg = NEXTARG();
++      frame->f_lasti = INSTR_OFFSET();
++      return BH_CONTINUE;
++
++    case BH_JUMP_ARG:
++      opcode = NEXTOP();
++      oparg = NEXTARG();
++      frame->f_lasti = oparg;
++      return BH_CONTINUE;
++
++    case BH_EXC_RAISED:
++      return BH_EXC;
++
++    default:
++      break;
++    }
++    return BH_CONTINUE;
++  }
++
++}