Title: [156376] trunk
Revision
156376
Author
[email protected]
Date
2013-09-24 17:37:57 -0700 (Tue, 24 Sep 2013)

Log Message

op_get_callee shouldn't use value profiling
https://bugs.webkit.org/show_bug.cgi?id=121821

Reviewed by Filip Pizlo.

Source/_javascript_Core: 

Currently it's one of the two opcodes that uses m_singletonValue, which is unnecessary. 
Our current plan is to remove m_singletonValue so that GenGC can have a simpler story 
for handling CodeBlocks/FunctionExecutables during nursery collections.

Instead of using a ValueProfile op_get_callee now has a simple inline cache of the most 
recent JSFunction that we saw.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitCreateThis):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_get_callee):
(JSC::JIT::emitSlow_op_get_callee):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_get_callee):
(JSC::JIT::emitSlow_op_get_callee):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:

LayoutTests: 

Added two tests to make sure we didn't regress the performance of op_get_callee.

* js/regress/get_callee_monomorphic-expected.txt: Added.
* js/regress/get_callee_monomorphic.html: Added.
* js/regress/get_callee_polymorphic-expected.txt: Added.
* js/regress/get_callee_polymorphic.html: Added.
* js/regress/script-tests/get_callee_monomorphic.js: Added.
* js/regress/script-tests/get_callee_polymorphic.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (156375 => 156376)


--- trunk/LayoutTests/ChangeLog	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/LayoutTests/ChangeLog	2013-09-25 00:37:57 UTC (rev 156376)
@@ -1,3 +1,19 @@
+2013-09-24  Mark Hahnenberg  <[email protected]>
+
+        op_get_callee shouldn't use value profiling
+        https://bugs.webkit.org/show_bug.cgi?id=121821
+
+        Reviewed by Filip Pizlo.
+
+        Added two tests to make sure we didn't regress the performance of op_get_callee.
+
+        * js/regress/get_callee_monomorphic-expected.txt: Added.
+        * js/regress/get_callee_monomorphic.html: Added.
+        * js/regress/get_callee_polymorphic-expected.txt: Added.
+        * js/regress/get_callee_polymorphic.html: Added.
+        * js/regress/script-tests/get_callee_monomorphic.js: Added.
+        * js/regress/script-tests/get_callee_polymorphic.js: Added.
+
 2013-09-24  Bear Travis  <[email protected]>
 
         Disable CSS_SHAPES on Windows

Added: trunk/LayoutTests/js/regress/get_callee_monomorphic-expected.txt (0 => 156376)


--- trunk/LayoutTests/js/regress/get_callee_monomorphic-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/get_callee_monomorphic-expected.txt	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,10 @@
+JSRegress/get_callee_monomorphic
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/get_callee_monomorphic.html (0 => 156376)


--- trunk/LayoutTests/js/regress/get_callee_monomorphic.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/get_callee_monomorphic.html	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/get_callee_polymorphic-expected.txt (0 => 156376)


--- trunk/LayoutTests/js/regress/get_callee_polymorphic-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/get_callee_polymorphic-expected.txt	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,10 @@
+JSRegress/get_callee_polymorphic
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/get_callee_polymorphic.html (0 => 156376)


--- trunk/LayoutTests/js/regress/get_callee_polymorphic.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/get_callee_polymorphic.html	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/get_callee_monomorphic.js (0 => 156376)


--- trunk/LayoutTests/js/regress/script-tests/get_callee_monomorphic.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/get_callee_monomorphic.js	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,12 @@
+function Foo() {
+    this.bar = function() { return 1; };
+}
+
+var sum = 0;
+for (var i = 0; i < 100000; i++) {
+    var f = new Foo();
+    sum += f.bar();
+}
+
+if (sum != 100000)
+    throw "Error: incorrect sum. Expected 10000 but got " + sum + ".";

Added: trunk/LayoutTests/js/regress/script-tests/get_callee_polymorphic.js (0 => 156376)


--- trunk/LayoutTests/js/regress/script-tests/get_callee_polymorphic.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/get_callee_polymorphic.js	2013-09-25 00:37:57 UTC (rev 156376)
@@ -0,0 +1,39 @@
+var Class = {
+    create: function() {
+        return function() { 
+            this.initialize.apply(this, arguments);
+        };
+    }
+};
+
+var sum = 0;
+
+var init = function(a, b) { sum += a + b; };
+
+var Class1 = Class.create();
+Class1.prototype = {
+    initialize: init
+};
+var Class2 = Class.create();
+Class2.prototype = {
+    initialize: init
+};
+var Class3 = Class.create();
+Class3.prototype = {
+    initialize: init
+};
+
+for (var i = 0; i < 1000; i++) {
+    for (var j = 0; j < 100; j++) {
+        var newObject;
+        if (j % 3 == 0)
+            newObject = new Class1(2, 3);
+        else if (j % 3 == 1)
+            newObject = new Class2(2, 3);
+        else
+            newObject = new Class3(2, 3);
+    }
+}
+
+if (sum != 5 * 100 * 1000)
+    throw "Error: incorrect sum. Expected " + (5 * 100 * 1000) + " but got " + sum + ".";

