Ignore:
Timestamp:
Jun 22, 2011, 1:07:37 PM (14 years ago)
Author:
[email protected]
Message:

Removed the conceit that global variables are local variables when running global code
https://bugs.webkit.org/show_bug.cgi?id=63106

Reviewed by Oliver Hunt.

Source/JavaScriptCore:

This is required for write barrier correctness.

SunSpider reports about a 0.5% regression, mostly from bitops-bitwise-and.js.
I was able to reduce the regression with a tiny peephole optimization in
the bytecompiler, but not eliminate it. I'm committing this assuming
that turning on generational GC will win back at least 0.5%.

(FWIW, the DFG JIT can easily eliminate any regression by sharing loads of
the global object's var storage. I considered doing the same kind of
optimization in the existing JIT, but it seemed like moving in the wrong
direction.)

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::addGlobalVar):
(JSC::BytecodeGenerator::BytecodeGenerator): Don't give global variables
negative indices, since they're no longer negatively offset from the
current stack frame.

Do give global variables monotonically increasing positive indices, since
that's much easier to work with.

Don't limit the number of optimizable global variables, since it's no
longer limited by the register file, since they're no longer stored in
the register file.

(JSC::BytecodeGenerator::registerFor): Global code never has any local
registers because a var in global code is actually a property of the
global object.

(JSC::BytecodeGenerator::constRegisterFor): Ditto.

(JSC::BytecodeGenerator::emitResolve): Did a tiny bit of constant
propagation and dead code elimination to speed up our compiles and
reduce WTFs / minute.

  • bytecompiler/BytecodeGenerator.h:

(JSC::BytecodeGenerator::registerFor): Removed special handling of globals.

(JSC::BytecodeGenerator::shouldOptimizeLocals): Don't optimize locals in
global code, since there are none.

(JSC::BytecodeGenerator::canOptimizeNonLocals): Do optimize non-locals
in global code (i.e., global vars), since there are some.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::callEval):
(JSC::Interpreter::Interpreter):
(JSC::Interpreter::dumpRegisters):
(JSC::Interpreter::execute):

  • interpreter/Interpreter.h: Updated for deleted / renamed code.
  • interpreter/RegisterFile.cpp:

(JSC::RegisterFile::gatherConservativeRoots):
(JSC::RegisterFile::releaseExcessCapacity): Updated for deleted / renamed
data members.

  • interpreter/RegisterFile.h:

(JSC::RegisterFile::begin):
(JSC::RegisterFile::size):
(JSC::RegisterFile::RegisterFile):
(JSC::RegisterFile::shrink): Removed all code and comments dealing with
global variables stored in the register file.

(JSC::RegisterFile::grow): Updated for same.

Also, a slight correctness fix: Test the VM commit end, and not just the
in-use end, when checking for stack overflow. In theory, it's invalid to
commit past the end of your allocation, even if you never touch that
memory. This makes the usable size of the stack slightly smaller. No test
because we don't know of any case in practice where this crashes.

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData): Updated for changes above.

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::resizeRegisters):
(JSC::JSGlobalObject::addStaticGlobals):

  • runtime/JSGlobalObject.h: Simplified globals to have monotonically

increasing indexes, always located in our external storage.

LayoutTests:

  • fast/js/recursion-limit-equal-expected.txt: Updated to reflect slightly

changed recursion limit.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r89228 r89465  
    410410        return throwError(callFrame, exceptionValue);
    411411
    412     return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
     412    return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->begin() + registerOffset, scopeChain);
    413413}
    414414
    415 Interpreter::Interpreter(JSGlobalData& globalData)
     415Interpreter::Interpreter()
    416416    : m_sampleEntryDepth(0)
    417417    , m_reentryDepth(0)
    418     , m_registerFile(globalData)
    419418{
    420419#if ENABLE(COMPUTED_GOTO_INTERPRETER)
     
    446445
    447446    CodeBlock* codeBlock = callFrame->codeBlock();
    448     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData().interpreter->registerFile();
    449447    const Register* it;
    450448    const Register* end;
    451449    JSValue v;
    452450
    453     if (codeBlock->codeType() == GlobalCode) {
    454         it = registerFile->lastGlobal();
    455         end = it + registerFile->numGlobals();
    456         while (it != end) {
    457             v = (*it).jsValue();
    458 #if USE(JSVALUE32_64)
    459             printf("[global var]               | %10p | %-16s 0x%llx \n", it, v.description(), JSValue::encode(v));
    460 #else
    461             printf("[global var]               | %10p | %-16s %p \n", it, v.description(), JSValue::encode(v));
    462 #endif
    463             ++it;
    464         }
    465         printf("-----------------------------------------------------------------------------\n");
    466     }
    467    
    468451    it = callFrame->registers() - RegisterFile::CallFrameHeaderSize - codeBlock->m_numParameters;
    469452    v = (*it).jsValue();
     
    827810        return checkedReturn(throwStackOverflowError(callFrame));
    828811
    829     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
    830     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
    831     globalObject->copyGlobalsTo(m_registerFile);
    832 
    833812    CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
    834813    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
     
    857836    if (*profiler)
    858837        (*profiler)->didExecute(callFrame, program->sourceURL(), program->lineNo());
    859 
    860     if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
    861         lastGlobalObject->copyGlobalsTo(m_registerFile);
    862838
    863839    m_registerFile.shrink(oldEnd);
     
    12051181
    12061182    Register* oldEnd = m_registerFile.end();
    1207     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
     1183    Register* newEnd = m_registerFile.begin() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
    12081184    if (!m_registerFile.grow(newEnd)) {
    12091185        if (pushedScope)
     
    12121188    }
    12131189
    1214     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
     1190    CallFrame* newCallFrame = CallFrame::create(m_registerFile.begin() + globalRegisterOffset);
    12151191
    12161192    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
Note: See TracChangeset for help on using the changeset viewer.