Commits

ebo  committed a7ffea3

Implemented more stuff.

  • Participants
  • Parent commits fa30ce1

Comments (0)

Files changed (1)

 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);
+@@ -31,44 +31,54 @@
+ #define LIBPYTHON_BC "libpython" STRINGIFY(PY_MAJOR_VERSION) "." \
+   STRINGIFY(PY_MINOR_VERSION) ".bc"
+ 
++extern "C" {
++  extern char _binary_Modules_libpython3_3_bc_start;
++  extern char _binary_Modules_libpython3_3_bc_size;
++}
++
++static llvm::MemoryBuffer *
++find_stdlib_bc2()
++{
++  llvm::StringRef module(&_binary_Modules_libpython3_3_bc_start,
++                   (size_t)&_binary_Modules_libpython3_3_bc_size);
++  return llvm::MemoryBuffer::getMemBuffer(module, "", false);
++}
++
+ // 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());
++// 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);
++//   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();
-@@ -60,7 +59,6 @@
-     llvm::StringRef elem = "./Modules";
-     path = elem;
-     path.appendComponent(LIBPYTHON_BC);
+-    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();
+-    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;
+-}
++//   for (ssize_t i = 0, size = sys_path.size(); i < size; ++i) {
++//     llvm::StringRef elem = sys_path[i];
++//     path = elem;
++//     path.appendComponent(LIBPYTHON_BC);
++//     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);
++//     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()
+@@ -100,7 +110,7 @@
+   llvm::InitializeNativeTarget();
+ 
+   std::string error;
+-  llvm::MemoryBuffer *stdlib_file = find_stdlib_bc();
++  llvm::MemoryBuffer *stdlib_file = find_stdlib_bc2();
+   this->module_ = llvm::getLazyBitcodeModule(stdlib_file, llvm::getGlobalContext(), &error);
+   if (module_ == NULL) {
+     Py_FatalError(error.c_str());
 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
  int _PyJIT_Init(void);
  void _PyJIT_Fini(void);
  
+diff --git a/JIT/jit_blackhole.cc b/JIT/jit_blackhole.cc
+--- a/JIT/jit_blackhole.cc
++++ b/JIT/jit_blackhole.cc
+@@ -42,7 +42,6 @@
+       return BH_CONTINUE;
+ 
+     case BH_BINARY_OP_FAIL:
+-    case BH_INPLACE_ADD_FAIL:
+       return BH_EXC;
+ 
+     case BH_NEXT_OPCODE:
+diff --git a/JIT/jit_blackhole.h b/JIT/jit_blackhole.h
+--- a/JIT/jit_blackhole.h
++++ b/JIT/jit_blackhole.h
+@@ -21,7 +21,6 @@
+     BH_NEXT_OPCODE,
+     BH_FOR_ITER_EXC,
+     BH_LOAD_FAST_FAIL,
+-    BH_INPLACE_ADD_FAIL,
+   };
+ 
+   enum BH_RESULT {
 diff --git a/JIT/jit_tracer.cc b/JIT/jit_tracer.cc
 --- a/JIT/jit_tracer.cc
 +++ b/JIT/jit_tracer.cc
      return;
    }
  
