[unladen-swallow] r1170 committed - Converted the JIT to use absolute stack positions instead of relative ...

1 view
Skip to first unread message

unladen...@googlecode.com

unread,
Aug 15, 2010, 6:03:59 AM8/15/10
to unladen...@googlegroups.com
Revision: 1170
Author: e...@4geeks.de
Date: Sun Aug 15 03:03:27 2010
Log: Converted the JIT to use absolute stack positions instead of relative
Push/Pop-operations. This is the first step towards a fully register based
implementation.

New opcode implementations should no longer use the Push/Pop methods.


http://code.google.com/p/unladen-swallow/source/detail?r=1170

Modified:
/trunk/JIT/PyBytecodeIterator.cc
/trunk/JIT/PyBytecodeIterator.h
/trunk/JIT/llvm_compile.cc
/trunk/JIT/llvm_fbuilder.cc
/trunk/JIT/llvm_fbuilder.h
/trunk/JIT/opcodes/attributes.cc
/trunk/JIT/opcodes/attributes.h
/trunk/JIT/opcodes/binops.cc
/trunk/JIT/opcodes/call.cc
/trunk/JIT/opcodes/cmpops.cc
/trunk/JIT/opcodes/globals.cc
/trunk/Python/compile.c

=======================================
--- /trunk/JIT/PyBytecodeIterator.cc Thu Apr 1 17:29:10 2010
+++ /trunk/JIT/PyBytecodeIterator.cc Sun Aug 15 03:03:27 2010
@@ -16,6 +16,15 @@
// the other fields.
this->Advance();
}
+
+PyBytecodeIterator::PyBytecodeIterator(PyBytecodeIterator &iter, int index)
+ : error_(false),
+ bytecode_str_(iter.bytecode_str_),
+ bytecode_size_(iter.bytecode_size_)
+{
+ this->next_index_ = index;
+ this->Advance();
+}

void
PyBytecodeIterator::Advance()
=======================================
--- /trunk/JIT/PyBytecodeIterator.h Thu Apr 1 17:29:10 2010
+++ /trunk/JIT/PyBytecodeIterator.h Sun Aug 15 03:03:27 2010
@@ -12,6 +12,7 @@
// Initializes the iterator to point to the first opcode in the
// bytecode string.
PyBytecodeIterator(PyObject *bytecode_string);
+ PyBytecodeIterator(PyBytecodeIterator &iter, int index);
// Allow the default copy operations.

int Opcode() const { return this->opcode_; }
=======================================
--- /trunk/JIT/llvm_compile.cc Sun Aug 8 19:48:05 2010
+++ /trunk/JIT/llvm_compile.cc Sun Aug 15 03:03:27 2010
@@ -311,7 +311,6 @@
}
return 0;
}
-

extern "C" _LlvmFunction *
_PyCode_ToLlvmIr(PyCodeObject *code)
@@ -345,6 +344,10 @@
if (-1 == validate_bytecode(code)) {
return NULL;
}
+
+ // This calculates the absolute stack offsets for each opcode.
+ // Must be run after validate_bytecode.
+ fbuilder.UpdateStackInfo();

py::PyBytecodeDispatch dispatch(&fbuilder);
PyBytecodeIterator iter(code->co_code);
=======================================
--- /trunk/JIT/llvm_fbuilder.cc Thu Jul 29 23:33:28 2010
+++ /trunk/JIT/llvm_fbuilder.cc Sun Aug 15 03:03:27 2010
@@ -6,8 +6,9 @@
#include "frameobject.h"

#include "JIT/ConstantMirror.h"
-#include "JIT/global_llvm_data.h"
+#include "JIT/PyBytecodeIterator.h"
#include "JIT/PyTypeBuilder.h"
+#include "JIT/global_llvm_data.h"
#include "Util/EventTimer.h"

