Commit 31f7002a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Some small independent changes

Can emit add/sub/etc instructions with 32-bit operands in addition to 8-bit now
Can get the RSP and RBP in rewriter1, for accessing scratch space
Change some debugging output

Fix a gc bug: if an object gets new'd, and takes a parameter that gets new'd, the sequence is
1) object space gets allocated
2) parameter space gets allocated
3) parameter gets constructed
4) object gets constructed
The bug is that the object construction is what initializes the GC header,
so if step #3 causes a collection, it can see that the allocation from step #1
has an invalid header.
As a workaround, always zero out the header in allocation, and skip blocks with
zeroed headers.
The real solution is probably to have the GC manage the header itself rather than
expecting the user to; this would mean that gc_alloc would take the allocation kind,
put that into the header, and then return a pointer to the post-header data section
of the allocation.
parent 138e4546
...@@ -289,8 +289,9 @@ private: ...@@ -289,8 +289,9 @@ private:
CompilerType* rtn_type = func->callType(ArgPassSpec(arg_types.size()), arg_types, NULL); CompilerType* rtn_type = func->callType(ArgPassSpec(arg_types.size()), arg_types, NULL);
// Should be unboxing things before getting here: // Should be unboxing things before getting here; would like to assert, though
ASSERT(rtn_type == unboxedType(rtn_type->getConcreteType()), "%s", rtn_type->debugName().c_str()); // we haven't specialized all of the stdlib.
// ASSERT(rtn_type == unboxedType(rtn_type->getConcreteType()), "%s", rtn_type->debugName().c_str());
rtn_type = unboxedType(rtn_type->getConcreteType()); rtn_type = unboxedType(rtn_type->getConcreteType());
if (speculation != TypeAnalysis::NONE) { if (speculation != TypeAnalysis::NONE) {
......
...@@ -73,7 +73,7 @@ void Assembler::emitArith(Immediate imm, Register r, int opcode) { ...@@ -73,7 +73,7 @@ void Assembler::emitArith(Immediate imm, Register r, int opcode) {
// assert(r != RSP && "This breaks unwinding, please don't use."); // assert(r != RSP && "This breaks unwinding, please don't use.");
int64_t amount = imm.val; int64_t amount = imm.val;
RELEASE_ASSERT(-0x80 <= amount && amount < 0x80 && "unsupported", ""); RELEASE_ASSERT((-1L << 31) <= amount && amount < (1L << 31) - 1, "");
assert(0 <= opcode && opcode < 8); assert(0 <= opcode && opcode < 8);
int rex = REX_W; int rex = REX_W;
...@@ -85,9 +85,15 @@ void Assembler::emitArith(Immediate imm, Register r, int opcode) { ...@@ -85,9 +85,15 @@ void Assembler::emitArith(Immediate imm, Register r, int opcode) {
} }
emitRex(rex); emitRex(rex);
emitByte(0x83); if (-0x80 <= amount && amount < 0x80) {
emitModRM(0b11, opcode, reg_idx); emitByte(0x83);
emitByte(amount); emitModRM(0b11, opcode, reg_idx);
emitByte(amount);
} else {
emitByte(0x81);
emitModRM(0b11, opcode, reg_idx);
emitInt(amount, 4);
}
} }
......
...@@ -27,6 +27,10 @@ using namespace pyston::assembler; ...@@ -27,6 +27,10 @@ using namespace pyston::assembler;
Register fromArgnum(int argnum) { Register fromArgnum(int argnum) {
switch (argnum) { switch (argnum) {
case -5:
return RBP;
case -4:
return RSP;
case -3: case -3:
return R11; return R11;
case -2: case -2:
...@@ -234,6 +238,17 @@ RewriterVar RewriterVar::toBool(int dest) { ...@@ -234,6 +238,17 @@ RewriterVar RewriterVar::toBool(int dest) {
return RewriterVar(rewriter, dest, version); return RewriterVar(rewriter, dest, version);
} }
RewriterVar RewriterVar::add(int64_t amount) {
assertValid();
if (amount > 0)
rewriter->assembler->add(assembler::Immediate(amount), fromArgnum(this->argnum));
else
rewriter->assembler->sub(assembler::Immediate(-amount), fromArgnum(this->argnum));
int new_version = rewriter->mutate(this->argnum);
return RewriterVar(rewriter, this->argnum, new_version);
}
Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num_temp_regs, const char* debug_name) { Rewriter* Rewriter::createRewriter(void* ic_rtn_addr, int num_orig_args, int num_temp_regs, const char* debug_name) {
assert(num_temp_regs <= 2 && "unsupported"); assert(num_temp_regs <= 2 && "unsupported");
...@@ -267,7 +282,7 @@ Rewriter::Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs) ...@@ -267,7 +282,7 @@ Rewriter::Rewriter(ICSlotRewrite* rewrite, int num_orig_args, int num_temp_regs)
//} //}
#ifndef NDEBUG #ifndef NDEBUG
for (int i = -3; i < MAX_ARGS; i++) { for (int i = -5; i < MAX_ARGS; i++) {
versions[i] = next_version++; versions[i] = next_version++;
} }
#endif #endif
...@@ -297,17 +312,39 @@ RewriterVar Rewriter::getArg(int argnum) { ...@@ -297,17 +312,39 @@ RewriterVar Rewriter::getArg(int argnum) {
#ifndef NDEBUG #ifndef NDEBUG
int version = versions[argnum]; int version = versions[argnum];
assert(version); assert(version);
assert(version == argnum + 5); assert(version == argnum + 7);
#else
int version = 0;
#endif
return RewriterVar(this, argnum, version);
}
RewriterVar Rewriter::getRsp() {
int argnum = -4;
#ifndef NDEBUG
int version = versions[argnum];
#else
int version = 0;
#endif
assert(version);
return RewriterVar(this, argnum, version);
}
RewriterVar Rewriter::getRbp() {
int argnum = -5;
#ifndef NDEBUG
int version = versions[argnum];
#else #else
int version = 0; int version = 0;
#endif #endif
assert(version);
return RewriterVar(this, argnum, version); return RewriterVar(this, argnum, version);
} }
#ifndef NDEBUG #ifndef NDEBUG
void Rewriter::checkArgsValid() { void Rewriter::checkArgsValid() {
for (int i = 0; i < num_orig_args; i++) for (int i = 0; i < num_orig_args; i++)
checkVersion(i, i + 5); checkVersion(i, i + 7);
} }
int Rewriter::mutate(int argnum) { int Rewriter::mutate(int argnum) {
......
...@@ -71,6 +71,7 @@ public: ...@@ -71,6 +71,7 @@ public:
void push(); void push();
RewriterVar cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar& val, int dest); RewriterVar cmp(AST_TYPE::AST_TYPE cmp_type, const RewriterVar& val, int dest);
RewriterVar toBool(int dest); RewriterVar toBool(int dest);
RewriterVar add(int64_t amount);
friend class Rewriter; friend class Rewriter;
}; };
...@@ -117,6 +118,12 @@ public: ...@@ -117,6 +118,12 @@ public:
inline void checkArgsValid() {} inline void checkArgsValid() {}
#endif #endif
int getFuncStackSize() { return rewrite->getFuncStackSize(); }
int getScratchRbpOffset() { return rewrite->getScratchRbpOffset(); }
int getScratchBytes() { return rewrite->getScratchBytes(); }
RewriterVar getRbp();
RewriterVar getRsp();
void addDecision(int way); void addDecision(int way);
RewriterVar alloca_(int bytes, int dest_argnum); RewriterVar alloca_(int bytes, int dest_argnum);
......
...@@ -1400,6 +1400,7 @@ bool PrintVisitor::visit_return(AST_Return* node) { ...@@ -1400,6 +1400,7 @@ bool PrintVisitor::visit_return(AST_Return* node) {
} }
bool PrintVisitor::visit_slice(AST_Slice* node) { bool PrintVisitor::visit_slice(AST_Slice* node) {
printf("<slice>(");
if (node->lower) if (node->lower)
node->lower->accept(this); node->lower->accept(this);
if (node->upper || node->step) if (node->upper || node->step)
...@@ -1410,6 +1411,7 @@ bool PrintVisitor::visit_slice(AST_Slice* node) { ...@@ -1410,6 +1411,7 @@ bool PrintVisitor::visit_slice(AST_Slice* node) {
putchar(':'); putchar(':');
node->step->accept(this); node->step->accept(this);
} }
printf(")");
return true; return true;
} }
......
...@@ -145,7 +145,7 @@ private: ...@@ -145,7 +145,7 @@ private:
AST_expr* remapped_iter = remapExpr(c->iter); AST_expr* remapped_iter = remapExpr(c->iter);
AST_expr* iter_attr = makeLoadAttribute(remapped_iter, "__iter__", true); AST_expr* iter_attr = makeLoadAttribute(remapped_iter, "__iter__", true);
AST_expr* iter_call = makeCall(iter_attr); AST_expr* iter_call = makeCall(iter_attr);
std::string iter_name = nodeName(node, "iter", i); std::string iter_name = nodeName(node, "lc_iter", i);
AST_stmt* iter_assign = makeAssign(iter_name, iter_call); AST_stmt* iter_assign = makeAssign(iter_name, iter_call);
push_back(iter_assign); push_back(iter_assign);
......
...@@ -121,6 +121,10 @@ static void markPhase() { ...@@ -121,6 +121,10 @@ static void markPhase() {
setMark(header); setMark(header);
// is being made
if (header->kind_id == 0)
continue;
ASSERT(KIND_OFFSET <= header->kind_id && header->kind_id < KIND_OFFSET + num_kinds, "%p %d", header, ASSERT(KIND_OFFSET <= header->kind_id && header->kind_id < KIND_OFFSET + num_kinds, "%p %d", header,
header->kind_id); header->kind_id);
......
...@@ -24,14 +24,6 @@ namespace gc { ...@@ -24,14 +24,6 @@ namespace gc {
#define MARK_BIT 0x1 #define MARK_BIT 0x1
inline GCObjectHeader* headerFromObject(void* obj) {
#ifndef NVALGRIND
return static_cast<GCObjectHeader*>((void*)((char*)obj + 0));
#else
return static_cast<GCObjectHeader*>(obj);
#endif
}
inline void setMark(GCObjectHeader* header) { inline void setMark(GCObjectHeader* header) {
header->gc_flags |= MARK_BIT; header->gc_flags |= MARK_BIT;
} }
......
...@@ -22,6 +22,14 @@ ...@@ -22,6 +22,14 @@
namespace pyston { namespace pyston {
namespace gc { namespace gc {
inline GCObjectHeader* headerFromObject(void* obj) {
#ifndef NVALGRIND
return static_cast<GCObjectHeader*>((void*)((char*)obj + 0));
#else
return static_cast<GCObjectHeader*>(obj);
#endif
}
#define BLOCK_SIZE 4096 #define BLOCK_SIZE 4096
#define ATOM_SIZE 16 #define ATOM_SIZE 16
static_assert(BLOCK_SIZE % ATOM_SIZE == 0, ""); static_assert(BLOCK_SIZE % ATOM_SIZE == 0, "");
...@@ -78,24 +86,28 @@ public: ...@@ -78,24 +86,28 @@ public:
void* realloc(void* ptr, size_t bytes); void* realloc(void* ptr, size_t bytes);
void* alloc(size_t bytes) { void* alloc(size_t bytes) {
void* rtn;
// assert(bytes >= 16); // assert(bytes >= 16);
if (bytes <= 16) if (bytes <= 16)
return allocSmall(16, &heads[0], &full_heads[0]); rtn = allocSmall(16, &heads[0], &full_heads[0]);
if (bytes <= 32) else if (bytes <= 32)
return allocSmall(32, &heads[1], &full_heads[1]); rtn = allocSmall(32, &heads[1], &full_heads[1]);
else if (bytes > sizes[NUM_BUCKETS - 1])
if (bytes > sizes[NUM_BUCKETS - 1]) { rtn = allocLarge(bytes);
return allocLarge(bytes); else {
} rtn = NULL;
for (int i = 2; i < NUM_BUCKETS; i++) {
for (int i = 2; i < NUM_BUCKETS; i++) { if (sizes[i] >= bytes) {
if (sizes[i] >= bytes) { rtn = allocSmall(sizes[i], &heads[i], &full_heads[i]);
return allocSmall(sizes[i], &heads[i], &full_heads[i]); break;
}
} }
} }
// unreachable // assert(rtn);
abort(); GCObjectHeader* header = headerFromObject(rtn);
*reinterpret_cast<intptr_t*>(header) = 0;
return rtn;
} }
void free(void* ptr); void free(void* ptr);
......
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