WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
more things
blah.patch (text/plain), 43.47 KB, created by
Filip Pizlo
on 2013-11-24 15:50:08 PST
(
hide
)
Description:
more things
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-11-24 15:50:08 PST
Size:
43.47 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 159736) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,56 @@ >+2013-11-23 Filip Pizlo <fpizlo@apple.com> >+ >+ Infer one-time scopes >+ https://bugs.webkit.org/show_bug.cgi?id=124812 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This detects JSActivations that are created only once. The JSActivation pointer is then >+ baked into the machine code. >+ >+ * bytecode/CodeBlock.cpp: >+ (JSC::CodeBlock::dumpBytecode): >+ (JSC::CodeBlock::CodeBlock): >+ (JSC::CodeBlock::finalizeUnconditionally): >+ * bytecode/Instruction.h: >+ * bytecode/Opcode.h: >+ (JSC::padOpcodeName): >+ * bytecode/Watchpoint.h: >+ (JSC::InlineWatchpointSet::notifyWrite): >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::emitResolveScope): >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::::executeEffects): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGFixupPhase.cpp: >+ (JSC::DFG::FixupPhase::fixupNode): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::hasSymbolTable): >+ (JSC::DFG::Node::symbolTable): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ (JSC::DFG::PredictionPropagationPhase::propagate): >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGWatchpointCollectionPhase.cpp: >+ (JSC::DFG::WatchpointCollectionPhase::handle): >+ * llint/LowLevelInterpreter64.asm: >+ * runtime/JSActivation.h: >+ (JSC::JSActivation::create): >+ * runtime/JSScope.cpp: >+ (JSC::abstractAccess): >+ (JSC::JSScope::abstractResolve): >+ * runtime/JSScope.h: >+ (JSC::ResolveOp::ResolveOp): >+ * runtime/SymbolTable.cpp: >+ (JSC::SymbolTable::SymbolTable): >+ * runtime/SymbolTable.h: >+ > 2013-11-23 Filip Pizlo <fpizlo@apple.com> > > Fix more fallout from failed attempts at div/mod DFG strength reductions >Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 159736) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -1365,6 +1365,7 @@ void CodeBlock::dumpBytecode(PrintStream > ++it; // depth > printLocationAndOp(out, exec, location, it, "resolve_scope"); > out.printf("%s, %s, %d", registerName(r0).data(), idName(id0, identifier(id0)).data(), resolveModeAndType); >+ ++it; > break; > } > case op_get_from_scope: { >@@ -1753,6 +1754,8 @@ CodeBlock::CodeBlock(ScriptExecutable* o > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Get, type); > instructions[i + 3].u.operand = op.type; > instructions[i + 4].u.operand = op.depth; >+ if (op.activation) >+ instructions[i + 5].u.activation.set(*vm(), ownerExecutable, op.activation); > break; > } > >@@ -1770,7 +1773,9 @@ CodeBlock::CodeBlock(ScriptExecutable* o > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Get, modeAndType.type()); > > instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand(); >- if (op.structure) >+ if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks) >+ instructions[i + 5].u.watchpointSet = op.watchpointSet; >+ else if (op.structure) > instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure); > instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand); > break; >@@ -1783,10 +1788,9 @@ CodeBlock::CodeBlock(ScriptExecutable* o > ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Put, modeAndType.type()); > > instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand(); >- if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks) { >- ASSERT(!op.structure); >+ if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks) > instructions[i + 5].u.watchpointSet = op.watchpointSet; >- } else if (op.structure) >+ else if (op.structure) > instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure); > instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand); > break; >@@ -2172,6 +2176,15 @@ void CodeBlock::finalizeUnconditionally( > dataLogF("Clearing LLInt get callee with function %p.\n", curInstruction[2].u.jsCell.get()); > curInstruction[2].u.jsCell.clear(); > break; >+ case op_resolve_scope: { >+ WriteBarrierBase<JSActivation>& activation = curInstruction[5].u.activation; >+ if (!activation || Heap::isMarked(activation.get())) >+ break; >+ if (Options::verboseOSR()) >+ dataLogF("Clearing dead activation %p.\n", activation.get()); >+ activation.clear(); >+ break; >+ } > case op_get_from_scope: > case op_put_to_scope: { > ResolveModeAndType modeAndType = >@@ -2182,7 +2195,7 @@ void CodeBlock::finalizeUnconditionally( > if (!structure || Heap::isMarked(structure.get())) > break; > if (Options::verboseOSR()) >- dataLogF("Clearing LLInt scope access with structure %p.\n", structure.get()); >+ dataLogF("Clearing scope access with structure %p.\n", structure.get()); > structure.clear(); > break; > } >Index: Source/JavaScriptCore/bytecode/Instruction.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Instruction.h (revision 159736) >+++ Source/JavaScriptCore/bytecode/Instruction.h (working copy) >@@ -116,6 +116,7 @@ struct Instruction { > ArrayAllocationProfile* arrayAllocationProfile; > ObjectAllocationProfile* objectAllocationProfile; > WatchpointSet* watchpointSet; >+ WriteBarrierBase<JSActivation> activation; > void* pointer; > bool* predicatePointer; > } u; >Index: Source/JavaScriptCore/bytecode/Opcode.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Opcode.h (revision 159736) >+++ Source/JavaScriptCore/bytecode/Opcode.h (working copy) >@@ -169,7 +169,7 @@ namespace JSC { > macro(op_get_pnames, 6) \ > macro(op_next_pname, 7) \ > \ >- macro(op_resolve_scope, 5) \ >+ macro(op_resolve_scope, 6) \ > macro(op_get_from_scope, 8) /* has value profiling */ \ > macro(op_put_to_scope, 7) \ > \ >Index: Source/JavaScriptCore/bytecode/Watchpoint.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Watchpoint.h (revision 159736) >+++ Source/JavaScriptCore/bytecode/Watchpoint.h (working copy) >@@ -209,6 +209,19 @@ public: > WTF::storeStoreFence(); > } > >+ void notifyWrite() >+ { >+ if (isFat()) { >+ fat()->notifyWrite(); >+ return; >+ } >+ if (decodeState(m_data) == ClearWatchpoint) >+ m_data = encodeState(IsWatched); >+ else >+ m_data = encodeState(IsInvalidated); >+ WTF::storeStoreFence(); >+ } >+ > private: > static const uintptr_t IsThinFlag = 1; > static const uintptr_t StateMask = 6; >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 159736) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -1212,6 +1212,8 @@ ResolveType BytecodeGenerator::resolveTy > > RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier) > { >+ m_codeBlock->addPropertyAccessInstruction(instructions().size()); >+ > ASSERT(!m_symbolTable || !m_symbolTable->contains(identifier.impl()) || resolveType() == Dynamic); > > // resolve_scope dst, id, ResolveType, depth >@@ -1220,6 +1222,7 @@ RegisterID* BytecodeGenerator::emitResol > instructions().append(addConstant(identifier)); > instructions().append(resolveType()); > instructions().append(0); >+ instructions().append(0); > return dst; > } > >Index: Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (working copy) >@@ -1145,6 +1145,9 @@ bool AbstractInterpreter<AbstractStateTy > m_graph, m_codeBlock->globalObjectFor(node->codeOrigin)->activationStructure()); > m_state.setHaveStructures(true); > break; >+ >+ case ActivationAllocationWatchpoint: >+ break; > > case CreateArguments: > forNode(node).setType(SpecArguments); >@@ -1250,10 +1253,12 @@ bool AbstractInterpreter<AbstractStateTy > break; > > case GetClosureVar: >+ case GetSingletonClosureVar: > forNode(node).makeHeapTop(); > break; > > case PutClosureVar: >+ case PutSingletonClosureVar: > clobberCapturedVars(node->codeOrigin); > break; > >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -36,6 +36,7 @@ > #include "DFGCapabilities.h" > #include "DFGJITCode.h" > #include "GetByIdStatus.h" >+#include "JSActivation.h" > #include "Operations.h" > #include "PreciseJumpTargets.h" > #include "PutByIdStatus.h" >@@ -179,6 +180,19 @@ private: > > Node* getScope(bool skipTop, unsigned skipCount); > >+ WriteBarrierBase<Unknown>* tryGetRegisters(Node* node) >+ { >+ if (!node->hasConstant()) >+ return 0; >+ JSActivation* activation = >+ jsDynamicCast<JSActivation*>(m_graph.valueOfJSConstant(node)); >+ if (!activation) >+ return 0; >+ if (!activation->isTornOff()) >+ return 0; >+ return activation->registers(); >+ } >+ > // Prepare to parse a block. > void prepareToParseBlock(); > // Parse a single basic block of bytecode instructions. >@@ -3046,9 +3060,18 @@ bool ByteCodeParser::parseBlock(unsigned > set(VirtualRegister(dst), cellConstant(m_inlineStackTop->m_codeBlock->globalObject())); > break; > case ClosureVar: >- case ClosureVarWithVarInjectionChecks: >- set(VirtualRegister(dst), getScope(m_inlineStackTop->m_codeBlock->needsActivation(), depth)); >+ case ClosureVarWithVarInjectionChecks: { >+ JSActivation* activation = currentInstruction[5].u.activation.get(); >+ if (activation >+ && activation->symbolTable()->m_activationAllocatedOnce.isStillValid()) { >+ addToGraph(ActivationAllocationWatchpoint, OpInfo(activation->symbolTable())); >+ set(VirtualRegister(dst), cellConstant(activation)); >+ break; >+ } >+ set(VirtualRegister(dst), >+ getScope(m_inlineStackTop->m_codeBlock->needsActivation(), depth)); > break; >+ } > case Dynamic: > RELEASE_ASSERT_NOT_REACHED(); > break; >@@ -3063,11 +3086,15 @@ bool ByteCodeParser::parseBlock(unsigned > StringImpl* uid = m_graph.identifiers()[identifierNumber]; > ResolveType resolveType = ResolveModeAndType(currentInstruction[4].u.operand).type(); > >- Structure* structure; >+ Structure* structure = 0; >+ WatchpointSet* watchpoints = 0; > uintptr_t operand; > { > ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock); >- structure = currentInstruction[5].u.structure.get(); >+ if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks) >+ watchpoints = currentInstruction[5].u.watchpointSet; >+ else >+ structure = currentInstruction[5].u.structure.get(); > operand = reinterpret_cast<uintptr_t>(currentInstruction[6].u.pointer); > } > >@@ -3108,11 +3135,22 @@ bool ByteCodeParser::parseBlock(unsigned > break; > } > case ClosureVar: >- case ClosureVarWithVarInjectionChecks: >+ case ClosureVarWithVarInjectionChecks: { >+ Node* scopeNode = get(VirtualRegister(scope)); >+ if (WriteBarrierBase<Unknown>* registers = tryGetRegisters(scopeNode)) { >+ SingletonClosureVarData* data = &m_graph.m_singletonClosureVarData.alloc(); >+ data->registers = registers; >+ data->operand = operand; >+ addToGraph(Phantom, scopeNode); >+ set(VirtualRegister(dst), >+ addToGraph(GetSingletonClosureVar, OpInfo(data), OpInfo(prediction))); >+ break; >+ } > set(VirtualRegister(dst), > addToGraph(GetClosureVar, OpInfo(operand), OpInfo(prediction), >- addToGraph(GetClosureRegisters, get(VirtualRegister(scope))))); >+ addToGraph(GetClosureRegisters, scopeNode))); > break; >+ } > case Dynamic: > RELEASE_ASSERT_NOT_REACHED(); > break; >@@ -3170,6 +3208,13 @@ bool ByteCodeParser::parseBlock(unsigned > case ClosureVar: > case ClosureVarWithVarInjectionChecks: { > Node* scopeNode = get(VirtualRegister(scope)); >+ if (WriteBarrierBase<Unknown>* registers = tryGetRegisters(scopeNode)) { >+ SingletonClosureVarData* data = &m_graph.m_singletonClosureVarData.alloc(); >+ data->registers = registers; >+ data->operand = operand; >+ addToGraph(PutSingletonClosureVar, OpInfo(data), scopeNode, get(VirtualRegister(value))); >+ break; >+ } > Node* scopeRegisters = addToGraph(GetClosureRegisters, scopeNode); > addToGraph(PutClosureVar, OpInfo(operand), scopeNode, scopeRegisters, get(VirtualRegister(value))); > break; >Index: Source/JavaScriptCore/dfg/DFGCSEPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (working copy) >@@ -227,7 +227,7 @@ private: > return 0; > } > >- Node* scopedVarLoadElimination(Node* registers, unsigned varNumber) >+ Node* scopedVarLoadElimination(Node* registers, int varNumber) > { > for (unsigned i = m_indexInBlock; i--;) { > Node* node = m_currentBlock->at(i); >@@ -244,6 +244,11 @@ private: > return node->child3().node(); > return 0; > } >+ case PutSingletonClosureVar: { >+ if (node->singletonClosureVarData()->operand != varNumber) >+ break; >+ return 0; >+ } > case SetLocal: { > VariableAccessData* variableAccessData = node->variableAccessData(); > if (variableAccessData->isCaptured() >@@ -260,6 +265,44 @@ private: > return 0; > } > >+ Node* singletonScopedVarLoadElimination(SingletonClosureVarData* data) >+ { >+ for (unsigned i = m_indexInBlock; i--;) { >+ Node* node = m_currentBlock->at(i); >+ switch (node->op()) { >+ case GetSingletonClosureVar: { >+ if (node->singletonClosureVarData()->registers == data->registers >+ && node->singletonClosureVarData()->operand == data->operand) >+ return node; >+ break; >+ } >+ case PutClosureVar: { >+ if (node->varNumber() != data->operand) >+ break; >+ return 0; >+ } >+ case PutSingletonClosureVar: { >+ if (node->singletonClosureVarData()->registers == data->registers >+ && node->singletonClosureVarData()->operand == data->operand) >+ return node->child2().node(); >+ break; >+ } >+ case SetLocal: { >+ VariableAccessData* variableAccessData = node->variableAccessData(); >+ if (variableAccessData->isCaptured() >+ && variableAccessData->local() == static_cast<VirtualRegister>(data->operand)) >+ return 0; >+ break; >+ } >+ default: >+ break; >+ } >+ if (m_graph.clobbersWorld(node)) >+ break; >+ } >+ return 0; >+ } >+ > bool globalVarWatchpointElimination(WriteBarrier<Unknown>* registerPointer) > { > for (unsigned i = m_indexInBlock; i--;) { >@@ -318,7 +361,7 @@ private: > return 0; > } > >- Node* scopedVarStoreElimination(Node* scope, Node* registers, unsigned varNumber) >+ Node* scopedVarStoreElimination(Node* scope, Node* registers, int varNumber) > { > for (unsigned i = m_indexInBlock; i--;) { > Node* node = m_currentBlock->at(i); >@@ -331,6 +374,12 @@ private: > return 0; > } > >+ case PutSingletonClosureVar: { >+ if (node->singletonClosureVarData()->operand != varNumber) >+ break; >+ return 0; >+ } >+ > case GetClosureVar: { > // Let's be conservative. > if (node->varNumber() == varNumber) >@@ -338,7 +387,15 @@ private: > break; > } > >- case GetLocal: { >+ case GetSingletonClosureVar: { >+ // Conservative. Let's be it. >+ if (node->singletonClosureVarData()->operand == varNumber) >+ return 0; >+ break; >+ } >+ >+ case GetLocal: >+ case SetLocal: { > VariableAccessData* variableAccessData = node->variableAccessData(); > if (variableAccessData->isCaptured() > && variableAccessData->local() == static_cast<VirtualRegister>(varNumber)) >@@ -355,6 +412,56 @@ private: > return 0; > } > >+ Node* singletonScopedVarStoreElimination(SingletonClosureVarData* data) >+ { >+ for (unsigned i = m_indexInBlock; i--;) { >+ Node* node = m_currentBlock->at(i); >+ switch (node->op()) { >+ case PutClosureVar: { >+ if (node->varNumber() != data->operand) >+ break; >+ return 0; >+ } >+ >+ case PutSingletonClosureVar: { >+ if (node->singletonClosureVarData()->registers == data->registers >+ && node->singletonClosureVarData()->operand == data->operand) >+ return node; >+ break; >+ } >+ >+ case GetClosureVar: { >+ // Let's be conservative. >+ if (node->varNumber() == data->operand) >+ return 0; >+ break; >+ } >+ >+ case GetSingletonClosureVar: { >+ if (node->singletonClosureVarData()->registers == data->registers >+ && node->singletonClosureVarData()->operand == data->operand) >+ return 0; >+ break; >+ } >+ >+ case GetLocal: >+ case SetLocal: { >+ VariableAccessData* variableAccessData = node->variableAccessData(); >+ if (variableAccessData->isCaptured() >+ && variableAccessData->local() == VirtualRegister(data->operand)) >+ return 0; >+ break; >+ } >+ >+ default: >+ break; >+ } >+ if (m_graph.clobbersWorld(node) || node->canExit()) >+ return 0; >+ } >+ return 0; >+ } >+ > Node* getByValLoadElimination(Node* child1, Node* child2) > { > for (unsigned i = m_indexInBlock; i--;) { >@@ -851,11 +958,18 @@ private: > } > break; > >+ case GetClosureVar: > case PutClosureVar: > if (static_cast<VirtualRegister>(node->varNumber()) == local) > return 0; > break; > >+ case GetSingletonClosureVar: >+ case PutSingletonClosureVar: >+ if (VirtualRegister(node->singletonClosureVarData()->operand) == local) >+ return 0; >+ break; >+ > default: > if (careAboutClobbering && m_graph.clobbersWorld(node)) > return 0; >@@ -904,10 +1018,17 @@ private: > } > > case GetClosureVar: >+ case PutClosureVar: > if (static_cast<VirtualRegister>(node->varNumber()) == local) > result.mayBeAccessed = true; > break; > >+ case GetSingletonClosureVar: >+ case PutSingletonClosureVar: >+ if (VirtualRegister(node->singletonClosureVarData()->operand) == local) >+ result.mayBeAccessed = true; >+ break; >+ > case GetMyScope: > case SkipTopScope: > if (node->codeOrigin.inlineCallFrame) >@@ -1229,6 +1350,13 @@ private: > break; > } > >+ case GetSingletonClosureVar: { >+ if (cseMode == StoreElimination) >+ break; >+ setReplacement(singletonScopedVarLoadElimination(node->singletonClosureVarData())); >+ break; >+ } >+ > case GlobalVarWatchpoint: > if (cseMode == StoreElimination) > break; >@@ -1256,6 +1384,13 @@ private: > break; > } > >+ case PutSingletonClosureVar: { >+ if (cseMode == NormalCSE) >+ break; >+ eliminate(singletonScopedVarStoreElimination(node->singletonClosureVarData())); >+ break; >+ } >+ > case GetByVal: > if (cseMode == StoreElimination) > break; >Index: Source/JavaScriptCore/dfg/DFGClobberize.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGClobberize.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGClobberize.h (working copy) >@@ -145,14 +145,20 @@ void clobberize(Graph& graph, Node* node > > case NotifyPutGlobalVar: > write(Watchpoint_fire); >+ write(SideState); > return; > > case CreateActivation: > case CreateArguments: > write(SideState); >+ write(Watchpoint_fire); > read(GCState); > write(GCState); > return; >+ >+ case ActivationAllocationWatchpoint: >+ read(Watchpoint_fire); >+ return; > > // These are forward-exiting nodes that assume that the subsequent instruction > // is a MovHint, and they try to roll forward over this MovHint in their >@@ -515,10 +521,18 @@ void clobberize(Graph& graph, Node* node > read(AbstractHeap(Variables, node->varNumber())); > return; > >+ case GetSingletonClosureVar: >+ read(AbstractHeap(Variables, node->singletonClosureVarData()->operand)); >+ return; >+ > case PutClosureVar: > write(AbstractHeap(Variables, node->varNumber())); > return; > >+ case PutSingletonClosureVar: >+ write(AbstractHeap(Variables, node->singletonClosureVarData()->operand)); >+ return; >+ > case GetGlobalVar: > case GlobalVarWatchpoint: > read(AbstractHeap(Absolute, node->registerPointer())); >Index: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (working copy) >@@ -767,7 +767,8 @@ private: > case PutStructure: > case AllocatePropertyStorage: > case ReallocatePropertyStorage: >- case GetScope: { >+ case GetScope: >+ case PutSingletonClosureVar: { > fixEdge<KnownCellUse>(node->child1()); > break; > } >@@ -901,6 +902,7 @@ private: > case GetLocalUnlinked: > case GetMyScope: > case GetClosureVar: >+ case GetSingletonClosureVar: > case GetGlobalVar: > case PutGlobalVar: > case NotifyPutGlobalVar: >@@ -939,6 +941,7 @@ private: > case Unreachable: > case ExtractOSREntryLocal: > case LoopHint: >+ case ActivationAllocationWatchpoint: > break; > #else > default: >Index: Source/JavaScriptCore/dfg/DFGGraph.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGGraph.h (working copy) >@@ -810,6 +810,7 @@ public: > SegmentedVector<StructureTransitionData, 8> m_structureTransitionData; > SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData; > SegmentedVector<SwitchData, 4> m_switchData; >+ SegmentedVector<SingletonClosureVarData, 4> m_singletonClosureVarData; > Vector<InlineVariableData, 4> m_inlineVariableData; > OwnPtr<InlineCallFrameSet> m_inlineCallFrames; > HashMap<CodeBlock*, std::unique_ptr<FullBytecodeLiveness>> m_bytecodeLiveness; >Index: Source/JavaScriptCore/dfg/DFGNode.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNode.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGNode.h (working copy) >@@ -139,6 +139,11 @@ struct SwitchData { > bool didUseJumpTable; > }; > >+struct SingletonClosureVarData { >+ WriteBarrierBase<Unknown>* registers; >+ int operand; >+}; >+ > // This type used in passing an immediate argument to Node constructor; > // distinguishes an immediate value (typically an index into a CodeBlock data structure - > // a constant index, argument, or identifier) from a Node*. >@@ -742,7 +747,7 @@ struct Node { > return op() == GetClosureVar || op() == PutClosureVar; > } > >- unsigned varNumber() >+ int varNumber() > { > ASSERT(hasVarNumber()); > return m_opInfo; >@@ -768,6 +773,16 @@ struct Node { > { > return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo); > } >+ >+ bool hasSingletonClosureVarData() >+ { >+ return op() == GetSingletonClosureVar || op() == PutSingletonClosureVar; >+ } >+ >+ SingletonClosureVarData* singletonClosureVarData() >+ { >+ return bitwise_cast<SingletonClosureVarData*>(m_opInfo); >+ } > > bool hasResult() > { >@@ -921,6 +936,7 @@ struct Node { > case Construct: > case GetByOffset: > case GetClosureVar: >+ case GetSingletonClosureVar: > case ArrayPop: > case ArrayPush: > case RegExpExec: >@@ -1062,6 +1078,17 @@ struct Node { > return m_opInfo; > } > >+ bool hasSymbolTable() >+ { >+ return op() == ActivationAllocationWatchpoint; >+ } >+ >+ SymbolTable* symbolTable() >+ { >+ ASSERT(hasSymbolTable()); >+ return reinterpret_cast<SymbolTable*>(m_opInfo); >+ } >+ > bool hasArrayMode() > { > switch (op()) { >Index: Source/JavaScriptCore/dfg/DFGNodeType.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGNodeType.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGNodeType.h (working copy) >@@ -182,11 +182,14 @@ namespace JSC { namespace DFG { > macro(GetClosureRegisters, NodeResultStorage) \ > macro(GetClosureVar, NodeResultJS) \ > macro(PutClosureVar, NodeMustGenerate) \ >+ macro(GetSingletonClosureVar, NodeResultJS) \ >+ macro(PutSingletonClosureVar, NodeMustGenerate) \ > macro(GetGlobalVar, NodeResultJS) \ > macro(PutGlobalVar, NodeMustGenerate) \ > macro(NotifyPutGlobalVar, NodeMustGenerate) \ > macro(GlobalVarWatchpoint, NodeMustGenerate) \ > macro(VarInjectionWatchpoint, NodeMustGenerate) \ >+ macro(ActivationAllocationWatchpoint, NodeMustGenerate) \ > macro(CheckFunction, NodeMustGenerate) \ > macro(AllocationProfileWatchpoint, NodeMustGenerate) \ > \ >Index: Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (working copy) >@@ -191,7 +191,8 @@ private: > case Call: > case Construct: > case GetGlobalVar: >- case GetClosureVar: { >+ case GetClosureVar: >+ case GetSingletonClosureVar: { > changed |= setPrediction(node->getHeapPrediction()); > break; > } >@@ -553,6 +554,7 @@ private: > case PutByValDirect: > case PutByVal: > case PutClosureVar: >+ case PutSingletonClosureVar: > case Return: > case Throw: > case PutById: >@@ -583,6 +585,7 @@ private: > case Unreachable: > case LoopHint: > case NotifyPutGlobalVar: >+ case ActivationAllocationWatchpoint: > break; > > // This gets ignored because it already has a prediction. >Index: Source/JavaScriptCore/dfg/DFGSafeToExecute.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSafeToExecute.h (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGSafeToExecute.h (working copy) >@@ -169,7 +169,9 @@ bool safeToExecute(AbstractStateType& st > case SkipScope: > case GetClosureRegisters: > case GetClosureVar: >+ case GetSingletonClosureVar: > case PutClosureVar: >+ case PutSingletonClosureVar: > case GetGlobalVar: > case PutGlobalVar: > case GlobalVarWatchpoint: >@@ -243,6 +245,7 @@ bool safeToExecute(AbstractStateType& st > case Int52ToValue: > case InvalidationPoint: > case NotifyPutGlobalVar: >+ case ActivationAllocationWatchpoint: > return true; > > case GetByVal: >Index: Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (working copy) >@@ -4009,6 +4009,13 @@ void SpeculativeJIT::compile(Node* node) > jsValueResult(resultGPR, node); > break; > } >+ case GetSingletonClosureVar: { >+ GPRTemporary result(this); >+ GPRReg resultGPR = result.gpr(); >+ m_jit.load64(node->singletonClosureVarData()->registers + node->singletonClosureVarData()->operand, resultGPR); >+ jsValueResult(resultGPR, node); >+ break; >+ } > case PutClosureVar: { > SpeculateCellOperand scope(this, node->child1()); > StorageOperand registers(this, node->child2()); >@@ -4025,6 +4032,20 @@ void SpeculativeJIT::compile(Node* node) > noResult(node); > break; > } >+ case PutSingletonClosureVar: { >+ SpeculateCellOperand scope(this, node->child1()); >+ JSValueOperand value(this, node->child2()); >+ GPRTemporary scratchRegister(this); >+ >+ GPRReg scopeGPR = scope.gpr(); >+ GPRReg valueGPR = value.gpr(); >+ GPRReg scratchGPR = scratchRegister.gpr(); >+ >+ m_jit.store64(valueGPR, node->singletonClosureVarData()->registers + node->singletonClosureVarData()->operand); >+ writeBarrier(scopeGPR, valueGPR, node->child2(), WriteBarrierForVariableAccess, scratchGPR); >+ noResult(node); >+ break; >+ } > case GetById: { > ASSERT(node->prediction()); > >@@ -4595,6 +4616,11 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >+ case ActivationAllocationWatchpoint: { >+ noResult(node); >+ break; >+ } >+ > case CreateArguments: { > JSValueOperand value(this, node->child1()); > GPRTemporary result(this, Reuse, value); >Index: Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp (revision 159736) >+++ Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp (working copy) >@@ -128,6 +128,10 @@ private: > addLazily(globalObject()->varInjectionWatchpoint()); > break; > >+ case ActivationAllocationWatchpoint: >+ addLazily(m_node->symbolTable()->m_activationAllocatedOnce); >+ break; >+ > default: > break; > } >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 159736) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -1831,39 +1831,39 @@ _llint_op_resolve_scope: > #rGlobalProperty: > bineq t0, GlobalProperty, .rGlobalVar > getGlobalObject(1) >- dispatch(5) >+ dispatch(6) > > .rGlobalVar: > bineq t0, GlobalVar, .rClosureVar > getGlobalObject(1) >- dispatch(5) >+ dispatch(6) > > .rClosureVar: > bineq t0, ClosureVar, .rGlobalPropertyWithVarInjectionChecks > resolveScope() >- dispatch(5) >+ dispatch(6) > > .rGlobalPropertyWithVarInjectionChecks: > bineq t0, GlobalPropertyWithVarInjectionChecks, .rGlobalVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getGlobalObject(1) >- dispatch(5) >+ dispatch(6) > > .rGlobalVarWithVarInjectionChecks: > bineq t0, GlobalVarWithVarInjectionChecks, .rClosureVarWithVarInjectionChecks > varInjectionCheck(.rDynamic) > getGlobalObject(1) >- dispatch(5) >+ dispatch(6) > > .rClosureVarWithVarInjectionChecks: > bineq t0, ClosureVarWithVarInjectionChecks, .rDynamic > varInjectionCheck(.rDynamic) > resolveScope() >- dispatch(5) >+ dispatch(6) > > .rDynamic: > callSlowPath(_llint_slow_path_resolve_scope) >- dispatch(5) >+ dispatch(6) > > > macro loadWithStructureCheck(operand, slowPath) >Index: Source/JavaScriptCore/runtime/JSActivation.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSActivation.h (revision 159736) >+++ Source/JavaScriptCore/runtime/JSActivation.h (working copy) >@@ -49,6 +49,7 @@ public: > static JSActivation* create(VM& vm, CallFrame* callFrame, Register* registers, CodeBlock* codeBlock) > { > SymbolTable* symbolTable = codeBlock->symbolTable(); >+ symbolTable->m_activationAllocatedOnce.notifyWrite(); > JSActivation* activation = new ( > NotNull, > allocateCell<JSActivation>( >Index: Source/JavaScriptCore/runtime/JSScope.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSScope.cpp (revision 159736) >+++ Source/JavaScriptCore/runtime/JSScope.cpp (working copy) >@@ -53,19 +53,19 @@ static inline bool abstractAccess(ExecSt > if (JSActivation* activation = jsDynamicCast<JSActivation*>(scope)) { > if (ident == exec->propertyNames().arguments) { > // We know the property will be at this activation scope, but we don't know how to cache it. >- op = ResolveOp(Dynamic, 0, 0, 0, 0); >+ op = ResolveOp(Dynamic, 0, 0, 0, 0, 0); > return true; > } > > SymbolTableEntry entry = activation->symbolTable()->get(ident.impl()); > if (entry.isReadOnly() && getOrPut == Put) { > // We know the property will be at this activation scope, but we don't know how to cache it. >- op = ResolveOp(Dynamic, 0, 0, 0, 0); >+ op = ResolveOp(Dynamic, 0, 0, 0, 0, 0); > return true; > } > > if (!entry.isNull()) { >- op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, activation->structure(), 0, entry.getIndex()); >+ op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, activation, 0, entry.getIndex()); > return true; > } > >@@ -79,12 +79,12 @@ static inline bool abstractAccess(ExecSt > if (!entry.isNull()) { > if (getOrPut == Put && entry.isReadOnly()) { > // We know the property will be at global scope, but we don't know how to cache it. >- op = ResolveOp(Dynamic, 0, 0, 0, 0); >+ op = ResolveOp(Dynamic, 0, 0, 0, 0, 0); > return true; > } > > op = ResolveOp( >- makeType(GlobalVar, needsVarInjectionChecks), depth, 0, entry.watchpointSet(), >+ makeType(GlobalVar, needsVarInjectionChecks), depth, 0, 0, entry.watchpointSet(), > reinterpret_cast<uintptr_t>(globalObject->registerAt(entry.getIndex()).slot())); > return true; > } >@@ -96,15 +96,15 @@ static inline bool abstractAccess(ExecSt > || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) { > // We know the property will be at global scope, but we don't know how to cache it. > ASSERT(!scope->next()); >- op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0); >+ op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0); > return true; > } > >- op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, slot.cachedOffset()); >+ op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset()); > return true; > } > >- op = ResolveOp(Dynamic, 0, 0, 0, 0); >+ op = ResolveOp(Dynamic, 0, 0, 0, 0, 0); > return true; > } > >@@ -142,7 +142,7 @@ JSValue JSScope::resolve(ExecState* exec > > ResolveOp JSScope::abstractResolve(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType) > { >- ResolveOp op(Dynamic, 0, 0, 0, 0); >+ ResolveOp op(Dynamic, 0, 0, 0, 0, 0); > if (unlinkedType == Dynamic) > return op; > >Index: Source/JavaScriptCore/runtime/JSScope.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSScope.h (revision 159736) >+++ Source/JavaScriptCore/runtime/JSScope.h (working copy) >@@ -96,10 +96,11 @@ inline bool needsVarInjectionChecks(Reso > } > > struct ResolveOp { >- ResolveOp(ResolveType type, size_t depth, Structure* structure, WatchpointSet* watchpointSet, uintptr_t operand) >+ ResolveOp(ResolveType type, size_t depth, Structure* structure, JSActivation* activation, WatchpointSet* watchpointSet, uintptr_t operand) > : type(type) > , depth(depth) > , structure(structure) >+ , activation(activation) > , watchpointSet(watchpointSet) > , operand(operand) > { >@@ -108,6 +109,7 @@ struct ResolveOp { > ResolveType type; > size_t depth; > Structure* structure; >+ JSActivation* activation; > WatchpointSet* watchpointSet; > uintptr_t operand; > }; >Index: Source/JavaScriptCore/runtime/JSVariableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSVariableObject.h (revision 159736) >+++ Source/JavaScriptCore/runtime/JSVariableObject.h (working copy) >@@ -46,6 +46,7 @@ class JSVariableObject : public JSSymbol > public: > typedef JSSymbolTableObject Base; > >+ WriteBarrierBase<Unknown>* registers() { return m_registers; } > WriteBarrierBase<Unknown>& registerAt(int index) const { return m_registers[index]; } > > WriteBarrierBase<Unknown>* const * addressOfRegisters() const { return &m_registers; } >Index: Source/JavaScriptCore/runtime/SymbolTable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.cpp (revision 159736) >+++ Source/JavaScriptCore/runtime/SymbolTable.cpp (working copy) >@@ -104,6 +104,7 @@ SymbolTable::SymbolTable(VM& vm) > , m_usesNonStrictEval(false) > , m_captureStart(0) > , m_captureEnd(0) >+ , m_activationAllocatedOnce(ClearWatchpoint) > { > } > >Index: Source/JavaScriptCore/runtime/SymbolTable.h >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.h (revision 159736) >+++ Source/JavaScriptCore/runtime/SymbolTable.h (working copy) >@@ -465,7 +465,7 @@ public: > // 0 if we don't capture any arguments; parameterCount() in length if we do. > const SlowArgument* slowArguments() { return m_slowArguments.get(); } > void setSlowArguments(std::unique_ptr<SlowArgument[]> slowArguments) { m_slowArguments = std::move(slowArguments); } >- >+ > DECLARE_EXPORT_INFO; > > private: >@@ -481,8 +481,10 @@ private: > int m_captureEnd; > > std::unique_ptr<SlowArgument[]> m_slowArguments; >- >+ > public: >+ InlineWatchpointSet m_activationAllocatedOnce; >+ > mutable ConcurrentJITLock m_lock; > }; > >Index: LayoutTests/js/regress/infer-one-time-closure-expected.txt >=================================================================== >--- LayoutTests/js/regress/infer-one-time-closure-expected.txt (revision 0) >+++ LayoutTests/js/regress/infer-one-time-closure-expected.txt (working copy) >@@ -0,0 +1,10 @@ >+JSRegress/infer-one-time-closure >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS no exception thrown >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >Index: LayoutTests/js/regress/infer-one-time-closure.html >=================================================================== >--- LayoutTests/js/regress/infer-one-time-closure.html (revision 0) >+++ LayoutTests/js/regress/infer-one-time-closure.html (working copy) >@@ -0,0 +1,12 @@ >+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> >+<html> >+<head> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script src="resources/regress-pre.js"></script> >+<script src="script-tests/infer-one-time-closure.js"></script> >+<script src="resources/regress-post.js"></script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >Index: LayoutTests/js/regress/script-tests/infer-one-time-closure.js >=================================================================== >--- LayoutTests/js/regress/script-tests/infer-one-time-closure.js (revision 0) >+++ LayoutTests/js/regress/script-tests/infer-one-time-closure.js (working copy) >@@ -0,0 +1,22 @@ >+function fooMaker(xParam) { >+ var x = xParam; >+ return function (y) { >+ for (var i = 0; i < 1000; ++i) >+ y += x; >+ return y; >+ } >+} >+ >+var foo = fooMaker(42); >+ >+noInline(foo); >+ >+for (var i = 0; i < 10000; ++i) { >+ var result = foo(5); >+ if (result != 42 * 1000 + 5) >+ throw "Error: bad result: " + result; >+} >+ >+var result = fooMaker(23)(5); >+if (result != 23 * 1000 + 5) >+ throw "Error: bad result: " + result;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 124812
:
217756
|
217766
|
217768
|
217769
|
217974
|
217980