Rolled out <http://trac.webkit.org/changeset/127698> because it broke
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Sep 2012 19:45:35 +0000 (19:45 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Sep 2012 19:45:35 +0000 (19:45 +0000)
fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html

    Named functions should not allocate scope objects for their names
    https://bugs.webkit.org/show_bug.cgi?id=95659

    Reviewed by Oliver Hunt.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@127774 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/JSNameScope.h

index fdea69b..cb59331 100644 (file)
@@ -1,3 +1,13 @@
+2012-09-05  Geoffrey Garen  <ggaren@apple.com>
+
+        Rolled out <http://trac.webkit.org/changeset/127698> because it broke
+        fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html
+
+            Named functions should not allocate scope objects for their names
+            https://bugs.webkit.org/show_bug.cgi?id=95659
+
+            Reviewed by Oliver Hunt.
+
 2012-09-06  Mark Lam  <mark.lam@apple.com>
 
         Renamed useYarrJIT() option to useRegExpJIT(). Also fixed regression in
         * interpreter/Interpreter.cpp:
         (JSC::Interpreter::privateExecute):
 
-2012-09-05  Geoffrey Garen  <ggaren@apple.com>
-
-        Named functions should not allocate scope objects for their names
-        https://bugs.webkit.org/show_bug.cgi?id=95659
-
-        Reviewed by Oliver Hunt.
-
-        In most cases, we can merge a function expression's name into its symbol
-        table. This reduces memory footprint per closure from three objects
-        (function + activation + name scope) to two (function + activation),
-        speeds up closure allocation, and speeds up recursive calls.
-
-        In the case of a named function expression that contains a non-strict
-        eval, the rules are so bat-poop crazy that I don't know how to model
-        them without an extra object. Since functions now default to not having
-        such an object, this case needs to allocate the object on function
-        entry.
-
-        Therefore, this patch makes the slow case a bit slower so the fast case
-        can be faster and more memory-efficient. (Note that the slow case already
-        allocates an activation on entry, and until recently also allocated a
-        scope chain node on entry, so adding one allocation on entry shouldn't
-        break the bank.)
-
-        * bytecode/CodeBlock.cpp:
-        (JSC::CodeBlock::CodeBlock): Caught a missed initializer. No behavior change.
-
-        * bytecompiler/BytecodeGenerator.cpp:
-        (JSC::BytecodeGenerator::BytecodeGenerator): Put the callee in static scope
-        during compilation so it doesn't need to be in dynamic scope at runtime.
-
-        (JSC::BytecodeGenerator::resolveCallee):
-        (JSC::BytecodeGenerator::addCallee): Helper functions for either statically
-        resolving the callee or adding a dynamic scope that will resolve to it,
-        depending on whether you're in the fast path.
-
-        We move the callee into a var location if it's captured because activations
-        prefer to have contiguous ranges of captured variables.
-
-        * bytecompiler/BytecodeGenerator.h:
-        (JSC::BytecodeGenerator::registerFor):
-        (BytecodeGenerator):
-
-        * dfg/DFGOperations.cpp:
-        * interpreter/Interpreter.cpp:
-        (JSC::Interpreter::privateExecute):
-        * jit/JITStubs.cpp:
-        (JSC::DEFINE_STUB_FUNCTION):
-        * llint/LLIntSlowPaths.cpp:
-        (JSC::LLInt::LLINT_SLOW_PATH_DECL): This is the point of the patch: remove
-        one allocation in the case of a named function expression.
-
-        * parser/Parser.cpp:
-        (JSC::::Parser):
-        * parser/Parser.h:
-        (JSC::Scope::declareCallee):
-        (Scope):
-        (Parser):
-        (JSC::parse):
-        * runtime/Executable.cpp:
-        (JSC::EvalExecutable::compileInternal):
-        (JSC::ProgramExecutable::checkSyntax):
-        (JSC::ProgramExecutable::compileInternal):
-        (JSC::FunctionExecutable::produceCodeBlockFor):
-        (JSC::FunctionExecutable::fromGlobalCode): Pipe the callee's name through
-        the parser so we get accurate information on whether the callee was captured.
-
-        (JSC::FunctionExecutable::FunctionExecutable):
-        (JSC::EvalExecutable::compileInternal):
-        (JSC::ProgramExecutable::checkSyntax):
-        (JSC::ProgramExecutable::compileInternal):
-        (JSC::FunctionExecutable::produceCodeBlockFor):
-        (JSC::FunctionExecutable::fromGlobalCode):
-        * runtime/Executable.h:
-        (JSC::FunctionExecutable::create):
-        (FunctionExecutable):
-        (JSC::FunctionExecutable::finishCreation): I had to refactor function
-        creation to support the following function constructor quirk: the function
-        gets a name, but its name is not in lexical scope.
-
-        To simplify this, FunctionExecutable now automatically extracts all the
-        data it needs from the parsed node. The special "fromGlobalCode" path
-        used by the function constructor creates an anonymous function, and then
-        quirkily sets the value used by the .name property to be non-null, even
-        though the parsed name is null.
-
-        * runtime/JSNameScope.h:
-        (JSC::JSNameScope::create):
-        (JSC::JSNameScope::JSNameScope): Added support for explicitly specifying
-        your container scope. The compiler uses this for named function expressions.
-
 2012-09-05  Gavin Barraclough  <barraclough@apple.com>
 
         a = data[a]++; sets the wrong key in data
index 41b23ae..559b0ae 100644 (file)
@@ -1752,7 +1752,6 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo
     , m_heap(&m_globalObject->globalData().heap)
     , m_numCalleeRegisters(0)
     , m_numVars(0)
-    , m_numCapturedVars(0)
     , m_isConstructor(isConstructor)
     , m_numParameters(0)
     , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
index 4838230..6cc25ce 100644 (file)
 
 #include "BatchedTransitionOptimizer.h"
 #include "Comment.h"
-#include "Interpreter.h"
 #include "JSActivation.h"
 #include "JSFunction.h"
-#include "JSNameScope.h"
+#include "Interpreter.h"
 #include "LowLevelInterpreter.h"
+
 #include "StrongInlines.h"
 #include <wtf/text/WTFString.h>
 
@@ -324,7 +324,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, JSScope* scope, S
         bool propertyDidExist = 
             globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
         
-        JSValue value = JSFunction::create(exec, FunctionExecutable::create(*m_globalData, function), scope);
+        JSValue value = JSFunction::create(exec, makeFunction(exec, function), scope);
         int index = addGlobalVar(
             function->ident(), IsVariable,
             !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
@@ -419,8 +419,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
         }
     }
 
