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

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

Bug 26249: Support JSON.stringify
<https://bugs.webkit.org/show_bug.cgi?id=26249>

Reviewed by Sam Weinig.

Implement JSON.stringify. This patch handles all the semantics of the ES5
JSON.stringify function, including replacer functions and arrays and both
string and numeric gap arguments.

Currently uses a clamped recursive algorithm basically identical to the spec
description but with a few minor tweaks for performance and corrected semantics
discussed in the es-discuss mailing list.

  • 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 private:
128 friend class Arguments;
129 friend class JSActivation;
130 friend class JSGlobalObject;
131 friend class Interpreter;
132 friend struct CallFrameClosure;
133
134 int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
135
136 void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = count; }
137 void setCallee(JSFunction* callee) { this[RegisterFile::Callee] = callee; }
138 void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; }
139
140 static const intptr_t HostCallFrameFlag = 1;
141
142 static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
143 bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
144 CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
145 CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
146
147 ExecState();
148 ~ExecState();
149 };
150
151} // namespace JSC
152
153#endif // CallFrame_h
Note: See TracBrowser for help on using the repository browser.