+@@ -144,11 +145,11 @@
+ 
+   jit::JITTraceAnalysis analysis;
+   analysis.analyseTrace(cut_trace);
+-  // analysis.dump();
++  analysis.dump();
+   jit::JITFunctionState state(PyGlobalJITData::Get());
+   analysis.emit(state);
+   PyGlobalJITData::Get()->optimize(state.function());
+-  state.function()->dump();
++  // state.function()->dump();
+ 
+   typedef int(*pyfunc_t)(PyFrameObject*);
+   pyfunc_t trace_func =
 @@ -160,7 +161,8 @@
  }
  
  {
    if (!active_)
      return;
-@@ -207,11 +209,11 @@
+@@ -189,6 +191,36 @@
+ 
+ namespace jit {
+ 
++  void
++  JITStack::Push(JITValue *value)
++  {
++    stack.push_back(value);
++  }
++
++  JITValue *
++  JITStack::Pop()
++  {
++    if (stack.size() > 0) {
++      JITValue *v = stack.back();
++      stack.pop_back();
++      return v;
++    }
++
++    JITStackValue *v = new JITStackValue;
++    this->loaded_stack.push_back(v);
++    return v;
++  }
++
++  JITValue *
++  JITStack::Top()
++  {
++    JITValue *v = this->Pop();
++    this->Push(v);
++    return v;
++  }
++
++  // *******************************
++
+   JITTraceAnalysis::JITTraceAnalysis()
+     : stack_counter_(0)
+   {
+@@ -206,37 +238,47 @@
+     }
    }
  
-   JITValue *
+-  JITValue *
 -  JITTraceAnalysis::Pop()
-+  JITTraceAnalysis::Pop(stack_t &stack)
++  void
++  JITTraceAnalysis::createBinaryOp(JITStack &stack, TraceEntry &entry)
    {
 -    if (stack_.size() > 0) {
 -      JITValue *v = stack_.back();
 -      stack_.pop_back();
-+    if (stack.size() > 0) {
-+      JITValue *v = stack.back();
-+      stack.pop_back();
-       return v;
+-      return v;
++    int opcode = entry.opcode;
++    JITValue *w = stack.Pop();
++    JITValue *v = stack.Pop();
++    if (entry.arg0 != NULL)
++      v->registerStaticType(entry.arg0);
++    if (entry.arg1 != NULL)
++      w->registerStaticType(entry.arg1);
++
++    JITValue *x = NULL;
++    switch (opcode) {
++    case INPLACE_ADD:
++      x = this->createInplaceAdd(v, w);
++      break;
++
++    case BINARY_ADD:
++      x = this->createBinaryAdd(v, w);
++      break;
++
++    case BINARY_SUBTRACT:
++      x = this->createBinarySubtract(v, w);
++      break;
++
++    case BINARY_MULTIPLY:
++      x = this->createBinaryMultiply(v, w);
++      break;
++
++    case BINARY_FLOOR_DIVIDE:
++      x = this->createBinaryDivide(v, w);
++      break;
      }
- 
-@@ -221,22 +223,23 @@
-   }
- 
-   JITValue *
+-
+-    JITStackValue *v = new JITStackValue;
+-    loaded_stack_.push_back(v);
+-    return v;
+-  }
+-
+-  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
+-    return v;
+-  }
+-
+-  void
 -  JITTraceAnalysis::Push(JITValue *value)
-+  JITTraceAnalysis::Push(stack_t &stack, JITValue *value)
-   {
+-  {
 -    stack_.push_back(value);
-+    stack.push_back(value);
++    this->createGuardNull(x, BH_BINARY_OP_FAIL, entry.pc, stack);
++    stack.Push(x);
    }
  
    void
    JITTraceAnalysis::analyseTrace(std::vector<TraceEntry> &trace)
    {
-+    stack_t stack;
++    JITStack stack;
      for (size_t i = 0; i < trace.size(); ++i) {
        TraceEntry &entry = trace[i];
        int opcode = entry.opcode;
-@@ -249,87 +252,113 @@
+@@ -249,87 +291,89 @@
  
  
        case POP_JUMP_IF_FALSE:
 -        v = this->Pop();
-+        v = this->Pop(stack);
++        v = stack.Pop();
          if (flag == TR_STANDARD) {
 -          this->createGuardTrue(v, BH_JUMP_ARG, entry.pc);
 +          this->createGuardTrue(v, BH_JUMP_ARG, entry.pc, stack);
  
        case FOR_ITER:
 -        v = this->Top();
-+        v = this->Top(stack);
++        v = stack.Top();
          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);
++        stack.Push(x);
          continue;
  
        case STORE_FAST:
 -        v = this->Pop();
-+        v = this->Pop(stack);
++        v = stack.Pop();
 +        if (entry.arg0 != NULL)
 +          v->registerStaticType(entry.arg0);
          this->createStoreFast(v, entry.oparg);
 +        this->createGuardNull(v, BH_LOAD_FAST_FAIL, entry.pc, stack);
          this->createIncRef(v);
 -        this->Push(v);
-+        this->Push(stack, v);
++        stack.Push(v);
          continue;
  
        case LOAD_CONST:
          v = this->createLoadConst(entry.oparg);
          this->createIncRef(v);
 -        this->Push(v);
-+        this->Push(stack, v);
++        stack.Push(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);
+-        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;
- 
+-        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);
+-        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;
- 
+-        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);
+-        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;
- 
+-        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);
+-        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;
- 
+-        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);
+-        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;
+-        continue;
++        this->createBinaryOp(stack, entry);
++        break;
  
        case COMPARE_OP:
 -        w = this->Pop();
 -        v = this->Pop();
-+        w = this->Pop(stack);
-+        v = this->Pop(stack);
++        w = stack.Pop();
++        v = stack.Pop();
 +        if (entry.arg0 != NULL)
 +          v->registerStaticType(entry.arg0);
 +        if (entry.arg1 != NULL)
 -        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);
++        stack.Push(x);
          continue;
        }
      }
 -    this->createTraceEnd();
 +    this->createTraceEnd(stack);
++    loaded_stack_ = stack.loaded_stack;
++    stack_counter_ = stack.stack_counter;
++  }
++
++  void
++  JITTraceAnalysis::analyseTypes()
++  {
++    JITStack stack;
++    std::vector<JITOpcode *> source;
++    trace_.swap(source);
++
++    JITOpcodeInfo *info = NULL;
++
++    for (size_t i = 0; i < source.size(); ++i) {
++      JITOpcode *op = source[i];
++      if (JITOpcodeInfo *v = dyn_cast<JITOpcodeInfo>(op)) {
++        info = v;
++        trace_.push_back(op);
++        continue;
++      }
++
++      if (JITInplaceAdd *v = dyn_cast<JITInplaceAdd>(op)) {
++        if (v->needsArgsTypeChecked()) {
++        }
++      }
++
++      trace_.push_back(op);
++    }
    }
  
  
-@@ -337,6 +366,7 @@
+@@ -337,6 +381,7 @@
    JITStackValue::emit(JITFunctionBuilder &builder)
    {
      value_ = builder.Pop();
    }
  
    void
-@@ -351,6 +381,7 @@
+@@ -351,6 +396,7 @@
                           "tp_iternext");
  
      value_ = fbuilder.getState()->CreateCall(tp_iternext, v);
    }
  
    void
-@@ -370,6 +401,7 @@
+@@ -370,6 +416,7 @@
      JITFunctionState::BuilderT &builder = fbuilder.builder();
      llvm::Value *localptr = fbuilder.LocalPtr(oparg_);
      value_ = builder.CreateLoad(localptr);
    }
  
    void
-@@ -378,6 +410,7 @@
+@@ -378,6 +425,7 @@
      JITFunctionState::BuilderT &builder = fbuilder.builder();
      llvm::Value *localptr = fbuilder.ConstPtr(oparg_);
      value_ = builder.CreateLoad(localptr);
    }
  
    void
-@@ -385,12 +418,25 @@
+@@ -385,12 +433,24 @@
    {
      JITFunctionState *state = fbuilder.getState();
  
 +    if (arg0_->getStaticType()->isFloat() &&
-+        arg1_->getStaticType()->isFloat() &&
-+        this->getStaticType()->isFloat()) {
++        arg1_->getStaticType()->isFloat()) {
 +      std::cout << "InplaceAdd may be specialized\n";
 +      JITType *type0 = arg0_->getStaticType();
 +      JITType *type1 = arg1_->getStaticType();
    }
  
    void
-@@ -404,6 +450,7 @@
+@@ -404,6 +464,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -417,6 +464,7 @@
+@@ -417,6 +478,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -430,6 +478,7 @@
+@@ -430,6 +492,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -443,6 +492,7 @@
+@@ -443,6 +506,7 @@
                                 arg1_->getValue());
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
    }
  
    void
