PageRenderTime 365ms CodeModel.GetById 121ms app.highlight 144ms RepoModel.GetById 97ms app.codeStats 0ms

/JIT/opcodes/closure.cc

http://unladen-swallow.googlecode.com/
C++ | 165 lines | 141 code | 18 blank | 6 comment | 2 complexity | 5b8e3ca382da2a84e28b98f24970074d MD5 | raw file
  1#include "Python.h"
  2
  3#include "JIT/opcodes/closure.h"
  4#include "JIT/llvm_fbuilder.h"
  5
  6#include "llvm/BasicBlock.h"
  7#include "llvm/Function.h"
  8#include "llvm/Instructions.h"
  9
 10using llvm::BasicBlock;
 11using llvm::ConstantInt;
 12using llvm::Function;
 13using llvm::Type;
 14using llvm::Value;
 15
 16namespace py {
 17
 18OpcodeClosure::OpcodeClosure(LlvmFunctionBuilder *fbuilder) :
 19    fbuilder_(fbuilder),
 20    state_(fbuilder->state()),
 21    builder_(fbuilder->builder()),
 22    llvm_data_(fbuilder->llvm_data())
 23{
 24}
 25
 26void
 27OpcodeClosure::LOAD_CLOSURE(int freevars_index)
 28{
 29    Value *cell = this->builder_.CreateLoad(
 30        this->builder_.CreateGEP(
 31            this->fbuilder_->freevars(),
 32            ConstantInt::get(Type::getInt32Ty(this->fbuilder_->context()),
 33                             freevars_index)));
 34    this->state_->IncRef(cell);
 35    this->fbuilder_->Push(cell);
 36}
 37
 38void
 39OpcodeClosure::MAKE_CLOSURE(int num_defaults)
 40{
 41    Value *code_object = this->fbuilder_->Pop();
 42    Function *pyfunction_new = this->state_->GetGlobalFunction<
 43        PyObject *(PyObject *, PyObject *)>("PyFunction_New");
 44    Value *func_object = this->state_->CreateCall(
 45        pyfunction_new, code_object, this->fbuilder_->globals(),
 46        "MAKE_CLOSURE_result");
 47    this->state_->DecRef(code_object);
 48    this->fbuilder_->PropagateExceptionOnNull(func_object);
 49    Value *closure = this->fbuilder_->Pop();
 50    Function *pyfunction_setclosure = this->state_->GetGlobalFunction<
 51        int(PyObject *, PyObject *)>("PyFunction_SetClosure");
 52    Value *setclosure_result = this->state_->CreateCall(
 53        pyfunction_setclosure, func_object, closure,
 54        "MAKE_CLOSURE_setclosure_result");
 55    this->state_->DecRef(closure);
 56    this->fbuilder_->PropagateExceptionOnNonZero(setclosure_result);
 57    if (num_defaults > 0) {
 58        // Effectively inline BuildSequenceLiteral and
 59        // PropagateExceptionOnNull so we can DecRef func_object on error.
 60        BasicBlock *failure =
 61            this->state_->CreateBasicBlock("MAKE_CLOSURE_failure");
 62        BasicBlock *success =
 63            this->state_->CreateBasicBlock("MAKE_CLOSURE_success");
 64
 65        Value *tupsize = ConstantInt::get(
 66            PyTypeBuilder<Py_ssize_t>::get(this->fbuilder_->context()),
 67            num_defaults);
 68        Function *pytuple_new = this->state_
 69              ->GetGlobalFunction<PyObject *(Py_ssize_t)>("PyTuple_New");
 70        Value *defaults = this->state_->CreateCall(pytuple_new, tupsize,
 71                                                   "MAKE_CLOSURE_defaults");
 72        this->builder_.CreateCondBr(this->state_->IsNull(defaults),
 73                                    failure, success);
 74
 75        this->builder_.SetInsertPoint(failure);
 76        this->state_->DecRef(func_object);
 77        this->fbuilder_->PropagateException();
 78
 79        this->builder_.SetInsertPoint(success);
 80        // XXX(twouters): do this with a memcpy?
 81        while (--num_defaults >= 0) {
 82            Value *itemslot = this->state_->GetTupleItemSlot(defaults,
 83                                                             num_defaults);
 84            this->builder_.CreateStore(this->fbuilder_->Pop(), itemslot);
 85        }
 86        // End of inlining.
 87        Function *pyfunction_setdefaults = this->state_->GetGlobalFunction<
 88            int(PyObject *, PyObject *)>("PyFunction_SetDefaults");
 89        Value *setdefaults_result = this->state_->CreateCall(
 90            pyfunction_setdefaults, func_object, defaults,
 91            "MAKE_CLOSURE_setdefaults_result");
 92        this->state_->DecRef(defaults);
 93        this->fbuilder_->PropagateExceptionOnNonZero(setdefaults_result);
 94    }
 95    this->fbuilder_->Push(func_object);
 96}
 97
 98void
 99OpcodeClosure::LOAD_DEREF(int index)
100{
101    BasicBlock *failed_load =
102        this->state_->CreateBasicBlock("LOAD_DEREF_failed_load");
103    BasicBlock *unbound_local =
104        this->state_->CreateBasicBlock("LOAD_DEREF_unbound_local");
105    BasicBlock *error =
106        this->state_->CreateBasicBlock("LOAD_DEREF_error");
107    BasicBlock *success =
108        this->state_->CreateBasicBlock("LOAD_DEREF_success");
109
110    Value *cell = this->builder_.CreateLoad(
111        this->builder_.CreateGEP(
112            this->fbuilder_->freevars(),
113            ConstantInt::get(Type::getInt32Ty(this->fbuilder_->context()),
114                             index)));
115    Function *pycell_get = this->state_->GetGlobalFunction<
116        PyObject *(PyObject *)>("PyCell_Get");
117    Value *value = this->state_->CreateCall(
118        pycell_get, cell, "LOAD_DEREF_cell_contents");
119    this->builder_.CreateCondBr(this->state_->IsNull(value),
120                                failed_load, success);
121
122    this->builder_.SetInsertPoint(failed_load);
123    Function *pyerr_occurred =
124        this->state_->GetGlobalFunction<PyObject *()>("PyErr_Occurred");
125    Value *was_err =
126        this->state_->CreateCall(pyerr_occurred, "LOAD_DEREF_err_occurred");
127    this->builder_.CreateCondBr(this->state_->IsNull(was_err),
128                                unbound_local, error);
129
130    this->builder_.SetInsertPoint(unbound_local);
131    Function *do_raise =
132        this->state_->GetGlobalFunction<void(PyFrameObject*, int)>(
133            "_PyEval_RaiseForUnboundFreeVar");
134    this->state_->CreateCall(
135        do_raise, this->fbuilder_->frame(),
136        ConstantInt::get(PyTypeBuilder<int>::get(this->fbuilder_->context()),
137                         index));
138
139    this->fbuilder_->FallThroughTo(error);
140    this->fbuilder_->PropagateException();
141
142    this->builder_.SetInsertPoint(success);
143    this->fbuilder_->Push(value);
144}
145
146void
147OpcodeClosure::STORE_DEREF(int index)
148{
149    Value *value = this->fbuilder_->Pop();
150    Value *cell = this->builder_.CreateLoad(
151        this->builder_.CreateGEP(
152            this->fbuilder_->freevars(),
153            ConstantInt::get(Type::getInt32Ty(this->fbuilder_->context()),
154                             index)));
155    Function *pycell_set = this->state_->GetGlobalFunction<
156        int(PyObject *, PyObject *)>("PyCell_Set");
157    Value *result = this->state_->CreateCall(
158        pycell_set, cell, value, "STORE_DEREF_result");
159    this->state_->DecRef(value);
160    // eval.cc doesn't actually check the return value of this, I guess
161    // we are a little more likely to do things wrong.
162    this->fbuilder_->PropagateExceptionOnNonZero(result);
163}
164
165}