JSGlobalObject.cpp 30.8 KB
Newer Older
ggaren@apple.com's avatar
ggaren@apple.com committed
1
/*
2
 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
mjs@apple.com's avatar
mjs@apple.com committed
3
 * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca)
ggaren@apple.com's avatar
ggaren@apple.com committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "JSGlobalObject.h"

33
#include "Arguments.h"
34
#include "ArrayConstructor.h"
weinig@apple.com's avatar
weinig@apple.com committed
35
#include "ArrayPrototype.h"
36
#include "BooleanConstructor.h"
weinig@apple.com's avatar
weinig@apple.com committed
37 38
#include "BooleanPrototype.h"
#include "CodeBlock.h"
39 40
#include "DateConstructor.h"
#include "DatePrototype.h"
41
#include "Debugger.h"
42
#include "Error.h"
43 44
#include "ErrorConstructor.h"
#include "ErrorPrototype.h"
weinig@apple.com's avatar
weinig@apple.com committed
45
#include "FunctionConstructor.h"
darin@apple.com's avatar
darin@apple.com committed
46
#include "FunctionPrototype.h"
47
#include "GetterSetter.h"
48 49
#include "Interpreter.h"
#include "JSActivation.h"
50
#include "JSBoundFunction.h"
51 52 53
#include "JSCallbackConstructor.h"
#include "JSCallbackFunction.h"
#include "JSCallbackObject.h"
54
#include "JSFunction.h"
weinig@apple.com's avatar
weinig@apple.com committed
55
#include "JSGlobalObjectFunctions.h"
ap@webkit.org's avatar
ap@webkit.org committed
56
#include "JSLock.h"
57
#include "JSNameScope.h"
58
#include "JSONObject.h"
59
#include "JSWithScope.h"
60
#include "Lookup.h"
darin@apple.com's avatar
darin@apple.com committed
61
#include "MathObject.h"
62 63 64
#include "NameConstructor.h"
#include "NameInstance.h"
#include "NamePrototype.h"
65 66
#include "NativeErrorConstructor.h"
#include "NativeErrorPrototype.h"
weinig@apple.com's avatar
weinig@apple.com committed
67 68 69 70
#include "NumberConstructor.h"
#include "NumberPrototype.h"
#include "ObjectConstructor.h"
#include "ObjectPrototype.h"
adachan@apple.com's avatar
adachan@apple.com committed
71
#include "Profiler.h"
72
#include "RegExpConstructor.h"
mjs@apple.com's avatar
mjs@apple.com committed
73
#include "RegExpMatchesArray.h"
74
#include "RegExpObject.h"
75
#include "RegExpPrototype.h"
76
#include "StrictEvalActivation.h"
weinig@apple.com's avatar
weinig@apple.com committed
77 78
#include "StringConstructor.h"
#include "StringPrototype.h"
79

80 81
#include "JSGlobalObject.lut.h"

82
namespace JSC {
ggaren@apple.com's avatar
ggaren@apple.com committed
83

84
const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &Base::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
85

86
const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled };
87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
/* Source for JSGlobalObject.lut.h
@begin globalObjectTable
  parseInt              globalFuncParseInt              DontEnum|Function 2
  parseFloat            globalFuncParseFloat            DontEnum|Function 1
  isNaN                 globalFuncIsNaN                 DontEnum|Function 1
  isFinite              globalFuncIsFinite              DontEnum|Function 1
  escape                globalFuncEscape                DontEnum|Function 1
  unescape              globalFuncUnescape              DontEnum|Function 1
  decodeURI             globalFuncDecodeURI             DontEnum|Function 1
  decodeURIComponent    globalFuncDecodeURIComponent    DontEnum|Function 1
  encodeURI             globalFuncEncodeURI             DontEnum|Function 1
  encodeURIComponent    globalFuncEncodeURIComponent    DontEnum|Function 1
@end
*/

