JavaScriptCore:

2008-10-08  Darin Adler  <darin@apple.com>

        Reviewed by Cameron Zwarich.

        - https://bugs.webkit.org/show_bug.cgi?id=21403
          Bug 21403: use new CallFrame class rather than Register* for call frame manipulation

        Add CallFrame as a synonym for ExecState. Arguably, some day we should switch every
        client over to the new name.

        Use CallFrame* consistently rather than Register* or ExecState* in low-level code such
        as Machine.cpp and CTI.cpp. Similarly, use callFrame rather than r as its name and use
        accessor functions to get at things in the frame.

        Eliminate other uses of ExecState* that aren't needed, replacing in some cases with
        JSGlobalData* and in other cases eliminating them entirely.

        * API/JSObjectRef.cpp:
        (JSObjectMakeFunctionWithCallback):
        (JSObjectMakeFunction):
        (JSObjectHasProperty):
        (JSObjectGetProperty):
        (JSObjectSetProperty):
        (JSObjectDeleteProperty):
        * API/OpaqueJSString.cpp:
        * API/OpaqueJSString.h:
        * VM/CTI.cpp:
        (JSC::CTI::getConstant):
        (JSC::CTI::emitGetArg):
        (JSC::CTI::emitGetPutArg):
        (JSC::CTI::getConstantImmediateNumericArg):
        (JSC::CTI::printOpcodeOperandTypes):
        (JSC::CTI::CTI):
        (JSC::CTI::compileOpCall):
        (JSC::CTI::compileBinaryArithOp):
        (JSC::CTI::privateCompileMainPass):
        (JSC::CTI::privateCompile):
        (JSC::CTI::privateCompileGetByIdProto):
        (JSC::CTI::privateCompileGetByIdChain):
        (JSC::CTI::compileRegExp):
        * VM/CTI.h:
        * VM/CodeBlock.h:
        * VM/CodeGenerator.cpp:
        (JSC::CodeGenerator::emitEqualityOp):
        (JSC::CodeGenerator::emitLoad):
        (JSC::CodeGenerator::emitUnexpectedLoad):
        (JSC::CodeGenerator::emitConstruct):
        * VM/CodeGenerator.h:
        * VM/Machine.cpp:
        (JSC::jsLess):
        (JSC::jsLessEq):
        (JSC::jsAddSlowCase):
        (JSC::jsAdd):
        (JSC::jsTypeStringForValue):
        (JSC::Machine::resolve):
        (JSC::Machine::resolveSkip):
        (JSC::Machine::resolveGlobal):
        (JSC::inlineResolveBase):
        (JSC::Machine::resolveBase):
        (JSC::Machine::resolveBaseAndProperty):
        (JSC::Machine::resolveBaseAndFunc):
        (JSC::Machine::slideRegisterWindowForCall):
        (JSC::isNotObject):
        (JSC::Machine::callEval):
        (JSC::Machine::dumpCallFrame):
        (JSC::Machine::dumpRegisters):
        (JSC::Machine::unwindCallFrame):
        (JSC::Machine::throwException):
        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope):
        (JSC::DynamicGlobalObjectScope::~DynamicGlobalObjectScope):
        (JSC::Machine::execute):
        (JSC::Machine::debug):
        (JSC::Machine::createExceptionScope):
        (JSC::cachePrototypeChain):
        (JSC::Machine::tryCachePutByID):
        (JSC::Machine::tryCacheGetByID):
        (JSC::Machine::privateExecute):
        (JSC::Machine::retrieveArguments):
        (JSC::Machine::retrieveCaller):
        (JSC::Machine::retrieveLastCaller):
        (JSC::Machine::findFunctionCallFrame):
        (JSC::Machine::getArgumentsData):
        (JSC::Machine::tryCTICachePutByID):
        (JSC::Machine::getCTIArrayLengthTrampoline):
        (JSC::Machine::getCTIStringLengthTrampoline):
        (JSC::Machine::tryCTICacheGetByID):
        (JSC::Machine::cti_op_convert_this):
        (JSC::Machine::cti_op_end):
        (JSC::Machine::cti_op_add):
        (JSC::Machine::cti_op_pre_inc):
        (JSC::Machine::cti_timeout_check):
        (JSC::Machine::cti_op_loop_if_less):
        (JSC::Machine::cti_op_loop_if_lesseq):
        (JSC::Machine::cti_op_new_object):
        (JSC::Machine::cti_op_put_by_id):
        (JSC::Machine::cti_op_put_by_id_second):
        (JSC::Machine::cti_op_put_by_id_generic):
        (JSC::Machine::cti_op_put_by_id_fail):
        (JSC::Machine::cti_op_get_by_id):
        (JSC::Machine::cti_op_get_by_id_second):
        (JSC::Machine::cti_op_get_by_id_generic):
        (JSC::Machine::cti_op_get_by_id_fail):
        (JSC::Machine::cti_op_instanceof):
        (JSC::Machine::cti_op_del_by_id):
        (JSC::Machine::cti_op_mul):
        (JSC::Machine::cti_op_new_func):
        (JSC::Machine::cti_op_call_JSFunction):
        (JSC::Machine::cti_vm_compile):
        (JSC::Machine::cti_op_push_activation):
        (JSC::Machine::cti_op_call_NotJSFunction):
        (JSC::Machine::cti_op_create_arguments):
        (JSC::Machine::cti_op_tear_off_activation):
        (JSC::Machine::cti_op_tear_off_arguments):
        (JSC::Machine::cti_op_ret_profiler):
        (JSC::Machine::cti_op_ret_scopeChain):
        (JSC::Machine::cti_op_new_array):
        (JSC::Machine::cti_op_resolve):
        (JSC::Machine::cti_op_construct_JSConstruct):
        (JSC::Machine::cti_op_construct_NotJSConstruct):
        (JSC::Machine::cti_op_get_by_val):
        (JSC::Machine::cti_op_resolve_func):
        (JSC::Machine::cti_op_sub):
        (JSC::Machine::cti_op_put_by_val):
        (JSC::Machine::cti_op_put_by_val_array):
        (JSC::Machine::cti_op_lesseq):
        (JSC::Machine::cti_op_loop_if_true):
        (JSC::Machine::cti_op_negate):
        (JSC::Machine::cti_op_resolve_base):
        (JSC::Machine::cti_op_resolve_skip):
        (JSC::Machine::cti_op_resolve_global):
        (JSC::Machine::cti_op_div):
        (JSC::Machine::cti_op_pre_dec):
        (JSC::Machine::cti_op_jless):
        (JSC::Machine::cti_op_not):
        (JSC::Machine::cti_op_jtrue):
        (JSC::Machine::cti_op_post_inc):
        (JSC::Machine::cti_op_eq):
        (JSC::Machine::cti_op_lshift):
        (JSC::Machine::cti_op_bitand):
        (JSC::Machine::cti_op_rshift):
        (JSC::Machine::cti_op_bitnot):
        (JSC::Machine::cti_op_resolve_with_base):
        (JSC::Machine::cti_op_new_func_exp):
        (JSC::Machine::cti_op_mod):
        (JSC::Machine::cti_op_less):
        (JSC::Machine::cti_op_neq):
        (JSC::Machine::cti_op_post_dec):
        (JSC::Machine::cti_op_urshift):
        (JSC::Machine::cti_op_bitxor):
        (JSC::Machine::cti_op_new_regexp):
        (JSC::Machine::cti_op_bitor):
        (JSC::Machine::cti_op_call_eval):
        (JSC::Machine::cti_op_throw):
        (JSC::Machine::cti_op_get_pnames):
        (JSC::Machine::cti_op_next_pname):
        (JSC::Machine::cti_op_push_scope):
        (JSC::Machine::cti_op_pop_scope):
        (JSC::Machine::cti_op_typeof):
        (JSC::Machine::cti_op_to_jsnumber):
        (JSC::Machine::cti_op_in):
        (JSC::Machine::cti_op_push_new_scope):
        (JSC::Machine::cti_op_jmp_scopes):
        (JSC::Machine::cti_op_put_by_index):
        (JSC::Machine::cti_op_switch_imm):
        (JSC::Machine::cti_op_switch_char):
        (JSC::Machine::cti_op_switch_string):
        (JSC::Machine::cti_op_del_by_val):
        (JSC::Machine::cti_op_put_getter):
        (JSC::Machine::cti_op_put_setter):
        (JSC::Machine::cti_op_new_error):
        (JSC::Machine::cti_op_debug):
        (JSC::Machine::cti_vm_throw):
        * VM/Machine.h:
        * VM/Register.h:
        * VM/RegisterFile.h:
        * kjs/Arguments.h:
        * kjs/DebuggerCallFrame.cpp:
        (JSC::DebuggerCallFrame::functionName):
        (JSC::DebuggerCallFrame::type):
        (JSC::DebuggerCallFrame::thisObject):
        (JSC::DebuggerCallFrame::evaluate):
        * kjs/DebuggerCallFrame.h:
        * kjs/ExecState.cpp:
        (JSC::CallFrame::thisValue):
        * kjs/ExecState.h:
        * kjs/FunctionConstructor.cpp:
        (JSC::constructFunction):
        * kjs/JSActivation.cpp:
        (JSC::JSActivation::JSActivation):
        (JSC::JSActivation::argumentsGetter):
        * kjs/JSActivation.h:
        * kjs/JSGlobalObject.cpp:
        (JSC::JSGlobalObject::init):
        * kjs/JSGlobalObjectFunctions.cpp:
        (JSC::globalFuncEval):
        * kjs/JSVariableObject.h:
        * kjs/Parser.cpp:
        (JSC::Parser::parse):
        * kjs/RegExpConstructor.cpp:
        (JSC::constructRegExp):
        * kjs/RegExpPrototype.cpp:
        (JSC::regExpProtoFuncCompile):
        * kjs/Shell.cpp:
        (prettyPrintScript):
        * kjs/StringPrototype.cpp:
        (JSC::stringProtoFuncMatch):
        (JSC::stringProtoFuncSearch):
        * kjs/identifier.cpp:
        (JSC::Identifier::checkSameIdentifierTable):
        * kjs/interpreter.cpp:
        (JSC::Interpreter::checkSyntax):
        (JSC::Interpreter::evaluate):
        * kjs/nodes.cpp:
        (JSC::ThrowableExpressionData::emitThrowError):
        (JSC::RegExpNode::emitCode):
        (JSC::ArrayNode::emitCode):
        (JSC::InstanceOfNode::emitCode):
        * kjs/nodes.h:
        * kjs/regexp.cpp:
        (JSC::RegExp::RegExp):
        (JSC::RegExp::create):
        * kjs/regexp.h:
        * profiler/HeavyProfile.h:
        * profiler/Profile.h:
        * wrec/WREC.cpp:
        * wrec/WREC.h:

