diff --git a/makefile b/makefile index 08287d14f9..9408df6d9c 100755 --- a/makefile +++ b/makefile @@ -214,6 +214,9 @@ openjdk-extra-cflags = -fvisibility=hidden bootimage-cflags = -DTARGET_BYTES_PER_WORD=$(pointer-size) +developer-dir := $(shell if test -d /Developer; then echo /Developer; \ + else echo /Applications/Xcode.app/Contents/Developer; fi) + ifeq ($(build-arch),powerpc) ifneq ($(arch),$(build-arch)) bootimage-cflags += -DTARGET_OPPOSITE_ENDIAN @@ -254,7 +257,7 @@ ifeq ($(arch),arm) ifneq ($(arch),$(build-arch)) ifeq ($(platform),darwin) - ios-bin = /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin + ios-bin = $(developer-dir)/Platforms/iPhoneOS.platform/Developer/usr/bin cxx = $(ios-bin)/g++ cc = $(ios-bin)/gcc ar = $(ios-bin)/ar @@ -322,7 +325,7 @@ ifeq ($(platform),darwin) converter-cflags += -DOPPOSITE_ENDIAN endif flags = -arch armv7 -isysroot \ - /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/ + $(developer-dir)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/ openjdk-extra-cflags += $(flags) cflags += $(flags) asmflags += $(flags) diff --git a/src/builtin.cpp b/src/builtin.cpp index eed2508564..f7f2c12d29 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -327,3 +327,177 @@ Avian_avian_Singleton_getLong (t, reinterpret_cast(arguments[0]), arguments[1]), 8); return v; } + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_allocateMemory +(Thread* t, object, uintptr_t* arguments) +{ + void* p = malloc(arguments[1]); + if (p) { + return reinterpret_cast(p); + } else { + throwNew(t, Machine::OutOfMemoryErrorType); + } +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_freeMemory +(Thread*, object, uintptr_t* arguments) +{ + void* p = reinterpret_cast(arguments[1]); + if (p) { + free(p); + } +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_setMemory +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int64_t count; memcpy(&count, arguments + 3, 8); + int8_t v = arguments[5]; + + memset(reinterpret_cast(p), v, count); +} + +// NB: The following primitive get/put methods are only used by the +// interpreter. The JIT/AOT compiler implements them as intrinsics, +// so these versions will be ignored. + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putByte__JB +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int8_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putShort__JS +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int16_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putChar__JC +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putShort__JS(t, method, arguments); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putInt__JI +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int32_t v = arguments[3]; + + *reinterpret_cast(p) = v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putFloat__JF +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putInt__JI(t, method, arguments); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putLong__JJ +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int64_t v; memcpy(&v, arguments + 3, 8); + + *reinterpret_cast(p) = v; +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putDouble__JD +(Thread* t, object method, uintptr_t* arguments) +{ + Avian_sun_misc_Unsafe_putLong__JJ(t, method, arguments); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_putAddress__JJ +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + int64_t v; memcpy(&v, arguments + 3, 8); + + *reinterpret_cast(p) = v; +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getByte__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getShort__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getChar__J +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getShort__J(t, method, arguments); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getInt__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getFloat__J +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getInt__J(t, method, arguments); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getLong__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getDouble__J +(Thread* t, object method, uintptr_t* arguments) +{ + return Avian_sun_misc_Unsafe_getLong__J(t, method, arguments); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_sun_misc_Unsafe_getAddress__J +(Thread*, object, uintptr_t* arguments) +{ + int64_t p; memcpy(&p, arguments + 1, 8); + + return *reinterpret_cast(p); +} diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index e1fde3ba5d..713bea71ec 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2230,19 +2230,40 @@ pipeAvailable(int fd, int* available) } object -fieldForOffset(Thread* t, object o, unsigned offset) +fieldForOffsetInClass(Thread* t, object c, unsigned offset) { - object table = classFieldTable(t, objectClass(t, o)); - for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { - object field = objectArrayBody(t, table, i); - if ((fieldFlags(t, field) & ACC_STATIC) == 0 - and fieldOffset(t, field) == offset) - { + object super = classSuper(t, c); + if (super) { + object field = fieldForOffsetInClass(t, super, offset); + if (field) { return field; } } - - abort(t); + + object table = classFieldTable(t, c); + if (table) { + for (unsigned i = 0; i < objectArrayLength(t, table); ++i) { + object field = objectArrayBody(t, table, i); + if ((fieldFlags(t, field) & ACC_STATIC) == 0 + and fieldOffset(t, field) == offset) + { + return field; + } + } + } + + return 0; +} + +object +fieldForOffset(Thread* t, object o, unsigned offset) +{ + object field = fieldForOffsetInClass(t, objectClass(t, o), offset); + if (field) { + return field; + } else { + abort(t); + } } } // namespace local @@ -2645,118 +2666,6 @@ Avian_sun_misc_Unsafe_compareAndSwapLong #endif } -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_allocateMemory -(Thread* t, object, uintptr_t* arguments) -{ - void* p = malloc(arguments[1]); - if (p) { - return reinterpret_cast(p); - } else { - throwNew(t, Machine::OutOfMemoryErrorType); - } -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_freeMemory -(Thread*, object, uintptr_t* arguments) -{ - void* p = reinterpret_cast(arguments[1]); - if (p) { - free(p); - } -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_setMemory -(Thread*, object, uintptr_t* arguments) -{ - object base = reinterpret_cast(arguments[1]); - int64_t offset; memcpy(&offset, arguments + 2, 8); - int64_t count; memcpy(&count, arguments + 4, 8); - int8_t v = arguments[6]; - - memset(base - ? &cast(base, offset) - : reinterpret_cast(offset), v, count); -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putByte__JB -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - int8_t v = arguments[3]; - - *reinterpret_cast(p) = v; -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putShort__JS -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - int16_t v = arguments[3]; - - *reinterpret_cast(p) = v; -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putLong__JJ -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - int64_t v; memcpy(&v, arguments + 3, 8); - - *reinterpret_cast(p) = v; -} - -extern "C" JNIEXPORT void JNICALL -Avian_sun_misc_Unsafe_putInt__JI -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - int32_t v = arguments[3]; - - *reinterpret_cast(p) = v; -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getByte__J -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - - return *reinterpret_cast(p); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getInt__J -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - - return *reinterpret_cast(p); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getLong__J -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - - return *reinterpret_cast(p); -} - -extern "C" JNIEXPORT int64_t JNICALL -Avian_sun_misc_Unsafe_getFloat__J -(Thread*, object, uintptr_t* arguments) -{ - int64_t p; memcpy(&p, arguments + 1, 8); - - return *reinterpret_cast(p); -} - extern "C" JNIEXPORT int64_t JNICALL Avian_sun_misc_Unsafe_pageSize (Thread*, object, uintptr_t*) @@ -2841,6 +2750,19 @@ Avian_sun_misc_Unsafe_copyMemory memcpy(dst, src, count); } +Avian_sun_misc_Unsafe_monitorEnter +(Thread* t, object, uintptr_t* arguments) +{ + acquire(t, reinterpret_cast(arguments[1])); +} + +extern "C" JNIEXPORT void JNICALL +Avian_sun_misc_Unsafe_monitorExit +(Thread* t, object, uintptr_t* arguments) +{ + release(t, reinterpret_cast(arguments[1])); +} + namespace { namespace local { @@ -3427,8 +3349,21 @@ EXPORT(JVM_IsInterrupted)(Thread* t, jobject thread, jboolean clear) return run(t, jvmIsInterrupted, arguments); } +uint64_t +jvmHoldsLock(Thread* t, uintptr_t* arguments) +{ + object m = objectMonitor(t, *reinterpret_cast(arguments[0]), false); + + return m and monitorOwner(t, m) == t; +} + extern "C" JNIEXPORT jboolean JNICALL -EXPORT(JVM_HoldsLock)(Thread*, jclass, jobject) { abort(); } +EXPORT(JVM_HoldsLock)(Thread* t, jclass, jobject o) +{ + uintptr_t arguments[] = { reinterpret_cast(o) }; + + return run(t, jvmHoldsLock, arguments); +} extern "C" JNIEXPORT void JNICALL EXPORT(JVM_DumpAllStacks)(Thread*, jclass) { abort(); } diff --git a/src/compile.cpp b/src/compile.cpp index 214cc7ba2c..2b415588db 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3809,6 +3809,13 @@ floatBranch(MyThread* t, Frame* frame, object code, unsigned& ip, return true; } +Compiler::Operand* +popLongAddress(Frame* frame) +{ + return TargetBytesPerWord == 8 ? frame->popLong() : frame->c->load + (8, 8, frame->popLong(), TargetBytesPerWord); +} + bool intrinsic(MyThread* t, Frame* frame, object target) { @@ -3837,6 +3844,127 @@ intrinsic(MyThread* t, Frame* frame, object target) return true; } } + } else if (UNLIKELY(MATCH(className, "sun/misc/Unsafe"))) { + Compiler* c = frame->c; + if (MATCH(methodName(t, target), "getByte") + and MATCH(methodSpec(t, target), "(J)B")) + { + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + frame->pushInt + (c->load + (1, 1, c->memory(address, Compiler::IntegerType, 0, 0, 1), + TargetBytesPerWord)); + return true; + } else if (MATCH(methodName(t, target), "putByte") + and MATCH(methodSpec(t, target), "(JB)V")) + { + Compiler::Operand* value = frame->popInt(); + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + c->store + (TargetBytesPerWord, value, 1, c->memory + (address, Compiler::IntegerType, 0, 0, 1)); + return true; + } else if ((MATCH(methodName(t, target), "getShort") + and MATCH(methodSpec(t, target), "(J)S")) + or (MATCH(methodName(t, target), "getChar") + and MATCH(methodSpec(t, target), "(J)C"))) + { + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + frame->pushInt + (c->load + (2, 2, c->memory(address, Compiler::IntegerType, 0, 0, 1), + TargetBytesPerWord)); + return true; + } else if ((MATCH(methodName(t, target), "putShort") + and MATCH(methodSpec(t, target), "(JS)V")) + or (MATCH(methodName(t, target), "putChar") + and MATCH(methodSpec(t, target), "(JC)V"))) + { + Compiler::Operand* value = frame->popInt(); + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + c->store + (TargetBytesPerWord, value, 2, c->memory + (address, Compiler::IntegerType, 0, 0, 1)); + return true; + } else if ((MATCH(methodName(t, target), "getInt") + and MATCH(methodSpec(t, target), "(J)I")) + or (MATCH(methodName(t, target), "getFloat") + and MATCH(methodSpec(t, target), "(J)F"))) + { + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + frame->pushInt + (c->load + (4, 4, c->memory + (address, MATCH(methodName(t, target), "getInt") + ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1), + TargetBytesPerWord)); + return true; + } else if ((MATCH(methodName(t, target), "putInt") + and MATCH(methodSpec(t, target), "(JI)V")) + or (MATCH(methodName(t, target), "putFloat") + and MATCH(methodSpec(t, target), "(JF)V"))) + { + Compiler::Operand* value = frame->popInt(); + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + c->store + (TargetBytesPerWord, value, 4, c->memory + (address, MATCH(methodName(t, target), "putInt") + ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1)); + return true; + } else if ((MATCH(methodName(t, target), "getLong") + and MATCH(methodSpec(t, target), "(J)J")) + or (MATCH(methodName(t, target), "getDouble") + and MATCH(methodSpec(t, target), "(J)D"))) + { + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + frame->pushLong + (c->load + (8, 8, c->memory + (address, MATCH(methodName(t, target), "getLong") + ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1), + 8)); + return true; + } else if ((MATCH(methodName(t, target), "putLong") + and MATCH(methodSpec(t, target), "(JJ)V")) + or (MATCH(methodName(t, target), "putDouble") + and MATCH(methodSpec(t, target), "(JD)V"))) + { + Compiler::Operand* value = frame->popLong(); + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + c->store + (8, value, 8, c->memory + (address, MATCH(methodName(t, target), "putLong") + ? Compiler::IntegerType : Compiler::FloatType, 0, 0, 1)); + return true; + } else if (MATCH(methodName(t, target), "getAddress") + and MATCH(methodSpec(t, target), "(J)J")) + { + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + frame->pushLong + (c->load + (TargetBytesPerWord, TargetBytesPerWord, + c->memory(address, Compiler::AddressType, 0, 0, 1), 8)); + return true; + } else if (MATCH(methodName(t, target), "putAddress") + and MATCH(methodSpec(t, target), "(JJ)V")) + { + Compiler::Operand* value = frame->popLong(); + Compiler::Operand* address = popLongAddress(frame); + frame->popObject(); + c->store + (8, value, TargetBytesPerWord, c->memory + (address, Compiler::AddressType, 0, 0, 1)); + return true; + } } return false; } @@ -5022,43 +5150,45 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, if (LIKELY(target)) { assert(t, (methodFlags(t, target) & ACC_STATIC) == 0); + + if (not intrinsic(t, frame, target)) { + bool tailCall = isTailCall(t, code, ip, context->method, target); - bool tailCall = isTailCall(t, code, ip, context->method, target); + if (LIKELY(methodVirtual(t, target))) { + unsigned parameterFootprint = methodParameterFootprint(t, target); - if (LIKELY(methodVirtual(t, target))) { - unsigned parameterFootprint = methodParameterFootprint(t, target); + unsigned offset = TargetClassVtable + + (methodOffset(t, target) * TargetBytesPerWord); - unsigned offset = TargetClassVtable - + (methodOffset(t, target) * TargetBytesPerWord); + Compiler::Operand* instance = c->peek(1, parameterFootprint - 1); - Compiler::Operand* instance = c->peek(1, parameterFootprint - 1); + unsigned rSize = resultSize(t, methodReturnCode(t, target)); - unsigned rSize = resultSize(t, methodReturnCode(t, target)); + Compiler::Operand* result = c->stackCall + (c->memory + (c->and_ + (TargetBytesPerWord, c->constant + (TargetPointerMask, Compiler::IntegerType), + c->memory(instance, Compiler::ObjectType, 0, 0, 1)), + Compiler::ObjectType, offset, 0, 1), + tailCall ? Compiler::TailJump : 0, + frame->trace(0, 0), + rSize, + operandTypeForFieldCode(t, methodReturnCode(t, target)), + parameterFootprint); - Compiler::Operand* result = c->stackCall - (c->memory - (c->and_ - (TargetBytesPerWord, c->constant - (TargetPointerMask, Compiler::IntegerType), - c->memory(instance, Compiler::ObjectType, 0, 0, 1)), - Compiler::ObjectType, offset, 0, 1), - tailCall ? Compiler::TailJump : 0, - frame->trace(0, 0), - rSize, - operandTypeForFieldCode(t, methodReturnCode(t, target)), - parameterFootprint); + frame->pop(parameterFootprint); - frame->pop(parameterFootprint); + if (rSize) { + pushReturnValue(t, frame, methodReturnCode(t, target), result); + } + } else { + // OpenJDK generates invokevirtual calls to private methods + // (e.g. readObject and writeObject for serialization), so + // we must handle such cases here. - if (rSize) { - pushReturnValue(t, frame, methodReturnCode(t, target), result); + compileDirectInvoke(t, frame, target, tailCall); } - } else { - // OpenJDK generates invokevirtual calls to private methods - // (e.g. readObject and writeObject for serialization), so - // we must handle such cases here. - - compileDirectInvoke(t, frame, target, tailCall); } } else { PROTECT(t, reference); @@ -6042,6 +6172,10 @@ logCompile(MyThread* t, const void* code, unsigned size, const char* class_, int resolveIpForwards(Context* context, int start, int end) { + if (start < 0) { + start = 0; + } + while (start < end and context->visitTable[start] == 0) { ++ start; } @@ -6056,6 +6190,13 @@ resolveIpForwards(Context* context, int start, int end) int resolveIpBackwards(Context* context, int start, int end) { + Thread* t = context->thread; + if (start >= static_cast + (codeLength(t, methodCode(t, context->method)))) + { + start = codeLength(t, methodCode(t, context->method)) - 1; + } + while (start >= end and context->visitTable[start] == 0) { -- start; } @@ -6139,11 +6280,16 @@ translateExceptionHandlerTable(MyThread* t, Context* context, intptr_t start) exceptionHandlerEnd(oldHandler)); if (LIKELY(handlerStart >= 0)) { + assert(t, handlerStart < static_cast + (codeLength(t, methodCode(t, context->method)))); + int handlerEnd = resolveIpBackwards (context, exceptionHandlerEnd(oldHandler), exceptionHandlerStart(oldHandler)); assert(t, handlerEnd >= 0); + assert(t, handlerEnd < static_cast + (codeLength(t, methodCode(t, context->method)))); intArrayBody(t, newIndex, ni * 3) = c->machineIp(handlerStart)->value() - start; diff --git a/src/interpret.cpp b/src/interpret.cpp index 6e04cd4942..6f3c853ec6 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -758,6 +758,8 @@ interpret3(Thread* t, const int base) object& exception = t->exception; uintptr_t* stack = t->stack; + code = methodCode(t, frameMethod(t, frame)); + if (UNLIKELY(exception)) { goto throw_; } diff --git a/src/x86.cpp b/src/x86.cpp index 28c6dc2bc7..42f6ccf8de 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -1478,7 +1478,8 @@ subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, opcode(c, 0x83, 0xd8 + regCode(b)); c->code.append(v); } else { - abort(c); + opcode(c, 0x81, 0xd8 + regCode(b)); + c->code.append4(v); } } diff --git a/test/Longs.java b/test/Longs.java index 434ee908c9..0472536f60 100644 --- a/test/Longs.java +++ b/test/Longs.java @@ -234,6 +234,54 @@ public class Longs { expect((a ^ 25214903884L) == (2L ^ 25214903884L)); } + { long b = 2; + expect((-281474976710656L) >> b == -281474976710656L >> 2); + expect((-281474976710656L) >>> b == -281474976710656L >>> 2); + expect((-281474976710656L) << b == -281474976710656L << 2); + expect((-281474976710656L) + b == -281474976710656L + 2L); + expect((-281474976710656L) - b == -281474976710656L - 2L); + expect((-281474976710656L) * b == -281474976710656L * 2L); + expect((-281474976710656L) / b == -281474976710656L / 2L); + expect((-281474976710656L) % b == -281474976710656L % 2L); + expect(((-281474976710656L) & b) == (-281474976710656L & 2L)); + expect(((-281474976710656L) | b) == (-281474976710656L | 2L)); + expect(((-281474976710656L) ^ b) == (-281474976710656L ^ 2L)); + + b = 2; + expect(281474976710656L >> b == 281474976710656L >> 2); + expect(281474976710656L >>> b == 281474976710656L >>> 2); + expect(281474976710656L << b == 281474976710656L << 2); + expect(281474976710656L + b == 281474976710656L + 2L); + expect(281474976710656L - b == 281474976710656L - 2L); + expect(281474976710656L * b == 281474976710656L * 2L); + expect(281474976710656L / b == 281474976710656L / 2L); + expect(281474976710656L % b == 281474976710656L % 2L); + expect((281474976710656L & b) == (281474976710656L & 2L)); + expect((281474976710656L | b) == (281474976710656L | 2L)); + expect((281474976710656L ^ b) == (281474976710656L ^ 2L)); + } + + { long a = 2L; + expect(a + (-281474976710656L) == 2L + (-281474976710656L)); + expect(a - (-281474976710656L) == 2L - (-281474976710656L)); + expect(a * (-281474976710656L) == 2L * (-281474976710656L)); + expect(a / (-281474976710656L) == 2L / (-281474976710656L)); + expect(a % (-281474976710656L) == 2L % (-281474976710656L)); + expect((a & (-281474976710656L)) == (2L & (-281474976710656L))); + expect((a | (-281474976710656L)) == (2L | (-281474976710656L))); + expect((a ^ (-281474976710656L)) == (2L ^ (-281474976710656L))); + + a = 2L; + expect(a + 281474976710656L == 2L + 281474976710656L); + expect(a - 281474976710656L == 2L - 281474976710656L); + expect(a * 281474976710656L == 2L * 281474976710656L); + expect(a / 281474976710656L == 2L / 281474976710656L); + expect(a % 281474976710656L == 2L % 281474976710656L); + expect((a & 281474976710656L) == (2L & 281474976710656L)); + expect((a | 281474976710656L) == (2L | 281474976710656L)); + expect((a ^ 281474976710656L) == (2L ^ 281474976710656L)); + } + { long x = 231; expect((x >> 32) == 0); expect((x >>> 32) == 0);