ggaren@apple.com's avatar
ggaren@apple.com committed
103 104
ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject);

ggaren@apple.com's avatar
ggaren@apple.com committed
105 106 107 108 109 110
// Default number of ticks before a timeout check should be done.
static const int initialTickCountThreshold = 255;

// Preferred number of milliseconds between each timeout check
static const int preferredScriptCheckTimeInterval = 1000;

111
JSGlobalObject::JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable)
112
    : Base(globalData, structure, 0)
113
    , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(InitializedWatching)))
114
    , m_havingABadTimeWatchpoint(adoptRef(new WatchpointSet(InitializedWatching)))
115
    , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
116 117 118 119 120
    , m_evalEnabled(true)
    , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
{
}

ggaren@apple.com's avatar
ggaren@apple.com committed
121
JSGlobalObject::~JSGlobalObject()
ggaren@apple.com's avatar
ggaren@apple.com committed
122
{
123 124
    if (m_debugger)
        m_debugger->detach(this);
ggaren@apple.com's avatar
ggaren@apple.com committed
125

126 127
    if (Profiler* profiler = globalData().enabledProfiler())
        profiler->stopProfiling(this);
ggaren@apple.com's avatar
ggaren@apple.com committed
128 129
}

130 131
void JSGlobalObject::destroy(JSCell* cell)
{
132
    static_cast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
133 134
}

135 136 137 138 139
void JSGlobalObject::setGlobalThis(JSGlobalData& globalData, JSObject* globalThis)
{ 
    m_globalThis.set(globalData, this, globalThis);
}

darin@apple.com's avatar
darin@apple.com committed
140
void JSGlobalObject::init(JSObject* thisValue)
ggaren@apple.com's avatar
ggaren@apple.com committed
141
{
142
    ASSERT(globalData().apiLock().currentThreadIsHoldingLock());
darin@apple.com's avatar
darin@apple.com committed
143

144 145
    setGlobalThis(globalData(), thisValue);
    JSGlobalObject::globalExec()->init(0, 0, this, CallFrame::noCaller(), 0, 0);
ap@webkit.org's avatar
ap@webkit.org committed
146

147
    m_debugger = 0;
148

ggaren@apple.com's avatar
ggaren@apple.com committed
149 150 151
    reset(prototype());
}

152
void JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
153
{
154
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
155
    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
ap@webkit.org's avatar
ap@webkit.org committed
156

157
    if (symbolTablePut(thisObject, exec, propertyName, value, slot.isStrictMode()))
ggaren@apple.com's avatar
ggaren@apple.com committed
158
        return;
159
    Base::put(thisObject, exec, propertyName, value, slot);
darin@apple.com's avatar
darin@apple.com committed
160 161
}

162
void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName propertyName, JSValue value, unsigned attributes)
darin@apple.com's avatar
darin@apple.com committed
163
{
164
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
165
    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
ap@webkit.org's avatar
ap@webkit.org committed
166

167
    if (symbolTablePutWithAttributes(thisObject, exec->globalData(), propertyName, value, attributes))
darin@apple.com's avatar
darin@apple.com committed
168 169
        return;

170
    JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName);
weinig@apple.com's avatar
weinig@apple.com committed
171
    PutPropertySlot slot;
172
    Base::put(thisObject, exec, propertyName, value, slot);
darin@apple.com's avatar
darin@apple.com committed
173
    if (!valueBefore) {
174
        JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName);
barraclough@apple.com's avatar
barraclough@apple.com committed
175
        if (valueAfter)
176
            JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes);
darin@apple.com's avatar
darin@apple.com committed
177
    }
ggaren@apple.com's avatar
ggaren@apple.com committed
178 179
}

180
bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
181
{
182
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
183
    PropertySlot slot;
184
    // silently ignore attempts to add accessors aliasing vars.
185
    if (descriptor.isAccessorDescriptor() && symbolTableGet(thisObject, propertyName, slot))
186 187
        return false;
    return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
188 189 190
}


