Commit 452cb41a authored by fpizlo@apple.com's avatar fpizlo@apple.com
Browse files

Value profling and execution count profiling is performed even for

code that cannot be optimized
https://bugs.webkit.org/show_bug.cgi?id=67694

Reviewed by Gavin Barraclough.

This is a 2% speed-up on V8 when tiered compilation is enabled.

* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::ProgramCodeBlock::canCompileWithDFG):
(JSC::EvalCodeBlock::canCompileWithDFG):
(JSC::FunctionCodeBlock::canCompileWithDFG):
* bytecode/CodeBlock.h:
* dfg/DFGCapabilities.cpp: Added.
(JSC::DFG::canCompileOpcodes):
* dfg/DFGCapabilities.h: Added.
(JSC::DFG::mightCompileEval):
(JSC::DFG::mightCompileProgram):
(JSC::DFG::mightCompileFunctionForCall):
(JSC::DFG::mightCompileFunctionForConstruct):
(JSC::DFG::canCompileOpcode):
(JSC::DFG::canCompileEval):
(JSC::DFG::canCompileProgram):
(JSC::DFG::canCompileFunctionForCall):
(JSC::DFG::canCompileFunctionForConstruct):
* jit/JIT.cpp:
(JSC::JIT::emitOptimizationCheck):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JSC::JIT::shouldEmitProfiling):
* jit/JITInlineMethods.h:
(JSC::JIT::emitValueProfilingSite):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@94802 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6cf9e8e6
2011-09-08 Filip Pizlo <fpizlo@apple.com>
Value profling and execution count profiling is performed even for
code that cannot be optimized
https://bugs.webkit.org/show_bug.cgi?id=67694
Reviewed by Gavin Barraclough.
This is a 2% speed-up on V8 when tiered compilation is enabled.
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::ProgramCodeBlock::canCompileWithDFG):
(JSC::EvalCodeBlock::canCompileWithDFG):
(JSC::FunctionCodeBlock::canCompileWithDFG):
* bytecode/CodeBlock.h:
* dfg/DFGCapabilities.cpp: Added.
(JSC::DFG::canCompileOpcodes):
* dfg/DFGCapabilities.h: Added.
(JSC::DFG::mightCompileEval):
(JSC::DFG::mightCompileProgram):
(JSC::DFG::mightCompileFunctionForCall):
(JSC::DFG::mightCompileFunctionForConstruct):
(JSC::DFG::canCompileOpcode):
(JSC::DFG::canCompileEval):
(JSC::DFG::canCompileProgram):
(JSC::DFG::canCompileFunctionForCall):
(JSC::DFG::canCompileFunctionForConstruct):
* jit/JIT.cpp:
(JSC::JIT::emitOptimizationCheck):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JSC::JIT::shouldEmitProfiling):
* jit/JITInlineMethods.h:
(JSC::JIT::emitValueProfilingSite):
2011-09-08 Filip Pizlo <fpizlo@apple.com>
 