-@@ -457,6 +507,7 @@
+@@ -457,6 +521,13 @@
  
      state->DecRef(arg0_->getValue());
      state->DecRef(arg1_->getValue());
 +    this->getStaticType()->init(value_);
++  }
++
++
++  void
++  JITGuardType::emit(JITFunctionBuilder &fbuilder)
++  {
    }
  
    void
+@@ -566,4 +637,21 @@
+     state->IncRef(arg_->getValue());
+   }
+ 
++  const int JITOpcodeInfo::ID = 0;
++  const int JITStackValue::ID = 0;
++  const int JITForIter::ID = 0;
++  const int JITStoreFast::ID = 0;
++  const int JITLoadFast::ID = 0;
++  const int JITLoadConst::ID = 0;
++  const int JITInplaceAdd::ID = 0;
++  const int JITBinaryAdd::ID = 0;
++  const int JITBinarySubtract::ID = 0;
++  const int JITBinaryMultiply::ID = 0;
++  const int JITBinaryDivide::ID = 0;
++  const int JITCompareOp::ID = 0;
++  const int JITIncRef::ID = 0;
++  const int JITGuardNull::ID = 0;
++  const int JITGuardType::ID = 0;
++  const int JITGuardTrue::ID = 0;
++  const int JITTraceEnd::ID = 0;
+ } // namespace jit
 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 @@
+@@ -9,24 +9,75 @@
  #include "JIT/global_jit_data.h"
  #include "JIT/jit_blackhole.h"
  #include "JIT/jit_fbuilder.h"
    public:
      virtual void dump() = 0;
      virtual void emit(JITFunctionBuilder &builder) = 0;
++
++    virtual uintptr_t type() = 0;
 +  };
 +
++  template<class T>
++  T *dyn_cast(JITOpcode *v)
++  {
++    uintptr_t id = reinterpret_cast<uintptr_t>(&(T::ID));
++    if (v->type() == id) {
++      return reinterpret_cast<T*>(v);
++    }
++    return NULL;
++  }
++
 +  class JITValue : public JITOpcode {
 +  public:
 +    // virtual llvm::Value *getOrMaterializeValue(JITFunctionBuilder &builder) = 0;
 +    virtual void emit(JITFunctionBuilder &)
 +    {}
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
 +  private:
 +    int lasti_;
 +    std::vector<JITValue *> stack_;
      virtual void dump()
      {
        std::cout << "Stack Value\n";
-@@ -34,16 +67,39 @@
+@@ -34,16 +85,45 @@
      virtual void emit(JITFunctionBuilder &builder);
      virtual llvm::Value *getValue() const
      {
 -      return value_;
 +      return getStaticType()->getValue();
-+    }
-+
+     }
+ 
 +    virtual JITType *getStaticType() const
 +    {
 +      return type_;
 +          std::cout << "Trace Type mismatch\n";
 +        }
 +      }
-     }
- 
++    }
++
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      llvm::Value *value_;
 +    JITType *type_;
      {}
  
      virtual void dump()
-@@ -55,17 +111,41 @@
+@@ -55,17 +135,47 @@
  
      virtual llvm::Value *getValue() const
      {
 +      }
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg_;
      llvm::Value *value_;
      {}
  
      virtual void dump()
-@@ -75,20 +155,15 @@
+@@ -75,20 +185,21 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -    virtual llvm::Value *getValue() const
--    {
++    virtual uintptr_t type()
+     {
 -      return value_;
--    }
++      return reinterpret_cast<uintptr_t>(&ID);
+     }
++    static const int ID;
++
    private:
      JITValue *arg_;
      int oparg_;
      {}
  
      virtual void dump()
