Title: [188318] branches/jsc-tailcall/Source/_javascript_Core
Revision
188318
Author
[email protected]
Date
2015-08-11 18:59:31 -0700 (Tue, 11 Aug 2015)

Log Message

jsc-tailcall: Arity fixup should make use of the possible extra empty slots at top of the frame
https://bugs.webkit.org/show_bug.cgi?id=147893

Reviewed by Michael Saboff.

This changes the way arity fixup is performed. Since r187767, we always
ensure that the total amount of space reserved for a call frame is
stack-aligned, which means that for a non-aligned call frame size, we
have an additional "free" slot at the top of the frame. This makes it
so that when performing arity fixup, we first use that space if
necessary before moving the frame down.

This ensures that the total stack space used by a frame is always
max(argCount, numParameters) + JSStack::CallFrameHeaderSize, rounded up
to be a multiple of 2.

* jit/CCallHelpers.h:
* jit/ThunkGenerators.cpp:
(JSC::arityFixupGenerator):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.h:
(JSC::CommonSlowPaths::arityCheckFor): Returns the padding in amount of slots instead of aligned stack units

Modified Paths

Diff

Modified: branches/jsc-tailcall/Source/_javascript_Core/ChangeLog (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/ChangeLog	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/ChangeLog	2015-08-12 01:59:31 UTC (rev 188318)
@@ -1,5 +1,32 @@
 2015-08-11  Basile Clement  <[email protected]>
 
+        jsc-tailcall: Arity fixup should make use of the possible extra empty slots at top of the frame
+        https://bugs.webkit.org/show_bug.cgi?id=147893
+
+        Reviewed by Michael Saboff.
+
+        This changes the way arity fixup is performed. Since r187767, we always
+        ensure that the total amount of space reserved for a call frame is
+        stack-aligned, which means that for a non-aligned call frame size, we
+        have an additional "free" slot at the top of the frame. This makes it
+        so that when performing arity fixup, we first use that space if
+        necessary before moving the frame down.
+
+        This ensures that the total stack space used by a frame is always
+        max(argCount, numParameters) + JSStack::CallFrameHeaderSize, rounded up
+        to be a multiple of 2.
+
+        * jit/CCallHelpers.h:
+        * jit/ThunkGenerators.cpp:
+        (JSC::arityFixupGenerator):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.h:
+        (JSC::CommonSlowPaths::arityCheckFor): Returns the padding in amount of slots instead of aligned stack units
+
+2015-08-11  Basile Clement  <[email protected]>
+
         jsc-tailcall: Make tail call tests run in all tiers
         https://bugs.webkit.org/show_bug.cgi?id=147895
 

Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/CCallHelpers.h	2015-08-12 01:59:31 UTC (rev 188318)
@@ -2047,10 +2047,7 @@
         loadPtr(Address(GPRInfo::callFrameRegister, JSStack::CodeBlock * static_cast<int>(sizeof(Register))), temp2);
         load32(Address(temp2, CodeBlock::offsetOfNumParameters()), temp2);
         MacroAssembler::Jump argumentCountWasNotFixedUp = branch32(BelowOrEqual, temp2, temp1);
-        sub32(temp1, temp2);
-        add32(TrustedImm32(stackAlignmentRegisters() - 1), temp2);
-        and32(TrustedImm32(-stackAlignmentRegisters()), temp2);
-        add32(temp2, temp1);
+        move(temp2, temp1);
         argumentCountWasNotFixedUp.link(this);
 
         add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), temp1);

Modified: branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-08-12 01:59:31 UTC (rev 188318)
@@ -367,7 +367,7 @@
 {
     JSInterfaceJIT jit(vm);
 
-    // We enter with fixup count, in aligned stack units, in argumentGPR0 and the return thunk in argumentGPR1
+    // We enter with fixup count in argumentGPR0
     // We have the guarantee that a0, a1, a2, t3, t4 and t5 (or t0 for Windows) are all distinct :-)
 #if USE(JSVALUE64)
 #if OS(WINDOWS)
@@ -378,12 +378,25 @@
 #  if CPU(X86_64)
     jit.pop(JSInterfaceJIT::regT4);
 #  endif
-    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
-    jit.neg64(JSInterfaceJIT::argumentGPR0);
     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
 
+    // Check to see if we have extra slots we can use
+    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
+    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
+    jit.move(JSInterfaceJIT::TrustedImm64(ValueUndefined), extraTemp);
+    JSInterfaceJIT::Label fillExtraSlots(jit.label());
+    jit.store64(extraTemp, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight));
+    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
+    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &jit);
+    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+    noExtraSlot.link(&jit);
+
+    jit.neg64(JSInterfaceJIT::argumentGPR0);
+
     // Move current frame down argumentGPR0 number of slots
     JSInterfaceJIT::Label copyLoop(jit.label());
     jit.load64(JSInterfaceJIT::regT3, extraTemp);
