/JIT/opcodes/globals.cc

http://unladen-swallow.googlecode.com/ · C++ · 176 lines · 139 code · 24 blank · 13 comment · 8 complexity · e62c0bc7038f313854be5dd95157a809 MD5 · raw file

  1. #include "Python.h"
  2. #include "JIT/opcodes/globals.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::Function;
  9. using llvm::Value;
  10. namespace py {
  11. OpcodeGlobals::OpcodeGlobals(LlvmFunctionBuilder *fbuilder) :
  12. fbuilder_(fbuilder),
  13. state_(fbuilder->state()),
  14. builder_(fbuilder->builder())
  15. {
  16. }
  17. void OpcodeGlobals::LOAD_GLOBAL(int index)
  18. {
  19. // A code object might not have co_watching set if
  20. // a) it was compiled by setting co_optimization, or
  21. // b) we couldn't watch the globals/builtins dicts.
  22. PyObject **watching = this->fbuilder_->code_object()->co_watching;
  23. if (watching && watching[WATCHING_GLOBALS] && watching[WATCHING_BUILTINS])
  24. this->LOAD_GLOBAL_fast(index);
  25. else
  26. this->LOAD_GLOBAL_safe(index);
  27. }
  28. void OpcodeGlobals::LOAD_GLOBAL_fast(int index)
  29. {
  30. PyCodeObject *code = this->fbuilder_->code_object();
  31. assert(code->co_watching != NULL);
  32. assert(code->co_watching[WATCHING_GLOBALS]);
  33. assert(code->co_watching[WATCHING_BUILTINS]);
  34. PyObject *name = PyTuple_GET_ITEM(code->co_names, index);
  35. PyObject *obj = PyDict_GetItem(code->co_watching[WATCHING_GLOBALS], name);
  36. if (obj == NULL) {
  37. obj = PyDict_GetItem(code->co_watching[WATCHING_BUILTINS], name);
  38. if (obj == NULL) {
  39. /* This isn't necessarily an error: it's legal Python
  40. code to refer to globals that aren't yet defined at
  41. compilation time. Is it a bad idea? Almost
  42. certainly. Is it legal? Unfortunatley. */
  43. this->LOAD_GLOBAL_safe(index);
  44. return;
  45. }
  46. }
  47. this->fbuilder_->WatchDict(WATCHING_GLOBALS);
  48. this->fbuilder_->WatchDict(WATCHING_BUILTINS);
  49. BasicBlock *keep_going =
  50. this->state_->CreateBasicBlock("LOAD_GLOBAL_keep_going");
  51. BasicBlock *invalid_assumptions =
  52. this->state_->CreateBasicBlock("LOAD_GLOBAL_invalid_assumptions");
  53. #ifdef WITH_TSC
  54. this->state_->LogTscEvent(LOAD_GLOBAL_ENTER_LLVM);
  55. #endif
  56. this->builder_.CreateCondBr(this->fbuilder_->GetUseJitCond(),
  57. keep_going,
  58. invalid_assumptions);
  59. /* Our assumptions about the state of the globals/builtins no longer hold;
  60. bail back to the interpreter. */
  61. this->builder_.SetInsertPoint(invalid_assumptions);
  62. this->fbuilder_->CreateBailPoint(_PYFRAME_FATAL_GUARD_FAIL);
  63. /* Our assumptions are still valid; encode the result of the lookups as an
  64. immediate in the IR. */
  65. this->builder_.SetInsertPoint(keep_going);
  66. Value *global = this->state_->EmbedPointer<PyObject*>(obj);
  67. this->state_->IncRef(global);
  68. this->fbuilder_->Push(global);
  69. #ifdef WITH_TSC
  70. this->state_->LogTscEvent(LOAD_GLOBAL_EXIT_LLVM);
  71. #endif
  72. }
  73. void OpcodeGlobals::LOAD_GLOBAL_safe(int index)
  74. {
  75. this->fbuilder_->SetOpcodeArguments(0);
  76. BasicBlock *global_missing =
  77. this->state_->CreateBasicBlock("LOAD_GLOBAL_global_missing");
  78. BasicBlock *global_success =
  79. this->state_->CreateBasicBlock("LOAD_GLOBAL_global_success");
  80. BasicBlock *builtin_missing =
  81. this->state_->CreateBasicBlock("LOAD_GLOBAL_builtin_missing");
  82. BasicBlock *builtin_success =
  83. this->state_->CreateBasicBlock("LOAD_GLOBAL_builtin_success");
  84. BasicBlock *done = this->state_->CreateBasicBlock("LOAD_GLOBAL_done");
  85. #ifdef WITH_TSC
  86. this->state_->LogTscEvent(LOAD_GLOBAL_ENTER_LLVM);
  87. #endif
  88. Value *name = this->fbuilder_->LookupName(index);
  89. Function *pydict_getitem = this->state_->GetGlobalFunction<
  90. PyObject *(PyObject *, PyObject *)>("PyDict_GetItem");
  91. Value *global = this->state_->CreateCall(
  92. pydict_getitem, this->fbuilder_->globals(), name, "global_variable");
  93. this->builder_.CreateCondBr(this->state_->IsNull(global),
  94. global_missing, global_success);
  95. this->builder_.SetInsertPoint(global_success);
  96. this->state_->IncRef(global);
  97. this->fbuilder_->SetOpcodeResult(0, global);
  98. this->builder_.CreateBr(done);
  99. this->builder_.SetInsertPoint(global_missing);
  100. // This ignores any exception set by PyDict_GetItem (and similarly
  101. // for the builtins dict below,) but this is what ceval does too.
  102. Value *builtin = this->state_->CreateCall(
  103. pydict_getitem, this->fbuilder_->builtins(), name, "builtin_variable");
  104. this->builder_.CreateCondBr(this->state_->IsNull(builtin),
  105. builtin_missing, builtin_success);
  106. this->builder_.SetInsertPoint(builtin_missing);
  107. Function *do_raise = this->state_->GetGlobalFunction<
  108. void(PyObject *)>("_PyEval_RaiseForGlobalNameError");
  109. this->state_->CreateCall(do_raise, name);
  110. this->fbuilder_->PropagateException();
  111. this->builder_.SetInsertPoint(builtin_success);
  112. this->state_->IncRef(builtin);
  113. this->fbuilder_->SetOpcodeResult(0, builtin);
  114. this->builder_.CreateBr(done);
  115. this->builder_.SetInsertPoint(done);
  116. #ifdef WITH_TSC
  117. this->state_->LogTscEvent(LOAD_GLOBAL_EXIT_LLVM);
  118. #endif
  119. }
  120. void OpcodeGlobals::STORE_GLOBAL(int index)
  121. {
  122. Value *name = this->fbuilder_->LookupName(index);
  123. Value *value = this->fbuilder_->Pop();
  124. Function *pydict_setitem = this->state_->GetGlobalFunction<
  125. int(PyObject *, PyObject *, PyObject *)>("PyDict_SetItem");
  126. Value *result = this->state_->CreateCall(
  127. pydict_setitem, this->fbuilder_->globals(), name, value,
  128. "STORE_GLOBAL_result");
  129. this->state_->DecRef(value);
  130. this->fbuilder_->PropagateExceptionOnNonZero(result);
  131. }
  132. void OpcodeGlobals::DELETE_GLOBAL(int index)
  133. {
  134. BasicBlock *failure =
  135. this->state_->CreateBasicBlock("DELETE_GLOBAL_failure");
  136. BasicBlock *success =
  137. this->state_->CreateBasicBlock("DELETE_GLOBAL_success");
  138. Value *name = this->fbuilder_->LookupName(index);
  139. Function *pydict_setitem = this->state_->GetGlobalFunction<
  140. int(PyObject *, PyObject *)>("PyDict_DelItem");
  141. Value *result = this->state_->CreateCall(
  142. pydict_setitem, this->fbuilder_->globals(), name, "STORE_GLOBAL_result");
  143. this->builder_.CreateCondBr(this->state_->IsNonZero(result),
  144. failure, success);
  145. this->builder_.SetInsertPoint(failure);
  146. Function *do_raise = this->state_->GetGlobalFunction<
  147. void(PyObject *)>("_PyEval_RaiseForGlobalNameError");
  148. this->state_->CreateCall(do_raise, name);
  149. this->fbuilder_->PropagateException();
  150. this->builder_.SetInsertPoint(success);
  151. }
  152. }