WebKit/mac:

2008-10-08  Darin Adler  <darin@apple.com>

        Reviewed by Cameron Zwarich.

        - https://bugs.webkit.org/show_bug.cgi?id=21403
          Bug 21403: use new CallFrame class rather than Register* for call frame manipulation

        * WebView/WebScriptDebugger.mm:
        (WebScriptDebugger::WebScriptDebugger): Update since DebuggerCallFrame is simpler now.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37433 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/ExecState.h b/JavaScriptCore/kjs/ExecState.h
index 35f8ea6..50d2b95 100644
--- a/JavaScriptCore/kjs/ExecState.h
+++ b/JavaScriptCore/kjs/ExecState.h
@@ -23,60 +23,65 @@
 #ifndef ExecState_h
 #define ExecState_h
 
+// FIXME: Rename this file to CallFrame.h.
+
 #include "JSGlobalData.h"
 #include "Machine.h"
 #include "ScopeChain.h"
 
 namespace JSC  {
 
-    class ExecState;
-    class JSValue;
-    class Register;
-
-    typedef ExecState CallFrame;
+    class Arguments;
+    class JSActivation;
 
     // Represents the current state of script execution.
     // Passed as the first argument to most functions.
-    class ExecState : private Register, Noncopyable {
+    class ExecState : private Register {
     public:
-        static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
-        Register* registers() { return this; }
+        JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
+        CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
+        ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
+
+        JSValue* thisValue();
 
         // Global object in which execution began.
         JSGlobalObject* dynamicGlobalObject();
 
         // Global object in which the currently executing code was defined.
         // Differs from dynamicGlobalObject() during function calls across web browser frames.
-        JSGlobalObject* lexicalGlobalObject()
+        JSGlobalObject* lexicalGlobalObject() const
         {
-            return Machine::scopeChain(this)->globalObject();
+            return scopeChain()->globalObject();
         }
 
         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
-        // the actual DOM window.
-        JSObject* globalThisValue()
+        // the actual DOM window, which can't be "this" for security reasons.
+        JSObject* globalThisValue() const
         {
-            return Machine::scopeChain(this)->globalThisObject();
+            return scopeChain()->globalThisObject();
         }
 
-        JSGlobalData& globalData()
+        // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
+        // We should make this more uniform and either use a reference everywhere
+        // or a pointer everywhere.
+        JSGlobalData& globalData() const
         {
-            return *Machine::scopeChain(this)->globalData;
+            return *scopeChain()->globalData;
         }
 
         // Convenience functions for access to global data.
+        // It takes a few memory references to get from a call frame to the global data
+        // pointer, so these are inefficient, and should be used sparingly in new code.
+        // But they're used in many places in legacy code, so they're not going away any time soon.
 
         void setException(JSValue* exception) { globalData().exception = exception; }
         void clearException() { globalData().exception = 0; }
-        JSValue* exception() { return globalData().exception; }
+        JSValue* exception() const { return globalData().exception; }
         JSValue** exceptionSlot() { return &globalData().exception; }
-        bool hadException() { return !!globalData().exception; }
+        bool hadException() const { return !!globalData().exception; }
 
-        IdentifierTable* identifierTable() { return globalData().identifierTable; }
-        const CommonIdentifiers& propertyNames() { return *globalData().propertyNames; }
-        const ArgList& emptyList() { return *globalData().emptyList; }
-        Lexer* lexer() { return globalData().lexer; }
-        Parser* parser() { return globalData().parser; }
+        const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
+        const ArgList& emptyList() const { return *globalData().emptyList; }
         Machine* machine() { return globalData().machine; }
         Heap* heap() { return &globalData().heap; }
 
@@ -89,6 +94,51 @@
         static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
 
     private:
+        friend class Arguments;
+        friend class JSActivation;
+        friend class JSGlobalObject;
+        friend class Machine;
+
+        static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
+        Register* registers() { return this; }
+
+        CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
+
+        int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
+        CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
+        Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
+        Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
+        int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
+
+        void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
+        void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
+        void setCalleeArguments(Arguments* arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; }
+        void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; }
+        void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
+        void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; }
+
+        ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
+            CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
+        {
+            ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
+
+            setCodeBlock(codeBlock);
+            setScopeChain(scopeChain);
+            setCallerFrame(callerFrame);
+            this[RegisterFile::ReturnPC] = vPC;
+            this[RegisterFile::ReturnValueRegister] = returnValueRegister;
+            setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
+            setCallee(function);
+            setCalleeArguments(0);
+        }
+
+        static const intptr_t HostCallFrameFlag = 1;
+
+        static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
+        bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
+        CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
+        CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
+
         ExecState();
         ~ExecState();
     };