ggaren@apple.com's avatar
ggaren@apple.com committed
191 192 193
static inline JSObject* lastInPrototypeChain(JSObject* object)
{
    JSObject* o = object;
weinig@apple.com's avatar
weinig@apple.com committed
194
    while (o->prototype().isObject())
darin@apple.com's avatar
darin@apple.com committed
195
        o = asObject(o->prototype());
ggaren@apple.com's avatar
ggaren@apple.com committed
196 197 198
    return o;
}

ggaren@apple.com's avatar
ggaren@apple.com committed
199
void JSGlobalObject::reset(JSValue prototype)
ggaren@apple.com's avatar
ggaren@apple.com committed
200
{
darin@apple.com's avatar
darin@apple.com committed
201
    ExecState* exec = JSGlobalObject::globalExec();
ggaren@apple.com's avatar
ggaren@apple.com committed
202

203 204
    m_functionPrototype.set(exec->globalData(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->globalData(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created.
    m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
205
    m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
206
    m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
207
    m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
208 209
    JSFunction* callFunction = 0;
    JSFunction* applyFunction = 0;
210
    m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction);
211 212
    m_callFunction.set(exec->globalData(), this, callFunction);
    m_applyFunction.set(exec->globalData(), this, applyFunction);
213
    m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull())));
214
    GetterSetter* protoAccessor = GetterSetter::create(exec);
215 216
    protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, String(), globalFuncProtoGetter));
    protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, String(), globalFuncProtoSetter));
217
    m_objectPrototype->putDirectAccessor(exec, exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum);
218
    m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
219

220 221 222 223 224
    m_nameScopeStructure.set(exec->globalData(), this, JSNameScope::createStructure(exec->globalData(), this, jsNull()));
    m_activationStructure.set(exec->globalData(), this, JSActivation::createStructure(exec->globalData(), this, jsNull()));
    m_strictEvalActivationStructure.set(exec->globalData(), this, StrictEvalActivation::createStructure(exec->globalData(), this, jsNull()));
    m_withScopeStructure.set(exec->globalData(), this, JSWithScope::createStructure(exec->globalData(), this, jsNull()));

225
    m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
226
    m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull()));
227

228 229 230
    m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), this, m_functionPrototype.get()));
    m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), this, m_objectPrototype.get()));
    m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get()));
231
    m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSNonFinalObject>::createStructure(exec->globalData(), this, m_objectPrototype.get()));
232

233
    m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
234 235
    m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithArrayStorage));
    m_arrayStructureForSlowPut.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage));
236
    m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get()));
237

238 239
    m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
    m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), this, m_stringPrototype.get()));
240

241 242
    m_booleanPrototype.set(exec->globalData(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
    m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), this, m_booleanPrototype.get()));
243

244 245
    m_numberPrototype.set(exec->globalData(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
    m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), this, m_numberPrototype.get()));
246

247 248
    m_datePrototype.set(exec->globalData(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
    m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), this, m_datePrototype.get()));
249

250
    RegExp* emptyRegex = RegExp::create(exec->globalData(), "", NoFlags);
251
    
252 253
    m_regExpPrototype.set(exec->globalData(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()), emptyRegex));
    m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), this, m_regExpPrototype.get()));
254

255
    m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
256

arv@chromium.org's avatar
arv@chromium.org committed
257 258
    m_errorPrototype.set(exec->globalData(), this, ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())));
    m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), this, m_errorPrototype.get()));
mjs@apple.com's avatar
mjs@apple.com committed
259

ggaren@apple.com's avatar
ggaren@apple.com committed
260
    // Constructors
darin@apple.com's avatar
darin@apple.com committed
261

262 263 264 265 266 267 268
    JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_objectPrototype.get());
    JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_functionPrototype.get());
    JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_arrayPrototype.get());
    JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_stringPrototype.get());
    JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_booleanPrototype.get());
    JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_numberPrototype.get());
    JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_datePrototype.get());
