Changeset 34838 in webkit for trunk/JavaScriptCore/VM/Machine.h


Ignore:
Timestamp:
Jun 27, 2008, 3:35:33 PM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

2008-06-27 Geoffrey Garen <[email protected]>

Reviewed by Oliver Hunt.


One RegisterFile to rule them all!


SunSpider reports a 0.2% speedup.

This patch removes the RegisterFileStack abstraction and replaces it with
a single register file that


(a) allocates a fixed storage area, including a fixed area for global
vars, so that no operation may cause the register file to reallocate


and

(b) swaps between global storage areas when executing code in different
global objects.


This patch also changes the layout of the register file so that all call
frames, including call frames for global code, get a header. This is
required to support re-entrant global code. It also just makes things simpler.


  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::addGlobalVar): New function. Differs from addVar in that


(a) global vars don't contribute to a CodeBlock's numLocals count, since
global storage is fixed and allocated at startup


and


(b) references to global vars get shifted to elide intermediate stack
between "r" and the global storage area.


  • VM/Machine.cpp: (KJS::Machine::dumpRegisters): Updated this function to match the new register file layout, and added the ability to dump exact identifiers for the different parts of a call frame.


(KJS::Machine::unwindCallFrame): Updated this function to match the new
register file layout.


(KJS::Machine::execute): Updated this function to initialize a call frame
header for global code, and to swap global storage areas when switching
to execution in a new global object.


(KJS::Machine::privateExecute): Got rid of "safeForReentry" and re-reading
of registerBase because the register file is always safe for reentry now,
and registerBase never changes.


  • VM/Machine.h: Moved the call frame header enum from Machine to RegisterFile, to resolve a header dependency problem (a good sign that the enum belonged in RegisterFile all along!)
  • VM/RegisterFile.cpp:
  • VM/RegisterFile.h: Changed RegisterFile to mmap a fixed size register area. This allows us to avoid re-allocting the register file later on. Instead, we rely on the OS to allocate physical pages to the register file as necessary.
  • VM/RegisterFileStack.cpp: Removed. Tada!
  • VM/RegisterFileStack.h: Removed. Tada!
  • kjs/DebuggerCallFrame.cpp: Updated this class to match the new register file layout, greatly simplifying it in the process.
  • kjs/JSActivation.h:
  • kjs/JSActivation.cpp: Moved some of this logic up to JSVariableObject, since the global object now needs to be able to tear off its registers just like the activation object.
  • kjs/JSFunction.cpp: No need to fiddle with the register file anymore.
  • kjs/JSGlobalObject.h:
  • kjs/JSGlobalObject.cpp: Updated JSGlobalObject to support moving its global storage area into and out of the register file.
  • kjs/PropertySlot.cpp: No need to fiddle with the register file anymore.
  • kjs/collector.cpp: Renamed markStackObjectConservatively to markConservatively, since we don't just mark stack objects this way.


Also, added code to mark the machine's register file.

  • kjs/config.h: Moved some platforms #defines from here...
  • wtf/Platform.h: ...to here, to support mmap/VirtualAlloc detection in RegisterFile.h.

LayoutTests:

2008-06-26 Geoffrey Garen <[email protected]>

Reviewed by Oliver Hunt.


Added a test for what happens when a script exceeds the limit on declared
global variables.

  • fast/js/global-var-limit-expected.txt: Added.
  • fast/js/global-var-limit.html: Added.
  • fast/js/global-recursion-on-full-stack-expected.txt: Updated for new (slightly more correct) behavior. Since the stack overflow happens in the middle of a try/catch block, it should be caught, instead of logged to the console.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/Machine.h

    r34781 r34838  
    3131
    3232#include "Opcode.h"
    33 #include "RegisterFileStack.h"
     33#include "RegisterFile.h"
    3434#include <kjs/list.h>
    3535#include <wtf/HashMap.h>
     
    4141    class ExecState;
    4242    class FunctionBodyNode;
     43    class Instruction;
     44    class JSFunction;
    4345    class ProgramNode;
    4446    class Register;
    4547    class RegisterFile;
    46     class RegisterFileStack;
    4748    class ScopeChainNode;
    4849
     
    6061    class Machine {
    6162    public:
    62         enum {
    63             CallerCodeBlock = 0,
    64             ReturnVPC,
    65             CallerScopeChain,
    66             CallerRegisterOffset,
    67             ReturnValueRegister,
    68             ArgumentStartRegister,
    69             ArgumentCount,
    70             CalledAsConstructor,
    71             Callee,
    72             OptionalCalleeActivation,
    73             CallFrameHeaderSize
    74         };
    75 
    76         enum { ProgramCodeThisRegister = -1 };
    77 
    7863        Machine();
    79 
     64       
     65        RegisterFile& registerFile() { return m_registerFile; }
     66       
    8067        Opcode getOpcode(OpcodeID id)
    8168        {
     
    9885
    9986        bool isOpcode(Opcode opcode);
    100 
    101         JSValue* execute(ProgramNode*, ExecState*, ScopeChainNode*, JSObject* thisObj, RegisterFileStack*, JSValue** exception);
    102         JSValue* execute(FunctionBodyNode*, ExecState*, JSFunction*, JSObject* thisObj, const ArgList& args, RegisterFileStack*, ScopeChainNode*, JSValue** exception);
    103         JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, RegisterFile*, int registerOffset, ScopeChainNode*, JSValue** exception);
    104         JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, RegisterFileStack*, ScopeChainNode*, JSValue** exception);
     87       
     88        JSValue* execute(ProgramNode*, ExecState*, ScopeChainNode*, JSObject* thisObj, JSValue** exception);
     89        JSValue* execute(FunctionBodyNode*, ExecState*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue** exception);
     90        JSValue* execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue** exception)
     91        {
     92            return execute(evalNode, exec, thisObj, m_registerFile.size(), scopeChain, exception);
     93        }
    10594
    10695        JSValue* retrieveArguments(ExecState*, JSFunction*) const;
     
    10998        void getFunctionAndArguments(Register** registerBase, Register* callFrame, JSFunction*&, Register*& argv, int& argc);
    11099
     100        void mark(Heap* heap) { m_registerFile.mark(heap); }
     101
    111102    private:
    112103        enum ExecutionFlag { Normal, InitializeAndReturn };
     104
     105        friend NEVER_INLINE JSValue* callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile*, Register* r, int argv, int argc, JSValue*& exceptionValue);
     106        JSValue* execute(EvalNode*, ExecState*, JSObject* thisObj, int registerOffset, ScopeChainNode*, JSValue** exception);
    113107
    114108        ALWAYS_INLINE void setScopeChain(ExecState* exec, ScopeChainNode*&, ScopeChainNode*);
     
    125119        void dumpRegisters(const CodeBlock*, RegisterFile*, const Register*);
    126120
    127         bool isGlobalCallFrame(Register** registerBase, const Register* r) const { return (*registerBase) == r; }
     121        int m_reentryDepth;
     122        RegisterFile m_registerFile;
    128123
    129         int m_reentryDepth;
    130124#if HAVE(COMPUTED_GOTO)
    131125        Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
Note: See TracChangeset for help on using the changeset viewer.