js/src/jit/x64/BaselineIC-x64.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "jit/BaselineHelpers.h"
     8 #include "jit/BaselineIC.h"
    10 using namespace js;
    11 using namespace js::jit;
    13 namespace js {
    14 namespace jit {
    16 // ICCompare_Int32
    18 bool
    19 ICCompare_Int32::Compiler::generateStubCode(MacroAssembler &masm)
    20 {
    21     // Guard that R0 is an integer and R1 is an integer.
    22     Label failure;
    23     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    24     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
    26     // Directly compare the int32 payload of R0 and R1.
    27     Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
    28     masm.mov(ImmWord(0), ScratchReg);
    29     masm.cmpl(R0.valueReg(), R1.valueReg());
    30     masm.setCC(cond, ScratchReg);
    32     // Box the result and return
    33     masm.boxValue(JSVAL_TYPE_BOOLEAN, ScratchReg, R0.valueReg());
    34     EmitReturnFromIC(masm);
    36     // Failure case - jump to next stub
    37     masm.bind(&failure);
    38     EmitStubGuardFailure(masm);
    40     return true;
    41 }
    43 // ICBinaryArith_Int32
    45 bool
    46 ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
    47 {
    48     // Guard that R0 is an integer and R1 is an integer.
    49     Label failure;
    50     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    51     masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
    53     Label revertRegister, maybeNegZero;
    54     switch(op_) {
    55       case JSOP_ADD:
    56         masm.unboxInt32(R0, ExtractTemp0);
    57         // Just jump to failure on overflow. R0 and R1 are preserved, so we can just jump to
    58         // the next stub.
    59         masm.addl(R1.valueReg(), ExtractTemp0);
    60         masm.j(Assembler::Overflow, &failure);
    62         // Box the result
    63         masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
    64         break;
    65       case JSOP_SUB:
    66         masm.unboxInt32(R0, ExtractTemp0);
    67         masm.subl(R1.valueReg(), ExtractTemp0);
    68         masm.j(Assembler::Overflow, &failure);
    69         masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
    70         break;
    71       case JSOP_MUL:
    72         masm.unboxInt32(R0, ExtractTemp0);
    73         masm.imull(R1.valueReg(), ExtractTemp0);
    74         masm.j(Assembler::Overflow, &failure);
    76         masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &maybeNegZero);
    78         masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
    79         break;
    80       case JSOP_DIV:
    81       {
    82         JS_ASSERT(R2.scratchReg() == rax);
    83         JS_ASSERT(R0.valueReg() != rdx);
    84         JS_ASSERT(R1.valueReg() != rdx);
    85         masm.unboxInt32(R0, eax);
    86         masm.unboxInt32(R1, ExtractTemp0);
    88         // Prevent division by 0.
    89         masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
    91         // Prevent negative 0 and -2147483648 / -1.
    92         masm.branch32(Assembler::Equal, eax, Imm32(INT32_MIN), &failure);
    94         Label notZero;
    95         masm.branch32(Assembler::NotEqual, eax, Imm32(0), &notZero);
    96         masm.branchTest32(Assembler::Signed, ExtractTemp0, ExtractTemp0, &failure);
    97         masm.bind(&notZero);
    99         // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
   100         masm.cdq();
   101         masm.idiv(ExtractTemp0);
   103         // A remainder implies a double result.
   104         masm.branchTest32(Assembler::NonZero, edx, edx, &failure);
   106         masm.boxValue(JSVAL_TYPE_INT32, eax, R0.valueReg());
   107         break;
   108       }
   109       case JSOP_MOD:
   110       {
   111         JS_ASSERT(R2.scratchReg() == rax);
   112         JS_ASSERT(R0.valueReg() != rdx);
   113         JS_ASSERT(R1.valueReg() != rdx);
   114         masm.unboxInt32(R0, eax);
   115         masm.unboxInt32(R1, ExtractTemp0);
   117         // x % 0 always results in NaN.
   118         masm.branchTest32(Assembler::Zero, ExtractTemp0, ExtractTemp0, &failure);
   120         // Prevent negative 0 and -2147483648 % -1.
   121         masm.branchTest32(Assembler::Zero, eax, Imm32(0x7fffffff), &failure);
   123         // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
   124         masm.cdq();
   125         masm.idiv(ExtractTemp0);
   127         // Fail when we would need a negative remainder.
   128         Label done;
   129         masm.branchTest32(Assembler::NonZero, edx, edx, &done);
   130         masm.orl(ExtractTemp0, eax);
   131         masm.branchTest32(Assembler::Signed, eax, eax, &failure);
   133         masm.bind(&done);
   134         masm.boxValue(JSVAL_TYPE_INT32, edx, R0.valueReg());
   135         break;
   136       }
   137       case JSOP_BITOR:
   138         // We can overide R0, because the instruction is unfailable.
   139         // Because the tag bits are the same, we don't need to retag.
   140         masm.orq(R1.valueReg(), R0.valueReg());
   141         break;
   142       case JSOP_BITXOR:
   143         masm.xorl(R1.valueReg(), R0.valueReg());
   144         masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
   145         break;
   146       case JSOP_BITAND:
   147         masm.andq(R1.valueReg(), R0.valueReg());
   148         break;
   149       case JSOP_LSH:
   150         masm.unboxInt32(R0, ExtractTemp0);
   151         masm.unboxInt32(R1, ecx); // Unboxing R1 to ecx, clobbers R0.
   152         masm.shll_cl(ExtractTemp0);
   153         masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
   154         break;
   155       case JSOP_RSH:
   156         masm.unboxInt32(R0, ExtractTemp0);
   157         masm.unboxInt32(R1, ecx);
   158         masm.sarl_cl(ExtractTemp0);
   159         masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
   160         break;
   161       case JSOP_URSH:
   162         if (!allowDouble_)
   163             masm.movq(R0.valueReg(), ScratchReg);
   165         masm.unboxInt32(R0, ExtractTemp0);
   166         masm.unboxInt32(R1, ecx); // This clobbers R0
   168         masm.shrl_cl(ExtractTemp0);
   169         masm.testl(ExtractTemp0, ExtractTemp0);
   170         if (allowDouble_) {
   171             Label toUint;
   172             masm.j(Assembler::Signed, &toUint);
   174             // Box and return.
   175             masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
   176             EmitReturnFromIC(masm);
   178             masm.bind(&toUint);
   179             masm.convertUInt32ToDouble(ExtractTemp0, ScratchFloatReg);
   180             masm.boxDouble(ScratchFloatReg, R0);
   181         } else {
   182             masm.j(Assembler::Signed, &revertRegister);
   183             masm.boxValue(JSVAL_TYPE_INT32, ExtractTemp0, R0.valueReg());
   184         }
   185         break;
   186       default:
   187         MOZ_ASSUME_UNREACHABLE("Unhandled op in BinaryArith_Int32");
   188     }
   190     // Return from stub.
   191     EmitReturnFromIC(masm);
   193     if (op_ == JSOP_MUL) {
   194         masm.bind(&maybeNegZero);
   196         // Result is -0 if exactly one of lhs or rhs is negative.
   197         masm.movl(R0.valueReg(), ScratchReg);
   198         masm.orl(R1.valueReg(), ScratchReg);
   199         masm.j(Assembler::Signed, &failure);
   201         // Result is +0.
   202         masm.moveValue(Int32Value(0), R0);
   203         EmitReturnFromIC(masm);
   204     }
   206     // Revert the content of R0 in the fallible >>> case.
   207     if (op_ == JSOP_URSH && !allowDouble_) {
   208         masm.bind(&revertRegister);
   209         // Restore tag and payload.
   210         masm.movq(ScratchReg, R0.valueReg());
   211         // Fall through to failure.
   212     }
   213     // Failure case - jump to next stub
   214     masm.bind(&failure);
   215     EmitStubGuardFailure(masm);
   217     return true;
   218 }
   220 bool
   221 ICUnaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
   222 {
   223     Label failure;
   224     masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
   226     switch (op) {
   227       case JSOP_BITNOT:
   228         masm.notl(R0.valueReg());
   229         break;
   230       case JSOP_NEG:
   231         // Guard against 0 and MIN_INT, both result in a double.
   232         masm.branchTest32(Assembler::Zero, R0.valueReg(), Imm32(0x7fffffff), &failure);
   233         masm.negl(R0.valueReg());
   234         break;
   235       default:
   236         MOZ_ASSUME_UNREACHABLE("Unexpected op");
   237     }
   239     masm.tagValue(JSVAL_TYPE_INT32, R0.valueReg(), R0);
   241     EmitReturnFromIC(masm);
   243     masm.bind(&failure);
   244     EmitStubGuardFailure(masm);
   245     return true;
   246 }
   248 } // namespace jit
   249 } // namespace js

mercurial