#include "llvm/ADT/DenseMap.h"
@@ -55,7 +56,92 @@
#define GET_GLOBAL_VARIABLE(TYPE, VARIABLE) \
state()->GetGlobalVariable<TYPE>(&VARIABLE, #VARIABLE)

+extern "C" {
+ extern int _Py_OpcodeStackEffect(int opcode, int oparg);
+}
+
namespace py {
+
+// find_stack_top fills stack info with the absolute stack levels
+// for each opcode. This takes jumps into account.
+
+static int
+find_stack_top(PyBytecodeIterator iter,
+ int stack_level,
+ std::vector<int>& stack_info)
+{
+ // Stop recursion if stack_info for this block is already set.
+ // Sanity check if both codepaths return the same stack level.
+ if (stack_info[iter.CurIndex()] >= 0) {
+ assert(stack_level == stack_info[iter.CurIndex()]);
+ return 0;
+ }
+
+ for (; !iter.Done() && !iter.Error(); iter.Advance()) {
+ stack_info[iter.CurIndex()] = stack_level;
+ stack_level += _Py_OpcodeStackEffect(iter.Opcode(), iter.Oparg());
+ switch (iter.Opcode()) {
+ case RETURN_VALUE:
+ return 0;
+ case JUMP_IF_FALSE_OR_POP:
+ case JUMP_IF_TRUE_OR_POP:
+ find_stack_top(PyBytecodeIterator(iter, iter.Oparg()),
+ stack_level,
+ stack_info);
+ stack_level -= 1;
+ break;
+ case POP_JUMP_IF_FALSE:
+ case POP_JUMP_IF_TRUE:
+ // Jump abs, cond
+ find_stack_top(PyBytecodeIterator(iter, iter.Oparg()),
+ stack_level,
+ stack_info);
+ break;
+
+ case JUMP_ABSOLUTE:
+ case CONTINUE_LOOP:
+ // Jump abs, always
+ find_stack_top(PyBytecodeIterator(iter, iter.Oparg()),
+ stack_level,
+ stack_info);
+ return 0;
+ break;
+
+ case FOR_ITER:
+ find_stack_top(PyBytecodeIterator(iter,
+ iter.NextIndex() +
iter.Oparg()),
+ stack_level - 2,
+ stack_info);
+ break;
+
+ case SETUP_LOOP:
+ find_stack_top(PyBytecodeIterator(iter,
+ iter.NextIndex() +
iter.Oparg()),
+ stack_level,
+ stack_info);
+ break;
+ case SETUP_EXCEPT:
+ case SETUP_FINALLY:
+ find_stack_top(PyBytecodeIterator(iter,
+ iter.NextIndex() +
iter.Oparg()),
+ stack_level,
+ stack_info);
+ stack_level -= 3;
+ break;
+
+ case JUMP_FORWARD:
+ // Jump rel, always
+ find_stack_top(PyBytecodeIterator(iter,
+ iter.NextIndex() +
iter.Oparg()),
+ stack_level,
+ stack_info);
+ return 0;
+ break;
+
+ }
+ }
+ return 0;
+}

static llvm::StringRef
pystring_to_stringref(const PyObject* str)
@@ -92,6 +178,7 @@
llvm::DIType(),
false, // Not local to unit.
true)), // Is definition.
+ stack_info_(0),
error_(false),
is_generator_(code_object->co_flags & CO_GENERATOR),
uses_delete_fast_(false)
@@ -301,6 +388,15 @@
this->state()->LogTscEvent(CALL_ENTER_LLVM);
#endif
}
+
+void
+LlvmFunctionBuilder::UpdateStackInfo()
+{
+ this->stack_info_
+ .resize(PyString_GET_SIZE(this->code_object_->co_code), -1);
+ PyBytecodeIterator iter(this->code_object_->co_code);
+ find_stack_top(iter, 0, this->stack_info_);
+}

void
LlvmFunctionBuilder::FillPropagateExceptionBlock()
@@ -500,17 +596,17 @@
"_PyLlvm_FastEnterExceptOrFinally"),
exc_info,
block_type);
- this->Push(this->builder_.CreateLoad(
- this->builder_.CreateStructGEP(
- exc_info, PyTypeBuilder<PyExcInfo>::FIELD_TB)));
- this->Push(this->builder_.CreateLoad(
- this->builder_.CreateStructGEP(
- exc_info,
- PyTypeBuilder<PyExcInfo>::FIELD_VAL)));
- this->Push(this->builder_.CreateLoad(
- this->builder_.CreateStructGEP(
- exc_info,
- PyTypeBuilder<PyExcInfo>::FIELD_EXC)));
+ this->PushRel(this->builder_.CreateLoad(
+ this->builder_.CreateStructGEP(
+ exc_info,
PyTypeBuilder<PyExcInfo>::FIELD_TB)));
+ this->PushRel(this->builder_.CreateLoad(
+ this->builder_.CreateStructGEP(
+ exc_info,
+ PyTypeBuilder<PyExcInfo>::FIELD_VAL)));
+ this->PushRel(this->builder_.CreateLoad(
+ this->builder_.CreateStructGEP(
+ exc_info,
+ PyTypeBuilder<PyExcInfo>::FIELD_EXC)));
this->builder_.CreateBr(goto_block_handler);

this->builder_.SetInsertPoint(handle_finally);
@@ -537,7 +633,7 @@
this->builder_.SetInsertPoint(push_pseudo_exception);
Value *none = this->state()->GetGlobalVariableFor(&_Py_NoneStruct);
this->state()->IncRef(none);
- this->Push(none);
+ this->PushRel(none);

llvm::SwitchInst *should_push_retval = this->builder_.CreateSwitch(
unwind_reason, push_no_retval, 2);
@@ -551,12 +647,12 @@
push_retval);

this->builder_.SetInsertPoint(push_retval);
-
this->Push(this->builder_.CreateLoad(this->retval_addr_, "retval"));
+
this->PushRel(this->builder_.CreateLoad(this->retval_addr_, "retval"));
this->builder_.CreateBr(handle_finally_end);

