2008-06-11 Cameron Zwarich <cwzwarich@uwaterloo.ca>
authorcwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jun 2008 19:48:15 +0000 (19:48 +0000)
committercwzwarich@webkit.org <cwzwarich@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jun 2008 19:48:15 +0000 (19:48 +0000)
        Reviewed by Darin.

        Bug 19457: Create fused opcodes for tests and conditional jumps
        <https://bugs.webkit.org/show_bug.cgi?id=19457>

        Add a new jless instruction, and modify the code generator to emit it
        instead of the pair (less, jtrue).

        Gives a 3.6% improvement on SunSpider.

        * VM/CodeBlock.cpp:
        (KJS::CodeBlock::dump):
        * VM/CodeGenerator.cpp:
        (KJS::CodeGenerator::CodeGenerator):
        (KJS::CodeGenerator::emitOpcode):
        (KJS::CodeGenerator::retrieveLastBinaryOp):
        (KJS::CodeGenerator::rewindBinaryOp):
        (KJS::CodeGenerator::emitJump):
        (KJS::CodeGenerator::emitJumpIfTrue):
        (KJS::CodeGenerator::emitJumpIfFalse):
        (KJS::CodeGenerator::emitMove):
        (KJS::CodeGenerator::emitNot):
        (KJS::CodeGenerator::emitEqual):
        (KJS::CodeGenerator::emitNotEqual):
        (KJS::CodeGenerator::emitStrictEqual):
        (KJS::CodeGenerator::emitNotStrictEqual):
        (KJS::CodeGenerator::emitLess):
        (KJS::CodeGenerator::emitLessEq):
        (KJS::CodeGenerator::emitPreInc):
        (KJS::CodeGenerator::emitPreDec):
        (KJS::CodeGenerator::emitPostInc):
        (KJS::CodeGenerator::emitPostDec):
        (KJS::CodeGenerator::emitToJSNumber):
        (KJS::CodeGenerator::emitNegate):
        (KJS::CodeGenerator::emitAdd):
        (KJS::CodeGenerator::emitMul):
        (KJS::CodeGenerator::emitDiv):
        (KJS::CodeGenerator::emitMod):
        (KJS::CodeGenerator::emitSub):
        (KJS::CodeGenerator::emitLeftShift):
        (KJS::CodeGenerator::emitRightShift):
        (KJS::CodeGenerator::emitUnsignedRightShift):
        (KJS::CodeGenerator::emitBitAnd):
        (KJS::CodeGenerator::emitBitXOr):
        (KJS::CodeGenerator::emitBitOr):
        (KJS::CodeGenerator::emitBitNot):
        (KJS::CodeGenerator::emitInstanceOf):
        (KJS::CodeGenerator::emitTypeOf):
        (KJS::CodeGenerator::emitIn):
        (KJS::CodeGenerator::emitLoad):
        (KJS::CodeGenerator::emitNewObject):
        (KJS::CodeGenerator::emitNewArray):
        (KJS::CodeGenerator::emitResolve):
        (KJS::CodeGenerator::emitGetScopedVar):
        (KJS::CodeGenerator::emitPutScopedVar):
        (KJS::CodeGenerator::emitResolveBase):
        (KJS::CodeGenerator::emitResolveWithBase):
        (KJS::CodeGenerator::emitResolveFunction):
        (KJS::CodeGenerator::emitGetById):
        (KJS::CodeGenerator::emitPutById):
        (KJS::CodeGenerator::emitPutGetter):
        (KJS::CodeGenerator::emitPutSetter):
        (KJS::CodeGenerator::emitDeleteById):
        (KJS::CodeGenerator::emitGetByVal):
        (KJS::CodeGenerator::emitPutByVal):
        (KJS::CodeGenerator::emitDeleteByVal):
        (KJS::CodeGenerator::emitPutByIndex):
        (KJS::CodeGenerator::emitNewFunction):
        (KJS::CodeGenerator::emitNewRegExp):
        (KJS::CodeGenerator::emitNewFunctionExpression):
        (KJS::CodeGenerator::emitCall):
        (KJS::CodeGenerator::emitReturn):
        (KJS::CodeGenerator::emitEnd):
        (KJS::CodeGenerator::emitConstruct):
        (KJS::CodeGenerator::emitPushScope):
        (KJS::CodeGenerator::emitPopScope):
        (KJS::CodeGenerator::emitDebugHook):
        (KJS::CodeGenerator::emitComplexJumpScopes):
        (KJS::CodeGenerator::emitJumpScopes):
        (KJS::CodeGenerator::emitNextPropertyName):
        (KJS::CodeGenerator::emitGetPropertyNames):
        (KJS::CodeGenerator::emitCatch):
        (KJS::CodeGenerator::emitThrow):
        (KJS::CodeGenerator::emitNewError):
        (KJS::CodeGenerator::emitJumpSubroutine):
        (KJS::CodeGenerator::emitSubroutineReturn):
        * VM/CodeGenerator.h:
        * VM/Machine.cpp:
        (KJS::Machine::privateExecute):
        * VM/Opcode.cpp:
        (KJS::):
        * VM/Opcode.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@34497 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/VM/CodeBlock.cpp