@@ -405,6 +418,8 @@
     jit.addPtr(extraTemp, JSInterfaceJIT::callFrameRegister);
     jit.addPtr(extraTemp, JSInterfaceJIT::stackPointerRegister);
 
+    done.link(&jit);
+
 #  if CPU(X86_64)
     jit.push(JSInterfaceJIT::regT4);
 #  endif
@@ -413,18 +428,33 @@
 #  if CPU(X86)
     jit.pop(JSInterfaceJIT::regT4);
 #  endif
-    jit.lshift32(JSInterfaceJIT::TrustedImm32(logStackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
-    jit.neg32(JSInterfaceJIT::argumentGPR0);
     jit.move(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::regT3);
     jit.load32(JSInterfaceJIT::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * sizeof(Register)), JSInterfaceJIT::argumentGPR2);
     jit.add32(JSInterfaceJIT::TrustedImm32(JSStack::CallFrameHeaderSize), JSInterfaceJIT::argumentGPR2);
 
+    // Check to see if we have extra slots we can use
+    jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR1);
+    jit.and32(JSInterfaceJIT::TrustedImm32(stackAlignmentRegisters() - 1), JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Jump noExtraSlot = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR1);
+    JSInterfaceJIT::Label fillExtraSlots(jit.label());
+    jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, PayloadOffset));
+    jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::callFrameRegister, JSInterfaceJIT::argumentGPR2, JSInterfaceJIT::TimesEight, TagOffset));
+    jit.add32(JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2);
+    jit.branchSub32(JSInterfaceJIT::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR1).linkTo(fillExtraSlots, &jit);
+    jit.and32(JSInterfaceJIT::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::argumentGPR0);
+    JSInterfaceJIT::Jump done = jit.branchTest32(MacroAssembler::Zero, JSInterfaceJIT::argumentGPR0);
+    noExtraSlot.link(&jit);
+
+    jit.neg32(JSInterfaceJIT::argumentGPR0);
+
     // Move current frame down argumentGPR0 number of slots
     JSInterfaceJIT::Label copyLoop(jit.label());
-    jit.load32(JSInterfaceJIT::regT3, JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
-    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, 4), JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
+    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, PayloadOffset), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
+    jit.load32(MacroAssembler::Address(JSInterfaceJIT::regT3, TagOffset), JSInterfaceJIT::regT5);
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
     jit.branchSub32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(copyLoop, &jit);
 
@@ -432,9 +462,9 @@
     jit.move(JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::argumentGPR2);
     JSInterfaceJIT::Label fillUndefinedLoop(jit.label());
     jit.move(JSInterfaceJIT::TrustedImm32(0), JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight));
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, PayloadOffset));
     jit.move(JSInterfaceJIT::TrustedImm32(JSValue::UndefinedTag), JSInterfaceJIT::regT5);
-    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, 4));
+    jit.store32(JSInterfaceJIT::regT5, MacroAssembler::BaseIndex(JSInterfaceJIT::regT3, JSInterfaceJIT::argumentGPR0, JSInterfaceJIT::TimesEight, TagOffset));
 
     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::regT3);
     jit.branchAdd32(MacroAssembler::NonZero, JSInterfaceJIT::TrustedImm32(1), JSInterfaceJIT::argumentGPR2).linkTo(fillUndefinedLoop, &jit);
@@ -445,6 +475,8 @@
     jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::callFrameRegister);
     jit.addPtr(JSInterfaceJIT::regT5, JSInterfaceJIT::stackPointerRegister);
 
+    done.link(&jit);
+
 #  if CPU(X86)
     jit.push(JSInterfaceJIT::regT4);
 #  endif

Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter.asm	2015-08-12 01:59:31 UTC (rev 188318)
@@ -168,6 +168,7 @@
 const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
 
 const StackAlignment = 16
+const StackAlignmentSlots = 2
 const StackAlignmentMask = StackAlignment - 1
 
 const CallerFrameAndPCSize = 2 * PtrSize
@@ -732,20 +733,15 @@
 macro popFrame(temp1, temp2)
     const argCount = temp1
     const numParameters = temp2
-    const missingArgCount = temp2
 
     loadi PayloadOffset + ArgumentCount[cfr], argCount
-    mulp SlotSize, argCount
     loadp CodeBlock[cfr], numParameters
     loadi CodeBlock::m_numParameters[numParameters], numParameters
