From c66451af37eb3eea958b66268111c9d34820879e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 13 Feb 2013 16:22:10 +0100 Subject: [PATCH] make binops pointer based Change-Id: Ic03e134ba2c0f51f6a72bd875aba1d30eee8fd2d Reviewed-by: Simon Hausmann --- src/v4/llvm_runtime.cpp | 42 +++---- src/v4/moth/qv4instr_moth_p.h | 2 +- src/v4/moth/qv4isel_moth.cpp | 5 +- src/v4/moth/qv4isel_moth_p.h | 2 +- src/v4/moth/qv4vme_moth.cpp | 2 +- src/v4/qmljs_environment.cpp | 5 +- src/v4/qmljs_runtime.cpp | 29 ++--- src/v4/qmljs_runtime.h | 249 +++++++++++++++++++++++------------------- src/v4/qv4codegen.cpp | 6 +- src/v4/qv4isel_llvm.cpp | 2 +- src/v4/qv4isel_llvm_p.h | 2 +- src/v4/qv4isel_masm.cpp | 7 +- src/v4/qv4isel_masm_p.h | 6 +- src/v4/qv4isel_p.cpp | 9 +- src/v4/qv4isel_p.h | 2 +- src/v4/qv4object.cpp | 8 +- 16 files changed, 202 insertions(+), 176 deletions(-) diff --git a/src/v4/llvm_runtime.cpp b/src/v4/llvm_runtime.cpp index c045507..635d9c0 100644 --- a/src/v4/llvm_runtime.cpp +++ b/src/v4/llvm_runtime.cpp @@ -105,107 +105,107 @@ bool __qmljs_llvm_to_boolean(ExecutionContext *ctx, const Value *value) void __qmljs_llvm_bit_and(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_bit_and(*left, *right, ctx); + __qmljs_bit_and(ctx, result, left, right); } void __qmljs_llvm_bit_or(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_bit_or(*left, *right, ctx); + __qmljs_bit_or(ctx, result, left, right); } void __qmljs_llvm_bit_xor(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_bit_xor(*left, *right, ctx); + __qmljs_bit_xor(ctx, result, left, right); } void __qmljs_llvm_add(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_add(*left, *right, ctx); + __qmljs_add(ctx, result, left, right); } void __qmljs_llvm_sub(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_sub(*left, *right, ctx); + __qmljs_sub(ctx, result, left, right); } void __qmljs_llvm_mul(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_mul(*left, *right, ctx); + __qmljs_mul(ctx, result, left, right); } void __qmljs_llvm_div(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_div(*left, *right, ctx); + __qmljs_div(ctx, result, left, right); } void __qmljs_llvm_mod(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_mod(*left, *right, ctx); + __qmljs_mod(ctx, result, left, right); } void __qmljs_llvm_shl(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_shl(*left, *right, ctx); + __qmljs_shl(ctx, result, left, right); } void __qmljs_llvm_shr(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_shr(*left, *right, ctx); + __qmljs_shr(ctx, result, left, right); } void __qmljs_llvm_ushr(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_ushr(*left, *right, ctx); + __qmljs_ushr(ctx, result, left, right); } void __qmljs_llvm_gt(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_gt(*left, *right, ctx); + __qmljs_gt(ctx, result, left, right); } void __qmljs_llvm_lt(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_lt(*left, *right, ctx); + __qmljs_lt(ctx, result, left, right); } void __qmljs_llvm_ge(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_ge(*left, *right, ctx); + __qmljs_ge(ctx, result, left, right); } void __qmljs_llvm_le(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_le(*left, *right, ctx); + __qmljs_le(ctx, result, left, right); } void __qmljs_llvm_eq(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_eq(*left, *right, ctx); + __qmljs_eq(ctx, result, left, right); } void __qmljs_llvm_ne(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_ne(*left, *right, ctx); + __qmljs_ne(ctx, result, left, right); } void __qmljs_llvm_se(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_se(*left, *right, ctx); + __qmljs_se(ctx, result, left, right); } void __qmljs_llvm_sne(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_sne(*left, *right, ctx); + __qmljs_sne(ctx, result, left, right); } void __qmljs_llvm_instanceof(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_instanceof(*left, *right, ctx); + __qmljs_instanceof(ctx, result, left, right); } void __qmljs_llvm_in(ExecutionContext *ctx, Value *result, Value *left, Value *right) { - *result = __qmljs_in(*left, *right, ctx); + __qmljs_in(ctx, result, left, right); } void __qmljs_llvm_uplus(ExecutionContext *ctx, Value *result, const Value *value) diff --git a/src/v4/moth/qv4instr_moth_p.h b/src/v4/moth/qv4instr_moth_p.h index d573713..9c85228 100644 --- a/src/v4/moth/qv4instr_moth_p.h +++ b/src/v4/moth/qv4instr_moth_p.h @@ -406,7 +406,7 @@ union Instr }; struct instr_binop { MOTH_INSTR_HEADER - VM::Value (*alu)(const VM::Value , const VM::Value, VM::ExecutionContext *); + VM::BinOp alu; Param lhs; Param rhs; Param result; diff --git a/src/v4/moth/qv4isel_moth.cpp b/src/v4/moth/qv4isel_moth.cpp index b054f13..d4ff709 100644 --- a/src/v4/moth/qv4isel_moth.cpp +++ b/src/v4/moth/qv4isel_moth.cpp @@ -172,8 +172,7 @@ private: }; #undef DBTC -typedef VM::Value (*ALUFunction)(const VM::Value, const VM::Value, VM::ExecutionContext*); -inline ALUFunction aluOpFunction(IR::AluOp op) +inline VM::BinOp aluOpFunction(IR::AluOp op) { switch (op) { case IR::OpInvalid: @@ -506,7 +505,7 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp * } } -void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) +void InstructionSelection::binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target) { Instruction::Binop binop; binop.alu = aluOpFunction(oper); diff --git a/src/v4/moth/qv4isel_moth_p.h b/src/v4/moth/qv4isel_moth_p.h index 691dca2..89d7a5b 100644 --- a/src/v4/moth/qv4isel_moth_p.h +++ b/src/v4/moth/qv4isel_moth_p.h @@ -74,7 +74,7 @@ protected: virtual void setElement(IR::Expr *source, IR::Temp *targetBase, IR::Temp *targetIndex); virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp); virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp); - virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target); + virtual void binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target); virtual void inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, const QString &targetName); virtual void inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr, IR::Temp *targetBaseTemp, IR::Temp *targetIndexTemp); virtual void inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR::Temp *targetBase, const QString &targetName); diff --git a/src/v4/moth/qv4vme_moth.cpp b/src/v4/moth/qv4vme_moth.cpp index fba5364..05e30a6 100644 --- a/src/v4/moth/qv4vme_moth.cpp +++ b/src/v4/moth/qv4vme_moth.cpp @@ -410,7 +410,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co MOTH_END_INSTR(Unop) MOTH_BEGIN_INSTR(Binop) - VALUE(instr.result) = instr.alu(VALUE(instr.lhs), VALUE(instr.rhs), context); + instr.alu(context, VALUEPTR(instr.result), VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)); MOTH_END_INSTR(Binop) MOTH_BEGIN_INSTR(Ret) diff --git a/src/v4/qmljs_environment.cpp b/src/v4/qmljs_environment.cpp index 0aee96e..1b1a753 100644 --- a/src/v4/qmljs_environment.cpp +++ b/src/v4/qmljs_environment.cpp @@ -506,8 +506,9 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base) void ExecutionContext::inplaceBitOp(Value value, String *name, BinOp op) { Value lhs = getProperty(name); - value = op(lhs, value, this); - setProperty(name, value); + Value result; + op(this, &result, &lhs, &value); + setProperty(name, result); } void ExecutionContext::throwError(Value value) diff --git a/src/v4/qmljs_runtime.cpp b/src/v4/qmljs_runtime.cpp index 985c3dd..c995e4e 100644 --- a/src/v4/qmljs_runtime.cpp +++ b/src/v4/qmljs_runtime.cpp @@ -216,40 +216,41 @@ Value __qmljs_delete_name(ExecutionContext *ctx, String *name) return Value::fromBoolean(ctx->deleteProperty(name)); } -Value __qmljs_add_helper(Value left, Value right, ExecutionContext *ctx) +void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { - Value pleft = __qmljs_to_primitive(left, ctx, PREFERREDTYPE_HINT); - Value pright = __qmljs_to_primitive(right, ctx, PREFERREDTYPE_HINT); + Value pleft = __qmljs_to_primitive(*left, ctx, PREFERREDTYPE_HINT); + Value pright = __qmljs_to_primitive(*right, ctx, PREFERREDTYPE_HINT); if (pleft.isString() || pright.isString()) { if (!pleft.isString()) pleft = __qmljs_to_string(pleft, ctx); if (!pright.isString()) pright = __qmljs_to_string(pright, ctx); String *string = __qmljs_string_concat(ctx, pleft.stringValue(), pright.stringValue()); - return Value::fromString(string); + *result = Value::fromString(string); + return; } double x = __qmljs_to_number(pleft, ctx); double y = __qmljs_to_number(pright, ctx); - return Value::fromDouble(x + y); + *result = Value::fromDouble(x + y); } -Value __qmljs_instanceof(Value left, Value right, ExecutionContext *ctx) +void __qmljs_instanceof(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { - FunctionObject *function = right.asFunctionObject(); + FunctionObject *function = right->asFunctionObject(); if (!function) __qmljs_throw_type_error(ctx); - bool r = function->hasInstance(ctx, left); - return Value::fromBoolean(r); + bool r = function->hasInstance(ctx, *left); + *result = Value::fromBoolean(r); } -Value __qmljs_in(Value left, Value right, ExecutionContext *ctx) +void __qmljs_in(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { - if (!right.isObject()) + if (!right->isObject()) __qmljs_throw_type_error(ctx); - String *s = left.toString(ctx); - bool r = right.objectValue()->__hasProperty__(ctx, s); - return Value::fromBoolean(r); + String *s = left->toString(ctx); + bool r = right->objectValue()->__hasProperty__(ctx, s); + *result = Value::fromBoolean(r); } void __qmljs_inplace_bit_and_name(Value value, String *name, ExecutionContext *ctx) diff --git a/src/v4/qmljs_runtime.h b/src/v4/qmljs_runtime.h index 20389f4..70ac132 100644 --- a/src/v4/qmljs_runtime.h +++ b/src/v4/qmljs_runtime.h @@ -219,31 +219,31 @@ void __qmljs_delete_exception_handler(ExecutionContext *context); Value __qmljs_get_exception(ExecutionContext *context); // binary operators -typedef Value (*BinOp)(Value left, Value right, ExecutionContext *ctx); - -Value __qmljs_instanceof(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_in(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_bit_or(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_bit_xor(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_bit_and(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_add(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_sub(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_mul(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_div(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_mod(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_shl(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_shr(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_ushr(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_gt(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_lt(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_ge(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_le(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_eq(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_ne(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_se(Value left, Value right, ExecutionContext *ctx); -Value __qmljs_sne(Value left, Value right, ExecutionContext *ctx); - -Value __qmljs_add_helper(Value left, Value right, ExecutionContext *ctx); +typedef void (*BinOp)(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); + +void __qmljs_instanceof(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_in(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_bit_or(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_bit_xor(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_bit_and(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_add(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_sub(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_mul(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_div(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_mod(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_shl(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_shr(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_ushr(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_gt(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_lt(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_ge(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_le(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_eq(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_ne(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_se(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); +void __qmljs_sne(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); + +void __qmljs_add_helper(ExecutionContext *ctx, Value *result, const Value *left, const Value *right); void __qmljs_inplace_bit_and_name(Value value, String *name, ExecutionContext *ctx); void __qmljs_inplace_bit_or_name(Value value, String *name, ExecutionContext *ctx); @@ -519,204 +519,225 @@ inline Value __qmljs_not(Value value, ExecutionContext *ctx) } // binary operators -inline Value __qmljs_bit_or(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_bit_or(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(left.integerValue() | right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = Value::fromInt32(left->integerValue() | right->integerValue()); + return; + } - int lval = Value::toInt32(__qmljs_to_number(left, ctx)); - int rval = Value::toInt32(__qmljs_to_number(right, ctx)); - return Value::fromInt32(lval | rval); + int lval = Value::toInt32(__qmljs_to_number(*left, ctx)); + int rval = Value::toInt32(__qmljs_to_number(*right, ctx)); + *result = Value::fromInt32(lval | rval); } -inline Value __qmljs_bit_xor(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_bit_xor(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(left.integerValue() ^ right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = Value::fromInt32(left->integerValue() ^ right->integerValue()); + return; + } - int lval = Value::toInt32(__qmljs_to_number(left, ctx)); - int rval = Value::toInt32(__qmljs_to_number(right, ctx)); - return Value::fromInt32(lval ^ rval); + int lval = Value::toInt32(__qmljs_to_number(*left, ctx)); + int rval = Value::toInt32(__qmljs_to_number(*right, ctx)); + *result = Value::fromInt32(lval ^ rval); } -inline Value __qmljs_bit_and(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_bit_and(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(left.integerValue() & right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = Value::fromInt32(left->integerValue() & right->integerValue()); + return; + } - int lval = Value::toInt32(__qmljs_to_number(left, ctx)); - int rval = Value::toInt32(__qmljs_to_number(right, ctx)); - return Value::fromInt32(lval & rval); + int lval = Value::toInt32(__qmljs_to_number(*left, ctx)); + int rval = Value::toInt32(__qmljs_to_number(*right, ctx)); + *result = Value::fromInt32(lval & rval); } -inline Value __qmljs_add(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_add(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); #ifdef QMLJS_INLINE_MATH - if (Value::integerCompatible(left, right)) - return add_int32(left.integerValue(), right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = add_int32(left->integerValue(), right->integerValue()); + return; + } #endif - if (Value::bothDouble(left, right)) - return Value::fromDouble(left.doubleValue() + right.doubleValue()); + if (Value::bothDouble(*left, *right)) { + *result = Value::fromDouble(left->doubleValue() + right->doubleValue()); + return; + } - return __qmljs_add_helper(left, right, ctx); + __qmljs_add_helper(ctx, result, left, right); } -inline Value __qmljs_sub(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_sub(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); #ifdef QMLJS_INLINE_MATH - if (Value::integerCompatible(left, right)) - return sub_int32(left.integerValue(), right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = sub_int32(left->integerValue(), right->integerValue()); + return; + } #endif - double lval = __qmljs_to_number(left, ctx); - double rval = __qmljs_to_number(right, ctx); - return Value::fromDouble(lval - rval); + double lval = __qmljs_to_number(*left, ctx); + double rval = __qmljs_to_number(*right, ctx); + *result = Value::fromDouble(lval - rval); } -inline Value __qmljs_mul(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_mul(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); #ifdef QMLJS_INLINE_MATH - if (Value::integerCompatible(left, right)) - return mul_int32(left.integerValue(), right.integerValue()); + if (Value::integerCompatible(*left, *right)) { + *result = mul_int32(left->integerValue(), right->integerValue()); + return; + } #endif - double lval = __qmljs_to_number(left, ctx); - double rval = __qmljs_to_number(right, ctx); - return Value::fromDouble(lval * rval); + double lval = __qmljs_to_number(*left, ctx); + double rval = __qmljs_to_number(*right, ctx); + *result = Value::fromDouble(lval * rval); } -inline Value __qmljs_div(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_div(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - double lval = __qmljs_to_number(left, ctx); - double rval = __qmljs_to_number(right, ctx); - return Value::fromDouble(lval / rval); + double lval = __qmljs_to_number(*left, ctx); + double rval = __qmljs_to_number(*right, ctx); + *result = Value::fromDouble(lval / rval); } -inline Value __qmljs_mod(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_mod(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right) && right.integerValue() != 0) - return Value::fromInt32(left.integerValue() % right.integerValue()); + if (Value::integerCompatible(*left, *right) && right->integerValue() != 0) { + *result = Value::fromInt32(left->integerValue() % right->integerValue()); + return; + } - double lval = __qmljs_to_number(left, ctx); - double rval = __qmljs_to_number(right, ctx); - return Value::fromDouble(fmod(lval, rval)); + double lval = __qmljs_to_number(*left, ctx); + double rval = __qmljs_to_number(*right, ctx); + *result = Value::fromDouble(fmod(lval, rval)); } -inline Value __qmljs_shl(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_shl(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(left.integerValue() << ((uint(right.integerValue()) & 0x1f))); + if (Value::integerCompatible(*left, *right)) { + *result = Value::fromInt32(left->integerValue() << ((uint(right->integerValue()) & 0x1f))); + return; + } - int lval = Value::toInt32(__qmljs_to_number(left, ctx)); - unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f; - return Value::fromInt32(lval << rval); + int lval = Value::toInt32(__qmljs_to_number(*left, ctx)); + unsigned rval = Value::toUInt32(__qmljs_to_number(*right, ctx)) & 0x1f; + *result = Value::fromInt32(lval << rval); } -inline Value __qmljs_shr(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_shr(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - if (Value::integerCompatible(left, right)) - return Value::fromInt32(left.integerValue() >> ((uint(right.integerValue()) & 0x1f))); + if (Value::integerCompatible(*left, *right)) { + *result = Value::fromInt32(left->integerValue() >> ((uint(right->integerValue()) & 0x1f))); + return; + } - int lval = Value::toInt32(__qmljs_to_number(left, ctx)); - unsigned rval = Value::toUInt32(__qmljs_to_number(right, ctx)) & 0x1f; - return Value::fromInt32(lval >> rval); + int lval = Value::toInt32(__qmljs_to_number(*left, ctx)); + unsigned rval = Value::toUInt32(__qmljs_to_number(*right, ctx)) & 0x1f; + *result = Value::fromInt32(lval >> rval); } -inline Value __qmljs_ushr(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_ushr(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - uint result; - if (Value::integerCompatible(left, right)) { - result = uint(left.integerValue()) >> (uint(right.integerValue()) & 0x1f); + uint res; + if (Value::integerCompatible(*left, *right)) { + res = 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; + res = lval >> rval; } - if (result > INT_MAX) - return Value::fromDouble(result); - return Value::fromInt32(result); + if (res > INT_MAX) + *result = Value::fromDouble(res); + else + *result = Value::fromInt32(res); } -inline Value __qmljs_gt(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_gt(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(__qmljs_cmp_gt(left, right, ctx)); + *result = Value::fromBoolean(__qmljs_cmp_gt(*left, *right, ctx)); } -inline Value __qmljs_lt(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_lt(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(__qmljs_cmp_lt(left, right, ctx)); + *result = Value::fromBoolean(__qmljs_cmp_lt(*left, *right, ctx)); } -inline Value __qmljs_ge(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_ge(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(__qmljs_cmp_ge(left, right, ctx)); + *result = Value::fromBoolean(__qmljs_cmp_ge(*left, *right, ctx)); } -inline Value __qmljs_le(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_le(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(__qmljs_cmp_le(left, right, ctx)); + *result = Value::fromBoolean(__qmljs_cmp_le(*left, *right, ctx)); } -inline Value __qmljs_eq(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_eq(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(__qmljs_cmp_eq(left, right, ctx)); + *result = Value::fromBoolean(__qmljs_cmp_eq(*left, *right, ctx)); } -inline Value __qmljs_ne(Value left, Value right, ExecutionContext *ctx) +inline void __qmljs_ne(ExecutionContext *ctx, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - return Value::fromBoolean(!__qmljs_cmp_eq(left, right, ctx)); + *result = Value::fromBoolean(!__qmljs_cmp_eq(*left, *right, ctx)); } -inline Value __qmljs_se(Value left, Value right, ExecutionContext *) +inline void __qmljs_se(ExecutionContext *, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - bool r = __qmljs_strict_equal(left, right); - return Value::fromBoolean(r); + bool r = __qmljs_strict_equal(*left, *right); + *result = Value::fromBoolean(r); } -inline Value __qmljs_sne(Value left, Value right, ExecutionContext *) +inline void __qmljs_sne(ExecutionContext *, Value *result, const Value *left, const Value *right) { TRACE2(left, right); - bool r = ! __qmljs_strict_equal(left, right); - return Value::fromBoolean(r); + bool r = ! __qmljs_strict_equal(*left, *right); + *result = Value::fromBoolean(r); } inline Bool __qmljs_cmp_gt(Value left, Value right, ExecutionContext *ctx) @@ -839,7 +860,8 @@ inline Bool __qmljs_cmp_instanceof(Value left, Value right, ExecutionContext *ct { TRACE2(left, right); - Value v = __qmljs_instanceof(left, right, ctx); + Value v; + __qmljs_instanceof(ctx, &v, &left, &right); return v.booleanValue(); } @@ -847,7 +869,8 @@ inline uint __qmljs_cmp_in(Value left, Value right, ExecutionContext *ctx) { TRACE2(left, right); - Value v = __qmljs_in(left, right, ctx); + Value v; + __qmljs_in(ctx, &v, &left, &right); return v.booleanValue(); } diff --git a/src/v4/qv4codegen.cpp b/src/v4/qv4codegen.cpp index 7faf22c..d82f1b1 100644 --- a/src/v4/qv4codegen.cpp +++ b/src/v4/qv4codegen.cpp @@ -683,13 +683,13 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right) } } - if (!left->asTemp() && !left->asConst()) { + if (!left->asTemp()) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), left); left = _block->TEMP(t); } - if (!right->asTemp() && !right->asConst()) { + if (!right->asTemp()) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), right); right = _block->TEMP(t); @@ -716,7 +716,7 @@ void Codegen::move(IR::Expr *target, IR::Expr *source, IR::AluOp op) _block->MOVE(_block->TEMP(t), source); source = _block->TEMP(t); } - if (!target->asTemp() && source->asConst()) { + if (source->asConst() && (!target->asTemp() || op != IR::OpInvalid)) { unsigned t = _block->newTemp(); _block->MOVE(_block->TEMP(t), source); source = _block->TEMP(t); diff --git a/src/v4/qv4isel_llvm.cpp b/src/v4/qv4isel_llvm.cpp index 6131e30..744f500 100644 --- a/src/v4/qv4isel_llvm.cpp +++ b/src/v4/qv4isel_llvm.cpp @@ -684,7 +684,7 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp * } } -void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) +void InstructionSelection::binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target) { const char *opName = 0; switch (oper) { diff --git a/src/v4/qv4isel_llvm_p.h b/src/v4/qv4isel_llvm_p.h index 24ed317..36b1c21 100644 --- a/src/v4/qv4isel_llvm_p.h +++ b/src/v4/qv4isel_llvm_p.h @@ -118,7 +118,7 @@ public: // methods from InstructionSelection: virtual void setElement(IR::Expr *source, IR::Temp *targetBase, IR::Temp *targetIndex); virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp); virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp); - virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target); + virtual void binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target); virtual void inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, const QString &targetName); virtual void inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr, IR::Temp *targetBaseTemp, IR::Temp *targetIndexTemp); virtual void inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR::Temp *targetBase, const QString &targetName); diff --git a/src/v4/qv4isel_masm.cpp b/src/v4/qv4isel_masm.cpp index 2f8a5d2..7de1b08 100644 --- a/src/v4/qv4isel_masm.cpp +++ b/src/v4/qv4isel_masm.cpp @@ -251,7 +251,7 @@ const Assembler::BinaryOperationInfo Assembler::binaryOperations[QQmlJS::IR::Las NULL_OP // OpOr }; -void Assembler::generateBinOp(IR::AluOp operation, IR::Temp* target, IR::Expr* left, IR::Expr* right) +void Assembler::generateBinOp(IR::AluOp operation, IR::Temp* target, IR::Temp *left, IR::Temp *right) { const BinaryOperationInfo& info = binaryOperations[operation]; if (!info.fallbackImplementation) { @@ -332,7 +332,8 @@ void Assembler::generateBinOp(IR::AluOp operation, IR::Temp* target, IR::Expr* l } // Fallback - generateFunctionCallImp(target, info.name, info.fallbackImplementation, left, right, ContextRegister); + generateFunctionCallImp(Assembler::Void, info.name, info.fallbackImplementation, ContextRegister, + Assembler::PointerToValue(target), Assembler::PointerToValue(left), Assembler::PointerToValue(right)); if (binOpFinished.isSet()) binOpFinished.link(this); @@ -748,7 +749,7 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp * Assembler::ContextRegister); } -void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) +void InstructionSelection::binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target) { _as->generateBinOp(oper, target, leftSource, rightSource); } diff --git a/src/v4/qv4isel_masm_p.h b/src/v4/qv4isel_masm_p.h index ee9573e..fb075cd 100644 --- a/src/v4/qv4isel_masm_p.h +++ b/src/v4/qv4isel_masm_p.h @@ -531,14 +531,14 @@ public: struct BinaryOperationInfo { const char *name; - VM::Value (*fallbackImplementation)(const VM::Value, const VM::Value, VM::ExecutionContext *); + VM::BinOp fallbackImplementation; MemRegBinOp inlineMemRegOp; ImmRegBinOp inlineImmRegOp; }; static const BinaryOperationInfo binaryOperations[QQmlJS::IR::LastAluOp + 1]; - void generateBinOp(IR::AluOp operation, IR::Temp* target, IR::Expr* left, IR::Expr* right); + void generateBinOp(IR::AluOp operation, IR::Temp* target, IR::Temp* left, IR::Temp* right); Jump inline_add32(Address addr, RegisterID reg) { @@ -717,7 +717,7 @@ protected: virtual void setElement(IR::Expr *source, IR::Temp *targetBase, IR::Temp *targetIndex); virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp); virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp); - virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target); + virtual void binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target); virtual void inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, const QString &targetName); virtual void inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr, IR::Temp *targetBaseTemp, IR::Temp *targetIndexTemp); virtual void inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR::Temp *targetBase, const QString &targetName); diff --git a/src/v4/qv4isel_p.cpp b/src/v4/qv4isel_p.cpp index 35cd826..8c79c32 100644 --- a/src/v4/qv4isel_p.cpp +++ b/src/v4/qv4isel_p.cpp @@ -124,9 +124,8 @@ void InstructionSelection::visitMove(IR::Move *s) return; } } else if (IR::Binop *b = s->source->asBinop()) { - if ((b->left->asTemp() || b->left->asConst()) - && (b->right->asTemp() || b->right->asConst())) { - binop(b->op, b->left, b->right, t); + if (b->left->asTemp() && b->right->asTemp()) { + binop(b->op, b->left->asTemp(), b->right->asTemp(), t); return; } } else if (IR::Call *c = s->source->asCall()) { @@ -160,8 +159,8 @@ void InstructionSelection::visitMove(IR::Move *s) } else { // inplace assignment, e.g. x += 1, ++x, ... if (IR::Temp *t = s->target->asTemp()) { - if (s->source->asTemp() || s->source->asConst()) { - binop(s->op, t, s->source, t); + if (s->source->asTemp()) { + binop(s->op, t, s->source->asTemp(), t); return; } } else if (IR::Name *n = s->target->asName()) { diff --git a/src/v4/qv4isel_p.h b/src/v4/qv4isel_p.h index cb04f0c..9e55a97 100644 --- a/src/v4/qv4isel_p.h +++ b/src/v4/qv4isel_p.h @@ -134,7 +134,7 @@ public: // to implement by subclasses: virtual void setElement(IR::Expr *source, IR::Temp *targetBase, IR::Temp *targetIndex) = 0; virtual void copyValue(IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0; virtual void unop(IR::AluOp oper, IR::Temp *sourceTemp, IR::Temp *targetTemp) = 0; - virtual void binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Temp *target) = 0; + virtual void binop(IR::AluOp oper, IR::Temp *leftSource, IR::Temp *rightSource, IR::Temp *target) = 0; virtual void inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, const QString &targetName) = 0; virtual void inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr, IR::Temp *targetBaseTemp, IR::Temp *targetIndexTemp) = 0; virtual void inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR::Temp *targetBase, const QString &targetName) = 0; diff --git a/src/v4/qv4object.cpp b/src/v4/qv4object.cpp index a6259f2..e28a5fb 100644 --- a/src/v4/qv4object.cpp +++ b/src/v4/qv4object.cpp @@ -141,7 +141,8 @@ void Object::inplaceBinOp(Value rhs, String *name, BinOp op, ExecutionContext *c { bool hasProperty = false; Value v = __get__(ctx, name, &hasProperty); - Value result = op(v, rhs, ctx); + Value result; + op(ctx, &result, &v, &rhs); __put__(ctx, name, result); } @@ -151,8 +152,9 @@ void Object::inplaceBinOp(Value rhs, Value index, BinOp op, ExecutionContext *ct if (idx < UINT_MAX) { bool hasProperty = false; Value v = __get__(ctx, idx, &hasProperty); - v = op(v, rhs, ctx); - __put__(ctx, idx, v); + Value result; + op(ctx, &result, &v, &rhs); + __put__(ctx, idx, result); return; } String *name = index.toString(ctx); -- 2.7.4