JavaScriptCore/VM/CodeGenerator.cpp
JavaScriptCore/VM/CodeGenerator.h
JavaScriptCore/VM/Machine.cpp
JavaScriptCore/VM/Opcode.cpp
JavaScriptCore/VM/Opcode.h

index a008bf47eb9f78f09e98424289997d6dc2c4f702..b129d5fdf845bc2ced7701b1b0b069db754a4005 100644 (file)
@@ -1,3 +1,98 @@
+2008-06-11  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
+
+        Reviewed by Darin.
+
+        Bug 19457: Create fused opcodes for tests and conditional jumps
+        <https://bugs.webkit.org/show_bug.cgi?id=19457>
+
+        Add a new jless instruction, and modify the code generator to emit it
+        instead of the pair (less, jtrue).
+
+        Gives a 3.6% improvement on SunSpider.
+
+        * VM/CodeBlock.cpp:
+        (KJS::CodeBlock::dump):
+        * VM/CodeGenerator.cpp:
+        (KJS::CodeGenerator::CodeGenerator):
+        (KJS::CodeGenerator::emitOpcode):
+        (KJS::CodeGenerator::retrieveLastBinaryOp):
+        (KJS::CodeGenerator::rewindBinaryOp):
+        (KJS::CodeGenerator::emitJump):
+        (KJS::CodeGenerator::emitJumpIfTrue):
+        (KJS::CodeGenerator::emitJumpIfFalse):
+        (KJS::CodeGenerator::emitMove):
+        (KJS::CodeGenerator::emitNot):
+        (KJS::CodeGenerator::emitEqual):
+        (KJS::CodeGenerator::emitNotEqual):
+        (KJS::CodeGenerator::emitStrictEqual):
+        (KJS::CodeGenerator::emitNotStrictEqual):
+        (KJS::CodeGenerator::emitLess):
+        (KJS::CodeGenerator::emitLessEq):
+        (KJS::CodeGenerator::emitPreInc):
+        (KJS::CodeGenerator::emitPreDec):
+        (KJS::CodeGenerator::emitPostInc):
+        (KJS::CodeGenerator::emitPostDec):
+        (KJS::CodeGenerator::emitToJSNumber):
+        (KJS::CodeGenerator::emitNegate):
+        (KJS::CodeGenerator::emitAdd):
+        (KJS::CodeGenerator::emitMul):
+        (KJS::CodeGenerator::emitDiv):
+        (KJS::CodeGenerator::emitMod):
+        (KJS::CodeGenerator::emitSub):
+        (KJS::CodeGenerator::emitLeftShift):
+        (KJS::CodeGenerator::emitRightShift):
+        (KJS::CodeGenerator::emitUnsignedRightShift):
+        (KJS::CodeGenerator::emitBitAnd):
+        (KJS::CodeGenerator::emitBitXOr):
+        (KJS::CodeGenerator::emitBitOr):
+        (KJS::CodeGenerator::emitBitNot):
+        (KJS::CodeGenerator::emitInstanceOf):
+        (KJS::CodeGenerator::emitTypeOf):
+        (KJS::CodeGenerator::emitIn):
+        (KJS::CodeGenerator::emitLoad):
+        (KJS::CodeGenerator::emitNewObject):
+        (KJS::CodeGenerator::emitNewArray):
+        (KJS::CodeGenerator::emitResolve):
+        (KJS::CodeGenerator::emitGetScopedVar):
+        (KJS::CodeGenerator::emitPutScopedVar):
+        (KJS::CodeGenerator::emitResolveBase):
+        (KJS::CodeGenerator::emitResolveWithBase):
+        (KJS::CodeGenerator::emitResolveFunction):
+        (KJS::CodeGenerator::emitGetById):
+        (KJS::CodeGenerator::emitPutById):
+        (KJS::CodeGenerator::emitPutGetter):
+        (KJS::CodeGenerator::emitPutSetter):
+        (KJS::CodeGenerator::emitDeleteById):
+        (KJS::CodeGenerator::emitGetByVal):
+        (KJS::CodeGenerator::emitPutByVal):
+        (KJS::CodeGenerator::emitDeleteByVal):
+        (KJS::CodeGenerator::emitPutByIndex):
+        (KJS::CodeGenerator::emitNewFunction):
+        (KJS::CodeGenerator::emitNewRegExp):
+        (KJS::CodeGenerator::emitNewFunctionExpression):
+        (KJS::CodeGenerator::emitCall):
+        (KJS::CodeGenerator::emitReturn):
+        (KJS::CodeGenerator::emitEnd):
+        (KJS::CodeGenerator::emitConstruct):
+        (KJS::CodeGenerator::emitPushScope):
+        (KJS::CodeGenerator::emitPopScope):
+        (KJS::CodeGenerator::emitDebugHook):
+        (KJS::CodeGenerator::emitComplexJumpScopes):
+        (KJS::CodeGenerator::emitJumpScopes):
+        (KJS::CodeGenerator::emitNextPropertyName):
+        (KJS::CodeGenerator::emitGetPropertyNames):
+        (KJS::CodeGenerator::emitCatch):
+        (KJS::CodeGenerator::emitThrow):
+        (KJS::CodeGenerator::emitNewError):
+        (KJS::CodeGenerator::emitJumpSubroutine):
+        (KJS::CodeGenerator::emitSubroutineReturn):
+        * VM/CodeGenerator.h:
+        * VM/Machine.cpp:
+        (KJS::Machine::privateExecute):
+        * VM/Opcode.cpp:
+        (KJS::):
+        * VM/Opcode.h:
+
 2008-06-11  Darin Adler  <darin@apple.com>
 
         Reviewed by Alexey.