this->builder_.SetInsertPoint(push_no_retval);
this->state()->IncRef(none);
- this->Push(none);
+ this->PushRel(none);

this->FallThroughTo(handle_finally_end);
// END_FINALLY expects to find the unwind reason on the top of
@@ -569,7 +665,7 @@
this->builder_.CreateZExt(unwind_reason,

PyTypeBuilder<long>::get(this->context_)),
"unwind_reason_as_pyint");
- this->Push(unwind_reason_as_pyint);
+ this->PushRel(unwind_reason_as_pyint);

this->FallThroughTo(goto_block_handler);
// Clear the unwind reason while running through the block's
@@ -778,7 +874,7 @@
this->builder_.CreateCondBr(finished_popping, pop_done, pop_block);

this->builder_.SetInsertPoint(pop_block);
- this->state()->XDecRef(this->Pop());
+ this->state()->XDecRef(this->PopRel());
this->builder_.CreateBr(pop_loop);

this->builder_.SetInsertPoint(pop_done);
@@ -878,6 +974,7 @@
LlvmFunctionBuilder::SetLasti(int current_instruction_index)
{
this->f_lasti_ = current_instruction_index;
+ this->stack_top_ = this->stack_info_[current_instruction_index];
}

void
@@ -1066,6 +1163,24 @@
{
Value *stack_pointer =
this->builder_.CreateLoad(this->stack_pointer_addr_);
this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);
+ Value *new_stack_pointer = this->builder_.CreateGEP(
+ stack_pointer, ConstantInt::get(Type::getInt32Ty(this->context_),
1));
+ this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);
+ this->builder_.CreateStore(new_stack_pointer,
this->stack_pointer_addr_);
+
+ Value *from_bottom = this->builder_.CreateGEP(
+ this->stack_bottom_,
+ ConstantInt::get(Type::getInt32Ty(this->context_),
this->stack_top_));
+ this->builder_.CreateStore(value, from_bottom);
+ this->llvm_data_->tbaa_stack.MarkInstruction(from_bottom);
+ ++this->stack_top_;
+}
+
+void
+LlvmFunctionBuilder::PushRel(Value *value)
+{
+ Value *stack_pointer =
this->builder_.CreateLoad(this->stack_pointer_addr_);
+ this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);

this->builder_.CreateStore(value, stack_pointer);
Value *new_stack_pointer = this->builder_.CreateGEP(
@@ -1080,6 +1195,26 @@
{
Value *stack_pointer =
this->builder_.CreateLoad(this->stack_pointer_addr_);
this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);
+ Value *new_stack_pointer = this->builder_.CreateGEP(
+ stack_pointer,
ConstantInt::getSigned(Type::getInt32Ty(this->context_),
+ -1));
+ this->llvm_data_->tbaa_stack.MarkInstruction(new_stack_pointer);
+ this->builder_.CreateStore(new_stack_pointer,
this->stack_pointer_addr_);
+
+ --this->stack_top_;
+ Value *from_bottom = this->builder_.CreateGEP(
+ this->stack_bottom_,
+ ConstantInt::get(Type::getInt32Ty(this->context_),
this->stack_top_));
+
+ Value *former_top = this->builder_.CreateLoad(from_bottom);
+ return former_top;
+}
+
+Value *
+LlvmFunctionBuilder::PopRel()
+{
+ Value *stack_pointer =
this->builder_.CreateLoad(this->stack_pointer_addr_);
+ this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);

