V4 JIT: clean-up conversion functions and add toUInt32.
authorErik Verbruggen <erik.verbruggen@me.com>
Fri, 11 Oct 2013 13:21:57 +0000 (15:21 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 12 Oct 2013 11:14:02 +0000 (13:14 +0200)
Change-Id: I7ac685145fa41db2a0e02c4d15d1d287d80621f8
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/compiler/qv4isel_masm.cpp
src/qml/compiler/qv4isel_masm_p.h
src/qml/compiler/qv4regalloc.cpp

index 4ca4f82..461186a 100644 (file)
@@ -1491,6 +1491,9 @@ void InstructionSelection::convertTypeToDouble(V4IR::Temp *source, V4IR::Temp *t
         convertUIntToDouble(source, target);
         break;
     case V4IR::UndefinedType:
+        _as->loadDouble(_as->loadTempAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
+        _as->storeDouble(Assembler::FPGpr0, target);
+        break;
     case V4IR::StringType:
     case V4IR::VarType: {
         // load the tag:
@@ -1666,46 +1669,86 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
 
     } break;
     case V4IR::DoubleType: {
-        Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
         Assembler::Jump success =
-                _as->branchTruncateDoubleToInt32(reg, Assembler::ReturnValueRegister,
+                _as->branchTruncateDoubleToInt32(_as->toDoubleRegister(source),
+                                                 Assembler::ReturnValueRegister,
                                                  Assembler::BranchIfTruncateSuccessful);
         generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_int32,
                              Assembler::PointerToValue(source));
         success.link(_as);
         _as->storeInt32(Assembler::ReturnValueRegister, target);
     } break;
-    case V4IR::UInt32Type: {
-        Assembler::RegisterID reg = _as->toUInt32Register(source, Assembler::ReturnValueRegister);
-        Assembler::Jump easy = _as->branch32(Assembler::GreaterThanOrEqual, reg, Assembler::TrustedImm32(0));
-        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
-                             Assembler::PointerToValue(source));
-        easy.link(_as);
-        _as->storeInt32(Assembler::ReturnValueRegister, target);
-    } break;
+    case V4IR::UInt32Type:
+        _as->storeInt32(_as->toUInt32Register(source, Assembler::ReturnValueRegister), target);
+        break;
     case V4IR::NullType:
     case V4IR::UndefinedType:
         _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
         _as->storeInt32(Assembler::ReturnValueRegister, target);
         break;
-    case V4IR::StringType:
-        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
-                             _as->loadTempAddress(Assembler::ScratchRegister, source));
-        _as->storeInt32(Assembler::ReturnValueRegister, target);
-        break;
     case V4IR::BoolType:
         _as->storeInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
         break;
+    case V4IR::StringType:
     default:
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_int32,
+                             _as->loadTempAddress(Assembler::ScratchRegister, source));
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
         break;
     } // switch (source->type)
 }
 
 void InstructionSelection::convertTypeToUInt32(V4IR::Temp *source, V4IR::Temp *target)
 {
-    generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
-                         Assembler::PointerToValue(source));
-    _as->storeUInt32(Assembler::ReturnValueRegister, target);
+    switch (source->type) {
+    case V4IR::VarType: {
+        // load the tag:
+        Assembler::Pointer tagAddr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+        tagAddr.offset += 4;
+        _as->load32(tagAddr, Assembler::ScratchRegister);
+
+        // check if it's an int32:
+        Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
+                                                Assembler::TrustedImm32(Value::_Integer_Type));
+        Assembler::Pointer addr = _as->loadTempAddress(Assembler::ScratchRegister, source);
+        _as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
+        Assembler::Jump intDone = _as->jump();
+
+        // not an int:
+        isNoInt.link(_as);
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
+                             _as->loadTempAddress(Assembler::ScratchRegister, source));
+        _as->storeInt32(Assembler::ReturnValueRegister, target);
+
+        intDone.link(_as);
+    } break;
+    case V4IR::DoubleType: {
+        Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
+        Assembler::Jump success =
+                _as->branchTruncateDoubleToUint32(reg, Assembler::ReturnValueRegister,
+                                                  Assembler::BranchIfTruncateSuccessful);
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_double_to_uint32,
+                             Assembler::PointerToValue(source));
+        success.link(_as);
+        _as->storeUInt32(Assembler::ReturnValueRegister, target);
+    } break;
+    case V4IR::NullType:
+    case V4IR::UndefinedType:
+        _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
+        _as->storeUInt32(Assembler::ReturnValueRegister, target);
+        break;
+    case V4IR::StringType:
+        generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_value_to_uint32,
+                             Assembler::PointerToValue(source));
+        _as->storeUInt32(Assembler::ReturnValueRegister, target);
+        break;
+    case V4IR::SInt32Type:
+    case V4IR::BoolType:
+        _as->storeUInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+        break;
+    default:
+        break;
+    } // switch (source->type)
 }
 
 void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