-@@ -100,17 +175,41 @@
+@@ -100,17 +211,47 @@
  
      virtual llvm::Value *getValue() const
      {
 +      }
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      int oparg_;
      llvm::Value *value_;
      {}
  
      virtual void dump()
-@@ -124,15 +223,26 @@
+@@ -124,16 +265,45 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      int oparg_;
      llvm::Value *value_;
    public:
      JITInplaceAdd(JITValue *arg0, JITValue *arg1)
 -      : arg0_(arg0), arg1_(arg1), value_(NULL)
-+      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject)
-     {}
+-    {}
++      : arg0_(arg0), arg1_(arg1), value_(NULL), type_(new JITOpaqueObject),
++        float_inline_(false)
++    {
++      if (arg0_->getStaticType()->isFloat() &&
++          arg1_->getStaticType()->isFloat()) {
++        this->registerStaticType(&PyFloat_Type);
++        float_inline_ = true;
++      }
++    }
++
++    bool needsArgsTypeChecked()
++    {
++      return float_inline_;
++    }
  
      virtual void dump()
-@@ -144,18 +254,42 @@
+     {
+@@ -144,18 +314,49 @@
  
      virtual llvm::Value *getValue() const
      {
 +      }
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      llvm::Value *value_;
 +    JITType *type_;
++    bool float_inline_;
    };
  
    class JITBinaryAdd : public JITValue {
      {}
  
      virtual void dump()
-@@ -169,16 +303,27 @@
+@@ -169,16 +370,33 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      {}
  
      virtual void dump()
-@@ -192,16 +337,27 @@
+@@ -192,16 +410,33 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      {}
  
      virtual void dump()
-@@ -215,16 +371,27 @@
+@@ -215,16 +450,33 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      {}
  
      virtual void dump()
-@@ -238,17 +405,28 @@
+@@ -238,17 +490,34 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      {}
  
      virtual void dump()
-@@ -262,16 +440,27 @@
+@@ -262,16 +531,33 @@
      {
        return value_;
      }
 +    {
 +    }
 +
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
    private:
      JITValue *arg0_;
      JITValue *arg1_;
      {}
  
      virtual void dump()
-@@ -281,21 +470,16 @@
+@@ -281,21 +567,50 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -    virtual llvm::Value *getValue() const
--    {
++    virtual uintptr_t type()
+     {
 -      return value_;
--    }
++      return reinterpret_cast<uintptr_t>(&ID);
+     }
++    static const int ID;
++
    private:
      JITValue *arg_;
 -    llvm::Value *value_;
    };
  
 -  class JITGuardNull : public JITValue {
++  class JITGuardType : public JITOpcode {
++  public:
++    JITGuardType(JITType *arg, BLACKHOLE reason, int lasti,
++                 std::vector<JITValue *> &stack)
++      : arg_(arg), reason_(reason), lasti_(lasti),
++        stack_(stack)
++    {}
++
++    virtual void dump()
++    {
++      std::cout << "GUARD_TYPE\n";
++    }
++
++    virtual void emit(JITFunctionBuilder &builder);
++
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
++  private:
++    JITType *arg_;
++    BLACKHOLE reason_;
++    int lasti_;
++    std::vector<JITValue *> stack_;
++  };
++
 +  class JITGuardNull : public JITOpcode {
    public:
      JITGuardNull(JITValue *arg, BLACKHOLE reason, int lasti,
      {}
  
      virtual void dump()
-@@ -305,24 +489,19 @@
+@@ -305,24 +620,25 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -    virtual llvm::Value *getValue() const
--    {
++    virtual uintptr_t type()
+     {
 -      return value_;
--    }
++      return reinterpret_cast<uintptr_t>(&ID);
+     }
++    static const int ID;
++
    private:
      JITValue *arg_;
      BLACKHOLE reason_;
      {}
  
      virtual void dump()
-@@ -332,22 +511,17 @@
+@@ -332,22 +648,23 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -    virtual llvm::Value *getValue() const
--    {
++    virtual uintptr_t type()
+     {
 -      return value_;
--    }
++      return reinterpret_cast<uintptr_t>(&ID);
+     }
++    static const int ID;
++
    private:
      JITValue *arg_;
      BLACKHOLE reason_;
      {}
  
      virtual void dump()
-@@ -357,23 +531,20 @@
+@@ -357,24 +674,40 @@
  
      virtual void emit(JITFunctionBuilder &builder);
  
 -    virtual llvm::Value *getValue() const
--    {
++    virtual uintptr_t type()
+     {
 -      return value_;
--    }
++      return reinterpret_cast<uintptr_t>(&ID);
+     }
++    static const int ID;
++
    private:
      std::vector<JITValue *> stack_;
 -    llvm::Value *value_;
    };
  
-   struct JITTraceAnalysis {
+-  struct JITTraceAnalysis {
+-    JITTraceAnalysis();
+-
+-    void analyseTrace(std::vector<TraceEntry> &trace);
++  class JITStack {
++  public:
++    JITStack()
++    {}
++    ~JITStack()
++    {}
+ 
+     void Push(JITValue *value);
+     JITValue *Pop();
+     JITValue *Top();
+ 
++    std::vector<JITValue *> stack;
++    std::vector<JITStackValue *> loaded_stack;
++    int stack_counter;
++  };
++
++  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);
- 
++    JITTraceAnalysis();
++
++    void analyseTrace(std::vector<TraceEntry> &trace);
++    void analyseTypes();
++
      void dump()
      {
-@@ -387,6 +558,13 @@
+       for (size_t i = 0; i < loaded_stack_.size(); ++i) {
+@@ -387,6 +720,15 @@
  
      void emit(JITFunctionState &state);
  
-+    JITOpcodeInfo *createOpcodeInfo(int lasti, stack_t &stack)
++    void createBinaryOp(JITStack &stack, TraceEntry &entry);
++
++    JITOpcodeInfo *createOpcodeInfo(int lasti, JITStack &stack)
 +    {
-+      JITOpcodeInfo *r = new JITOpcodeInfo(lasti, stack);
++      JITOpcodeInfo *r = new JITOpcodeInfo(lasti, stack.stack);
 +      trace_.push_back(r);
 +      return r;
 +    }
      JITForIter *createForIter(JITValue *v)
      {
        JITForIter *r = new JITForIter(v);
-@@ -436,16 +614,16 @@
+@@ -436,16 +778,23 @@
        return r;
      }
  
 -    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti)
-+    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti, stack_t &stack)
++    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack)
      {
 -      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack_);
-+      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack);
++      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack.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 *createGuardTrue(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack)
      {
 -      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack_);
-+      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack);
++      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack.stack);
++      trace_.push_back(r);
++      return r;
++    }
++
++    JITGuardType *createGuardType(JITType *v, BLACKHOLE reason, int lasti, JITStack &stack)
++    {
++      JITGuardType *r = new JITGuardType(v, reason, lasti, stack.stack);
        trace_.push_back(r);
        return r;
      }
