Changeset 45609 in webkit for trunk/JavaScriptCore/bytecompiler


Ignore:
Timestamp:
Jul 7, 2009, 2:52:07 PM (16 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

Stop loading constants into the register file.

Instead, use high register values (highest bit bar the sign bit set) to indicate
constants in the instruction stream, and when we encounter such a value load it
directly from the CodeBlock.

Since constants are no longer copied into the register file, this patch renders
the 'unexpected constant' mechanism redundant, and removes it.

2% improvement, thanks to Sam Weinig.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::mark): (JSC::CodeBlock::shrinkToFit):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isTemporaryRegisterIndex): (JSC::CodeBlock::constantRegister): (JSC::CodeBlock::isConstantRegisterIndex): (JSC::CodeBlock::getConstant): (JSC::ExecState::r):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::preserveLastVar): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::addConstantValue): (JSC::BytecodeGenerator::emitEqualityOp): (JSC::BytecodeGenerator::emitLoad): (JSC::BytecodeGenerator::emitResolveBase): (JSC::BytecodeGenerator::emitResolveWithBase): (JSC::BytecodeGenerator::emitNewError):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNode):
  • interpreter/CallFrame.h: (JSC::ExecState::noCaller): (JSC::ExecState::hasHostCallFrameFlag): (JSC::ExecState::addHostCallFrameFlag): (JSC::ExecState::removeHostCallFrameFlag):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolve): (JSC::Interpreter::resolveSkip): (JSC::Interpreter::resolveGlobal): (JSC::Interpreter::resolveBase): (JSC::Interpreter::resolveBaseAndProperty): (JSC::Interpreter::resolveBaseAndFunc): (JSC::Interpreter::dumpRegisters): (JSC::Interpreter::throwException): (JSC::Interpreter::createExceptionScope): (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveArguments):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITInlineMethods.h: (JSC::JIT::emitLoadDouble): (JSC::JIT::emitLoadInt32ToDouble):
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_new_error): (JSC::JIT::emit_op_enter): (JSC::JIT::emit_op_enter_with_activation):
  • parser/Nodes.cpp: (JSC::DeleteResolveNode::emitBytecode): (JSC::DeleteValueNode::emitBytecode): (JSC::PrefixResolveNode::emitBytecode):
  • runtime/JSActivation.cpp: (JSC::JSActivation::JSActivation):
  • wtf/Platform.h:

LayoutTests:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

fast/js/global-recursion-on-full-stack.html is a little finicky.

The test recurses down the JS stack to find the bottom (catching this with an exception),
then tries to call a host function (document.write), switch writes new '<script>' code,
and expects this code to be run, then expects this code to try to call 'f();' again,
which it expects to fail, and it expects to catch that exception. However it is possible
that one of the earlier stages (the call to document.write, entering the interpreter to
run the new global code) will fail, depending on exactly how much stack space was free at
the point the last call to f() failed.

Tweak the test to make it work.

  • fast/js/global-recursion-on-full-stack.html:
Location:
trunk/JavaScriptCore/bytecompiler
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r44711 r45609  
    197197}
    198198
    199 void BytecodeGenerator::allocateConstants(size_t count)
    200 {
    201     m_codeBlock->m_numConstants = count;
    202     if (!count)
    203         return;
    204    
    205     m_nextConstantIndex = m_calleeRegisters.size();
    206 
    207     for (size_t i = 0; i < count; ++i)
    208         newRegister();
    209     m_lastConstant = &m_calleeRegisters.last();
     199void BytecodeGenerator::preserveLastVar()
     200{
     201    if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
     202        m_lastVar = &m_calleeRegisters.last();
    210203}
    211204
     
    223216    , m_codeType(GlobalCode)
    224217    , m_nextGlobalIndex(-1)
     218    , m_nextConstantOffset(0)
    225219    , m_globalConstantIndex(0)
    226220    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     
    273267                newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
    274268
    275         allocateConstants(programNode->neededConstants());
     269        preserveLastVar();
    276270
    277271        for (size_t i = 0; i < newVars.size(); ++i)
     
    291285        }
    292286
    293         allocateConstants(programNode->neededConstants());
     287        preserveLastVar();
    294288    }
    295289}
     
    306300    , m_baseScopeDepth(0)
    307301    , m_codeType(FunctionCode)
     302    , m_nextConstantOffset(0)
    308303    , m_globalConstantIndex(0)
    309304    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     
    373368        addParameter(parameters[i]);
    374369
    375     allocateConstants(functionBody->neededConstants());
     370    preserveLastVar();
    376371}
    377372
     
    388383    , m_baseScopeDepth(codeBlock->baseScopeDepth())
    389384    , m_codeType(EvalCode)
     385    , m_nextConstantOffset(0)
    390386    , m_globalConstantIndex(0)
    391387    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     
    402398    m_codeBlock->m_numParameters = 1; // Allocate space for "this"
    403399
    404     allocateConstants(evalNode->neededConstants());
     400    preserveLastVar();
    405401}
    406402
     
    792788}
    793789
    794 RegisterID* BytecodeGenerator::addConstant(JSValue v)
    795 {
    796     pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantIndex);
     790RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
     791{
     792    int index = m_nextConstantOffset;
     793
     794    pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
    797795    if (result.second) {
    798         RegisterID& constant = m_calleeRegisters[m_nextConstantIndex];
    799        
    800         ++m_nextConstantIndex;
    801 
     796        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
     797        ++m_nextConstantOffset;
    802798        m_codeBlock->addConstantRegister(JSValue(v));
    803         return &constant;
    804     }
    805 
    806     return &registerFor(result.first->second);
    807 }
    808 
    809 unsigned BytecodeGenerator::addUnexpectedConstant(JSValue v)
    810 {
    811     return m_codeBlock->addUnexpectedConstant(v);
    812 }
    813 
    814 RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject)
    815 {
    816     if (!m_globalConstantIndex)
    817         m_globalConstantIndex = m_codeBlock->addUnexpectedConstant(globalObject);
    818     emitOpcode(op_unexpected_load);
    819     instructions().append(dst->index());
    820     instructions().append(m_globalConstantIndex);
    821     return dst;
     799    } else
     800        index = result.first->second;
     801
     802    return &m_constantPoolRegisters[index];
    822803}
    823804
     
    899880            && src1->isTemporary()
    900881            && m_codeBlock->isConstantRegisterIndex(src2->index())
    901             && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue().isString()) {
    902             const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue())->value();
     882            && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
     883            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->value();
    903884            if (value == "undefined") {
    904885                rewindUnaryOp();
     
    980961RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
    981962{
    982     RegisterID* constantID = addConstant(v);
     963    RegisterID* constantID = addConstantValue(v);
    983964    if (dst)
    984965        return emitMove(dst, constantID);
    985966    return constantID;
    986 }
    987 
    988 RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
    989 {
    990     emitOpcode(op_unexpected_load);
    991     instructions().append(dst->index());
    992     instructions().append(addUnexpectedConstant(jsBoolean(b)));
    993     return dst;
    994 }
    995 
    996 RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
    997 {
    998     emitOpcode(op_unexpected_load);
    999     instructions().append(dst->index());
    1000     instructions().append(addUnexpectedConstant(jsNumber(globalData(), d)));
    1001     return dst;
    1002967}
    1003968
     
    11701135
    11711136    // Global object is the base
    1172     return emitLoadGlobalObject(dst, globalObject);
     1137    return emitLoad(dst, JSValue(globalObject));
    11731138}
    11741139
     
    11971162
    11981163    // Global object is the base
    1199     emitLoadGlobalObject(baseDst, globalObject);
     1164    emitLoad(baseDst, JSValue(globalObject));
    12001165
    12011166    if (index != missingSymbolMarker() && !forceGlobalResolve) {
     
    18321797    instructions().append(dst->index());
    18331798    instructions().append(static_cast<int>(type));
    1834     instructions().append(addUnexpectedConstant(message));
     1799    instructions().append(addConstantValue(message)->index());
    18351800    return dst;
    18361801}
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r45128 r45609  
    246246        RegisterID* emitLoad(RegisterID* dst, const Identifier&);
    247247        RegisterID* emitLoad(RegisterID* dst, JSValue);
    248         RegisterID* emitUnexpectedLoad(RegisterID* dst, bool);
    249         RegisterID* emitUnexpectedLoad(RegisterID* dst, double);
    250         RegisterID* emitLoadGlobalObject(RegisterID* dst, JSObject* globalObject);
    251248
    252249        RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
     
    400397        RegisterID* addParameter(const Identifier&);
    401398       
    402         void allocateConstants(size_t);
     399        void preserveLastVar();
    403400
    404401        RegisterID& registerFor(int index)
     
    421418        unsigned addConstant(FuncExprNode*);
    422419        unsigned addConstant(const Identifier&);
    423         RegisterID* addConstant(JSValue);
    424         unsigned addUnexpectedConstant(JSValue);
     420        RegisterID* addConstantValue(JSValue);
    425421        unsigned addRegExp(RegExp*);
    426422
     
    451447        RegisterID m_argumentsRegister;
    452448        int m_activationRegisterIndex;
     449        WTF::SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
    453450        WTF::SegmentedVector<RegisterID, 32> m_calleeRegisters;
    454451        WTF::SegmentedVector<RegisterID, 32> m_parameters;
     
    456453        WTF::SegmentedVector<Label, 32> m_labels;
    457454        WTF::SegmentedVector<LabelScope, 8> m_labelScopes;
    458         RefPtr<RegisterID> m_lastConstant;
     455        RefPtr<RegisterID> m_lastVar;
    459456        int m_finallyDepth;
    460457        int m_dynamicScopeDepth;
     
    467464        int m_nextGlobalIndex;
    468465        int m_nextParameterIndex;
    469         int m_nextConstantIndex;
     466        int m_firstConstantIndex;
     467        int m_nextConstantOffset;
    470468        unsigned m_globalConstantIndex;
    471469
Note: See TracChangeset for help on using the changeset viewer.