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();
};