-    RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
-
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
 
@@ -458,7 +456,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
     }
 
     codeBlock->m_numCapturedVars = codeBlock->m_numVars;
-
     m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
@@ -500,9 +497,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* sc
 
     preserveLastVar();
 
-    // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.
-    addCallee(functionBody, calleeRegister);
-
     if (isConstructor()) {
         prependComment("'this' because we are a Constructor function");
         emitOpcode(op_create_this);
@@ -555,7 +549,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SymbolT
 
     const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i)
-        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i]));
+        m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
 
     const DeclarationStacks::VarStack& varStack = evalNode->varStack();
     unsigned numVariables = varStack.size();
@@ -580,53 +574,6 @@ RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
     return reg;
 }
 
-RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
-{
-    if (functionBodyNode->ident().isNull())
-        return 0;
-
-    m_calleeRegister.setIndex(RegisterFile::Callee);
-
-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
-        emitOpcode(op_push_name_scope);
-        instructions().append(addConstant(functionBodyNode->ident()));
-        instructions().append(m_calleeRegister.index());
-        instructions().append(ReadOnly | DontDelete);
-
-        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
-        m_scope.set(*globalData(),
-            JSNameScope::create(
-                m_scope->globalObject()->globalExec(),
-                functionBodyNode->ident(),
-                jsUndefined(),
-                ReadOnly | DontDelete,
-                m_scope.get()
-            )
-        );
-        return 0;
-    }
-
-    if (!functionBodyNode->captures(functionBodyNode->ident()))
-        return &m_calleeRegister;
-
-    // Move the callee into the captured section of the stack.
-    return emitMove(addVar(), &m_calleeRegister);
-}
-
-void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
-{
-    if (functionBodyNode->ident().isNull())
-        return;
-
-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
-        return;
-
-    ASSERT(calleeRegister);
-    symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly));
-}
-
 void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
 {
     // Parameters overwrite var declarations, but not function declarations.
@@ -1883,14 +1830,14 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
 
 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
-    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function)), false);
+    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)), false);
 }
 
 RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
     FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0);
     if (ptr.isNewEntry)
-        ptr.iterator->second = m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function));
+        ptr.iterator->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
     return emitNewFunctionInternal(dst, ptr.iterator->second, true);
 }
 
@@ -1915,7 +1862,7 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
     FunctionBodyNode* function = n->body();
-    unsigned index = m_codeBlock->addFunctionExpr(FunctionExecutable::create(*m_globalData, function));
+    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
     
     createActivationIfNecessary();
     emitOpcode(op_new_func_exp);
