Changeset 36317 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Sep 10, 2008, 2:23:35 AM (17 years ago)
Author:
[email protected]
Message:

Add optimised access to known properties on the global object.

Reviewed by Maciej Stachowiak

Improve cross scope access to the global object by emitting
code to access it directly rather than by walking the scope chain.

This is a 0.8% win in SunSpider and a 1.7% win in the v8 benchmarks.

Location:
trunk/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r36316 r36317  
     12008-09-09  Oliver Hunt  <[email protected]>
     2
     3        Reviewed by Maciej Stachowiak.
     4
     5        Add optimised access to known properties on the global object.
     6
     7        Improve cross scope access to the global object by emitting
     8        code to access it directly rather than by walking the scope chain.
     9
     10        This is a 0.8% win in SunSpider and a 1.7% win in the v8 benchmarks.
     11
     12        * VM/CTI.cpp:
     13        (JSC::CTI::privateCompileMainPass):
     14        (JSC::CTI::emitGetVariableObjectRegister):
     15        (JSC::CTI::emitPutVariableObjectRegister):
     16        * VM/CTI.h:
     17        * VM/CodeBlock.cpp:
     18        (JSC::CodeBlock::dump):
     19        * VM/CodeGenerator.cpp:
     20        (JSC::CodeGenerator::findScopedProperty):
     21        (JSC::CodeGenerator::emitResolve):
     22        (JSC::CodeGenerator::emitGetScopedVar):
     23        (JSC::CodeGenerator::emitPutScopedVar):
     24        * VM/CodeGenerator.h:
     25        * VM/Machine.cpp:
     26        (JSC::Machine::privateExecute):
     27        * VM/Opcode.h:
     28        * kjs/nodes.cpp:
     29        (JSC::FunctionCallResolveNode::emitCode):
     30        (JSC::PostfixResolveNode::emitCode):
     31        (JSC::PrefixResolveNode::emitCode):
     32        (JSC::ReadModifyResolveNode::emitCode):
     33        (JSC::AssignResolveNode::emitCode):
     34
    1352008-09-10  Maciej Stachowiak  <[email protected]>
    236
  • trunk/JavaScriptCore/VM/CTI.cpp

    r36316 r36317  
    629629            break;
    630630        }
     631        case op_get_global_var: {
     632            JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
     633            m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
     634            emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
     635            emitPutResult(instruction[i + 1].u.operand, X86::eax);
     636            i += 4;
     637            break;
     638        }
     639        case op_put_global_var: {
     640            JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
     641            m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
     642            emitGetArg(instruction[i + 3].u.operand, X86::edx);
     643            emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
     644            i += 4;
     645            break;
     646        }
    631647        case op_get_scoped_var: {
    632648            int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
     
    637653
    638654            m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::eax, X86::eax);
    639             m_jit.movl_mr(JSVariableObject::offsetOf_d(), X86::eax, X86::eax);
    640             m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), X86::eax, X86::eax);
    641             m_jit.movl_mr((instruction[i + 2].u.operand) * sizeof(Register), X86::eax, X86::eax);
     655            emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
    642656            emitPutResult(instruction[i + 1].u.operand);
    643657            i += 4;
     
    653667
    654668            m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::edx, X86::edx);
    655             m_jit.movl_mr(JSVariableObject::offsetOf_d(), X86::edx, X86::edx);
    656             m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), X86::edx, X86::edx);
    657             m_jit.movl_rm(X86::eax, (instruction[i + 1].u.operand) * sizeof(Register), X86::edx);
     669            emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
    658670            i += 4;
    659671            break;
     
    18311843}
    18321844
     1845void CTI::emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst)
     1846{
     1847    m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, dst);
     1848    m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), dst, dst);
     1849    m_jit.movl_mr(index * sizeof(Register), dst, dst);
     1850}
     1851
     1852void CTI::emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index)
     1853{
     1854    m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, variableObject);
     1855    m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), variableObject, variableObject);
     1856    m_jit.movl_rm(src, index * sizeof(Register), variableObject);
     1857}
     1858
    18331859#if ENABLE(WREC)
    18341860
  • trunk/JavaScriptCore/VM/CTI.h

    r36316 r36317  
    330330        void emitCall(unsigned opcodeIndex, CTIHelper_v);
    331331        void emitCall(unsigned opcodeIndex, CTIHelper_s);
    332 
     332       
     333        void emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst);
     334        void emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index);
     335       
    333336        void emitSlowScriptCheck(unsigned opcodeIndex);
    334337#ifndef NDEBUG
  • trunk/JavaScriptCore/VM/CodeBlock.cpp

    r36263 r36317  
    523523            break;
    524524        }
     525        case op_get_global_var: {
     526            int r0 = (++it)->u.operand;
     527            JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);
     528            int index = (++it)->u.operand;
     529            printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
     530            break;
     531        }
     532        case op_put_global_var: {
     533            JSValue* scope = static_cast<JSValue*>((++it)->u.jsCell);
     534            int index = (++it)->u.operand;
     535            int r0 = (++it)->u.operand;
     536            printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
     537            break;
     538        }
    525539        case op_resolve_base: {
    526540            int r0 = (++it)->u.operand;
  • trunk/JavaScriptCore/VM/CodeGenerator.cpp

    r36263 r36317  
    678678}
    679679
    680 bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting)
     680bool CodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSValue*& globalObject)
    681681{
    682682    // Cases where we cannot optimise the lookup
     
    703703                stackDepth = 0;
    704704                index = missingSymbolMarker();
     705                if (++iter == end)
     706                    globalObject = currentVariableObject;
    705707                return false;
    706708            }
    707709            stackDepth = depth;
    708710            index = entry.getIndex();
     711            if (++iter == end)
     712                globalObject = currentVariableObject;
    709713            return true;
    710714        }
     
    716720    stackDepth = depth;
    717721    index = missingSymbolMarker();
     722    JSObject* scope = *iter;
     723    if (++iter == end)
     724        globalObject = scope;
    718725    return true;
    719726}
     
    723730    size_t depth = 0;
    724731    int index = 0;
    725     if (!findScopedProperty(property, index, depth, false)) {
     732    JSValue* globalObject = 0;
     733    if (!findScopedProperty(property, index, depth, false, globalObject)) {
    726734        // We can't optimise at all :-(
    727735        emitOpcode(op_resolve);
     
    742750
    743751    // Directly index the property lookup across multiple scopes.  Yay!
    744     return emitGetScopedVar(dst, depth, index);
    745 }
    746 
    747 RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index)
    748 {
     752    return emitGetScopedVar(dst, depth, index, globalObject);
     753}
     754
     755RegisterID* CodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue* globalObject)
     756{
     757    if (globalObject) {
     758        emitOpcode(op_get_global_var);
     759        instructions().append(dst->index());
     760        instructions().append(static_cast<JSCell*>(globalObject));
     761        instructions().append(index);
     762        return dst;
     763    }
     764
    749765    emitOpcode(op_get_scoped_var);
    750766    instructions().append(dst->index());
     
    754770}
    755771
    756 RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value)
    757 {
     772RegisterID* CodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue* globalObject)
     773{
     774    if (globalObject) {
     775        emitOpcode(op_put_global_var);
     776        instructions().append(static_cast<JSCell*>(globalObject));
     777        instructions().append(index);
     778        instructions().append(value->index());
     779        return value;
     780    }
    758781    emitOpcode(op_put_scoped_var);
    759782    instructions().append(index);
  • trunk/JavaScriptCore/VM/CodeGenerator.h

    r36263 r36317  
    104104        // NB: depth does _not_ include the local scope.  eg. a depth of 0 refers
    105105        // to the scope containing this codeblock.
    106         bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting);
     106        bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, JSValue*& globalObject);
    107107
    108108        // Returns the register storing "this"
     
    257257
    258258        RegisterID* emitResolve(RegisterID* dst, const Identifier& property);
    259         RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index);
    260         RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value);
     259        RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue* globalObject);
     260        RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue* globalObject);
    261261
    262262        RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
  • trunk/JavaScriptCore/VM/Machine.cpp

    r36316 r36317  
    20872087        NEXT_OPCODE;
    20882088    }
     2089    BEGIN_OPCODE(op_get_global_var) {
     2090        /* get_global_var dst(r) index(n)
     2091
     2092           Gets the global var at global slot index and places it in register dst.
     2093         */
     2094        int dst = (++vPC)->u.operand;
     2095        JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
     2096        ASSERT(scope->isGlobalObject());
     2097        int index = (++vPC)->u.operand;
     2098
     2099        r[dst] = scope->registerAt(index);
     2100        ++vPC;
     2101        NEXT_OPCODE;
     2102    }
     2103    BEGIN_OPCODE(op_put_global_var) {
     2104        /* put_global_var globalObject(c) index(n) value(r)
     2105         
     2106           Puts value into global slot index.
     2107         */
     2108        JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell);
     2109        ASSERT(scope->isGlobalObject());
     2110        int index = (++vPC)->u.operand;
     2111        int value = (++vPC)->u.operand;
     2112       
     2113        scope->registerAt(index) = r[value].jsValue(exec);
     2114        ++vPC;
     2115        NEXT_OPCODE;
     2116    }           
    20892117    BEGIN_OPCODE(op_get_scoped_var) {
    20902118        /* get_scoped_var dst(r) index(n) skip(n)
  • trunk/JavaScriptCore/VM/Opcode.h

    r36263 r36317  
    8585        macro(op_get_scoped_var) \
    8686        macro(op_put_scoped_var) \
     87        macro(op_get_global_var) \
     88        macro(op_put_global_var) \
    8789        macro(op_resolve_base) \
    8890        macro(op_resolve_with_base) \
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r36270 r36317  
    433433    int index = 0;
    434434    size_t depth = 0;
    435     if (generator.findScopedProperty(m_ident, index, depth, false) && index != missingSymbolMarker()) {
    436         RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
     435    JSValue* globalObject = 0;
     436    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
     437        RegisterID* func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
    437438        return generator.emitCall(generator.finalDestination(dst), func, 0, m_args.get(), m_divot, m_startOffset, m_endOffset);
    438439    }
     
    491492    int index = 0;
    492493    size_t depth = 0;
    493     if (generator.findScopedProperty(m_ident, index, depth, true) && index != missingSymbolMarker()) {
    494         RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index);
     494    JSValue* globalObject = 0;
     495    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
     496        RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
    495497        RegisterID* oldValue;
    496498        if (dst == ignoredResult()) {
     
    500502            oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    501503        }
    502         generator.emitPutScopedVar(depth, index, value.get());
     504        generator.emitPutScopedVar(depth, index, value.get(), globalObject);
    503505        return oldValue;
    504506    }
     
    674676    int index = 0;
    675677    size_t depth = 0;
    676     if (generator.findScopedProperty(m_ident, index, depth, false) && index != missingSymbolMarker()) {
    677         RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
     678    JSValue* globalObject = 0;
     679    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
     680        RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    678681        emitPreIncOrDec(generator, propDst.get(), m_operator);
    679         generator.emitPutScopedVar(depth, index, propDst.get());
     682        generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
    680683        return generator.moveToDestinationIfNeeded(dst, propDst.get());;
    681684    }
     
    885888    int index = 0;
    886889    size_t depth = 0;
    887     if (generator.findScopedProperty(m_ident, index, depth, true) && index != missingSymbolMarker()) {
    888         RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index);
     890    JSValue* globalObject = 0;
     891    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
     892        RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
    889893        RegisterID* src2 = generator.emitNode(m_right.get());
    890894        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), src2, m_operator);
    891         generator.emitPutScopedVar(depth, index, result);
     895        generator.emitPutScopedVar(depth, index, result, globalObject);
    892896        return result;
    893897    }
     
    916920    int index = 0;
    917921    size_t depth = 0;
    918     if (generator.findScopedProperty(m_ident, index, depth, true) && index != missingSymbolMarker()) {
     922    JSValue* globalObject = 0;
     923    if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) {
    919924        if (dst == ignoredResult())
    920925            dst = 0;
    921926        RegisterID* value = generator.emitNode(dst, m_right.get());
    922         generator.emitPutScopedVar(depth, index, value);
     927        generator.emitPutScopedVar(depth, index, value, globalObject);
    923928        return value;
    924929    }
Note: See TracChangeset for help on using the changeset viewer.