-@@ -478,19 +656,18 @@
+@@ -478,19 +827,18 @@
        return r;
      }
  
 -    JITTraceEnd *createTraceEnd()
-+    JITTraceEnd *createTraceEnd(stack_t &stack)
++    JITTraceEnd *createTraceEnd(JITStack &stack)
      {
 -      JITTraceEnd *r = new JITTraceEnd(stack_);
-+      JITTraceEnd *r = new JITTraceEnd(stack);
++      JITTraceEnd *r = new JITTraceEnd(stack.stack);
        trace_.push_back(r);
        return r;
      }
 +    return NULL;
 +  }
 +
-+  llvm::Value *
-+  JITBoxedFloat::ensureGuard(JITFunctionBuilder &fbuilder)
-+  {
-+    if (has_guard_)
-+      return NULL;
++  // llvm::Value *
++  // JITBoxedFloat::ensureGuard(JITFunctionBuilder &fbuilder)
++  // {
++  //   if (has_guard_)
++  //     return NULL;
 +
-+    JITFunctionState::BuilderT &builder = fbuilder.builder();
-+    JITFunctionState *state = fbuilder.getState();
++  //   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);
++  //   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;
-+  }
++  //   return check;
++  // }
 +
 +  llvm::Value *
 +  JITBoxedFloat::getNakedValue(JITFunctionBuilder &fbuilder)
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_types.h
-@@ -0,0 +1,163 @@
+@@ -0,0 +1,196 @@
 +// -*- C++ -*-
 +#ifndef PYTHON_JIT_TYPES_H_
 +#define PYTHON_JIT_TYPES_H_
 +    virtual bool canSpecialize(const PyTypeObject *) const = 0;
 +
 +    virtual llvm::Value *getValue() const = 0;
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder) = 0;
 +
 +    virtual bool isFloat() const
 +    {
 +      return false;
 +    }
 +