index 3f98e22681e030d38fe5c68a88c4857a7a7edb6b..cb82183ca242e527a6ddb96441de568dfbdfd6ea 100644 (file)
@@ -467,6 +467,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printConditionalJump(begin, it, location, "jfalse");
             break;
         }
+        case op_jless: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int offset = (++it)->u.operand;
+            printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset));
+            break;
+        }
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
index cdb6cc6ad74909ed4399d9bb386bc17e9deed01a..a307a28dde1a5978861249d560e97a6a9abdf0ac 100644 (file)
@@ -180,6 +180,7 @@ CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger,
     , m_continueDepth(0)
     , m_nextVar(-1)
     , m_propertyNames(&scopeChain.globalObject()->globalExec()->propertyNames())
+    , m_lastOpcodeID(op_end)
 {
     // Global code can inherit previously defined symbols.
     int size = symbolTable->size() + 1; // + 1 slot for  "this"
@@ -238,6 +239,7 @@ CodeGenerator::CodeGenerator(FunctionBodyNode* functionBody, const Debugger* deb
     , m_continueDepth(0)
     , m_nextVar(-1)
     , m_propertyNames(&scopeChain.globalObject()->globalExec()->propertyNames())
+    , m_lastOpcodeID(op_end)
 {
     const Node::FunctionStack& functionStack = functionBody->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i) {
@@ -285,6 +287,7 @@ CodeGenerator::CodeGenerator(EvalNode* evalNode, const Debugger* debugger, const
     , m_continueDepth(0)
     , m_nextVar(-1)
     , m_propertyNames(&scopeChain.globalObject()->globalExec()->propertyNames())
+    , m_lastOpcodeID(op_end)
 {
     m_codeBlock->numVars = 1; // Allocate space for "this"
 }
@@ -383,16 +386,54 @@ PassRefPtr<LabelID> CodeGenerator::emitLabel(LabelID* l0)
     return l0;
 }
 
+void CodeGenerator::emitOpcode(OpcodeID opcodeID)
+{
+    instructions().append(machine().getOpcode(opcodeID));
+    m_lastOpcodeID = opcodeID;
+}
+
+void CodeGenerator::retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index)
+{
+    ASSERT(instructions().size() >= 4);
+    size_t size = instructions().size();
+    dstIndex = instructions().at(size - 3).u.operand;
+    src1Index = instructions().at(size - 2).u.operand;
+    src2Index = instructions().at(size - 1).u.operand;
+}
+
+void CodeGenerator::rewindBinaryOp()
+{
+    ASSERT(instructions().size() >= 4);
+    instructions().shrink(instructions().size() - 4);
+}
+
 PassRefPtr<LabelID> CodeGenerator::emitJump(LabelID* target)
 {
-    instructions().append(machine().getOpcode(op_jmp));
+    emitOpcode(op_jmp);
     instructions().append(target->offsetFrom(instructions().size()));
     return target;
 }
 
 PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* target)
 {
-    instructions().append(machine().getOpcode(op_jtrue));
+    if (m_lastOpcodeID == op_less) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+        
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+        
+        if (cond->index() == dstIndex) {
+            rewindBinaryOp();
+            emitOpcode(op_jless);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->offsetFrom(instructions().size()));
+            return target;
+        }
+    }
+    
+    emitOpcode(op_jtrue);
     instructions().append(cond->index());
     instructions().append(target->offsetFrom(instructions().size()));
     return target;
