Log Message
Make the type profiler work with lexical scoping and add tests https://bugs.webkit.org/show_bug.cgi?id=145438
Reviewed by Geoffrey Garen. op_profile_type now knows how to resolve variables allocated within the local scope stack. This means it knows how to resolve "let" and "const" variables. Also, some refactoring was done inside the BytecodeGenerator to make writing code to support the type profiler much simpler and clearer. * bytecode/CodeBlock.cpp: (JSC::CodeBlock::CodeBlock): * bytecode/CodeBlock.h: (JSC::CodeBlock::symbolTable): Deleted. * bytecode/UnlinkedCodeBlock.h: (JSC::UnlinkedCodeBlock::addExceptionHandler): (JSC::UnlinkedCodeBlock::exceptionHandler): (JSC::UnlinkedCodeBlock::vm): (JSC::UnlinkedCodeBlock::addArrayProfile): (JSC::UnlinkedCodeBlock::setSymbolTableConstantIndex): Deleted. (JSC::UnlinkedCodeBlock::symbolTableConstantIndex): Deleted. * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitMove): (JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo): (JSC::BytecodeGenerator::emitProfileType): (JSC::BytecodeGenerator::emitProfileControlFlow): (JSC::BytecodeGenerator::pushLexicalScopeInternal): * bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNodeForLeftHandSide): * bytecompiler/NodesCodegen.cpp: (JSC::ThisNode::emitBytecode): (JSC::ResolveNode::emitBytecode): (JSC::BracketAccessorNode::emitBytecode): (JSC::DotAccessorNode::emitBytecode): (JSC::FunctionCallValueNode::emitBytecode): (JSC::FunctionCallResolveNode::emitBytecode): (JSC::FunctionCallBracketNode::emitBytecode): (JSC::FunctionCallDotNode::emitBytecode): (JSC::CallFunctionCallDotNode::emitBytecode): (JSC::ApplyFunctionCallDotNode::emitBytecode): (JSC::PostfixNode::emitResolve): (JSC::PostfixNode::emitBracket): (JSC::PostfixNode::emitDot): (JSC::PrefixNode::emitResolve): (JSC::PrefixNode::emitBracket): (JSC::PrefixNode::emitDot): (JSC::ReadModifyResolveNode::emitBytecode): (JSC::AssignResolveNode::emitBytecode): (JSC::AssignDotNode::emitBytecode): (JSC::ReadModifyDotNode::emitBytecode): (JSC::AssignBracketNode::emitBytecode): (JSC::ReadModifyBracketNode::emitBytecode): (JSC::EmptyVarExpression::emitBytecode): (JSC::EmptyLetExpression::emitBytecode): (JSC::ForInNode::emitLoopHeader): (JSC::ForOfNode::emitBytecode): (JSC::ReturnNode::emitBytecode): (JSC::FunctionNode::emitBytecode): (JSC::BindingNode::bindValue): * dfg/DFGSpeculativeJIT32_64.cpp: (JSC::DFG::SpeculativeJIT::compile): * dfg/DFGSpeculativeJIT64.cpp: (JSC::DFG::SpeculativeJIT::compile): * jit/JITOpcodes.cpp: (JSC::JIT::emit_op_profile_type): * jit/JITOpcodes32_64.cpp: (JSC::JIT::emit_op_profile_type): * llint/LowLevelInterpreter32_64.asm: * llint/LowLevelInterpreter64.asm: * tests/typeProfiler/es6-block-scoping.js: Added. (noop): (arr): (wrapper.changeFoo): (wrapper.scoping): (wrapper.scoping2): (wrapper): * tests/typeProfiler/es6-classes.js: Added. (noop): (wrapper.Animal): (wrapper.Animal.prototype.methodA): (wrapper.Dog): (wrapper.Dog.prototype.methodB): (wrapper):
Modified Paths
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp
- trunk/Source/_javascript_Core/bytecode/CodeBlock.h
- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h
- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp
- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h
- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp
- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp
- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp
- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp
- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp
- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm
- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm
Added Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (187523 => 187524)
--- trunk/Source/_javascript_Core/ChangeLog 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-07-28 22:39:12 UTC (rev 187524)
@@ -1,5 +1,93 @@
2015-07-28 Saam barati <[email protected]>
+ Make the type profiler work with lexical scoping and add tests
+ https://bugs.webkit.org/show_bug.cgi?id=145438
+
+ Reviewed by Geoffrey Garen.
+
+ op_profile_type now knows how to resolve variables allocated within
+ the local scope stack. This means it knows how to resolve "let"
+ and "const" variables. Also, some refactoring was done inside
+ the BytecodeGenerator to make writing code to support the type
+ profiler much simpler and clearer.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock):
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::symbolTable): Deleted.
+ * bytecode/UnlinkedCodeBlock.h:
+ (JSC::UnlinkedCodeBlock::addExceptionHandler):
+ (JSC::UnlinkedCodeBlock::exceptionHandler):
+ (JSC::UnlinkedCodeBlock::vm):
+ (JSC::UnlinkedCodeBlock::addArrayProfile):
+ (JSC::UnlinkedCodeBlock::setSymbolTableConstantIndex): Deleted.
+ (JSC::UnlinkedCodeBlock::symbolTableConstantIndex): Deleted.
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ (JSC::BytecodeGenerator::emitMove):
+ (JSC::BytecodeGenerator::emitTypeProfilerExpressionInfo):
+ (JSC::BytecodeGenerator::emitProfileType):
+ (JSC::BytecodeGenerator::emitProfileControlFlow):
+ (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::emitNodeForLeftHandSide):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ThisNode::emitBytecode):
+ (JSC::ResolveNode::emitBytecode):
+ (JSC::BracketAccessorNode::emitBytecode):
+ (JSC::DotAccessorNode::emitBytecode):
+ (JSC::FunctionCallValueNode::emitBytecode):
+ (JSC::FunctionCallResolveNode::emitBytecode):
+ (JSC::FunctionCallBracketNode::emitBytecode):
+ (JSC::FunctionCallDotNode::emitBytecode):
+ (JSC::CallFunctionCallDotNode::emitBytecode):
+ (JSC::ApplyFunctionCallDotNode::emitBytecode):
+ (JSC::PostfixNode::emitResolve):
+ (JSC::PostfixNode::emitBracket):
+ (JSC::PostfixNode::emitDot):
+ (JSC::PrefixNode::emitResolve):
+ (JSC::PrefixNode::emitBracket):
+ (JSC::PrefixNode::emitDot):
+ (JSC::ReadModifyResolveNode::emitBytecode):
+ (JSC::AssignResolveNode::emitBytecode):
+ (JSC::AssignDotNode::emitBytecode):
+ (JSC::ReadModifyDotNode::emitBytecode):
+ (JSC::AssignBracketNode::emitBytecode):
+ (JSC::ReadModifyBracketNode::emitBytecode):
+ (JSC::EmptyVarExpression::emitBytecode):
+ (JSC::EmptyLetExpression::emitBytecode):
+ (JSC::ForInNode::emitLoopHeader):
+ (JSC::ForOfNode::emitBytecode):
+ (JSC::ReturnNode::emitBytecode):
+ (JSC::FunctionNode::emitBytecode):
+ (JSC::BindingNode::bindValue):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_profile_type):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_profile_type):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * tests/typeProfiler/es6-block-scoping.js: Added.
+ (noop):
+ (arr):
+ (wrapper.changeFoo):
+ (wrapper.scoping):
+ (wrapper.scoping2):
+ (wrapper):
+ * tests/typeProfiler/es6-classes.js: Added.
+ (noop):
+ (wrapper.Animal):
+ (wrapper.Animal.prototype.methodA):
+ (wrapper.Dog):
+ (wrapper.Dog.prototype.methodB):
+ (wrapper):
+
+2015-07-28 Saam barati <[email protected]>
+
Implement catch scope using lexical scoping constructs introduced with "let" scoping patch
https://bugs.webkit.org/show_bug.cgi?id=146979
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -1694,8 +1694,6 @@
ASSERT(m_heap->isDeferred());
ASSERT(m_scopeRegister.isLocal());
- m_symbolTableConstantIndex = other.m_symbolTableConstantIndex;
-
setNumParameters(other.numParameters());
optimizeAfterWarmUp();
jitAfterWarmUp();
@@ -1767,7 +1765,6 @@
}
HashSet<int, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int>> clonedConstantSymbolTables;
- m_symbolTableConstantIndex = unlinkedCodeBlock->symbolTableConstantIndex();
{
HashSet<SymbolTable*> clonedSymbolTables;
for (unsigned i = 0; i < m_constantRegisters.size(); i++) {
@@ -2059,17 +2056,16 @@
VirtualRegister profileRegister(pc[1].u.operand);
ProfileTypeBytecodeFlag flag = static_cast<ProfileTypeBytecodeFlag>(pc[3].u.operand);
SymbolTable* symbolTable = nullptr;
- int localScopeDepth = pc[2].u.operand;
switch (flag) {
- case ProfileTypeBytecodePutToScope:
- case ProfileTypeBytecodeGetFromScope: {
+ case ProfileTypeBytecodeClosureVar: {
const Identifier& ident = identifier(pc[4].u.operand);
+ int localScopeDepth = pc[2].u.operand;
ResolveType type = static_cast<ResolveType>(pc[5].u.operand);
- ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, (flag == ProfileTypeBytecodeGetFromScope ? Get : Put), type);
+ // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
+ // we're abstractly "read"ing from a JSScope.
+ ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type);
- // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
- // https://bugs.webkit.org/show_bug.cgi?id=135184
if (op.type == ClosureVar)
symbolTable = op.lexicalEnvironment->symbolTable();
else if (op.type == GlobalVar)
@@ -2086,34 +2082,18 @@
break;
}
- case ProfileTypeBytecodePutToLocalScope:
- case ProfileTypeBytecodeGetFromLocalScope: {
- if (!m_symbolTableConstantIndex) {
- globalVariableID = TypeProfilerNoGlobalIDExists;
- break;
- }
+ case ProfileTypeBytecodeLocallyResolved: {
+ int symbolTableIndex = pc[2].u.operand;
+ RELEASE_ASSERT(clonedConstantSymbolTables.contains(symbolTableIndex));
+ SymbolTable* symbolTable = jsCast<SymbolTable*>(getConstant(symbolTableIndex));
const Identifier& ident = identifier(pc[4].u.operand);
- symbolTable = this->symbolTable();
ConcurrentJITLocker locker(symbolTable->m_lock);
// If our parent scope was created while profiling was disabled, it will not have prepared for profiling yet.
- symbolTable->prepareForTypeProfiling(locker);
globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
break;
}
-
- case ProfileTypeBytecodeHasGlobalID: {
- if (!m_symbolTableConstantIndex) {
- globalVariableID = TypeProfilerNoGlobalIDExists;
- break;
- }
- symbolTable = this->symbolTable();
- ConcurrentJITLocker locker(symbolTable->m_lock);
- globalVariableID = symbolTable->uniqueIDForOffset(locker, VarOffset(profileRegister), *vm());
- globalTypeSet = symbolTable->globalTypeSetForOffset(locker, VarOffset(profileRegister), *vm());
- break;
- }
case ProfileTypeBytecodeDoesNotHaveGlobalID:
case ProfileTypeBytecodeFunctionArgument: {
globalVariableID = TypeProfilerNoGlobalIDExists;
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2015-07-28 22:39:12 UTC (rev 187524)
@@ -916,15 +916,6 @@
private:
friend class CodeBlockSet;
- SymbolTable* symbolTable() const
- {
- // FIXME: Get rid of this function once the type profiler has a notion of what
- // symbol table it's reading from.
- // https://bugs.webkit.org/show_bug.cgi?id=145438
- RELEASE_ASSERT(m_symbolTableConstantIndex);
- return jsCast<SymbolTable*>(getConstant(m_symbolTableConstantIndex));
- }
-
CodeBlock* specialOSREntryBlockOrNull();
void noticeIncomingCall(ExecState* callerFrame);
@@ -1006,7 +997,6 @@
VM* m_vm;
RefCountedArray<Instruction> m_instructions;
- int m_symbolTableConstantIndex;
VirtualRegister m_thisRegister;
VirtualRegister m_scopeRegister;
VirtualRegister m_lexicalEnvironmentRegister;
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-07-28 22:39:12 UTC (rev 187524)
@@ -418,9 +418,6 @@
void addExceptionHandler(const UnlinkedHandlerInfo& handler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(handler); }
UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
- void setSymbolTableConstantIndex(int index) { m_symbolTableConstantIndex = index; }
- int symbolTableConstantIndex() const { return m_symbolTableConstantIndex; }
-
VM* vm() const { return m_vm; }
UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
@@ -563,7 +560,6 @@
FunctionExpressionVector m_functionExprs;
WriteBarrier<SymbolTable> m_symbolTable;
- int m_symbolTableConstantIndex { 0 };
Vector<unsigned> m_propertyAccessInstructions;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -207,7 +207,6 @@
SymbolTable* functionSymbolTable = SymbolTable::create(*m_vm);
functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
int symbolTableConstantIndex = addConstantValue(functionSymbolTable)->index();
- m_codeBlock->setSymbolTableConstantIndex(symbolTableConstantIndex);
Vector<Identifier> boundParameterProperties;
FunctionParameters& parameters = *functionNode->parameters();
@@ -1180,9 +1179,6 @@
instructions().append(dst->index());
instructions().append(src->index());
- if (!dst->isTemporary() && vm()->typeProfiler())
- emitProfileType(dst, ProfileTypeBytecodeHasGlobalID, nullptr);
-
return dst;
}
@@ -1289,26 +1285,87 @@
void BytecodeGenerator::emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
{
+ ASSERT(vm()->typeProfiler());
+
unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
unsigned instructionOffset = instructions().size() - 1;
m_codeBlock->addTypeProfilerExpressionInfo(instructionOffset, start, end);
}
-void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const Identifier* identifier)
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag)
{
- if (flag == ProfileTypeBytecodeGetFromScope || flag == ProfileTypeBytecodePutToScope)
- RELEASE_ASSERT(identifier);
+ if (!vm()->typeProfiler())
+ return;
+ if (!registerToProfile)
+ return;
+
+ emitOpcode(op_profile_type);
+ instructions().append(registerToProfile->index());
+ instructions().append(0);
+ instructions().append(flag);
+ instructions().append(0);
+ instructions().append(resolveType());
+
+ // Don't emit _expression_ info for this version of profile type. This generally means
+ // we're profiling information for something that isn't in the actual text of a _javascript_
+ // program. For example, implicit return undefined from a function call.
+}
+
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+ emitProfileType(registerToProfile, ProfileTypeBytecodeDoesNotHaveGlobalID, startDivot, endDivot);
+}
+
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag flag, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+ if (!vm()->typeProfiler())
+ return;
+
+ if (!registerToProfile)
+ return;
+
// The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
emitOpcode(op_profile_type);
instructions().append(registerToProfile->index());
- instructions().append(localScopeDepth());
+ instructions().append(0);
instructions().append(flag);
- instructions().append(identifier ? addConstant(*identifier) : 0);
+ instructions().append(0);
instructions().append(resolveType());
+
+ emitTypeProfilerExpressionInfo(startDivot, endDivot);
}
+void BytecodeGenerator::emitProfileType(RegisterID* registerToProfile, const Variable& var, const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+ if (!vm()->typeProfiler())
+ return;
+
+ if (!registerToProfile)
+ return;
+
+ ProfileTypeBytecodeFlag flag;
+ int symbolTableOrScopeDepth;
+ if (var.local() || var.offset().isScope()) {
+ flag = ProfileTypeBytecodeLocallyResolved;
+ symbolTableOrScopeDepth = var.symbolTableConstantIndex();
+ } else {
+ flag = ProfileTypeBytecodeClosureVar;
+ symbolTableOrScopeDepth = localScopeDepth();
+ }
+
+ // The format of this instruction is: op_profile_type regToProfile, TypeLocation*, flag, identifier?, resolveType?
+ emitOpcode(op_profile_type);
+ instructions().append(registerToProfile->index());
+ instructions().append(symbolTableOrScopeDepth);
+ instructions().append(flag);
+ instructions().append(addConstant(var.ident()));
+ instructions().append(resolveType());
+
+ emitTypeProfilerExpressionInfo(startDivot, endDivot);
+}
+
void BytecodeGenerator::emitProfileControlFlow(int textOffset)
{
if (vm()->controlFlowProfiler()) {
@@ -1408,13 +1465,20 @@
}
RegisterID* newScope = nullptr;
+ RegisterID* constantSymbolTable = nullptr;
int symbolTableConstantIndex = 0;
+ if (vm()->typeProfiler()) {
+ constantSymbolTable = addConstantValue(symbolTable.get());
+ symbolTableConstantIndex = constantSymbolTable->index();
+ }
if (hasCapturedVariables) {
newScope = newBlockScopeVariable();
newScope->ref();
-
- RegisterID* constantSymbolTable = addConstantValue(!m_codeBlock->vm()->typeProfiler() ? symbolTable->cloneScopePart(*m_vm) : symbolTable.get());
- symbolTableConstantIndex = constantSymbolTable->index();
+ if (!constantSymbolTable) {
+ ASSERT(!vm()->typeProfiler());
+ constantSymbolTable = addConstantValue(symbolTable->cloneScopePart(*m_vm));
+ symbolTableConstantIndex = constantSymbolTable->index();
+ }
if (constantSymbolTableResult)
*constantSymbolTableResult = constantSymbolTable;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-07-28 22:39:12 UTC (rev 187524)
@@ -252,11 +252,8 @@
};
enum ProfileTypeBytecodeFlag {
- ProfileTypeBytecodePutToScope,
- ProfileTypeBytecodeGetFromScope,
- ProfileTypeBytecodePutToLocalScope,
- ProfileTypeBytecodeGetFromLocalScope,
- ProfileTypeBytecodeHasGlobalID,
+ ProfileTypeBytecodeClosureVar,
+ ProfileTypeBytecodeLocallyResolved,
ProfileTypeBytecodeDoesNotHaveGlobalID,
ProfileTypeBytecodeFunctionArgument,
ProfileTypeBytecodeFunctionReturnStatement
@@ -447,9 +444,19 @@
return emitNode(n);
}
+ private:
void emitTypeProfilerExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
- void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const Identifier*);
+ public:
+ // This doesn't emit _expression_ info. If using this, make sure you shouldn't be emitting text offset.
+ void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag);
+ // These variables are associated with variables in a program. They could be Locals, LocalClosureVar, or ClosureVar.
+ void emitProfileType(RegisterID* registerToProfile, const Variable&, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
+
+ void emitProfileType(RegisterID* registerToProfile, ProfileTypeBytecodeFlag, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
+ // These are not associated with variables and don't have a global id.
+ void emitProfileType(RegisterID* registerToProfile, const JSTextPosition& startDivot, const JSTextPosition& endDivot);
+
void emitProfileControlFlow(int);
RegisterID* emitLoad(RegisterID* dst, bool);
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -153,11 +153,8 @@
return 0;
RegisterID* result = generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(generator.thisRegister(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- static const unsigned thisLength = 4;
- generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + thisLength, -1));
- }
+ static const unsigned thisLength = 4;
+ generator.emitProfileType(generator.thisRegister(), position(), JSTextPosition(-1, position().offset + thisLength, -1));
return result;
}
@@ -209,10 +206,8 @@
generator.emitTDZCheckIfNecessary(var, local, nullptr);
if (dst == generator.ignoredResult())
return nullptr;
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
- }
+
+ generator.emitProfileType(local, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
return generator.moveToDestinationIfNeeded(dst, local);
}
@@ -222,10 +217,7 @@
RegisterID* finalDest = generator.finalDestination(dst);
RegisterID* result = generator.emitGetFromScope(finalDest, scope.get(), var, ThrowIfNotFound);
generator.emitTDZCheckIfNecessary(var, finalDest, nullptr);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(finalDest, var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
- generator.emitTypeProfilerExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
- }
+ generator.emitProfileType(finalDest, var, m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
return result;
}
@@ -623,10 +615,7 @@
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(finalDest, divotStart(), divotEnd());
return ret;
}
@@ -638,10 +627,7 @@
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* finalDest = generator.finalDestination(dst);
RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(finalDest, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(finalDest, divotStart(), divotEnd());
return ret;
}
@@ -734,10 +720,7 @@
}
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -757,10 +740,7 @@
// This passes NoExpectedFunction because we expect that if the function is in a
// local variable, then it's not one of our built-in constructors.
RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -776,10 +756,7 @@
generator.emitGetFromScope(func.get(), callArguments.thisRegister(), var, ThrowIfNotFound);
generator.emitTDZCheckIfNecessary(var, func.get(), nullptr);
RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -847,10 +824,7 @@
else
generator.emitMove(callArguments.thisRegister(), base.get());
RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -869,10 +843,7 @@
generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return ret;
}
@@ -927,10 +898,7 @@
}
generator.emitLabel(end.get());
}
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return returnValue.get();
}
@@ -1038,10 +1006,7 @@
generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
generator.emitLabel(end.get());
}
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnValue.get(), divotStart(), divotEnd());
return returnValue.get();
}
@@ -1077,19 +1042,10 @@
if (var.isReadOnly()) {
generator.emitReadOnlyExceptionIfNeeded(var);
localReg = generator.emitMove(generator.tempDestination(dst), local);
- } else if (generator.vm()->typeProfiler()) {
- RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
- ASSERT(dst != localReg);
- RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
- generator.emitToNumber(tempDst.get(), localReg.get());
- generator.emitMove(tempDstSrc.get(), localReg.get());
- emitIncOrDec(generator, tempDstSrc.get(), m_operator);
- generator.emitMove(localReg.get(), tempDstSrc.get());
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- return tempDst.get();
}
- return emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
+ RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator);
+ generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
+ return oldValue.get();
}
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
@@ -1103,10 +1059,7 @@
}
RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
return oldValue.get();
}
@@ -1129,10 +1082,7 @@
RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutByVal(base.get(), property.get(), value.get());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value.get(), divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, oldValue);
}
@@ -1153,10 +1103,7 @@
RegisterID* oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutById(base.get(), ident, value.get());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value.get(), divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, oldValue);
}
@@ -1291,8 +1238,7 @@
generator.emitMove(tempDst.get(), localReg.get());
emitIncOrDec(generator, tempDst.get(), m_operator);
generator.emitMove(localReg.get(), tempDst.get());
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
+ generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, tempDst.get());
}
emitIncOrDec(generator, localReg.get(), m_operator);
@@ -1311,10 +1257,7 @@
emitIncOrDec(generator, value.get(), m_operator);
generator.emitPutToScope(scope.get(), var, value.get(), ThrowIfNotFound);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value.get(), var, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, value.get());
}
@@ -1334,10 +1277,7 @@
emitIncOrDec(generator, value, m_operator);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutByVal(base.get(), property.get(), value);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
}
@@ -1356,10 +1296,7 @@
emitIncOrDec(generator, value, m_operator);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutById(base.get(), ident, value);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
}
@@ -1809,23 +1746,24 @@
generator.emitTDZCheckIfNecessary(var, local, nullptr);
if (var.isReadOnly()) {
generator.emitReadOnlyExceptionIfNeeded(var);
- return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+ generator.emitProfileType(result, divotStart(), divotEnd());
+ return result;
}
- if (generator.vm()->typeProfiler()
- || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
+ if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
RefPtr<RegisterID> result = generator.newTemporary();
generator.emitMove(result.get(), local);
emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
generator.emitMove(local, result.get());
generator.invalidateForInContextForLocal(local);
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
+ generator.emitProfileType(local, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, result.get());
}
RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
generator.invalidateForInContextForLocal(local);
+ generator.emitProfileType(result, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, result);
}
@@ -1840,10 +1778,7 @@
}
RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), ThrowIfNotFound);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
return returnResult;
}
@@ -1860,16 +1795,17 @@
if (var.isReadOnly() && m_assignmentContext != AssignmentContext::ConstDeclarationStatement) {
result = generator.emitNode(dst, m_right); // Execute side effects first.
generator.emitReadOnlyExceptionIfNeeded(var);
- } else if (var.isSpecial() || generator.vm()->typeProfiler()) {
+ generator.emitProfileType(result, var, divotStart(), divotEnd());
+ } else if (var.isSpecial()) {
RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
generator.emitNode(tempDst.get(), m_right);
generator.emitMove(local, tempDst.get());
+ generator.emitProfileType(local, var, divotStart(), divotEnd());
generator.invalidateForInContextForLocal(local);
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
result = generator.moveToDestinationIfNeeded(dst, tempDst.get());
} else {
RegisterID* right = generator.emitNode(local, m_right);
+ generator.emitProfileType(right, var, divotStart(), divotEnd());
generator.invalidateForInContextForLocal(local);
result = generator.moveToDestinationIfNeeded(dst, right);
}
@@ -1895,10 +1831,7 @@
}
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* returnResult = generator.emitPutToScope(scope.get(), var, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(result.get(), var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_ident);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(result.get(), var, divotStart(), divotEnd());
if (m_assignmentContext == AssignmentContext::DeclarationStatement || m_assignmentContext == AssignmentContext::ConstDeclarationStatement)
generator.liftTDZCheckIfPossible(var);
@@ -1915,10 +1848,7 @@
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result.get() : generator.moveToDestinationIfNeeded(generator.tempDestination(result.get()), result.get());
generator.emitPutById(base.get(), m_ident, forwardResult);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(forwardResult, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, forwardResult);
}
@@ -1934,10 +1864,7 @@
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(updatedValue, divotStart(), divotEnd());
return ret;
}
@@ -1965,10 +1892,7 @@
else
generator.emitPutByVal(base.get(), property.get(), forwardResult);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(forwardResult, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(forwardResult, divotStart(), divotEnd());
return generator.moveToDestinationIfNeeded(dst, forwardResult);
}
@@ -1985,10 +1909,7 @@
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutByVal(base.get(), property.get(), updatedValue);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(updatedValue, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(updatedValue, divotStart(), divotEnd());
return updatedValue;
}
@@ -2080,15 +2001,13 @@
Variable var = generator.variable(m_ident);
if (RegisterID* local = var.local())
- generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
+ generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
else {
RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, DoNotThrowIfNotFound);
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
+ generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
}
- generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
-
return nullptr;
}
@@ -2101,17 +2020,13 @@
Variable var = generator.variable(m_ident);
if (RegisterID* local = var.local()) {
generator.emitLoad(local, jsUndefined());
- if (generator.vm()->typeProfiler())
- generator.emitProfileType(local, ProfileTypeBytecodeHasGlobalID, nullptr);
+ generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
} else {
RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
RefPtr<RegisterID> value = generator.emitLoad(nullptr, jsUndefined());
generator.emitPutToScope(scope.get(), var, value.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
- if (generator.vm()->typeProfiler())
- generator.emitProfileType(value.get(), var.isResolved() ? ProfileTypeBytecodeGetFromLocalScope : ProfileTypeBytecodeGetFromScope, &m_ident);
+ generator.emitProfileType(value.get(), var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
}
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(position(), JSTextPosition(-1, position().offset + m_ident.length(), -1));
// It's safe to return null here because this node will always be a child node of DeclarationStatement which ignores our return value.
return nullptr;
@@ -2316,11 +2231,8 @@
RegisterID* scope = generator.emitResolveScope(nullptr, var);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutToScope(scope, var, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
- if (generator.vm()->typeProfiler())
- generator.emitProfileType(propertyName, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
}
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
+ generator.emitProfileType(propertyName, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
return;
}
if (m_lexpr->isDotAccessorNode()) {
@@ -2329,10 +2241,7 @@
RegisterID* base = generator.emitNode(assignNode->base());
generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
generator.emitPutById(base, ident, propertyName);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
+ generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
return;
}
if (m_lexpr->isBracketAccessorNode()) {
@@ -2341,10 +2250,7 @@
RegisterID* subscript = generator.emitNode(assignNode->subscript());
generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
generator.emitPutByVal(base.get(), subscript, propertyName);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(propertyName, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
+ generator.emitProfileType(propertyName, assignNode->divotStart(), assignNode->divotEnd());
return;
}
@@ -2364,8 +2270,7 @@
return;
}
generator.emitMove(var.local(), propertyName);
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(simpleBinding->divotStart(), simpleBinding->divotEnd());
+ generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd());
return;
}
@@ -2547,11 +2452,8 @@
RegisterID* scope = generator.emitResolveScope(nullptr, var);
generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
- if (generator.vm()->typeProfiler())
- generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &ident);
}
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
+ generator.emitProfileType(value, var, m_lexpr->position(), JSTextPosition(-1, m_lexpr->position().offset + ident.length(), -1));
} else if (m_lexpr->isDotAccessorNode()) {
DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
const Identifier& ident = assignNode->identifier();
@@ -2559,10 +2461,7 @@
generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
generator.emitPutById(base.get(), ident, value);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
+ generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
} else if (m_lexpr->isBracketAccessorNode()) {
BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
@@ -2570,10 +2469,7 @@
generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
generator.emitPutByVal(base.get(), subscript, value);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
- generator.emitTypeProfilerExpressionInfo(assignNode->divotStart(), assignNode->divotEnd());
- }
+ generator.emitProfileType(value, assignNode->divotStart(), assignNode->divotEnd());
} else {
ASSERT(m_lexpr->isDestructuringNode());
DestructuringAssignmentNode* assignNode = static_cast<DestructuringAssignmentNode*>(m_lexpr);
@@ -2656,10 +2552,7 @@
dst = 0;
RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, nullptr);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(returnRegister.get(), ProfileTypeBytecodeFunctionReturnStatement, divotStart(), divotEnd());
if (generator.labelScopeDepth()) {
returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
generator.emitPopScopes(generator.scopeRegister(), 0);
@@ -3019,13 +2912,12 @@
{
if (generator.vm()->typeProfiler()) {
for (size_t i = 0; i < m_parameters->size(); i++) {
- // FIXME: Handle Destructuring assignments into arguments.
+ // Destructuring parameters are handled in destructuring nodes.
if (!m_parameters->at(i).first->isBindingNode())
continue;
BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i).first);
RegisterID reg(CallFrame::argumentOffset(i));
- generator.emitProfileType(®, ProfileTypeBytecodeFunctionArgument, nullptr);
- generator.emitTypeProfilerExpressionInfo(parameter->divotStart(), parameter->divotEnd());
+ generator.emitProfileType(®, ProfileTypeBytecodeFunctionArgument, parameter->divotStart(), parameter->divotEnd());
}
}
@@ -3046,8 +2938,7 @@
// If there is no return we must automatically insert one.
if (!returnNode) {
RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
- if (generator.vm()->typeProfiler())
- generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement, nullptr); // Do not emit _expression_ info for this profile because it's not in the user's source code.
+ generator.emitProfileType(r0, ProfileTypeBytecodeFunctionReturnStatement); // Do not emit _expression_ info for this profile because it's not in the user's source code.
ASSERT(startOffset() >= lineStartOffset());
generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
generator.emitReturn(r0);
@@ -3367,8 +3258,7 @@
return;
}
generator.emitMove(local, value);
- if (generator.vm()->typeProfiler())
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
+ generator.emitProfileType(local, var, divotStart(), divotEnd());
if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
generator.liftTDZCheckIfPossible(var);
return;
@@ -3385,10 +3275,7 @@
return;
}
generator.emitPutToScope(scope, var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
- if (generator.vm()->typeProfiler()) {
- generator.emitProfileType(value, var.isResolved() ? ProfileTypeBytecodePutToLocalScope : ProfileTypeBytecodePutToScope, &m_boundProperty);
- generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd());
- }
+ generator.emitProfileType(value, var, divotStart(), divotEnd());
if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement)
generator.liftTDZCheckIfPossible(var);
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -4580,6 +4580,8 @@
GPRReg scratch2GPR = scratch2.gpr();
GPRReg scratch3GPR = scratch3.gpr();
+ JITCompiler::Jump isTDZValue = m_jit.branch32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag));
+
// Load the TypeProfilerLog into Scratch2.
TypeProfilerLog* cachedTypeProfilerLog = m_jit.vm()->typeProfilerLog();
m_jit.move(TrustedImmPtr(cachedTypeProfilerLog), scratch2GPR);
@@ -4612,6 +4614,8 @@
addSlowPathGenerator(
slowPathCall(clearLog, this, operationProcessTypeProfilerLogDFG, NoResult));
+ isTDZValue.link(&m_jit);
+
noResult(node);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -4609,6 +4609,8 @@
MacroAssembler::JumpList jumpToEnd;
+ jumpToEnd.append(m_jit.branchTest64(JITCompiler::Zero, valueGPR));
+
TypeLocation* cachedTypeLocation = node->typeLocation();
// Compile in a predictive type check, if possible, to see if we can skip writing to the log.
// These typechecks are inlined to match those of the 64-bit JSValue type checks.
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -1239,6 +1239,8 @@
JumpList jumpToEnd;
+ jumpToEnd.append(branchTest64(Zero, regT0));
+
// Compile in a predictive type check, if possible, to see if we can skip writing to the log.
// These typechecks are inlined to match those of the 64-bit JSValue type checks.
if (cachedTypeLocation->m_lastSeenType == TypeUndefined)
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (187523 => 187524)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2015-07-28 22:39:12 UTC (rev 187524)
@@ -1244,6 +1244,8 @@
JumpList jumpToEnd;
+ jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::EmptyValueTag)));
+
// Compile in a predictive type check, if possible, to see if we can skip writing to the log.
// These typechecks are inlined to match those of the 32-bit JSValue type checks.
if (cachedTypeLocation->m_lastSeenType == TypeUndefined)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (187523 => 187524)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2015-07-28 22:39:12 UTC (rev 187524)
@@ -2342,6 +2342,8 @@
loadisFromInstruction(1, t2)
loadConstantOrVariable(t2, t4, t0)
+ bieq t4, EmptyValueTag, .opProfileTypeDone
+
# t2 is holding the pointer to the current log entry.
loadp TypeProfilerLog::m_currentLogEntryPtr[t1], t2
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (187523 => 187524)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-07-28 22:38:17 UTC (rev 187523)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2015-07-28 22:39:12 UTC (rev 187524)
@@ -2200,6 +2200,7 @@
loadisFromInstruction(1, t3)
loadConstantOrVariable(t3, t0)
+ bqeq t0, ValueEmpty, .opProfileTypeDone
# Store the JSValue onto the log entry.
storeq t0, TypeProfilerLog::LogEntry::value[t2]
Added: trunk/Source/_javascript_Core/tests/typeProfiler/es6-block-scoping.js (0 => 187524)
--- trunk/Source/_javascript_Core/tests/typeProfiler/es6-block-scoping.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/typeProfiler/es6-block-scoping.js 2015-07-28 22:39:12 UTC (rev 187524)
@@ -0,0 +1,83 @@
+load("./driver/driver.js");
+
+let changeFoo;
+let tdzError;
+let scoping;
+let scoping2;
+function noop(){}
+function arr() {
+ return [1, 1.5, "hello", {}];
+}
+
+function wrapper() {
+
+let foo=20;
+changeFoo = function(arg) { foo = arg; }
+
+scoping = function ()
+{
+ let x = "hello";
+ if (true) {
+ let x = 20;
+ const y = true;
+ x = "h"
+ }
+ noop(x);
+}
+
+scoping2 = function()
+{
+ for (const item of arr()) {
+ noop(item);
+ }
+}
+
+}
+wrapper();
+
+// ====== End test cases ======
+
+var types = findTypeForExpression(wrapper, "foo=20;");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain exactly only one item globally");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain exactly only one item on the instruction");
+assert(types.globalTypeSet.displayTypeName === T.Integer, "global display name should be Integer");
+assert(types.instructionTypeSet.displayTypeName === T.Integer, "instruction display name should be Integer");
+
+changeFoo(20.5);
+types = findTypeForExpression(wrapper, "foo=20;");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain STILL only contain exactly one item on the instruction");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Global primitive type names should now still contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, "Global primitive type names should now contain 'Number'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, "Global primitive type names should contain exactly two items globally");
+assert(types.globalTypeSet.displayTypeName === T.Number, "global display name should be Number");
+
+
+scoping();
+types = findTypeForExpression(scoping, "x = 20");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "Primitive type names should contain only one item on the instruction");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.globalTypeSet.primitiveTypeNames.length === 2, "Primitive type names should contain two items: [String, Integer]");
+
+types = findTypeForExpression(scoping, "x)");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Global primitive type names should have string.");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Global primitive type names should have string.");
+
+types = findTypeForExpression(scoping, "y = true");
+assert(types.globalTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, "Global primitive type names should have boolean.");
+assert(types.globalTypeSet.primitiveTypeNames.length === 1, "type only have one item.");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Boolean) !== -1, "Global primitive type names should have boolean.");
+assert(types.instructionTypeSet.primitiveTypeNames.length === 1, "type only have one item.");
+
+
+scoping2();
+types = findTypeForExpression(scoping2, "item)");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Integer) !== -1, "Primitive type names should contain 'Integer'");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.Number) !== -1, "Primitive type names should contain 'Number'");
+assert(types.instructionTypeSet.primitiveTypeNames.indexOf(T.String) !== -1, "Primitive type names should contain 'String'");
+assert(types.instructionTypeSet.structures.length === 1, "should have one structure");
+assert(types.instructionTypeSet.structures[0].constructorName === "Object", "Should be object");
+assert(types.instructionTypeSet.structures[0].fields.length === 0, "Should have no fields");
Added: trunk/Source/_javascript_Core/tests/typeProfiler/es6-classes.js (0 => 187524)
--- trunk/Source/_javascript_Core/tests/typeProfiler/es6-classes.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/typeProfiler/es6-classes.js 2015-07-28 22:39:12 UTC (rev 187524)
@@ -0,0 +1,39 @@
+load("./driver/driver.js");
+
+let changeFoo;
+let tdzError;
+let scoping;
+let scoping2;
+function noop(){}
+
+function wrapper() {
+ class Animal {
+ constructor() { }
+ methodA() {}
+ }
+ class Dog extends Animal {
+ constructor() { super() }
+ methodB() {}
+ }
+
+ let dogInstance = new Dog;
+ const animalInstance = new Animal;
+}
+wrapper();
+
+// ====== End test cases ======
+
+var types = findTypeForExpression(wrapper, "dogInstance =");
+assert(types.globalTypeSet.displayTypeName === "Dog", "Should show constructor name");
+assert(types.globalTypeSet.structures[0].constructorName === "Dog", "Should be Dog");
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, "should have two fields");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("constructor") !== -1, "should have constructor");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("methodB") !== -1, "should have methodB");
+
+types = findTypeForExpression(wrapper, "animalInstance =");
+assert(types.globalTypeSet.displayTypeName === "Animal", "Should show constructor name");
+assert(types.globalTypeSet.structures.length === 1, "should have one structure");
+assert(types.globalTypeSet.structures[0].constructorName === "Animal", "Should be Animal");
+assert(types.globalTypeSet.structures[0].proto.fields.length === 2, "should have two fields");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("constructor") !== -1, "should have constructor");
+assert(types.globalTypeSet.structures[0].proto.fields.indexOf("methodA") !== -1, "should have methodA");
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
