2011-06-21 Geoffrey Garen <ggaren@apple.com>
Reviewed by Oliver Hunt.
Moved 'const' off the global-variable-as-local-variable crack pipe
https://bugs.webkit.org/show_bug.cgi?id=63105
This is necessary for moving the rest of the code off of same.
Many problems remain in our handling of const. I have fixed none of them.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::scopeChain): New accessor, needed to enable
const to directly implement its unique scoping rules.
* bytecompiler/NodesCodegen.cpp:
(JSC::PrefixResolveNode::emitBytecode): Do specify that our resolve is
for writing, so we don't overwrite const variables.
(JSC::ConstDeclNode::emitCodeSingle): Don't assume that all declared const
variables are available as local variables, since this won't be the case
once global variables are not available as local variables. Instead, use
put_scoped_var in the case where there is no local variable. Like a local
variable, put_scoped_var succeeds even though const properties are
read-only, since put_scoped_var skips read-only checks. (Yay?)
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@89392 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 034e4f9..2f4bbda 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,29 @@
+2011-06-21 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Moved 'const' off the global-variable-as-local-variable crack pipe
+ https://bugs.webkit.org/show_bug.cgi?id=63105
+
+ This is necessary for moving the rest of the code off of same.
+
+ Many problems remain in our handling of const. I have fixed none of them.
+
+ * bytecompiler/BytecodeGenerator.h:
+ (JSC::BytecodeGenerator::scopeChain): New accessor, needed to enable
+ const to directly implement its unique scoping rules.
+
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::PrefixResolveNode::emitBytecode): Do specify that our resolve is
+ for writing, so we don't overwrite const variables.
+
+ (JSC::ConstDeclNode::emitCodeSingle): Don't assume that all declared const
+ variables are available as local variables, since this won't be the case
+ once global variables are not available as local variables. Instead, use
+ put_scoped_var in the case where there is no local variable. Like a local
+ variable, put_scoped_var succeeds even though const properties are
+ read-only, since put_scoped_var skips read-only checks. (Yay?)
+
2011-06-21 Oliver Hunt <oliver@apple.com>
Reviewed by Alexey Proskuryakov.
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 4daa198..2bbc19c 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -399,6 +399,8 @@
bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
+
+ ScopeChainNode* scopeChain() const { return m_scopeChain.get(); }
private:
void emitOpcode(OpcodeID);
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index a7abadf..881bbe0 100644
--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -744,7 +744,7 @@
size_t depth = 0;
JSObject* globalObject = 0;
bool requiresDynamicChecks = false;
- if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
+ if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
emitPreIncOrDec(generator, propDst.get(), m_operator);
generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
@@ -1293,6 +1293,7 @@
RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
{
+ // FIXME: This code does not match the behavior of const in Firefox.
if (RegisterID* local = generator.constRegisterFor(m_ident)) {
if (!m_init)
return local;
@@ -1300,17 +1301,30 @@
return generator.emitNode(local, m_init);
}
- if (generator.codeType() != EvalCode) {
- if (m_init)
- return generator.emitNode(m_init);
- else
- return generator.emitResolve(generator.newTemporary(), m_ident);
+ RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
+
+ ScopeChainIterator iter = generator.scopeChain()->begin();
+ ScopeChainIterator end = generator.scopeChain()->end();
+ size_t depth = 0;
+ for (; iter != end; ++iter, ++depth) {
+ JSObject* currentScope = iter->get();
+ if (!currentScope->isVariableObject())
+ continue;
+ JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
+ SymbolTableEntry entry = currentVariableObject->symbolTable().get(m_ident.impl());
+ if (entry.isNull())
+ continue;
+
+ return generator.emitPutScopedVar(depth, entry.getIndex(), value.get(), currentVariableObject->isGlobalObject() ? currentVariableObject : 0);
}
- // FIXME: While this code should only be hit in eval code, it will potentially
- // assign to the wrong base if m_ident exists in an intervening dynamic scope.
+
+ if (generator.codeType() != EvalCode)
+ return value.get();
+
+ // FIXME: While this code should only be hit in an eval block, it will assign
+ // to the wrong base if m_ident exists in an intervening with scope.
RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
- RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
- return generator.emitPutById(base.get(), m_ident, value);
+ return generator.emitPutById(base.get(), m_ident, value.get());
}
RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)