Value *new_stack_pointer = this->builder_.CreateGEP(
stack_pointer,
ConstantInt::getSigned(Type::getInt32Ty(this->context_),
@@ -1102,6 +1237,81 @@

PyTypeBuilder<int>::get(this->context_),
"stack_level");
}
+
+void
+LlvmFunctionBuilder::SetOpcodeArguments(int amount)
+{
+ if (amount > 0) {
+ this->stack_top_ -= amount;
+
+ Value *stack_pointer =
+ this->builder_.CreateLoad(this->stack_pointer_addr_);
+ this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);
+
+ Value *new_stack_pointer = this->builder_.CreateGEP(
+ stack_pointer,
+ ConstantInt::getSigned(Type::getInt32Ty(this->context_),
+ -amount));
+ this->llvm_data_->tbaa_stack.MarkInstruction(new_stack_pointer);
+ this->builder_.CreateStore(new_stack_pointer,
+ this->stack_pointer_addr_);
+ }
+}
+
+void
+LlvmFunctionBuilder::SetOpcodeArgsWithGuard(int amount)
+{
+ this->stack_top_ -= amount;
+}
+
+void
+LlvmFunctionBuilder::BeginOpcodeImpl()
+{
+ Value *from_bottom = this->builder_.CreateGEP(
+ this->stack_bottom_,
+ ConstantInt::get(Type::getInt32Ty(this->context_),
+ this->stack_top_));
+ this->llvm_data_->tbaa_stack.MarkInstruction(from_bottom);
+ this->builder_.CreateStore(from_bottom,
+ this->stack_pointer_addr_);
+}
+
+Value *
+LlvmFunctionBuilder::GetOpcodeArg(int i)
+{
+ Value *from_bottom = this->builder_.CreateGEP(
+ this->stack_bottom_,
+ ConstantInt::get(Type::getInt32Ty(this->context_),
+ this->stack_top_ + i));
+ this->llvm_data_->tbaa_stack.MarkInstruction(from_bottom);
+ return this->builder_.CreateLoad(from_bottom);
+}
+
+void
+LlvmFunctionBuilder::SetOpcodeResult(int i, llvm::Value *value)
+{
+ Value *stack_pointer =
this->builder_.CreateLoad(this->stack_pointer_addr_);
+ this->llvm_data_->tbaa_stack.MarkInstruction(stack_pointer);
+
+ Value *new_stack_pointer = this->builder_.CreateGEP(
+ stack_pointer,
ConstantInt::getSigned(Type::getInt32Ty(this->context_),
+ 1));
+ this->llvm_data_->tbaa_stack.MarkInstruction(new_stack_pointer);
+ this->builder_.CreateStore(new_stack_pointer,
this->stack_pointer_addr_);
+
+ Value *from_bottom = this->builder_.CreateGEP(
+ this->stack_bottom_,
+ ConstantInt::get(Type::getInt32Ty(this->context_),
+ this->stack_top_ + i));
+ this->builder_.CreateStore(value, from_bottom);
+ this->llvm_data_->tbaa_stack.MarkInstruction(from_bottom);
+}
+
+void
+LlvmFunctionBuilder::FinishOpcodeImpl(int i)
+{
+ this->stack_top_ += i;
+}

void
LlvmFunctionBuilder::CheckPyTicker(BasicBlock *next_block)
=======================================
--- /trunk/JIT/llvm_fbuilder.h Sun Aug 8 19:48:05 2010
+++ /trunk/JIT/llvm_fbuilder.h Sun Aug 15 03:03:27 2010
@@ -81,7 +81,8 @@
llvm::Value *f_lasti_addr() const { return this->f_lasti_addr_; }

llvm::Value *stack_bottom() const { return this->stack_bottom_; }
-
+ int stack_top() const { return this->stack_top_; }
+
llvm::Value *freevars() const { return this->freevars_; }
llvm::Value *frame() const { return this->frame_; }
llvm::Value *globals() const { return this->globals_; }
@@ -92,6 +93,7 @@

llvm::Value *GetLocal(int i) const { return this->locals_[i]; }

+ void UpdateStackInfo();
bool Error() { return this->error_; }

/// Sets the current instruction index. This is only put into the
@@ -134,9 +136,42 @@
/// Push() consumes a reference and gives ownership of it to the
/// new value on the stack, and Pop() returns a pointer that owns
/// a reference (which it got from the stack).
+ /// Push/Pop are legacy methods to provide compatibility to existing
+ /// opcode implementations. They should not be used any more.
+ /// You must call Push only once per argument and Pop only once
+ /// per result.
void Push(llvm::Value *value);
llvm::Value *Pop();

+ /// Set the number of arguments the next opcode uses.
+ /// This serves as a baseline for reading/writing to the stack.
+ /// It also resets the stack pointer to it's base value.
+ void SetOpcodeArguments(int amount);
+
+ /// Sets the number of arguments the next opcode uses.
+ /// Use this when the opcode needs to implement guards.
+ /// GetOpcodeArg can be used as usual. Call BeginOpcodeImpl
+ /// if the guard was successfully passed.
+ void SetOpcodeArgsWithGuard(int amount);
+ /// Changes the stack pointer after a successfully passed guard.
+ void BeginOpcodeImpl();
+ /// Retrieve an opcode argument. Must be called after
SetOpcodeArguments.
+ /// Can be called unlimited.
+ /// Increasing the argument reads in the direction of stack growth.
+ llvm::Value *GetOpcodeArg(int i);
+ /// Sets the result of an opcode. Must be called after
SetOpcodeArguments.
+ /// Must only be called once per result per IR-codepath.
+ void SetOpcodeResult(int i, llvm::Value *value);
+
+ /// Normally it is not needed to specify the number of result values an
+ /// opcode produces, as the stack top will be set to the correct value
+ /// at the beginning of each opcode
+ /// If you want to use SetOpcodeArguments/SetOpocodeArgsWithGuard twice
+ /// in one opcode (e.g. to split the opcode in to sub-implementations)
+ /// call FinishOpcodeImpl with the number of results from the previous
+ /// opcode.
+ void FinishOpcodeImpl(int amount);
+
/// Takes a target stack pointer and pops values off the stack
/// until it gets there, decref'ing as it goes.
void PopAndDecrefTo(llvm::Value *target_stack_pointer);
@@ -280,6 +315,11 @@
void AddYieldResumeBB(llvm::ConstantInt *number, llvm::BasicBlock
*block);