darin@apple.com's avatar
darin@apple.com committed
269

270
    m_regExpConstructor.set(exec->globalData(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_regExpPrototype.get()));
darin@apple.com's avatar
darin@apple.com committed
271

arv@chromium.org's avatar
arv@chromium.org committed
272
    m_errorConstructor.set(exec->globalData(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_errorPrototype.get()));
darin@apple.com's avatar
darin@apple.com committed
273

arv@chromium.org's avatar
arv@chromium.org committed
274
    Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), this, m_errorPrototype.get());
275
    Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get());
276 277 278 279 280 281
    m_evalErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("EvalError")));
    m_rangeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("RangeError")));
    m_referenceErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("ReferenceError")));
    m_syntaxErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("SyntaxError")));
    m_typeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("TypeError")));
    m_URIErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("URIError")));
282

283 284 285 286 287 288 289 290
    m_objectPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
    m_functionPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
    m_arrayPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
    m_booleanPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
    m_stringPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
    m_numberPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
    m_datePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
    m_regExpPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
arv@chromium.org's avatar
arv@chromium.org committed
291
    m_errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum);
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
ggaren@apple.com's avatar
ggaren@apple.com committed
308

309
    m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval.string(), globalFuncEval));
310
    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum);
311

312
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum);
313
    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum);
314

315
    GlobalPropertyInfo staticGlobals[] = {
316
        GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
317
        GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
318
        GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly)
319
    };
320
    addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
ggaren@apple.com's avatar
ggaren@apple.com committed
321

322 323 324 325 326 327 328 329 330
    if (m_experimentsEnabled) {
        NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()));
        m_privateNameStructure.set(exec->globalData(), this, NameInstance::createStructure(exec->globalData(), this, privateNamePrototype));

        JSCell* privateNameConstructor = NameConstructor::create(exec, this, NameConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), privateNamePrototype);
        privateNamePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, privateNameConstructor, DontEnum);
        putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Name"), privateNameConstructor, DontEnum);
    }

331
    resetPrototype(exec->globalData(), prototype);
weinig@apple.com's avatar
weinig@apple.com committed
332
}
ggaren@apple.com's avatar
ggaren@apple.com committed
333

334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
// Private namespace for helpers for JSGlobalObject::haveABadTime()
namespace {

class ObjectsWithBrokenIndexingFinder : public MarkedBlock::VoidFunctor {
public:
    ObjectsWithBrokenIndexingFinder(MarkedArgumentBuffer&, JSGlobalObject*);
    void operator()(JSCell*);

private:
    MarkedArgumentBuffer& m_foundObjects;
    JSGlobalObject* m_globalObject;
};

ObjectsWithBrokenIndexingFinder::ObjectsWithBrokenIndexingFinder(
    MarkedArgumentBuffer& foundObjects, JSGlobalObject* globalObject)
    : m_foundObjects(foundObjects)
    , m_globalObject(globalObject)
{
}

inline bool hasBrokenIndexing(JSObject* object)
{
    // This will change if we have more indexing types.
    return !!(object->structure()->indexingType() & HasArrayStorage);
}

void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell)
{
    if (!cell->isObject())
        return;
    
    JSObject* object = asObject(cell);
366 367 368

    // Run this filter first, since it's cheap, and ought to filter out a lot of objects.
    if (!hasBrokenIndexing(object))
369 370
        return;
    
371 372
    // We only want to have a bad time in the affected global object, not in the entire
    // VM. But we have to be careful, since there may be objects that claim to belong to
373
    // a different global object that have prototypes from our global object.
374 375
    bool foundGlobalObject = false;
    for (JSObject* current = object; ;) {
376
        if (current->globalObject() == m_globalObject) {
377 378 379 380 381 382 383 384 385 386
            foundGlobalObject = true;
            break;
        }
        
        JSValue prototypeValue = current->prototype();
        if (prototypeValue.isNull())
            break;
        current = asObject(prototypeValue);
    }
    if (!foundGlobalObject)
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
        return;
    
    m_foundObjects.append(object);
}

} // end private namespace for helpers for JSGlobalObject::haveABadTime()