@@ -400,7 +441,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpIfTrue(RegisterID* cond, LabelID* tar
 
 PassRefPtr<LabelID> CodeGenerator::emitJumpIfFalse(RegisterID* cond, LabelID* target)
 {
-    instructions().append(machine().getOpcode(op_jfalse));
+    emitOpcode(op_jfalse);
     instructions().append(cond->index());
     instructions().append(target->offsetFrom(instructions().size()));
     return target;
@@ -450,7 +491,7 @@ unsigned CodeGenerator::addRegExp(RegExp* r)
 
 RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_mov));
+    emitOpcode(op_mov);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -458,7 +499,7 @@ RegisterID* CodeGenerator::emitMove(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitNot(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_not));
+    emitOpcode(op_not);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -466,7 +507,7 @@ RegisterID* CodeGenerator::emitNot(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_eq));
+    emitOpcode(op_eq);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -475,7 +516,7 @@ RegisterID* CodeGenerator::emitEqual(RegisterID* dst, RegisterID* src1, Register
 
 RegisterID* CodeGenerator::emitNotEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_neq));
+    emitOpcode(op_neq);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -484,7 +525,7 @@ RegisterID* CodeGenerator::emitNotEqual(RegisterID* dst, RegisterID* src1, Regis
 
 RegisterID* CodeGenerator::emitStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_stricteq));
+    emitOpcode(op_stricteq);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -493,7 +534,7 @@ RegisterID* CodeGenerator::emitStrictEqual(RegisterID* dst, RegisterID* src1, Re
 
 RegisterID* CodeGenerator::emitNotStrictEqual(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_nstricteq));
+    emitOpcode(op_nstricteq);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -502,7 +543,7 @@ RegisterID* CodeGenerator::emitNotStrictEqual(RegisterID* dst, RegisterID* src1,
 
 RegisterID* CodeGenerator::emitLess(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_less));
+    emitOpcode(op_less);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -511,7 +552,7 @@ RegisterID* CodeGenerator::emitLess(RegisterID* dst, RegisterID* src1, RegisterI
 
 RegisterID* CodeGenerator::emitLessEq(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_lesseq));
