Commits

ebo committed 864cd20

Stack and locals are now managed with phi nodes

Comments (0)

Files changed (1)

 +llvm::FunctionPass *PyCreateSingleFunctionInliningPass();
 +
 +#endif  // UTIL_SINGLEFUNCTIONINLINER_H
+diff --git a/JIT/TODO b/JIT/TODO
+new file mode 100644
+--- /dev/null
++++ b/JIT/TODO
+@@ -0,0 +1,3 @@
++Add JITPhiNode
++
++global_jit_data.cc: Delete engine again. Currently crashes.
+\ No newline at end of file
 diff --git a/JIT/_jitfunctionobject.h b/JIT/_jitfunctionobject.h
 new file mode 100644
 --- /dev/null
 +  if (self->co_jit) {
 +    std::string str;
 +    llvm::raw_string_ostream out(str);
-+    for (size_t i = 0, e = self->co_jit->funcs.size(); i < e; ++i) {
-+      _JITFunction &func = self->co_jit->funcs[i];
++    for (auto &func : self->co_jit->funcs) {
 +      func.func->print(out);
 +    }
 +    return PyUnicode_DecodeLocale(out.str().c_str(), NULL);
 +
 +PyGlobalJITData::~PyGlobalJITData()
 +{
-+  delete this->engine_;
++  // TODO: delete engine?!?
++  // delete this->engine_;
 +}
 +
 +int
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_analyse.cc
-@@ -0,0 +1,380 @@
+@@ -0,0 +1,382 @@
 +#include "Python.h"
 +#include "Include/opcode.h"
 +
 +      }
 +    }
 +    else {
-+      opb.createTraceEnd(stack, locals);
++      JITTraceEnd *t = opb.createTraceEnd(stack, locals);
++      locals.TraceEnd(t);
++      stack.TraceEnd(t);
 +    }
 +    return 0;
 +  }
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_env.cc
-@@ -0,0 +1,104 @@
+@@ -0,0 +1,165 @@
 +#include "Python.h"
 +
 +#include "global_jit_data_fwd.h"
 +namespace jit {
 +
 +  void
++  JITStack::TraceEnd(JITTraceEnd *t)
++  {
++    auto &fstack = frame_->stack();
++    assert(stack.size() == frame_->stack().size());
++
++    for (size_t i = 0; i < stack.size(); ++i) {
++      auto phi = fstack[i].second;
++      assert(phi != nullptr);
++
++      if (phi == stack[i])
++        continue;
++
++      phi->add_edge(stack[i]);
++      t->push_stack(stack[i], phi);
++    }
++  }
++
++  void
 +  JITStack::Push(JITValue *value)
 +  {
 +    stack.push_back(value);
 +  }
 +
++  std::pair<JITStackValue *, JITPhiNode *> JITStack::Generate()
++  {
++    JITStackValue *v = new JITStackValue;
++    JITPhiNode *p = new JITPhiNode(v);
++
++    auto &loaded = frame_->stack();
++
++    loaded.push_back(std::make_pair(v, p));
++    frame_->getFrameBlock()->push_front(p);
++
++    return loaded.back();
++  }
++
 +  JITValue *
 +  JITStack::Pop()
 +  {
 +    if (stack.size() > 0) {
 +      JITValue *v = stack.back();
 +      stack.pop_back();
-+      if (stack.size() == 0) {
-+        std::cout << "*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*!*\n";
-+      }
 +      return v;
 +    }
 +
 +    auto &loaded = frame_->stack();
 +
-+    // Pull value from shared loaded_stack
-+    if (static_cast<int>(loaded.size()) > stack_counter_) {
-+      return loaded[stack_counter_++];
-+    }
-+
-+    JITStackValue *v = new JITStackValue;
-+    loaded.push_back(v);
-+    ++stack_counter_;
-+    return v;
++    // Pull value from shared loaded_stack, pull one more value from frame stack if needed
++    if (static_cast<int>(loaded.size()) <= stack_counter_) {
++      this->Generate();
++    }
++    return loaded[stack_counter_++].second;
 +  }
 +
 +  JITValue *
 +  JITLocals::JITLocals(const JITLocals &other)
 +      : locals(other.locals), frame_(other.frame_), no_load_(other.no_load_) {}
 +
++  JITPhiNode *
++  JITLocals::Find(size_t num)
++  {
++    auto &flocals = frame_->locals();
++
++    assert(flocals.size() > num);
++    return flocals[num].second;
++  }
++
++  void
++  JITLocals::TraceEnd(JITTraceEnd *t)
++  {
++    for (size_t i = 0; i < locals.size(); ++i) {
++      auto v = locals[i];
++      if (v == nullptr)
++        continue;
++
++      JITPhiNode *s = this->Find(i);
++
++      assert(s != nullptr);
++
++      if (v == s)
++        continue;
++
++      s->add_edge(v);
++      t->push_local(v, s);
++    }
++  }
++
++  std::pair<JITLocalValue *, JITPhiNode *>
++  JITLocals::Generate(size_t num)
++  {
++    JITLocalValue *v = new JITLocalValue(static_cast<int>(num));
++    JITPhiNode *p = new JITPhiNode(v);
++
++    auto &flocals = frame_->locals();
++    if (flocals.size() <= num) {
++      flocals.resize(num + 1);
++    }
++
++
++    flocals[num] = std::make_pair(v, p);
++    frame_->getFrameBlock()->push_front(p);
++
++    return flocals[num];
++  }
++
 +  JITValue *
 +  JITLocals::Load(size_t num)
 +  {
 +      locals.resize(num + 1);
 +    }
 +    if (locals[num] == NULL) {
-+      if (!no_load_) {
-+        JITLocalValue *v = nullptr;
-+
-+        for (auto val : frame_->locals()) {
-+          if (val->number() == static_cast<int>(num)) {
-+            v = val;
-+            break;
-+          }
-+        }
-+
-+        if (v == nullptr) {
-+          v = new JITLocalValue(num);
-+          frame_->locals().push_back(v);
-+        }
-+        locals[num] = v;
++      assert(!no_load_);
++
++      auto &flocals = frame_->locals();
++
++      if (flocals.size() <= num || flocals[num].first == nullptr) {
++        this->Generate(num);
 +      }
-+      else {
-+        assert(false);
-+      }
++
++      locals[num] = flocals[num].second;
 +    }
 +
 +    return locals[num];
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_env.h
-@@ -0,0 +1,59 @@
+@@ -0,0 +1,68 @@
 +// -*- C++ -*-
 +#ifndef PYTHON_JIT_ENV_H_
 +#define PYTHON_JIT_ENV_H_
 +  class JITValue;
 +  class JITStackValue;
 +  class JITLocalValue;
++  class JITTraceEnd;
++  class JITPhiNode;
 +  class JITBasicFrame;
 +
 +  class JITStack {
 +  public:
-+    JITStack(JITBasicFrame *frame) : frame_(frame), stack_counter_(0)
-+    {}
++    JITStack(JITBasicFrame *frame) : frame_(frame), stack_counter_(0) {}
 +    JITStack(const JITStack &other)
 +        : stack(other.stack), frame_(other.frame_),
 +          stack_counter_(other.stack_counter_) {}
 +    ~JITStack() {}
 +
++    void TraceEnd(JITTraceEnd *t);
++
 +    void Push(JITValue *value);
 +    JITValue *Pop();
 +
 +
 +    std::vector<JITValue *> stack;
 +  private:
++    std::pair<JITStackValue *, JITPhiNode *> Generate();
++
 +    JITBasicFrame *frame_;
 +    // How many values were already loaded from the frame
 +    int stack_counter_;
 +    JITLocals(JITBasicFrame *frame, int num = 0);
 +    JITLocals(const JITLocals &other);
 +
++    void TraceEnd(JITTraceEnd *t);
 +    void setNoLoad(bool no_load) {
 +      no_load_ = no_load;
 +    }
 +
 +    std::vector<JITValue *> locals;
 +  private:
++    std::pair<JITLocalValue *, JITPhiNode *> Generate(size_t);
++    JITPhiNode *Find(size_t num);
++
 +    JITBasicFrame *frame_;
 +    bool no_load_;
 +  };
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_fbuilder.cc
-@@ -0,0 +1,428 @@
+@@ -0,0 +1,434 @@
 +#include "Python.h"
 +#include "opcode.h"
 +
 +
 +namespace jit {
 +
-+  JITFasterFBuilder::JITFasterFBuilder(JITFunctionBuilder &parent,
-+                                       llvm::BasicBlock *bail_parent,
-+                                       llvm::Value *bail_result,
-+                                       llvm::Value *code,
-+                                       llvm::Value *globals,
-+                                       llvm::Value *builtins)
-+    : state_(parent.getState()),
-+      builder_(state_->builder()),
-+      context_(state_->context()),
-+      function_(state_->function()),
-+      code_(code),
-+      globals_(globals),
-+      builtins_(builtins),
-+      bail_parent_(bail_parent),
-+      bail_result_(bail_result)
-+  {
-+
-+    // Export entry block
-+    llvm::BasicBlock *entry = this->state_->CreateBasicBlock("entry_inlined");
-+    this->builder_.CreateBr(entry);
-+    this->builder_.SetInsertPoint(entry);
-+
-+    names_ = this->builder_.CreateLoad(CodeTy::co_names(this->builder_, this->code_), "names");
-+
-+    Function *func = this->state_->GetGlobalFunction<PyObject**(PyCodeObject*)>("_PyJIT_GetConstsFromCode");
-+    consts_ = this->state_->CreateCall(func, this->code_);
-+
-+    this->trace_block_ = this->state_->CreateBasicBlock("trace_block");
-+    this->builder_.CreateBr(this->trace_block_);
-+
-+    this->CreateBailBlock();
-+
-+    this->builder_.SetInsertPoint(this->trace_block_);
-+    this->SetBailReason(BH_NO_BLACKHOLE);
-+  }
-+
-+  void
-+  JITFasterFBuilder::CreateBailBlock()
-+  {
-+    this->bail_reason_ =
-+      this->state_->CreateAllocaInEntryBlock(Type::getInt32Ty(this->context_),
-+                                             NULL, "bail_reason");
-+    this->bail_frame_ =
-+      this->state_->CreateAllocaInEntryBlock(PyTypeBuilder<PyFrameObject*>::get(this->context_),
-+                                             NULL, "bail_frame");
-+    this->lasti_store_ =
-+      this->state_->CreateAllocaInEntryBlock(Type::getInt32Ty(this->context_),
-+                                             NULL, "lasti");
-+
-+    this->bail_block_ = this->state_->CreateBasicBlock("bail_block");
-+    this->builder_.SetInsertPoint(this->bail_block_);
-+
-+    Value *frame = this->builder_.CreateLoad(this->bail_frame_);
-+
-+    Value *f_lasti = FrameTy::f_lasti(this->builder_, frame);
-+    Value *lasti = this->builder_.CreateLoad(this->lasti_store_);
-+    this->builder_.CreateStore(lasti, f_lasti);
-+
-+    Value *bh =
-+      state_->GetGlobalFunction<int(PyFrameObject*, int)>("_PyJIT_BlackHoleEval");
-+    Value *br =
-+      state_->CreateCall(bh, frame,
-+                         this->builder_.CreateLoad(this->bail_reason_));
-+
-+    lasti =
-+      this->builder_.CreateSub(this->builder_.CreateLoad(f_lasti),
-+                               ConstantInt::getSigned(Type::getInt32Ty(this->context_), 1));
-+    this->builder_.CreateStore(lasti, f_lasti);
-+
-+    Value *ef =
-+      state_->GetGlobalFunction<PyObject*(PyFrameObject*, int)>("PyEval_EvalFrameEx");
-+    Value *er = state_->CreateCall(ef, frame, br);
-+    state_->DecRef(builder_.CreateBitCast(frame,
-+                                          PyTypeBuilder<PyObject*>::get(state_->context())));
-+
-+    this->builder_.CreateStore(er, this->bail_result_);
-+    this->builder_.CreateBr(this->bail_parent_);
-+  }
-+
-+  void
-+  JITFasterFBuilder::SetLastI(int v)
-+  {
-+    this->builder_.CreateStore(
-+      ConstantInt::getSigned(Type::getInt32Ty(this->context_), v),
-+      this->lasti_store_);
-+  }
-+
-+  void
-+  JITFasterFBuilder::SetBailReason(int v)
-+  {
-+    this->builder_.CreateStore(
-+      ConstantInt::getSigned(Type::getInt32Ty(this->context_), v),
-+      this->bail_reason_);
-+  }
-+
-+  void
-+  JITFasterFBuilder::SetBailBlockId(int v)
-+  {
-+    // TODO: Implement Me!
-+  }
-+
-+  void
-+  JITFasterFBuilder::SetBailOpcodeId(int v)
-+  {
-+    // TODO: Implement Me!
-+  }
-+
-+  void
-+  JITFasterFBuilder::CreateBailBr()
-+  {
-+    this->builder_.CreateBr(this->bail_block_);
-+  }
-+
-+  void
-+  JITFasterFBuilder::CreateEntryBr()
-+  {
-+    this->builder_.CreateBr(this->trace_block_);
-+  }
-+
-+  Value *
-+  JITFasterFBuilder::Pop()
-+  {
-+    assert(false);
-+    // May be unneeded
-+    // Value *stack_pointer = this->builder_.CreateLoad(this->stack_pointer_addr_);
-+    // Value *new_stack_pointer = this->builder_.CreateGEP(stack_pointer,
-+    //   ConstantInt::getSigned(Type::getInt32Ty(this->context_), -1));
-+    // Value *former_top = this->builder_.CreateLoad(new_stack_pointer);
-+    // this->builder_.CreateStore(new_stack_pointer, this->stack_pointer_addr_);
-+    // return former_top;
-+
-+    return NULL;
-+  }
-+
-+  void
-+  JITFasterFBuilder::Push(Value *value)
-+  {
-+    Value *frame = this->builder_.CreateLoad(this->bail_frame_);
-+    Value *f_stacktop = FrameTy::f_stacktop(this->builder_, frame);
-+    Value *stack_pointer =
-+        this->builder_.CreateLoad(f_stacktop,
-+                                  "stack_pointer_from_frame");
-+    this->builder_.CreateStore(value, stack_pointer);
-+    Value *new_stack_pointer = this->builder_.CreateGEP(
-+      stack_pointer, ConstantInt::get(Type::getInt32Ty(this->context_), 1));
-+    this->builder_.CreateStore(new_stack_pointer, f_stacktop);
-+  }
-+
-+  void
-+  JITFasterFBuilder::DropLocal(int num, llvm::Value *value)
-+  {
-+    Value *ptr = this->LocalPtr(num);
-+    this->builder_.CreateStore(value, ptr);
-+  }
-+
-+  llvm::Value *
-+  JITFasterFBuilder::TakeLocal(int num)
-+  {
-+    assert(false);
-+    return NULL;
-+  }
-+
-+  llvm::Value *
-+  JITFasterFBuilder::LocalPtr(int arg)
-+  {
-+    Value *frame = this->builder_.CreateLoad(this->bail_frame_);
-+
-+    Value *localsplus = FrameTy::f_localsplus(this->builder_, frame);
-+    Value *fastlocals = this->builder_.CreateStructGEP(localsplus, 0, "fastlocals");
-+    return this->builder_.CreateGEP(fastlocals,
-+      ConstantInt::getSigned(Type::getInt32Ty(this->context_), arg));
-+  }
-+
-+  llvm::Value *
-+  JITFasterFBuilder::ConstPtr(int arg)
-+  {
-+    return this->builder_.CreateGEP(this->consts_,
-+      ConstantInt::getSigned(Type::getInt32Ty(this->context_), arg));
-+  }
-+
-+  void
-+  JITFasterFBuilder::OutputInfo(Value *v)
-+  {
-+    Function *func = this->state_->GetGlobalFunction<void(PyObject*)>("output_info");
-+    this->state_->CreateCall(func, v);
-+  }
-+
-+  void
-+  JITFasterFBuilder::WriteFrameBail(std::vector<JITValue *> &stack, std::vector<JITValue *> &locals)
-+  {
-+    Function *func = this->state_->GetGlobalFunction<PyFrameObject*(PyCodeObject*, PyObject*)>("_PyJIT_CreateFrame");
-+    Value *frame = this->state_->CreateCall(func, code_, globals_);
-+    this->builder_.CreateStore(frame, bail_frame_);
-+    for (size_t i = 0; i < locals.size(); ++i) {
-+      // Avoid writing NULL values, a new frame is clear by default
-+      if (locals[i] != NULL && dyn_cast<JITNullValue>(locals[i]) == NULL)
-+        this->DropLocal(i, locals[i]->getStaticType()->getValue(*this, false, false));
-+    }
-+    for (size_t i = 0; i < stack.size(); ++i) {
-+      this->Push(stack[i]->getStaticType()->getValue(*this, false, false));
-+    }
-+  }
++  // JITFasterFBuilder::JITFasterFBuilder(JITFunctionBuilder &parent,
++  //                                      llvm::BasicBlock *bail_parent,
++  //                                      llvm::Value *bail_result,
++  //                                      llvm::Value *code,
++  //                                      llvm::Value *globals,
++  //                                      llvm::Value *builtins)
++  //   : state_(parent.getState()),
++  //     builder_(state_->builder()),
++  //     context_(state_->context()),
++  //     function_(state_->function()),
++  //     code_(code),
++  //     globals_(globals),
++  //     builtins_(builtins),
++  //     bail_parent_(bail_parent),
++  //     bail_result_(bail_result)
++  // {
++
++  //   // Export entry block
++  //   llvm::BasicBlock *entry = this->state_->CreateBasicBlock("entry_inlined");
++  //   this->builder_.CreateBr(entry);
++  //   this->builder_.SetInsertPoint(entry);
++
++  //   names_ = this->builder_.CreateLoad(CodeTy::co_names(this->builder_, this->code_), "names");
++
++  //   Function *func = this->state_->GetGlobalFunction<PyObject**(PyCodeObject*)>("_PyJIT_GetConstsFromCode");
++  //   consts_ = this->state_->CreateCall(func, this->code_);
++
++  //   this->trace_block_ = this->state_->CreateBasicBlock("trace_block");
++  //   this->builder_.CreateBr(this->trace_block_);
++
++  //   this->CreateBailBlock();
++
++  //   this->builder_.SetInsertPoint(this->trace_block_);
++  //   this->SetBailReason(BH_NO_BLACKHOLE);
++  // }
++
++  // void
++  // JITFasterFBuilder::CreateBailBlock()
++  // {
++  //   this->bail_reason_ =
++  //     this->state_->CreateAllocaInEntryBlock(Type::getInt32Ty(this->context_),
++  //                                            NULL, "bail_reason");
++  //   this->bail_frame_ =
++  //     this->state_->CreateAllocaInEntryBlock(PyTypeBuilder<PyFrameObject*>::get(this->context_),
++  //                                            NULL, "bail_frame");
++  //   this->lasti_store_ =
++  //     this->state_->CreateAllocaInEntryBlock(Type::getInt32Ty(this->context_),
++  //                                            NULL, "lasti");
++
++  //   this->bail_block_ = this->state_->CreateBasicBlock("bail_block");
++  //   this->builder_.SetInsertPoint(this->bail_block_);
++
++  //   Value *frame = this->builder_.CreateLoad(this->bail_frame_);
++
++  //   Value *f_lasti = FrameTy::f_lasti(this->builder_, frame);
++  //   Value *lasti = this->builder_.CreateLoad(this->lasti_store_);
++  //   this->builder_.CreateStore(lasti, f_lasti);
++
++  //   Value *bh =
++  //     state_->GetGlobalFunction<int(PyFrameObject*, int)>("_PyJIT_BlackHoleEval");
++  //   Value *br =
++  //     state_->CreateCall(bh, frame,
++  //                        this->builder_.CreateLoad(this->bail_reason_));
++
++  //   lasti =
++  //     this->builder_.CreateSub(this->builder_.CreateLoad(f_lasti),
++  //                              ConstantInt::getSigned(Type::getInt32Ty(this->context_), 1));
++  //   this->builder_.CreateStore(lasti, f_lasti);
++
++  //   Value *ef =
++  //     state_->GetGlobalFunction<PyObject*(PyFrameObject*, int)>("PyEval_EvalFrameEx");
++  //   Value *er = state_->CreateCall(ef, frame, br);
++  //   state_->DecRef(builder_.CreateBitCast(frame,
++  //                                         PyTypeBuilder<PyObject*>::get(state_->context())));
++
++  //   this->builder_.CreateStore(er, this->bail_result_);
++  //   this->builder_.CreateBr(this->bail_parent_);
++  // }
++
++  // void
++  // JITFasterFBuilder::SetLastI(int v)
++  // {
++  //   this->builder_.CreateStore(
++  //     ConstantInt::getSigned(Type::getInt32Ty(this->context_), v),
++  //     this->lasti_store_);
++  // }
++
++  // void
++  // JITFasterFBuilder::SetBailReason(int v)
++  // {
++  //   this->builder_.CreateStore(
++  //     ConstantInt::getSigned(Type::getInt32Ty(this->context_), v),
++  //     this->bail_reason_);
++  // }
++
++  // void
++  // JITFasterFBuilder::SetBailBlockId(int v)
++  // {
++  //   // TODO: Implement Me!
++  // }
++
++  // void
++  // JITFasterFBuilder::SetBailOpcodeId(int v)
++  // {
++  //   // TODO: Implement Me!
++  // }
++
++  // void
++  // JITFasterFBuilder::CreateBailBr()
++  // {
++  //   this->builder_.CreateBr(this->bail_block_);
++  // }
++
++  // void
++  // JITFasterFBuilder::CreateEntryBr()
++  // {
++  //   this->builder_.CreateBr(this->trace_block_);
++  // }
++
++  // Value *
++  // JITFasterFBuilder::Pop()
++  // {
++  //   assert(false);
++  //   // May be unneeded
++  //   // Value *stack_pointer = this->builder_.CreateLoad(this->stack_pointer_addr_);
++  //   // Value *new_stack_pointer = this->builder_.CreateGEP(stack_pointer,
++  //   //   ConstantInt::getSigned(Type::getInt32Ty(this->context_), -1));
++  //   // Value *former_top = this->builder_.CreateLoad(new_stack_pointer);
++  //   // this->builder_.CreateStore(new_stack_pointer, this->stack_pointer_addr_);
++  //   // return former_top;
++
++  //   return NULL;
++  // }
++
++  // void
++  // JITFasterFBuilder::Push(Value *value)
++  // {
++  //   Value *frame = this->builder_.CreateLoad(this->bail_frame_);
++  //   Value *f_stacktop = FrameTy::f_stacktop(this->builder_, frame);
++  //   Value *stack_pointer =
++  //       this->builder_.CreateLoad(f_stacktop,
++  //                                 "stack_pointer_from_frame");
++  //   this->builder_.CreateStore(value, stack_pointer);
++  //   Value *new_stack_pointer = this->builder_.CreateGEP(
++  //     stack_pointer, ConstantInt::get(Type::getInt32Ty(this->context_), 1));
++  //   this->builder_.CreateStore(new_stack_pointer, f_stacktop);
++  // }
++
++  // void
++  // JITFasterFBuilder::DropLocal(int num, llvm::Value *value)
++  // {
++  //   Value *ptr = this->LocalPtr(num);
++  //   this->builder_.CreateStore(value, ptr);
++  // }
++
++  // llvm::Value *
++  // JITFasterFBuilder::TakeLocal(int num)
++  // {
++  //   assert(false);
++  //   return NULL;
++  // }
++
++  // llvm::Value *
++  // JITFasterFBuilder::LocalPtr(int arg)
++  // {
++  //   Value *frame = this->builder_.CreateLoad(this->bail_frame_);
++
++  //   Value *localsplus = FrameTy::f_localsplus(this->builder_, frame);
++  //   Value *fastlocals = this->builder_.CreateStructGEP(localsplus, 0, "fastlocals");
++  //   return this->builder_.CreateGEP(fastlocals,
++  //     ConstantInt::getSigned(Type::getInt32Ty(this->context_), arg));
++  // }
++
++  // llvm::Value *
++  // JITFasterFBuilder::ConstPtr(int arg)
++  // {
++  //   return this->builder_.CreateGEP(this->consts_,
++  //     ConstantInt::getSigned(Type::getInt32Ty(this->context_), arg));
++  // }
++
++  // void
++  // JITFasterFBuilder::OutputInfo(Value *v)
++  // {
++  //   Function *func = this->state_->GetGlobalFunction<void(PyObject*)>("output_info");
++  //   this->state_->CreateCall(func, v);
++  // }
++
++  // void
++  // JITFasterFBuilder::WriteFrameBail(std::vector<JITValue *> &stack, std::vector<JITValue *> &locals)
++  // {
++  //   Function *func = this->state_->GetGlobalFunction<PyFrameObject*(PyCodeObject*, PyObject*)>("_PyJIT_CreateFrame");
++  //   Value *frame = this->state_->CreateCall(func, code_, globals_);
++  //   this->builder_.CreateStore(frame, bail_frame_);
++  //   for (size_t i = 0; i < locals.size(); ++i) {
++  //     // Avoid writing NULL values, a new frame is clear by default
++  //     if (locals[i] != NULL && dyn_cast<JITNullValue>(locals[i]) == NULL)
++  //       this->DropLocal(i, locals[i]->getStaticType()->getValue(*this, false, false));
++  //   }
++  //   for (size_t i = 0; i < stack.size(); ++i) {
++  //     this->Push(stack[i]->getStaticType()->getValue(*this, false, false));
++  //   }
++  // }
 +
 +
 +  // ############################
 +
-+  JITFrameFBuilder::JITFrameFBuilder(JITFunctionState *state)
++  JITFrameFBuilder::JITFrameFBuilder(JITFunctionState *state, JITBasicFrame *jit_frame)
 +    : state_(state),
 +      builder_(state_->builder()),
 +      context_(state_->context()),
++      jit_frame_(jit_frame),
 +      function_(state_->function())
 +  {
 +    Function::arg_iterator args = this->function_->arg_begin();
 +
 +    this->fastlocals_ = this->builder_.CreateStructGEP(localsplus, 0, "fastlocals");
 +
-+    this->code_ =
-+      this->builder_.CreateLoad(FrameTy::f_code(this->builder_, this->frame_),
-+                                "code_object");
-+
-+    Function *func = this->state_->GetGlobalFunction<PyObject**(PyCodeObject*)>("_PyJIT_GetConstsFromCode");
++    this->code_ = this->builder_.CreateLoad(
++        FrameTy::f_code(this->builder_, this->frame_), "code_object");
++
++    Function *func =
++        this->state_->GetGlobalFunction<PyObject **(PyCodeObject *)>(
++            "_PyJIT_GetConstsFromCode");
 +    this->consts_ = this->state_->CreateCall(func, this->code_);
 +
-+    globals_ = this->builder_.CreateLoad(FrameTy::f_globals(this->builder_, this->frame_), "globals");
-+    builtins_ = this->builder_.CreateLoad(FrameTy::f_builtins(this->builder_, this->frame_), "globals");
++    globals_ = this->builder_.CreateLoad(
++        FrameTy::f_globals(this->builder_, this->frame_), "globals");
++    builtins_ = this->builder_.CreateLoad(
++        FrameTy::f_builtins(this->builder_, this->frame_), "globals");
 +
 +    names_ = this->builder_.CreateLoad(CodeTy::co_names(this->builder_, this->code_), "names");
 +
++    this->load_block_ = this->state_->CreateBasicBlock("load_block");
++    this->builder_.CreateBr(this->load_block_);
++
++    this->builder_.SetInsertPoint(this->load_block_);
 +    this->trace_block_ = this->state_->CreateBasicBlock("trace_block");
-+    this->builder_.CreateBr(this->trace_block_);
++    // This is done after finishing construction of the load block
++    // this->builder_.CreateBr(this->trace_block_);
 +
 +    this->CreateBailBlock();
 +
 +    Value *ptr = this->LocalPtr(num);
 +    Value *local = this->builder_.CreateLoad(ptr);;
 +    this->builder_.CreateStore(this->state_->GetNull<PyObject*>(), ptr);
-+    if (num + 1 > static_cast<int>(shadow_locals_.size())) {
-+      shadow_locals_.resize(num + 1);
-+    }
-+    shadow_locals_[num] = local;
 +    return local;
 +  }
 +
 +        this->DropLocal(i, v);
 +      }
 +    }
-+    for (size_t i = 0; i < shadow_locals_.size(); ++i) {
-+      if ((locals.size() <= i || locals[i] == NULL) && shadow_locals_[i] != NULL) {
-+        this->DropLocal(i, shadow_locals_[i]);
++    auto &shadow_locals = jit_frame_->locals();
++    for (size_t i = 0; i < shadow_locals.size(); ++i) {
++      if ((locals.size() <= i || locals[i] == NULL) && shadow_locals[i].second != NULL) {
++        this->DropLocal(i, shadow_locals[i].second->getStaticType()->getValue(*this, false, false));
 +      }
 +    }
 +    for (size_t i = 0; i < stack.size(); ++i) {
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_fbuilder.h
-@@ -0,0 +1,219 @@
+@@ -0,0 +1,227 @@
 +// -*- C++ -*-
 +#ifndef PYTHON_JIT_FBUILDER_H_
 +#define PYTHON_JIT_FBUILDER_H_
 +namespace jit {
 +
 +  class JITValue;
++  class JITBasicFrame;
 +
 +  class JITFunctionBuilder {
 +  public:
 +    virtual llvm::Value *getNames() = 0;
 +    virtual llvm::Value *getGlobals() = 0;
 +    virtual llvm::Value *getBuiltins() = 0;
++    virtual llvm::BasicBlock *getLoadBB() = 0;
 +
 +    virtual bool isInlined() = 0;
 +  };
 +
-+  class JITFasterFBuilder : public JITFunctionBuilder {
-+    JITFasterFBuilder(const JITFasterFBuilder &);
-+    void operator=(const JITFasterFBuilder &);
++  // class JITFasterFBuilder : public JITFunctionBuilder {
++  //   JITFasterFBuilder(const JITFasterFBuilder &);
++  //   void operator=(const JITFasterFBuilder &);
++
++  // public:
++  //   JITFasterFBuilder(JITFunctionBuilder &parent,
++  //                     llvm::BasicBlock *bail_parent,
++  //                     llvm::Value *bail_result,
++  //                     llvm::Value *code,
++  //                     llvm::Value *globals,
++  //                     llvm::Value *builtins);
++  //   JITFunctionState::BuilderT &builder()
++  //   {
++  //     return builder_;
++  //   }
++  //   JITFunctionState *getState()
++  //   {
++  //     return state_;
++  //   }
++
++  //   llvm::Value *Pop();
++  //   void Push(llvm::Value *value);
++
++  //   llvm::Value *TakeLocal(int num);
++  //   void DropLocal(int num, llvm::Value *value);
++
++  //   void SetLastI(int v);
++  //   void SetBailReason(int v);
++  //   void SetBailBlockId(int v);
++  //   void SetBailOpcodeId(int v);
++  //   void CreateBailBr();
++  //   void CreateEntryBr();
++
++  //   void OutputInfo(llvm::Value *v);
++
++  //   llvm::Value *ConstPtr(int arg);
++
++  //   llvm::Value *getNames()
++  //   {
++  //     return names_;
++  //   }
++  //   llvm::Value *getGlobals()
++  //   {
++  //     return globals_;
++  //   }
++  //   llvm::Value *getBuiltins()
++  //   {
++  //     return builtins_;
++  //   }
++
++  //   bool isInlined()
++  //   {
++  //     return true;
++  //   }
++
++  //   virtual void WriteFrameBail(std::vector<JITValue *> &stack, std::vector<JITValue *> &locals);
++
++  // private:
++  //   llvm::Value *LocalPtr(int arg);
++  //   void CreateBailBlock();
++
++  //   JITFunctionState *state_;
++  //   JITFunctionState::BuilderT &builder_;
++  //   llvm::LLVMContext &context_;
++
++  //   llvm::Function *function_;
++
++  //   llvm::Value *code_;
++  //   llvm::Value *consts_;
++  //   llvm::Value *globals_;
++  //   llvm::Value *builtins_;
++  //   llvm::Value *names_;
++
++  //   llvm::BasicBlock *bail_parent_;
++  //   llvm::Value *bail_result_;
++  //   llvm::Value *lasti_store_;
++  //   llvm::Value *bail_reason_;
++  //   llvm::Value *bail_frame_;
++  //   llvm::BasicBlock *bail_block_;
++
++  //   llvm::BasicBlock *trace_block_;
++  // };
++
++  class JITFrameFBuilder : public JITFunctionBuilder {
++    JITFrameFBuilder(const JITFrameFBuilder &) = delete;
++    void operator=(const JITFrameFBuilder &) = delete;
 +
 +  public:
-+    JITFasterFBuilder(JITFunctionBuilder &parent,
-+                      llvm::BasicBlock *bail_parent,
-+                      llvm::Value *bail_result,
-+                      llvm::Value *code,
-+                      llvm::Value *globals,
-+                      llvm::Value *builtins);
++    JITFrameFBuilder(JITFunctionState *state, JITBasicFrame *jit_frame);
 +    JITFunctionState::BuilderT &builder()
 +    {
 +      return builder_;
 +    {
 +      return builtins_;
 +    }
++    llvm::BasicBlock *getLoadBB()
++    {
++      return load_block_;
++    }
 +
 +    bool isInlined()
 +    {
 +    JITFunctionState::BuilderT &builder_;
 +    llvm::LLVMContext &context_;
 +
-+    llvm::Function *function_;
-+
-+    llvm::Value *code_;
-+    llvm::Value *consts_;
-+    llvm::Value *globals_;
-+    llvm::Value *builtins_;
-+    llvm::Value *names_;
-+
-+    llvm::BasicBlock *bail_parent_;
-+    llvm::Value *bail_result_;
-+    llvm::Value *lasti_store_;
-+    llvm::Value *bail_reason_;
-+    llvm::Value *bail_frame_;
-+    llvm::BasicBlock *bail_block_;
-+
-+    llvm::BasicBlock *trace_block_;
-+  };
-+
-+  class JITFrameFBuilder : public JITFunctionBuilder {
-+    JITFrameFBuilder(const JITFrameFBuilder &);
-+    void operator=(const JITFrameFBuilder &);
-+
-+  public:
-+    JITFrameFBuilder(JITFunctionState *state);
-+    JITFunctionState::BuilderT &builder()
-+    {
-+      return builder_;
-+    }
-+    JITFunctionState *getState()
-+    {
-+      return state_;
-+    }
-+
-+    llvm::Value *Pop();
-+    void Push(llvm::Value *value);
-+
-+    llvm::Value *TakeLocal(int num);
-+    void DropLocal(int num, llvm::Value *value);
-+
-+    void SetLastI(int v);
-+    void SetBailReason(int v);
-+    void SetBailBlockId(int v);
-+    void SetBailOpcodeId(int v);
-+    void CreateBailBr();
-+    void CreateEntryBr();
-+
-+    void OutputInfo(llvm::Value *v);
-+
-+    llvm::Value *ConstPtr(int arg);
-+
-+    llvm::Value *getNames()
-+    {
-+      return names_;
-+    }
-+    llvm::Value *getGlobals()
-+    {
-+      return globals_;
-+    }
-+    llvm::Value *getBuiltins()
-+    {
-+      return builtins_;
-+    }
-+
-+    bool isInlined()
-+    {
-+      return true;
-+    }
-+
-+    virtual void WriteFrameBail(std::vector<JITValue *> &stack, std::vector<JITValue *> &locals);
-+
-+  private:
-+    llvm::Value *LocalPtr(int arg);
-+    void CreateBailBlock();
-+
-+    JITFunctionState *state_;
-+    JITFunctionState::BuilderT &builder_;
-+    llvm::LLVMContext &context_;
++    JITBasicFrame *jit_frame_;
 +
 +    llvm::Function *function_;
 +    llvm::Value *frame_;
 +    llvm::Value *lasti_store_;
 +    llvm::Value *bail_reason_;
 +    llvm::BasicBlock *bail_block_;
-+    std::vector<llvm::Value *> shadow_locals_;
 +
 +    llvm::BasicBlock *trace_block_;
++    llvm::BasicBlock *load_block_;
 +  };
 +
 +}
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_opcode.cc
-@@ -0,0 +1,769 @@
+@@ -0,0 +1,823 @@
 +#include "Python.h"
 +#include "opcode.h"
 +
 +  void
 +  JITBasicFunction::emit(JITFunctionBuilder &fbuilder)
 +  {
++    auto fstate = fbuilder.getState();
++    auto &builder = fbuilder.builder();
++
++    auto ip = builder.saveIP();
++    builder.SetInsertPoint(fbuilder.getLoadBB());
++
 +    for (auto val : loaded_stack_) {
-+      val->emit(fbuilder);
++      val.first->emit(fbuilder);
 +    }
 +    for (auto val : loaded_locals_) {
-+      val->emit(fbuilder);
-+    }
-+
-+    auto fstate = fbuilder.getState();
++      if (val.first != nullptr) {
++        val.first->emit(fbuilder);
++      }
++    }
++
++    fbuilder.CreateEntryBr();
++    builder.restoreIP(ip);
++
 +    for(auto block : blocks_) {
 +      auto bb = fstate->CreateBasicBlock("jit_block");
 +      fstate->block_map().insert(std::make_pair(block, bb));
 +    }
 +
-+    auto &builder = fbuilder.builder();
 +    auto entry_bb = fstate->block_map()[entry_];
 +    builder.CreateBr(entry_bb);
 +
 +  }
 +
 +  void
++  JITBasicFunction::dump()
++  {
++    for (auto value : loaded_locals_) {
++      if (value.first != nullptr) {
++        value.first->dump();
++      }
++    }
++    for (auto value : loaded_stack_) {
++      value.first->dump();
++    }
++    for (auto block : blocks_) {
++      std::cout << "** BLOCK **\n";
++      block->dump();
++    }
++  }
++
++  void
 +  JITStackValue::emit(JITFunctionBuilder &builder)
 +  {
 +    value_ = builder.Pop();
 +  }
 +
 +  void
++  JITPhiNode::emit(JITFunctionBuilder &fbuilder)
++  {
++    JITFunctionState *state = fbuilder.getState();
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++    alloca_ = state->CreateAllocaInEntryBlock(
++        PyTypeBuilder<PyObject *>::get(state->context()), NULL, "jit_phi");
++
++    auto inval = incoming_->getValue(fbuilder);
++    assert(llvm::isa<llvm::Instruction>(inval));
++    auto store = new llvm::StoreInst(inval, alloca_);
++    store->insertAfter(llvm::dyn_cast<llvm::Instruction>(inval));
++
++    this->getStaticType()->init(builder.CreateLoad(alloca_));
++  }
++
++  void
 +  JITForIter::emit(JITFunctionBuilder &fbuilder)
 +  {
 +    JITFunctionState::BuilderT &builder = fbuilder.builder();
 +
 +    builder.SetInsertPoint(trace_cont);
 +
-+    Value *as_tuple =
-+      builder.CreateBitCast(args,
-+                            PyTypeBuilder<PyTupleObject*>::get(state->context()));
-+    Value *items =
-+      builder.CreateBitCast(TupleTy::ob_item(builder, as_tuple),
-+                            PyTypeBuilder<PyObject**>::get(state->context()));
++    Value *as_tuple = builder.CreateBitCast(
++        args, PyTypeBuilder<PyTupleObject *>::get(state->context()));
++    Value *items = builder.CreateBitCast(
++        TupleTy::ob_item(builder, as_tuple),
++        PyTypeBuilder<PyObject **>::get(state->context()));
++
 +    for (size_t i = 0; i < args_.size(); ++i) {
-+      Value *gep =
-+        builder.CreateGEP(items,
-+                          ConstantInt::getSigned(Type::getInt32Ty(state->context()), i));
-+      builder.CreateStore(args_[i]->getValue(fbuilder),
-+                          gep);
-+    }
-+
-+    Value *call = state->GetGlobalFunction<PyObject *(PyObject *, PyObject *, PyObject *)>("PyObject_Call");
-+
-+    Value *res = state->CreateCall(call,
-+                                   func_->getValue(fbuilder),
-+                                   args,
++      Value *gep = builder.CreateGEP(
++          items, ConstantInt::getSigned(Type::getInt32Ty(state->context()), i));
++      builder.CreateStore(args_[i]->getValue(fbuilder), gep);
++    }
++
++    Value *call = state->GetGlobalFunction<
++        PyObject *(PyObject *, PyObject *, PyObject *)>("PyObject_Call");
++
++    Value *res = state->CreateCall(call, func_->getValue(fbuilder), args,
 +                                   state->GetNull<PyObject *>());
 +    state->DecRef(args);
 +    this->getStaticType()->init(res);
 +  void
 +  JITCallFasterFunction::emit(JITFunctionBuilder &fbuilder)
 +  {
-+    JITFunctionState::BuilderT &builder = fbuilder.builder();
-+    JITFunctionState *state = fbuilder.getState();
-+
-+    llvm::BasicBlock *trace_cont = state->CreateBasicBlock("trace_cont");
-+    llvm::BasicBlock *bail = state->CreateBasicBlock("bail");
-+
-+    Value *as_func =
-+      builder.CreateBitCast(func_->getValue(fbuilder),
-+                            PyTypeBuilder<PyFunctionObject*>::get(state->context()));
-+    Value *co = builder.CreateLoad(FunctionTy::func_code(builder, as_func), "code");
-+    Value *as_code =
-+      builder.CreateBitCast(co,
-+                            PyTypeBuilder<PyCodeObject*>::get(state->context()));
-+
-+    Value *code_type = state->EmbedPointer<PyCodeObject*>(code_);
-+
-+    Value *check = builder.CreateICmpEQ(as_code, code_type);
-+    builder.CreateCondBr(check, trace_cont, bail);
-+    builder.SetInsertPoint(trace_cont);
-+    trace_cont = state->CreateBasicBlock("trace_cont");
-+
-+    Value *globals = builder.CreateLoad(FunctionTy::func_globals(builder, as_func),
-+                                        "globals");
-+
-+    // If globals are the same, reuse builtins
-+    check = builder.CreateICmpEQ(globals, fbuilder.getGlobals());
-+    builder.CreateCondBr(check, trace_cont, bail);
-+    builder.SetInsertPoint(trace_cont);
-+    trace_cont = state->CreateBasicBlock("trace_cont");
-+
-+    // Check argdefs ?
-+    // Number of arguments (needed & provided) is fixed here.
-+    // argdefs would not be used.
-+
-+    builder.CreateBr(trace_cont);
-+
-+    builder.SetInsertPoint(bail);
-+    fbuilder.WriteFrameBail(stack_, locals_);
-+    fbuilder.Push(func_->getStaticType()->getValue(fbuilder, false, false));
-+    for (size_t i = 0; i < args_.size(); ++i) {
-+      fbuilder.Push(args_[i]->getStaticType()->getValue(fbuilder, false, false));
-+    }
-+    fbuilder.SetBailReason(BH_NO_BLACKHOLE);
-+    fbuilder.CreateBailBr();
-+
-+    llvm::Value *bail_result =
-+      state->CreateAllocaInEntryBlock(PyTypeBuilder<PyObject*>::get(state->context()),
-+                                      NULL, "");
-+    llvm::BasicBlock *inline_bail = state->CreateBasicBlock("inline_bail");
-+    llvm::BasicBlock *ib_exc = state->CreateBasicBlock("inline_bail_exc");
-+    llvm::BasicBlock *ib_ok = state->CreateBasicBlock("inline_bail_ok");
-+    llvm::BasicBlock *ib_cont = state->CreateBasicBlock("inline_bail_cont");
-+
-+    builder.SetInsertPoint(inline_bail);
-+    fbuilder.WriteFrameBail(stack_, locals_);
-+    llvm::Value *br = builder.CreateLoad(bail_result);
-+    builder.CreateCondBr(state->IsNull(br), ib_exc, ib_ok);
-+
-+    builder.SetInsertPoint(ib_exc);
-+    fbuilder.SetBailReason(BH_EXC_RAISED);
-+    builder.CreateBr(ib_cont);
-+
-+    builder.SetInsertPoint(ib_ok);
-+    fbuilder.Push(br);
-+    fbuilder.SetBailReason(BH_NEXT_OPCODE);
-+    builder.CreateBr(ib_cont);
-+
-+    builder.SetInsertPoint(ib_cont);
-+    fbuilder.CreateBailBr();
-+
-+    builder.SetInsertPoint(trace_cont);
-+    JITFasterFBuilder new_builder(fbuilder, inline_bail, bail_result,
-+                                  as_code,
-+                                  globals, fbuilder.getBuiltins());
-+    function_->emit(new_builder);
++    assert(false);
++    // JITFunctionState::BuilderT &builder = fbuilder.builder();
++    // JITFunctionState *state = fbuilder.getState();
++
++    // llvm::BasicBlock *trace_cont = state->CreateBasicBlock("trace_cont");
++    // llvm::BasicBlock *bail = state->CreateBasicBlock("bail");
++
++    // Value *as_func =
++    //   builder.CreateBitCast(func_->getValue(fbuilder),
++    //                         PyTypeBuilder<PyFunctionObject*>::get(state->context()));
++    // Value *co = builder.CreateLoad(FunctionTy::func_code(builder, as_func), "code");
++    // Value *as_code =
++    //   builder.CreateBitCast(co,
++    //                         PyTypeBuilder<PyCodeObject*>::get(state->context()));
++
++    // Value *code_type = state->EmbedPointer<PyCodeObject*>(code_);
++
++    // Value *check = builder.CreateICmpEQ(as_code, code_type);
++    // builder.CreateCondBr(check, trace_cont, bail);
++    // builder.SetInsertPoint(trace_cont);
++    // trace_cont = state->CreateBasicBlock("trace_cont");
++
++    // Value *globals = builder.CreateLoad(FunctionTy::func_globals(builder, as_func),
++    //                                     "globals");
++
++    // // If globals are the same, reuse builtins
++    // check = builder.CreateICmpEQ(globals, fbuilder.getGlobals());
++    // builder.CreateCondBr(check, trace_cont, bail);
++    // builder.SetInsertPoint(trace_cont);
++    // trace_cont = state->CreateBasicBlock("trace_cont");
++
++    // // Check argdefs ?
++    // // Number of arguments (needed & provided) is fixed here.
++    // // argdefs would not be used.
++
++    // builder.CreateBr(trace_cont);
++
++    // builder.SetInsertPoint(bail);
++    // fbuilder.WriteFrameBail(stack_, locals_);
++    // fbuilder.Push(func_->getStaticType()->getValue(fbuilder, false, false));
++    // for (size_t i = 0; i < args_.size(); ++i) {
++    //   fbuilder.Push(args_[i]->getStaticType()->getValue(fbuilder, false, false));
++    // }
++    // fbuilder.SetBailReason(BH_NO_BLACKHOLE);
++    // fbuilder.CreateBailBr();
++
++    // llvm::Value *bail_result =
++    //   state->CreateAllocaInEntryBlock(PyTypeBuilder<PyObject*>::get(state->context()),
++    //                                   NULL, "");
++    // llvm::BasicBlock *inline_bail = state->CreateBasicBlock("inline_bail");
++    // llvm::BasicBlock *ib_exc = state->CreateBasicBlock("inline_bail_exc");
++    // llvm::BasicBlock *ib_ok = state->CreateBasicBlock("inline_bail_ok");
++    // llvm::BasicBlock *ib_cont = state->CreateBasicBlock("inline_bail_cont");
++
++    // builder.SetInsertPoint(inline_bail);
++    // fbuilder.WriteFrameBail(stack_, locals_);
++    // llvm::Value *br = builder.CreateLoad(bail_result);
++    // builder.CreateCondBr(state->IsNull(br), ib_exc, ib_ok);
++
++    // builder.SetInsertPoint(ib_exc);
++    // fbuilder.SetBailReason(BH_EXC_RAISED);
++    // builder.CreateBr(ib_cont);
++
++    // builder.SetInsertPoint(ib_ok);
++    // fbuilder.Push(br);
++    // fbuilder.SetBailReason(BH_NEXT_OPCODE);
++    // builder.CreateBr(ib_cont);
++
++    // builder.SetInsertPoint(ib_cont);
++    // fbuilder.CreateBailBr();
++
++    // builder.SetInsertPoint(trace_cont);
++    // JITFasterFBuilder new_builder(fbuilder, inline_bail, bail_result,
++    //                               as_code,
++    //                               globals, fbuilder.getBuiltins());
++    // function_->emit(new_builder);
 +  }
 +
 +  void
 +  JITTraceEnd::emit(JITFunctionBuilder &fbuilder)
 +  {
 +    // This is in the trace
-+    for (size_t i = 0; i < locals_.size(); ++i) {
-+      if (locals_[i] != NULL)
-+        fbuilder.DropLocal(i, locals_[i]->getValue(fbuilder));
-+    }
-+
-+    for (size_t i = 0; i < stack_.size(); ++i) {
-+      fbuilder.Push(stack_[i]->getValue(fbuilder));
-+    }
++    // for (size_t i = 0; i < locals_.size(); ++i) {
++    //   if (locals_[i] != NULL)
++    //     fbuilder.DropLocal(i, locals_[i]->getValue(fbuilder));
++    // }
++
++    // for (size_t i = 0; i < stack_.size(); ++i) {
++    //   fbuilder.Push(stack_[i]->getValue(fbuilder));
++    // }
++
++    JITFunctionState::BuilderT &builder = fbuilder.builder();
++
++    for (auto v : phi_locals_) {
++      Value *alloca = v.second->get_alloca();
++      builder.CreateStore(v.first->getValue(fbuilder), alloca);
++    }
++
++    for (auto v : phi_stack_) {
++      Value *alloca = v.second->get_alloca();
++      builder.CreateStore(v.first->getValue(fbuilder), alloca);
++    }
++
 +    fbuilder.CreateEntryBr();
 +  }
 +
 +  const int JITMethodGetFunc::ID = 0;
 +  const int JITCallFasterFunction::ID = 0;
 +  const int JITExtractValue::ID = 0;
++  const int JITPhiNode::ID = 0;
 +
 +  const int JITGenericBinOp::ID = 0;
 +
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_opcode.h
-@@ -0,0 +1,1540 @@
+@@ -0,0 +1,1627 @@
 +// -*- C++ -*-
 +#ifndef PYTHON_JIT_OPCODE_H_
 +#define PYTHON_JIT_OPCODE_H_
 +    return NULL;
 +  }
 +
++  template<class T>
++  bool isa(JITOpcode *v)
++  {
++    AssertSameOrDerivedFrom<T, JITOpcode>();
++    uintptr_t id = reinterpret_cast<uintptr_t>(&(T::ID));
++    return v->type() == id;
++  }
++
 +  class JITBasicBlock {
 +  public:
 +    JITBasicBlock()
 +      }
 +    }
 +
++    void push_front(JITOpcode *opcode)
++    {
++      opcodes_.insert(opcodes_.begin(), opcode);
++    }
++
 +    void push_back(JITOpcode *opcode)
 +    {
 +      opcodes_.push_back(opcode);
 +
 +  class JITBasicFrame {
 +  public:
-+    virtual std::vector<JITStackValue *> &stack() = 0;
-+    virtual std::vector<JITLocalValue *> &locals() = 0;
++    virtual JITBasicBlock *getFrameBlock() = 0;
++    virtual std::vector<std::pair<JITStackValue *, JITPhiNode *> > &stack() = 0;
++    virtual std::vector<std::pair<JITLocalValue *, JITPhiNode *> > &locals() = 0;
 +  };
 +
 +  class JITBasicFunction : public JITBasicFrame {
 +    JITBasicFunction()
 +    {
 +      entry_ = new JITBasicBlock();
++
 +      blocks_.push_back(entry_);
 +    }
++
 +    virtual ~JITBasicFunction()
 +    {
 +      for(auto block : blocks_) {
 +
 +    void emit(JITFunctionBuilder &builder);
 +
-+    void dump()
-+    {
-+      for (auto block : blocks_) {
-+        std::cout << "** BLOCK **\n";
-+        block->dump();
-+      }
-+    }
-+
-+    std::vector<JITStackValue *> &stack()
++    void dump();
++
++    JITBasicBlock *getFrameBlock()
++    {
++      return getEntryBlock();
++    }
++
++    std::vector<std::pair<JITStackValue *, JITPhiNode *> > &stack()
 +    {
 +      return loaded_stack_;
 +    }
 +
-+    std::vector<JITLocalValue *> &locals()
++    std::vector<std::pair<JITLocalValue *, JITPhiNode *> > &locals()
 +    {
 +      return loaded_locals_;
 +    }
 +    JITBasicBlock *entry_;
 +    std::vector<JITBasicBlock *> blocks_;
 +
-+    std::vector<JITLocalValue *> loaded_locals_;
-+    std::vector<JITStackValue *> loaded_stack_;
++    std::vector<std::pair<JITLocalValue *, JITPhiNode *> > loaded_locals_;
++    std::vector<std::pair<JITStackValue *, JITPhiNode *> > loaded_stack_;
 +  };
 +
 +  class JITValue : public JITOpcode {
 +    int blockid_;
 +  };
 +
++  class JITPhiNode : public JITValue {
++  public:
++    JITPhiNode(JITValue *v)
++        : incoming_(v), type_(new JITOpaqueObject), alloca_(nullptr) {
++      incoming_->addUser(this);
++    }
++    ~JITPhiNode() { delete type_; }
++
++    void add_edge(JITValue *v)
++    {
++      edges_.push_back(v);
++    }
++    llvm::Value *get_alloca() const
++    {
++      return alloca_;
++    }
++
++    virtual void dump()
++    {
++      std::cout << "PHI_NODE " << edges_.size() << "\n";
++    }
++
++    virtual void emit(JITFunctionBuilder &fbuilder);
++    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: PHI_NODE\n";
++        }
++      }
++    }
++
++    virtual uintptr_t type()
++    {
++      return reinterpret_cast<uintptr_t>(&ID);
++    }
++    static const int ID;
++
++  private:
++    std::vector<JITValue *> edges_;
++    JITValue *incoming_;
++    JITType *type_;
++
++    llvm::Value *alloca_;
++  };
++
 +  class JITLocalValue : public JITValue {
 +  public:
 +    JITLocalValue(int num)
 +    {
 +    }
 +
++    void push_local(JITValue *v, JITPhiNode *p)
++    {
++      phi_locals_.emplace_back(std::make_pair(v, p));
++    }
++
++    void push_stack(JITValue *v, JITPhiNode *p)
++    {
++      phi_stack_.emplace_back(std::make_pair(v, p));
++    }
++
 +    virtual void dump()
 +    {
 +      std::cout << "TRACE_END\n";
 +  private:
 +    std::vector<JITValue *> stack_;
 +    std::vector<JITValue *> locals_;
++
++    std::vector<std::pair<JITValue *, JITPhiNode *> > phi_locals_;
++    std::vector<std::pair<JITValue *, JITPhiNode *> > phi_stack_;
 +  };
 +
 +  class JITOpBuilder {
 new file mode 100644
 --- /dev/null
 +++ b/JIT/jit_tracer.cc
-@@ -0,0 +1,880 @@
+@@ -0,0 +1,882 @@
 +#include "Python.h"
 +#include "opcode.h"
 +
 +  jit::JITBasicFunction *bfunc = root->analyse();
 +  assert(bfunc != NULL);
 +
++  // bfunc->dump();
++
 +  jit::JITFunctionState state(PyGlobalJITData::Get());
-+  jit::JITFrameFBuilder builder(&state);
++  jit::JITFrameFBuilder builder(&state, bfunc);
 +  bfunc->emit(builder);
 +
 +#ifdef JIT_COMPILE_TIME
 +  assert(bfunc != NULL);
 +
 +  jit::JITFunctionState state(PyGlobalJITData::Get());
-+  jit::JITFrameFBuilder builder(&state);
++  jit::JITFrameFBuilder builder(&state, bfunc);
 +  bfunc->emit(builder);
 +
 +#ifdef JIT_COMPILE_TIME
 +
 +  // *******************************
 +
-+  JITTraceAnalysis::JITTraceAnalysis(JITBasicFunction *func)
-+    : stack_counter_(0),
-+      function_(func),
-+      block_(NULL)
-+  {
-+    block_ = function_->getEntryBlock();
-+  }
-+
-+  JITTraceAnalysis::~JITTraceAnalysis()
-+  {
-+  }
-+
-+  void
-+  JITTraceAnalysis::emit(JITFunctionState &state)
-+  {
-+    JITFrameFBuilder builder(&state);
-+    for (size_t i = 0; i < loaded_stack_.size(); ++i) {
-+      loaded_stack_[i]->emit(builder);
-+    }
-+    for (size_t i = 0; i < loaded_locals_.size(); ++i) {
-+      loaded_locals_[i]->emit(builder);
-+    }
-+
-+    function_->emit(builder);
-+  }
++  // JITTraceAnalysis::JITTraceAnalysis(JITBasicFunction *func)
++  //   : stack_counter_(0),
++  //     function_(func),
++  //     block_(NULL)
++  // {
++  //   block_ = function_->getEntryBlock();
++  // }
++
++  // JITTraceAnalysis::~JITTraceAnalysis()
++  // {
++  // }
++
++  // void
++  // JITTraceAnalysis::emit(JITFunctionState &state)
++  // {
++  //   JITFrameFBuilder builder(&state);
++  //   for (size_t i = 0; i < loaded_stack_.size(); ++i) {
++  //     loaded_stack_[i]->emit(builder);
++  //   }
++  //   for (size_t i = 0; i < loaded_locals_.size(); ++i) {
++  //     loaded_locals_[i]->emit(builder);
++  //   }
++
++  //   function_->emit(builder);
++  // }
 +
 +  // void
 +  // JITTraceAnalysis::createBinaryOp(bool inplace, JITStack &stack, JITLocals &locals, TraceEntry &entry)
 +    JITBasicFunction *analyse();
 +  };
 +
-+  struct JITTraceAnalysis {
-+    typedef std::vector<JITValue *> stack_t;
-+
-+    JITTraceAnalysis(JITBasicFunction *func);
-+    ~JITTraceAnalysis();
-+
-+    JITValue *analyseTrace(PyCodeObject *co,
-+                           JITValue *func,
-+                           std::vector<JITValue *> args,
-+                           std::vector<TraceEntry>::iterator &iter,
-+                           std::vector<TraceEntry>::iterator &end);
-+
-+    JITValue *analyseTrace(std::vector<TraceEntry>::iterator &iter,
-+                           std::vector<TraceEntry>::iterator &end);
-+
-+    JITValue *analyseTrace(JITStack &stack,
-+                           JITLocals &locals,
-+                           std::vector<TraceEntry>::iterator &iter,
-+                           std::vector<TraceEntry>::iterator &end,
-+                           bool inlined);
-+
-+    void swallowTrace(std::vector<TraceEntry>::iterator &iter,
-+                      std::vector<TraceEntry>::iterator &end);
-+
-+    void dump()
-+    {
-+      for (size_t i = 0; i < loaded_stack_.size(); ++i) {
-+        loaded_stack_[i]->dump();
-+      }
-+      function_->dump();
-+    }
-+
-+    void emit(JITFunctionState &state);
-+
-+    void createBinaryOp(bool inplace, JITStack &stack, JITLocals &locals, TraceEntry &entry);
-+
-+    void createCallFunctionOp(JITStack &stack, JITLocals &locals,
-+                              std::vector<TraceEntry>::iterator &iter,
-+                              std::vector<TraceEntry>::iterator &end);
-+
-+    JITCallFunction *createCallFunction(JITValue *func, std::vector<JITValue *> &args,
-+                                        JITStack &stack, JITLocals &locals)
-+    {
-+      JITCallFunction *r = new JITCallFunction(func, args, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITCallFasterFunction *
-+    createCallFasterFunction(JITValue *func, PyCodeObject *code,
-+                             JITBasicFunction *bfunc,
-+                             std::vector<JITValue *> &args,
-+                             JITStack &stack, JITLocals &locals)
-+    {
-+      JITCallFasterFunction *r =
-+        new JITCallFasterFunction(func, code,
-+                                  bfunc, args,
-+                                  stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITMethodGetSelf *
-+    createMethodGetSelf(JITValue *arg)
-+    {
-+      JITMethodGetSelf *r = new JITMethodGetSelf(arg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITMethodGetFunc *
-+    createMethodGetFunc(JITValue *arg)
-+    {
-+      JITMethodGetFunc *r = new JITMethodGetFunc(arg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITExtractValue *
-+    createExtractValue(JITValue *arg, PyTypeObject *pytype=NULL)
-+    {
-+      JITExtractValue *r = new JITExtractValue(arg, pytype);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITOpcodeInfo *createOpcodeInfo(int lasti, JITStack &stack, JITLocals &locals)
-+    {
-+      JITOpcodeInfo *r = new JITOpcodeInfo(-1, lasti, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITForIter *createForIter(JITValue *v)
-+    {
-+      JITForIter *r = new JITForIter(v);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITGenericBinOp *createGenericBinOp(BinaryOpImpl *impl, bool inplace, JITValue *v, JITValue *w)
-+    {
-+      JITGenericBinOp *r = new JITGenericBinOp(impl, inplace, v, w);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITCompareOp *createCompareOp(JITValue *v, JITValue *w, int oparg)
-+    {
-+      JITCompareOp *r = new JITCompareOp(v, w, oparg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
-+    {
-+      JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITGuardTrue *createGuardTrue(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
-+    {
-+      JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITGuardFalse *createGuardFalse(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
-+    {
-+      JITGuardFalse *r = new JITGuardFalse(v, reason, lasti, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITGuardType *createGuardType(JITValue *v, PyTypeObject *type, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
-+    {
-+      JITGuardType *r = new JITGuardType(v, type, reason, lasti, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITLoadConst *createLoadConst(int oparg)
-+    {
-+      JITLoadConst *r = new JITLoadConst(oparg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITLoadGlobal *createLoadGlobal(int oparg)
-+    {
-+      JITLoadGlobal *r = new JITLoadGlobal(oparg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITNullValue *createNullValue()
-+    {
-+      JITNullValue *r = new JITNullValue();
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITLoadAttr *createLoadAttr(JITValue *v, int oparg)
-+    {
-+      JITLoadAttr *r = new JITLoadAttr(v, oparg);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITStoreAttr *createStoreAttr(JITValue *target, JITValue *arg, int oparg,
-+                                  JITStack &stack, JITLocals &locals)
-+    {
-+      JITStoreAttr *r = new JITStoreAttr(target, arg, oparg, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITStoreSubscr *createStoreSubscr(JITValue *v0, JITValue *v1, JITValue *v2,
-+                                      JITStack &stack, JITLocals &locals)
-+    {
-+      JITStoreSubscr *r = new JITStoreSubscr(v0, v1, v2, stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITIncRef *createIncRef(JITValue *v)
-+    {
-+      JITIncRef *r = new JITIncRef(v);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITDecRef *createDecRef(JITValue *v)
-+    {
-+      JITDecRef *r = new JITDecRef(v);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITXDecRef *createXDecRef(JITValue *v)
-+    {
-+      JITXDecRef *r = new JITXDecRef(v);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITTraceEnd *createTraceEnd(JITStack &stack, JITLocals &locals)
-+    {
-+      JITTraceEnd *r = new JITTraceEnd(stack.stack, locals.locals);
-+      block_->push_back(r);
-+      return r;
-+    }
-+
-+    JITBasicBlock *current_block() const
-+    {
-+      return block_;
-+    }
-+
-+    JITBasicFunction *function() const
-+    {
-+      return function_;
-+    }
-+
-+  private:
-+    bool createCallFunctionOp(JITValue *func,
-+                              std::vector<JITValue*> args,
-+                              JITStack &stack, JITLocals &locals,
-+                              std::vector<TraceEntry>::iterator &iter,
-+                              std::vector<TraceEntry>::iterator &end);
-+
-+
-+    std::vector<JITLocalValue *> loaded_locals_;
-+    std::vector<JITStackValue *> loaded_stack_;
-+    int stack_counter_;
-+
-+
-+    JITBasicFunction *function_;
-+    JITBasicBlock *block_;
-+  };
-+
++  // struct JITTraceAnalysis {
++  //   typedef std::vector<JITValue *> stack_t;
++
++  //   JITTraceAnalysis(JITBasicFunction *func);
++  //   ~JITTraceAnalysis();
++
++  //   JITValue *analyseTrace(PyCodeObject *co,
++  //                          JITValue *func,
++  //                          std::vector<JITValue *> args,
++  //                          std::vector<TraceEntry>::iterator &iter,
++  //                          std::vector<TraceEntry>::iterator &end);
++
++  //   JITValue *analyseTrace(std::vector<TraceEntry>::iterator &iter,
++  //                          std::vector<TraceEntry>::iterator &end);
++
++  //   JITValue *analyseTrace(JITStack &stack,
++  //                          JITLocals &locals,
++  //                          std::vector<TraceEntry>::iterator &iter,
++  //                          std::vector<TraceEntry>::iterator &end,
++  //                          bool inlined);
++
++  //   void swallowTrace(std::vector<TraceEntry>::iterator &iter,
++  //                     std::vector<TraceEntry>::iterator &end);
++
++  //   void dump()
++  //   {
++  //     for (size_t i = 0; i < loaded_stack_.size(); ++i) {
++  //       loaded_stack_[i]->dump();
++  //     }
++  //     function_->dump();
++  //   }
++
++  //   void emit(JITFunctionState &state);
++
++  //   void createBinaryOp(bool inplace, JITStack &stack, JITLocals &locals, TraceEntry &entry);
++
++  //   void createCallFunctionOp(JITStack &stack, JITLocals &locals,
++  //                             std::vector<TraceEntry>::iterator &iter,
++  //                             std::vector<TraceEntry>::iterator &end);
++
++  //   JITCallFunction *createCallFunction(JITValue *func, std::vector<JITValue *> &args,
++  //                                       JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITCallFunction *r = new JITCallFunction(func, args, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITCallFasterFunction *
++  //   createCallFasterFunction(JITValue *func, PyCodeObject *code,
++  //                            JITBasicFunction *bfunc,
++  //                            std::vector<JITValue *> &args,
++  //                            JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITCallFasterFunction *r =
++  //       new JITCallFasterFunction(func, code,
++  //                                 bfunc, args,
++  //                                 stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITMethodGetSelf *
++  //   createMethodGetSelf(JITValue *arg)
++  //   {
++  //     JITMethodGetSelf *r = new JITMethodGetSelf(arg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITMethodGetFunc *
++  //   createMethodGetFunc(JITValue *arg)
++  //   {
++  //     JITMethodGetFunc *r = new JITMethodGetFunc(arg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITExtractValue *
++  //   createExtractValue(JITValue *arg, PyTypeObject *pytype=NULL)
++  //   {
++  //     JITExtractValue *r = new JITExtractValue(arg, pytype);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITOpcodeInfo *createOpcodeInfo(int lasti, JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITOpcodeInfo *r = new JITOpcodeInfo(-1, lasti, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITForIter *createForIter(JITValue *v)
++  //   {
++  //     JITForIter *r = new JITForIter(v);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITGenericBinOp *createGenericBinOp(BinaryOpImpl *impl, bool inplace, JITValue *v, JITValue *w)
++  //   {
++  //     JITGenericBinOp *r = new JITGenericBinOp(impl, inplace, v, w);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITCompareOp *createCompareOp(JITValue *v, JITValue *w, int oparg)
++  //   {
++  //     JITCompareOp *r = new JITCompareOp(v, w, oparg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITGuardNull *createGuardNull(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITGuardNull *r = new JITGuardNull(v, reason, lasti, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITGuardTrue *createGuardTrue(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITGuardTrue *r = new JITGuardTrue(v, reason, lasti, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITGuardFalse *createGuardFalse(JITValue *v, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITGuardFalse *r = new JITGuardFalse(v, reason, lasti, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITGuardType *createGuardType(JITValue *v, PyTypeObject *type, BLACKHOLE reason, int lasti, JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITGuardType *r = new JITGuardType(v, type, reason, lasti, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITLoadConst *createLoadConst(int oparg)
++  //   {
++  //     JITLoadConst *r = new JITLoadConst(oparg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITLoadGlobal *createLoadGlobal(int oparg)
++  //   {
++  //     JITLoadGlobal *r = new JITLoadGlobal(oparg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITNullValue *createNullValue()
++  //   {
++  //     JITNullValue *r = new JITNullValue();
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITLoadAttr *createLoadAttr(JITValue *v, int oparg)
++  //   {
++  //     JITLoadAttr *r = new JITLoadAttr(v, oparg);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITStoreAttr *createStoreAttr(JITValue *target, JITValue *arg, int oparg,
++  //                                 JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITStoreAttr *r = new JITStoreAttr(target, arg, oparg, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITStoreSubscr *createStoreSubscr(JITValue *v0, JITValue *v1, JITValue *v2,
++  //                                     JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITStoreSubscr *r = new JITStoreSubscr(v0, v1, v2, stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITIncRef *createIncRef(JITValue *v)
++  //   {
++  //     JITIncRef *r = new JITIncRef(v);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITDecRef *createDecRef(JITValue *v)
++  //   {
++  //     JITDecRef *r = new JITDecRef(v);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITXDecRef *createXDecRef(JITValue *v)
++  //   {
++  //     JITXDecRef *r = new JITXDecRef(v);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITTraceEnd *createTraceEnd(JITStack &stack, JITLocals &locals)
++  //   {
++  //     JITTraceEnd *r = new JITTraceEnd(stack.stack, locals.locals);
++  //     block_->push_back(r);
++  //     return r;
++  //   }
++
++  //   JITBasicBlock *current_block() const
++  //   {
++  //     return block_;
++  //   }
++
++  //   JITBasicFunction *function() const
++  //   {
++  //     return function_;
++  //   }
++
++  // private:
++  //   bool createCallFunctionOp(JITValue *func,
++  //                             std::vector<JITValue*> args,
++  //                             JITStack &stack, JITLocals &locals,
++  //                             std::vector<TraceEntry>::iterator &iter,
++  //                             std::vector<TraceEntry>::iterator &end);
++
++
++  //   std::vector<JITLocalValue *> loaded_locals_;
++  //   std::vector<JITStackValue *> loaded_stack_;
++  //   int stack_counter_;
++
++
++  //   JITBasicFunction *function_;
++  //   JITBasicBlock *block_;
++  // };
++  
 +
 +}
 +