void JSGlobalObject::haveABadTime(JSGlobalData& globalData)
{
    ASSERT(&globalData == &this->globalData());
    
    if (isHavingABadTime())
        return;
    
    // Make sure that all allocations or indexed storage transitions that are inlining
    // the assumption that it's safe to transition to a non-SlowPut array storage don't
    // do so anymore.
    m_havingABadTimeWatchpoint->notifyWrite();
    ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time.
    
    // Make sure that all JSArray allocations that load the appropriate structure from
    // this object now load a structure that uses SlowPut.
    m_arrayStructure.set(globalData, this, m_arrayStructureForSlowPut.get());
    
    // Make sure that all objects that have indexed storage switch to the slow kind of
    // indexed storage.
    MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC.
    ObjectsWithBrokenIndexingFinder finder(foundObjects, this);
    globalData.heap.objectSpace().forEachLiveCell(finder);
    while (!foundObjects.isEmpty()) {
        JSObject* object = asObject(foundObjects.last());
        foundObjects.removeLast();
        ASSERT(hasBrokenIndexing(object));
        object->switchToSlowPutArrayStorage(globalData);
    }
}

424 425
void JSGlobalObject::createThrowTypeError(ExecState* exec)
{
426
    JSFunction* thrower = JSFunction::create(exec, this, 0, String(), globalFuncThrowTypeError);
427 428 429 430 431 432
    GetterSetter* getterSetter = GetterSetter::create(exec);
    getterSetter->setGetter(exec->globalData(), thrower);
    getterSetter->setSetter(exec->globalData(), thrower);
    m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter);
}

weinig@apple.com's avatar
weinig@apple.com committed
433
// Set prototype, and also insert the object prototype at the end of the chain.
434
void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
weinig@apple.com's avatar
weinig@apple.com committed
435
{
436
    setPrototype(globalData, prototype);
437 438

    JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this);
439
    JSObject* objectPrototype = m_objectPrototype.get();
440
    if (oldLastInPrototypeChain != objectPrototype)
441
        oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
ggaren@apple.com's avatar
ggaren@apple.com committed
442 443
}