+    emitOpcode(op_lesseq);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -520,21 +561,21 @@ RegisterID* CodeGenerator::emitLessEq(RegisterID* dst, RegisterID* src1, Registe
 
 RegisterID* CodeGenerator::emitPreInc(RegisterID* srcDst)
 {
-    instructions().append(machine().getOpcode(op_pre_inc));
+    emitOpcode(op_pre_inc);
     instructions().append(srcDst->index());
     return srcDst;
 }
 
 RegisterID* CodeGenerator::emitPreDec(RegisterID* srcDst)
 {
-    instructions().append(machine().getOpcode(op_pre_dec));
+    emitOpcode(op_pre_dec);
     instructions().append(srcDst->index());
     return srcDst;
 }
 
 RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
 {
-    instructions().append(machine().getOpcode(op_post_inc));
+    emitOpcode(op_post_inc);
     instructions().append(dst->index());
     instructions().append(srcDst->index());
     return dst;
@@ -542,7 +583,7 @@ RegisterID* CodeGenerator::emitPostInc(RegisterID* dst, RegisterID* srcDst)
 
 RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
 {
-    instructions().append(machine().getOpcode(op_post_dec));
+    emitOpcode(op_post_dec);
     instructions().append(dst->index());
     instructions().append(srcDst->index());
     return dst;
@@ -550,7 +591,7 @@ RegisterID* CodeGenerator::emitPostDec(RegisterID* dst, RegisterID* srcDst)
 
 RegisterID* CodeGenerator::emitToJSNumber(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_to_jsnumber));
+    emitOpcode(op_to_jsnumber);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -558,7 +599,7 @@ RegisterID* CodeGenerator::emitToJSNumber(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitNegate(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_negate));
+    emitOpcode(op_negate);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -566,7 +607,7 @@ RegisterID* CodeGenerator::emitNegate(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitAdd(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_add));
+    emitOpcode(op_add);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -575,7 +616,7 @@ RegisterID* CodeGenerator::emitAdd(RegisterID* dst, RegisterID* src1, RegisterID
 
 RegisterID* CodeGenerator::emitMul(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_mul));
+    emitOpcode(op_mul);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -584,7 +625,7 @@ RegisterID* CodeGenerator::emitMul(RegisterID* dst, RegisterID* src1, RegisterID
 
 RegisterID* CodeGenerator::emitDiv(RegisterID* dst, RegisterID* dividend, RegisterID* divisor)
 {
-    instructions().append(machine().getOpcode(op_div));
+    emitOpcode(op_div);
     instructions().append(dst->index());
     instructions().append(dividend->index());
     instructions().append(divisor->index());
@@ -593,7 +634,7 @@ RegisterID* CodeGenerator::emitDiv(RegisterID* dst, RegisterID* dividend, Regist
 
 RegisterID* CodeGenerator::emitMod(RegisterID* dst, RegisterID* dividend, RegisterID* divisor)
 {
-    instructions().append(machine().getOpcode(op_mod));
+    emitOpcode(op_mod);
     instructions().append(dst->index());
     instructions().append(dividend->index());
     instructions().append(divisor->index());
@@ -602,7 +643,7 @@ RegisterID* CodeGenerator::emitMod(RegisterID* dst, RegisterID* dividend, Regist
 
 RegisterID* CodeGenerator::emitSub(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_sub));
+    emitOpcode(op_sub);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -611,7 +652,7 @@ RegisterID* CodeGenerator::emitSub(RegisterID* dst, RegisterID* src1, RegisterID
 
 RegisterID* CodeGenerator::emitLeftShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
 {
-    instructions().append(machine().getOpcode(op_lshift));
+    emitOpcode(op_lshift);
     instructions().append(dst->index());
     instructions().append(val->index());
     instructions().append(shift->index());
@@ -620,7 +661,7 @@ RegisterID* CodeGenerator::emitLeftShift(RegisterID* dst, RegisterID* val, Regis
 
 RegisterID* CodeGenerator::emitRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
 {
-    instructions().append(machine().getOpcode(op_rshift));
+    emitOpcode(op_rshift);
     instructions().append(dst->index());
     instructions().append(val->index());
     instructions().append(shift->index());
@@ -629,7 +670,7 @@ RegisterID* CodeGenerator::emitRightShift(RegisterID* dst, RegisterID* val, Regi
 
 RegisterID* CodeGenerator::emitUnsignedRightShift(RegisterID* dst, RegisterID* val, RegisterID* shift)
 {
-    instructions().append(machine().getOpcode(op_urshift));
+    emitOpcode(op_urshift);
     instructions().append(dst->index());
     instructions().append(val->index());
     instructions().append(shift->index());
@@ -638,7 +679,7 @@ RegisterID* CodeGenerator::emitUnsignedRightShift(RegisterID* dst, RegisterID* v
 
 RegisterID* CodeGenerator::emitBitAnd(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_bitand));
+    emitOpcode(op_bitand);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -647,7 +688,7 @@ RegisterID* CodeGenerator::emitBitAnd(RegisterID* dst, RegisterID* src1, Registe
 
 RegisterID* CodeGenerator::emitBitXOr(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_bitxor));
+    emitOpcode(op_bitxor);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -656,7 +697,7 @@ RegisterID* CodeGenerator::emitBitXOr(RegisterID* dst, RegisterID* src1, Registe
 
 RegisterID* CodeGenerator::emitBitOr(RegisterID* dst, RegisterID* src1, RegisterID* src2)
 {
-    instructions().append(machine().getOpcode(op_bitor));
+    emitOpcode(op_bitor);
     instructions().append(dst->index());
     instructions().append(src1->index());
     instructions().append(src2->index());
@@ -665,7 +706,7 @@ RegisterID* CodeGenerator::emitBitOr(RegisterID* dst, RegisterID* src1, Register
 
 RegisterID* CodeGenerator::emitBitNot(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_bitnot));
+    emitOpcode(op_bitnot);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -673,7 +714,7 @@ RegisterID* CodeGenerator::emitBitNot(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base)
 {
-    instructions().append(machine().getOpcode(op_instanceof));
+    emitOpcode(op_instanceof);
     instructions().append(dst->index());
     instructions().append(value->index());
     instructions().append(base->index());
@@ -682,7 +723,7 @@ RegisterID* CodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, Re
 
 RegisterID* CodeGenerator::emitTypeOf(RegisterID* dst, RegisterID* src)
 {
-    instructions().append(machine().getOpcode(op_typeof));
+    emitOpcode(op_typeof);
     instructions().append(dst->index());
     instructions().append(src->index());
     return dst;
@@ -690,7 +731,7 @@ RegisterID* CodeGenerator::emitTypeOf(RegisterID* dst, RegisterID* src)
 
 RegisterID* CodeGenerator::emitIn(RegisterID* dst, RegisterID* property, RegisterID* base)
 {
-    instructions().append(machine().getOpcode(op_in));
+    emitOpcode(op_in);
     instructions().append(dst->index());
     instructions().append(property->index());
     instructions().append(base->index());
@@ -699,7 +740,7 @@ RegisterID* CodeGenerator::emitIn(RegisterID* dst, RegisterID* property, Registe
 
 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, bool b)
 {
-    instructions().append(machine().getOpcode(op_load));
+    emitOpcode(op_load);
     instructions().append(dst->index());
     instructions().append(addConstant(jsBoolean(b)));
     return dst;
@@ -707,7 +748,7 @@ RegisterID* CodeGenerator::emitLoad(RegisterID* dst, bool b)
 
 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, double d)
 {
-    instructions().append(machine().getOpcode(op_load));
+    emitOpcode(op_load);
     instructions().append(dst->index());
     instructions().append(addConstant(jsNumber(d)));
     return dst;
@@ -715,7 +756,7 @@ RegisterID* CodeGenerator::emitLoad(RegisterID* dst, double d)
 
 RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v)
 {
-    instructions().append(machine().getOpcode(op_load));
+    emitOpcode(op_load);
     instructions().append(dst->index());
     instructions().append(addConstant(v));
     return dst;
@@ -723,14 +764,14 @@ RegisterID* CodeGenerator::emitLoad(RegisterID* dst, JSValue* v)
 
 RegisterID* CodeGenerator::emitNewObject(RegisterID* dst)
 {
-    instructions().append(machine().getOpcode(op_new_object));
+    emitOpcode(op_new_object);
     instructions().append(dst->index());
     return dst;
 }
 
 RegisterID* CodeGenerator::emitNewArray(RegisterID* dst)
 {
-    instructions().append(machine().getOpcode(op_new_array));
+    emitOpcode(op_new_array);
     instructions().append(dst->index());
     return dst;
 }
@@ -777,7 +818,7 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper
     int index = 0;
     if (!findScopedProperty(property, index, depth)) {
         // We can't optimise at all :-(
-        instructions().append(machine().getOpcode(op_resolve));
+        emitOpcode(op_resolve);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         return dst;
@@ -786,7 +827,7 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper
     if (index == missingSymbolMarker()) {
         // In this case we are at least able to drop a few scope chains from the
         // lookup chain, although we still need to hash from then on.
-        instructions().append(machine().getOpcode(op_resolve_skip));
+        emitOpcode(op_resolve_skip);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
         instructions().append(depth);
@@ -799,7 +840,7 @@ RegisterID* CodeGenerator::emitResolve(RegisterID* dst, const Identifier& proper
 
 RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index)
 {
-    instructions().append(machine().getOpcode(op_get_scoped_var));
+    emitOpcode(op_get_scoped_var);
     instructions().append(dst->index());
     instructions().append(index);
     instructions().append(depth);
@@ -808,7 +849,7 @@ RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int i
 
 RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_scoped_var));
+    emitOpcode(op_put_scoped_var);
     instructions().append(index);
     instructions().append(depth);
     instructions().append(value->index());
@@ -817,7 +858,7 @@ RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID*
 
 RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
 {
-    instructions().append(machine().getOpcode(op_resolve_base));
+    emitOpcode(op_resolve_base);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     return dst;
@@ -825,7 +866,7 @@ RegisterID* CodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& pr
 
 RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
 {
-    instructions().append(machine().getOpcode(op_resolve_with_base));
+    emitOpcode(op_resolve_with_base);
     instructions().append(baseDst->index());
     instructions().append(propDst->index());
     instructions().append(addConstant(property));
@@ -834,7 +875,7 @@ RegisterID* CodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID*
 
 RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
 {
-    instructions().append(machine().getOpcode(op_resolve_func));
+    emitOpcode(op_resolve_func);
     instructions().append(baseDst->index());
     instructions().append(funcDst->index());
     instructions().append(addConstant(property));
@@ -843,7 +884,7 @@ RegisterID* CodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID*
 
 RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
-    instructions().append(machine().getOpcode(op_get_by_id));
+    emitOpcode(op_get_by_id);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
@@ -852,7 +893,7 @@ RegisterID* CodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const
 
 RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_by_id));
+    emitOpcode(op_put_by_id);
     instructions().append(base->index());
     instructions().append(addConstant(property));
     instructions().append(value->index());
@@ -861,7 +902,7 @@ RegisterID* CodeGenerator::emitPutById(RegisterID* base, const Identifier& prope
 
 RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_getter));
+    emitOpcode(op_put_getter);
     instructions().append(base->index());
     instructions().append(addConstant(property));
     instructions().append(value->index());
@@ -870,7 +911,7 @@ RegisterID* CodeGenerator::emitPutGetter(RegisterID* base, const Identifier& pro
 
 RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_setter));
+    emitOpcode(op_put_setter);
     instructions().append(base->index());
     instructions().append(addConstant(property));
     instructions().append(value->index());
@@ -879,7 +920,7 @@ RegisterID* CodeGenerator::emitPutSetter(RegisterID* base, const Identifier& pro
 
 RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
-    instructions().append(machine().getOpcode(op_del_by_id));
+    emitOpcode(op_del_by_id);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(addConstant(property));
@@ -888,7 +929,7 @@ RegisterID* CodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, con
 
 RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
-    instructions().append(machine().getOpcode(op_get_by_val));
+    emitOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
@@ -897,7 +938,7 @@ RegisterID* CodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, Regis
 
 RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_by_val));
+    emitOpcode(op_put_by_val);
     instructions().append(base->index());
     instructions().append(property->index());
     instructions().append(value->index());
@@ -906,7 +947,7 @@ RegisterID* CodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property,
 
 RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
-    instructions().append(machine().getOpcode(op_del_by_val));
+    emitOpcode(op_del_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     instructions().append(property->index());
@@ -915,7 +956,7 @@ RegisterID* CodeGenerator::emitDeleteByVal(RegisterID* dst, RegisterID* base, Re
 
 RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value)
 {
-    instructions().append(machine().getOpcode(op_put_by_index));
+    emitOpcode(op_put_by_index);
     instructions().append(base->index());
     instructions().append(index);
     instructions().append(value->index());
@@ -924,7 +965,7 @@ RegisterID* CodeGenerator::emitPutByIndex(RegisterID* base, unsigned index, Regi
 
 RegisterID* CodeGenerator::emitNewFunction(RegisterID* r0, FuncDeclNode* n)
 {
-    instructions().append(machine().getOpcode(op_new_func));
+    emitOpcode(op_new_func);
     instructions().append(r0->index());
     instructions().append(addConstant(n));
     return r0;
@@ -932,7 +973,7 @@ RegisterID* CodeGenerator::emitNewFunction(RegisterID* r0, FuncDeclNode* n)
 
 RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 {
-    instructions().append(machine().getOpcode(op_new_regexp));
+    emitOpcode(op_new_regexp);
     instructions().append(dst->index());
     instructions().append(addRegExp(regExp));
     return dst;
@@ -941,7 +982,7 @@ RegisterID* CodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 
 RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
-    instructions().append(machine().getOpcode(op_new_func_exp));
+    emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
     instructions().append(addConstant(n));
     return r0;
@@ -977,7 +1018,7 @@ RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Register
         emitNode(argv.last().get(), n);
     }
 
-    instructions().append(machine().getOpcode(opcodeID));
+    emitOpcode(opcodeID);
     instructions().append(dst->index());
     instructions().append(func->index());
     instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it.
@@ -988,14 +1029,14 @@ RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Register
 
 RegisterID* CodeGenerator::emitReturn(RegisterID* r0)
 {
-    instructions().append(machine().getOpcode(op_ret));
+    emitOpcode(op_ret);
     instructions().append(r0->index());
     return r0;
 }
 
 RegisterID* CodeGenerator::emitEnd(RegisterID* dst)
 {
-    instructions().append(machine().getOpcode(op_end));
+    emitOpcode(op_end);
     instructions().append(dst->index());
     return dst;
 }
@@ -1015,7 +1056,7 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
         emitNode(argv.last().get(), n);
     }
 
-    instructions().append(machine().getOpcode(op_construct));
+    emitOpcode(op_construct);
     instructions().append(dst->index());
     instructions().append(func->index());
     instructions().append(argv.size() ? argv[0]->index() : m_temporaries.size()); // argv
@@ -1026,7 +1067,7 @@ RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
 RegisterID* CodeGenerator::emitPushScope(RegisterID* scope)
 {
     m_codeBlock->needsFullScopeChain = true;
-    instructions().append(machine().getOpcode(op_push_scope));
+    emitOpcode(op_push_scope);
     instructions().append(scope->index());
 
     ControlFlowContext context;
@@ -1041,7 +1082,7 @@ void CodeGenerator::emitPopScope()
     ASSERT(m_scopeContextStack.size());
     ASSERT(!m_scopeContextStack.last().isFinallyBlock);
 
-    instructions().append(machine().getOpcode(op_pop_scope));
+    emitOpcode(op_pop_scope);
 
     m_scopeContextStack.removeLast();
     m_dynamicScopeDepth--;
@@ -1051,7 +1092,7 @@ void CodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int la
 {
     if (!m_shouldEmitDebugHooks)
         return;
-    instructions().append(machine().getOpcode(op_debug));
+    emitOpcode(op_debug);
     instructions().append(debugHookID);
     instructions().append(firstLine);
     instructions().append(lastLine);
@@ -1152,7 +1193,7 @@ PassRefPtr<LabelID> CodeGenerator::emitComplexJumpScopes(LabelID* target, Contro
         if (nNormalScopes) {
             // We need to remove a number of dynamic scopes to get to the next
             // finally block
-            instructions().append(machine().getOpcode(op_jmp_scopes));
+            emitOpcode(op_jmp_scopes);
             instructions().append(nNormalScopes);
 
             // If topScope == bottomScope then there isn't actually a finally block
@@ -1193,7 +1234,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetSco
     if (m_finallyDepth)
         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 
-    instructions().append(machine().getOpcode(op_jmp_scopes));
+    emitOpcode(op_jmp_scopes);
     instructions().append(scopeDelta);
     instructions().append(target->offsetFrom(instructions().size()));
     return target;
@@ -1201,7 +1242,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpScopes(LabelID* target, int targetSco
 
 RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, LabelID* target)
 {
-    instructions().append(machine().getOpcode(op_next_pname));
+    emitOpcode(op_next_pname);
     instructions().append(dst->index());
     instructions().append(iter->index());
     instructions().append(target->offsetFrom(instructions().size()));
@@ -1210,7 +1251,7 @@ RegisterID* CodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* ite
 
 RegisterID* CodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base)
 {
-    instructions().append(machine().getOpcode(op_get_pnames));
+    emitOpcode(op_get_pnames);
     instructions().append(dst->index());
     instructions().append(base->index());
     return dst;
@@ -1220,20 +1261,20 @@ RegisterID* CodeGenerator::emitCatch(RegisterID* targetRegister, LabelID* start,
 {
     HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth };
     exceptionHandlers().append(info);
-    instructions().append(machine().getOpcode(op_catch));
+    emitOpcode(op_catch);
     instructions().append(targetRegister->index());
     return targetRegister;
 }
 
 void CodeGenerator::emitThrow(RegisterID* exception)
 {
-    instructions().append(machine().getOpcode(op_throw));
+    emitOpcode(op_throw);
     instructions().append(exception->index());
 }
 
 RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue* message)
 {
-    instructions().append(machine().getOpcode(op_new_error));
+    emitOpcode(op_new_error);
     instructions().append(dst->index());
     instructions().append(static_cast<int>(type));
     instructions().append(addConstant(message));
@@ -1242,7 +1283,7 @@ RegisterID* CodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue
 
 PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, LabelID* finally)
 {
-    instructions().append(machine().getOpcode(op_jsr));
+    emitOpcode(op_jsr);
     instructions().append(retAddrDst->index());
     instructions().append(finally->offsetFrom(instructions().size()));
     return finally;
@@ -1250,7 +1291,7 @@ PassRefPtr<LabelID> CodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, La
 
 void CodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
 {
-    instructions().append(machine().getOpcode(op_sret));
+    emitOpcode(op_sret);
     instructions().append(retAddrSrc->index());
 }
 
index e4edbe0453fad5617d6319368a74cdf02a66a275..a6a3e5cb8effe3e3b89c6f0ab55cfb6ad2178005 100644 (file)
@@ -293,6 +293,10 @@ namespace KJS {
         CodeType codeType() const { return m_codeType; }
 
     private:
+        void emitOpcode(OpcodeID);
+        void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
+        void rewindBinaryOp();
+
         PassRefPtr<LabelID> emitComplexJumpScopes(LabelID* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
         struct JSValueHashTraits : HashTraits<JSValue*> {
             static void constructDeletedValue(JSValue** slot) { *slot = JSImmediate::impossibleValue(); }
@@ -373,6 +377,8 @@ namespace KJS {
 
         const CommonIdentifiers* m_propertyNames;
 
+        OpcodeID m_lastOpcodeID;
+
 #ifndef NDEBUG
         static bool s_dumpsGeneratedCode;
 #endif
index 6303470e3e2216a58d9eca29a35f9361915e607c..f9e94b07922e9c641f84ab930ffd5617aac9f24a 100644 (file)
@@ -1912,6 +1912,29 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
         ++vPC;
         NEXT_OPCODE;
     }
+    BEGIN_OPCODE(op_jless) {
+        /* jless src1(r) src2(r) target(offset)
+
+           Checks whether register src1 is less than register src2, as
+           with the ECMAScript '<' operator, and then jumps to offset
+           target from the current instruction, if and only if the 
+           result of the comparison is true.
+        */
+        JSValue* src1 = r[(++vPC)->u.operand].u.jsValue;
+        JSValue* src2 = r[(++vPC)->u.operand].u.jsValue;
+        int target = (++vPC)->u.operand;
+
+        bool result = jsLess(exec, src1, src2);
+        VM_CHECK_EXCEPTION();
+        
+        if (result) {
+            vPC += target;
+            NEXT_OPCODE;
+        }
+
+        ++vPC;
+        NEXT_OPCODE;
+    }
     BEGIN_OPCODE(op_new_func) {
         /* new_func dst(r) func(f)
 
index d878dd8219ab6a438ae4cea4c9e5fc98066c2d78..0eb3f5526e25a0e8b8259be75f8308b8ff3c6c7e 100644 (file)
@@ -103,6 +103,7 @@ static const char* opcodeNames[] = {
     "jmp",
     "jtrue",
     "jfalse",
+    "jless",
     "jmp_scopes",
 
     "new_func",
index 1dbbba9e6fd0741bca4614b0a90f275783c368a5..a913222e95f2bfd1a79341ef24fa1fc6780aa9fb 100644 (file)
@@ -95,6 +95,7 @@ namespace KJS {
         macro(op_jmp) \
         macro(op_jtrue) \
         macro(op_jfalse) \
+        macro(op_jless) \
         macro(op_jmp_scopes) \
         \
         macro(op_new_func) \