private:
+ // Stack pointer relative push and pop methods are for internal
+ // use only.
+ void PushRel(llvm::Value *value);
+ llvm::Value *PopRel();
+
LlvmFunctionState *state_;
PyGlobalLlvmData *const llvm_data_;
// The code object is used for looking up peripheral information
@@ -364,6 +404,10 @@
// method calls, like this: f.foo(b.bar()).
std::vector<bool> loads_optimized_;

+ // Stores information about the stack top for every opcode
+ std::vector<int> stack_info_;
+ int stack_top_;
+
// True if something went wrong and we need to stop compilation without
// aborting the process. If this is true, a Python error has already
// been set.
=======================================
--- /trunk/JIT/opcodes/attributes.cc Sun Aug 8 19:48:05 2010
+++ /trunk/JIT/opcodes/attributes.cc Sun Aug 15 03:03:27 2010
@@ -129,14 +129,15 @@
OpcodeAttributes::LOAD_ATTR_safe(int names_index)
{
Value *attr = this->fbuilder_->LookupName(names_index);
- Value *obj = this->fbuilder_->Pop();
+ this->fbuilder_->SetOpcodeArguments(1);
+ Value *obj = this->fbuilder_->GetOpcodeArg(0);
Function *pyobj_getattr = this->state_->GetGlobalFunction<
PyObject *(PyObject *, PyObject *)>("PyObject_GetAttr");
Value *result = this->state_->CreateCall(
pyobj_getattr, obj, attr, "LOAD_ATTR_result");
this->state_->DecRef(obj);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);
}

bool
@@ -152,14 +153,17 @@
}
ACCESS_ATTR_INC_STATS(optimized_loads);

+ this->fbuilder_->SetOpcodeArgsWithGuard(1);
+
// Emit the appropriate guards.
- Value *obj_v = this->fbuilder_->Pop();
+ Value *obj_v = this->fbuilder_->GetOpcodeArg(0);
BasicBlock *do_load =
this->state_->CreateBasicBlock("LOAD_ATTR_do_load");
accessor.GuardAttributeAccess(obj_v, do_load);

// Call the inline function that deals with the lookup. LLVM
propagates
// these constant arguments through the body of the function.
this->builder_.SetInsertPoint(do_load);
+ this->fbuilder_->BeginOpcodeImpl();
PyConstantMirror &mirror = llvm_data_->constant_mirror();
Value *descr_get_v = mirror.GetGlobalForFunctionPointer<descrgetfunc>(
(void*)accessor.descr_get_, "");
@@ -182,7 +186,7 @@
// Put the result on the stack and possibly propagate an exception.
this->state_->DecRef(obj_v);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);
return true;
}

@@ -223,8 +227,11 @@
}
ACCESS_ATTR_INC_STATS(optimized_stores);

