From eaaa408100da8e1b65d3b3f0c4553ce112f4accf Mon Sep 17 00:00:00 2001 From: "fpizlo@apple.com" Date: Fri, 23 Sep 2011 23:28:07 +0000 Subject: [PATCH] Resolve opcodes should have value profiling. https://bugs.webkit.org/show_bug.cgi?id=68723 Reviewed by Oliver Hunt. This adds value profiling to all forms of op_resolve in the old JIT, and patches that information into the DFG along with performing the appropriate type propagation. * dfg/DFGByteCodeParser.cpp: (JSC::DFG::ByteCodeParser::parseBlock): * dfg/DFGGraph.h: (JSC::DFG::Graph::predict): * dfg/DFGNode.h: (JSC::DFG::Node::hasIdentifier): (JSC::DFG::Node::resolveGlobalDataIndex): (JSC::DFG::Node::hasPrediction): * dfg/DFGPropagator.cpp: (JSC::DFG::Propagator::propagateNodePredictions): * dfg/DFGSpeculativeJIT.cpp: (JSC::DFG::SpeculativeJIT::compile): * jit/JITOpcodes.cpp: (JSC::JIT::emit_op_resolve): (JSC::JIT::emit_op_resolve_base): (JSC::JIT::emit_op_resolve_skip): (JSC::JIT::emit_op_resolve_global): (JSC::JIT::emitSlow_op_resolve_global): (JSC::JIT::emit_op_resolve_with_base): (JSC::JIT::emit_op_resolve_with_this): (JSC::JIT::emitSlow_op_resolve_global_dynamic): * jit/JITStubCall.h: (JSC::JITStubCall::callWithValueProfiling): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95887 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/JavaScriptCore/ChangeLog | 35 +++++++++++++++++++++++++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp | 15 +++++++---- Source/JavaScriptCore/dfg/DFGGraph.h | 10 +++++++ Source/JavaScriptCore/dfg/DFGNode.h | 9 ++++--- Source/JavaScriptCore/dfg/DFGPropagator.cpp | 17 +++++------- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp | 5 ++-- Source/JavaScriptCore/jit/JITOpcodes.cpp | 15 ++++++----- Source/JavaScriptCore/jit/JITStubCall.h | 15 +++++++++++ 8 files changed, 93 insertions(+), 28 deletions(-) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 863687f..f0fbfbc 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,38 @@ +2011-09-23 Filip Pizlo + + Resolve opcodes should have value profiling. + https://bugs.webkit.org/show_bug.cgi?id=68723 + + Reviewed by Oliver Hunt. + + This adds value profiling to all forms of op_resolve in the + old JIT, and patches that information into the DFG along with + performing the appropriate type propagation. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::predict): + * dfg/DFGNode.h: + (JSC::DFG::Node::hasIdentifier): + (JSC::DFG::Node::resolveGlobalDataIndex): + (JSC::DFG::Node::hasPrediction): + * dfg/DFGPropagator.cpp: + (JSC::DFG::Propagator::propagateNodePredictions): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_resolve): + (JSC::JIT::emit_op_resolve_base): + (JSC::JIT::emit_op_resolve_skip): + (JSC::JIT::emit_op_resolve_global): + (JSC::JIT::emitSlow_op_resolve_global): + (JSC::JIT::emit_op_resolve_with_base): + (JSC::JIT::emit_op_resolve_with_this): + (JSC::JIT::emitSlow_op_resolve_global_dynamic): + * jit/JITStubCall.h: + (JSC::JITStubCall::callWithValueProfiling): + 2011-09-23 Oliver Hunt Fix windows build. diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index c255f0a..0fc7696 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -1415,8 +1415,9 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_resolve: { unsigned identifier = currentInstruction[2].u.operand; - NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier)); + NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(PredictNone)); set(currentInstruction[1].u.operand, resolve); + stronglyPredict(resolve); NEXT_OPCODE(op_resolve); } @@ -1424,17 +1425,21 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_resolve_base: { unsigned identifier = currentInstruction[2].u.operand; - NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier)); + NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(PredictNone)); set(currentInstruction[1].u.operand, resolve); + stronglyPredict(resolve); NEXT_OPCODE(op_resolve_base); } case op_resolve_global: { - unsigned identifier = currentInstruction[2].u.operand; - - NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(identifier), OpInfo(m_globalResolveNumber++)); + NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(PredictNone)); + m_graph.m_resolveGlobalData.append(ResolveGlobalData()); + ResolveGlobalData& data = m_graph.m_resolveGlobalData.last(); + data.identifierNumber = currentInstruction[2].u.operand; + data.resolveInfoIndex = m_globalResolveNumber++; set(currentInstruction[1].u.operand, resolve); + stronglyPredict(resolve); NEXT_OPCODE(op_resolve_global); } diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index 3c8ab23..c754128 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -97,6 +97,11 @@ struct StorageAccessData { // Structure*. }; +struct ResolveGlobalData { + unsigned identifierNumber; + unsigned resolveInfoIndex; +}; + typedef Vector PredecessorList; struct BasicBlock { @@ -197,6 +202,10 @@ public: case Construct: case GetByOffset: case GetScopedVar: + case Resolve: + case ResolveBase: + case ResolveBaseStrictPut: + case ResolveGlobal: return node.predict(prediction, source); default: return false; @@ -316,6 +325,7 @@ public: Vector m_varArgChildren; Vector m_methodCheckData; Vector m_storageAccessData; + Vector m_resolveGlobalData; unsigned m_preservedVars; unsigned m_parameterSlots; private: diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index e721146..e320795 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -467,7 +467,6 @@ struct Node { case Resolve: case ResolveBase: case ResolveBaseStrictPut: - case ResolveGlobal: return true; default: return false; @@ -481,10 +480,10 @@ struct Node { return m_opInfo; } - unsigned resolveInfoIndex() + unsigned resolveGlobalDataIndex() { ASSERT(op == ResolveGlobal); - return m_opInfo2; + return m_opInfo; } bool hasArithNodeFlags() @@ -633,6 +632,10 @@ struct Node { case Construct: case GetByOffset: case GetScopedVar: + case Resolve: + case ResolveBase: + case ResolveBaseStrictPut: + case ResolveGlobal: return true; default: return false; diff --git a/Source/JavaScriptCore/dfg/DFGPropagator.cpp b/Source/JavaScriptCore/dfg/DFGPropagator.cpp index 9bb159f..48c5a85 100644 --- a/Source/JavaScriptCore/dfg/DFGPropagator.cpp +++ b/Source/JavaScriptCore/dfg/DFGPropagator.cpp @@ -534,7 +534,11 @@ private: break; } - case GetScopedVar: { + case GetScopedVar: + case Resolve: + case ResolveBase: + case ResolveBaseStrictPut: + case ResolveGlobal: { changed |= node.predict(m_uses[m_compileIndex] & ~PredictionTagMask, StrongPrediction); PredictedType prediction = node.getPrediction(); if (isStrongPrediction(prediction)) @@ -593,6 +597,7 @@ private: #ifndef NDEBUG // These get ignored because they don't return anything. + case PutScopedVar: case DFG::Jump: case Branch: case Breakpoint: @@ -603,19 +608,9 @@ private: case ThrowReferenceError: break; - // These get ignored because we don't have profiling for them, yet. - case Resolve: - case ResolveBase: - case ResolveBaseStrictPut: - case ResolveGlobal: - case PutScopedVar: - break; - // This gets ignored because it doesn't do anything. case Phantom: break; - - #else default: break; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index b1930ac..4189665 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -2055,7 +2055,8 @@ void SpeculativeJIT::compile(Node& node) GPRReg resolveInfoGPR = resolveInfo.gpr(); GPRReg resultGPR = result.gpr(); - GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(node.resolveInfoIndex())); + ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()]; + GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex)); // Check Structure of global object m_jit.move(JITCompiler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectGPR); @@ -2065,7 +2066,7 @@ void SpeculativeJIT::compile(Node& node) silentSpillAllRegisters(resultGPR); m_jit.move(resolveInfoGPR, GPRInfo::argumentGPR1); - m_jit.move(JITCompiler::TrustedImmPtr(&m_jit.codeBlock()->identifier(node.identifierNumber())), GPRInfo::argumentGPR2); + m_jit.move(JITCompiler::TrustedImmPtr(&m_jit.codeBlock()->identifier(data.identifierNumber)), GPRInfo::argumentGPR2); m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationResolveGlobal); m_jit.move(GPRInfo::returnValueGPR, resultGPR); diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 8f31999..e084da0 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -518,7 +518,7 @@ void JIT::emit_op_resolve(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); - stubCall.call(currentInstruction[1].u.operand); + stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite); } void JIT::emit_op_to_primitive(Instruction* currentInstruction) @@ -549,7 +549,7 @@ void JIT::emit_op_resolve_base(Instruction* currentInstruction) { JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); - stubCall.call(currentInstruction[1].u.operand); + stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite); } void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) @@ -565,7 +565,7 @@ void JIT::emit_op_resolve_skip(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_resolve_skip); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); - stubCall.call(currentInstruction[1].u.operand); + stubCall.callWithValueProfiling(currentInstruction[1].u.operand, FirstProfilingSite); } void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool) @@ -586,6 +586,7 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool) loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0); load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1); loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0); + emitValueProfilingSite(FirstProfilingSite); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -601,7 +602,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vectoridentifier(currentInstruction[3].u.operand))); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); - stubCall.call(currentInstruction[2].u.operand); + stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite); } void JIT::emit_op_resolve_with_this(Instruction* currentInstruction) @@ -730,7 +731,7 @@ void JIT::emit_op_resolve_with_this(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_resolve_with_this); stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); - stubCall.call(currentInstruction[2].u.operand); + stubCall.callWithValueProfiling(currentInstruction[2].u.operand, FirstProfilingSite); } void JIT::emit_op_jtrue(Instruction* currentInstruction) @@ -1531,7 +1532,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(Imm32(currentIndex)); stubCall.addArgument(regT0); - stubCall.call(dst); + stubCall.callWithValueProfiling(dst, SubsequentProfilingSite); // The first profiling site is in emit_op_resolve_global } void JIT::emit_op_new_regexp(Instruction* currentInstruction) diff --git a/Source/JavaScriptCore/jit/JITStubCall.h b/Source/JavaScriptCore/jit/JITStubCall.h index 41411d7..d4ec2d4 100644 --- a/Source/JavaScriptCore/jit/JITStubCall.h +++ b/Source/JavaScriptCore/jit/JITStubCall.h @@ -200,6 +200,11 @@ namespace JSC { m_jit->emitStoreCell(dst, JIT::returnValueRegister); return call; } + + JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind) + { + return call(dst); + } #else JIT::Call call(unsigned dst) // dst is a virtual register. { @@ -208,6 +213,16 @@ namespace JSC { m_jit->emitPutVirtualRegister(dst); return call; } + + JIT::Call callWithValueProfiling(unsigned dst, JIT::ValueProfilingSiteKind kind) + { + ASSERT(m_returnType == VoidPtr || m_returnType == Cell); + JIT::Call call = this->call(); + ASSERT(JIT::returnValueRegister == JIT::regT0); + m_jit->emitValueProfilingSite(kind); + m_jit->emitPutVirtualRegister(dst); + return call; + } #endif JIT::Call call(JIT::RegisterID dst) // dst is a machine register. -- 2.7.4