X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..a253471d7f8e4d91bf6ebabab00155c3b387d3d0:/runtime/JSGlobalObject.cpp diff --git a/runtime/JSGlobalObject.cpp b/runtime/JSGlobalObject.cpp index a71624f..dc68bde 100644 --- a/runtime/JSGlobalObject.cpp +++ b/runtime/JSGlobalObject.cpp @@ -42,10 +42,13 @@ #include "CodeBlock.h" #include "DateConstructor.h" #include "DatePrototype.h" +#include "Error.h" #include "ErrorConstructor.h" #include "ErrorPrototype.h" #include "FunctionConstructor.h" #include "FunctionPrototype.h" +#include "GetterSetter.h" +#include "JSBoundFunction.h" #include "JSFunction.h" #include "JSGlobalObjectFunctions.h" #include "JSLock.h" @@ -73,7 +76,11 @@ namespace JSC { -const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable }; +const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) }; + +const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript + , &shouldInterruptScriptBeforeTimeout +}; /* Source for JSGlobalObject.lut.h @begin globalObjectTable @@ -106,8 +113,6 @@ template static inline void visitIfNeeded(SlotVisitor& visitor, Wri JSGlobalObject::~JSGlobalObject() { - ASSERT(JSLock::currentThreadIsHoldingLock()); - if (m_debugger) m_debugger->detach(this); @@ -117,63 +122,64 @@ JSGlobalObject::~JSGlobalObject() } } +void JSGlobalObject::destroy(JSCell* cell) +{ + jsCast(cell)->JSGlobalObject::~JSGlobalObject(); +} + void JSGlobalObject::init(JSObject* thisValue) { - ASSERT(JSLock::currentThreadIsHoldingLock()); + ASSERT(globalData().apiLock().currentThreadIsHoldingLock()); structure()->disableSpecificFunctionTracking(); - m_globalData = Heap::heap(this)->globalData(); - m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue)); + m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue)); JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); m_debugger = 0; - m_profileGroup = 0; - reset(prototype()); } -void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +void JSGlobalObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + JSGlobalObject* thisObject = jsCast(cell); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); - if (symbolTablePut(exec->globalData(), propertyName, value)) + if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode())) return; - JSVariableObject::put(exec, propertyName, value, slot); + JSVariableObject::put(thisObject, exec, propertyName, value, slot); } -void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { - ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + JSGlobalObject* thisObject = jsCast(object); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); - if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes)) + if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes)) return; - JSValue valueBefore = getDirect(exec->globalData(), propertyName); + JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName); PutPropertySlot slot; - JSVariableObject::put(exec, propertyName, value, slot); + JSVariableObject::put(thisObject, exec, propertyName, value, slot); if (!valueBefore) { - JSValue valueAfter = getDirect(exec->globalData(), propertyName); + JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName); if (valueAfter) - JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes); + JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes); } } -void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes) +bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) { + JSGlobalObject* thisObject = jsCast(object); PropertySlot slot; - if (!symbolTableGet(propertyName, slot)) - JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes); + // silently ignore attempts to add accessors aliasing vars. + if (descriptor.isAccessorDescriptor() && thisObject->symbolTableGet(propertyName, slot)) + return false; + return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); } -void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes) -{ - PropertySlot slot; - if (!symbolTableGet(propertyName, slot)) - JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes); -} static inline JSObject* lastInPrototypeChain(JSObject* object) { @@ -187,115 +193,131 @@ void JSGlobalObject::reset(JSValue prototype) { ExecState* exec = JSGlobalObject::globalExec(); - m_functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(exec->globalData(), jsNull()))); // The real prototype will be set once ObjectPrototype is created. - m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), m_functionPrototype.get())); - m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get())); + 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())); + m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); + m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset)); + m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); JSFunction* callFunction = 0; JSFunction* applyFunction = 0; - m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction); + m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction); m_callFunction.set(exec->globalData(), this, callFunction); m_applyFunction.set(exec->globalData(), this, applyFunction); - m_objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(exec->globalData(), jsNull()))); + m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull()))); + GetterSetter* protoAccessor = GetterSetter::create(exec); + protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoGetter)); + protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoSetter)); + m_objectPrototype->putDirectAccessor(exec->globalData(), exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum); m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get()); m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData())); - m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), jsNull())); + m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull())); - m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get())); - m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), m_objectPrototype.get())); - m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get())); - m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject::createStructure(exec->globalData(), m_objectPrototype.get())); + 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())); + m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject::createStructure(exec->globalData(), this, m_objectPrototype.get())); - m_arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), m_arrayPrototype.get())); - m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get())); + m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); + m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); + m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); - m_stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), m_stringPrototype.get())); + 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())); - m_booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get())); + 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())); - m_numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), m_numberPrototype.get())); + 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())); - m_datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); - m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), m_datePrototype.get())); + 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())); - RegExp* emptyRegex = RegExp::create(&exec->globalData(), "", NoFlags); + RegExp* emptyRegex = RegExp::create(exec->globalData(), "", NoFlags); - m_regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), emptyRegex)); - m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get())); + 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())); m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); - ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get())); - m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), errorPrototype)); + ErrorPrototype* errorPrototype = ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())); + m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), this, errorPrototype)); // Constructors - JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_objectPrototype.get()); - JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionPrototype.get()); - JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_arrayPrototype.get()); - JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_stringPrototype.get()); - JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_booleanPrototype.get()); - JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_numberPrototype.get()); - JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_datePrototype.get()); - - m_regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_regExpPrototype.get())); - - m_errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), errorPrototype)); - - Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype); - Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()); - m_evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); - m_rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); - m_referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); - m_syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); - m_typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); - m_URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); - - m_objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); - m_functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); - m_arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); - m_booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); - m_stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); - m_numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); - m_datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); - m_regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum); - errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); - - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum); - - m_evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval)); - putDirectFunctionWithoutTransition(exec, m_evalFunction.get(), DontEnum); + 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()); + + m_regExpConstructor.set(exec->globalData(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_regExpPrototype.get())); + + m_errorConstructor.set(exec->globalData(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), errorPrototype)); + + Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), this, errorPrototype); + Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()); + m_evalErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); + m_rangeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); + m_referenceErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); + m_syntaxErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); + m_typeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); + m_URIErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); + + 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); + errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); + + 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); + + m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval, globalFuncEval)); + putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum); + + putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum); GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete) + GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits::infinity()), DontEnum | DontDelete | ReadOnly), + GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); resetPrototype(exec->globalData(), prototype); } +void JSGlobalObject::createThrowTypeError(ExecState* exec) +{ + JSFunction* thrower = JSFunction::create(exec, this, 0, Identifier(), globalFuncThrowTypeError); + GetterSetter* getterSetter = GetterSetter::create(exec); + getterSetter->setGetter(exec->globalData(), thrower); + getterSetter->setSetter(exec->globalData(), thrower); + m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter); +} + // Set prototype, and also insert the object prototype at the end of the chain. void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype) { @@ -307,64 +329,68 @@ void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype) oldLastInPrototypeChain->setPrototype(globalData, objectPrototype); } -void JSGlobalObject::visitChildren(SlotVisitor& visitor) -{ - ASSERT_GC_OBJECT_INHERITS(this, &s_info); +void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + JSGlobalObject* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(structure()->typeInfo().overridesVisitChildren()); - JSVariableObject::visitChildren(visitor); - - visitIfNeeded(visitor, &m_globalScopeChain); - visitIfNeeded(visitor, &m_methodCallDummy); - - visitIfNeeded(visitor, &m_regExpConstructor); - visitIfNeeded(visitor, &m_errorConstructor); - visitIfNeeded(visitor, &m_evalErrorConstructor); - visitIfNeeded(visitor, &m_rangeErrorConstructor); - visitIfNeeded(visitor, &m_referenceErrorConstructor); - visitIfNeeded(visitor, &m_syntaxErrorConstructor); - visitIfNeeded(visitor, &m_typeErrorConstructor); - visitIfNeeded(visitor, &m_URIErrorConstructor); - - visitIfNeeded(visitor, &m_evalFunction); - visitIfNeeded(visitor, &m_callFunction); - visitIfNeeded(visitor, &m_applyFunction); - - visitIfNeeded(visitor, &m_objectPrototype); - visitIfNeeded(visitor, &m_functionPrototype); - visitIfNeeded(visitor, &m_arrayPrototype); - visitIfNeeded(visitor, &m_booleanPrototype); - visitIfNeeded(visitor, &m_stringPrototype); - visitIfNeeded(visitor, &m_numberPrototype); - visitIfNeeded(visitor, &m_datePrototype); - visitIfNeeded(visitor, &m_regExpPrototype); - - visitIfNeeded(visitor, &m_argumentsStructure); - visitIfNeeded(visitor, &m_arrayStructure); - visitIfNeeded(visitor, &m_booleanObjectStructure); - visitIfNeeded(visitor, &m_callbackConstructorStructure); - visitIfNeeded(visitor, &m_callbackFunctionStructure); - visitIfNeeded(visitor, &m_callbackObjectStructure); - visitIfNeeded(visitor, &m_dateStructure); - visitIfNeeded(visitor, &m_emptyObjectStructure); - visitIfNeeded(visitor, &m_nullPrototypeObjectStructure); - visitIfNeeded(visitor, &m_errorStructure); - visitIfNeeded(visitor, &m_functionStructure); - visitIfNeeded(visitor, &m_numberObjectStructure); - visitIfNeeded(visitor, &m_regExpMatchesArrayStructure); - visitIfNeeded(visitor, &m_regExpStructure); - visitIfNeeded(visitor, &m_stringObjectStructure); - visitIfNeeded(visitor, &m_internalFunctionStructure); - - if (m_registerArray) { + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); + JSVariableObject::visitChildren(thisObject, visitor); + + visitIfNeeded(visitor, &thisObject->m_globalScopeChain); + visitIfNeeded(visitor, &thisObject->m_methodCallDummy); + + visitIfNeeded(visitor, &thisObject->m_regExpConstructor); + visitIfNeeded(visitor, &thisObject->m_errorConstructor); + visitIfNeeded(visitor, &thisObject->m_evalErrorConstructor); + visitIfNeeded(visitor, &thisObject->m_rangeErrorConstructor); + visitIfNeeded(visitor, &thisObject->m_referenceErrorConstructor); + visitIfNeeded(visitor, &thisObject->m_syntaxErrorConstructor); + visitIfNeeded(visitor, &thisObject->m_typeErrorConstructor); + visitIfNeeded(visitor, &thisObject->m_URIErrorConstructor); + + visitIfNeeded(visitor, &thisObject->m_evalFunction); + visitIfNeeded(visitor, &thisObject->m_callFunction); + visitIfNeeded(visitor, &thisObject->m_applyFunction); + visitIfNeeded(visitor, &thisObject->m_throwTypeErrorGetterSetter); + + visitIfNeeded(visitor, &thisObject->m_objectPrototype); + visitIfNeeded(visitor, &thisObject->m_functionPrototype); + visitIfNeeded(visitor, &thisObject->m_arrayPrototype); + visitIfNeeded(visitor, &thisObject->m_booleanPrototype); + visitIfNeeded(visitor, &thisObject->m_stringPrototype); + visitIfNeeded(visitor, &thisObject->m_numberPrototype); + visitIfNeeded(visitor, &thisObject->m_datePrototype); + visitIfNeeded(visitor, &thisObject->m_regExpPrototype); + + visitIfNeeded(visitor, &thisObject->m_argumentsStructure); + visitIfNeeded(visitor, &thisObject->m_arrayStructure); + visitIfNeeded(visitor, &thisObject->m_booleanObjectStructure); + visitIfNeeded(visitor, &thisObject->m_callbackConstructorStructure); + visitIfNeeded(visitor, &thisObject->m_callbackFunctionStructure); + visitIfNeeded(visitor, &thisObject->m_callbackObjectStructure); + visitIfNeeded(visitor, &thisObject->m_dateStructure); + visitIfNeeded(visitor, &thisObject->m_emptyObjectStructure); + visitIfNeeded(visitor, &thisObject->m_nullPrototypeObjectStructure); + visitIfNeeded(visitor, &thisObject->m_errorStructure); + visitIfNeeded(visitor, &thisObject->m_functionStructure); + visitIfNeeded(visitor, &thisObject->m_boundFunctionStructure); + visitIfNeeded(visitor, &thisObject->m_namedFunctionStructure); + visitIfNeeded(visitor, &thisObject->m_numberObjectStructure); + visitIfNeeded(visitor, &thisObject->m_regExpMatchesArrayStructure); + visitIfNeeded(visitor, &thisObject->m_regExpStructure); + visitIfNeeded(visitor, &thisObject->m_stringObjectStructure); + visitIfNeeded(visitor, &thisObject->m_internalFunctionStructure); + + if (thisObject->m_registerArray) { // Outside the execution of global code, when our variables are torn off, // we can mark the torn-off array. - visitor.appendValues(m_registerArray.get(), m_registerArraySize); - } else if (m_registers) { + visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_registerArraySize); + } else if (thisObject->m_registers) { // During execution of global code, when our variables are in the register file, // the symbol table tells us how many variables there are, and registers // points to where they end, and the registers used for execution begin. - visitor.appendValues(m_registers - symbolTable().size(), symbolTable().size()); + visitor.appendValues(thisObject->m_registers - thisObject->symbolTable().size(), thisObject->symbolTable().size()); } } @@ -373,122 +399,57 @@ ExecState* JSGlobalObject::globalExec() return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize); } -bool JSGlobalObject::isDynamicScope(bool&) const -{ - return true; -} - -void JSGlobalObject::disableEval() -{ - ASSERT(m_isEvalEnabled); - m_isEvalEnabled = false; -} - -void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) -{ - ASSERT(!m_registerArray); - ASSERT(!m_registerArraySize); - - int numGlobals = registerFile.numGlobals(); - if (!numGlobals) { - m_registers = 0; - return; - } - - OwnArrayPtr > registerArray = copyRegisterArray(globalData(), reinterpret_cast*>(registerFile.lastGlobal()), numGlobals, numGlobals); - WriteBarrier* registers = registerArray.get() + numGlobals; - setRegisters(registers, registerArray.release(), numGlobals); -} - -void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) -{ - JSGlobalObject* lastGlobalObject = registerFile.globalObject(); - if (lastGlobalObject && lastGlobalObject != this) - lastGlobalObject->copyGlobalsFrom(registerFile); - - registerFile.setGlobalObject(this); - registerFile.setNumGlobals(symbolTable().size()); - - if (m_registerArray) { - // The register file is always a gc root so no barrier is needed here - memcpy(registerFile.start() - m_registerArraySize, m_registerArray.get(), m_registerArraySize * sizeof(WriteBarrier)); - setRegisters(reinterpret_cast*>(registerFile.start()), nullptr, 0); - } -} - -void JSGlobalObject::resizeRegisters(int oldSize, int newSize) +void JSGlobalObject::resizeRegisters(size_t newSize) { - ASSERT(oldSize <= newSize); - if (newSize == oldSize) + // Previous duplicate symbols may have created spare capacity in m_registerArray. + if (newSize <= m_registerArraySize) return; - ASSERT(newSize && newSize > oldSize); - if (m_registerArray || !m_registers) { - ASSERT(static_cast(oldSize) == m_registerArraySize); - OwnArrayPtr > registerArray = adoptArrayPtr(new WriteBarrier[newSize]); - for (int i = 0; i < oldSize; i++) - registerArray[newSize - oldSize + i].set(globalData(), this, m_registerArray[i].get()); - WriteBarrier* registers = registerArray.get() + newSize; - setRegisters(registers, registerArray.release(), newSize); - } else { - ASSERT(static_cast(newSize) < globalData().interpreter->registerFile().maxGlobals()); - globalData().interpreter->registerFile().setNumGlobals(newSize); - } - for (int i = -newSize; i < -oldSize; ++i) - m_registers[i].setUndefined(); -} + size_t oldSize = m_registerArraySize; + OwnArrayPtr > registerArray = adoptArrayPtr(new WriteBarrier[newSize]); + for (size_t i = 0; i < oldSize; ++i) + registerArray[i].set(globalData(), this, m_registerArray[i].get()); + for (size_t i = oldSize; i < newSize; ++i) + registerArray[i].setUndefined(); -void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) -{ - return globalData->heap.allocate(size); + WriteBarrier* registers = registerArray.get(); + setRegisters(registers, registerArray.release(), newSize); } void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) { - size_t oldSize = m_registerArraySize; - size_t newSize = oldSize + count; - OwnArrayPtr > registerArray = adoptArrayPtr(new WriteBarrier[newSize]); - if (m_registerArray) { - // memcpy is safe here as we're copying barriers we already own from the existing array - memcpy(registerArray.get() + count, m_registerArray.get(), oldSize * sizeof(Register)); - } + resizeRegisters(symbolTable().size() + count); - WriteBarrier* registers = registerArray.get() + newSize; - setRegisters(registers, registerArray.release(), newSize); - - for (int i = 0, index = -static_cast(oldSize) - 1; i < count; ++i, --index) { + for (int i = 0; i < count; ++i) { GlobalPropertyInfo& global = globals[i]; ASSERT(global.attributes & DontDelete); + + int index = symbolTable().size(); SymbolTableEntry newEntry(index, global.attributes); symbolTable().add(global.identifier.impl(), newEntry); registerAt(index).set(globalData(), this, global.value); } } -bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (getStaticFunctionSlot(exec, ExecState::globalObjectTable(exec), this, propertyName, slot)) + JSGlobalObject* thisObject = jsCast(cell); + if (getStaticFunctionSlot(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot)) return true; - return symbolTableGet(propertyName, slot); + return thisObject->symbolTableGet(propertyName, slot); } -bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { - if (getStaticFunctionDescriptor(exec, ExecState::globalObjectTable(exec), this, propertyName, descriptor)) + JSGlobalObject* thisObject = jsCast(object); + if (getStaticFunctionDescriptor(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor)) return true; - return symbolTableGet(propertyName, descriptor); -} - -void JSGlobalObject::WeakMapsFinalizer::finalize(Handle handle, void*) -{ - JSGlobalObject* globalObject = asGlobalObject(handle.get()); - globalObject->m_weakMaps.clear(); + return thisObject->symbolTableGet(propertyName, descriptor); } -JSGlobalObject::WeakMapsFinalizer* JSGlobalObject::weakMapsFinalizer() +void JSGlobalObject::clearRareData(JSCell* cell) { - static WeakMapsFinalizer* finalizer = new WeakMapsFinalizer(); - return finalizer; + jsCast(cell)->m_rareData.clear(); } DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject) @@ -498,7 +459,7 @@ DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSG if (!m_dynamicGlobalObjectSlot) { #if ENABLE(ASSEMBLER) if (ExecutableAllocator::underMemoryPressure()) - globalData.recompileAllJSFunctions(); + globalData.heap.discardAllCompiledCode(); #endif m_dynamicGlobalObjectSlot = dynamicGlobalObject;