+ this->fbuilder_->SetOpcodeArgsWithGuard(2);
+
// Emit appropriate guards.
- Value *obj_v = this->fbuilder_->Pop();
+ Value *val_v = this->fbuilder_->GetOpcodeArg(0);
+ Value *obj_v = this->fbuilder_->GetOpcodeArg(1);
BasicBlock *do_store =
this->state_->CreateBasicBlock("STORE_ATTR_do_store");
accessor.GuardAttributeAccess(obj_v, do_store);
@@ -232,7 +239,7 @@
// Call the inline function that deals with the lookup. LLVM
propagates
// these constant arguments through the body of the function.
this->builder_.SetInsertPoint(do_store);
- Value *val_v = this->fbuilder_->Pop();
+ this->fbuilder_->BeginOpcodeImpl();
PyConstantMirror &mirror = llvm_data_->constant_mirror();
Value *descr_set_v = mirror.GetGlobalForFunctionPointer<descrsetfunc>(
(void*)accessor.descr_set_, "");
@@ -286,9 +293,13 @@
// No data, conflicting data, or we couldn't do the optimization.
Emit
// the unoptimized, safe code.
this->LOAD_ATTR(names_index);
- Value *attr = this->fbuilder_->Pop();
- this->fbuilder_->Push(this->state_->GetNull<PyObject*>());
- this->fbuilder_->Push(attr);
+ // Use a sub-opcode to insert the padding.
+ this->fbuilder_->FinishOpcodeImpl(1);
+ this->fbuilder_->SetOpcodeArguments(1);
+ Value *attr = this->fbuilder_->GetOpcodeArg(0);
+ this->fbuilder_->SetOpcodeResult(0,
+
this->state_->GetNull<PyObject*>());
+ this->fbuilder_->SetOpcodeResult(1, attr);
} else {
// We currently count LOAD_METHODs as attribute loads. LOAD_ATTR
will
// automatically count the opcode, but we won't call it if we took
the
@@ -312,9 +323,10 @@

METHOD_INC_STATS(unknown);

+ this->fbuilder_->SetOpcodeArgsWithGuard(1);
// Call the inline function that deals with the lookup. LLVM
propagates
// these constant arguments through the body of the function.
- Value *obj_v = this->fbuilder_->Pop();
+ Value *obj_v = this->fbuilder_->GetOpcodeArg(0);
Value *name_v = this->state_->EmbedPointer<PyObject*>(name);
Value *getattr_func = this->state_->GetGlobalFunction<
PyObject *(PyObject *obj, PyObject *name)>(
@@ -331,14 +343,14 @@

// Fill in the bail bb.
this->builder_.SetInsertPoint(bail_block);
- this->fbuilder_->Push(obj_v);
this->fbuilder_->CreateGuardBailPoint(_PYGUARD_LOAD_METHOD);

// Put the method and self on the stack. We bail instead of raising
// exceptions.
this->builder_.SetInsertPoint(push_result);
- this->fbuilder_->Push(method);
- this->fbuilder_->Push(obj_v);
+ this->fbuilder_->BeginOpcodeImpl();
+ this->fbuilder_->SetOpcodeResult(0, method);
+ this->fbuilder_->SetOpcodeResult(1, obj_v);
return true;
}

@@ -366,8 +378,10 @@
METHOD_INC_STATS(known);
ACCESS_ATTR_INC_STATS(optimized_loads);

+ this->fbuilder_->SetOpcodeArgsWithGuard(1);
+
// Emit the appropriate guards.
- Value *obj_v = this->fbuilder_->Pop();
+ Value *obj_v = this->fbuilder_->GetOpcodeArg(0);
BasicBlock *do_load = state_->CreateBasicBlock("LOAD_METHOD_do_load");
accessor.GuardAttributeAccess(obj_v, do_load);

@@ -396,8 +410,9 @@
// Put the method and self on the stack. We bail instead of raising
// exceptions.
this->builder_.SetInsertPoint(push_result);
- this->fbuilder_->Push(method_v);
- this->fbuilder_->Push(obj_v);
+ this->fbuilder_->BeginOpcodeImpl();
+ this->fbuilder_->SetOpcodeResult(0, method_v);
+ this->fbuilder_->SetOpcodeResult(1, obj_v);
return true;
}

@@ -511,8 +526,7 @@
}

void
-AttributeAccessor::GuardAttributeAccess(
- Value *obj_v, BasicBlock *do_access)
+AttributeAccessor::GuardAttributeAccess(Value *obj_v, BasicBlock
*do_access)
{
LlvmFunctionBuilder *fbuilder = this->fbuilder_;
BuilderT &builder = this->fbuilder_->builder();
@@ -561,7 +575,6 @@

// Fill in the bail bb.
builder.SetInsertPoint(bail_block);
- fbuilder->Push(obj_v);
fbuilder->CreateGuardBailPoint(_PYGUARD_ATTR);
}

=======================================
--- /trunk/JIT/opcodes/attributes.h Sun Aug 8 19:48:05 2010
+++ /trunk/JIT/opcodes/attributes.h Sun Aug 15 03:03:27 2010
@@ -67,8 +67,7 @@

// This helper method emits the common type guards for an optimized
// LOAD_ATTR or STORE_ATTR.
- void GuardAttributeAccess(llvm::Value *obj_v,
- llvm::BasicBlock *do_access);
+ void GuardAttributeAccess(llvm::Value *obj_v, llvm::BasicBlock
*do_access);

LlvmFunctionBuilder *fbuilder_;
AttrAccessKind access_kind_;
=======================================
--- /trunk/JIT/opcodes/binops.cc Wed Jul 28 23:50:04 2010
+++ /trunk/JIT/opcodes/binops.cc Sun Aug 15 03:03:27 2010
@@ -95,13 +95,15 @@
return;
}
}
+
+ this->fbuilder_->SetOpcodeArgsWithGuard(2);

BINOP_INC_STATS(optimized);
BasicBlock *success =
this->state_->CreateBasicBlock("BINOP_OPT_success");
BasicBlock *bailpoint =
this->state_->CreateBasicBlock("BINOP_OPT_bail");

- Value *rhs = this->fbuilder_->Pop();
- Value *lhs = this->fbuilder_->Pop();
+ Value *lhs = this->fbuilder_->GetOpcodeArg(0);
+ Value *rhs = this->fbuilder_->GetOpcodeArg(1);

// This strategy of bailing may duplicate the work (once in the inlined
// version, once again in the eval loop). This is generally (in a
Halting
@@ -115,14 +117,13 @@
bailpoint, success);

this->fbuilder_->builder().SetInsertPoint(bailpoint);
- this->fbuilder_->Push(lhs);
- this->fbuilder_->Push(rhs);
this->fbuilder_->CreateGuardBailPoint(_PYGUARD_BINOP);