444 445
void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{ 
446
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
447
    ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
448
    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
449
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
450
    Base::visitChildren(thisObject, visitor);
451

452
    visitor.append(&thisObject->m_globalThis);
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
    visitor.append(&thisObject->m_methodCallDummy);

    visitor.append(&thisObject->m_regExpConstructor);
    visitor.append(&thisObject->m_errorConstructor);
    visitor.append(&thisObject->m_evalErrorConstructor);
    visitor.append(&thisObject->m_rangeErrorConstructor);
    visitor.append(&thisObject->m_referenceErrorConstructor);
    visitor.append(&thisObject->m_syntaxErrorConstructor);
    visitor.append(&thisObject->m_typeErrorConstructor);
    visitor.append(&thisObject->m_URIErrorConstructor);

    visitor.append(&thisObject->m_evalFunction);
    visitor.append(&thisObject->m_callFunction);
    visitor.append(&thisObject->m_applyFunction);
    visitor.append(&thisObject->m_throwTypeErrorGetterSetter);

    visitor.append(&thisObject->m_objectPrototype);
    visitor.append(&thisObject->m_functionPrototype);
    visitor.append(&thisObject->m_arrayPrototype);
    visitor.append(&thisObject->m_booleanPrototype);
    visitor.append(&thisObject->m_stringPrototype);
    visitor.append(&thisObject->m_numberPrototype);
    visitor.append(&thisObject->m_datePrototype);
    visitor.append(&thisObject->m_regExpPrototype);
    visitor.append(&thisObject->m_errorPrototype);

479 480 481 482
    visitor.append(&thisObject->m_withScopeStructure);
    visitor.append(&thisObject->m_strictEvalActivationStructure);
    visitor.append(&thisObject->m_activationStructure);
    visitor.append(&thisObject->m_nameScopeStructure);
483 484
    visitor.append(&thisObject->m_argumentsStructure);
    visitor.append(&thisObject->m_arrayStructure);
485
    visitor.append(&thisObject->m_arrayStructureForSlowPut);
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    visitor.append(&thisObject->m_booleanObjectStructure);
    visitor.append(&thisObject->m_callbackConstructorStructure);
    visitor.append(&thisObject->m_callbackFunctionStructure);
    visitor.append(&thisObject->m_callbackObjectStructure);
    visitor.append(&thisObject->m_dateStructure);
    visitor.append(&thisObject->m_emptyObjectStructure);
    visitor.append(&thisObject->m_nullPrototypeObjectStructure);
    visitor.append(&thisObject->m_errorStructure);
    visitor.append(&thisObject->m_functionStructure);
    visitor.append(&thisObject->m_boundFunctionStructure);
    visitor.append(&thisObject->m_namedFunctionStructure);
    visitor.append(&thisObject->m_numberObjectStructure);
    visitor.append(&thisObject->m_privateNameStructure);
    visitor.append(&thisObject->m_regExpMatchesArrayStructure);
    visitor.append(&thisObject->m_regExpStructure);
    visitor.append(&thisObject->m_stringObjectStructure);
    visitor.append(&thisObject->m_internalFunctionStructure);
ggaren@apple.com's avatar
ggaren@apple.com committed
503 504
}

505 506 507 508 509
JSObject* JSGlobalObject::toThisObject(JSCell* cell, ExecState*)
{
    return jsCast<JSGlobalObject*>(cell)->globalThis();
}

ggaren@apple.com's avatar
ggaren@apple.com committed
510 511
ExecState* JSGlobalObject::globalExec()
{
512
    return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
ggaren@apple.com's avatar
ggaren@apple.com committed
513 514
}

515 516
void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
{
517
    addRegisters(count);
518

519
    for (int i = 0; i < count; ++i) {
520 521
        GlobalPropertyInfo& global = globals[i];
        ASSERT(global.attributes & DontDelete);
522
        
523
        int index = symbolTable()->size();
524
        SymbolTableEntry newEntry(index, global.attributes);
525
        symbolTable()->add(global.identifier.impl(), newEntry);
526 527 528 529
        registerAt(index).set(globalData(), this, global.value);
    }
}

530
bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
531
{
532
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell);
533
    if (getStaticFunctionSlot<Base>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot))
534
        return true;
535
    return symbolTableGet(thisObject, propertyName, slot);
536 537
}

538
bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
539
{
540
    JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object);
541
    if (getStaticFunctionDescriptor<Base>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor))
542
        return true;
543
    return symbolTableGet(thisObject, propertyName, descriptor);
544 545
}

546
void JSGlobalObject::clearRareData(JSCell* cell)
547
{
548
    jsCast<JSGlobalObject*>(cell)->m_rareData.clear();
549 550
}

551 552
DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
    : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject)
553 554 555 556 557
    , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
{
    if (!m_dynamicGlobalObjectSlot) {
#if ENABLE(ASSEMBLER)
        if (ExecutableAllocator::underMemoryPressure())
558
            globalData.heap.deleteAllCompiledCode();
559 560 561 562 563 564
#endif

        m_dynamicGlobalObjectSlot = dynamicGlobalObject;

        // Reset the date cache between JS invocations to force the VM
        // to observe time zone changes.
565
        globalData.resetDateCache();
566 567 568
    }
}

569 570 571 572 573 574 575
void slowValidateCell(JSGlobalObject* globalObject)
{
    if (!globalObject->isGlobalObject())
        CRASH();
    ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
}

576
} // namespace JSC