last changes required to get IM functioning (bug 698695,r=jbramley)
authorMarty Rosenberg <mrosenberg@mozilla.com>
Thu, 10 Nov 2011 11:51:12 -0800
changeset 105312 7d978454409ebdaff6e5fcec29ace032e7bb8226
parent 105311 28a531088115eafa38ecc700fe51757bc521f20e
child 105313 00c3477ea630e9ce5715fa5bf714ca42459e716f
push id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherdermozilla-central@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjbramley
bugs698695
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last changes required to get IM functioning (bug 698695,r=jbramley)
js/src/assembler/assembler/MacroAssemblerARM.h
js/src/ion/IonMacroAssembler.cpp
js/src/ion/arm/CodeGenerator-arm.cpp
js/src/ion/arm/LIR-arm.h
js/src/ion/arm/Lowering-arm.cpp
js/src/ion/arm/MacroAssembler-arm.cpp
js/src/ion/arm/Trampoline-arm.cpp
--- a/js/src/assembler/assembler/MacroAssemblerARM.h
+++ b/js/src/assembler/assembler/MacroAssemblerARM.h
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=79:
+n * vim: set ts=8 sw=4 et tw=79:
  *
  * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc.
  * Copyright (C) 2009, 2010 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
--- a/js/src/ion/IonMacroAssembler.cpp
+++ b/js/src/ion/IonMacroAssembler.cpp
@@ -141,25 +141,23 @@ MacroAssembler::setAnyABIArg(uint32 arg,
 }
 
 void
 MacroAssembler::callWithABI(void *fun)
 {
     JS_ASSERT(inCall_);
 
     // Perform argument move resolution now.
-    if (stackAdjust_ >= sizeof(void *)) {
-        enoughMemory_ &= moveResolver_.resolve();
-        if (!enoughMemory_)
-            return;
-
-        MoveEmitter emitter(*this);
-        emitter.emit(moveResolver());
-        emitter.finish();
-    }
+    enoughMemory_ &= moveResolver_.resolve();
+    if (!enoughMemory_)
+        return;
+    
+    MoveEmitter emitter(*this);
+    emitter.emit(moveResolver());
+    emitter.finish();
 
 #ifdef DEBUG
     checkCallAlignment();
 #endif
 
     call(fun);
 }
 
--- a/js/src/ion/arm/CodeGenerator-arm.cpp
+++ b/js/src/ion/arm/CodeGenerator-arm.cpp
@@ -405,16 +405,17 @@ CodeGeneratorARM::visitMulI(LMulI *ins)
           case -1:
               masm.ma_rsb(ToRegister(lhs), Imm32(0), ToRegister(dest));
             break;
           case 0:
               masm.ma_mov(Imm32(0), ToRegister(dest));
             return true; // escape overflow check;
           case 1:
             // nop
+            masm.ma_mov(ToRegister(lhs), ToRegister(dest));
             return true; // escape overflow check;
           case 2:
             masm.ma_add(ToRegister(lhs), ToRegister(lhs), ToRegister(dest), SetCond);
             break;
           default:
 #if 0
             if (!mul->canOverflow() && constant > 0) {
                 // Use shift if cannot overflow and constant is power of 2
@@ -464,21 +465,27 @@ CodeGeneratorARM::visitMulI(LMulI *ins)
             masm.ma_cmp(Imm32(0), ToRegister(lhs));
             if (!bailoutIf(Assembler::Zero, ins->snapshot()))
                 return false;
         }
     }
 
     return true;
 }
-
+extern "C" {
+    extern int __aeabi_idiv(int,int);
+}
 bool
 CodeGeneratorARM::visitDivI(LDivI *ins)
 {
-    JS_NOT_REACHED("codegen for DIVI NYI");
+    masm.setupAlignedABICall(2);
+    masm.setABIArg(0, ToRegister(ins->lhs()));
+    masm.setABIArg(1, ToRegister(ins->rhs()));
+    masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, __aeabi_idiv));
+    masm.finishABICall();
 #if 0
     Register remainder = ToRegister(ins->remainder());
     Register lhs = ToRegister(ins->lhs());
     Register rhs = ToRegister(ins->rhs());
 
     JS_ASSERT(remainder == edx);
     JS_ASSERT(lhs == eax);
 