Modified: trunk/Source/_javascript_Core/ChangeLog (156375 => 156376)


--- trunk/Source/_javascript_Core/ChangeLog	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-09-25 00:37:57 UTC (rev 156376)
@@ -1,3 +1,39 @@
+2013-09-24  Mark Hahnenberg  <[email protected]>
+
+        op_get_callee shouldn't use value profiling
+        https://bugs.webkit.org/show_bug.cgi?id=121821
+
+        Reviewed by Filip Pizlo.
+
+        Currently it's one of the two opcodes that uses m_singletonValue, which is unnecessary. 
+        Our current plan is to remove m_singletonValue so that GenGC can have a simpler story 
+        for handling CodeBlocks/FunctionExecutables during nursery collections.
+
+        Instead of using a ValueProfile op_get_callee now has a simple inline cache of the most 
+        recent JSFunction that we saw.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitCreateThis):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_get_callee):
+        (JSC::JIT::emitSlow_op_get_callee):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_get_callee):
+        (JSC::JIT::emitSlow_op_get_callee):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+
 2013-09-24  Mark Lam  <[email protected]>
 
         Change JSC debug hooks to pass a CallFrame* instead of a DebuggerCallFrame.

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -1736,8 +1736,7 @@
         }
         case op_to_this:
         case op_get_by_id:
-        case op_call_varargs:
-        case op_get_callee: {
+        case op_call_varargs: {
             ValueProfile* profile = "" + opLength - 1].u.operand];
             ASSERT(profile->m_bytecodeOffset == -1);
             profile->m_bytecodeOffset = i;
@@ -2239,6 +2238,13 @@
                 break;
             case op_get_array_length:
                 break;
+            case op_get_callee:
+                if (!curInstruction[2].u.jsCell || Heap::isMarked(curInstruction[2].u.jsCell.get()))
+                    break;
+                if (Options::verboseOSR())
+                    dataLogF("Clearing LLInt get callee with function %p.\n", curInstruction[2].u.jsCell.get());
+                curInstruction[2].u.jsCell.clear();
+                break;
             case op_get_from_scope:
             case op_put_to_scope: {
                 WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -1404,9 +1404,9 @@
 {
     RefPtr<RegisterID> func = newTemporary(); 
 
-    UnlinkedValueProfile profile = ""
+    emitOpcode(op_get_callee);
     instructions().append(func->index());
-    instructions().append(profile);
+    instructions().append(0);
 
     size_t begin = instructions().size();
     m_staticPropertyAnalyzer.createThis(m_thisRegister.index(), begin + 3);

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -2007,18 +2007,16 @@
         }
             
         case op_get_callee: {
-            ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
-            ValueProfile* profile = ""
-            profile->computeUpdatedPrediction(locker);
-            if (profile->m_singletonValueIsTop
-                || !profile->m_singletonValue
-                || !profile->m_singletonValue.isCell())
+            JSCell* cachedFunction = currentInstruction[2].u.jsCell.get();
+            if (!cachedFunction 
+                || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
+                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadFunction)) {
                 set(currentInstruction[1].u.operand, get(JSStack::Callee));
-            else {
-                ASSERT(profile->m_singletonValue.asCell()->inherits(JSFunction::info()));
+            } else {
+                ASSERT(cachedFunction->inherits(JSFunction::info()));
                 Node* actualCallee = get(JSStack::Callee);
-                addToGraph(CheckFunction, OpInfo(profile->m_singletonValue.asCell()), actualCallee);
-                set(currentInstruction[1].u.operand, addToGraph(WeakJSConstant, OpInfo(profile->m_singletonValue.asCell())));
+                addToGraph(CheckFunction, OpInfo(cachedFunction), actualCallee);
+                set(currentInstruction[1].u.operand, addToGraph(WeakJSConstant, OpInfo(cachedFunction)));
             }
             NEXT_OPCODE(op_get_callee);
         }

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -407,6 +407,7 @@
         DEFINE_SLOWCASE_OP(op_create_this)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_eq)
