/JIT/opcodes/container.cc

http://unladen-swallow.googlecode.com/ · C++ · 359 lines · 285 code · 52 blank · 22 comment · 21 complexity · 2cdb05c986a5975f2e4930decf1bf8f1 MD5 · raw file

  1. #include "Python.h"
  2. #include "JIT/opcodes/binops.h"
  3. #include "JIT/opcodes/container.h"
  4. #include "JIT/llvm_fbuilder.h"
  5. #include "llvm/BasicBlock.h"
  6. #include "llvm/Function.h"
  7. #include "llvm/Instructions.h"
  8. #include "llvm/Support/ManagedStatic.h"
  9. #include "llvm/Support/raw_ostream.h"
  10. using llvm::BasicBlock;
  11. using llvm::ConstantInt;
  12. using llvm::Function;
  13. using llvm::Type;
  14. using llvm::Value;
  15. using llvm::errs;
  16. #ifdef Py_WITH_INSTRUMENTATION
  17. class ImportNameStats {
  18. public:
  19. ImportNameStats()
  20. : total(0), optimized(0) {
  21. }
  22. ~ImportNameStats() {
  23. errs() << "\nIMPORT_NAME opcodes:\n";
  24. errs() << "Total: " << this->total << "\n";
  25. errs() << "Optimized: " << this->optimized << "\n";
  26. }
  27. // Total number of IMPORT_NAME opcodes compiled.
  28. unsigned total;
  29. // Number of imports successfully optimized.
  30. unsigned optimized;
  31. };
  32. static llvm::ManagedStatic<ImportNameStats> import_name_stats;
  33. #define IMPORT_NAME_INC_STATS(field) import_name_stats->field++
  34. #else
  35. #define IMPORT_NAME_INC_STATS(field)
  36. #endif /* Py_WITH_INSTRUMENTATION */
  37. namespace py {
  38. OpcodeContainer::OpcodeContainer(LlvmFunctionBuilder *fbuilder) :
  39. fbuilder_(fbuilder),
  40. state_(fbuilder->state()),
  41. builder_(fbuilder->builder())
  42. {
  43. }
  44. void
  45. OpcodeContainer::BuildSequenceLiteral(
  46. int size, const char *createname,
  47. Value *(LlvmFunctionState::*getitemslot)(Value*, int))
  48. {
  49. const Type *IntSsizeTy =
  50. PyTypeBuilder<Py_ssize_t>::get(this->fbuilder_->context());
  51. Value *seqsize = ConstantInt::getSigned(IntSsizeTy, size);
  52. Function *create =
  53. this->state_->GetGlobalFunction<PyObject *(Py_ssize_t)>(createname);
  54. Value *seq = this->state_->CreateCall(create, seqsize, "sequence_literal");
  55. this->fbuilder_->PropagateExceptionOnNull(seq);
  56. // XXX(twouters): do this with a memcpy?
  57. while (--size >= 0) {
  58. Value *itemslot = (this->state_->*getitemslot)(seq, size);
  59. this->builder_.CreateStore(this->fbuilder_->Pop(), itemslot);
  60. }
  61. this->fbuilder_->Push(seq);
  62. }
  63. void
  64. OpcodeContainer::BUILD_LIST(int size)
  65. {
  66. this->BuildSequenceLiteral(size, "PyList_New",
  67. &LlvmFunctionState::GetListItemSlot);
  68. }
  69. void
  70. OpcodeContainer::BUILD_TUPLE(int size)
  71. {
  72. this->BuildSequenceLiteral(size, "PyTuple_New",
  73. &LlvmFunctionState::GetTupleItemSlot);
  74. }
  75. void
  76. OpcodeContainer::BUILD_MAP(int size)
  77. {
  78. Value *sizehint = ConstantInt::getSigned(
  79. PyTypeBuilder<Py_ssize_t>::get(this->fbuilder_->context()), size);
  80. Function *create_dict = this->state_->GetGlobalFunction<
  81. PyObject *(Py_ssize_t)>("_PyDict_NewPresized");
  82. Value *result = this->state_->CreateCall(create_dict, sizehint,
  83. "BULD_MAP_result");
  84. this->fbuilder_->PropagateExceptionOnNull(result);
  85. this->fbuilder_->Push(result);
  86. }
  87. void
  88. OpcodeContainer::UNPACK_SEQUENCE(int size)
  89. {
  90. // TODO(twouters): We could do even better by combining this opcode and the
  91. // STORE_* ones that follow into a single block of code circumventing the
  92. // stack altogether. And omitting the horrible external stack munging that
  93. // UnpackIterable does.
  94. Value *iterable = this->fbuilder_->Pop();
  95. Function *unpack_iterable = this->state_->GetGlobalFunction<
  96. int(PyObject *, int, PyObject **)>("_PyLlvm_FastUnpackIterable");
  97. Value *new_stack_pointer = this->builder_.CreateGEP(
  98. this->builder_.CreateLoad(this->fbuilder_->stack_pointer_addr()),
  99. ConstantInt::getSigned(
  100. PyTypeBuilder<Py_ssize_t>::get(this->fbuilder_->context()), size));
  101. this->fbuilder_->llvm_data()->tbaa_stack.MarkInstruction(new_stack_pointer);
  102. Value *result = this->state_->CreateCall(
  103. unpack_iterable, iterable,
  104. ConstantInt::get(
  105. PyTypeBuilder<int>::get(this->fbuilder_->context()), size, true),
  106. // _PyLlvm_FastUnpackIterable really takes the *new* stack pointer as
  107. // an argument, because it builds the result stack in reverse.
  108. new_stack_pointer);
  109. this->state_->DecRef(iterable);
  110. this->fbuilder_->PropagateExceptionOnNonZero(result);
  111. // Not setting the new stackpointer on failure does mean that if
  112. // _PyLlvm_FastUnpackIterable failed after pushing some values onto the
  113. // stack, and it didn't clean up after itself, we lose references. This
  114. // is what eval.cc does as well.
  115. this->builder_.CreateStore(new_stack_pointer,
  116. this->fbuilder_->stack_pointer_addr());
  117. }
  118. #define INT_OBJ_OBJ_OBJ int(PyObject*, PyObject*, PyObject*)
  119. void
  120. OpcodeContainer::STORE_SUBSCR_list_int()
  121. {
  122. BasicBlock *success =
  123. this->state_->CreateBasicBlock("STORE_SUBSCR_success");
  124. BasicBlock *bailpoint =
  125. this->state_->CreateBasicBlock("STORE_SUBSCR_bail");
  126. Value *key = this->fbuilder_->Pop();
  127. Value *obj = this->fbuilder_->Pop();
  128. Value *value = this->fbuilder_->Pop();
  129. Function *setitem =
  130. this->state_->GetGlobalFunction<INT_OBJ_OBJ_OBJ>(
  131. "_PyLlvm_StoreSubscr_List");
  132. Value *result = this->state_->CreateCall(setitem, obj, key, value,
  133. "STORE_SUBSCR_result");
  134. this->builder_.CreateCondBr(this->state_->IsNonZero(result),
  135. bailpoint, success);
  136. this->builder_.SetInsertPoint(bailpoint);
  137. this->fbuilder_->Push(value);
  138. this->fbuilder_->Push(obj);
  139. this->fbuilder_->Push(key);
  140. this->fbuilder_->CreateGuardBailPoint(_PYGUARD_STORE_SUBSCR);
  141. this->builder_.SetInsertPoint(success);
  142. this->state_->DecRef(value);
  143. this->state_->DecRef(obj);
  144. this->state_->DecRef(key);
  145. }
  146. void
  147. OpcodeContainer::STORE_SUBSCR_safe()
  148. {
  149. // Performing obj[key] = val
  150. Value *key = this->fbuilder_->Pop();
  151. Value *obj = this->fbuilder_->Pop();
  152. Value *value = this->fbuilder_->Pop();
  153. Function *setitem =
  154. this->state_->GetGlobalFunction<INT_OBJ_OBJ_OBJ>("PyObject_SetItem");
  155. Value *result = this->state_->CreateCall(setitem, obj, key, value,
  156. "STORE_SUBSCR_result");
  157. this->state_->DecRef(value);
  158. this->state_->DecRef(obj);
  159. this->state_->DecRef(key);
  160. this->fbuilder_->PropagateExceptionOnNonZero(result);
  161. }
  162. #undef INT_OBJ_OBJ_OBJ
  163. void
  164. OpcodeContainer::STORE_SUBSCR()
  165. {
  166. OpcodeBinops::IncStatsTotal();
  167. const PyTypeObject *lhs_type = this->fbuilder_->GetTypeFeedback(0);
  168. const PyTypeObject *rhs_type = this->fbuilder_->GetTypeFeedback(1);
  169. if (lhs_type == &PyList_Type && rhs_type == &PyInt_Type) {
  170. OpcodeBinops::IncStatsOptimized();
  171. this->STORE_SUBSCR_list_int();
  172. return;
  173. }
  174. else {
  175. OpcodeBinops::IncStatsOmitted();
  176. this->STORE_SUBSCR_safe();
  177. return;
  178. }
  179. }
  180. void
  181. OpcodeContainer::DELETE_SUBSCR()
  182. {
  183. Value *key = this->fbuilder_->Pop();
  184. Value *obj = this->fbuilder_->Pop();
  185. Function *delitem = this->state_->GetGlobalFunction<
  186. int(PyObject *, PyObject *)>("PyObject_DelItem");
  187. Value *result = this->state_->CreateCall(delitem, obj, key,
  188. "DELETE_SUBSCR_result");
  189. this->state_->DecRef(obj);
  190. this->state_->DecRef(key);
  191. this->fbuilder_->PropagateExceptionOnNonZero(result);
  192. }
  193. void
  194. OpcodeContainer::LIST_APPEND()
  195. {
  196. Value *item = this->fbuilder_->Pop();
  197. Value *listobj = this->fbuilder_->Pop();
  198. Function *list_append = this->state_->GetGlobalFunction<
  199. int(PyObject *, PyObject *)>("PyList_Append");
  200. Value *result = this->state_->CreateCall(list_append, listobj, item,
  201. "LIST_APPEND_result");
  202. this->state_->DecRef(listobj);
  203. this->state_->DecRef(item);
  204. this->fbuilder_->PropagateExceptionOnNonZero(result);
  205. }
  206. void
  207. OpcodeContainer::STORE_MAP()
  208. {
  209. Value *key = this->fbuilder_->Pop();
  210. Value *value = this->fbuilder_->Pop();
  211. Value *dict = this->fbuilder_->Pop();
  212. this->fbuilder_->Push(dict);
  213. Value *dict_type = this->builder_.CreateLoad(
  214. ObjectTy::ob_type(this->builder_, dict));
  215. Value *is_exact_dict = this->builder_.CreateICmpEQ(
  216. dict_type, this->state_->GetGlobalVariableFor((PyObject*)&PyDict_Type));
  217. this->state_->Assert(is_exact_dict,
  218. "dict argument to STORE_MAP is not exactly a PyDict");
  219. Function *setitem = this->state_->GetGlobalFunction<
  220. int(PyObject *, PyObject *, PyObject *)>("PyDict_SetItem");
  221. Value *result = this->state_->CreateCall(setitem, dict, key, value,
  222. "STORE_MAP_result");
  223. this->state_->DecRef(value);
  224. this->state_->DecRef(key);
  225. this->fbuilder_->PropagateExceptionOnNonZero(result);
  226. }
  227. #define FUNC_TYPE PyObject *(PyObject *, PyObject *, PyObject *)
  228. void
  229. OpcodeContainer::IMPORT_NAME()
  230. {
  231. IMPORT_NAME_INC_STATS(total);
  232. if (this->IMPORT_NAME_fast())
  233. return;
  234. Value *mod_name = this->fbuilder_->Pop();
  235. Value *names = this->fbuilder_->Pop();
  236. Value *level = this->fbuilder_->Pop();
  237. Value *module = this->state_->CreateCall(
  238. this->state_->GetGlobalFunction<FUNC_TYPE>("_PyEval_ImportName"),
  239. level, names, mod_name);
  240. this->state_->DecRef(level);
  241. this->state_->DecRef(names);
  242. this->state_->DecRef(mod_name);
  243. this->fbuilder_->PropagateExceptionOnNull(module);
  244. this->fbuilder_->Push(module);
  245. }
  246. #undef FUNC_TYPE
  247. bool
  248. OpcodeContainer::IMPORT_NAME_fast()
  249. {
  250. PyCodeObject *code = fbuilder_->code_object();
  251. // If we're not already monitoring the builtins dict, monitor it. Normally
  252. // we pick it up from the eval loop, but if it isn't here, then we make a
  253. // guess. If we are wrong, we will bail.
  254. if (code->co_watching == NULL ||
  255. code->co_watching[WATCHING_BUILTINS] == NULL) {
  256. PyObject *builtins = PyThreadState_GET()->interp->builtins;
  257. _PyCode_WatchDict(code, WATCHING_BUILTINS, builtins);
  258. }
  259. const PyRuntimeFeedback *feedback = this->fbuilder_->GetFeedback();
  260. if (feedback == NULL || feedback->ObjectsOverflowed()) {
  261. return false;
  262. }
  263. llvm::SmallVector<PyObject *, 3> objects;
  264. feedback->GetSeenObjectsInto(objects);
  265. if (objects.size() != 1 || !PyModule_Check(objects[0])) {
  266. return false;
  267. }
  268. PyObject *module = objects[0];
  269. // We need to invalidate this function if someone changes sys.modules.
  270. if (code->co_watching[WATCHING_SYS_MODULES] == NULL) {
  271. PyObject *sys_modules = PyImport_GetModuleDict();
  272. if (sys_modules == NULL) {
  273. return false;
  274. }
  275. if (_PyCode_WatchDict(code,
  276. WATCHING_SYS_MODULES,
  277. sys_modules)) {
  278. PyErr_Clear();
  279. return false;
  280. }
  281. fbuilder_->WatchDict(WATCHING_BUILTINS);
  282. fbuilder_->WatchDict(WATCHING_SYS_MODULES);
  283. }
  284. BasicBlock *keep_going =
  285. this->state_->CreateBasicBlock("IMPORT_NAME_keep_going");
  286. BasicBlock *invalid_assumptions =
  287. this->state_->CreateBasicBlock("IMPORT_NAME_invalid_assumptions");
  288. this->builder_.CreateCondBr(this->fbuilder_->GetUseJitCond(),
  289. keep_going,
  290. invalid_assumptions);
  291. /* Our assumptions about the state of sys.modules no longer hold;
  292. bail back to the interpreter. */
  293. this->builder_.SetInsertPoint(invalid_assumptions);
  294. this->fbuilder_->CreateBailPoint(_PYFRAME_FATAL_GUARD_FAIL);
  295. this->builder_.SetInsertPoint(keep_going);
  296. /* TODO(collinwinter): we pop to get rid of the inputs to IMPORT_NAME.
  297. Find a way to omit this work. */
  298. this->state_->DecRef(this->fbuilder_->Pop());
  299. this->state_->DecRef(this->fbuilder_->Pop());
  300. this->state_->DecRef(this->fbuilder_->Pop());
  301. Value *mod = this->state_->GetGlobalVariableFor(module);
  302. this->state_->IncRef(mod);
  303. this->fbuilder_->Push(mod);
  304. IMPORT_NAME_INC_STATS(optimized);
  305. return true;
  306. }
  307. }