DFG speculative JIT does not initialize integer tags for PredictInt32 temporaries
......
......@@ -60,6 +60,7 @@
0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */; };
0FD3C82714115D4F00FD81CB /* DFGPropagator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82414115D2200FD81CB /* DFGPropagator.h */; };
0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82214115D0E00FD81CB /* DFGDriver.h */; };
0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; };
1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; };
......@@ -785,6 +786,8 @@
0FD3C82214115D0E00FD81CB /* DFGDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDriver.h; path = dfg/DFGDriver.h; sourceTree = "<group>"; };
0FD3C82314115D1A00FD81CB /* DFGPropagator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPropagator.cpp; path = dfg/DFGPropagator.cpp; sourceTree = "<group>"; };
0FD3C82414115D2200FD81CB /* DFGPropagator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropagator.h; path = dfg/DFGPropagator.h; sourceTree = "<group>"; };
0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCapabilities.cpp; path = dfg/DFGCapabilities.cpp; sourceTree = "<group>"; };
0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCapabilities.h; path = dfg/DFGCapabilities.h; sourceTree = "<group>"; };
1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; };
......@@ -2181,6 +2184,8 @@
86EC9DB31328DF44002B2AD7 /* dfg */ = {
isa = PBXGroup;
children = (
0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */,
0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */,
0FD3C82414115D2200FD81CB /* DFGPropagator.h */,
0FD3C82314115D1A00FD81CB /* DFGPropagator.cpp */,
0FD3C82214115D0E00FD81CB /* DFGDriver.h */,
......@@ -3040,6 +3045,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */,
0FD3C82514115D4000FD81CB /* DFGPropagator.cpp in Sources */,
0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */,
0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */,
......
......@@ -31,6 +31,7 @@
#include "CodeBlock.h"
#include "BytecodeGenerator.h"
#include "DFGCapabilities.h"
#include "Debugger.h"
#include "Interpreter.h"
#include "JIT.h"
......@@ -1930,6 +1931,23 @@ JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* s
JSObject* error = static_cast<FunctionExecutable*>(ownerExecutable())->compileOptimizedFor(exec, scopeChainNode, m_isConstructor ? CodeForConstruct : CodeForCall);
return error;
}
bool ProgramCodeBlock::canCompileWithDFG()
{
return DFG::canCompileProgram(this);
}
bool EvalCodeBlock::canCompileWithDFG()
{
return DFG::canCompileEval(this);
}
bool FunctionCodeBlock::canCompileWithDFG()
{
if (m_isConstructor)
return DFG::canCompileFunctionForConstruct(this);
return DFG::canCompileFunctionForCall(this);
}
#endif
} // namespace JSC
......@@ -327,6 +327,7 @@ namespace JSC {
ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); }
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
virtual CodeBlock* replacement() = 0;
virtual bool canCompileWithDFG() = 0;
#else
JITCode::JITType getJITType() { return JITCode::BaselineJIT; }
#endif
......@@ -334,6 +335,7 @@ namespace JSC {
ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
JSGlobalData* globalData() { return m_globalData; }
void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
int thisRegister() const { return m_thisRegister; }
......@@ -723,6 +725,7 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFG();
#endif
};
......@@ -748,6 +751,7 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFG();
#endif
private:
......@@ -774,6 +778,7 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual CodeBlock* replacement();
virtual bool canCompileWithDFG();
#endif
};
......
......@@ -29,6 +29,7 @@
#if ENABLE(DFG_JIT)
#include "DFGAliasTracker.h"
#include "DFGCapabilities.h"
#include "DFGScoreBoard.h"
#include "CodeBlock.h"
......@@ -598,7 +599,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// Switch on the current bytecode opcode.
Instruction* currentInstruction = instructionsBegin + m_currentIndex;
switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) {
OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
switch (opcodeID) {
// === Function entry opcodes ===
......@@ -1208,8 +1210,11 @@ bool ByteCodeParser::parseBlock(unsigned limit)
default:
// Parse failed!
ASSERT(!canCompileOpcode(opcodeID));
return false;
}
ASSERT(canCompileOpcode(opcodeID));
}
}
......
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DFGCapabilities.h"
#include "CodeBlock.h"
#include "Interpreter.h"
namespace JSC { namespace DFG {
bool canCompileOpcodes(CodeBlock* codeBlock)
{
Interpreter* interpreter = codeBlock->globalData()->interpreter;
Instruction* instructionsBegin = codeBlock->instructions().begin();
unsigned instructionCount = codeBlock->instructions().size();
for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) {
switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) {
#define DEFINE_OP(opcode, length) \
case opcode: \
if (!canCompileOpcode(opcode)) \
return false; \
bytecodeOffset += length; \
break;
FOR_EACH_OPCODE_ID(DEFINE_OP)
#undef DEFINE_OP
default:
ASSERT_NOT_REACHED();
break;
}
}
return true;
}
} } // namespace JSC::DFG
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DFGCapabilities_h
#define DFGCapabilities_h
#include "Interpreter.h"
#include <wtf/Platform.h>
namespace JSC { namespace DFG {
#if ENABLE(DFG_JIT)
// Fast check functions; if they return true it is still necessary to
// check opcodes.
inline bool mightCompileEval(CodeBlock*) { return true; }
inline bool mightCompileProgram(CodeBlock*) { return true; }
inline bool mightCompileFunctionForCall(CodeBlock*) { return true; }
inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
// Opcode checking.
inline bool canCompileOpcode(OpcodeID opcodeID)
{
switch (opcodeID) {
case op_enter:
case op_convert_this:
case op_bitand:
case op_bitor:
case op_bitxor:
case op_rshift:
case op_lshift:
case op_urshift:
case op_pre_inc:
case op_post_inc:
case op_pre_dec:
case op_post_dec:
case op_add:
case op_sub:
case op_mul:
case op_mod:
case op_div:
#if ENABLE(DEBUG_WITH_BREAKPOINT)
case op_debug:
#endif
case op_mov:
case op_check_has_instance:
case op_instanceof:
case op_not:
case op_less:
case op_lesseq:
case op_greater:
case op_greatereq:
case op_eq:
case op_eq_null:
case op_stricteq:
case op_neq:
case op_neq_null:
case op_nstricteq:
case op_get_by_val:
case op_put_by_val:
case op_method_check:
case op_get_by_id:
case op_put_by_id:
case op_get_global_var:
case op_put_global_var:
case op_jmp:
case op_loop:
case op_jtrue:
case op_jfalse:
case op_loop_if_true:
case op_loop_if_false:
case op_jeq_null:
case op_jneq_null:
case op_jless:
case op_jlesseq:
case op_jgreater:
case op_jgreatereq:
case op_jnless:
case op_jnlesseq:
case op_jngreater:
case op_jngreatereq:
case op_loop_if_less:
case op_loop_if_lesseq:
case op_loop_if_greater:
case op_loop_if_greatereq:
case op_ret:
case op_end:
case op_call:
case op_construct:
case op_call_put_result:
case op_resolve:
case op_resolve_base:
return true;
default:
return false;
}
}
bool canCompileOpcodes(CodeBlock*);
#else // ENABLE(DFG_JIT)
inline bool mightCompileEval(CodeBlock*) { return false; }
inline bool mightCompileProgram(CodeBlock*) { return false; }
inline bool mightCompileFunctionForCall(CodeBlock*) { return false; }
inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; }
inline bool canCompileOpcode(OpcodeID) { return false; }
inline bool canCompileOpcodes(CodeBlock*) { return false; }
#endif // ENABLE(DFG_JIT)
inline bool canCompileEval(CodeBlock* codeBlock)
{
return mightCompileEval(codeBlock) && canCompileOpcodes(codeBlock);
}
inline bool canCompileProgram(CodeBlock* codeBlock)
{
return mightCompileProgram(codeBlock) && canCompileOpcodes(codeBlock);
}
inline bool canCompileFunctionForCall(CodeBlock* codeBlock)
{
return mightCompileFunctionForCall(codeBlock) && canCompileOpcodes(codeBlock);
}
inline bool canCompileFunctionForConstruct(CodeBlock* codeBlock)
{
return mightCompileFunctionForConstruct(codeBlock) && canCompileOpcodes(codeBlock);
}
} } // namespace JSC::DFG
#endif // DFGCapabilities_h
......@@ -36,6 +36,7 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse
#include "CodeBlock.h"
#include "CryptographicallyRandomNumber.h"
#include "DFGNode.h" // for DFG_SUCCESS_STATS
#include "Interpreter.h"
#include "JITInlineMethods.h"
#include "JITStubCall.h"
......@@ -45,7 +46,6 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse
#include "RepatchBuffer.h"
#include "ResultType.h"
#include "SamplingTool.h"
#include "dfg/DFGNode.h" // for DFG_SUCCESS_STATS
using namespace std;
......@@ -96,6 +96,9 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
#if ENABLE(TIERED_COMPILATION)
void JIT::emitOptimizationCheck(OptimizationCheckKind kind)
{
if (!shouldEmitProfiling())
return;
Jump skipOptimize = branchAdd32(Signed, TrustedImm32(kind == LoopOptimizationCheck ? 1 : 30), AbsoluteAddress(&m_codeBlock->m_executeCounter));
JITStubCall stubCall(this, kind == LoopOptimizationCheck ? cti_optimize_from_loop : cti_optimize_from_ret);
stubCall.call();
......@@ -497,6 +500,10 @@ void JIT::privateCompileSlowCases()
JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
{
#if ENABLE(TIERED_COMPILATION)
m_canBeOptimized = m_codeBlock->canCompileWithDFG();
#endif
// Just add a little bit of randomness to the codegen
if (m_randomGenerator.getUint32() & 1)
nop();
......
......@@ -1004,6 +1004,14 @@ namespace JSC {
void sampleCodeBlock(CodeBlock*) {}
#endif
#if ENABLE(TIERED_COMPILATION)
bool shouldEmitProfiling() { return m_canBeOptimized; }
#else
// Enables use of value profiler with tiered compilation turned off,
// in which case all code gets profiled.
bool shouldEmitProfiling() { return true; }
#endif
Interpreter* m_interpreter;
JSGlobalData* m_globalData;
CodeBlock* m_codeBlock;
......@@ -1043,6 +1051,10 @@ namespace JSC {
#endif
WeakRandom m_randomGenerator;
static CodePtr stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool);
#if ENABLE(TIERED_COMPILATION)
bool m_canBeOptimized;
#endif
} JIT_CLASS_ALIGNMENT;
inline void JIT::emit_op_loop(Instruction* currentInstruction)
......
......@@ -435,6 +435,9 @@ inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, Register
#if ENABLE(VALUE_PROFILER)
inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
{
if (!shouldEmitProfiling())
return;
const RegisterID value = regT0;
const RegisterID scratch = regT3;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment