aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-06-22 11:57:11 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-06-22 17:24:14 +0000
commitcb0e5faa05b63a3db6239a911edaccf75a4ad1af (patch)
tree14dba331821b11d6b33f9309b12f153a21074a42
parentfb2f1089a017bf2c3cd83454cb06077d72fdaa6e (diff)
Fix language/expressions/equals/coerce-symbol-to-prim-return-prim.js with JIT
Use the same method for comparing values for the JIT as well as the interpreter, so that the test passes with interpreter as well as the JIT. Change-Id: I2e0249d8e915c816a64adc922839cb71f0e065db Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp131
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp120
2 files changed, 122 insertions, 129 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 4e782fea00..8759a72074 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1720,24 +1720,133 @@ ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right)
return Encode(r);
}
+struct LazyScope
+{
+ ExecutionEngine *engine = nullptr;
+ Value *stackMark = nullptr;
+ ~LazyScope() {
+ if (engine)
+ engine->jsStackTop = stackMark;
+ }
+ template <typename T>
+ void set(Value **scopedValue, T value, ExecutionEngine *e) {
+ if (!engine) {
+ engine = e;
+ stackMark = engine->jsStackTop;
+ }
+ if (!*scopedValue)
+ *scopedValue = e->jsAlloca(1);
+ **scopedValue = value;
+ }
+};
+
Bool Runtime::method_compareEqual(const Value &left, const Value &right)
{
TRACE2(left, right);
- if (left.rawValue() == right.rawValue())
- // NaN != NaN
- return !left.isNaN();
+ Value lhs = left;
+ Value rhs = right;
- if (left.type() == right.type()) {
- if (left.isDouble() && left.doubleValue() == 0 && right.doubleValue() == 0)
- return true; // this takes care of -0 == +0 (which obviously have different raw values)
- if (!left.isManaged())
- return false;
- if (left.isString() == right.isString())
- return left.cast<Managed>()->isEqualTo(right.cast<Managed>());
+#ifndef V4_BOOTSTRAP
+ LazyScope scope;
+ Value *lhsGuard = nullptr;
+ Value *rhsGuard = nullptr;
+#endif
+
+ redo:
+ if (lhs.asReturnedValue() == rhs.asReturnedValue())
+ return !lhs.isNaN();
+
+ int lt = lhs.quickType();
+ int rt = rhs.quickType();
+ if (rt < lt) {
+ qSwap(lhs, rhs);
+ qSwap(lt, rt);
}
- return RuntimeHelpers::equalHelper(left, right);
+ switch (lt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ if (lhs.isUndefined())
+ return rhs.isNullOrUndefined();
+ Q_FALLTHROUGH();
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3:
+ // LHS: Managed
+ switch (rt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ if (rhs.isUndefined())
+ return false;
+ Q_FALLTHROUGH();
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3: {
+#ifndef V4_BOOTSTRAP
+ // RHS: Managed
+ Heap::Base *l = lhs.m();
+ Heap::Base *r = rhs.m();
+ Q_ASSERT(l);
+ Q_ASSERT(r);
+ if (l->internalClass->vtable->isStringOrSymbol == r->internalClass->vtable->isStringOrSymbol)
+ return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs));
+ if (l->internalClass->vtable->isStringOrSymbol) {
+ scope.set(&rhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT), r->internalClass->engine);
+ rhs = rhsGuard->asReturnedValue();
+ break;
+ } else {
+ Q_ASSERT(r->internalClass->vtable->isStringOrSymbol);
+ scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), l->internalClass->engine);
+ lhs = lhsGuard->asReturnedValue();
+ break;
+ }
+#endif
+ return false;
+ }
+ case QV4::Value::QT_Empty:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Null:
+ return false;
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ rhs = Primitive::fromDouble(rhs.int_32());
+ // fall through
+ default: // double
+#ifndef V4_BOOTSTRAP
+ if (lhs.m()->internalClass->vtable->isStringOrSymbol) {
+ return lhs.m()->internalClass->vtable->isString ? (RuntimeHelpers::toNumber(lhs) == rhs.doubleValue()) : false;
+ } else {
+ scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), lhs.m()->internalClass->engine);
+ lhs = lhsGuard->asReturnedValue();
+ }
+#else
+ Q_UNIMPLEMENTED();
+#endif
+ }
+ goto redo;
+ case QV4::Value::QT_Empty:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Null:
+ return rhs.isNull();
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ switch (rt) {
+ case QV4::Value::QT_ManagedOrUndefined:
+ case QV4::Value::QT_ManagedOrUndefined1:
+ case QV4::Value::QT_ManagedOrUndefined2:
+ case QV4::Value::QT_ManagedOrUndefined3:
+ case QV4::Value::QT_Empty:
+ case QV4::Value::QT_Null:
+ Q_UNREACHABLE();
+ case QV4::Value::QT_Bool:
+ case QV4::Value::QT_Int:
+ return lhs.int_32() == rhs.int_32();
+ default: // double
+ return lhs.int_32() == rhs.doubleValue();
+ }
+ default: // double
+ Q_ASSERT(rhs.isDouble());
+ return lhs.doubleValue() == rhs.doubleValue();
+ }
}
ReturnedValue Runtime::method_equal(const Value &left, const Value &right)
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 547c3fce7a..18aae4bd32 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -362,122 +362,6 @@ static inline const QV4::Value &constant(Function *function, int index)
return function->compilationUnit->constants[index];
}
-struct LazyScope
-{
- ExecutionEngine *engine = nullptr;
- Value *stackMark = nullptr;
- ~LazyScope() {
- if (engine)
- engine->jsStackTop = stackMark;
- }
- template <typename T>
- void set(Value **scopedValue, T value, ExecutionEngine *e) {
- if (!engine) {
- engine = e;
- stackMark = engine->jsStackTop;
- }
- if (!*scopedValue)
- *scopedValue = e->jsAlloca(1);
- **scopedValue = value;
- }
-};
-
-static bool compareEqual(QV4::Value lhs, QV4::Value rhs)
-{
- LazyScope scope;
- Value *lhsGuard = nullptr;
- Value *rhsGuard = nullptr;
-
- redo:
- if (lhs.asReturnedValue() == rhs.asReturnedValue())
- return !lhs.isNaN();
-
- int lt = lhs.quickType();
- int rt = rhs.quickType();
- if (rt < lt) {
- qSwap(lhs, rhs);
- qSwap(lt, rt);
- }
-
- switch (lt) {
- case QV4::Value::QT_ManagedOrUndefined:
- if (lhs.isUndefined())
- return rhs.isNullOrUndefined();
- Q_FALLTHROUGH();
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3:
- // LHS: Managed
- switch (rt) {
- case QV4::Value::QT_ManagedOrUndefined:
- if (rhs.isUndefined())
- return false;
- Q_FALLTHROUGH();
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3: {
- // RHS: Managed
- Heap::Base *l = lhs.m();
- Heap::Base *r = rhs.m();
- Q_ASSERT(l);
- Q_ASSERT(r);
- if (l->internalClass->vtable->isStringOrSymbol == r->internalClass->vtable->isStringOrSymbol)
- return static_cast<QV4::Managed &>(lhs).isEqualTo(&static_cast<QV4::Managed &>(rhs));
- if (l->internalClass->vtable->isStringOrSymbol) {
- scope.set(&rhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(rhs), PREFERREDTYPE_HINT), r->internalClass->engine);
- rhs = rhsGuard->asReturnedValue();
- break;
- } else {
- Q_ASSERT(r->internalClass->vtable->isStringOrSymbol);
- scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), l->internalClass->engine);
- lhs = lhsGuard->asReturnedValue();
- break;
- }
- return false;
- }
- case QV4::Value::QT_Empty:
- Q_UNREACHABLE();
- case QV4::Value::QT_Null:
- return false;
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- rhs = Primitive::fromDouble(rhs.int_32());
- // fall through
- default: // double
- if (lhs.m()->internalClass->vtable->isStringOrSymbol) {
- return lhs.m()->internalClass->vtable->isString ? (RuntimeHelpers::toNumber(lhs) == rhs.doubleValue()) : false;
- } else {
- scope.set(&lhsGuard, RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT), lhs.m()->internalClass->engine);
- lhs = lhsGuard->asReturnedValue();
- }
- }
- goto redo;
- case QV4::Value::QT_Empty:
- Q_UNREACHABLE();
- case QV4::Value::QT_Null:
- return rhs.isNull();
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- switch (rt) {
- case QV4::Value::QT_ManagedOrUndefined:
- case QV4::Value::QT_ManagedOrUndefined1:
- case QV4::Value::QT_ManagedOrUndefined2:
- case QV4::Value::QT_ManagedOrUndefined3:
- case QV4::Value::QT_Empty:
- case QV4::Value::QT_Null:
- Q_UNREACHABLE();
- case QV4::Value::QT_Bool:
- case QV4::Value::QT_Int:
- return lhs.int_32() == rhs.int_32();
- default: // double
- return lhs.int_32() == rhs.doubleValue();
- }
- default: // double
- Q_ASSERT(rhs.isDouble());
- return lhs.doubleValue() == rhs.doubleValue();
- }
-}
-
static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
{
redo:
@@ -1177,7 +1061,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code)
acc = Encode(left.int_32() == ACC.int_32());
} else {
STORE_ACC();
- acc = Encode(compareEqual(left, accumulator));
+ acc = Encode(bool(Runtime::method_compareEqual(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpEq)
@@ -1188,7 +1072,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code)
acc = Encode(bool(left.int_32() != ACC.int_32()));
} else {
STORE_ACC();
- acc = Encode(!compareEqual(left, accumulator));
+ acc = Encode(bool(!Runtime::method_compareEqual(left, accumulator)));
CHECK_EXCEPTION;
}
MOTH_END_INSTR(CmpNe)