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 = ¤tInstruction[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 = ¤tInstruction[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);