Changeset 127810 in webkit


Ignore:
Timestamp:
Sep 6, 2012 6:42:53 PM (12 years ago)
Author:
ggaren@apple.com
Message:

Source/JavaScriptCore: Rolled back in <http://trac.webkit.org/changeset/127698> with a fix for
fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html, which
is to make sure that function declarations don't put their names in scope.

Reviewed by Gavin Barraclough.

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

Reviewed by Oliver Hunt.

LayoutTests: Rolled back in <http://trac.webkit.org/changeset/127698> with a fix for
fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html.

Added a more explicit test for the feature I broke in
fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html.

Reviewed by Gavin Barraclough.

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

Reviewed by Oliver Hunt.

  • fast/dom/HTMLScriptElement/script-reexecution.html:
  • fast/js/function-name-is-in-scope-expected.txt: Added.
  • fast/js/function-name-is-in-scope.html: Added.
Location:
trunk
Files:
2 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r127808 r127810  
     12012-09-06  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Rolled back in <http://trac.webkit.org/changeset/127698> with a fix for
     4        fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html.
     5
     6        Added a more explicit test for the feature I broke in
     7        fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html.
     8
     9        Reviewed by Gavin Barraclough.
     10
     11            Named functions should not allocate scope objects for their names
     12            https://bugs.webkit.org/show_bug.cgi?id=95659
     13
     14            Reviewed by Oliver Hunt.
     15
     16        * fast/dom/HTMLScriptElement/script-reexecution.html:
     17        * fast/js/function-name-is-in-scope-expected.txt: Added.
     18        * fast/js/function-name-is-in-scope.html: Added.
     19
    1202012-09-06  Tim Horton  <timothy_horton@apple.com>
    221
  • trunk/Source/JavaScriptCore/ChangeLog

    r127809 r127810  
     12012-09-05  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Rolled back in <http://trac.webkit.org/changeset/127698> with a fix for
     4        fast/dom/HTMLScriptElement/script-reexecution-pretty-diff.html, which
     5        is to make sure that function declarations don't put their names in scope.
     6
     7        Reviewed by Gavin Barraclough.
     8
     9            Named functions should not allocate scope objects for their names
     10            https://bugs.webkit.org/show_bug.cgi?id=95659
     11
     12            Reviewed by Oliver Hunt.
     13
    1142012-09-06  Michael Saboff  <msaboff@apple.com>
    215
     
    8295        * interpreter/Interpreter.cpp:
    8396        (JSC::Interpreter::privateExecute):
     97
     982012-09-05  Geoffrey Garen  <ggaren@apple.com>
     99
     100        Named functions should not allocate scope objects for their names
     101        https://bugs.webkit.org/show_bug.cgi?id=95659
     102
     103        Reviewed by Oliver Hunt.
     104
     105        In most cases, we can merge a function expression's name into its symbol
     106        table. This reduces memory footprint per closure from three objects
     107        (function + activation + name scope) to two (function + activation),
     108        speeds up closure allocation, and speeds up recursive calls.
     109
     110        In the case of a named function expression that contains a non-strict
     111        eval, the rules are so bat-poop crazy that I don't know how to model
     112        them without an extra object. Since functions now default to not having
     113        such an object, this case needs to allocate the object on function
     114        entry.
     115
     116        Therefore, this patch makes the slow case a bit slower so the fast case
     117        can be faster and more memory-efficient. (Note that the slow case already
     118        allocates an activation on entry, and until recently also allocated a
     119        scope chain node on entry, so adding one allocation on entry shouldn't
     120        break the bank.)
     121
     122        * bytecode/CodeBlock.cpp:
     123        (JSC::CodeBlock::CodeBlock): Caught a missed initializer. No behavior change.
     124
     125        * bytecompiler/BytecodeGenerator.cpp:
     126        (JSC::BytecodeGenerator::BytecodeGenerator): Put the callee in static scope
     127        during compilation so it doesn't need to be in dynamic scope at runtime.
     128
     129        (JSC::BytecodeGenerator::resolveCallee):
     130        (JSC::BytecodeGenerator::addCallee): Helper functions for either statically
     131        resolving the callee or adding a dynamic scope that will resolve to it,
     132        depending on whether you're in the fast path.
     133
     134        We move the callee into a var location if it's captured because activations
     135        prefer to have contiguous ranges of captured variables.
     136
     137        * bytecompiler/BytecodeGenerator.h:
     138        (JSC::BytecodeGenerator::registerFor):
     139        (BytecodeGenerator):
     140
     141        * dfg/DFGOperations.cpp:
     142        * interpreter/Interpreter.cpp:
     143        (JSC::Interpreter::privateExecute):
     144        * jit/JITStubs.cpp:
     145        (JSC::DEFINE_STUB_FUNCTION):
     146        * llint/LLIntSlowPaths.cpp:
     147        (JSC::LLInt::LLINT_SLOW_PATH_DECL): This is the point of the patch: remove
     148        one allocation in the case of a named function expression.
     149
     150        * parser/Parser.cpp:
     151        (JSC::::Parser):
     152        * parser/Parser.h:
     153        (JSC::Scope::declareCallee):
     154        (Scope):
     155        (Parser):
     156        (JSC::parse):
     157        * runtime/Executable.cpp:
     158        (JSC::EvalExecutable::compileInternal):
     159        (JSC::ProgramExecutable::checkSyntax):
     160        (JSC::ProgramExecutable::compileInternal):
     161        (JSC::FunctionExecutable::produceCodeBlockFor):
     162        (JSC::FunctionExecutable::fromGlobalCode): Pipe the callee's name through
     163        the parser so we get accurate information on whether the callee was captured.
     164
     165        (JSC::FunctionExecutable::FunctionExecutable):
     166        (JSC::EvalExecutable::compileInternal):
     167        (JSC::ProgramExecutable::checkSyntax):
     168        (JSC::ProgramExecutable::compileInternal):
     169        (JSC::FunctionExecutable::produceCodeBlockFor):
     170        (JSC::FunctionExecutable::fromGlobalCode):
     171        * runtime/Executable.h:
     172        (JSC::FunctionExecutable::create):
     173        (FunctionExecutable):
     174        (JSC::FunctionExecutable::finishCreation): I had to refactor function
     175        creation to support the following function constructor quirk: the function
     176        gets a name, but its name is not in lexical scope.
     177
     178        To simplify this, FunctionExecutable now automatically extracts all the
     179        data it needs from the parsed node. The special "fromGlobalCode" path
     180        used by the function constructor creates an anonymous function, and then
     181        quirkily sets the value used by the .name property to be non-null, even
     182        though the parsed name is null.
     183
     184        * runtime/JSNameScope.h:
     185        (JSC::JSNameScope::create):
     186        (JSC::JSNameScope::JSNameScope): Added support for explicitly specifying
     187        your container scope. The compiler uses this for named function expressions.
    84188
    851892012-09-05  Gavin Barraclough  <barraclough@apple.com>
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r127774 r127810  
    17531753    , m_numCalleeRegisters(0)
    17541754    , m_numVars(0)
     1755    , m_numCapturedVars(0)
    17551756    , m_isConstructor(isConstructor)
    17561757    , m_numParameters(0)
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r127774 r127810  
    3434#include "BatchedTransitionOptimizer.h"
    3535#include "Comment.h"
     36#include "Interpreter.h"
    3637#include "JSActivation.h"
    3738#include "JSFunction.h"
    38 #include "Interpreter.h"
     39#include "JSNameScope.h"
    3940#include "LowLevelInterpreter.h"
    40 
    4141#include "StrongInlines.h"
    4242#include <wtf/text/WTFString.h>
     
    325325            globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
    326326       
    327         JSValue value = JSFunction::create(exec, makeFunction(exec, function), scope);
     327        JSValue value = JSFunction::create(exec, FunctionExecutable::create(*m_globalData, function), scope);
    328328        int index = addGlobalVar(
    329329            function->ident(), IsVariable,
     
    420420    }
    421421
     422    RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
     423
    422424    const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
    423425    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
     
    457459
    458460    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     461
    459462    m_firstLazyFunction = codeBlock->m_numVars;
    460463    for (size_t i = 0; i < functionStack.size(); ++i) {
     
    497500
    498501    preserveLastVar();
     502
     503    // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.
     504    addCallee(functionBody, calleeRegister);
    499505
    500506    if (isConstructor()) {
     
    550556    const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
    551557    for (size_t i = 0; i < functionStack.size(); ++i)
    552         m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
     558        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i]));
    553559
    554560    const DeclarationStacks::VarStack& varStack = evalNode->varStack();
     
    573579    instructions().append(reg->index());
    574580    return reg;
     581}
     582
     583RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
     584{
     585    if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
     586        return 0;
     587
     588    m_calleeRegister.setIndex(RegisterFile::Callee);
     589
     590    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
     591    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
     592        emitOpcode(op_push_name_scope);
     593        instructions().append(addConstant(functionBodyNode->ident()));
     594        instructions().append(m_calleeRegister.index());
     595        instructions().append(ReadOnly | DontDelete);
     596
     597        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
     598        m_scope.set(*globalData(),
     599            JSNameScope::create(
     600                m_scope->globalObject()->globalExec(),
     601                functionBodyNode->ident(),
     602                jsUndefined(),
     603                ReadOnly | DontDelete,
     604                m_scope.get()
     605            )
     606        );
     607        return 0;
     608    }
     609
     610    if (!functionBodyNode->captures(functionBodyNode->ident()))
     611        return &m_calleeRegister;
     612
     613    // Move the callee into the captured section of the stack.
     614    return emitMove(addVar(), &m_calleeRegister);
     615}
     616
     617void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
     618{
     619    if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
     620        return;
     621
     622    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
     623    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
     624        return;
     625
     626    ASSERT(calleeRegister);
     627    symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly));
    575628}
    576629
     
    18311884RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
    18321885{
    1833     return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)), false);
     1886    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function)), false);
    18341887}
    18351888
     
    18381891    FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0);
    18391892    if (ptr.isNewEntry)
    1840         ptr.iterator->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
     1893        ptr.iterator->second = m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, function));
    18411894    return emitNewFunctionInternal(dst, ptr.iterator->second, true);
    18421895}
     
    18631916{
    18641917    FunctionBodyNode* function = n->body();
    1865     unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
     1918    unsigned index = m_codeBlock->addFunctionExpr(FunctionExecutable::create(*m_globalData, function));
    18661919   
    18671920    createActivationIfNecessary();
     
    26002653        return;
    26012654
    2602     RefPtr<RegisterID> error = emitLoad(newTemporary(), createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError));
     2655    RefPtr<RegisterID> error = emitLoad(newTemporary(), JSValue(createTypeError(scope()->globalObject()->globalExec(), StrictModeReadonlyPropertyWriteError)));
    26032656    emitThrow(error.get());
    26042657}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r127774 r127810  
    618618
    619619        void addParameter(const Identifier&, int parameterIndex);
    620        
     620        RegisterID* resolveCallee(FunctionBodyNode*);
     621        void addCallee(FunctionBodyNode*, RegisterID*);
     622
    621623        void preserveLastVar();
    622624        bool shouldAvoidResolveGlobal();
     
    626628            if (index >= 0)
    627629                return m_calleeRegisters[index];
     630
     631            if (index == RegisterFile::Callee)
     632                return m_calleeRegister;
    628633
    629634            ASSERT(m_parameters.size());
     
    637642        unsigned addConstantBuffer(unsigned length);
    638643       
    639         FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
    640         {
    641             return FunctionExecutable::create(exec, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
    642         }
    643 
    644         FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
    645         {
    646             return FunctionExecutable::create(*globalData, body->ident(), body->inferredName(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
    647         }
    648 
    649644        JSString* addStringConstant(const Identifier&);
    650645
     
    717712        RegisterID m_ignoredResultRegister;
    718713        RegisterID m_thisRegister;
     714        RegisterID m_calleeRegister;
    719715        RegisterID* m_activationRegister;
    720716        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r127774 r127810  
    12441244    JSGlobalData& globalData = exec->globalData();
    12451245    NativeCallFrameTracer tracer(&globalData, exec);
    1246     return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scope());
     1246    return JSFunction::create(exec, static_cast<FunctionExecutable*>(functionExecutable), exec->scope());
    12471247}
    12481248
     
    12521252    FunctionExecutable* functionExecutable =
    12531253        static_cast<FunctionExecutable*>(functionExecutableAsCell);
    1254     JSFunction* function = functionExecutable->make(exec, exec->scope());
    1255     if (!functionExecutable->name().isNull()) {
    1256         JSNameScope* functionScopeObject =
    1257             JSNameScope::create(
    1258                 exec, functionExecutable->name(), function, ReadOnly | DontDelete);
    1259         function->setScope(exec->globalData(), functionScopeObject);
    1260     }
    1261     return function;
     1254    return JSFunction::create(exec, functionExecutable, exec->scope());
    12621255}
    12631256
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r127774 r127810  
    13481348            FunctionExecutable* function = codeBlock->functionDecl(i);
    13491349            PutPropertySlot slot;
    1350             variableObject->methodTable()->put(variableObject, callFrame, function->name(), function->make(callFrame, scope), slot);
     1350            variableObject->methodTable()->put(variableObject, callFrame, function->name(), JSFunction::create(callFrame, function, scope), slot);
    13511351        }
    13521352    }
     
    42804280        JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
    42814281
    4282         /*
    4283             The Identifier in a FunctionExpression can be referenced from inside
    4284             the FunctionExpression's FunctionBody to allow the function to call
    4285             itself recursively. However, unlike in a FunctionDeclaration, the
    4286             Identifier in a FunctionExpression cannot be referenced from and
    4287             does not affect the scope enclosing the FunctionExpression.
    4288          */
    4289         if (!function->name().isNull()) {
    4290             JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);
    4291             func->setScope(*globalData, functionScopeObject);
    4292         }
    4293 
    42944282        callFrame->uncheckedR(dst) = JSValue(func);
    42954283
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r127774 r127810  
    21422142   
    21432143    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
    2144     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scope());
     2144    return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
    21452145}
    21462146
     
    29832983
    29842984    FunctionExecutable* function = stackFrame.args[0].function();
    2985     JSFunction* func = function->make(callFrame, callFrame->scope());
     2985    JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
    29862986    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
    2987 
    2988     /*
    2989         The Identifier in a FunctionExpression can be referenced from inside
    2990         the FunctionExpression's FunctionBody to allow the function to call
    2991         itself recursively. However, unlike in a FunctionDeclaration, the
    2992         Identifier in a FunctionExpression cannot be referenced from and
    2993         does not affect the scope enclosing the FunctionExpression.
    2994      */
    2995     if (!function->name().isNull()) {
    2996         JSNameScope* functionScopeObject = JSNameScope::create(callFrame, function->name(), func, ReadOnly | DontDelete);
    2997         func->setScope(callFrame->globalData(), functionScopeObject);
    2998     }
    29992987
    30002988    return func;
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r127774 r127810  
    12611261    dataLog("Creating function!\n");
    12621262#endif
    1263     LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scope()));
     1263    LLINT_RETURN(JSFunction::create(exec, codeBlock->functionDecl(pc[2].u.operand), exec->scope()));
    12641264}
    12651265
     
    12691269    CodeBlock* codeBlock = exec->codeBlock();
    12701270    FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
    1271     JSFunction* func = function->make(exec, exec->scope());
    1272    
    1273     if (!function->name().isNull()) {
    1274         JSNameScope* functionScopeObject = JSNameScope::create(exec, function->name(), func, ReadOnly | DontDelete);
    1275         func->setScope(globalData, functionScopeObject);
    1276     }
     1271    JSFunction* func = JSFunction::create(exec, function, exec->scope());
    12771272   
    12781273    LLINT_RETURN(func);
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r127654 r127810  
    750750        , m_body(body)
    751751    {
    752         m_body->finishParsing(source, parameter, ident);
     752        m_body->finishParsing(source, parameter, ident, FunctionNameIsInScope);
    753753    }
    754754
     
    757757        , m_body(body)
    758758    {
    759         m_body->finishParsing(source, parameter, ident);
     759        m_body->finishParsing(source, parameter, ident, FunctionNameIsNotInScope);
    760760    }
    761761
  • trunk/Source/JavaScriptCore/parser/Nodes.cpp

    r126893 r127810  
    168168}
    169169
    170 void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
     170void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle)
    171171{
    172172    setSource(source);
    173     finishParsing(FunctionParameters::create(firstParameter), ident);
    174 }
    175 
    176 void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident)
     173    finishParsing(FunctionParameters::create(firstParameter), ident, functionNameIsInScopeToggle);
     174}
     175
     176void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident, FunctionNameIsInScopeToggle functionNameIsInScopeToggle)
    177177{
    178178    ASSERT(!source().isNull());
    179179    m_parameters = parameters;
    180180    m_ident = ident;
     181    m_functionNameIsInScopeToggle = functionNameIsInScopeToggle;
    181182}
    182183
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r127666 r127810  
    14041404    };
    14051405
     1406    enum FunctionNameIsInScopeToggle { FunctionNameIsNotInScope, FunctionNameIsInScope };
    14061407    class FunctionBodyNode : public ScopeNode {
    14071408    public:
     
    14151416        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
    14161417
    1417         void finishParsing(const SourceCode&, ParameterNode*, const Identifier&);
    1418         void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&);
     1418        void finishParsing(const SourceCode&, ParameterNode*, const Identifier&, FunctionNameIsInScopeToggle);
     1419        void finishParsing(PassRefPtr<FunctionParameters>, const Identifier&, FunctionNameIsInScopeToggle);
    14191420       
    14201421        const Identifier& ident() { return m_ident; }
     
    14221423        const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; }
    14231424
     1425        bool functionNameIsInScope() { return m_functionNameIsInScopeToggle == FunctionNameIsInScope; }
     1426        FunctionNameIsInScopeToggle functionNameIsInScopeToggle() { return m_functionNameIsInScopeToggle; }
     1427
    14241428        static const bool scopeIsFunction = true;
    14251429
     
    14301434        Identifier m_ident;
    14311435        Identifier m_inferredName;
     1436        FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
    14321437        RefPtr<FunctionParameters> m_parameters;
    14331438    };
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r127774 r127810  
    4141
    4242template <typename LexerType>
    43 Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode)
     43Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode)
    4444    : m_globalData(globalData)
    4545    , m_source(&source)
     
    7272            scope->declareParameter(&parameters->at(i));
    7373    }
     74    if (!name.isNull())
     75        scope->declareCallee(&name);
    7476    next();
    7577    m_lexer->setLastLineNumber(tokenLine());
  • trunk/Source/JavaScriptCore/parser/Parser.h

    r127774 r127810  
    209209    bool isFunctionBoundary() { return m_isFunctionBoundary; }
    210210
     211    void declareCallee(const Identifier* ident)
     212    {
     213        m_declaredVariables.add(ident->ustring().impl());
     214    }
     215
    211216    bool declareVariable(const Identifier* ident)
    212217    {
     
    383388
    384389public:
    385     Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, JSParserStrictness, JSParserMode);
     390    Parser(JSGlobalData*, const SourceCode&, FunctionParameters*, const Identifier&, JSParserStrictness, JSParserMode);
    386391    ~Parser();
    387392
     
    10211026
    10221027template <class ParsedNode>
    1023 PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
     1028PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, Debugger* debugger, ExecState* execState, JSObject** exception)
    10241029{
    10251030    SamplingRegion samplingRegion("Parsing");
     
    10281033
    10291034    if (source.provider()->data()->is8Bit()) {
    1030         Parser< Lexer<LChar> > parser(globalData, source, parameters, strictness, parserMode);
     1035        Parser< Lexer<LChar> > parser(globalData, source, parameters, name, strictness, parserMode);
    10311036        return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
    10321037    }
    1033     Parser< Lexer<UChar> > parser(globalData, source, parameters, strictness, parserMode);
     1038    Parser< Lexer<UChar> > parser(globalData, source, parameters, name, strictness, parserMode);
    10341039    return parser.parse<ParsedNode>(lexicalGlobalObject, debugger, execState, exception);
    10351040}
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r127774 r127810  
    134134const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
    135135
    136 FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
    137     : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext)
     136FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node)
     137    : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode())
    138138    , m_numCapturedVariables(0)
    139     , m_forceUsesArguments(forceUsesArguments)
    140     , m_parameters(parameters)
    141     , m_name(name)
    142     , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
    143 {
    144 }
    145 
    146 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext)
    147     : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
    148     , m_numCapturedVariables(0)
    149     , m_forceUsesArguments(forceUsesArguments)
    150     , m_parameters(parameters)
    151     , m_name(name)
    152     , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
    153 {
     139    , m_forceUsesArguments(node->usesArguments())
     140    , m_parameters(node->parameters())
     141    , m_name(node->ident())
     142    , m_inferredName(node->inferredName().isNull() ? globalData.propertyNames->emptyIdentifier : node->inferredName())
     143    , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
     144{
     145    m_firstLine = node->lineNo();
     146    m_lastLine = node->lastLine();
    154147}
    155148
     
    211204        if (!lexicalGlobalObject->evalEnabled())
    212205            return throwError(exec, createEvalError(exec, ASCIILiteral("Eval is disabled")));
    213         RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
     206        RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
    214207        if (!evalNode) {
    215208            ASSERT(exception);
     
    294287    JSGlobalData* globalData = &exec->globalData();
    295288    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    296     RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
     289    RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
    297290    if (programNode)
    298291        return 0;
     
    336329        m_programCodeBlock = newCodeBlock.release();
    337330    } else {
    338         RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
     331        RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
    339332        if (!programNode) {
    340333            ASSERT(exception);
     
    479472    JSGlobalData* globalData = scope->globalData();
    480473    JSGlobalObject* globalObject = scope->globalObject();
    481     RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(globalData, globalObject, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, 0, 0, &exception);
     474    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(
     475        globalData,
     476        globalObject,
     477        m_source,
     478        m_parameters.get(),
     479        name(),
     480        isStrictMode() ? JSParseStrict : JSParseNormal,
     481        FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode,
     482        0,
     483        0,
     484        &exception
     485    );
    482486
    483487    if (!body) {
     
    487491    if (m_forceUsesArguments)
    488492        body->setUsesArguments();
    489     body->finishParsing(m_parameters, m_name);
     493    body->finishParsing(m_parameters, m_name, m_functionNameIsInScopeToggle);
    490494    recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
    491495
     
    648652}
    649653
    650 FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
     654FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
    651655{
    652656    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    653     RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
     657    RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
    654658    if (!program) {
    655659        ASSERT(*exception);
     
    657661    }
    658662
    659     // Uses of this function that would not result in a single function expression are invalid.
     663    // This function assumes an input string that would result in a single anonymous function expression.
    660664    StatementNode* exprStatement = program->singleStatement();
    661665    ASSERT(exprStatement);
     
    666670    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
    667671    ASSERT(body);
    668 
    669     return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
     672    ASSERT(body->ident().isNull());
     673
     674    FunctionExecutable* functionExecutable = FunctionExecutable::create(exec->globalData(), body);
     675    functionExecutable->m_nameValue.set(exec->globalData(), functionExecutable, jsString(&exec->globalData(), name.ustring()));
     676    return functionExecutable;
    670677}
    671678
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r127774 r127810  
    540540        typedef ScriptExecutable Base;
    541541
    542         static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
    543         {
    544             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
    545             executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
     542        static FunctionExecutable* create(JSGlobalData& globalData, FunctionBodyNode* node)
     543        {
     544            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, node);
     545            executable->finishCreation(globalData);
    546546            return executable;
    547547        }
    548 
    549         static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
    550         {
    551             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
    552             executable->finishCreation(globalData, name, firstLine, lastLine);
    553             return executable;
    554         }
     548        static FunctionExecutable* fromGlobalCode(const Identifier& name, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
    555549
    556550        static void destroy(JSCell*);
    557551
    558         JSFunction* make(ExecState* exec, JSScope* scope)
    559         {
    560             return JSFunction::create(exec, this, scope);
    561         }
    562        
    563552        // Returns either call or construct bytecode. This can be appropriate
    564553        // for answering questions that that don't vary between call and construct --
     
    709698        void clearCodeIfNotCompiling();
    710699        static void visitChildren(JSCell*, SlotVisitor&);
    711         static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
    712700        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
    713701        {
     
    722710
    723711    protected:
    724         void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
     712        void finishCreation(JSGlobalData& globalData)
    725713        {
    726714            Base::finishCreation(globalData);
    727             m_firstLine = firstLine;
    728             m_lastLine = lastLine;
    729             m_nameValue.set(globalData, this, jsString(&globalData, name.ustring()));
     715            m_nameValue.set(globalData, this, jsString(&globalData, name().ustring()));
    730716        }
    731717
    732718    private:
    733         FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
    734         FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool);
     719        FunctionExecutable(JSGlobalData&, FunctionBodyNode*);
    735720
    736721        JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
     
    765750        Identifier m_name;
    766751        Identifier m_inferredName;
     752        FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
    767753        WriteBarrier<JSString> m_nameValue;
    768754        WriteBarrier<SharedSymbolTable> m_symbolTable;
  • trunk/Source/JavaScriptCore/runtime/JSNameScope.h

    r127774 r127810  
    3939    static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes)
    4040    {
    41         JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec);
     41        JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, exec->scope());
     42        scopeObject->finishCreation(exec, identifier, value, attributes);
     43        return scopeObject;
     44    }
     45
     46    static JSNameScope* create(ExecState* exec, const Identifier& identifier, JSValue value, unsigned attributes, JSScope* next)
     47    {
     48        JSNameScope* scopeObject = new (NotNull, allocateCell<JSNameScope>(*exec->heap())) JSNameScope(exec, next);
    4249        scopeObject->finishCreation(exec, identifier, value, attributes);
    4350        return scopeObject;
     
    6572
    6673private:
    67     JSNameScope(ExecState* exec)
     74    JSNameScope(ExecState* exec, JSScope* next)
    6875        : Base(
    6976            exec->globalData(),
    7077            exec->lexicalGlobalObject()->nameScopeStructure(),
    7178            reinterpret_cast<Register*>(&m_registerStore + 1),
    72             exec->scope()
     79            next
    7380        )
    7481    {
Note: See TracChangeset for help on using the changeset viewer.