this->fbuilder_->builder().SetInsertPoint(success);
+ this->fbuilder_->BeginOpcodeImpl();
this->state_->DecRef(lhs);
this->state_->DecRef(rhs);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);
}

#define BINOP_METH(OPCODE, APIFUNC) \
=======================================
--- /trunk/JIT/opcodes/call.cc Sun Aug 8 19:48:05 2010
+++ /trunk/JIT/opcodes/call.cc Sun Aug 15 03:03:27 2010
@@ -302,16 +302,9 @@
this->state_->XDecRef(args[i]);
}

- // Adjust the stack pointer to pop the function and its arguments.
- Value *new_stack_pointer = this->builder_.CreateGEP(
- stack_pointer,
- ConstantInt::getSigned(
- Type::getInt64Ty(this->fbuilder_->context()),
- -num_args - 1));
- this->builder_.CreateStore(new_stack_pointer,
- this->fbuilder_->stack_pointer_addr());
+ this->fbuilder_->SetOpcodeArguments(num_args + 1);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);

// Check signals and maybe switch threads after each function call.
this->fbuilder_->CheckPyTicker();
@@ -327,8 +320,9 @@
const char *function_name)
{
BasicBlock *success =
this->state_->CreateBasicBlock("BUILTIN_LEN_success");
-
- Value *obj = this->fbuilder_->Pop();
+ this->fbuilder_->SetOpcodeArguments(2);
+
+ Value *obj = this->fbuilder_->GetOpcodeArg(1);
Function *builtin_len =
this->state_->GetGlobalFunction<PyObject *(PyObject
*)>(function_name);

@@ -341,15 +335,7 @@
this->state_->DecRef(actual_func);
this->state_->DecRef(obj);

- Value *new_stack_pointer = this->builder_.CreateGEP(
- stack_pointer,
- ConstantInt::getSigned(
- Type::getInt64Ty(this->fbuilder_->context()),
- -2)); // -1 for the function, -1 for the argument.
- this->builder_.CreateStore(new_stack_pointer,
- this->fbuilder_->stack_pointer_addr());
-
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);

// Check signals and maybe switch threads after each function call.
this->fbuilder_->CheckPyTicker();
@@ -377,14 +363,10 @@

ConstantInt::get(PyTypeBuilder<int>::get(this->fbuilder_->context()),
num_kwargs),
"CALL_FUNCTION_result");
- Value *new_stack_pointer = this->builder_.CreateGEP(
- stack_pointer,
-
ConstantInt::getSigned(Type::getInt64Ty(this->fbuilder_->context()),
- -num_args - 2*num_kwargs - 1));
- this->builder_.CreateStore(new_stack_pointer,
- this->fbuilder_->stack_pointer_addr());
+
+ this->fbuilder_->SetOpcodeArguments(num_args + 2*num_kwargs + 1);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);

// Check signals and maybe switch threads after each function call.
this->fbuilder_->CheckPyTicker();
@@ -455,11 +437,16 @@
this->CALL_FUNCTION(oparg);

if (!load_optimized) {
+ // Use a sub-opcode to remove the padding.
+ this->fbuilder_->FinishOpcodeImpl(1);
+
// Pop off the padding cell.
- Value *result = fbuilder_->Pop();
- Value *padding = fbuilder_->Pop();
- state_->Assert(state_->IsNull(padding), "Padding was non-NULL!");
- fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeArguments(2);
+ Value *result = this->fbuilder_->GetOpcodeArg(1);
+ Value *padding = this->fbuilder_->GetOpcodeArg(0);
+ this->state_->Assert(this->state_->IsNull(padding),
+ "Padding was non-NULL!");
+ this->fbuilder_->SetOpcodeResult(0, result);
}
}

@@ -498,14 +485,9 @@
if (call_flag & CALL_FLAG_KW) {
++stack_items;
}
- Value *new_stack_pointer = this->builder_.CreateGEP(
- stack_pointer,
-
ConstantInt::getSigned(Type::getInt64Ty(this->fbuilder_->context()),
- -stack_items));
- this->builder_.CreateStore(new_stack_pointer,
- this->fbuilder_->stack_pointer_addr());
+ this->fbuilder_->SetOpcodeArguments(stack_items);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);

// Check signals and maybe switch threads after each function call.
this->fbuilder_->CheckPyTicker();
=======================================
--- /trunk/JIT/opcodes/cmpops.cc Wed Jul 28 23:50:04 2010
+++ /trunk/JIT/opcodes/cmpops.cc Sun Aug 15 03:03:27 2010
@@ -85,8 +85,10 @@
BasicBlock *success =
this->state_->CreateBasicBlock("CMPOP_OPT_success");
BasicBlock *bailpoint =
this->state_->CreateBasicBlock("CMPOP_OPT_bail");

- Value *rhs = this->fbuilder_->Pop();
- Value *lhs = this->fbuilder_->Pop();
+ this->fbuilder_->SetOpcodeArgsWithGuard(2);
+
+ Value *lhs = this->fbuilder_->GetOpcodeArg(0);
+ Value *rhs = this->fbuilder_->GetOpcodeArg(1);

Function *op =
this->state_->GetGlobalFunction<PyObject*(PyObject*,
PyObject*)>(name);
@@ -95,14 +97,13 @@
bailpoint, success);

this->builder_.SetInsertPoint(bailpoint);
- this->fbuilder_->Push(lhs);
- this->fbuilder_->Push(rhs);
this->fbuilder_->CreateBailPoint(_PYFRAME_GUARD_FAIL);

this->builder_.SetInsertPoint(success);
+ this->fbuilder_->BeginOpcodeImpl();
this->state_->DecRef(lhs);
this->state_->DecRef(rhs);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);
return true;
}

@@ -129,8 +130,10 @@
void
OpcodeCmpops::COMPARE_OP_safe(int cmp_op)
{
- Value *rhs = this->fbuilder_->Pop();
- Value *lhs = this->fbuilder_->Pop();
+ this->fbuilder_->SetOpcodeArguments(2);
+
+ Value *lhs = this->fbuilder_->GetOpcodeArg(0);
+ Value *rhs = this->fbuilder_->GetOpcodeArg(1);
Value *result;
switch (cmp_op) {
case PyCmp_IS:
@@ -179,7 +182,7 @@
this->state_->GetGlobalVariableFor((PyObject*)&_Py_ZeroStruct),
"COMPARE_OP_result");
this->state_->IncRef(value);
- this->fbuilder_->Push(value);
+ this->fbuilder_->SetOpcodeResult(0, value);
}

void
@@ -195,7 +198,7 @@
this->state_->DecRef(lhs);
this->state_->DecRef(rhs);
this->fbuilder_->PropagateExceptionOnNull(result);
- this->fbuilder_->Push(result);
+ this->fbuilder_->SetOpcodeResult(0, result);
}

Value *
=======================================
--- /trunk/JIT/opcodes/globals.cc Wed Jul 28 23:50:04 2010
+++ /trunk/JIT/opcodes/globals.cc Sun Aug 15 03:03:27 2010
@@ -86,6 +86,7 @@

void OpcodeGlobals::LOAD_GLOBAL_safe(int index)
{
+ this->fbuilder_->SetOpcodeArguments(0);
BasicBlock *global_missing =
this->state_->CreateBasicBlock("LOAD_GLOBAL_global_missing");
BasicBlock *global_success =
@@ -108,7 +109,7 @@

this->builder_.SetInsertPoint(global_success);
this->state_->IncRef(global);
- this->fbuilder_->Push(global);
+ this->fbuilder_->SetOpcodeResult(0, global);
this->builder_.CreateBr(done);

this->builder_.SetInsertPoint(global_missing);
@@ -127,7 +128,7 @@

this->builder_.SetInsertPoint(builtin_success);
this->state_->IncRef(builtin);
- this->fbuilder_->Push(builtin);
+ this->fbuilder_->SetOpcodeResult(0, builtin);
this->builder_.CreateBr(done);

this->builder_.SetInsertPoint(done);
=======================================
--- /trunk/Python/compile.c Sun Aug 8 19:48:05 2010
+++ /trunk/Python/compile.c Sun Aug 15 03:03:27 2010
@@ -675,8 +675,8 @@
b->b_instr[off].i_lineno = c->u->u_lineno;
}

-static int
-opcode_stack_effect(int opcode, int oparg)
+int
+_Py_OpcodeStackEffect(int opcode, int oparg)
{
switch (opcode) {
case POP_TOP:
@@ -714,13 +714,13 @@
return -1;

case SLICE_NONE:
- return 1;
- case SLICE_LEFT:
return 0;
+ case SLICE_LEFT:
+ return -1;
case SLICE_RIGHT:
- return 0;
- case SLICE_BOTH:
return -1;
+ case SLICE_BOTH:
+ return -2;

case STORE_SLICE_NONE:
return -2;
@@ -875,7 +875,7 @@
case BUILD_SLICE_THREE:
return -2;
case MAKE_CLOSURE:
- return -oparg;
+ return -(oparg + 1);
case LOAD_CLOSURE:
return 1;
case LOAD_DEREF:
@@ -884,7 +884,7 @@
return -1;
default:
fprintf(stderr, "opcode = %d\n", opcode);
- Py_FatalError("opcode_stack_effect()");
+ Py_FatalError("_Py_OpcodeStackEffect()");

}
return 0; /* not reachable */
@@ -3546,7 +3546,7 @@
b->b_startdepth = depth;
for (i = 0; i < b->b_iused; i++) {
instr = &b->b_instr[i];
- depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg);
+ depth += _Py_OpcodeStackEffect(instr->i_opcode, instr->i_oparg);
if (depth > maxdepth)
maxdepth = depth;
assert(depth >= 0); /* invalid code or bug in stackdepth() */

Reply all
Reply to author
Forward
0 new messages