Changeset 31783

Show
Ignore:
Timestamp:
04/10/08 13:27:40 (2 years ago)
Author:
ggaren@apple.com
Message:

2008-04-10 Geoffrey Garen < ggaren@apple.com>

Reviewed by Oliver Hunt and Sam Weinig.


Re-entrant execution of function code (global code -> built-in function
-> JS function):


Miraculously, sunspider --squirrelfish does not seem to complain.

A re-entrant function call is the same as a normal function call with
one exception: the re-entrant call leaves everything except for
CallerCodeBlock in the call frame header uninitialized, since the call
doesn't need to return to JS code. (It sets CallerCodeBlock to 0, to
indicate that the call shouldn't return to JS code.)


Also fixed a few issues along the way:


  • Fixed two bugs in the read-write List implementation that caused m_size and m_buffer to go stale.


  • Changed native call code to update "r" *before* setting the return value, since the call may in turn call JS code, which changes the value of "r".


  • Migrated initialization of "r" outside of Machine::privateExecute, because global code and function code initialize "r" differently.


  • Migrated a codegen warning from Machine::privateExecute to the wiki.


  • Removed unnecessary "r" parameter from slideRegisterWindowForCall
  • VM/Machine.cpp: (KJS::slideRegisterWindowForCall): (KJS::scopeChainForCall): (KJS::Machine::execute): (KJS::Machine::privateExecute):
  • VM/Machine.h:
  • kjs/function.cpp: (KJS::FunctionImp::callAsFunction):
  • kjs/list.cpp: (KJS::List::getSlice):
  • kjs/list.h: (KJS::List::clear):
Location:
branches/squirrelfish/JavaScriptCore
Files:
7 modified

Legend:

Unmodified
Added
Removed
  • branches/squirrelfish/JavaScriptCore/ChangeLog

    r31774 r31783  
     12008-04-10  Geoffrey Garen  <ggaren@apple.com> 
     2 
     3        Reviewed by Oliver Hunt and Sam Weinig. 
     4         
     5        Re-entrant execution of function code (global code -> built-in function 
     6        -> JS function): 
     7         
     8        Miraculously, sunspider --squirrelfish does not seem to complain. 
     9 
     10        A re-entrant function call is the same as a normal function call with 
     11        one exception: the re-entrant call leaves everything except for 
     12        CallerCodeBlock in the call frame header uninitialized, since the call 
     13        doesn't need to return to JS code. (It sets CallerCodeBlock to 0, to 
     14        indicate that the call shouldn't return to JS code.) 
     15         
     16        Also fixed a few issues along the way: 
     17         
     18        - Fixed two bugs in the read-write List implementation that caused 
     19        m_size and m_buffer to go stale. 
     20         
     21        - Changed native call code to update "r" *before* setting the return 
     22        value, since the call may in turn call JS code, which changes the value 
     23        of "r". 
     24         
     25        - Migrated initialization of "r" outside of Machine::privateExecute, 
     26        because global code and function code initialize "r" differently. 
     27         
     28        - Migrated a codegen warning from Machine::privateExecute to the wiki. 
     29         
     30        - Removed unnecessary "r" parameter from slideRegisterWindowForCall 
     31 
     32        * VM/Machine.cpp: 
     33        (KJS::slideRegisterWindowForCall): 
     34        (KJS::scopeChainForCall): 
     35        (KJS::Machine::execute): 
     36        (KJS::Machine::privateExecute): 
     37        * VM/Machine.h: 
     38        * kjs/function.cpp: 
     39        (KJS::FunctionImp::callAsFunction): 
     40        * kjs/list.cpp: 
     41        (KJS::List::getSlice): 
     42        * kjs/list.h: 
     43        (KJS::List::clear): 
     44 
    1452008-04-10  Maciej Stachowiak  <mjs@apple.com> 
    246 
  • branches/squirrelfish/JavaScriptCore/VM/CodeBlock.h

    r31701 r31783  
    3131#define CodeBlock_h 
    3232 
     33#include "Instruction.h" 
     34#include "nodes.h" 
     35#include "ustring.h" 
    3336#include <wtf/RefPtr.h> 
    3437#include <wtf/Vector.h> 
    35 #include "nodes.h" 
    36 #include "Instruction.h" 
    37 #include "UString.h" 
    3838 
    3939namespace KJS { 
  • branches/squirrelfish/JavaScriptCore/VM/Machine.cpp

    r31773 r31783  
    296296} 
    297297 
    298 ALWAYS_INLINE Register* slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc, Register* r) 
    299 { 
     298ALWAYS_INLINE Register* slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, Register** registerBase, int registerOffset, int argv, int argc) 
     299{ 
     300    Register* r; 
    300301    registerOffset += argv + argc + newCodeBlock->numVars; 
     302 
    301303    if (argc == newCodeBlock->numParameters) { // correct number of arguments 
    302304        size_t size = registerOffset + newCodeBlock->numTemporaries; 
     
    327329} 
    328330 
    329     ALWAYS_INLINE ScopeChain* scopeChainForCall(CodeBlock* newCodeBlock, ScopeChain* callDataScopeChain, FunctionBodyNode* functionBody, Register* callFrame, Register** registerBase, Register* r) 
     331ALWAYS_INLINE ScopeChain* scopeChainForCall(CodeBlock* newCodeBlock, ScopeChain* callDataScopeChain, FunctionBodyNode* functionBody, Register* callFrame, Register** registerBase, Register* r) 
    330332{ 
    331333    ScopeChain* scopeChain; 
     
    413415    registerFile->addGlobalSlots(codeBlock->numVars); 
    414416    registerFile->grow(codeBlock->numTemporaries); 
    415  
    416     JSValue* result = privateExecute(Normal, exec, registerFile, scopeChain, codeBlock, exception); 
     417    Register* r = (*registerFile->basePointer()); 
     418 
     419    JSValue* result = privateExecute(Normal, exec, registerFile, r, scopeChain, codeBlock, exception); 
    417420 
    418421    registerFileStack->popRegisterFile(); 
     
    420423} 
    421424 
    422 JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, RegisterFileStack* registerFileStack, ScopeChain* scopeChain, JSValue** exception) 
     425JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, const List& args, JSObject* thisObj, ExecState* exec, RegisterFileStack* registerFileStack, ScopeChain* scopeChain, JSValue** exception) 
    423426{ 
    424427    RegisterFile* registerFile = registerFileStack->current(); 
    425     CodeBlock* codeBlock = &functionBodyNode->code(*scopeChain); 
    426     registerFile->grow(registerFile->size() + CallFrameHeaderSize + codeBlock->numParameters + codeBlock->numVars + codeBlock->numTemporaries); 
    427     // put return info in place 
    428     // use 0 codeBlock to indicate termination 
    429     // put args in place 
    430  
    431     return privateExecute(Normal, exec, registerFile, scopeChain, codeBlock, exception); 
    432 } 
    433  
    434 JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, ScopeChain* scopeChain, CodeBlock* codeBlock, JSValue** exception) 
     428 
     429    int argv = CallFrameHeaderSize; 
     430    int argc = args.size() + 1; // implicit "this" parameter 
     431     
     432    size_t oldSize = registerFile->size(); 
     433    registerFile->grow(oldSize + CallFrameHeaderSize + argc); 
     434     
     435    Register** registerBase = registerFile->basePointer(); 
     436    int registerOffset = oldSize; 
     437    Register* callFrame = (*registerBase) + registerOffset; 
     438     
     439    // put return info in place, using 0 codeBlock to indicate built-in caller 
     440    callFrame[CallerCodeBlock].u.codeBlock = 0; 
     441 
     442    // put args in place, including "this" 
     443    Register* dst = callFrame + CallFrameHeaderSize; 
     444    (*dst).u.jsValue = thisObj; 
     445     
     446    List::const_iterator end = args.end(); 
     447    for (List::const_iterator it = args.begin(); it != end; ++it) 
     448        (*++dst).u.jsValue = *it; 
     449 
     450    CodeBlock* newCodeBlock = &functionBodyNode->code(*scopeChain); 
     451    Register* r = slideRegisterWindowForCall(newCodeBlock, registerFile, registerBase, registerOffset, argv, argc); 
     452    scopeChain = scopeChainForCall(newCodeBlock, scopeChain, functionBodyNode, callFrame, registerBase, r);             
     453    return privateExecute(Normal, exec, registerFile, r, scopeChain, newCodeBlock, exception); 
     454} 
     455 
     456JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChain* scopeChain, CodeBlock* codeBlock, JSValue** exception) 
    435457{ 
    436458    // One-time initialization of our address tables. We have to put this code 
     
    454476     
    455477    Register** registerBase = registerFile->basePointer(); 
    456     Register* r = (*registerBase); 
    457478    Instruction* vPC = codeBlock->instructions.begin(); 
    458479    Instruction* exceptionTarget = 0; 
     
    950971 
    951972            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, r0, argv, 0); 
    952  
    953             // WARNING: If code generation wants to optimize resolves to parent scopes, 
    954             // it needs to be aware that, for functions that require activations, 
    955             // the scope chain is off by one, since the activation hasn't been pushed yet. 
    956973            CodeBlock* newCodeBlock = &callData.js.functionBody->code(*scopeChain); 
    957974 
    958             r = slideRegisterWindowForCall(newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, r); 
     975            r = slideRegisterWindowForCall(newCodeBlock, registerFile, registerBase, registerOffset, argv, argc); 
    959976            scopeChain = scopeChainForCall(newCodeBlock, callData.js.scopeChain, callData.js.functionBody, callFrame, registerBase, r);             
    960977            k = newCodeBlock->jsValues.data(); 
     
    976993            List args(&r[argv + 1].u.jsValue, argc - 1); 
    977994 
    978             r[r0].u.jsValue = static_cast<JSObject*>(v)->callAsFunction(exec, thisObj, args); 
     995            JSValue* returnValue = static_cast<JSObject*>(v)->callAsFunction(exec, thisObj, args); 
    979996 
    980997            r = (*registerBase) + registerOffset; 
    981  
     998            r[r0].u.jsValue = returnValue; 
     999             
    9821000            ++vPC; 
    9831001            NEXT_OPCODE; 
     
    10541072 
    10551073            initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, registerOffset, r0, argv, 1); 
    1056  
    1057             // WARNING: If code generation wants to optimize resolves to parent scopes, 
    1058             // it needs to be aware that, for functions that require activations, 
    1059             // the scope chain is off by one, since the activation hasn't been pushed yet. 
    10601074            CodeBlock* newCodeBlock = &callData.js.functionBody->code(*scopeChain); 
    10611075 
    1062             r = slideRegisterWindowForCall(newCodeBlock, registerFile, registerBase, registerOffset, argv, argc, r); 
     1076            r = slideRegisterWindowForCall(newCodeBlock, registerFile, registerBase, registerOffset, argv, argc); 
    10631077            scopeChain = scopeChainForCall(newCodeBlock, callData.js.scopeChain, callData.js.functionBody, callFrame, registerBase, r);             
    10641078            k = newCodeBlock->jsValues.data(); 
  • branches/squirrelfish/JavaScriptCore/VM/Machine.h

    r31773 r31783  
    7676         
    7777        JSValue* execute(ProgramNode*, ExecState*, RegisterFileStack*, ScopeChain*, JSValue** exception); 
    78         JSValue* execute(FunctionBodyNode*, ExecState*, RegisterFileStack*, ScopeChain*, JSValue** exception); 
     78        JSValue* execute(FunctionBodyNode*, const List& args, JSObject* thisObj, ExecState*, RegisterFileStack*, ScopeChain*, JSValue** exception); 
    7979         
    8080    private: 
     
    8484        NEVER_INLINE Instruction* throwException(CodeBlock*&, JSValue**&, ScopeChain*&, Register**, Register*&, const Instruction*); 
    8585 
    86         JSValue* privateExecute(ExecutionFlag, ExecState* = 0, RegisterFile* = 0, ScopeChain* = 0, CodeBlock* = 0, JSValue** exception = 0); 
     86        JSValue* privateExecute(ExecutionFlag, ExecState* = 0, RegisterFile* = 0, Register* = 0, ScopeChain* = 0, CodeBlock* = 0, JSValue** exception = 0); 
    8787 
    8888        void dumpCallFrame(const CodeBlock*, const ScopeChain*, RegisterFile*, const Register*); 
  • branches/squirrelfish/JavaScriptCore/kjs/function.cpp

    r31576 r31783  
    2929#include "Activation.h" 
    3030#include "ExecState.h" 
     31#include "ExecStateInlines.h" 
    3132#include "JSGlobalObject.h" 
     33#include "Machine.h" 
    3234#include "Parser.h" 
    3335#include "PropertyNameArray.h" 
     
    4042#include "operations.h" 
    4143#include "scope_chain_mark.h" 
    42 #include "ExecStateInlines.h" 
    4344#include <errno.h> 
    4445#include <stdio.h> 
     
    7374} 
    7475 
    75 JSValue* FunctionImp::callAsFunction(ExecState*, JSObject*, const List&) 
    76 { 
    77     ASSERT_NOT_REACHED(); 
    78     return 0; 
     76JSValue* FunctionImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args) 
     77{ 
     78    JSValue* exception; 
     79    JSValue* result = machine().execute(body.get(), args, thisObj, exec, &exec->dynamicGlobalObject()->registerFileStack(), &_scope, &exception); 
     80    if (!result) 
     81        exec->setException(exception); 
     82    return result; 
    7983} 
    8084 
  • branches/squirrelfish/JavaScriptCore/kjs/list.cpp

    r29067 r31783  
    2828void List::getSlice(int startIndex, List& result) const 
    2929{ 
     30    ASSERT(!result.m_isReadOnly); 
     31 
    3032    const_iterator start = min(begin() + startIndex, end()); 
    3133    result.m_vector.appendRange(start, end()); 
     34    result.m_size = result.m_vector.size(); 
    3235} 
    3336 
  • branches/squirrelfish/JavaScriptCore/kjs/list.h

    r31538 r31783  
    8686        { 
    8787            m_vector.clear(); 
    88             m_buffer = 0; 
    8988            m_size = 0; 
    9089        }