@@ -2652,7 +2599,7 @@ void BytecodeGenerator::emitReadOnlyExceptionIfNeeded()
     if (!isStrictMode())
         return;
 
-    RefPtr<RegisterID> error = emitLoad(newTemporary(), JSValue(createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError)));
+    RefPtr<RegisterID> error = emitLoad(newTemporary(), createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError));
     emitThrow(error.get());
 }
 
index 037a2ce..d3b5266 100644 (file)
@@ -617,9 +617,7 @@ namespace JSC {
         int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
 
         void addParameter(const Identifier&, int parameterIndex);
-        RegisterID* resolveCallee(FunctionBodyNode*);
-        void addCallee(FunctionBodyNode*, RegisterID*);
-
+        
         void preserveLastVar();
         bool shouldAvoidResolveGlobal();
 
@@ -628,9 +626,6 @@ namespace JSC {
             if (index >= 0)
                 return m_calleeRegisters[index];
 
-            if (index == RegisterFile::Callee)
-                return m_calleeRegister;
-
             ASSERT(m_parameters.size());
             return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
         }
@@ -641,6 +636,16 @@ namespace JSC {
 
         unsigned addConstantBuffer(unsigned length);
         
+        FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
+        {
+            return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+        }
+
+        FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
+        {
+            return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
+        }
+
         JSString* addStringConstant(const Identifier&);
 
         void addLineInfo(unsigned lineNo)
@@ -711,7 +716,6 @@ namespace JSC {
         HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
         RegisterID m_ignoredResultRegister;
         RegisterID m_thisRegister;
-        RegisterID m_calleeRegister;
         RegisterID* m_activationRegister;
         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
         SegmentedVector<RegisterID, 32> m_calleeRegisters;
index 824a0a3..72fe983 100644 (file)
@@ -1243,7 +1243,7 @@ JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExec
     ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info));
     JSGlobalData& globalData = exec->globalData();
     NativeCallFrameTracer tracer(&globalData, exec);
-    return JSFunction::create(exec, static_cast<FunctionExecutable*>(functionExecutable), exec->scope());
+    return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scope());
 }
 
 JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* functionExecutableAsCell)
@@ -1251,7 +1251,14 @@ JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* fu
     ASSERT(functionExecutableAsCell->inherits(&FunctionExecutable::s_info));
     FunctionExecutable* functionExecutable =
         static_cast<FunctionExecutable*>(functionExecutableAsCell);
-    return JSFunction::create(exec, functionExecutable, exec->scope());
+    JSFunction* function = functionExecutable->make(exec, exec->scope());
+    if (!functionExecutable->name().isNull()) {
+        JSNameScope* functionScopeObject =
+            JSNameScope::create(
+                exec, functionExecutable->name(), function, ReadOnly | DontDelete);
+        function->setScope(exec->globalData(), functionScopeObject);
+    }
+    return function;
 }
 
 size_t DFG_OPERATION operationIsObject(ExecState* exec, EncodedJSValue value)
index 3a76380..37c1cab 100644 (file)
@@ -1347,7 +1347,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
         for (int i = 0; i < numFunctions; ++i) {
             FunctionExecutable* function = codeBlock->functionDecl(i);
             PutPropertySlot slot;
-            variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
+            variableObject->methodTable()->put(variableObject, callFrame, function->name(), function->make(callFrame, scope), slot);
         }
     }
 
@@ -4279,6 +4279,18 @@ skip_id_custom_self:
         FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
         JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
 
+        /* 
+            The Identifier in a FunctionExpression can be referenced from inside
+            the FunctionExpression's FunctionBody to allow the function to call
+            itself recursively. However, unlike in a FunctionDeclaration, the
+            Identifier in a FunctionExpression cannot be referenced from and
+            does not affect the scope enclosing the FunctionExpression.
+         */
+        if (!function->name().isNull()) {
+            JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);
+            func->setScope(*globalData, functionScopeObject);
+        }
+
         callFrame->uncheckedR(dst) = JSValue(func);
 
         vPC += OPCODE_LENGTH(op_new_func_exp);
index 1c65d70..576dba6 100644 (file)
@@ -2141,7 +2141,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
     STUB_INIT_STACK_FRAME(stackFrame);
     
     ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
-    return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
+    return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scope());
 }
 
 inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
@@ -2982,9 +2982,21 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
     CallFrame* callFrame = stackFrame.callFrame;
 
     FunctionExecutable* function = stackFrame.args[0].function();
-    JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
+    JSFunction* func = function->make(callFrame, callFrame->scope());
     ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
 
