Ignore:
Timestamp:
Sep 6, 2012, 6:42:53 PM (13 years ago)
Author:
[email protected]
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/Source/JavaScriptCore/bytecompiler
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • 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;
Note: See TracChangeset for help on using the changeset viewer.