index 3dfd979..a0f81a7 100644 (file)
@@ -1294,6 +1294,8 @@ public:
 
     RegisterID toUInt32Register(Pointer addr, RegisterID scratchReg)
     {
+        Q_ASSERT(addr.base != scratchReg);
+
         // The UInt32 representation in QV4::Value is really convoluted. See also storeUInt32.
         Pointer tagAddr = addr;
         tagAddr.offset += 4;
@@ -1480,30 +1482,25 @@ private:
 
     void convertUIntToDouble(V4IR::Temp *source, V4IR::Temp *target)
     {
+        Assembler::RegisterID tmpReg = Assembler::ScratchRegister;
+        Assembler::RegisterID reg = _as->toInt32Register(source, tmpReg);
+
         if (target->kind == V4IR::Temp::PhysicalRegister) {
-            _as->convertUInt32ToDouble(_as->toInt32Register(source, Assembler::ScratchRegister),
-                                       (Assembler::FPRegisterID) target->index,
-                                       Assembler::ScratchRegister);
-        } else if (target->kind == V4IR::Temp::StackSlot) {
-            _as->convertUInt32ToDouble(_as->toUInt32Register(source, Assembler::ScratchRegister),
-                                      Assembler::FPGpr0, Assembler::ScratchRegister);
-            _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
+            _as->convertUInt32ToDouble(reg, (Assembler::FPRegisterID) target->index, tmpReg);
         } else {
-            Q_UNIMPLEMENTED();
+            _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg),
+                                      Assembler::FPGpr0, tmpReg);
+            _as->storeDouble(Assembler::FPGpr0, _as->stackSlotPointer(target));
         }
     }
 
     void convertIntToBool(V4IR::Temp *source, V4IR::Temp *target)
     {
-        Assembler::RegisterID reg = Assembler::ScratchRegister;
-        if (target->kind == V4IR::Temp::PhysicalRegister) {
-            reg = _as->toInt32Register(source, reg);
-        } else if (target->kind == V4IR::Temp::StackSlot) {
-            _as->move(_as->toInt32Register(source, reg), reg);
-        } else {
-            Q_UNIMPLEMENTED();
-        }
+        Assembler::RegisterID reg = target->kind == V4IR::Temp::PhysicalRegister
+                ? (Assembler::RegisterID) target->index
+                : Assembler::ScratchRegister;
 
+        _as->move(_as->toInt32Register(source, reg), reg);
         _as->compare32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0), reg);
         _as->storeBool(reg, target);
     }
index 210ae68..b4ec0f3 100644 (file)
@@ -242,27 +242,27 @@ protected: // IRDecoder
 
         switch (target->type) {
         case DoubleType:
-            if (source->type == UInt32Type) {
-                sourceReg = Use::MustHaveRegister;
+            switch (source->type) {
+            case UInt32Type:
+            case SInt32Type:
+            case NullType:
+            case UndefinedType:
+            case BoolType:
                 needsCall = false;
                 break;
-            }
-        case SInt32Type:
-            if (source->type == DoubleType || source->type == UInt32Type) {
-                // this might need a call
+            default:
                 break;
             }
-#if 0 // TODO: change masm to generate code
-        case UInt32Type:
-#endif
+            break;
         case BoolType:
             switch (source->type) {
             case UInt32Type:
-            case BoolType:
-            case DoubleType:
                 sourceReg = Use::MustHaveRegister;
                 needsCall = false;
                 break;
+            case DoubleType:
+            case UndefinedType:
+            case NullType:
             case SInt32Type:
                 needsCall = false;
                 break;
@@ -270,6 +270,28 @@ protected: // IRDecoder
                 break;
             }
             break;
+        case SInt32Type:
+            switch (source->type) {
+            case UInt32Type:
+            case NullType:
+            case UndefinedType:
+            case BoolType:
+                needsCall = false;
+            default:
+                break;
+            }
+            break;
+        case UInt32Type:
+            switch (source->type) {
+            case SInt32Type:
+            case NullType:
+            case UndefinedType:
+            case BoolType:
+                needsCall = false;
+            default:
+                break;
+            }
+            break;
         default:
             break;
         }