@@ -582,25 +589,33 @@ CodeGeneratorARM::visitShiftOp(LShiftOp 
           if (rhs->isConstant()) {
                 masm.ma_lsl(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
           } else {
                 masm.ma_lsl(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
           }
             break;
         case JSOP_RSH:
           if (rhs->isConstant()) {
-                masm.ma_asr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
+              if ((ToInt32(rhs) & 0x1f) != 0) {
+                  masm.ma_asr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
+              } else {
+                  masm.ma_mov(ToRegister(lhs), ToRegister(dest));
+              }
           } else {
                 masm.ma_asr(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
           }
             break;
         case JSOP_URSH: {
             MUrsh *ursh = ins->mir()->toUrsh();
             if (rhs->isConstant()) {
-                masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
+                if ((ToInt32(rhs) & 0x1f) != 0) {
+                    masm.ma_lsr(Imm32(ToInt32(rhs) & 0x1F), ToRegister(lhs), ToRegister(dest));
+                } else {
+                    masm.ma_mov(ToRegister(lhs), ToRegister(dest));
+                }
             } else {
                 masm.ma_lsr(ToRegister(rhs), ToRegister(lhs), ToRegister(dest));
             }
 
             // Note: this is an unsigned operation.
             // We don't have a UINT32 type, so we will emulate this with INT32
             // The bit representation of an integer from ToInt32 and ToUint32 are the same.
             // So the inputs are ok.
--- a/js/src/ion/arm/LIR-arm.h
+++ b/js/src/ion/arm/LIR-arm.h
@@ -109,27 +109,43 @@ class LDouble : public LInstructionHelpe
   public:
     LIR_HEADER(Double);
 
     LDouble(const LConstantIndex &cindex) {
         setOperand(0, cindex);
     }
 };
 
-class LDivI : public LBinaryMath<2>
+// LDivI is presently implemented as a proper C function,
+// so it trashes r0, r1, r2 and r3.  The call also trashes lr, and has the
+// ability to trash ip. The function also takes two arguments (dividend in r0,
+// divisor in r1). The LInstruction gets encoded such that the divisor and
+// dividend are passed in their apropriate registers, and are marked as copy
+// so we can modify them (and the function will).
+// The other thre registers that can be trashed are marked as such. For the time
+// being, the link register is not marked as trashed because we never allocate
+// to the link register.
+class LDivI : public LBinaryMath<3>
 {
   public:
     LIR_HEADER(DivI);
 
     LDivI(const LAllocation &lhs, const LAllocation &rhs,
-          const LDefinition &temp1, const LDefinition &temp2) {
+          const LDefinition &temp1, const LDefinition &temp2
+#if 0
+          , const LDefinition &temp3
+#endif
+) {
         setOperand(0, lhs);
         setOperand(1, rhs);
         setTemp(0, temp1);
         setTemp(1, temp2);
+#if 0
+        setTemp(2, temp3);
+#endif
     }
 
     const LDefinition *remainder() {
         return getTemp(0);
     }
 };
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 1>
--- a/js/src/ion/arm/Lowering-arm.cpp
+++ b/js/src/ion/arm/Lowering-arm.cpp
@@ -292,17 +292,19 @@ LIRGeneratorARM::lowerForShift(LInstruct
     }
     return define(ins, mir,
                   LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
 }
 
 bool
 LIRGeneratorARM::lowerDivI(MDiv *div)
 {
-    LDivI *lir = new LDivI(useRegister(div->lhs()), useRegister(div->rhs()), temp(LDefinition::INTEGER), temp(LDefinition::INTEGER));
+    LDivI *lir = new LDivI(useFixed(div->lhs(), r0), useFixed(div->rhs(), r1),
+                           tempFixed(r2), tempFixed(r3)/*, tempFixed(lr)*/);
+    
     return define(lir, div,
                   LDefinition(LDefinition::TypeFrom(div->type()), LDefinition::DEFAULT))
     && assignSnapshot(lir);
 }
 
 bool
 LIRGeneratorARM::visitTableSwitch(MTableSwitch *tableswitch)
 {
--- a/js/src/ion/arm/MacroAssembler-arm.cpp
+++ b/js/src/ion/arm/MacroAssembler-arm.cpp
@@ -921,19 +921,22 @@ MacroAssemblerARM::checkCallAlignment()
     // higher level tag testing code
 Assembler::Condition
 MacroAssemblerARM::compareDoubles(JSOp compare, FloatRegister lhs, FloatRegister rhs)
 {
     ma_vcmp(lhs, rhs);
     as_vmrs(pc);
     switch (compare) {
       case JSOP_LT:
+        as_cmp(ScratchRegister, O2Reg(ScratchRegister), Overflow);
         return Assembler::LessThan;
       case JSOP_LE:
+        as_cmp(ScratchRegister, O2Reg(ScratchRegister), Overflow);
         return Assembler::LessThanOrEqual;
+        // GT and GE are naturally followed by "and not unordered..."
       case JSOP_GT:
         return Assembler::GreaterThan;
       case JSOP_GE:
         return Assembler::GreaterThanOrEqual;
       default:
         JS_NOT_REACHED("Unrecognized comparison operation");
         return Assembler::Equal;
     }
--- a/js/src/ion/arm/Trampoline-arm.cpp
+++ b/js/src/ion/arm/Trampoline-arm.cpp
@@ -192,20 +192,21 @@ IonCompartment::generateArgumentsRectifi
 {
     MacroAssembler masm(cx);
 #if 0
     // ArgumentsRectifierReg contains the |nargs| pushed onto the current frame.
     // Including |this|, there are (|nargs| + 1) arguments to copy.
     JS_ASSERT(ArgumentsRectifierReg == r8);
 
     // Load the number of |undefined|s to push into %rcx.
-    masm.movq(Operand(rsp, offsetof(IonFrameData, calleeToken_)), rax);
-    masm.load16(Operand(rax, offsetof(JSFunction, nargs)), rcx);
-    masm.subq(r8, rcx);
+    masm.ma_ldr(DTRAddr(sp, DtrOffsetImm(offsetof(IonFrameData, calleeToken_))), r1);
+    masm.ma_ldrh(EDTRAddr(r1, EDtrOffsetImm(offsetof(JSFunction, nargs))), r2);
 
+    masm.ma_sub(r2, r8, r2);
+    //CONTINUE HERE
     masm.moveValue(UndefinedValue(), r10);
 
     masm.movq(rsp, rbp); // Save %rsp.
 
     // Push undefined.
     {
         Label undefLoopTop;
         masm.bind(&undefLoopTop);
@@ -325,16 +326,17 @@ GenerateBailoutThunk(MacroAssembler &mas
     // Not Anymore!  pushing both the snapshotoffset as well as the
     // masm.as_sub(sp, sp, Imm8(4));
 
     // Set the old (4-byte aligned) value of the sp as the first argument
     masm.setABIArg(0, sp);
 
     // Sp % 8 == 0
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, Bailout));
+    masm.finishABICall();
     // Common size of a bailout frame.
     uint32 bailoutFrameSize = sizeof(void *) + // frameClass
                               sizeof(double) * FloatRegisters::Total +
                               sizeof(void *) * Registers::Total;
 
     if (frameClass == NO_FRAME_SIZE_CLASS_ID) {
         // Make sure the bailout frame size fits into the offset for a load
         masm.as_dtr(IsLoad, 32, Offset,
@@ -367,16 +369,17 @@ GenerateBailoutThunk(MacroAssembler &mas
     // And make that the second argument
     masm.as_mov(r1, O2Reg(sp));
     // Do the call
     masm.setupAlignedABICall(2);
     // These should be NOPs
     masm.setABIArg(0, r0);
     masm.setABIArg(1, r1);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ThunkToInterpreter));
+    masm.finishABICall();
 
     // Load the value that the interpreter returned *and* return the stack
     // to its previous location
     masm.as_extdtr(IsLoad, 64, true, PostIndex,
                    JSReturnReg_Data, EDtrAddr(sp, EDtrOffImm(8)));
 
     // Test for an exception
     masm.as_cmp(r0, Imm8(0));
@@ -384,16 +387,18 @@ GenerateBailoutThunk(MacroAssembler &mas
     masm.as_dtr(IsLoad, 32, PostIndex, pc, DTRAddr(sp, DtrOffImm(4)));
     masm.bind(&exception);
 
     // Call into HandleException, passing in the top frame prefix
     masm.as_mov(r0, O2Reg(sp));
     masm.setupAlignedABICall(1);
     masm.setABIArg(0,r0);
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, HandleException));
+    masm.finishABICall();
+
     // The return value is how much stack to adjust before returning.
     masm.as_add(sp, sp, O2Reg(r0));
     // We're going to be returning by the ion calling convention, which returns
     // by ??? (for now, I think ldr pc, [sp]!)
     masm.as_dtr(IsLoad, 32, PostIndex, pc, DTRAddr(sp, DtrOffImm(4)));
 }
 
 IonCode *