Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (183788 => 183789)
--- trunk/Source/_javascript_Core/ChangeLog 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-05-05 03:27:09 UTC (rev 183789)
@@ -1,3 +1,31 @@
+2015-05-04 Saam Barati <[email protected]>
+
+ Global functions should be initialized as JSFunctions in byte code
+ https://bugs.webkit.org/show_bug.cgi?id=144178
+
+ Reviewed by Geoffrey Garen.
+
+ This patch makes the initialization of global functions more explicit by
+ moving initialization into bytecode. It also prepares JSC for having ES6
+ style lexical scoping because initializing global functions in bytecode
+ easily allows global functions to be initialized with the proper scope that
+ will have access to global lexical variables. Global lexical variables
+ should be visible to global functions but don't live on the global object.
+
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::UnlinkedProgramCodeBlock::visitChildren):
+ * bytecode/UnlinkedCodeBlock.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::generate):
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * bytecompiler/BytecodeGenerator.h:
+ * runtime/Executable.cpp:
+ (JSC::ProgramExecutable::initializeGlobalProperties):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::addGlobalVar):
+ (JSC::JSGlobalObject::addFunction):
+ * runtime/JSGlobalObject.h:
+
2015-05-04 Filip Pizlo <[email protected]>
Large array shouldn't be slow
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (183788 => 183789)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2015-05-05 03:27:09 UTC (rev 183789)
@@ -471,8 +471,6 @@
UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
Base::visitChildren(thisObject, visitor);
- for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
- visitor.append(&thisObject->m_functionDeclarations[i].second);
}
UnlinkedCodeBlock::~UnlinkedCodeBlock()
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (183788 => 183789)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2015-05-05 03:27:09 UTC (rev 183789)
@@ -654,21 +654,14 @@
static void destroy(JSCell*);
- void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
- {
- m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
- }
-
void addVariableDeclaration(const Identifier& name, bool isConstant)
{
m_varDeclarations.append(std::make_pair(name, isConstant));
}
typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
- typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
- const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
static void visitChildren(JSCell*, SlotVisitor&);
@@ -679,7 +672,6 @@
}
VariableDeclations m_varDeclarations;
- FunctionDeclations m_functionDeclarations;
public:
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (183788 => 183789)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2015-05-05 03:27:09 UTC (rev 183789)
@@ -77,9 +77,17 @@
{
RefPtr<RegisterID> temp = newTemporary();
- for (FunctionBodyNode* functionBody : m_functionsToInitialize) {
+ RefPtr<RegisterID> globalScope = scopeRegister(); // FIXME: With lexical scoping, this won't always be the global object: https://bugs.webkit.org/show_bug.cgi?id=142944
+ for (auto functionPair : m_functionsToInitialize) {
+ FunctionBodyNode* functionBody = functionPair.first;
+ FunctionVariableType functionType = functionPair.second;
emitNewFunction(temp.get(), functionBody);
- initializeVariable(variable(functionBody->ident()), temp.get());
+ if (functionType == NormalFunctionVariable)
+ initializeVariable(variable(functionBody->ident()) , temp.get());
+ else if (functionType == GlobalFunctionVariable)
+ emitPutToScope(globalScope.get(), Variable(functionBody->ident()), temp.get(), ThrowIfNotFound);
+ else
+ RELEASE_ASSERT_NOT_REACHED();
}
}
@@ -163,8 +171,7 @@
for (size_t i = 0; i < functionStack.size(); ++i) {
FunctionBodyNode* function = functionStack[i];
- UnlinkedFunctionExecutable* unlinkedFunction = makeFunction(function);
- codeBlock->addFunctionDeclaration(*m_vm, function->ident(), unlinkedFunction);
+ m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable));
}
for (size_t i = 0; i < varStack.size(); ++i)
@@ -384,7 +391,7 @@
for (FunctionBodyNode* function : functionNode->functionStack()) {
const Identifier& ident = function->ident();
createVariable(ident, varKind(ident.impl()), IsVariable);
- m_functionsToInitialize.append(function);
+ m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
}
for (auto& entry : functionNode->varStack()) {
ConstantMode constantMode = modeForIsConstant(entry.second & DeclarationStacks::IsConstant);
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (183788 => 183789)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2015-05-05 03:27:09 UTC (rev 183789)
@@ -744,7 +744,8 @@
Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
Vector<TryContext> m_tryContextStack;
Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
- Vector<FunctionBodyNode*> m_functionsToInitialize;
+ enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
+ Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
bool m_needToInitializeArguments { false };
Vector<TryRange> m_tryRanges;
Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (183788 => 183789)
--- trunk/Source/_javascript_Core/runtime/Executable.cpp 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp 2015-05-05 03:27:09 UTC (rev 183789)
@@ -510,12 +510,11 @@
BatchedTransitionOptimizer optimizer(vm, globalObject);
const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
- const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
- for (size_t i = 0; i < functionDeclarations.size(); ++i) {
- UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
- JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source), scope);
- globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
+ for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
+ UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
+ ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
+ globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
if (vm.typeProfiler() || vm.controlFlowProfiler()) {
vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(),
unlinkedFunctionExecutable->typeProfilingStartOffset(),
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (183788 => 183789)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2015-05-05 03:27:09 UTC (rev 183789)
@@ -502,16 +502,12 @@
return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
}
-JSGlobalObject::NewGlobalVar JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
+void JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
{
ConcurrentJITLocker locker(symbolTable()->m_lock);
SymbolTableEntry entry = symbolTable()->get(locker, ident.impl());
- if (!entry.isNull()) {
- NewGlobalVar result;
- result.offset = entry.scopeOffset();
- result.set = entry.watchpointSet();
- return result;
- }
+ if (!entry.isNull())
+ return;
ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker);
SymbolTableEntry newEntry(VarOffset(offset), (constantMode == IsConstant) ? ReadOnly : 0);
@@ -523,21 +519,13 @@
ScopeOffset offsetForAssert = addVariables(1);
RELEASE_ASSERT(offsetForAssert == offset);
-
- NewGlobalVar var;
- var.offset = offset;
- var.set = newEntry.watchpointSet();
- return var;
}
-void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName, JSValue value)
+void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName)
{
VM& vm = exec->vm();
removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties.
- NewGlobalVar var = addGlobalVar(propertyName, IsVariable);
- variableAt(var.offset).set(exec->vm(), this, value);
- if (var.set)
- var.set->touch(VariableWriteFireDetail(this, propertyName));
+ addGlobalVar(propertyName, IsVariable);
}
static inline JSObject* lastInPrototypeChain(JSObject* object)
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (183788 => 183789)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2015-05-05 03:27:09 UTC (rev 183789)
@@ -338,11 +338,7 @@
setGlobalThis(vm, thisValue);
}
- struct NewGlobalVar {
- ScopeOffset offset;
- WatchpointSet* set;
- };
- NewGlobalVar addGlobalVar(const Identifier&, ConstantMode);
+ void addGlobalVar(const Identifier&, ConstantMode);
public:
JS_EXPORT_PRIVATE ~JSGlobalObject();
@@ -374,7 +370,7 @@
if (!hasProperty(exec, propertyName))
addGlobalVar(propertyName, IsConstant);
}
- void addFunction(ExecState*, const Identifier&, JSValue);
+ void addFunction(ExecState*, const Identifier&);
// The following accessors return pristine values, even if a script
// replaces the global object's associated property.