summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecompiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-06-20 13:01:08 +0200
commit49233e234e5c787396cadb2cea33b31ae0cd65c1 (patch)
tree5410cb9a8fd53168bb60d62c54b654d86f03c38d /Source/JavaScriptCore/bytecompiler
parentb211c645d8ab690f713515dfdc84d80b11c27d2c (diff)
downloadqtwebkit-49233e234e5c787396cadb2cea33b31ae0cd65c1.tar.gz
Imported WebKit commit 3a8c29f35d00659d2ce7a0ccdfa8304f14e82327 (http://svn.webkit.org/repository/webkit/trunk@120813)
New snapshot with Windows build fixes
Diffstat (limited to 'Source/JavaScriptCore/bytecompiler')
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp104
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h21
-rw-r--r--Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp18
3 files changed, 102 insertions, 41 deletions
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index fb05e48ff..8969a7f25 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -148,6 +148,7 @@ void ResolveResult::checkValidity()
return;
case IndexedGlobal:
case ReadOnlyIndexedGlobal:
+ case WatchedIndexedGlobal:
case DynamicIndexedGlobal:
case DynamicReadOnlyIndexedGlobal:
ASSERT(m_index != missingSymbolMarker());
@@ -161,6 +162,11 @@ void ResolveResult::checkValidity()
}
#endif
+WriteBarrier<Unknown>* ResolveResult::registerPointer() const
+{
+ return &jsCast<JSGlobalObject*>(globalObject())->registerAt(index());
+}
+
static bool s_dumpsGeneratedCode = false;
void BytecodeGenerator::setDumpsGeneratedCode(bool dumpsGeneratedCode)
@@ -211,13 +217,19 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe
return true;
}
-int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant)
+int BytecodeGenerator::addGlobalVar(
+ const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
{
+ UNUSED_PARAM(functionMode);
int index = symbolTable().size();
- SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
+ SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
+ if (functionMode == IsFunctionToSpecialize)
+ newEntry.attemptToWatch();
SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry);
- if (!result.isNewEntry)
+ if (!result.isNewEntry) {
+ result.iterator->second.notifyWrite();
index = result.iterator->second.getIndex();
+ }
return index;
}
@@ -280,21 +292,27 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s
size_t newGlobals = varStack.size() + functionStack.size();
if (!newGlobals)
return;
- globalObject->resizeRegisters(symbolTable->size() + newGlobals);
+ globalObject->addRegisters(newGlobals);
for (size_t i = 0; i < functionStack.size(); ++i) {
FunctionBodyNode* function = functionStack[i];
- globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
-
+ bool propertyDidExist =
+ globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
+
JSValue value = JSFunction::create(exec, makeFunction(exec, function), scopeChain);
- int index = addGlobalVar(function->ident(), false);
+ int index = addGlobalVar(
+ function->ident(), IsVariable,
+ !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
globalObject->registerAt(index).set(*m_globalData, globalObject, value);
}
for (size_t i = 0; i < varStack.size(); ++i) {
if (globalObject->hasProperty(exec, *varStack[i].first))
continue;
- addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+ addGlobalVar(
+ *varStack[i].first,
+ (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
+ NotFunctionOrNotSpecializable);
}
}
@@ -679,6 +697,14 @@ void BytecodeGenerator::retrieveLastUnaryOp(int& dstIndex, int& srcIndex)
srcIndex = instructions().at(size - 1).u.operand;
}
+void BytecodeGenerator::retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex)
+{
+ ASSERT(instructions().size() >= 3);
+ size_t size = instructions().size();
+ dstPointer = instructions().at(size - 2).u.registerPointer;
+ srcIndex = instructions().at(size - 1).u.operand;
+}
+
void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
{
ASSERT(instructions().size() >= 4);
@@ -1170,6 +1196,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
ScopeChainIterator iter = m_scopeChain->begin();
ScopeChainIterator end = m_scopeChain->end();
size_t depth = 0;
+ size_t depthOfFirstScopeWithDynamicChecks = 0;
unsigned flags = 0;
for (; iter != end; ++iter, ++depth) {
JSObject* currentScope = iter->get();
@@ -1177,7 +1204,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
flags |= ResolveResult::DynamicFlag;
break;
}
- JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
+ JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
// Found the property
@@ -1188,7 +1215,9 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
if (++iter == end) {
if (flags & ResolveResult::DynamicFlag)
return ResolveResult::dynamicIndexedGlobalResolve(entry.getIndex(), depth, currentScope, flags);
- return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentScope, flags);
+ return ResolveResult::indexedGlobalResolve(
+ entry.getIndex(), currentScope,
+ flags | (entry.couldBeWatched() ? ResolveResult::WatchedFlag : 0));
}
#if !ASSERT_DISABLED
if (JSActivation* activation = jsDynamicCast<JSActivation*>(currentVariableObject))
@@ -1199,19 +1228,27 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property)
bool scopeRequiresDynamicChecks = false;
if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
break;
- if (scopeRequiresDynamicChecks)
- flags |= ResolveResult::DynamicFlag;
+ if (!(flags & ResolveResult::DynamicFlag)) {
+ if (scopeRequiresDynamicChecks)
+ flags |= ResolveResult::DynamicFlag;
+ else
+ ++depthOfFirstScopeWithDynamicChecks;
+ }
}
// Can't locate the property but we're able to avoid a few lookups.
JSObject* scope = iter->get();
+ // Step over the function's activation, if it needs one. At this point we
+ // know there is no dynamic scope in the function itself, so this is safe to
+ // do.
depth += m_codeBlock->needsFullScopeChain();
+ depthOfFirstScopeWithDynamicChecks += m_codeBlock->needsFullScopeChain();
if (++iter == end) {
if ((flags & ResolveResult::DynamicFlag) && depth)
return ResolveResult::dynamicGlobalResolve(depth, scope);
return ResolveResult::globalResolve(scope);
}
- return ResolveResult::dynamicResolve(depth);
+ return ResolveResult::dynamicResolve(depthOfFirstScopeWithDynamicChecks);
}
ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
@@ -1234,7 +1271,7 @@ ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
JSObject* currentScope = iter->get();
if (!currentScope->isVariableObject())
continue;
- JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope);
+ JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope);
SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
if (entry.isNull())
continue;
@@ -1274,7 +1311,7 @@ bool BytecodeGenerator::shouldAvoidResolveGlobal()
RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
{
if (resolveResult.isStatic())
- return emitGetStaticVar(dst, resolveResult);
+ return emitGetStaticVar(dst, resolveResult, property);
if (resolveResult.isGlobal() && !shouldAvoidResolveGlobal()) {
#if ENABLE(JIT)
@@ -1357,7 +1394,7 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
if (resolveResult.isStatic()) {
// Directly index the property lookup across multiple scopes.
- emitGetStaticVar(propDst, resolveResult);
+ emitGetStaticVar(propDst, resolveResult, property);
return baseDst;
}
@@ -1396,7 +1433,7 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
{
if (resolveResult.isStatic()) {
emitLoad(baseDst, jsUndefined());
- emitGetStaticVar(propDst, resolveResult);
+ emitGetStaticVar(propDst, resolveResult, property);
return baseDst;
}
@@ -1414,7 +1451,7 @@ RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, Register
return emitResolve(propDst, resolveResult, property);
}
-RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult)
+RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& identifier)
{
ValueProfile* profile = 0;
@@ -1437,16 +1474,27 @@ RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveRe
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
if (m_lastOpcodeID == op_put_global_var) {
- int dstIndex;
+ WriteBarrier<Unknown>* dstPointer;
int srcIndex;
- retrieveLastUnaryOp(dstIndex, srcIndex);
- if (dstIndex == resolveResult.index() && srcIndex == dst->index())
+ retrieveLastUnaryOp(dstPointer, srcIndex);
+ if (dstPointer == resolveResult.registerPointer() && srcIndex == dst->index())
return dst;
}
profile = emitProfiledOpcode(op_get_global_var);
instructions().append(dst->index());
- instructions().append(resolveResult.index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(profile);
+ return dst;
+
+ case ResolveResult::WatchedIndexedGlobal:
+ // Skip the peephole for now. It's not clear that it's profitable given
+ // the DFG's capabilities, and the fact that if it's watchable then we
+ // don't expect to see any put_global_var's anyway.
+ profile = emitProfiledOpcode(op_get_global_var_watchable);
+ instructions().append(dst->index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(addConstant(identifier)); // For the benefit of the DFG.
instructions().append(profile);
return dst;
@@ -1456,7 +1504,7 @@ RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveRe
}
}
-RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, RegisterID* value)
+RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, const Identifier& identifier, RegisterID* value)
{
switch (resolveResult.type()) {
case ResolveResult::Register:
@@ -1474,8 +1522,16 @@ RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResu
case ResolveResult::IndexedGlobal:
case ResolveResult::ReadOnlyIndexedGlobal:
emitOpcode(op_put_global_var);
- instructions().append(resolveResult.index());
+ instructions().append(resolveResult.registerPointer());
+ instructions().append(value->index());
+ return value;
+
+ case ResolveResult::WatchedIndexedGlobal:
+ emitOpcode(op_put_global_var_check);
+ instructions().append(resolveResult.registerPointer());
instructions().append(value->index());
+ instructions().append(jsCast<JSGlobalObject*>(resolveResult.globalObject())->symbolTable().get(identifier.impl()).addressOfIsWatched());
+ instructions().append(addConstant(identifier));
return value;
default:
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index a71bbb785..8b1d1d744 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -111,7 +111,9 @@ namespace JSC {
// The resolved binding is immutable.
ReadOnlyFlag = 0x20,
// The base object is the global object.
- GlobalFlag = 0x40
+ GlobalFlag = 0x40,
+ // The property is being watched, so writes should be special.
+ WatchedFlag = 0x80
};
enum Type {
// The property is local, and stored in a register.
@@ -131,6 +133,8 @@ namespace JSC {
// binding created with "var" at the top level. At runtime we'll
// just index into the global object.
IndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag,
+ // Like IndexedGlobal, but the property is being watched.
+ WatchedIndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag | WatchedFlag,
// Like IndexedGlobal, but the property is also read-only, like NaN,
// Infinity, or undefined.
ReadOnlyIndexedGlobal = IndexedFlag | ReadOnlyFlag | GlobalFlag | StaticFlag,
@@ -197,6 +201,7 @@ namespace JSC {
int index() const { ASSERT (isIndexed() || isRegister()); return m_index; }
size_t depth() const { ASSERT(isScoped()); return m_depth; }
JSObject* globalObject() const { ASSERT(isGlobal()); ASSERT(m_globalObject); return m_globalObject; }
+ WriteBarrier<Unknown>* registerPointer() const;
bool isRegister() const { return m_type & RegisterFlag; }
bool isDynamic() const { return m_type & DynamicFlag; }
@@ -440,8 +445,8 @@ namespace JSC {
RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
- RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&);
- RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);
+ RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&, const Identifier&);
+ RegisterID* emitPutStaticVar(const ResolveResult&, const Identifier&, RegisterID* value);
RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
@@ -541,6 +546,7 @@ namespace JSC {
ValueProfile* emitProfiledOpcode(OpcodeID);
void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
+ void retrieveLastUnaryOp(WriteBarrier<Unknown>*& dstPointer, int& srcIndex);
ALWAYS_INLINE void rewindBinaryOp();
ALWAYS_INLINE void rewindUnaryOp();
@@ -572,7 +578,9 @@ namespace JSC {
}
// Returns the index of the added var.
- int addGlobalVar(const Identifier&, bool isConstant);
+ enum ConstantMode { IsConstant, IsVariable };
+ enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
+ int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
void addParameter(const Identifier&, int parameterIndex);
@@ -608,10 +616,7 @@ namespace JSC {
void addLineInfo(unsigned lineNo)
{
-#if !ENABLE(OPCODE_SAMPLING)
- if (m_shouldEmitRichSourceInfo)
-#endif
- m_codeBlock->addLineInfo(instructions().size(), lineNo);
+ m_codeBlock->addLineInfo(instructions().size(), lineNo);
}
RegisterID* emitInitLazyRegister(RegisterID*);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index 4f113f776..d243e8ce0 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -430,7 +430,7 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
if (resolveResult.isStatic()) {
RefPtr<RegisterID> func = generator.newTemporary();
CallArguments callArguments(generator, m_args);
- generator.emitGetStaticVar(func.get(), resolveResult);
+ generator.emitGetStaticVar(func.get(), resolveResult, m_ident);
generator.emitLoad(callArguments.thisRegister(), jsUndefined());
return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
}
@@ -618,7 +618,7 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult);
+ RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult, m_ident);
RegisterID* oldValue;
if (dst == generator.ignoredResult()) {
oldValue = 0;
@@ -626,7 +626,7 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis
} else {
oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
}
- generator.emitPutStaticVar(resolveResult, value.get());
+ generator.emitPutStaticVar(resolveResult, m_ident, value.get());
return oldValue;
}
@@ -803,9 +803,9 @@ RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
+ RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident);
emitPreIncOrDec(generator, propDst.get(), m_operator);
- generator.emitPutStaticVar(resolveResult, propDst.get());
+ generator.emitPutStaticVar(resolveResult, m_ident, propDst.get());
return generator.moveToDestinationIfNeeded(dst, propDst.get());
}
@@ -1226,9 +1226,9 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
}
if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
- RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
+ RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident);
RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
- generator.emitPutStaticVar(resolveResult, result);
+ generator.emitPutStaticVar(resolveResult, m_ident, result);
return result;
}
@@ -1256,7 +1256,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
if (dst == generator.ignoredResult())
dst = 0;
RegisterID* value = generator.emitNode(dst, m_right);
- generator.emitPutStaticVar(resolveResult, value);
+ generator.emitPutStaticVar(resolveResult, m_ident, value);
return value;
}
@@ -1361,7 +1361,7 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
if (resolveResult.isStatic())
- return generator.emitPutStaticVar(resolveResult, value.get());
+ return generator.emitPutStaticVar(resolveResult, m_ident, value.get());
if (generator.codeType() != EvalCode)
return value.get();