-+    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder) = 0;
-+    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder) = 0;
++    virtual bool hasGuard() const = 0;
++    virtual void setGuard(bool v) = 0;
++    virtual PyTypeObject *getPyType() const = 0;
++
 +  };
 +
 +  class JITOpaqueObject : public JITType {
 +      return value_;
 +    }
 +
-+    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder)
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
 +    {
 +      return NULL;
 +    }
 +
-+    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
++    virtual bool hasGuard() const
++    {
++      return true;
++    }
++
++    virtual void setGuard(bool)
++    {}
++
++    virtual PyTypeObject *getPyType() const
 +    {
 +      return NULL;
 +    }
 +
 +    virtual bool matchesType(const PyTypeObject *t) const
 +    {
-+      return PyFloat_CheckExact(t);
++      return &PyFloat_Type == t;
 +    }
 +    virtual bool canSpecialize(const PyTypeObject *) const
 +    {
 +      return value_;
 +    }
 +
-+    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder);
 +    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder);
 +
++    virtual bool hasGuard() const
++    {
++      return has_guard_;
++    }
++
++    virtual void setGuard(bool v)
++    {
++      has_guard_ = v;
++    }
++
++    virtual PyTypeObject *getPyType() const
++    {
++      return &PyFloat_Type;
++    }
++
 +  private:
 +    llvm::Value *value_;
 +    llvm::Value *naked_value_;
 +
 +    virtual bool matchesType(const PyTypeObject *t) const
 +    {
-+      return PyFloat_CheckExact(t);
++      return &PyFloat_Type == t;
 +    }
 +    virtual bool canSpecialize(const PyTypeObject *) const
 +    {
 +      return NULL;
 +    }
 +
-+    virtual llvm::Value *ensureGuard(JITFunctionBuilder &fbuilder)
++    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
 +    {
 +      return NULL;
 +    }
 +
-+    virtual llvm::Value *getNakedValue(JITFunctionBuilder &fbuilder)
++    virtual bool hasGuard() const
 +    {
-+      return NULL;
++      return true;
++    }
++
++    virtual void setGuard(bool)
++    {}
++
++    virtual PyTypeObject *getPyType() const
++    {
++      return &PyFloat_Type;
 +    }
 +
 +  private:
 diff --git a/Makefile.pre.in b/Makefile.pre.in
 --- a/Makefile.pre.in
 +++ b/Makefile.pre.in
-@@ -73,7 +73,7 @@
+@@ -30,6 +30,7 @@
+ 
+ CC=		@CC@
+ CXX=		@CXX@
++LD=		@LD@
+ MAINCC=		@MAINCC@
+ LINKCC=		@LINKCC@
+ AR=		@AR@
+@@ -73,7 +74,7 @@
  # command line to append to these values without stomping the pre-set
  # values.
  PY_CFLAGS=	$(BASECFLAGS) $(OPT) $(CONFIGURE_CFLAGS) $(CFLAGS) $(EXTRA_CFLAGS)
  # 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 @@
