WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
I wrote all of the code.
blah.patch (text/plain), 36.06 KB, created by
Filip Pizlo
on 2013-12-02 15:26:24 PST
(
hide
)
Description:
I wrote all of the code.
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2013-12-02 15:26:24 PST
Size:
36.06 KB
patch
obsolete
>Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 159944) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -768,6 +768,7 @@ void CodeBlock::dumpBytecode(PrintStream > int r1 = (++it)->u.operand; > printLocationAndOp(out, exec, location, it, "captured_mov"); > out.printf("%s, %s", registerName(r0).data(), registerName(r1).data()); >+ ++it; > break; > } > case op_not: { >@@ -1224,9 +1225,9 @@ void CodeBlock::dumpBytecode(PrintStream > case op_new_captured_func: { > int r0 = (++it)->u.operand; > int f0 = (++it)->u.operand; >- int shouldCheck = (++it)->u.operand; > printLocationAndOp(out, exec, location, it, "new_captured_func"); >- out.printf("%s, f%d, %s", registerName(r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>"); >+ out.printf("%s, f%d", registerName(r0).data(), f0); >+ ++it; > break; > } > case op_new_func_exp: { >@@ -1551,10 +1552,13 @@ CodeBlock::CodeBlock(ScriptExecutable* o > { > ASSERT(m_heap->isDeferred()); > >+ bool didCloneSymbolTable = false; >+ > if (SymbolTable* symbolTable = unlinkedCodeBlock->symbolTable()) { >- if (codeType() == FunctionCode && symbolTable->captureCount()) >+ if (codeType() == FunctionCode && symbolTable->captureCount()) { > m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable->clone(*m_vm)); >- else >+ didCloneSymbolTable = true; >+ } else > m_symbolTable.set(*m_vm, m_ownerExecutable.get(), symbolTable); > } > >@@ -1820,11 +1824,27 @@ CodeBlock::CodeBlock(ScriptExecutable* o > instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand(); > if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks) > instructions[i + 5].u.watchpointSet = op.watchpointSet; >+ else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) >+ op.watchpointSet->invalidate(); > 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; > } >+ >+ case op_captured_mov: >+ case op_new_captured_func: { >+ StringImpl* uid = pc[i + 3].u.uid; >+ if (!uid) >+ break; >+ RELEASE_ASSERT(didCloneSymbolTable); >+ ConcurrentJITLocker locker(m_symbolTable->m_lock); >+ SymbolTable::Map::iterator iter = m_symbolTable->find(locker, uid); >+ ASSERT(iter != m_symbolTable->end(locker)); >+ iter->value.prepareToWatch(); >+ pc[i + 3].u.watchpointSet = iter->value.watchpointSet(); >+ break; >+ } > > default: > break; >Index: Source/JavaScriptCore/bytecode/Instruction.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Instruction.h (revision 159944) >+++ Source/JavaScriptCore/bytecode/Instruction.h (working copy) >@@ -90,16 +90,13 @@ struct Instruction { > Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; } > > Instruction(LLIntCallLinkInfo* callLinkInfo) { u.callLinkInfo = callLinkInfo; } >- > Instruction(ValueProfile* profile) { u.profile = profile; } > Instruction(ArrayProfile* profile) { u.arrayProfile = profile; } > Instruction(ArrayAllocationProfile* profile) { u.arrayAllocationProfile = profile; } > Instruction(ObjectAllocationProfile* profile) { u.objectAllocationProfile = profile; } >- > Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; } >- > Instruction(Special::Pointer pointer) { u.specialPointer = pointer; } >- >+ Instruction(StringImpl* uid) { u.uid = uid; } > Instruction(bool* predicatePointer) { u.predicatePointer = predicatePointer; } > > union { >@@ -112,6 +109,7 @@ struct Instruction { > Special::Pointer specialPointer; > PropertySlot::GetValueFunc getterFunc; > LLIntCallLinkInfo* callLinkInfo; >+ StringImpl* uid; > ValueProfile* profile; > ArrayProfile* arrayProfile; > ArrayAllocationProfile* arrayAllocationProfile; >Index: Source/JavaScriptCore/bytecode/Opcode.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Opcode.h (revision 159944) >+++ Source/JavaScriptCore/bytecode/Opcode.h (working copy) >@@ -55,7 +55,7 @@ namespace JSC { > macro(op_new_array_buffer, 5) \ > macro(op_new_regexp, 3) \ > macro(op_mov, 3) \ >- macro(op_captured_mov, 3) \ >+ macro(op_captured_mov, 4) \ > \ > macro(op_not, 3) \ > macro(op_eq, 4) \ >Index: Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >=================================================================== >--- Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (revision 159944) >+++ Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (working copy) >@@ -229,9 +229,11 @@ struct UnlinkedInstruction { > UnlinkedInstruction() { u.operand = 0; } > UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; } > UnlinkedInstruction(int operand) { u.operand = operand; } >+ UnlinkedInstruction(StringImpl* uid) { u.uid = uid; } > union { > OpcodeID opcode; > int32_t operand; >+ StringImpl* uid; > } u; > }; > >Index: Source/JavaScriptCore/bytecode/VariableWatchpointSet.h >=================================================================== >--- Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (revision 159944) >+++ Source/JavaScriptCore/bytecode/VariableWatchpointSet.h (working copy) >@@ -80,10 +80,8 @@ public: > > void invalidate() > { >- ASSERT(!!m_inferredValue); >- ASSERT(state() == IsWatched); > m_inferredValue = JSValue(); >- fireAll(); >+ Watchpoint::invalidate(); > } > > void finalizeUnconditionally() >Index: Source/JavaScriptCore/bytecode/Watchpoint.h >=================================================================== >--- Source/JavaScriptCore/bytecode/Watchpoint.h (revision 159944) >+++ Source/JavaScriptCore/bytecode/Watchpoint.h (working copy) >@@ -115,6 +115,13 @@ public: > else > fireAll(); > } >+ >+ void invalidate() >+ { >+ if (state() == IsWatched) >+ fireAll(); >+ m_state = IsInvalidated; >+ } > > int8_t* addressOfState() { return &m_state; } > int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; } >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 159944) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -115,19 +115,31 @@ ParserError BytecodeGenerator::generate( > return ParserError(ParserError::ErrorNone); > } > >-bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0) >+bool BytecodeGenerator::addVar( >+ const Identifier& ident, ConstantMode constantMode, WatchMode watchMode, RegisterID*& r0) > { >+ ASSERT(static_cast<size_t>(m_codeBlock->m_numVars) == m_calleeRegisters.size()); >+ > ConcurrentJITLocker locker(symbolTable().m_lock); > int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset(); >- SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); >+ SymbolTableEntry newEntry(index, constantMode == IsConstant ? ReadOnly : 0); > SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry); > > if (!result.isNewEntry) { > r0 = ®isterFor(result.iterator->value.getIndex()); > return false; > } >- >+ >+ if (watchMode == IsWatchable) { >+ while (m_watchableVariables.size() < static_cast<size_t>(m_codeBlock->m_numVars)) >+ m_watchableVariables.append(nullptr); >+ m_watchableVariables.append(ident.impl()); >+ } >+ > r0 = addVar(); >+ >+ ASSERT(watchMode == NotWatchable || static_cast<size_t>(m_codeBlock->m_numVars) == m_watchableVariables.size()); >+ > return true; > } > >@@ -236,7 +248,7 @@ BytecodeGenerator::BytecodeGenerator(VM& > > if (functionBody->usesArguments() || codeBlock->usesEval()) { // May reify arguments object. > RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. >- RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'. >+ RegisterID* argumentsRegister = addVar(propertyNames().arguments, IsVariable, NotWatchable); // Can be changed by assigning to 'arguments'. > > // We can save a little space by hard-coding the knowledge that the two > // 'arguments' values are stored in consecutive registers, and storing >@@ -307,13 +319,13 @@ BytecodeGenerator::BytecodeGenerator(VM& > instructions().append(m_activationRegister->index()); > } > m_functions.add(ident.impl()); >- emitNewFunction(addVar(ident, false), IsCaptured, function); >+ emitNewFunction(addVar(ident, IsVariable, IsWatchable), IsCaptured, function); > } > } > for (size_t i = 0; i < varStack.size(); ++i) { > const Identifier& ident = varStack[i].first; > if (functionBody->captures(ident)) >- addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); >+ addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, IsWatchable); > } > } > bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; >@@ -331,7 +343,7 @@ BytecodeGenerator::BytecodeGenerator(VM& > const Identifier& ident = function->ident(); > if (!functionBody->captures(ident)) { > m_functions.add(ident.impl()); >- RefPtr<RegisterID> reg = addVar(ident, false); >+ RefPtr<RegisterID> reg = addVar(ident, IsVariable, NotWatchable); > // Don't lazily create functions that override the name 'arguments' > // as this would complicate lazy instantiation of actual arguments. > if (!canLazilyCreateFunctions || ident == propertyNames().arguments) >@@ -346,7 +358,7 @@ BytecodeGenerator::BytecodeGenerator(VM& > for (size_t i = 0; i < varStack.size(); ++i) { > const Identifier& ident = varStack[i].first; > if (!functionBody->captures(ident)) >- addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); >+ addVar(ident, (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, NotWatchable); > } > > if (shouldCaptureAllTheThings) >@@ -457,6 +469,7 @@ RegisterID* BytecodeGenerator::emitInitL > { > emitOpcode(op_init_lazy_reg); > instructions().append(reg->index()); >+ ASSERT(!watchableVariable(reg->index())); > return reg; > } > >@@ -1007,6 +1020,8 @@ RegisterID* BytecodeGenerator::emitMove( > emitOpcode(captureMode == IsCaptured ? op_captured_mov : op_mov); > instructions().append(dst->index()); > instructions().append(src->index()); >+ if (captureMode == IsCaptured) >+ instructions().append(watchableVariable(dst->index())); > return dst; > } > >@@ -1579,7 +1594,11 @@ RegisterID* BytecodeGenerator::emitNewFu > emitOpcode(captureMode == IsCaptured ? op_new_captured_func : op_new_func); > instructions().append(dst->index()); > instructions().append(index); >- instructions().append(doNullCheck); >+ if (captureMode == IsCaptured) { >+ ASSERT(!doNullCheck); >+ instructions().append(watchableVariable(dst->index())); >+ } else >+ instructions().append(doNullCheck); > return dst; > } > >@@ -1621,6 +1640,7 @@ void BytecodeGenerator::createArgumentsI > > emitOpcode(op_create_arguments); > instructions().append(m_codeBlock->argumentsRegister().offset()); >+ ASSERT(!watchableVariable(m_codeBlock->argumentsRegister().offset())); > } > > void BytecodeGenerator::createActivationIfNecessary() >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (revision 159944) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (working copy) >@@ -497,15 +497,16 @@ namespace JSC { > RegisterID* newRegister(); > > // Adds a var slot and maps it to the name ident in symbolTable(). >- RegisterID* addVar(const Identifier& ident, bool isConstant) >+ enum WatchMode { IsWatchable, NotWatchable }; >+ RegisterID* addVar(const Identifier& ident, ConstantMode constantMode, WatchMode watchMode) > { > RegisterID* local; >- addVar(ident, isConstant, local); >+ addVar(ident, constantMode, watchMode, local); > return local; > } > > // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used. >- bool addVar(const Identifier&, bool isConstant, RegisterID*&); >+ bool addVar(const Identifier&, ConstantMode, WatchMode, RegisterID*&); > > // Adds an anonymous var slot. To give this slot a name, add it to symbolTable(). > RegisterID* addVar() >@@ -590,6 +591,16 @@ namespace JSC { > void createActivationIfNecessary(); > RegisterID* createLazyRegisterIfNecessary(RegisterID*); > >+ StringImpl* watchableVariable(int operand) >+ { >+ VirtualRegister reg(operand); >+ if (!reg.isLocal()) >+ return 0; >+ if (static_cast<size_t>(reg.toLocal()) >= m_watchableVariables.size()) >+ return 0; >+ return m_watchableVariables[reg.toLocal()]; >+ } >+ > Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions; > > bool m_shouldEmitDebugHooks; >@@ -609,6 +620,7 @@ namespace JSC { > RegisterID* m_activationRegister; > RegisterID* m_emptyValueRegister; > RegisterID* m_globalObjectRegister; >+ Vector<StringImpl*, 16> m_watchableVariables; > SegmentedVector<RegisterID, 32> m_constantPoolRegisters; > SegmentedVector<RegisterID, 32> m_calleeRegisters; > SegmentedVector<RegisterID, 32> m_parameters; >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 159944) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -216,6 +216,16 @@ private: > > Node* get(VirtualRegister operand) > { >+ if (operand.isLocal() >+ && static_cast<size_t>(operand.toLocal()) < m_localWatchpoints.size()) { >+ if (VariableWatchpointSet* set = m_localWatchpoints[operand.toLocal()]) { >+ if (JSValue value = set->inferredValue()) { >+ addToGraph(FunctionReentryWatchpoint, OpInfo(m_codeBlock->symbolTable())); >+ addToGraph(VariableWatchpoint, OpInfo(set)); >+ return inferredConstant(value); >+ } >+ } >+ } > if (inlineCallFrame()) { > if (!inlineCallFrame()->isClosureCall) { > JSFunction* callee = inlineCallFrame()->calleeConstant(); >@@ -684,6 +694,13 @@ private: > return result.iterator->value; > } > >+ Node* inferredConstant(JSValue value) >+ { >+ if (value.isCell()) >+ return cellConstant(value.asCell()); >+ return getJSConstantForValue(value, 0); >+ } >+ > InlineCallFrame* inlineCallFrame() > { > return m_inlineStackTop->m_inlineCallFrame; >@@ -1000,6 +1017,8 @@ private: > > HashMap<ConstantBufferKey, unsigned> m_constantBufferCache; > >+ Vector<VariableWatchpointSet*, 16> m_localWatchpoints; >+ > struct InlineStackEntry { > ByteCodeParser* m_byteCodeParser; > >@@ -2146,12 +2165,19 @@ bool ByteCodeParser::parseBlock(unsigned > addToGraph(Breakpoint); > NEXT_OPCODE(op_debug); > #endif >- case op_mov: >- case op_captured_mov: { >+ case op_mov: { > Node* op = get(VirtualRegister(currentInstruction[2].u.operand)); > set(VirtualRegister(currentInstruction[1].u.operand), op); > NEXT_OPCODE(op_mov); > } >+ >+ case op_captured_mov: { >+ Node* op = get(VirtualRegister(currentInstruction[2].u.operand)); >+ if (VariableWatchpointSet* set = currentInstruction[3].u.watchpointSet) >+ addToGraph(NotifyWrite, OpInfo(set), op); >+ set(VirtualRegister(currentInstruction[1].u.operand), op); >+ NEXT_OPCODE(op_captured_mov); >+ } > > case op_check_has_instance: > addToGraph(CheckHasInstance, get(VirtualRegister(currentInstruction[3].u.operand))); >@@ -3078,15 +3104,27 @@ bool ByteCodeParser::parseBlock(unsigned > } > > addToGraph(VariableWatchpoint, OpInfo(watchpointSet)); >- if (specificValue.isCell()) >- set(VirtualRegister(dst), cellConstant(specificValue.asCell())); >- else >- set(VirtualRegister(dst), getJSConstantForValue(specificValue, 0)); >+ set(VirtualRegister(dst), inferredConstant(specificValue)); > break; > } > case ClosureVar: > case ClosureVarWithVarInjectionChecks: { > Node* scopeNode = get(VirtualRegister(scope)); >+ if (JSActivation* activation = m_graph.tryGetActivation(scopeNode)) { >+ SymbolTable* symbolTable = activation->symbolTable(); >+ ConcurrentJITLocker locker(symbolTable->m_lock); >+ SymbolTable::Map::iterator iter = symbolTable->find(locker, uid); >+ ASSERT(iter != symbolTable->end(locker)); >+ VariableWatchpointSet* set = iter->value.watchpointSet(); >+ if (set) { >+ if (JSValue value = set->inferredValue()) { >+ addToGraph(Phantom, scopeNode); >+ addToGraph(VariableWatchpoint, OpInfo(set)); >+ set(VirtualRegister(dst), inferredConstant(value)); >+ break; >+ } >+ } >+ } > set(VirtualRegister(dst), > addToGraph(GetClosureVar, OpInfo(operand), OpInfo(prediction), > addToGraph(GetClosureRegisters, scopeNode))); >@@ -3227,8 +3265,7 @@ bool ByteCodeParser::parseBlock(unsigned > NEXT_OPCODE(op_get_argument_by_val); > } > >- case op_new_func: >- case op_new_captured_func: { >+ case op_new_func: { > if (!currentInstruction[3].u.operand) { > set(VirtualRegister(currentInstruction[1].u.operand), > addToGraph(NewFunctionNoCheck, OpInfo(currentInstruction[2].u.operand))); >@@ -3242,6 +3279,15 @@ bool ByteCodeParser::parseBlock(unsigned > NEXT_OPCODE(op_new_func); > } > >+ case op_new_captured_func: { >+ Node* function = addToGraph( >+ NewFunctionNoCheck, OpInfo(currentInstruction[2].u.operand)); >+ if (VariableWatchpointSet* set = currentInstruction[3].u.watchpointSet) >+ addToGraph(NotifyWrite, OpInfo(set), function); >+ set(VirtualRegister(currentInstruction[1].u.operand), function); >+ NEXT_OPCODE(op_new_captured_func); >+ } >+ > case op_new_func_exp: { > set(VirtualRegister(currentInstruction[1].u.operand), > addToGraph(NewFunctionExpression, OpInfo(currentInstruction[2].u.operand))); >@@ -3611,6 +3657,22 @@ bool ByteCodeParser::parse() > // Set during construction. > ASSERT(!m_currentIndex); > >+ if (m_codeBlock->captureCount()) { >+ SymbolTable* symbolTable = m_codeBlock->symbolTable(); >+ ConcurrentJITLocker locker(symbolTable->m_lock); >+ SymbolTable::Map::iterator iter = symbolTable->begin(locker); >+ SymbolTable::Map::iterator end = symbolTable->end(locker); >+ for (; iter != end; ++iter) { >+ VariableWatchpointSet* set = iter->watchpointSet(); >+ if (!set) >+ continue; >+ size_t index = static_cast<size_t>(VirtualRegister(iter->getIndex()).toLocal()); >+ while (m_localWatchpoints.size() <= index) >+ m_localWatchpoints.append(nullptr); >+ m_localWatchpoints[index] = set; >+ } >+ } >+ > InlineStackEntry inlineStackEntry( > this, m_codeBlock, m_profiledBlock, 0, 0, VirtualRegister(), VirtualRegister(), > m_codeBlock->numParameters(), CodeForCall); >Index: Source/JavaScriptCore/dfg/DFGGraph.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.cpp (revision 159944) >+++ Source/JavaScriptCore/dfg/DFGGraph.cpp (working copy) >@@ -723,11 +723,16 @@ unsigned Graph::requiredRegisterCountFor > return std::max(frameRegisterCount(), requiredRegisterCountForExit()); > } > >-WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node) >+JSActivation* Graph::tryGetActivation(Node* node) > { > if (!node->hasConstant()) > return 0; >- JSActivation* activation = jsDynamicCast<JSActivation*>(valueOfJSConstant(node)); >+ return jsDynamicCast<JSActivation*>(valueOfJSConstant(node)); >+} >+ >+WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node) >+{ >+ JSActivation* activation = tryGetActivation(node); > if (!activation) > return 0; > if (!activation->isTornOff()) >Index: Source/JavaScriptCore/dfg/DFGGraph.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGGraph.h (revision 159944) >+++ Source/JavaScriptCore/dfg/DFGGraph.h (working copy) >@@ -791,6 +791,7 @@ public: > unsigned requiredRegisterCountForExit(); > unsigned requiredRegisterCountForExecutionAndExit(); > >+ JSActivation* tryGetActivation(Node*); > WriteBarrierBase<Unknown>* tryGetRegisters(Node*); > > VM& m_vm; >Index: Source/JavaScriptCore/jit/JIT.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JIT.cpp (revision 159944) >+++ Source/JavaScriptCore/jit/JIT.cpp (working copy) >@@ -226,7 +226,7 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_loop_hint) > DEFINE_OP(op_lshift) > DEFINE_OP(op_mod) >- case op_captured_mov: >+ DEFINE_OP(op_captured_mov) > DEFINE_OP(op_mov) > DEFINE_OP(op_mul) > DEFINE_OP(op_negate) >@@ -235,8 +235,8 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_new_array) > DEFINE_OP(op_new_array_with_size) > DEFINE_OP(op_new_array_buffer) >- case op_new_captured_func: > DEFINE_OP(op_new_func) >+ DEFINE_OP(op_new_captured_func) > DEFINE_OP(op_new_func_exp) > DEFINE_OP(op_new_object) > DEFINE_OP(op_new_regexp) >Index: Source/JavaScriptCore/jit/JIT.h >=================================================================== >--- Source/JavaScriptCore/jit/JIT.h (revision 159944) >+++ Source/JavaScriptCore/jit/JIT.h (working copy) >@@ -463,6 +463,7 @@ namespace JSC { > void emit_op_call(Instruction*); > void emit_op_call_eval(Instruction*); > void emit_op_call_varargs(Instruction*); >+ void emit_op_captured_mov(Instruction*); > void emit_op_catch(Instruction*); > void emit_op_construct(Instruction*); > void emit_op_get_callee(Instruction*); >@@ -515,6 +516,7 @@ namespace JSC { > void emit_op_new_array_with_size(Instruction*); > void emit_op_new_array_buffer(Instruction*); > void emit_op_new_func(Instruction*); >+ void emit_op_new_captured_func(Instruction*); > void emit_op_new_func_exp(Instruction*); > void emit_op_new_object(Instruction*); > void emit_op_new_regexp(Instruction*); >Index: Source/JavaScriptCore/jit/JITOpcodes.cpp >=================================================================== >--- Source/JavaScriptCore/jit/JITOpcodes.cpp (revision 159944) >+++ Source/JavaScriptCore/jit/JITOpcodes.cpp (working copy) >@@ -55,12 +55,30 @@ void JIT::emit_op_mov(Instruction* curre > int dst = currentInstruction[1].u.operand; > int src = currentInstruction[2].u.operand; > >- // Use simpler approach, since the DFG thinks that the last result register >- // is always set to the destination on every operation. > emitGetVirtualRegister(src, regT0); > emitPutVirtualRegister(dst); > } > >+void JIT::emit_op_captured_mov(Instruction* currentInstruction) >+{ >+ int dst = currentInstruction[1].u.operand; >+ int src = currentInstruction[2].u.operand; >+ >+ emitGetVirtualRegister(src, regT0); >+ emitNotifyWrite(regT0, regT1, currentInstruction[3].u.watchpointSet); >+ emitPutVirtualRegister(dst); >+} >+ >+void JIT::emitSlow_op_captured_mov(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) >+{ >+ VariableWatchpointSet* set = currentInstruction[3].u.watchpointSet; >+ if (!set || set->state() == IsInvalidated) >+ return; >+ linkSlowCase(iter); >+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_captured_mov); >+ slowPathCall.call(); >+} >+ > void JIT::emit_op_end(Instruction* currentInstruction) > { > RELEASE_ASSERT(returnValueGPR != callFrameRegister); >@@ -1180,6 +1198,12 @@ void JIT::emit_op_new_func(Instruction* > lazyJump.link(this); > } > >+void JIT::emit_op_new_captured_func(Instruction* currentInstruction) >+{ >+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_new_captured_func); >+ slowPathCall.call(); >+} >+ > void JIT::emit_op_new_func_exp(Instruction* currentInstruction) > { > int dst = currentInstruction[1].u.operand; >Index: Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (revision 159944) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (working copy) >@@ -549,7 +549,7 @@ _llint_op_captured_mov: > loadConstantOrVariable(t1, t2, t3) > storei t2, TagOffset[cfr, t0, 8] > storei t3, PayloadOffset[cfr, t0, 8] >- dispatch(3) >+ dispatch(4) > > > _llint_op_not: >@@ -1674,12 +1674,7 @@ _llint_op_new_func: > > _llint_op_new_captured_func: > traceExecution() >- btiz 12[PC], .opNewCapturedFuncUnchecked >- loadi 4[PC], t1 >- bineq TagOffset[cfr, t1, 8], EmptyValueTag, .opNewCapturedFuncDone >-.opNewCapturedFuncUnchecked: > callSlowPath(_llint_slow_path_new_func) >-.opNewCapturedFuncDone: > dispatch(4) > > >Index: Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >=================================================================== >--- Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (revision 159944) >+++ Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (working copy) >@@ -418,13 +418,38 @@ _llint_op_mov: > dispatch(3) > > >+macro notifyWrite(set, value, scratch, slow) >+ loadb VariableWatchpointSet::m_state[set], scratch >+ bieq scratch, IsInvalidated, .done >+ bineq scratch, ClearWatchpoint, .overwrite >+ storeq value, VariableWatchpointSet::m_inferredValue[set] >+ storeb IsWatched, VariableWatchpointSet::m_state[set] >+ jmp .done >+ >+.overwrite: >+ bqeq value, VariableWatchpointSet::m_inferredValue[set], .done >+ btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow >+ storeq 0, VariableWatchpointSet::m_inferredValue[set] >+ storeb IsInvalidated, VariableWatchpointSet::m_state[set] >+ >+.done: >+end >+ > _llint_op_captured_mov: > traceExecution() > loadisFromInstruction(2, t1) >- loadisFromInstruction(1, t0) > loadConstantOrVariable(t1, t2) >+ loadpFromInstruction(3, t0) >+ btpz t0, .opCapturedMovReady >+ notifyWrite(t0, t2, t1, .opCapturedMovSlow) >+.opCapturedMovReady: >+ loadisFromInstruction(1, t0) > storeq t2, [cfr, t0, 8] >- dispatch(3) >+ dispatch(4) >+ >+.opCapturedMovSlow: >+ callSlowPath(_slow_path_captured_mov) >+ dispath(4) > > > _llint_op_not: >@@ -1525,13 +1550,7 @@ _llint_op_new_func: > > _llint_op_new_captured_func: > traceExecution() >- loadisFromInstruction(3, t2) >- btiz t2, .opNewCapturedFuncUnchecked >- loadisFromInstruction(1, t1) >- btqnz [cfr, t1, 8], .opNewCapturedFuncDone >-.opNewCapturedFuncUnchecked: >- callSlowPath(_llint_slow_path_new_func) >-.opNewCapturedFuncDone: >+ callSlowPath(_slow_path_new_captured_func) > dispatch(4) > > >@@ -1973,23 +1992,6 @@ macro putProperty() > storePropertyAtVariableOffset(t1, t0, t2) > end > >-macro notifyWrite(set, value, scratch, slow) >- loadb VariableWatchpointSet::m_state[set], scratch >- bieq scratch, IsInvalidated, .done >- bineq scratch, ClearWatchpoint, .overwrite >- storeq value, VariableWatchpointSet::m_inferredValue[set] >- storeb IsWatched, VariableWatchpointSet::m_state[set] >- jmp .done >- >-.overwrite: >- bqeq value, VariableWatchpointSet::m_inferredValue[set], .done >- btbnz VariableWatchpointSet::m_setIsNotEmpty[set], slow >- storeq 0, VariableWatchpointSet::m_inferredValue[set] >- storeb IsInvalidated, VariableWatchpointSet::m_state[set] >- >-.done: >-end >- > macro putGlobalVar() > loadisFromInstruction(3, t0) > loadConstantOrVariable(t0, t1) >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (revision 159944) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (working copy) >@@ -244,6 +244,28 @@ SLOW_PATH_DECL(slow_path_to_this) > RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode)); > } > >+SLOW_PATH_DECL(slow_path_captured_mov) >+{ >+ BEGIN(); >+ JSValue value = OP_C(2).jsValue(); >+ if (VariableWatchpointSet* set = pc[3].u.watchpointSet) >+ set->notifyWrite(value); >+ RETURN(value); >+} >+ >+SLOW_PATH_DECL(slow_path_new_captured_func) >+{ >+ BEGIN(); >+ CodeBlock* codeBlock = exec->codeBlock(); >+ ASSERT(codeBlock->codeType() != FunctionCode >+ || !codeBlock->needsFullScopeChain() >+ || exec->uncheckedR(codeBlock->activationRegister().offset()).jsValue()); >+ JSValue value = JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope()); >+ if (VariableWatchpointSet* set = pc[3].u.watchpointSet) >+ set->notifyWrite(value); >+ RETURN(value); >+} >+ > SLOW_PATH_DECL(slow_path_not) > { > BEGIN(); >Index: Source/JavaScriptCore/runtime/CommonSlowPaths.h >=================================================================== >--- Source/JavaScriptCore/runtime/CommonSlowPaths.h (revision 159944) >+++ Source/JavaScriptCore/runtime/CommonSlowPaths.h (working copy) >@@ -165,6 +165,40 @@ SLOW_PATH_HIDDEN_DECL(slow_path_create_a > 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_captured_mov); >+SLOW_PATH_HIDDEN_DECL(slow_path_new_captured_func); >+SLOW_PATH_HIDDEN_DECL(slow_path_not); >+SLOW_PATH_HIDDEN_DECL(slow_path_eq); >+SLOW_PATH_HIDDEN_DECL(slow_path_neq); >+SLOW_PATH_HIDDEN_DECL(slow_path_stricteq); >+SLOW_PATH_HIDDEN_DECL(slow_path_nstricteq); >+SLOW_PATH_HIDDEN_DECL(slow_path_less); >+SLOW_PATH_HIDDEN_DECL(slow_path_lesseq); >+SLOW_PATH_HIDDEN_DECL(slow_path_greater); >+SLOW_PATH_HIDDEN_DECL(slow_path_greatereq); >+SLOW_PATH_HIDDEN_DECL(slow_path_inc); >+SLOW_PATH_HIDDEN_DECL(slow_path_dec); >+SLOW_PATH_HIDDEN_DECL(slow_path_to_number); >+SLOW_PATH_HIDDEN_DECL(slow_path_negate); >+SLOW_PATH_HIDDEN_DECL(slow_path_add); >+SLOW_PATH_HIDDEN_DECL(slow_path_mul); >+SLOW_PATH_HIDDEN_DECL(slow_path_sub); >+SLOW_PATH_HIDDEN_DECL(slow_path_div); >+SLOW_PATH_HIDDEN_DECL(slow_path_mod); >+SLOW_PATH_HIDDEN_DECL(slow_path_lshift); >+SLOW_PATH_HIDDEN_DECL(slow_path_rshift); >+SLOW_PATH_HIDDEN_DECL(slow_path_urshift); >+SLOW_PATH_HIDDEN_DECL(slow_path_bitand); >+SLOW_PATH_HIDDEN_DECL(slow_path_bitor); >+SLOW_PATH_HIDDEN_DECL(slow_path_bitxor); >+SLOW_PATH_HIDDEN_DECL(slow_path_typeof); >+SLOW_PATH_HIDDEN_DECL(slow_path_is_object); >+SLOW_PATH_HIDDEN_DECL(slow_path_is_function); >+SLOW_PATH_HIDDEN_DECL(slow_path_in); >+SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val); >+SLOW_PATH_HIDDEN_DECL(slow_path_strcat); >+SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive); >+SLOW_PATH_HIDDEN_DECL(slow_path_captured_mov); > SLOW_PATH_HIDDEN_DECL(slow_path_not); > SLOW_PATH_HIDDEN_DECL(slow_path_eq); > SLOW_PATH_HIDDEN_DECL(slow_path_neq); >Index: Source/JavaScriptCore/runtime/ConstantMode.h >=================================================================== >--- Source/JavaScriptCore/runtime/ConstantMode.h (revision 0) >+++ Source/JavaScriptCore/runtime/ConstantMode.h (working copy) >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2013 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 ConstantMode_h >+#define ConstantMode_h >+ >+namespace JSC { >+ >+enum ConstantMode { IsConstant, IsVariable }; >+ >+} // namespace JSC >+ >+#endif // ConstantMode_h >+ >Index: Source/JavaScriptCore/runtime/JSGlobalObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.h (revision 159944) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.h (working copy) >@@ -23,6 +23,7 @@ > #define JSGlobalObject_h > > #include "ArrayAllocationProfile.h" >+#include "ConstantMode.h" > #include "JSArray.h" > #include "JSArrayBufferPrototype.h" > #include "JSClassRef.h" >@@ -288,7 +289,6 @@ protected: > init(thisValue); > } > >- enum ConstantMode { IsConstant, IsVariable }; > struct NewGlobalVar { > int registerNumber; > VariableWatchpointSet* set; >Index: Source/JavaScriptCore/runtime/JSScope.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSScope.cpp (revision 159944) >+++ Source/JavaScriptCore/runtime/JSScope.cpp (working copy) >@@ -65,7 +65,7 @@ static inline bool abstractAccess(ExecSt > } > > if (!entry.isNull()) { >- op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, activation, 0, entry.getIndex()); >+ op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, 0, activation, entry.watchpointSet(), entry.getIndex()); > return true; > } > >Index: Source/JavaScriptCore/runtime/SymbolTable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.cpp (revision 159944) >+++ Source/JavaScriptCore/runtime/SymbolTable.cpp (working copy) >@@ -68,7 +68,8 @@ JSValue SymbolTableEntry::inferredValue( > void SymbolTableEntry::prepareToWatch() > { > FatEntry* entry = inflate(); >- ASSERT(!entry->m_watchpoints); >+ if (entry->m_watchpoints) >+ return; > entry->m_watchpoints = adoptRef(new VariableWatchpointSet()); > } >
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 124630
:
218217
|
218221
|
218224
|
218262
|
218264
|
218355
|
218357
|
218371