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

Last change on this file since 45609 was 45609, checked in by [email protected], 16 years ago

JavaScriptCore:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

Stop loading constants into the register file.

Instead, use high register values (highest bit bar the sign bit set) to indicate
constants in the instruction stream, and when we encounter such a value load it
directly from the CodeBlock.

Since constants are no longer copied into the register file, this patch renders
the 'unexpected constant' mechanism redundant, and removes it.

2% improvement, thanks to Sam Weinig.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::mark): (JSC::CodeBlock::shrinkToFit):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::isTemporaryRegisterIndex): (JSC::CodeBlock::constantRegister): (JSC::CodeBlock::isConstantRegisterIndex): (JSC::CodeBlock::getConstant): (JSC::ExecState::r):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::preserveLastVar): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::addConstantValue): (JSC::BytecodeGenerator::emitEqualityOp): (JSC::BytecodeGenerator::emitLoad): (JSC::BytecodeGenerator::emitResolveBase): (JSC::BytecodeGenerator::emitResolveWithBase): (JSC::BytecodeGenerator::emitNewError):
  • bytecompiler/BytecodeGenerator.h: (JSC::BytecodeGenerator::emitNode):
  • interpreter/CallFrame.h: (JSC::ExecState::noCaller): (JSC::ExecState::hasHostCallFrameFlag): (JSC::ExecState::addHostCallFrameFlag): (JSC::ExecState::removeHostCallFrameFlag):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolve): (JSC::Interpreter::resolveSkip): (JSC::Interpreter::resolveGlobal): (JSC::Interpreter::resolveBase): (JSC::Interpreter::resolveBaseAndProperty): (JSC::Interpreter::resolveBaseAndFunc): (JSC::Interpreter::dumpRegisters): (JSC::Interpreter::throwException): (JSC::Interpreter::createExceptionScope): (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveArguments):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITInlineMethods.h: (JSC::JIT::emitLoadDouble): (JSC::JIT::emitLoadInt32ToDouble):
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_new_error): (JSC::JIT::emit_op_enter): (JSC::JIT::emit_op_enter_with_activation):
  • parser/Nodes.cpp: (JSC::DeleteResolveNode::emitBytecode): (JSC::DeleteValueNode::emitBytecode): (JSC::PrefixResolveNode::emitBytecode):
  • runtime/JSActivation.cpp: (JSC::JSActivation::JSActivation):
  • wtf/Platform.h:

LayoutTests:

2009-07-07 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

fast/js/global-recursion-on-full-stack.html is a little finicky.

The test recurses down the JS stack to find the bottom (catching this with an exception),
then tries to call a host function (document.write), switch writes new '<script>' code,
and expects this code to be run, then expects this code to try to call 'f();' again,
which it expects to fail, and it expects to catch that exception. However it is possible
that one of the earlier stages (the call to document.write, entering the interpreter to
run the new global code) will fail, depending on exactly how much stack space was free at
the point the last call to f() failed.

Tweak the test to make it work.

  • fast/js/global-recursion-on-full-stack.html:
  • Property svn:eol-style set to native
File size: 7.4 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 { return this[RegisterFile::ScopeChain].Register::scopeChain(); }
43 int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
44
45 JSValue thisValue();
46
47 // Global object in which execution began.
48 JSGlobalObject* dynamicGlobalObject();
49
50 // Global object in which the currently executing code was defined.
51 // Differs from dynamicGlobalObject() during function calls across web browser frames.
52 JSGlobalObject* lexicalGlobalObject() const
53 {
54 return scopeChain()->globalObject();
55 }
56
57 // Differs from lexicalGlobalObject because this will have DOM window shell rather than
58 // the actual DOM window, which can't be "this" for security reasons.
59 JSObject* globalThisValue() const
60 {
61 return scopeChain()->globalThisObject();
62 }
63
64 // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
65 // We should make this more uniform and either use a reference everywhere
66 // or a pointer everywhere.
67 JSGlobalData& globalData() const
68 {
69 return *scopeChain()->globalData;
70 }
71
72 // Convenience functions for access to global data.
73 // It takes a few memory references to get from a call frame to the global data
74 // pointer, so these are inefficient, and should be used sparingly in new code.
75 // But they're used in many places in legacy code, so they're not going away any time soon.
76
77 void setException(JSValue exception) { globalData().exception = exception; }
78 void clearException() { globalData().exception = JSValue(); }
79 JSValue exception() const { return globalData().exception; }
80 JSValue* exceptionSlot() { return &globalData().exception; }
81 bool hadException() const { return globalData().exception; }
82
83 const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
84 const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; }
85 Interpreter* interpreter() { return globalData().interpreter; }
86 Heap* heap() { return &globalData().heap; }
87#ifndef NDEBUG
88 void dumpCaller();
89#endif
90 static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
91 static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
92 static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; }
93 static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
94 static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
95 static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
96 static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
97 static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
98
99 static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
100 Register* registers() { return this; }
101
102 CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
103
104 CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
105 Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
106 Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
107
108 void setCalleeArguments(Arguments* arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; }
109 void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; }
110 void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; }
111
112 ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
113 CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
114 {
115 ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
116
117 setCodeBlock(codeBlock);
118 setScopeChain(scopeChain);
119 setCallerFrame(callerFrame);
120 this[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
121 this[RegisterFile::ReturnValueRegister] = returnValueRegister;
122 setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
123 setCallee(function);
124 setCalleeArguments(0);
125 }
126
127 // Read a register from the codeframe (or constant from the CodeBlock).
128 inline Register& r(int);
129
130 static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
131 int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
132
133 bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
134 CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
135 CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
136
137 private:
138 void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
139 void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
140 void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
141
142 static const intptr_t HostCallFrameFlag = 1;
143
144 ExecState();
145 ~ExecState();
146 };
147
148} // namespace JSC
149
150#endif // CallFrame_h
Note: See TracBrowser for help on using the repository browser.