+    /* 
+        The Identifier in a FunctionExpression can be referenced from inside
+        the FunctionExpression's FunctionBody to allow the function to call
+        itself recursively. However, unlike in a FunctionDeclaration, the
+        Identifier in a FunctionExpression cannot be referenced from and
+        does not affect the scope enclosing the FunctionExpression.
+     */
+    if (!function->name().isNull()) {
+        JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);
+        func->setScope(callFrame->globalData(), functionScopeObject);
+    }
+
     return func;
 }
 
index 820079c..c5fff77 100644 (file)
@@ -1260,7 +1260,7 @@ LLINT_SLOW_PATH_DECL(slow_path_new_func)
 #if LLINT_SLOW_PATH_TRACING
     dataLog("Creating function!\n");
 #endif
-    LLINT_RETURN(JSFunction::create(exec, codeBlock->functionDecl(pc[2].u.operand), exec->scope()));
+    LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scope()));
 }
 
 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
@@ -1268,7 +1268,12 @@ LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
     LLINT_BEGIN();
     CodeBlock* codeBlock = exec->codeBlock();
     FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
-    JSFunction* func = JSFunction::create(exec, function, exec->scope());
+    JSFunction* func = function->make(exec, exec->scope());
+    
+    if (!function->name().isNull()) {
+        JSNameScope* functionScopeObject = JSNameScope::create(exec, function->name(), func, ReadOnly | DontDelete);
+        func->setScope(globalData, functionScopeObject);
+    }
     
     LLINT_RETURN(func);
 }
index a70c684..fdda73c 100644 (file)
@@ -40,7 +40,7 @@ using namespace std;
 namespace JSC {
 
 template <typename LexerType>
-Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
+Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode)
     : m_globalData(globalData)
     , m_source(&source)
     , m_stack(wtfThreadData().stack())
@@ -71,8 +71,6 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu
         for (unsigned i = 0; i < parameters->size(); i++)
             scope->declareParameter(&parameters->at(i));
     }
-    if (!name.isNull())
-        scope->declareCallee(&name);
     next();
     m_lexer->setLastLineNumber(tokenLine());
 }
index 3ca5ec4..401f21e 100644 (file)
@@ -208,11 +208,6 @@ struct Scope {
     bool isFunction() { return m_isFunction; }
     bool isFunctionBoundary() { return m_isFunctionBoundary; }
 
-    void declareCallee(const Identifier* ident)
-    {
-        m_declaredVariables.add(ident->ustring().impl());
-    }
-
     bool declareVariable(const Identifier* ident)
     {
         bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
@@ -387,7 +382,7 @@ class Parser {
     WTF_MAKE_FAST_ALLOCATED;
 
 public:
-    Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
+    Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, JSParserStrictness, JSParserMode);
     ~Parser();
 
     template <class ParsedNode>
@@ -1025,17 +1020,17 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
 }
 
 template <class ParsedNode>
-PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
+PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
 {
     SamplingRegion samplingRegion("Parsing");
 
     ASSERT(source.provider()->data());
 
     if (source.provider()->data()->is8Bit()) {
-        Parser< Lexer<LChar> > parser(globalData, source, parameters, name, strictness, parserMode);
+        Parser< Lexer<LChar> > parser(globalData, source, parameters, strictness, parserMode);
         return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
     }
-    Parser< Lexer<UChar> > parser(globalData, source, parameters, name, strictness, parserMode);
+    Parser< Lexer<UChar> > parser(globalData, source, parameters, strictness, parserMode);
     return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
 }
 
index 024f065..77c2749 100644 (file)
@@ -133,16 +133,24 @@ void ProgramExecutable::destroy(JSCell* cell)
 
 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
 
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node)
-    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode())
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
     , m_numCapturedVariables(0)
-    , m_forceUsesArguments(node->usesArguments())
-    , m_parameters(node->parameters())
-    , m_name(node->ident())
-    , m_inferredName(node->inferredName().isNull() ? globalData.propertyNames->emptyIdentifier : node->inferredName())
+    , m_forceUsesArguments(forceUsesArguments)
+    , m_parameters(parameters)
+    , m_name(name)
+    , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
+{
+}
+
+FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
+    : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
+    , m_numCapturedVariables(0)
+    , m_forceUsesArguments(forceUsesArguments)
+    , m_parameters(parameters)
+    , m_name(name)
+    , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
 {
-    m_firstLine = node->lineNo();
-    m_lastLine = node->lastLine();
 }
 
 void FunctionExecutable::destroy(JSCell* cell)