+@@ -332,7 +333,7 @@
  		Python/asdl.o \
  		Python/ast.o \
  		Python/bltinmodule.o \
  		Python/compile.o \
  		Python/codecs.o \
  		Python/dynamic_annotations.o \
-@@ -379,6 +379,7 @@
+@@ -379,6 +380,7 @@
  PYTHON_OBJS+=	\
  		JIT/global_jit_data.o \
  		JIT/jit_tracer.o \
  		JIT/PyTypeBuilder.o \
  		JIT/SingleFunctionInliner.o \
  		JIT/jit_blackhole.o \
-@@ -730,7 +731,7 @@
+@@ -494,14 +496,14 @@
+ 
+ # Build static library
+ # avoid long command lines, same as LIBRARY_OBJS
+-$(LIBRARY): $(LIBRARY_OBJS) $(LLVM_LIB_PATHS)
++$(LIBRARY): $(LIBRARY_OBJS) $(LLVM_LIB_PATHS) JIT/jit_inline_functions.o
+ 	-rm -f $@
+ 	$(AR) $(ARFLAGS) $@ Modules/getbuildinfo.o
+ 	$(AR) $(ARFLAGS) $@ $(PARSER_OBJS)
+ 	$(AR) $(ARFLAGS) $@ $(OBJECT_OBJS)
+ 	$(AR) $(ARFLAGS) $@ $(PYTHON_OBJS)
+ 	$(AR) $(ARFLAGS) $@ $(MODULE_OBJS) $(SIGNAL_OBJS)
+-	$(AR) $(ARFLAGS) $@ $(MODOBJS)
++	$(AR) $(ARFLAGS) $@ $(MODOBJS) JIT/jit_inline_functions.o
+ 	$(RANLIB) $@
+ 
+ libpython$(LDVERSION).so: $(LIBRARY_OBJS)
+@@ -730,7 +732,7 @@
  $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES)
  	$(OPCODETARGETGEN) $(OPCODETARGETS_H)
  
  
  Python/formatter_unicode.o: $(srcdir)/Python/formatter_unicode.c \
  				$(BYTESTR_DEPS)
-@@ -832,6 +833,7 @@
+@@ -832,6 +834,7 @@
  		$(srcdir)/JIT/global_jit_data_fwd.h \
  		$(srcdir)/JIT/jit_fstate.h \
  		$(srcdir)/JIT/jit_tracer.h \
  		$(srcdir)/JIT/jit_fbuilder.h \
  		$(srcdir)/JIT/jit_blackhole.h \
  		$(srcdir)/JIT/PyTypeBuilder.h \
+@@ -849,7 +852,8 @@
+ 	$(LLVM_BIN_DIR)/llvm-link -o $@ $(filter %.bc, $^)
+ $(BCLIBRARY): $(BCLIBRARY:.bc=.unopt.bc)
+ 	$(LLVM_BIN_DIR)/opt -o $@ -O3 $<
+-
++JIT/jit_inline_functions.o: $(BCLIBRARY)
++	$(LD) -r -b binary -o $@ $(BCLIBRARY)
+ 
+ ######################################################################
+ 
 diff --git a/Objects/codeobject.c b/Objects/codeobject.c
 --- a/Objects/codeobject.c
 +++ b/Objects/codeobject.c
              x = v = POP();
              Py_DECREF(v);
              JUMPBY(oparg);
+diff --git a/configure.ac b/configure.ac
+--- a/configure.ac
++++ b/configure.ac
+@@ -793,6 +793,9 @@
+ esac
+ AC_MSG_RESULT($GNULD)
+ 
++AC_SUBST(LD)
++LD=$ac_proc
++
+ AC_C_INLINE
+ if test "$ac_cv_c_inline" != no ; then
+         AC_DEFINE(USE_INLINE, 1, [Define to use the C99 inline keyword.])