+        DEFINE_SLOWCASE_OP(op_get_callee)
         case op_get_by_id_out_of_line:
         case op_get_array_length:
         DEFINE_SLOWCASE_OP(op_get_by_id)

Modified: trunk/Source/_javascript_Core/jit/JIT.h (156375 => 156376)


--- trunk/Source/_javascript_Core/jit/JIT.h	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2013-09-25 00:37:57 UTC (rev 156376)
@@ -746,6 +746,7 @@
         void emitSlow_op_create_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_callee(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -878,11 +878,24 @@
 void JIT::emit_op_get_callee(Instruction* currentInstruction)
 {
     int result = currentInstruction[1].u.operand;
+    WriteBarrierBase<JSCell>* cachedFunction = &currentInstruction[2].u.jsCell;
     emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT0);
-    emitValueProfilingSite(regT4);
+
+    loadPtr(cachedFunction, regT2);
+    addSlowCase(branchPtr(NotEqual, regT0, regT2));
+
     emitPutVirtualRegister(result);
 }
 
+void JIT::emitSlow_op_get_callee(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_callee);
+    slowPathCall.call();
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+}
+
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
     int callee = currentInstruction[2].u.operand;

Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -1129,13 +1129,26 @@
 
 void JIT::emit_op_get_callee(Instruction* currentInstruction)
 {
-    int dst = currentInstruction[1].u.operand;
+    int result = currentInstruction[1].u.operand;
+    WriteBarrierBase<JSCell>* cachedFunction = &currentInstruction[2].u.jsCell;
     emitGetFromCallFrameHeaderPtr(JSStack::Callee, regT0);
+
+    loadPtr(cachedFunction, regT2);
+    addSlowCase(branchPtr(NotEqual, regT0, regT2));
+
     move(TrustedImm32(JSValue::CellTag), regT1);
-    emitValueProfilingSite(regT4);
-    emitStore(dst, regT1, regT0);
+    emitStore(result, regT1, regT0);
 }
 
+void JIT::emitSlow_op_get_callee(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_callee);
+    slowPathCall.call();
+    emitLoad(currentInstruction[1].u.operand, regT1, regT0);
+}
+
 void JIT::emit_op_create_this(Instruction* currentInstruction)
 {
     int callee = currentInstruction[2].u.operand;

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (156375 => 156376)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm	2013-09-25 00:37:57 UTC (rev 156376)
@@ -414,11 +414,15 @@
     traceExecution()
     loadi 4[PC], t0
     loadp PayloadOffset + Callee[cfr], t1
-    valueProfile(CellTag, t1, 8, t2)
+    loadpFromInstruction(2, t2)
+    bpneq t1, t2, .opGetCalleeSlow
     storei CellTag, TagOffset[cfr, t0, 8]
     storei t1, PayloadOffset[cfr, t0, 8]
     dispatch(3)
 
+.opGetCalleeSlow:
+    callSlowPath(_slow_path_get_callee)
+    dispatch(3)
 
 _llint_op_to_this:
     traceExecution()

Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (156375 => 156376)


--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm	2013-09-25 00:37:57 UTC (rev 156376)
@@ -295,10 +295,14 @@
     traceExecution()
     loadisFromInstruction(1, t0)
     loadp Callee[cfr], t1
-    valueProfile(t1, 2, t2)
+    loadpFromInstruction(2, t2)
+    bpneq t1, t2, .opGetCalleeSlow
     storep t1, [cfr, t0, 8]
     dispatch(3)
 
+.opGetCalleeSlow:
+    callSlowPath(_slow_path_get_callee)
+    dispatch(3)
 
 _llint_op_to_this:
     traceExecution()

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp (156375 => 156376)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.cpp	2013-09-25 00:37:57 UTC (rev 156376)
@@ -193,6 +193,14 @@
     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
 }
 
+SLOW_PATH_DECL(slow_path_get_callee)
+{
+    BEGIN();
+    JSFunction* callee = jsCast<JSFunction*>(exec->callee());
+    pc[2].u.jsCell.set(exec->vm(), exec->codeBlock()->ownerExecutable(), callee);
+    RETURN(callee);
+}
+
 SLOW_PATH_DECL(slow_path_create_arguments)
 {
     BEGIN();

Modified: trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h (156375 => 156376)


--- trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2013-09-25 00:14:46 UTC (rev 156375)
+++ trunk/Source/_javascript_Core/runtime/CommonSlowPaths.h	2013-09-25 00:37:57 UTC (rev 156376)
@@ -153,6 +153,7 @@
 SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
 SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
 SLOW_PATH_HIDDEN_DECL(slow_path_not);
 SLOW_PATH_HIDDEN_DECL(slow_path_eq);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to