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