From 064ba4519a1fc20e6d25110b5bdf8758ca015b4c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 8 Jun 2008 15:51:11 -0600 Subject: [PATCH 01/12] update version number to 0.1 --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 63954a932f..0308a916b5 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ MAKEFLAGS = -s name = avian -version = 0.0.1 +version = 0.1 build-arch = $(shell uname -m) ifeq ($(build-arch),i586) From fc8c5a2ea9bd571c9e08a82174c18a4eef0f93bb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Jun 2008 08:49:13 -0600 Subject: [PATCH 02/12] fix a few bugs revealed by ProGuard optimizations, including too-early constant propagation during array loads and stores --- src/compile.cpp | 170 ++++++++++++++--------------------------------- src/compiler.cpp | 44 ++++++------ src/compiler.h | 3 - test/Misc.java | 7 ++ 4 files changed, 81 insertions(+), 143 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index e6fb0bc22d..7dd9397690 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1834,67 +1834,34 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (&singletonValue(t, aioobThunk(t), 0))); } - if (c->isConstant(index)) { - unsigned i = c->constantValue(index); - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord)))); - break; + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); + break; - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4)))); - break; + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); + break; - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody + i))); - break; + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); + break; - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2)))); - break; + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); + break; - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody + (i * 8)))); - break; + case daload: + case laload: + frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); + break; - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2)))); - break; - } - } else { - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); - break; - - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); - break; - - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); - break; - - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); - break; - - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); - break; - - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); - break; - } + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); + break; } } break; @@ -1923,72 +1890,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, (&singletonValue(t, aioobThunk(t), 0))); } - if (c->isConstant(index)) { - unsigned i = c->constantValue(index); - switch (instruction) { - case aastore: { - c->call - (c->constant(getThunk(t, setMaybeNullThunk)), - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->constant(ArrayBody + (i * BytesPerWord)), - value); - } break; + switch (instruction) { + case aastore: { + c->call + (c->constant(getThunk(t, setMaybeNullThunk)), + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->add(4, c->constant(ArrayBody), + c->shl(4, c->constant(log(BytesPerWord)), index)), + value); + } break; - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody + (i * 4))); - break; + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody, index, 4)); + break; - case bastore: - c->store(1, value, c->memory(array, ArrayBody + i)); - break; + case bastore: + c->store(1, value, c->memory(array, ArrayBody, index, 1)); + break; - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody + (i * 2))); - break; + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody, index, 2)); + break; - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody + (i * 8))); - break; - } - } else { - switch (instruction) { - case aastore: { - c->call - (c->constant(getThunk(t, setMaybeNullThunk)), - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->add(4, c->constant(ArrayBody), - c->shl(4, c->constant(log(BytesPerWord)), index)), - value); - } break; - - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody, index, 4)); - break; - - case bastore: - c->store(1, value, c->memory(array, ArrayBody, index, 1)); - break; - - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody, index, 2)); - break; - - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody, index, 8)); - break; - } + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody, index, 8)); + break; } } break; @@ -2602,7 +2534,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, c->jle(target); break; } - + compile(t, frame, newIp); if (UNLIKELY(t->exception)) return; } break; diff --git a/src/compiler.cpp b/src/compiler.cpp index 53ca697095..bc242b26e1 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1826,7 +1826,7 @@ class MemoryEvent: public Event { scale(scale), result(result) { addRead(c, base, BytesPerWord, anyRegisterSite(c)); - if (index) addRead(c, index, BytesPerWord, anyRegisterSite(c)); + if (index) addRead(c, index, BytesPerWord, registerOrConstantSite(c)); } virtual void compile(Context* c) { @@ -1835,9 +1835,26 @@ class MemoryEvent: public Event { } int indexRegister; + int displacement = this->displacement; + unsigned scale = this->scale; if (index) { - assert(c, index->source->type(c) == RegisterOperand); - indexRegister = static_cast(index->source)->register_.low; + ConstantSite* constant = 0; + for (Site* s = index->sites; s; s = s->next) { + if (s->type(c) == ConstantOperand) { + constant = static_cast(s); + break; + } + } + + if (constant) { + indexRegister = NoRegister; + displacement += (constant->value.value->value() * scale); + scale = 1; + } else { + assert(c, index->source->type(c) == RegisterOperand); + indexRegister = static_cast + (index->source)->register_.low; + } } else { indexRegister = NoRegister; } @@ -1846,7 +1863,7 @@ class MemoryEvent: public Event { nextRead(c, base); if (index) { - if (BytesPerWord == 8) { + if (BytesPerWord == 8 and indexRegister != NoRegister) { apply(c, Move4To8, 8, index->source, index->source); } @@ -2641,22 +2658,6 @@ class MyCompiler: public Compiler { return value(&c, s, s); } - virtual bool isConstant(Operand* a) { - for (Site* s = static_cast(a)->sites; s; s = s->next) { - if (s->type(&c) == ConstantOperand) return true; - } - return false; - } - - virtual int64_t constantValue(Operand* a) { - for (Site* s = static_cast(a)->sites; s; s = s->next) { - if (s->type(&c) == ConstantOperand) { - return static_cast(s)->value.value->value(); - } - } - abort(&c); - } - virtual Operand* label() { return value(&c, ::constantSite(&c, static_cast(0))); } @@ -2698,7 +2699,8 @@ class MyCompiler: public Compiler { Value* v = value(&c); c.state->stack = ::stack(&c, v, 1, c.state->stack); c.state->stack->pushed = true; -// v->sites = pushSite(&c, c.state->stack->index); + c.state->stack->pushSite + = v->sites = pushSite(&c, c.state->stack->index); } } diff --git a/src/compiler.h b/src/compiler.h index 6d27a60cc1..89f2aa0a49 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -62,9 +62,6 @@ class Compiler { virtual Operand* base() = 0; virtual Operand* thread() = 0; - virtual bool isConstant(Operand* value) = 0; - virtual int64_t constantValue(Operand* value) = 0; - virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; diff --git a/test/Misc.java b/test/Misc.java index 483ba73820..81bdbe55a0 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -95,6 +95,13 @@ public class Misc { } public static void main(String[] args) { + { boolean p = true; + int[] array = new int[] { 1, 2 }; + expect(array[0] == array[p ? 0 : 1]); + p = false; + expect(array[1] == array[p ? 0 : 1]); + } + expect(roundUp(156, 2) == 156); { Foo foo = new Foo(); From 5b2065e76c19a3676bc618768c01f25815b62ef1 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Jun 2008 18:14:15 -0600 Subject: [PATCH 03/12] only elide constant multiply if constant is one, not zero (duh) --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index 8f0e05eab4..30c292f11a 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1144,7 +1144,7 @@ multiplyCR(Context* c, unsigned size, Assembler::Constant* a, c->client->releaseTemporary(tmp.high); } else { int64_t v = a->value->value(); - if (v) { + if (v != 1) { if (isInt32(v)) { if (size == 8) rex(c); if (isInt8(v)) { From dc136bb751ae6e7bd93393a1f902fbe6ba56e710 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Jun 2008 18:16:02 -0600 Subject: [PATCH 04/12] fix stack tracking weirdness for jsr instruction --- src/compile.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compile.cpp b/src/compile.cpp index 7dd9397690..4bd272b352 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2790,6 +2790,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, assert(t, newIp < codeLength(t, code)); + c->saveStack(); + frame->pushAddress(frame->machineIp(ip)); c->jmp(frame->machineIp(newIp)); From b80a3cea85a6b85bb6e6ce052ad7892b596940a2 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Jun 2008 18:17:44 -0600 Subject: [PATCH 05/12] handle constant comparisons (sometimes generated by ProGuard) in compiler --- src/compiler.cpp | 121 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 19 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index bc242b26e1..99b647c2bb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -37,6 +37,13 @@ apply(Context* c, UnaryOperation op, unsigned size, Site* a); void apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b); +enum ConstantCompare { + CompareNone, + CompareLess, + CompareGreater, + CompareEqual +}; + class Site { public: Site(): next(0) { } @@ -207,7 +214,8 @@ class Context { machineCode(0), locals(0), localTable(0), - stackReset(false) + stackReset(false), + constantCompare(CompareNone) { for (unsigned i = 0; i < assembler->registerCount(); ++i) { registers[i] = new (zone->allocate(sizeof(Register))) Register(i); @@ -238,6 +246,7 @@ class Context { Local* locals; Local** localTable; bool stackReset; + ConstantCompare constantCompare; }; class PoolPromise: public Promise { @@ -1595,6 +1604,17 @@ appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, MoveEvent(c, type, size, src, dst, srcTarget, dstTarget); } +ConstantSite* +findConstantSite(Context* c, Value* v) +{ + for (Site* s = v->sites; s; s = s->next) { + if (s->type(c) == ConstantOperand) { + return static_cast(s); + } + } + return 0; +} + class CompareEvent: public Event { public: CompareEvent(Context* c, unsigned size, Value* first, Value* second, @@ -1610,7 +1630,25 @@ class CompareEvent: public Event { fprintf(stderr, "CompareEvent.compile\n"); } - apply(c, Compare, size, first->source, second->source); + ConstantSite* firstConstant = findConstantSite(c, first); + ConstantSite* secondConstant = findConstantSite(c, second); + + if (firstConstant and secondConstant) { + int64_t d = firstConstant->value.value->value() + - secondConstant->value.value->value(); + + if (d < 0) { + c->constantCompare = CompareLess; + } else if (d > 0) { + c->constantCompare = CompareGreater; + } else { + c->constantCompare = CompareEqual; + } + } else { + c->constantCompare = CompareNone; + + apply(c, Compare, size, first->source, second->source); + } nextRead(c, first); nextRead(c, second); @@ -1838,13 +1876,7 @@ class MemoryEvent: public Event { int displacement = this->displacement; unsigned scale = this->scale; if (index) { - ConstantSite* constant = 0; - for (Site* s = index->sites; s; s = s->next) { - if (s->type(c) == ConstantOperand) { - constant = static_cast(s); - break; - } - } + ConstantSite* constant = findConstantSite(c, index); if (constant) { indexRegister = NoRegister; @@ -2022,7 +2054,65 @@ class BranchEvent: public Event { fprintf(stderr, "BranchEvent.compile\n"); } - apply(c, type, BytesPerWord, address->source); + bool jump; + UnaryOperation type = this->type; + if (type != Jump) { + switch (c->constantCompare) { + case CompareLess: + switch (type) { + case JumpIfLess: + case JumpIfLessOrEqual: + case JumpIfNotEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareGreater: + switch (type) { + case JumpIfGreater: + case JumpIfGreaterOrEqual: + case JumpIfNotEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareEqual: + switch (type) { + case JumpIfEqual: + case JumpIfLessOrEqual: + case JumpIfGreaterOrEqual: + jump = true; + type = Jump; + break; + + default: + jump = false; + } + break; + + case CompareNone: + jump = true; + break; + + default: abort(c); + } + } else { + jump = true; + } + + if (jump) { + apply(c, type, BytesPerWord, address->source); + } nextRead(c, address); } @@ -2220,14 +2310,7 @@ class BoundsCheckEvent: public Event { Assembler* a = c->assembler; - ConstantSite* constant = 0; - for (Site* s = index->sites; s; s = s->next) { - if (s->type(c) == ConstantOperand) { - constant = static_cast(s); - break; - } - } - + ConstantSite* constant = findConstantSite(c, index); CodePromise* nextPromise = codePromise(c, -1); CodePromise* outOfBoundsPromise = 0; @@ -2249,7 +2332,7 @@ class BoundsCheckEvent: public Event { Site* length = memorySite(c, base, lengthOffset); length->acquire(c, 0, 0, 0); - apply(c, Compare, BytesPerWord, index->source, length); + apply(c, Compare, 4, index->source, length); length->release(c); From 633ef83fa12ba77ce55d97477c160cb15359c179 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 10 Jun 2008 18:48:46 -0600 Subject: [PATCH 06/12] fix handling of values which appear more than once on the stack in trySteal --- src/compiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 99b647c2bb..64ced76ac2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1008,7 +1008,7 @@ trySteal(Context* c, Register* r, Stack* stack) unsigned count = 0; Stack* start = 0; for (Stack* s = stack; s and (not s->pushed); s = s->next) { - if (s->value == v) { + if (start == 0 and s->value == v) { start = s; } if (start) { From 94f7efc160f8a70a21d22053fd4de6b09a614d79 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 11 Jun 2008 08:47:06 -0600 Subject: [PATCH 07/12] ignore contents of stack location in popNow if the value already resides elsewhere besides the stack --- src/compiler.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 64ced76ac2..fddab04ae0 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1969,22 +1969,23 @@ popNow(Context* c, Stack* stack, unsigned count, bool ignore) s->pushSite = 0; s->pushed = false; - if (s->value->reads and (not ignore)) { + Value* v = s->value; + if (v->reads and v->sites == 0 and (not ignore)) { ::ignore(c, ignored); - Site* target = targetOrRegister(c, s->value); + Site* target = targetOrRegister(c, v); if (DebugStack) { fprintf(stderr, "pop %p value: %p target: %p\n", s, s->value, target); } - addSite(c, stack, s->size * BytesPerWord, s->value, target); + addSite(c, stack, s->size * BytesPerWord, v, target); apply(c, Pop, BytesPerWord * s->size, target); } else { if (DebugStack) { - fprintf(stderr, "ignore %p value: %p\n", s, s->value); + fprintf(stderr, "ignore %p value: %p\n", s, v); } ignored += s->size; From 357acbdb0f80a3234f4e48def07cf7f2b39766cb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 11 Jun 2008 08:59:05 -0600 Subject: [PATCH 08/12] implement move4To8CR, which just defers to moveCR --- src/x86.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/x86.cpp b/src/x86.cpp index 30c292f11a..dd9a042fac 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -771,6 +771,13 @@ moveRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) } } +void +move4To8CR(Context* c, unsigned, Assembler::Constant* a, + Assembler::Register* b) +{ + moveCR(c, 8, a, b); +} + void move4To8RR(Context* c, unsigned, Assembler::Register* a, Assembler::Register* b) @@ -1826,6 +1833,7 @@ populateTables() BinaryOperations[INDEX2(Move, Address, Memory)] = CAST2(moveAM); BinaryOperations[INDEX2(Move, Memory, Memory)] = CAST2(moveMM); + BinaryOperations[INDEX2(Move4To8, Constant, Register)] = CAST2(move4To8CR); BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); From eabb37e6ebd2ed85c7728e8a006b3d9620410cf3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Jun 2008 10:56:48 -0600 Subject: [PATCH 09/12] add lcmp instruction to Compiler and corresponding LongCompare instruction to Assembler, since that's the only efficient way to implement the lcmp bytecode on x86 --- src/assembler.h | 1 + src/compile.cpp | 30 +---- src/compiler.cpp | 11 +- src/compiler.h | 1 + src/x86.cpp | 284 ++++++++++++++++++++++++++++------------------- 5 files changed, 180 insertions(+), 147 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 8369c59064..ca7926965b 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -37,6 +37,7 @@ enum BinaryOperation { MoveZ, Move4To8, Swap, + LongCompare, Compare, Add, Subtract, diff --git a/src/compile.cpp b/src/compile.cpp index 4bd272b352..ec3c1d9235 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -2836,38 +2836,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, } break; case lcmp: { - Compiler::Operand* next = c->label(); - Compiler::Operand* less = c->label(); - Compiler::Operand* greater = c->label(); - Compiler::Operand* a = frame->popLong(); Compiler::Operand* b = frame->popLong(); - c->cmp(8, a, b); - - c->jl(less); - c->pushState(); - - c->jg(greater); - c->pushState(); - - c->push(4, c->constant(0)); - c->jmp(next); - - c->popState(); - c->mark(less); - - c->push(4, c->constant(-1)); - c->jmp(next); - - c->popState(); - c->mark(greater); - - c->push(4, c->constant(1)); - - c->mark(next); - - frame->pushedInt(); + frame->pushInt(c->load(4, c->lcmp(a, b))); } break; case lconst_0: diff --git a/src/compiler.cpp b/src/compiler.cpp index fddab04ae0..bffbf37b0c 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1742,7 +1742,7 @@ class CombineEvent: public Event { removeSite(c, second, second->source); if (result->reads) { - addSite(c, 0, 0, result, second->source); + addSite(c, 0, size, result, second->source); } } @@ -1824,7 +1824,7 @@ class TranslateEvent: public Event { removeSite(c, value, value->source); if (result->reads) { - addSite(c, 0, 0, result, value->source); + addSite(c, 0, size, result, value->source); } } @@ -2917,6 +2917,13 @@ class MyCompiler: public Compiler { return dst; } + virtual Operand* lcmp(Operand* a, Operand* b) { + Value* result = value(&c); + appendCombine(&c, LongCompare, 8, static_cast(a), + static_cast(b), result); + return result; + } + virtual void cmp(unsigned size, Operand* a, Operand* b) { appendCompare(&c, size, static_cast(a), static_cast(b)); diff --git a/src/compiler.h b/src/compiler.h index 89f2aa0a49..621f941019 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -91,6 +91,7 @@ class Compiler { virtual Operand* load(unsigned size, Operand* src) = 0; virtual Operand* loadz(unsigned size, Operand* src) = 0; virtual Operand* load4To8(Operand* src) = 0; + virtual Operand* lcmp(Operand* a, Operand* b) = 0; virtual void cmp(unsigned size, Operand* a, Operand* b) = 0; virtual void jl(Operand* address) = 0; virtual void jg(Operand* address) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index dd9a042fac..3e5ec4c17f 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1590,47 +1590,143 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, } void -multiwordCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, - Assembler::Operand* bl, Assembler::Operand* bh, - BinaryOperationType op) +longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) { - op(c, BytesPerWord, ah, bh); + assert(c, size == 8); - // if the high order bits are equal, we compare the low order - // bits; otherwise, we jump past that comparison - c->code.append(0x0f); - c->code.append(0x85); // jne + int64_t v = a->value->value(); + + ResolvedPromise negativePromise(-1); + Assembler::Constant negative(&negativePromise); - unsigned comparisonOffset = c->code.length(); - c->code.append4(0); + ResolvedPromise zeroPromise(0); + Assembler::Constant zero(&zeroPromise); - op(c, BytesPerWord, al, bl); + ResolvedPromise positivePromise(1); + Assembler::Constant positive(&positivePromise); - int32_t comparisonSize = c->code.length() - comparisonOffset - 4; - c->code.set(comparisonOffset, &comparisonSize, 4); + if (BytesPerWord == 8) { + compareCR(c, 8, a, b); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + moveCR(c, 4, &zero, b); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + moveCR(c, 4, &negative, b); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + moveCR(c, 4, &positive, b); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } else { + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Register bh(b->high); + + compareCR(c, 4, &ah, &bh); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + compareCR(c, 4, &al, b); + + c->code.append(0x0f); + c->code.append(0x82); // ja + unsigned above = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x87); // jb + unsigned below = c->code.length(); + c->code.append4(0); + + moveCR(c, 4, &zero, b); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + int32_t aboveOffset = c->code.length() - above - 4; + c->code.set(above, &aboveOffset, 4); + + moveCR(c, 4, &negative, b); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + int32_t belowOffset = c->code.length() - below - 4; + c->code.set(below, &belowOffset, 4); + + moveCR(c, 4, &positive, b); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } } void compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - Assembler::Register bh(b->high); + assert(c, BytesPerWord == 8 or size == 4); - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRR)); - } else { - if (size == 8) rex(c); - c->code.append(0x39); - c->code.append(0xc0 | (a->low << 3) | b->low); - } + if (size == 8) rex(c); + c->code.append(0x39); + c->code.append(0xc0 | (a->low << 3) | b->low); } void compareAR(Context* c, unsigned size, Assembler::Address* a, Assembler::Register* b) { - assert(c, BytesPerWord == 8 or size == 4); // todo + assert(c, BytesPerWord == 8 or size == 4); Assembler::Register tmp(c->client->acquireTemporary()); moveAR(c, size, a, &tmp); @@ -1642,36 +1738,26 @@ void compareCR(Context* c, unsigned size, Assembler::Constant* a, Assembler::Register* b) { + assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - - Assembler::Register bh(b->high); - - multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCR)); - } else { - if (isInt32(v)) { - if (size == 8) rex(c); - if (isInt8(v)) { - c->code.append(0x83); - c->code.append(0xf8 | b->low); - c->code.append(v); - } else { - c->code.append(0x81); - c->code.append(0xf8 | b->low); - c->code.append4(v); - } + if (isInt32(v)) { + if (size == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xf8 | b->low); + c->code.append(v); } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, a, &tmp); - compareRR(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); + c->code.append(0x81); + c->code.append(0xf8 | b->low); + c->code.append4(v); } + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, a, &tmp); + compareRR(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } } @@ -1679,28 +1765,18 @@ void compareCM(Context* c, unsigned size, Assembler::Constant* a, Assembler::Memory* b) { + assert(c, BytesPerWord == 8 or size == 4); + int64_t v = a->value->value(); - if (BytesPerWord == 4 and size == 8) { - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); + encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, &al, &ah, b, &bh, CAST2(compareCM)); + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); } else { - encode(c, isInt8(v) ? 0x83 : 0x81, 7, b, true); - - if (isInt8(v)) { - c->code.append(v); - } else if (isInt32(v)) { - c->code.append4(v); - } else { - abort(c); - } + abort(c); } } @@ -1708,75 +1784,48 @@ void compareRM(Context* c, unsigned size, Assembler::Register* a, Assembler::Memory* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareRM)); - } else { - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, a, a); - } - encode(c, 0x39, a->low, b, true); + assert(c, BytesPerWord == 8 or size == 4); + + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, a, a); } + encode(c, 0x39, a->low, b, true); } void compareMR(Context* c, unsigned size, Assembler::Memory* a, Assembler::Register* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); - Assembler::Register bh(b->high); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMR)); - } else { - if (BytesPerWord == 8 and size == 4) { - move4To8RR(c, size, b, b); - } - encode(c, 0x3b, b->low, a, true); + assert(c, BytesPerWord == 8 or size == 4); + + if (BytesPerWord == 8 and size == 4) { + move4To8RR(c, size, b, b); } + encode(c, 0x3b, b->low, a, true); } void compareMM(Context* c, unsigned size, Assembler::Memory* a, Assembler::Memory* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Memory ah(a->base, a->offset + 4, a->index, a->scale); - Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); - - multiwordCompare(c, a, &ah, b, &bh, CAST2(compareMM)); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveMR(c, size, a, &tmp); - compareRM(c, size, &tmp, b); - c->client->releaseTemporary(tmp.low); - } + assert(c, BytesPerWord == 8 or size == 4); + + Assembler::Register tmp(c->client->acquireTemporary()); + moveMR(c, size, a, &tmp); + compareRM(c, size, &tmp, b); + c->client->releaseTemporary(tmp.low); } void compareRC(Context* c, unsigned size, Assembler::Register* a, Assembler::Constant* b) { - if (BytesPerWord == 4 and size == 8) { - Assembler::Register ah(a->high); - - int64_t v = b->value->value(); - - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant bl(&low); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant bh(&high); - - multiwordCompare(c, a, &ah, &bl, &bh, CAST2(compareRC)); - } else { - Assembler::Register tmp(c->client->acquireTemporary()); - moveCR(c, size, b, &tmp); - compareRR(c, size, a, &tmp); - c->client->releaseTemporary(tmp.low); - } + assert(c, BytesPerWord == 8 or size == 4); + + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, size, b, &tmp); + compareRR(c, size, a, &tmp); + c->client->releaseTemporary(tmp.low); } void @@ -1882,6 +1931,9 @@ populateTables() BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); BinaryOperations[INDEX2(Subtract, Register, Register)] = CAST2(subtractRR); + BinaryOperations[INDEX2(LongCompare, Constant, Register)] + = CAST2(longCompareCR); + BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC); BinaryOperations[INDEX2(Compare, Register, Register)] = CAST2(compareRR); From e9c37f5ffdc2d40fb96440215c69ea012c493d41 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Jun 2008 11:00:43 -0600 Subject: [PATCH 10/12] add more tests of operations on longs to Misc.java --- test/Misc.java | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/Misc.java b/test/Misc.java index 81bdbe55a0..28c8e6c16c 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -95,6 +95,15 @@ public class Misc { } public static void main(String[] args) { + { long foo = 25214903884L; + int radix = 10; + expect(foo > 0); + foo /= radix; + expect(foo > 0); + } + + expect(String.valueOf(25214903884l).equals("25214903884")); + { boolean p = true; int[] array = new int[] { 1, 2 }; expect(array[0] == array[p ? 0 : 1]); @@ -192,6 +201,39 @@ public class Misc { expect(~a == ~5L); } + { long a = -25214903884L; + long b = 2; + expect(a >> b == -25214903884L >> 2); + expect(a >>> b == -25214903884L >>> 2); + expect(a << b == -25214903884L << 2); + expect(a + b == -25214903884L + 2L); + expect(a - b == -25214903884L - 2L); + expect(a * b == -25214903884L * 2L); + expect(a / b == -25214903884L / 2L); + expect(a % b == -25214903884L % 2L); + expect((a & b) == (-25214903884L & 2L)); + expect((a | b) == (-25214903884L | 2L)); + expect((a ^ b) == (-25214903884L ^ 2L)); + expect(-a == 25214903884L); + expect(~a == ~-25214903884L); + + a = 25214903884L; + b = 2; + expect(a >> b == 25214903884L >> 2); + expect(a >>> b == 25214903884L >>> 2); + expect(a << b == 25214903884L << 2); + expect(a + b == 25214903884L + 2L); + expect(a - b == 25214903884L - 2L); + expect(a * b == 25214903884L * 2L); + expect(a / b == 25214903884L / 2L); + expect(a % b == 25214903884L % 2L); + expect((a & b) == (25214903884L & 2L)); + expect((a | b) == (25214903884L | 2L)); + expect((a ^ b) == (25214903884L ^ 2L)); + expect(-a == -25214903884L); + expect(~a == ~25214903884L); + } + byte2 = 0; expect(byte2 == 0); From 6f5cc9f45f2842d2398ec3c917b8b46f69dfdf1a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Jun 2008 11:09:53 -0600 Subject: [PATCH 11/12] fix unused parameter warning --- src/x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/x86.cpp b/src/x86.cpp index 3e5ec4c17f..2af36d001f 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1762,7 +1762,7 @@ compareCR(Context* c, unsigned size, Assembler::Constant* a, } void -compareCM(Context* c, unsigned size, Assembler::Constant* a, +compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Memory* b) { assert(c, BytesPerWord == 8 or size == 4); From b683d836c3b703cf2770de3435fc501451d3e8cd Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 12 Jun 2008 11:23:20 -0600 Subject: [PATCH 12/12] implement longCompareRR --- src/x86.cpp | 266 ++++++++++++++++++++++++++++------------------------ 1 file changed, 144 insertions(+), 122 deletions(-) diff --git a/src/x86.cpp b/src/x86.cpp index 2af36d001f..0a515f2fba 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1589,128 +1589,6 @@ unsignedShiftRightCR(Context* c, unsigned size, Assembler::Constant* a, doShift(c, unsignedShiftRightRR, 0xe8, size, a, b); } -void -longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, - Assembler::Register* b) -{ - assert(c, size == 8); - - int64_t v = a->value->value(); - - ResolvedPromise negativePromise(-1); - Assembler::Constant negative(&negativePromise); - - ResolvedPromise zeroPromise(0); - Assembler::Constant zero(&zeroPromise); - - ResolvedPromise positivePromise(1); - Assembler::Constant positive(&positivePromise); - - if (BytesPerWord == 8) { - compareCR(c, 8, a, b); - - c->code.append(0x0f); - c->code.append(0x8c); // jl - unsigned less = c->code.length(); - c->code.append4(0); - - c->code.append(0x0f); - c->code.append(0x8f); // jg - unsigned greater = c->code.length(); - c->code.append4(0); - - moveCR(c, 4, &zero, b); - - c->code.append(0xe9); // jmp - unsigned nextFirst = c->code.length(); - c->code.append4(0); - - int32_t lessOffset = c->code.length() - less - 4; - c->code.set(less, &lessOffset, 4); - - moveCR(c, 4, &negative, b); - - c->code.append(0xe9); // jmp - unsigned nextSecond = c->code.length(); - c->code.append4(0); - - int32_t greaterOffset = c->code.length() - greater - 4; - c->code.set(greater, &greaterOffset, 4); - - moveCR(c, 4, &positive, b); - - int32_t nextFirstOffset = c->code.length() - nextFirst - 4; - c->code.set(nextFirst, &nextFirstOffset, 4); - - int32_t nextSecondOffset = c->code.length() - nextSecond - 4; - c->code.set(nextSecond, &nextSecondOffset, 4); - } else { - ResolvedPromise low(v & 0xFFFFFFFF); - Assembler::Constant al(&low); - - ResolvedPromise high((v >> 32) & 0xFFFFFFFF); - Assembler::Constant ah(&high); - - Assembler::Register bh(b->high); - - compareCR(c, 4, &ah, &bh); - - c->code.append(0x0f); - c->code.append(0x8c); // jl - unsigned less = c->code.length(); - c->code.append4(0); - - c->code.append(0x0f); - c->code.append(0x8f); // jg - unsigned greater = c->code.length(); - c->code.append4(0); - - compareCR(c, 4, &al, b); - - c->code.append(0x0f); - c->code.append(0x82); // ja - unsigned above = c->code.length(); - c->code.append4(0); - - c->code.append(0x0f); - c->code.append(0x87); // jb - unsigned below = c->code.length(); - c->code.append4(0); - - moveCR(c, 4, &zero, b); - - c->code.append(0xe9); // jmp - unsigned nextFirst = c->code.length(); - c->code.append4(0); - - int32_t lessOffset = c->code.length() - less - 4; - c->code.set(less, &lessOffset, 4); - - int32_t aboveOffset = c->code.length() - above - 4; - c->code.set(above, &aboveOffset, 4); - - moveCR(c, 4, &negative, b); - - c->code.append(0xe9); // jmp - unsigned nextSecond = c->code.length(); - c->code.append4(0); - - int32_t greaterOffset = c->code.length() - greater - 4; - c->code.set(greater, &greaterOffset, 4); - - int32_t belowOffset = c->code.length() - below - 4; - c->code.set(below, &belowOffset, 4); - - moveCR(c, 4, &positive, b); - - int32_t nextFirstOffset = c->code.length() - nextFirst - 4; - c->code.set(nextFirst, &nextFirstOffset, 4); - - int32_t nextSecondOffset = c->code.length() - nextSecond - 4; - c->code.set(nextSecond, &nextSecondOffset, 4); - } -} - void compareRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) @@ -1828,6 +1706,148 @@ compareRC(Context* c, unsigned size, Assembler::Register* a, c->client->releaseTemporary(tmp.low); } +void +longCompare(Context* c, Assembler::Operand* al, Assembler::Operand* ah, + Assembler::Operand* bl, Assembler::Operand* bh, + BinaryOperationType compare, BinaryOperationType move) +{ + ResolvedPromise negativePromise(-1); + Assembler::Constant negative(&negativePromise); + + ResolvedPromise zeroPromise(0); + Assembler::Constant zero(&zeroPromise); + + ResolvedPromise positivePromise(1); + Assembler::Constant positive(&positivePromise); + + if (BytesPerWord == 8) { + compare(c, 8, al, bl); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + move(c, 4, &zero, bl); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + move(c, 4, &negative, bl); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + move(c, 4, &positive, bl); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } else { + compare(c, 4, ah, bh); + + c->code.append(0x0f); + c->code.append(0x8c); // jl + unsigned less = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x8f); // jg + unsigned greater = c->code.length(); + c->code.append4(0); + + compare(c, 4, al, bl); + + c->code.append(0x0f); + c->code.append(0x82); // ja + unsigned above = c->code.length(); + c->code.append4(0); + + c->code.append(0x0f); + c->code.append(0x87); // jb + unsigned below = c->code.length(); + c->code.append4(0); + + move(c, 4, &zero, bl); + + c->code.append(0xe9); // jmp + unsigned nextFirst = c->code.length(); + c->code.append4(0); + + int32_t lessOffset = c->code.length() - less - 4; + c->code.set(less, &lessOffset, 4); + + int32_t aboveOffset = c->code.length() - above - 4; + c->code.set(above, &aboveOffset, 4); + + move(c, 4, &negative, bl); + + c->code.append(0xe9); // jmp + unsigned nextSecond = c->code.length(); + c->code.append4(0); + + int32_t greaterOffset = c->code.length() - greater - 4; + c->code.set(greater, &greaterOffset, 4); + + int32_t belowOffset = c->code.length() - below - 4; + c->code.set(below, &belowOffset, 4); + + move(c, 4, &positive, bl); + + int32_t nextFirstOffset = c->code.length() - nextFirst - 4; + c->code.set(nextFirst, &nextFirstOffset, 4); + + int32_t nextSecondOffset = c->code.length() - nextSecond - 4; + c->code.set(nextSecond, &nextSecondOffset, 4); + } +} + +void +longCompareCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, size == 8); + + int64_t v = a->value->value(); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + Assembler::Register bh(b->high); + + longCompare(c, &al, &ah, b, &bh, CAST2(compareCR), CAST2(moveCR)); +} + +void +longCompareRR(Context* c, unsigned size UNUSED, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, size == 8); + + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); + + longCompare(c, a, &ah, b, &bh, CAST2(compareRR), CAST2(moveCR)); +} + void populateTables() { @@ -1933,6 +1953,8 @@ populateTables() BinaryOperations[INDEX2(LongCompare, Constant, Register)] = CAST2(longCompareCR); + BinaryOperations[INDEX2(LongCompare, Register, Register)] + = CAST2(longCompareRR); BinaryOperations[INDEX2(Compare, Constant, Register)] = CAST2(compareCR); BinaryOperations[INDEX2(Compare, Register, Constant)] = CAST2(compareRC);