Commit 351b3060 authored by Travis Hance's avatar Travis Hance Committed by Travis Hance

member descriptor ics

parent e36e88e5
......@@ -122,7 +122,9 @@ void Assembler::emitInt(int64_t n, int bytes) {
}
void Assembler::emitRex(uint8_t rex) {
emitByte(rex | 0x40);
if (rex != 0) {
emitByte(rex | 0x40);
}
}
void Assembler::emitModRM(uint8_t mod, uint8_t reg, uint8_t rm) {
......@@ -261,8 +263,20 @@ void Assembler::mov(Register src, Indirect dest) {
}
}
void Assembler::mov(Indirect src, Register dest) {
int rex = REX_W;
void Assembler::mov(Indirect src, Register dest, MovType type) {
int rex;
switch (type) {
case MovType::Q:
rex = REX_W;
break;
case MovType::L:
case MovType::B:
case MovType::ZBL:
rex = 0;
break;
default:
RELEASE_ASSERT(false, "unrecognized MovType");
}
int src_idx = src.base.regnum;
int dest_idx = dest.regnum;
......@@ -276,8 +290,25 @@ void Assembler::mov(Indirect src, Register dest) {
dest_idx -= 8;
}
emitRex(rex);
emitByte(0x8b); // opcode
if (rex)
emitRex(rex);
// opcode
switch (type) {
case MovType::Q:
case MovType::L:
emitByte(0x8b);
break;
case MovType::B:
emitByte(0x8a);
break;
case MovType::ZBL:
emitByte(0x0f);
emitByte(0xb6);
break;
default:
RELEASE_ASSERT(false, "unrecognized MovType");
}
bool needssib = (src_idx == 0b100);
......
......@@ -48,6 +48,13 @@ enum ConditionCode {
COND_GREATER = 0xF, // ZF=0 && SF==OF: NLE/G
};
enum class MovType {
Q,
L,
B,
ZBL,
};
class Assembler {
private:
uint8_t* const start_addr, *const end_addr;
......@@ -80,7 +87,7 @@ public:
void movq(Immediate imm, Indirect dest);
void mov(Register src, Register dest);
void mov(Register src, Indirect dest);
void mov(Indirect src, Register dest);
void mov(Indirect src, Register dest, MovType type = MovType::Q);
void movsd(XMMRegister src, XMMRegister dest);
void movsd(XMMRegister src, Indirect dest);
void movsd(Indirect src, XMMRegister dest);
......
......@@ -191,7 +191,7 @@ void RewriterVarUsage::addAttrGuard(int offset, uint64_t val, bool negate) {
assembler->jne(assembler::JumpDestination::fromStart(rewriter->rewrite->getSlotSize()));
}
RewriterVarUsage RewriterVarUsage::getAttr(int offset, KillFlag kill, Location dest) {
RewriterVarUsage RewriterVarUsage::getAttr(int offset, KillFlag kill, Location dest, assembler::MovType type) {
assertValid();
// Save these, since if we kill this register the var might disappear:
......@@ -202,10 +202,18 @@ RewriterVarUsage RewriterVarUsage::getAttr(int offset, KillFlag kill, Location d
setDoneUsing();
}
assembler::Register newvar_reg = rewriter->allocReg(dest);
RewriterVarUsage newvar = rewriter->createNewVar(newvar_reg);
rewriter->assembler->mov(assembler::Indirect(this_reg, offset), newvar_reg);
return std::move(newvar);
if (dest.type == Location::XMMRegister) {
assert(rewriter->vars_by_location.count(dest) == 0);
assembler::XMMRegister newvar_reg = dest.asXMMRegister();
RewriterVarUsage newvar = rewriter->createNewVar(dest);
rewriter->assembler->movsd(assembler::Indirect(this_reg, offset), newvar_reg);
return std::move(newvar);
} else {
assembler::Register newvar_reg = rewriter->allocReg(dest);
RewriterVarUsage newvar = rewriter->createNewVar(newvar_reg);
rewriter->assembler->mov(assembler::Indirect(this_reg, offset), newvar_reg, type);
return std::move(newvar);
}
}
RewriterVarUsage RewriterVarUsage::cmp(AST_TYPE::AST_TYPE cmp_type, RewriterVarUsage other, Location dest) {
......@@ -533,7 +541,8 @@ static const Location caller_save_registers[]{
assembler::XMM11, assembler::XMM12, assembler::XMM13, assembler::XMM14, assembler::XMM15,
};
RewriterVarUsage Rewriter::call(bool can_call_into_python, void* func_addr, std::vector<RewriterVarUsage> args) {
RewriterVarUsage Rewriter::call(bool can_call_into_python, void* func_addr, std::vector<RewriterVarUsage> args,
std::vector<RewriterVarUsage> args_xmm) {
// TODO figure out why this is here -- what needs to be done differently
// if can_call_into_python is true?
// assert(!can_call_into_python);
......@@ -577,6 +586,11 @@ RewriterVarUsage Rewriter::call(bool can_call_into_python, void* func_addr, std:
assert(var->isInLocation(Location::forArg(i)));
}
for (int i = 0; i < args_xmm.size(); i++) {
Location l((assembler::XMMRegister(i)));
assert(args_xmm[i].var->isInLocation(l));
}
#ifndef NDEBUG
for (int i = 0; i < args.size(); i++) {
RewriterVar* var = args[i].var;
......
......@@ -93,6 +93,7 @@ public:
static constexpr Location any() { return Location(AnyReg, 0); }
static constexpr Location none() { return Location(None, 0); }
static Location forArg(int argnum);
static Location forXMMArg(int argnum);
bool operator==(const Location rhs) const { return this->asInt() == rhs.asInt(); }
......@@ -160,7 +161,8 @@ public:
void addGuard(uint64_t val);
void addGuardNotEq(uint64_t val);
void addAttrGuard(int offset, uint64_t val, bool negate = false);
RewriterVarUsage getAttr(int offset, KillFlag kill, Location loc = Location::any());
RewriterVarUsage getAttr(int offset, KillFlag kill, Location loc = Location::any(),
assembler::MovType type = assembler::MovType::Q);
void setAttr(int offset, RewriterVarUsage other);
RewriterVarUsage cmp(AST_TYPE::AST_TYPE cmp_type, RewriterVarUsage other, Location loc = Location::any());
RewriterVarUsage toBool(KillFlag kill, Location loc = Location::any());
......@@ -292,7 +294,8 @@ public:
void trap();
RewriterVarUsage loadConst(int64_t val, Location loc = Location::any());
RewriterVarUsage call(bool can_call_into_python, void* func_addr, std::vector<RewriterVarUsage> args);
RewriterVarUsage call(bool can_call_into_python, void* func_addr, std::vector<RewriterVarUsage> args,
std::vector<RewriterVarUsage> args_xmm = std::vector<RewriterVarUsage>());
RewriterVarUsage call(bool can_call_into_python, void* func_addr, RewriterVarUsage arg0);
RewriterVarUsage call(bool can_call_into_python, void* func_addr, RewriterVarUsage arg0, RewriterVarUsage arg1);
RewriterVarUsage allocate(int n);
......
......@@ -881,10 +881,20 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box* o
RewriterVarUsage& r_descr, bool for_call, bool* should_bind_out) {
// Special case: data descriptor: member descriptor
if (descr->cls == member_cls) {
static StatCounter slowpath("slowpath_member_descriptor_get");
slowpath.log();
BoxedMemberDescriptor* member_desc = static_cast<BoxedMemberDescriptor*>(descr);
// TODO should also have logic to raise a type error if type of obj is wrong
if (rewrite_args) {
// TODO we should use this an index in the lookup rather than hardcoding
// the value and guarding on it be the same.
RewriterVarUsage r_offset = r_descr.getAttr(offsetof(BoxedMemberDescriptor, offset),
RewriterVarUsage::KillFlag::NoKill, Location::any());
r_offset.addGuard(member_desc->offset);
r_offset.setDoneUsing();
if (rewrite_args->call_done_guarding)
rewrite_args->rewriter->setDoneGuarding();
r_descr.setDoneUsing();
......@@ -892,37 +902,70 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box* o
switch (member_desc->type) {
case BoxedMemberDescriptor::OBJECT: {
assert(member_desc->offset % sizeof(Box*) == 0);
Box* rtn = reinterpret_cast<Box**>(obj)[member_desc->offset / sizeof(Box*)];
RELEASE_ASSERT(rtn, "");
if (rewrite_args) {
rewrite_args->out_rtn = rewrite_args->obj.getAttr(
member_desc->offset, RewriterVarUsage::KillFlag::Kill, rewrite_args->destination);
rewrite_args->out_success = true;
}
Box* rtn = *reinterpret_cast<Box**>((char*)obj + member_desc->offset);
RELEASE_ASSERT(rtn, "");
return rtn;
}
case BoxedMemberDescriptor::BYTE: {
// TODO rewriter stuff for these other cases as well
rewrite_args = NULL;
if (rewrite_args) {
RewriterVarUsage r_unboxed_val
= rewrite_args->obj.getAttr(member_desc->offset, RewriterVarUsage::KillFlag::Kill,
Location::forArg(0), assembler::MovType::ZBL);
rewrite_args->out_rtn
= rewrite_args->rewriter->call(false, (void*)boxInt, std::move(r_unboxed_val));
rewrite_args->out_success = true;
}
int8_t rtn = reinterpret_cast<int8_t*>(obj)[member_desc->offset];
return boxInt(rtn);
}
case BoxedMemberDescriptor::BOOL: {
rewrite_args = NULL;
if (rewrite_args) {
RewriterVarUsage r_unboxed_val
= rewrite_args->obj.getAttr(member_desc->offset, RewriterVarUsage::KillFlag::Kill,
Location::forArg(0), assembler::MovType::B);
rewrite_args->out_rtn
= rewrite_args->rewriter->call(false, (void*)boxBool, std::move(r_unboxed_val));
rewrite_args->out_success = true;
}
bool rtn = reinterpret_cast<bool*>(obj)[member_desc->offset];
return boxBool(rtn);
}
case BoxedMemberDescriptor::INT: {
rewrite_args = NULL;
int rtn = reinterpret_cast<int*>(obj)[member_desc->offset / sizeof(int)];
// rewrite_args = NULL;
if (rewrite_args) {
rewrite_args->rewriter->trap();
RewriterVarUsage r_unboxed_val
= rewrite_args->obj.getAttr(member_desc->offset, RewriterVarUsage::KillFlag::Kill,
Location::forArg(0), assembler::MovType::L);
rewrite_args->out_rtn
= rewrite_args->rewriter->call(false, (void*)boxInt, std::move(r_unboxed_val));
rewrite_args->out_success = true;
}
int rtn = *reinterpret_cast<int*>((char*)obj + member_desc->offset);
return boxInt(rtn);
}
case BoxedMemberDescriptor::FLOAT: {
rewrite_args = NULL;
double rtn = reinterpret_cast<double*>(obj)[member_desc->offset / sizeof(double)];
if (rewrite_args) {
RewriterVarUsage r_unboxed_val = rewrite_args->obj.getAttr(
member_desc->offset, RewriterVarUsage::KillFlag::Kill, assembler::XMM0);
std::vector<RewriterVarUsage> normal_args;
std::vector<RewriterVarUsage> float_args;
float_args.push_back(std::move(r_unboxed_val));
rewrite_args->out_rtn = rewrite_args->rewriter->call(false, (void*)boxFloat, std::move(normal_args),
std::move(float_args));
rewrite_args->out_success = true;
}
double rtn = *reinterpret_cast<double*>((char*)obj + member_desc->offset);
return boxFloat(rtn);
}
default:
......
# skip-if: sys.version_info.micro >= 4
# - Error message changed in 2.7.4
# Regression test:
# If the init function doesn't exist, shouldn't just silently ignore any args
# that got passed
......
# run_args: -n
# statcheck: noninit_count('slowpath_member_descriptor_get') <= 50
f = open("/dev/null")
def go():
# object
s = slice(i, 1.0, "abc")
print s.start
print s.stop
print s.step
# byte
# TODO
# using softspace works for this test as long as we implement softspace as
# a member descriptor but it should actually a getset_descriptor
# in addition to fixing that, we should replace it in this test with a legit
# member descriptor
print f.softspace
# TODO figure out what uses BOOL and test that
# TODO figure out what uses INT and test that
# float
c = 1j + i
print c.real
print c.imag
for i in xrange(1000):
go();
# skip-if: sys.version_info.micro >= 4
# - Error message changed in 2.7.4
# object.__new__ doesn't complain if __init__ is overridden:
class C1(object):
......
......@@ -35,7 +35,7 @@ IMAGE = "pyston_dbg"
KEEP_GOING = False
FN_JUST_SIZE = 20
EXTRA_JIT_ARGS = []
TIME_LIMIT = 3
TIME_LIMIT = 4
# For fun, can test pypy.
# Tough because the tester will check to see if the error messages are exactly the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment