source: webkit/trunk/JavaScriptCore/runtime/JSGlobalData.cpp@ 44711

Last change on this file since 44711 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: 8.1 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "JSGlobalData.h"
31
32#include "ArgList.h"
33#include "Collector.h"
34#include "CommonIdentifiers.h"
35#include "FunctionConstructor.h"
36#include "Interpreter.h"
37#include "JSActivation.h"
38#include "JSArray.h"
39#include "JSByteArray.h"
40#include "JSClassRef.h"
41#include "JSFunction.h"
42#include "JSLock.h"
43#include "JSNotAnObject.h"
44#include "JSStaticScopeObject.h"
45#include "Parser.h"
46#include "Lexer.h"
47#include "Lookup.h"
48#include "Nodes.h"
49
50#if ENABLE(JSC_MULTIPLE_THREADS)
51#include <wtf/Threading.h>
52#endif
53
54#if PLATFORM(MAC)
55#include "ProfilerServer.h"
56#endif
57
58using namespace WTF;
59
60namespace JSC {
61
62extern const HashTable arrayTable;
63extern const HashTable jsonTable;
64extern const HashTable dateTable;
65extern const HashTable mathTable;
66extern const HashTable numberTable;
67extern const HashTable regExpTable;
68extern const HashTable regExpConstructorTable;
69extern const HashTable stringTable;
70
71struct VPtrSet {
72 VPtrSet();
73
74 void* jsArrayVPtr;
75 void* jsByteArrayVPtr;
76 void* jsStringVPtr;
77 void* jsFunctionVPtr;
78};
79
80VPtrSet::VPtrSet()
81{
82 // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
83 void* storage = fastMalloc(sizeof(CollectorBlock));
84
85 JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
86 jsArrayVPtr = jsArray->vptr();
87 jsArray->~JSCell();
88
89 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
90 jsByteArrayVPtr = jsByteArray->vptr();
91 jsByteArray->~JSCell();
92
93 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
94 jsStringVPtr = jsString->vptr();
95 jsString->~JSCell();
96
97 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
98 jsFunctionVPtr = jsFunction->vptr();
99 jsFunction->~JSCell();
100
101 fastFree(storage);
102}
103
104JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
105 : isSharedInstance(isShared)
106 , clientData(0)
107 , arrayTable(fastNew<HashTable>(JSC::arrayTable))
108 , dateTable(fastNew<HashTable>(JSC::dateTable))
109 , jsonTable(fastNew<HashTable>(JSC::jsonTable))
110 , mathTable(fastNew<HashTable>(JSC::mathTable))
111 , numberTable(fastNew<HashTable>(JSC::numberTable))
112 , regExpTable(fastNew<HashTable>(JSC::regExpTable))
113 , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
114 , stringTable(fastNew<HashTable>(JSC::stringTable))
115 , activationStructure(JSActivation::createStructure(jsNull()))
116 , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
117 , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
118 , stringStructure(JSString::createStructure(jsNull()))
119 , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
120 , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
121#if !USE(ALTERNATE_JSIMMEDIATE)
122 , numberStructure(JSNumberCell::createStructure(jsNull()))
123#endif
124 , jsArrayVPtr(vptrSet.jsArrayVPtr)
125 , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr)
126 , jsStringVPtr(vptrSet.jsStringVPtr)
127 , jsFunctionVPtr(vptrSet.jsFunctionVPtr)
128 , identifierTable(createIdentifierTable())
129 , propertyNames(new CommonIdentifiers(this))
130 , emptyList(new MarkedArgumentBuffer)
131 , lexer(new Lexer(this))
132 , parser(new Parser)
133 , interpreter(new Interpreter)
134#if ENABLE(JIT)
135 , jitStubs(this)
136#endif
137 , heap(this)
138 , initializingLazyNumericCompareFunction(false)
139 , head(0)
140 , dynamicGlobalObject(0)
141 , scopeNodeBeingReparsed(0)
142{
143#if PLATFORM(MAC)
144 startProfilerServerIfNeeded();
145#endif
146}
147
148JSGlobalData::~JSGlobalData()
149{
150 // By the time this is destroyed, heap.destroy() must already have been called.
151
152 delete interpreter;
153#ifndef NDEBUG
154 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
155 interpreter = 0;
156#endif
157
158 arrayTable->deleteTable();
159 dateTable->deleteTable();
160 jsonTable->deleteTable();
161 mathTable->deleteTable();
162 numberTable->deleteTable();
163 regExpTable->deleteTable();
164 regExpConstructorTable->deleteTable();
165 stringTable->deleteTable();
166#if ENABLE(JIT)
167 lazyNativeFunctionThunk.clear();
168#endif
169
170 fastDelete(const_cast<HashTable*>(arrayTable));
171 fastDelete(const_cast<HashTable*>(dateTable));
172 fastDelete(const_cast<HashTable*>(jsonTable));
173 fastDelete(const_cast<HashTable*>(mathTable));
174 fastDelete(const_cast<HashTable*>(numberTable));
175 fastDelete(const_cast<HashTable*>(regExpTable));
176 fastDelete(const_cast<HashTable*>(regExpConstructorTable));
177 fastDelete(const_cast<HashTable*>(stringTable));
178
179 delete parser;
180 delete lexer;
181
182 deleteAllValues(opaqueJSClassData);
183
184 delete emptyList;
185
186 delete propertyNames;
187 deleteIdentifierTable(identifierTable);
188
189 delete clientData;
190}
191
192PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared)
193{
194 return adoptRef(new JSGlobalData(isShared, VPtrSet()));
195}
196
197PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
198{
199 Structure::startIgnoringLeaks();
200 RefPtr<JSGlobalData> data = create();
201 Structure::stopIgnoringLeaks();
202 return data.release();
203}
204
205bool JSGlobalData::sharedInstanceExists()
206{
207 return sharedInstanceInternal();
208}
209
210JSGlobalData& JSGlobalData::sharedInstance()
211{
212 JSGlobalData*& instance = sharedInstanceInternal();
213 if (!instance) {
214 instance = create(true).releaseRef();
215#if ENABLE(JSC_MULTIPLE_THREADS)
216 instance->makeUsableFromMultipleThreads();
217#endif
218 }
219 return *instance;
220}
221
222JSGlobalData*& JSGlobalData::sharedInstanceInternal()
223{
224 ASSERT(JSLock::currentThreadIsHoldingLock());
225 static JSGlobalData* sharedInstance;
226 return sharedInstance;
227}
228
229#if ENABLE(JIT)
230
231void JSGlobalData::createNativeThunk()
232{
233 lazyNativeFunctionThunk = FunctionBodyNode::createNativeThunk(this);
234}
235
236#endif
237
238// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
239const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
240{
241 if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
242 initializingLazyNumericCompareFunction = true;
243 RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
244 RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get());
245 lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
246 initializingLazyNumericCompareFunction = false;
247 }
248
249 return lazyNumericCompareFunction;
250}
251
252JSGlobalData::ClientData::~ClientData()
253{
254}
255
256} // namespace JSC
Note: See TracBrowser for help on using the repository browser.