From 5968e9bb4eaca7ee08dac91eb3d621dfdc9ba1f8 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 12 Dec 2012 21:33:17 +0100 Subject: [PATCH] Fix the bit shift and complement operators Take care of some corner cases and make them pass the test suite. Change-Id: Ic83508859800c62681ee873968b475ef81fffb82 Reviewed-by: Simon Hausmann --- qmljs_runtime.h | 22 +++++++++++++--------- qv4codegen.cpp | 6 +++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/qmljs_runtime.h b/qmljs_runtime.h index 263c151..aa2bc4e 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -472,9 +472,9 @@ inline Value __qmljs_compl(Value value, ExecutionContext *ctx) int n; if (value.isConvertibleToInt()) - n = ~value.int_32; + n = value.int_32; else - n = Value::toInteger(__qmljs_to_number(value, ctx)); + n = Value::toInt32(__qmljs_to_number(value, ctx)); return Value::fromInt32(~n); } @@ -588,8 +588,6 @@ inline Value __qmljs_mod(Value left, Value right, ExecutionContext *ctx) return Value::fromDouble(fmod(lval, rval)); } -// ### unsigned shl missing? - inline Value __qmljs_shl(Value left, Value right, ExecutionContext *ctx) { TRACE2(left, right); @@ -618,12 +616,18 @@ inline Value __qmljs_ushr(Value left, Value right, ExecutionContext *ctx) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(uint(left.integerValue()) >> ((uint(right.integerValue()) & 0x1f))); + uint result; + if (Value::integerCompatible(left, right)) { + result = uint(left.integerValue()) >> (uint(right.integerValue()) & 0x1f); + } else { + unsigned lval = Value::toUInt32(__qmljs_to_number(left, ctx)); + unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f; + result = lval >> rval; + } - unsigned lval = Value::toUInt32(__qmljs_to_number(left, ctx)); - unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f; - return Value::fromInt32(lval >> rval); + if (result > INT_MAX) + return Value::fromDouble(result); + return Value::fromInt32(result); } inline Value __qmljs_gt(Value left, Value right, ExecutionContext *ctx) diff --git a/qv4codegen.cpp b/qv4codegen.cpp index fef6b4e..7409a54 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -553,13 +553,13 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right) case IR::OpGt: return _block->CONST(IR::BoolType, c1->value > c2->value); case IR::OpLe: return _block->CONST(IR::BoolType, c1->value <= c2->value); case IR::OpLt: return _block->CONST(IR::BoolType, c1->value < c2->value); - case IR::OpLShift: return _block->CONST(IR::NumberType, int(c1->value) << int(c2->value)); + case IR::OpLShift: return _block->CONST(IR::NumberType, VM::Value::toInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f)); case IR::OpMod: return _block->CONST(IR::NumberType, ::fmod(c1->value, c2->value)); case IR::OpMul: return _block->CONST(IR::NumberType, c1->value * c2->value); case IR::OpOr: return _block->CONST(IR::NumberType, c1->value ? c1->value : c2->value); - case IR::OpRShift: return _block->CONST(IR::NumberType, int(c1->value) >> int(c2->value)); + case IR::OpRShift: return _block->CONST(IR::NumberType, VM::Value::toInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f)); case IR::OpSub: return _block->CONST(IR::NumberType, c1->value - c2->value); - case IR::OpURShift: return _block->CONST(IR::NumberType, unsigned(c1->value) >> int(c2->value)); + case IR::OpURShift: return _block->CONST(IR::NumberType,VM::Value::toUInt32(c1->value) << (VM::Value::toUInt32(c2->value) & 0x1f)); case IR::OpInstanceof: case IR::OpIn: -- 2.7.4