@@ -202,7 +210,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
     } else {
         if (!lexicalGlobalObject->evalEnabled())
             return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled")));
-        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
         if (!evalNode) {
             ASSERT(exception);
             return exception;
@@ -285,7 +293,7 @@ JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
     JSObject* exception = 0;
     JSGlobalData* globalData = &exec->globalData();
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
     if (programNode)
         return 0;
     ASSERT(exception);
@@ -327,7 +335,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI
         newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
         m_programCodeBlock = newCodeBlock.release();
     } else {
-        RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+        RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
         if (!programNode) {
             ASSERT(exception);
             return exception;
@@ -470,18 +478,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* s
     exception = 0;
     JSGlobalData* globalData = scope->globalData();
     JSGlobalObject* globalObject = scope->globalObject();
-    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(
-        globalData,
-        globalObject,
-        m_source,
-        m_parameters.get(),
-        name(),
-        isStrictMode() ? JSParseStrict : JSParseNormal,
-        FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode,
-        0,
-        0,
-        &exception
-    );
+    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(globalData, globalObject, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 0, 0, &exception);
 
     if (!body) {
         ASSERT(exception);
@@ -650,16 +647,16 @@ void FunctionExecutable::unlinkCalls()
 #endif
 }
 
-FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
+FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
 {
     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-    RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
     if (!program) {
         ASSERT(*exception);
         return 0;
     }
 
-    // This function assumes an input string that would result in a single anonymous function expression.
+    // Uses of this function that would not result in a single function expression are invalid.
     StatementNode* exprStatement = program->singleStatement();
     ASSERT(exprStatement);
     ASSERT(exprStatement->isExprStatement());
@@ -668,11 +665,8 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, E
     ASSERT(funcExpr->isFuncExprNode());
     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
     ASSERT(body);
-    ASSERT(body->ident().isNull());
 
-    FunctionExecutable* functionExecutable = FunctionExecutable::create(exec->globalData(), body);
-    functionExecutable->m_nameValue.set(exec->globalData(), functionExecutable, jsString(&exec->globalData(), name.ustring()));
-    return functionExecutable;
+    return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
 }
 
 String FunctionExecutable::paramString() const
index 5c4fc69..6c7bb42 100644 (file)
@@ -539,16 +539,27 @@ namespace JSC {
     public:
         typedef ScriptExecutable Base;
 
-        static FunctionExecutable* create(JSGlobalData& globalData, FunctionBodyNode* node)
+        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, node);
-            executable->finishCreation(globalData);
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
+            executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
+            return executable;
+        }
+
+        static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
+        {
+            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
+            executable->finishCreation(globalData, name, firstLine, lastLine);
             return executable;
         }
-        static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
 
         static void destroy(JSCell*);
 
+        JSFunction* make(ExecState* exec, JSScope* scope)
+        {
+            return JSFunction::create(exec, this, scope);
+        }
+        
         // Returns either call or construct bytecode. This can be appropriate
         // for answering questions that that don't vary between call and construct --
         // for example, argumentsRegister().
@@ -697,6 +708,7 @@ namespace JSC {
 
         void clearCodeIfNotCompiling();
         static void visitChildren(JSCell*, SlotVisitor&);
+        static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
         {
             return Structure::create(globalData, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info);
@@ -709,14 +721,17 @@ namespace JSC {
         void clearCode();
 
     protected:
-        void finishCreation(JSGlobalData& globalData)
+        void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
         {
             Base::finishCreation(globalData);
-            m_nameValue.set(globalData, this, jsString(&globalData, name().ustring()));
+            m_firstLine = firstLine;
+            m_lastLine = lastLine;
+            m_nameValue.set(globalData, this, jsString(&globalData, name.ustring()));
         }
 
     private:
-        FunctionExecutable(JSGlobalData&, FunctionBodyNode*);
+        FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
+        FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
 
         JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
         JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
index e67370d..73b1208 100644 (file)
@@ -38,14 +38,7 @@ public:
 
     static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes)
     {
-        JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, exec->scope());
-        scopeObject->finishCreation(exec, identifier, value, attributes);
-        return scopeObject;
-    }
-
-    static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes, JSScope* next)
-    {
-        JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, next);
+        JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec);
         scopeObject->finishCreation(exec, identifier, value, attributes);
         return scopeObject;
     }
@@ -71,12 +64,12 @@ protected:
     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | Base::StructureFlags;
 
 private:
-    JSNameScope(ExecState* exec, JSScope* next)
+    JSNameScope(ExecState* exec)
         : Base(
             exec->globalData(),
             exec->lexicalGlobalObject()->nameScopeStructure(),
             reinterpret_cast<Register*>(&m_registerStore + 1),
-            next
+            exec->scope()
         )
     {
     }