source: webkit/trunk/JavaScriptCore/interpreter/CallFrame.h@ 57853

Last change on this file since 57853 was 52343, checked in by [email protected], 15 years ago

Changed Register constructors to assignment operators, to streamline
moving values into registers. (In theory, there's no difference between
the two, since the constructor should just inline away, but there seems
to be a big difference in the addled mind of the GCC optimizer.)

Reviewed by Cameron Zwarich and Gavin Barraclough.

In the interpreter, this is a 3.5% SunSpider speedup and a 1K-2K
reduction in stack usage per privateExecute stack frame.

  • interpreter/CallFrame.h:

(JSC::ExecState::setCalleeArguments):
(JSC::ExecState::setCallerFrame):
(JSC::ExecState::setScopeChain):
(JSC::ExecState::init):
(JSC::ExecState::setArgumentCount):
(JSC::ExecState::setCallee):
(JSC::ExecState::setCodeBlock): Added a little bit of casting so these
functions could use the new Register assignment operators.

  • interpreter/Register.h:

(JSC::Register::withInt):
(JSC::Register::Register):
(JSC::Register::operator=): Swapped in assignment operators for constructors.

  • Property svn:eol-style set to native
File size: 7.7 KB
Line 
1/*
2 * Copyright (C) 1999-2001 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef CallFrame_h
24#define CallFrame_h
25
26#include "JSGlobalData.h"
27#include "RegisterFile.h"
28#include "ScopeChain.h"
29
30namespace JSC {
31
32 class Arguments;
33 class JSActivation;
34 class Interpreter;
35
36 // Represents the current state of script execution.
37 // Passed as the first argument to most functions.
38 class ExecState : private Register {
39 public:
40 JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
41 CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
42 ScopeChainNode* scopeChain() const
43 {
44 ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain());
45 return this[RegisterFile::ScopeChain].Register::scopeChain();
46 }
47 int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
48
49 JSValue thisValue();
50
51 // Global object in which execution began.
52 JSGlobalObject* dynamicGlobalObject();
53
54 // Global object in which the currently executing code was defined.
55 // Differs from dynamicGlobalObject() during function calls across web browser frames.
56 JSGlobalObject* lexicalGlobalObject() const
57 {
58 return scopeChain()->globalObject;
59 }
60
61 // Differs from lexicalGlobalObject because this will have DOM window shell rather than
62 // the actual DOM window, which can't be "this" for security reasons.
63 JSObject* globalThisValue() const
64 {
65 return scopeChain()->globalThis;
66 }
67
68 // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
69 // We should make this more uniform and either use a reference everywhere
70 // or a pointer everywhere.
71 JSGlobalData& globalData() const
72 {
73 ASSERT(scopeChain()->globalData);
74 return *scopeChain()->globalData;
75 }
76
77 // Convenience functions for access to global data.
78 // It takes a few memory references to get from a call frame to the global data
79 // pointer, so these are inefficient, and should be used sparingly in new code.
80 // But they're used in many places in legacy code, so they're not going away any time soon.
81
82 void setException(JSValue exception) { globalData().exception = exception; }
83 void clearException() { globalData().exception = JSValue(); }
84 JSValue exception() const { return globalData().exception; }
85 JSValue* exceptionSlot() { return &globalData().exception; }
86 bool hadException() const { return globalData().exception; }
87
88 const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
89 const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; }
90 Interpreter* interpreter() { return globalData().interpreter; }
91 Heap* heap() { return &globalData().heap; }
92#ifndef NDEBUG
93 void dumpCaller();
94#endif
95 static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
96 static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
97 static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; }
98 static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
99 static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
100 static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
101 static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
102 static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
103
104 static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
105 Register* registers() { return this; }
106
107 CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
108
109 CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
110 Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
111 Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
112
113 void setCalleeArguments(JSValue arguments) { static_cast<Register*>(this)[RegisterFile::OptionalCalleeArguments] = arguments; }
114 void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
115 void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
116
117 ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
118 CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
119 {
120 ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
121
122 setCodeBlock(codeBlock);
123 setScopeChain(scopeChain);
124 setCallerFrame(callerFrame);
125 static_cast<Register*>(this)[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
126 static_cast<Register*>(this)[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister);
127 setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
128 setCallee(function);
129 setCalleeArguments(JSValue());
130 }
131
132 // Read a register from the codeframe (or constant from the CodeBlock).
133 inline Register& r(int);
134
135 static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
136 int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
137
138 bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
139 CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
140 CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
141
142 private:
143 void setArgumentCount(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
144 void setCallee(JSFunction* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = callee; }
145 void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
146
147 static const intptr_t HostCallFrameFlag = 1;
148
149 ExecState();
150 ~ExecState();
151 };
152
153} // namespace JSC
154
155#endif // CallFrame_h
Note: See TracBrowser for help on using the repository browser.