-    mulp SlotSize, numParameters
     bilteq numParameters, argCount, .noArityFixup
+    move numParameters, argCount
 
-    subi numParameters, argCount, missingArgCount
-    addp StackAlignmentMask, missingArgCount
-    andp ~StackAlignmentMask, missingArgCount
-    addi missingArgCount, argCount
 .noArityFixup:
+    mulp SlotSize, argCount
     alignFrameSize(argCount)
     addp argCount, cfr
 end

Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2015-08-12 01:59:31 UTC (rev 188318)
@@ -585,13 +585,27 @@
 .proceedInline:
     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
     btiz t1, .continue
+    loadi PayloadOffset + ArgumentCount[cfr], t2
+    addi CallFrameHeaderSlots, t2
 
-    // Move frame up "t1 * 2" slots
-    lshiftp 1, t1
+    // Check if there are some unaligned slots we can use
+    move t1, t3
+    andi StackAlignmentSlots - 1, t3
+    btiz t3, .noExtraSlot
+.fillExtraSlots:
+    move 0, t0
+    storei t0, PayloadOffset[cfr, t2, 8]
+    move UndefinedTag, t0
+    storei t0, TagOffset[cfr, t2, 8]
+    addi 1, t2
+    bsubinz 1, t3, .fillExtraSlots
+    andi ~(StackAlignmentSlots - 1), t1
+    btiz t1, .continue
+
+.noExtraSlot:
+    // Move frame up t1 slots
     negi t1
     move cfr, t3
-    loadi PayloadOffset + ArgumentCount[cfr], t2
-    addi CallFrameHeaderSlots, t2
 .copyLoop:
     loadi PayloadOffset[t3], t0
     storei t0, PayloadOffset[t3, t1, 8]

Modified: branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2015-08-12 01:59:31 UTC (rev 188318)
@@ -496,14 +496,27 @@
 .noError:
     loadi CommonSlowPaths::ArityCheckData::paddedStackSpace[r1], t1
     btiz t1, .continue
+    loadi PayloadOffset + ArgumentCount[cfr], t2
+    addi CallFrameHeaderSlots, t2
 
-    // Move frame up "t1 * 2" slots
-    lshiftp 1, t1
+    // Check if there are some unaligned slots we can use
+    move t1, t3
+    andi StackAlignmentSlots - 1, t3
+    btiz t3, .noExtraSlot
+    move ValueUndefined, t0
+.fillExtraSlots:
+    storeq t0, [cfr, t2, 8]
+    addi 1, t2
+    bsubinz 1, t3, .fillExtraSlots
+    andi ~(StackAlignmentSlots - 1), t1
+    btiz t1, .continue
+
+.noExtraSlot:
+    // Move frame up t1 slots
     negq t1
     move cfr, t3
     subp CalleeSaveSpaceAsVirtualRegisters * 8, t3
-    loadi PayloadOffset + ArgumentCount[cfr], t2
-    addi CallFrameHeaderSlots + CalleeSaveSpaceAsVirtualRegisters, t2
+    addi CalleeSaveSpaceAsVirtualRegisters, t2
 .copyLoop:
     loadq [t3], t0
     storeq t0, [t3, t1, 8]

Modified: branches/jsc-tailcall/Source/_javascript_Core/runtime/CommonSlowPaths.h (188317 => 188318)


--- branches/jsc-tailcall/Source/_javascript_Core/runtime/CommonSlowPaths.h	2015-08-12 01:46:06 UTC (rev 188317)
+++ branches/jsc-tailcall/Source/_javascript_Core/runtime/CommonSlowPaths.h	2015-08-12 01:59:31 UTC (rev 188318)
@@ -59,12 +59,14 @@
     int argumentCountIncludingThis = exec->argumentCountIncludingThis();
     
     ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
-    int missingArgumentCount = newCodeBlock->numParameters() - argumentCountIncludingThis;
-    int paddedStackSpace = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), missingArgumentCount);
+    int frameSize = argumentCountIncludingThis + JSStack::CallFrameHeaderSize;
+    int alignedFrameSizeForParameters = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),
+        newCodeBlock->numParameters() + JSStack::CallFrameHeaderSize);
+    int paddedStackSpace = alignedFrameSizeForParameters - frameSize;
 
-    if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace))
+    if (!stack->ensureCapacityFor(exec->registers() - paddedStackSpace % stackAlignmentRegisters()))
         return -1;
-    return paddedStackSpace / stackAlignmentRegisters();
+    return paddedStackSpace;
 }
 
 inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to