diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-09-24 14:35:49 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-09-24 15:36:17 (GMT) |
commit | aabd12223bda6260756ab19430082477d5669c0a (patch) | |
tree | 6ca7a12e627915992cfd0038f6ddd8ee244711f4 /src/3rdparty/javascriptcore/JavaScriptCore/runtime | |
parent | 270c374c178ec5a532d37168b018cd7ebc844558 (diff) | |
download | Qt-aabd12223bda6260756ab19430082477d5669c0a.zip Qt-aabd12223bda6260756ab19430082477d5669c0a.tar.gz Qt-aabd12223bda6260756ab19430082477d5669c0a.tar.bz2 |
Update src/3rdparty/javascriptcore and adapt src/script to the changes.
Reviewed-by: Simon Hausmann
Diffstat (limited to 'src/3rdparty/javascriptcore/JavaScriptCore/runtime')
127 files changed, 4492 insertions, 1750 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.cpp index 0b5d958..ab2b5d7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -37,16 +37,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const result = ArgList(m_args + startIndex, m_argCount - startIndex); } -void MarkedArgumentBuffer::markLists(ListSet& markSet) +void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet) { ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { MarkedArgumentBuffer* list = *it; - - iterator end2 = list->end(); - for (iterator it2 = list->begin(); it2 != end2; ++it2) - if (!(*it2).marked()) - (*it2).mark(); + markStack.appendValues(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h index 0899e85..3227770 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008, 2009 Apple Computer, Inc. + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,15 +22,15 @@ #ifndef ArgList_h #define ArgList_h -#include "JSImmediate.h" #include "Register.h" - #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/Vector.h> namespace JSC { - + + class MarkStack; + class MarkedArgumentBuffer : public Noncopyable { private: static const unsigned inlineCapacity = 8; @@ -136,7 +136,7 @@ namespace JSC { const_iterator begin() const { return m_buffer; } const_iterator end() const { return m_buffer + m_size; } - static void markLists(ListSet&); + static void markLists(MarkStack&, ListSet&); private: void slowAppend(JSValue); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp index 7cb4fe9..d90ea15 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -43,30 +43,22 @@ Arguments::~Arguments() delete [] d->extraArguments; } -void Arguments::mark() +void Arguments::markChildren(MarkStack& markStack) { - JSObject::mark(); + JSObject::markChildren(markStack); - if (d->registerArray) { - for (unsigned i = 0; i < d->numParameters; ++i) { - if (!d->registerArray[i].marked()) - d->registerArray[i].mark(); - } - } + if (d->registerArray) + markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters); if (d->extraArguments) { unsigned numExtraArguments = d->numArguments - d->numParameters; - for (unsigned i = 0; i < numExtraArguments; ++i) { - if (!d->extraArguments[i].marked()) - d->extraArguments[i].mark(); - } + markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments); } - if (!d->callee->marked()) - d->callee->mark(); + markStack.append(d->callee); - if (d->activation && !d->activation->marked()) - d->activation->mark(); + if (d->activation) + markStack.append(d->activation); } void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize) @@ -187,6 +179,31 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa return JSObject::getOwnPropertySlot(exec, propertyName, slot); } +bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + bool isArrayIndex; + unsigned i = propertyName.toArrayIndex(&isArrayIndex); + if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { + if (i < d->numParameters) { + descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum); + } else + descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum); + return true; + } + + if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) { + descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum); + return true; + } + + if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) { + descriptor.setDescriptor(d->callee, DontEnum); + return true; + } + + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h index dc54dac..2aa0921 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -28,6 +28,8 @@ #include "JSFunction.h" #include "JSGlobalObject.h" #include "Interpreter.h" +#include "ObjectConstructor.h" +#include "PrototypeFunction.h" namespace JSC { @@ -61,7 +63,7 @@ namespace JSC { static const ClassInfo info; - virtual void mark(); + virtual void markChildren(MarkStack&); void fillArgList(ExecState*, MarkedArgumentBuffer&); @@ -90,6 +92,7 @@ namespace JSC { void getArgumentsData(CallFrame*, JSObject*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); @@ -116,21 +119,20 @@ namespace JSC { callee = callFrame->callee(); int numParameters; - if (callee->isObject(&JSFunction::info)) { - CodeBlock* codeBlock = &JSC::asFunction(callee)->body()->generatedBytecode(); - numParameters = codeBlock->m_numParameters; - } else { + if (callee->inherits(&JSFunction::info)) + numParameters = JSC::asFunction(callee)->jsExecutable()->parameterCount(); + else numParameters = 0; - } + argc = callFrame->argumentCount(); if (argc <= numParameters) - argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this" + argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters; else - argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this" + argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc; argc -= 1; // - 1 to skip "this" - firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this" + firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters; } inline Arguments::Arguments(CallFrame* callFrame) @@ -143,8 +145,8 @@ namespace JSC { int numArguments; getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); - if (callee->isObject(&JSFunction::info)) - d->numParameters = JSC::asFunction(callee)->body()->parameterCount(); + if (callee->inherits(&JSFunction::info)) + d->numParameters = JSC::asFunction(callee)->jsExecutable()->parameterCount(); else d->numParameters = 0; d->firstParameterIndex = firstParameterIndex; @@ -177,8 +179,8 @@ namespace JSC { : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) , d(new ArgumentsData) { - if (callFrame->callee() && callFrame->callee()->isObject(&JSC::JSFunction::info)) - ASSERT(!asFunction(callFrame->callee())->body()->parameterCount()); + if (callFrame->callee() && callFrame->callee()->inherits(&JSC::JSFunction::info)) + ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount()); unsigned numArguments = callFrame->argumentCount() - 1; @@ -193,7 +195,7 @@ namespace JSC { extraArguments = d->extraArgumentsFixedBuffer; Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1; - if (callFrame->callee() && !callFrame->callee()->isObject(&JSC::JSFunction::info)) + if (callFrame->callee() && !callFrame->callee()->inherits(&JSC::JSFunction::info)) ++argv; // ### off-by-one issue with native functions for (unsigned i = 0; i < numArguments; ++i) extraArguments[i] = argv[i]; @@ -226,8 +228,8 @@ namespace JSC { { ASSERT(!d()->registerArray); - size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; - size_t numVars = d()->functionBody->generatedBytecode().m_numVars; + size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1; + size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars; size_t numLocals = numVars + numParametersMinusThis; if (!numLocals) @@ -242,6 +244,14 @@ namespace JSC { static_cast<Arguments*>(arguments)->setActivation(this); } + ALWAYS_INLINE Arguments* Register::arguments() const + { + if (jsValue() == JSValue()) + return 0; + return asArguments(jsValue()); + } + + } // namespace JSC #endif // Arguments_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp index e96bdfc..c60cb0e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -25,15 +25,19 @@ #include "ArrayConstructor.h" #include "ArrayPrototype.h" +#include "Error.h" #include "JSArray.h" #include "JSFunction.h" #include "Lookup.h" +#include "PrototypeFunction.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor); + +static JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList&); -ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype) +ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure) : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className)) { // ECMA 15.4.3.1 Array.prototype @@ -41,6 +45,9 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> struct // no. of arguments for constructor putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete); + + // ES5 + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum); } static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) @@ -82,4 +89,9 @@ CallType ArrayConstructor::getCallData(CallData& callData) return CallTypeHost; } +JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList& args) +{ + return jsBoolean(args.at(0).inherits(&JSArray::info)); +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h index 8300d8c..2b79510 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ArrayConstructor : public InternalFunction { public: - ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*); + ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*, Structure*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp index 807e59a..e1b1f34 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -67,7 +67,7 @@ static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JS namespace JSC { -static inline bool isNumericCompareFunction(CallType callType, const CallData& callData) +static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData& callData) { if (callType != CallTypeJS) return false; @@ -75,10 +75,10 @@ static inline bool isNumericCompareFunction(CallType callType, const CallData& c #if ENABLE(JIT) // If the JIT is enabled then we need to preserve the invariant that every // function with a CodeBlock also has JIT code. - callData.js.functionBody->jitCode(callData.js.scopeChain); - CodeBlock& codeBlock = callData.js.functionBody->generatedBytecode(); + callData.js.functionExecutable->jitCode(exec, callData.js.scopeChain); + CodeBlock& codeBlock = callData.js.functionExecutable->generatedBytecode(); #else - CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain); + CodeBlock& codeBlock = callData.js.functionExecutable->bytecode(exec, callData.js.scopeChain); #endif return codeBlock.isNumericCompareFunction(); @@ -125,6 +125,11 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot); } +bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, descriptor); +} + // ------------------------------ Array Functions ---------------------------- // Helper function @@ -144,7 +149,7 @@ static void putProperty(ExecState* exec, JSObject* obj, const Identifier& proper JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&JSArray::info)) + if (!thisValue.inherits(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); @@ -190,7 +195,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&JSArray::info)) + if (!thisValue.inherits(&JSArray::info)) return throwError(exec, TypeError); JSObject* thisObj = asArray(thisValue); @@ -298,7 +303,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue t ArgList::const_iterator it = args.begin(); ArgList::const_iterator end = args.end(); while (1) { - if (curArg.isObject(&JSArray::info)) { + if (curArg.inherits(&JSArray::info)) { unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec); JSObject* curObject = curArg.toObject(exec); for (unsigned k = 0; k < length; ++k) { @@ -456,7 +461,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thi CallType callType = function.getCallData(callData); if (thisObj->classInfo() == &JSArray::info) { - if (isNumericCompareFunction(callType, callData)) + if (isNumericCompareFunction(exec, callType, callData)) asArray(thisObj)->sortNumeric(exec, function, callType, callData); else if (callType != CallTypeNone) asArray(thisObj)->sort(exec, function, callType, callData); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h index 2165089..6f7ed12 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h @@ -31,6 +31,7 @@ namespace JSC { explicit ArrayPrototype(PassRefPtr<Structure>); bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index b9f738f..929a5e7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -38,7 +38,7 @@ namespace JSC { : m_object(object) { if (!m_object->structure()->isDictionary()) - m_object->setStructure(Structure::toDictionaryTransition(m_object->structure())); + m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure())); } ~BatchedTransitionOptimizer() diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h index cfd55fe..5f3e5f0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h @@ -31,6 +31,11 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + } }; BooleanObject* asBooleanObject(JSValue); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp index 703a568..cf4fbd7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -59,7 +59,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSVal if (thisValue == jsBoolean(true)) return jsNontrivialString(exec, "true"); - if (!thisValue.isObject(&BooleanObject::info)) + if (!thisValue.inherits(&BooleanObject::info)) return throwError(exec, TypeError); if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false)) @@ -74,7 +74,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValu if (thisValue.isBoolean()) return thisValue; - if (!thisValue.isObject(&BooleanObject::info)) + if (!thisValue.inherits(&BooleanObject::info)) return throwError(exec, TypeError); return asBooleanObject(thisValue)->internalValue(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h index 541779c..ef4988b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h @@ -35,7 +35,7 @@ namespace JSC { class ArgList; class ExecState; - class FunctionBodyNode; + class FunctionExecutable; class JSObject; class JSValue; class ScopeChainNode; @@ -79,7 +79,7 @@ namespace JSC { #endif } native; struct { - FunctionBodyNode* functionBody; + FunctionExecutable* functionExecutable; ScopeChainNode* scopeChain; } js; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ClassInfo.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ClassInfo.h index 097fb09..acec4e7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ClassInfo.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ClassInfo.h @@ -27,7 +27,7 @@ namespace JSC { - struct HashEntry; + class HashEntry; struct HashTable; struct ClassInfo { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp index d7fbce8..3784da8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel <eric@webkit.org> * * This library is free software; you can redistribute it and/or @@ -23,16 +23,20 @@ #include "ArgList.h" #include "CallFrame.h" +#include "CodeBlock.h" #include "CollectorHeapIterator.h" #include "Interpreter.h" +#include "JSArray.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "JSONObject.h" #include "JSString.h" #include "JSValue.h" +#include "MarkStack.h" #include "Nodes.h" #include "Tracing.h" #include <algorithm> +#include <limits.h> #include <setjmp.h> #include <stdlib.h> #include <wtf/FastMalloc.h> @@ -56,28 +60,19 @@ #elif PLATFORM(WIN_OS) #include <windows.h> +#include <malloc.h> + +#elif PLATFORM(HAIKU) + +#include <OS.h> #elif PLATFORM(UNIX) #include <stdlib.h> +#if !PLATFORM(HAIKU) #include <sys/mman.h> -#include <unistd.h> - -#if defined(QT_LINUXBASE) -#include <dlfcn.h> -#endif - -#if defined(__UCLIBC__) -// versions of uClibc 0.9.28 and below do not have -// pthread_getattr_np or pthread_attr_getstack. -#if __UCLIBC_MAJOR__ == 0 && \ - (__UCLIBC_MINOR__ < 9 || \ - (__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ <= 30)) -#define UCLIBC_USE_PROC_SELF_MAPS 1 -#include <stdio_ext.h> -extern int *__libc_stack_end; -#endif #endif +#include <unistd.h> #if PLATFORM(SOLARIS) #include <thread.h> @@ -98,7 +93,6 @@ extern int *__libc_stack_end; #endif -#define DEBUG_COLLECTOR 0 #define COLLECT_ON_EVERY_ALLOCATION 0 using std::max; @@ -107,7 +101,6 @@ namespace JSC { // tunable parameters -const size_t SPARE_EMPTY_BLOCKS = 2; const size_t GROWTH_FACTOR = 2; const size_t LOW_WATER_FACTOR = 4; const size_t ALLOCATIONS_PER_COLLECTION = 4000; @@ -120,8 +113,6 @@ const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB static RHeap* userChunk = 0; #endif -static void freeHeap(CollectorHeap*); - #if ENABLE(JSC_MULTIPLE_THREADS) #if PLATFORM(DARWIN) @@ -210,8 +201,8 @@ void Heap::destroy() ASSERT(!primaryHeap.numLiveObjects); - freeHeap(&primaryHeap); - freeHeap(&numberHeap); + freeBlocks(&primaryHeap); + freeBlocks(&numberHeap); #if ENABLE(JSC_MULTIPLE_THREADS) if (m_currentThreadRegistrar) { @@ -231,7 +222,7 @@ void Heap::destroy() } template <HeapType heapType> -static NEVER_INLINE CollectorBlock* allocateBlock() +NEVER_INLINE CollectorBlock* Heap::allocateBlock() { // Disable the use of vm_map for the Qt build on Darwin, because when compiled on 10.4 // it crashes on 10.5 @@ -247,9 +238,15 @@ static NEVER_INLINE CollectorBlock* allocateBlock() uintptr_t address = reinterpret_cast<uintptr_t>(mask); memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE); +#elif PLATFORM(WINCE) + void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #elif PLATFORM(WIN_OS) - // windows virtual address granularity is naturally 64k - LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); +#if COMPILER(MINGW) + void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); +#else + void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); +#endif + memset(address, 0, BLOCK_SIZE); #elif HAVE(POSIX_MEMALIGN) void* address; posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE); @@ -281,11 +278,45 @@ static NEVER_INLINE CollectorBlock* allocateBlock() address += adjust; memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE); #endif - reinterpret_cast<CollectorBlock*>(address)->type = heapType; - return reinterpret_cast<CollectorBlock*>(address); + + CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address); + block->freeList = block->cells; + block->heap = this; + block->type = heapType; + + CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; + size_t numBlocks = heap.numBlocks; + if (heap.usedBlocks == numBlocks) { + static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR; + if (numBlocks > maxNumBlocks) + CRASH(); + numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); + heap.numBlocks = numBlocks; + heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*))); + } + heap.blocks[heap.usedBlocks++] = block; + + return block; +} + +template <HeapType heapType> +NEVER_INLINE void Heap::freeBlock(size_t block) +{ + CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; + + freeBlock(heap.blocks[block]); + + // swap with the last block so we compact as we go + heap.blocks[block] = heap.blocks[heap.usedBlocks - 1]; + heap.usedBlocks--; + + if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) { + heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; + heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*))); + } } -static void freeBlock(CollectorBlock* block) +NEVER_INLINE void Heap::freeBlock(CollectorBlock* block) { // Disable the use of vm_deallocate for the Qt build on Darwin, because when compiled on 10.4 // it crashes on 10.5 @@ -293,8 +324,14 @@ static void freeBlock(CollectorBlock* block) vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE); #elif PLATFORM(SYMBIAN) userChunk->Free(reinterpret_cast<TAny*>(block)); -#elif PLATFORM(WIN_OS) +#elif PLATFORM(WINCE) VirtualFree(block, 0, MEM_RELEASE); +#elif PLATFORM(WIN_OS) +#if COMPILER(MINGW) + __mingw_aligned_free(block); +#else + _aligned_free(block); +#endif #elif HAVE(POSIX_MEMALIGN) free(block); #else @@ -302,7 +339,7 @@ static void freeBlock(CollectorBlock* block) #endif } -static void freeHeap(CollectorHeap* heap) +void Heap::freeBlocks(CollectorHeap* heap) { for (size_t i = 0; i < heap->usedBlocks; ++i) if (heap->blocks[i]) @@ -395,38 +432,23 @@ collect: #ifndef NDEBUG heap.operationInProgress = NoOperation; #endif - bool collected = collect(); + bool foundGarbage = collect(); + numLiveObjects = heap.numLiveObjects; + usedBlocks = heap.usedBlocks; + i = heap.firstBlockWithPossibleSpace; #ifndef NDEBUG heap.operationInProgress = Allocation; #endif - if (collected) { - numLiveObjects = heap.numLiveObjects; - usedBlocks = heap.usedBlocks; - i = heap.firstBlockWithPossibleSpace; + if (foundGarbage) goto scan; - } - } - - // didn't find a block, and GC didn't reclaim anything, need to allocate a new block - size_t numBlocks = heap.numBlocks; - if (usedBlocks == numBlocks) { - static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR; - if (numBlocks > maxNumBlocks) - CRASH(); - numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); - heap.numBlocks = numBlocks; - heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*))); } + // didn't find a block, and GC didn't reclaim anything, need to allocate a new block targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>()); - targetBlock->freeList = targetBlock->cells; - targetBlock->heap = this; + heap.firstBlockWithPossibleSpace = heap.usedBlocks - 1; targetBlockUsedCells = 0; - heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock); - heap.usedBlocks = usedBlocks + 1; - heap.firstBlockWithPossibleSpace = usedBlocks; } - + // find a free spot in the block and detach it from the free list Cell* newCell = targetBlock->freeList; @@ -554,6 +576,33 @@ static void *hpux_get_stack_base() } #endif +#if PLATFORM(QNX) +static inline void *currentThreadStackBaseQNX() +{ + static void* stackBase = 0; + static size_t stackSize = 0; + static pthread_t stackThread; + pthread_t thread = pthread_self(); + if (stackBase == 0 || thread != stackThread) { + struct _debug_thread_info threadInfo; + memset(&threadInfo, 0, sizeof(threadInfo)); + threadInfo.tid = pthread_self(); + int fd = open("/proc/self", O_RDONLY); + if (fd == -1) { + LOG_ERROR("Unable to open /proc/self (errno: %d)", errno); + return 0; + } + devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0); + close(fd); + stackBase = reinterpret_cast<void*>(threadInfo.stkbase); + stackSize = threadInfo.stksize; + ASSERT(stackBase); + stackThread = thread; + } + return static_cast<char*>(stackBase) + stackSize; +} +#endif + static inline void* currentThreadStackBase() { #if PLATFORM(DARWIN) @@ -579,6 +628,8 @@ static inline void* currentThreadStackBase() : "=r" (pTib) ); return static_cast<void*>(pTib->StackBase); +#elif PLATFORM(QNX) + return currentThreadStackBaseQNX(); #elif PLATFORM(HPUX) return hpux_get_stack_base(); #elif PLATFORM(SOLARIS) @@ -611,77 +662,21 @@ static inline void* currentThreadStackBase() stackBase = (void*)info.iBase; } return (void*)stackBase; +#elif PLATFORM(HAIKU) + thread_info threadInfo; + get_thread_info(find_thread(NULL), &threadInfo); + return threadInfo.stack_end; #elif PLATFORM(UNIX) -#ifdef UCLIBC_USE_PROC_SELF_MAPS - // Read /proc/self/maps and locate the line whose address - // range contains __libc_stack_end. - FILE *file = fopen("/proc/self/maps", "r"); - if (!file) - return 0; - __fsetlocking(file, FSETLOCKING_BYCALLER); - char *line = NULL; - size_t lineLen = 0; - while (!feof_unlocked(file)) { - if (getdelim(&line, &lineLen, '\n', file) <= 0) - break; - - long from; - long to; - if (sscanf (line, "%lx-%lx", &from, &to) != 2) - continue; - if (from <= (long)__libc_stack_end && (long)__libc_stack_end < to) { - fclose(file); - free(line); -#ifdef _STACK_GROWS_UP - return (void *)from; -#else - return (void *)to; -#endif - } - } - fclose(file); - free(line); - return 0; -#else static void* stackBase = 0; static size_t stackSize = 0; static pthread_t stackThread; pthread_t thread = pthread_self(); if (stackBase == 0 || thread != stackThread) { -#if PLATFORM(QNX) - int fd; - struct _debug_thread_info tinfo; - memset(&tinfo, 0, sizeof(tinfo)); - tinfo.tid = pthread_self(); - fd = open("/proc/self", O_RDONLY); - if (fd == -1) { -#ifndef NDEBUG - perror("Unable to open /proc/self:"); -#endif - return 0; - } - devctl(fd, DCMD_PROC_TIDSTATUS, &tinfo, sizeof(tinfo), NULL); - close(fd); - stackBase = (void*)tinfo.stkbase; - stackSize = tinfo.stksize; - ASSERT(stackBase); -#else -#if defined(QT_LINUXBASE) - // LinuxBase is missing pthread_getattr_np - resolve it once at runtime instead - // see http://bugs.linuxbase.org/show_bug.cgi?id=2364 - typedef int (*GetAttrPtr)(pthread_t, pthread_attr_t *); - static int (*pthread_getattr_np_ptr)(pthread_t, pthread_attr_t *) = 0; - if (!pthread_getattr_np_ptr) - *(void **)&pthread_getattr_np_ptr = dlsym(RTLD_DEFAULT, "pthread_getattr_np"); -#endif pthread_attr_t sattr; pthread_attr_init(&sattr); #if HAVE(PTHREAD_NP_H) || PLATFORM(NETBSD) // e.g. on FreeBSD 5.4, neundorf@kde.org pthread_attr_get_np(thread, &sattr); -#elif defined(QT_LINUXBASE) - if (pthread_getattr_np_ptr) - pthread_getattr_np_ptr(thread, &sattr); #else // FIXME: this function is non-portable; other POSIX systems may have different np alternatives pthread_getattr_np(thread, &sattr); @@ -690,11 +685,9 @@ static inline void* currentThreadStackBase() (void)rc; // FIXME: Deal with error code somehow? Seems fatal. ASSERT(stackBase); pthread_attr_destroy(&sattr); -#endif stackThread = thread; } return static_cast<char*>(stackBase) + stackSize; -#endif #elif PLATFORM(WINCE) if (g_stackBase) return g_stackBase; @@ -731,6 +724,8 @@ void Heap::makeUsableFromMultipleThreads() void Heap::registerThread() { + ASSERT(!m_globalData->mainThreadOnly || isMainThread()); + if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) return; @@ -787,7 +782,7 @@ void Heap::registerThread() // cell size needs to be a power of two for this to be valid #define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0) -void Heap::markConservatively(void* start, void* end) +void Heap::markConservatively(MarkStack& markStack, void* start, void* end) { if (start > end) { void* tmp = start; @@ -827,10 +822,9 @@ void Heap::markConservatively(void* start, void* end) // Mark the primary heap for (size_t block = 0; block < usedPrimaryBlocks; block++) { if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) { - if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) { - JSCell* imp = reinterpret_cast<JSCell*>(xAsBits); - if (!imp->marked()) - imp->mark(); + if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree) { + markStack.append(reinterpret_cast<JSCell*>(xAsBits)); + markStack.drain(); } break; } @@ -841,15 +835,15 @@ void Heap::markConservatively(void* start, void* end) } } -void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal() +void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack) { void* dummy; void* stackPointer = &dummy; void* stackBase = currentThreadStackBase(); - markConservatively(stackPointer, stackBase); + markConservatively(markStack, stackPointer, stackBase); } -void Heap::markCurrentThreadConservatively() +void Heap::markCurrentThreadConservatively(MarkStack& markStack) { // setjmp forces volatile registers onto the stack jmp_buf registers; @@ -862,7 +856,7 @@ void Heap::markCurrentThreadConservatively() #pragma warning(pop) #endif - markCurrentThreadConservativelyInternal(); + markCurrentThreadConservativelyInternal(markStack); } #if ENABLE(JSC_MULTIPLE_THREADS) @@ -994,7 +988,7 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) #endif } -void Heap::markOtherThreadConservatively(Thread* thread) +void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread) { suspendThread(thread->platformThread); @@ -1002,19 +996,19 @@ void Heap::markOtherThreadConservatively(Thread* thread) size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); // mark the thread's registers - markConservatively(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + markConservatively(markStack, static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); void* stackPointer = otherThreadStackPointer(regs); - markConservatively(stackPointer, thread->stackBase); + markConservatively(markStack, stackPointer, thread->stackBase); resumeThread(thread->platformThread); } #endif -void Heap::markStackObjectsConservatively() +void Heap::markStackObjectsConservatively(MarkStack& markStack) { - markCurrentThreadConservatively(); + markCurrentThreadConservatively(markStack); #if ENABLE(JSC_MULTIPLE_THREADS) @@ -1024,7 +1018,7 @@ void Heap::markStackObjectsConservatively() #ifndef NDEBUG // Forbid malloc during the mark phase. Marking a thread suspends it, so - // a malloc inside mark() would risk a deadlock with a thread that had been + // a malloc inside markChildren() would risk a deadlock with a thread that had been // suspended while holding the malloc lock. fastMallocForbid(); #endif @@ -1032,7 +1026,7 @@ void Heap::markStackObjectsConservatively() // and since this is a shared heap, they are real locks. for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { if (!pthread_equal(thread->posixThread, pthread_self())) - markOtherThreadConservatively(thread); + markOtherThreadConservatively(markStack, thread); } #ifndef NDEBUG fastMallocAllow(); @@ -1085,23 +1079,15 @@ void Heap::unprotect(JSValue k) m_protectedValuesMutex->unlock(); } -Heap* Heap::heap(JSValue v) -{ - if (!v.isCell()) - return 0; - return Heap::cellBlock(v.asCell())->heap; -} - -void Heap::markProtectedObjects() +void Heap::markProtectedObjects(MarkStack& markStack) { if (m_protectedValuesMutex) m_protectedValuesMutex->lock(); ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) { - JSCell* val = it->first; - if (!val->marked()) - val->mark(); + markStack.append(it->first); + markStack.drain(); } if (m_protectedValuesMutex) @@ -1179,34 +1165,37 @@ template <HeapType heapType> size_t Heap::sweep() curBlock->freeList = freeList; curBlock->marked.clearAll(); - if (usedCells == 0) { - emptyBlocks++; - if (emptyBlocks > SPARE_EMPTY_BLOCKS) { -#if !DEBUG_COLLECTOR - freeBlock(reinterpret_cast<CollectorBlock*>(curBlock)); -#endif - // swap with the last block so we compact as we go - heap.blocks[block] = heap.blocks[heap.usedBlocks - 1]; - heap.usedBlocks--; - block--; // Don't move forward a step in this case - - if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) { - heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; - heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*))); - } - } - } + if (!usedCells) + ++emptyBlocks; } if (heap.numLiveObjects != numLiveObjects) heap.firstBlockWithPossibleSpace = 0; - + heap.numLiveObjects = numLiveObjects; heap.numLiveObjectsAtLastCollect = numLiveObjects; heap.extraCost = 0; + + if (!emptyBlocks) + return numLiveObjects; + + size_t neededCells = 1.25f * (numLiveObjects + max(ALLOCATIONS_PER_COLLECTION, numLiveObjects)); + size_t neededBlocks = (neededCells + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock; + for (size_t block = 0; block < heap.usedBlocks; block++) { + if (heap.usedBlocks <= neededBlocks) + break; + + Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]); + if (curBlock->usedCells) + continue; + + freeBlock<heapType>(block); + block--; // Don't move forward a step in this case + } + return numLiveObjects; } - + bool Heap::collect() { #ifndef NDEBUG @@ -1225,24 +1214,26 @@ bool Heap::collect() numberHeap.operationInProgress = Collection; // MARK: first mark all referenced objects recursively starting out from the set of root objects - - markStackObjectsConservatively(); - markProtectedObjects(); + MarkStack& markStack = m_globalData->markStack; + markStackObjectsConservatively(markStack); + markProtectedObjects(markStack); #if QT_BUILD_SCRIPT_LIB if (m_globalData->clientData) - m_globalData->clientData->mark(); + m_globalData->clientData->mark(markStack); #endif if (m_markListSet && m_markListSet->size()) - MarkedArgumentBuffer::markLists(*m_markListSet); - if (m_globalData->exception && !m_globalData->exception.marked()) - m_globalData->exception.mark(); - m_globalData->interpreter->registerFile().markCallFrames(this); - m_globalData->smallStrings.mark(); - if (m_globalData->scopeNodeBeingReparsed) - m_globalData->scopeNodeBeingReparsed->mark(); + MarkedArgumentBuffer::markLists(markStack, *m_markListSet); + if (m_globalData->exception) + markStack.append(m_globalData->exception); + m_globalData->interpreter->registerFile().markCallFrames(markStack, this); + m_globalData->smallStrings.markChildren(markStack); + if (m_globalData->functionCodeBlockBeingReparsed) + m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack); if (m_globalData->firstStringifierToMark) - JSONObject::markStringifiers(m_globalData->firstStringifierToMark); + JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); + markStack.drain(); + markStack.compact(); JAVASCRIPTCORE_GC_MARKED(); size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects; @@ -1332,12 +1323,14 @@ static const char* typeName(JSCell* cell) { if (cell->isString()) return "string"; +#if USE(JSVALUE32) if (cell->isNumber()) return "number"; +#endif if (cell->isGetterSetter()) return "gettersetter"; ASSERT(cell->isObject()); - const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo(); + const ClassInfo* info = cell->classInfo(); return info ? info->className : "Object"; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h index 852ac59..1a55bb5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h @@ -39,11 +39,12 @@ namespace JSC { - class MarkedArgumentBuffer; class CollectorBlock; class JSCell; class JSGlobalData; class JSValue; + class MarkedArgumentBuffer; + class MarkStack; enum OperationInProgress { NoOperation, Allocation, Collection }; enum HeapType { PrimaryHeap, NumberHeap }; @@ -100,6 +101,7 @@ namespace JSC { void unprotect(JSValue); static Heap* heap(JSValue); // 0 for immediate values + static Heap* heap(JSCell*); size_t globalObjectCount(); size_t protectedObjectCount(); @@ -111,7 +113,7 @@ namespace JSC { static bool isCellMarked(const JSCell*); static void markCell(JSCell*); - void markConservatively(void* start, void* end); + void markConservatively(MarkStack&, void* start, void* end); HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } @@ -132,12 +134,17 @@ namespace JSC { Heap(JSGlobalData*); ~Heap(); + template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock(); + template <HeapType heapType> NEVER_INLINE void freeBlock(size_t); + NEVER_INLINE void freeBlock(CollectorBlock*); + void freeBlocks(CollectorHeap*); + void recordExtraCost(size_t); - void markProtectedObjects(); - void markCurrentThreadConservatively(); - void markCurrentThreadConservativelyInternal(); - void markOtherThreadConservatively(Thread*); - void markStackObjectsConservatively(); + void markProtectedObjects(MarkStack&); + void markCurrentThreadConservatively(MarkStack&); + void markCurrentThreadConservativelyInternal(MarkStack&); + void markOtherThreadConservatively(MarkStack&, Thread*); + void markStackObjectsConservatively(MarkStack&); typedef HashCountedSet<JSCell*> ProtectCountSet; @@ -167,9 +174,18 @@ namespace JSC { template<size_t bytesPerWord> struct CellSize; // cell size needs to be a power of two for certain optimizations in collector.cpp - template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit - template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit - const size_t BLOCK_SIZE = 16 * 4096; // 64k +#if USE(JSVALUE32) + template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; +#else + template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 64; }; +#endif + template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; + +#if PLATFORM(WINCE) + const size_t BLOCK_SIZE = 64 * 1024; // 64k +#else + const size_t BLOCK_SIZE = 64 * 4096; // 256k +#endif // derived constants const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h index 7b275bd..abe5038 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h @@ -37,16 +37,26 @@ macro(callee) \ macro(caller) \ macro(compile) \ + macro(configurable) \ macro(constructor) \ + macro(create) \ + macro(defineProperty) \ + macro(defineProperties) \ + macro(enumerable) \ macro(eval) \ macro(exec) \ macro(fromCharCode) \ macro(global) \ + macro(get) \ + macro(getPrototypeOf) \ + macro(getOwnPropertyDescriptor) \ macro(hasOwnProperty) \ macro(ignoreCase) \ macro(index) \ macro(input) \ + macro(isArray) \ macro(isPrototypeOf) \ + macro(keys) \ macro(length) \ macro(message) \ macro(multiline) \ @@ -55,6 +65,7 @@ macro(parse) \ macro(propertyIsEnumerable) \ macro(prototype) \ + macro(set) \ macro(source) \ macro(test) \ macro(toExponential) \ @@ -65,7 +76,9 @@ macro(toPrecision) \ macro(toString) \ macro(UTC) \ + macro(value) \ macro(valueOf) \ + macro(writable) \ macro(displayName) namespace JSC { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp index 04c9a2e..b75a7a5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp @@ -33,11 +33,6 @@ #ifdef QT_BUILD_SCRIPT_LIB #include "DebuggerCallFrame.h" -#include "SourcePoolQt.h" -#endif - -#if !PLATFORM(WIN_OS) -#include <unistd.h> #endif namespace JSC { @@ -46,33 +41,27 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) { JSLock lock(exec); - int errLine; - UString errMsg; + ProgramExecutable program(source); + JSObject* error = program.checkSyntax(exec); + if (error) + return Completion(Throw, error); - RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (!progNode) - return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url())); return Completion(Normal); } Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue) { JSLock lock(exec); - - intptr_t sourceId = source.provider()->asID(); - int errLine; - UString errMsg; - RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (!programNode) { - JSValue error = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, source.provider()->url()); + ProgramExecutable program(source); + JSObject* error = program.compile(exec, scopeChain.node()); + if (error) return Completion(Throw, error); - } JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSValue exception; - JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception); + JSValue result = exec->interpreter()->execute(&program, exec, scopeChain.node(), thisObj, &exception); if (exception) { if (exception.isObject() && asObject(exception)->isWatchdogException()) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h index 477399c..1dcfb00 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h @@ -33,7 +33,7 @@ namespace JSC { class ArgList; class ExecState; - class FunctionBodyNode; + class FunctionExecutable; class JSObject; class JSValue; class ScopeChainNode; @@ -84,7 +84,7 @@ namespace JSC { #endif } native; struct { - FunctionBodyNode* functionBody; + FunctionExecutable* functionExecutable; ScopeChainNode* scopeChain; } js; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp index 6d7d934..1879c3f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp @@ -36,7 +36,7 @@ #include <wtf/MathExtras.h> #if PLATFORM(WINCE) && !PLATFORM(QT) -extern "C" time_t time(time_t* timer); //provided by libce +extern "C" time_t time(time_t* timer); // Provided by libce. #endif #if HAVE(SYS_TIME_H) @@ -51,8 +51,6 @@ using namespace WTF; namespace JSC { -// TODO: MakeTime (15.9.11.1) etc. ? - ASSERT_CLASS_FITS_IN_CELL(DateConstructor); static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&); @@ -81,7 +79,7 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) if (numArgs == 0) // new Date() ECMA 15.9.3.3 value = getCurrentUTCTime(); else if (numArgs == 1) { - if (args.at(0).isObject(&DateInstance::info)) + if (args.at(0).inherits(&DateInstance::info)) value = asDateInstance(args.at(0))->internalNumber(); else { JSValue primitive = args.at(0).toPrimitive(exec); @@ -100,17 +98,17 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) || (numArgs >= 7 && isnan(args.at(6).toNumber(exec)))) value = NaN; else { - GregorianDateTime t; - int year = args.at(0).toInt32(exec); - t.year = (year >= 0 && year <= 99) ? year : year - 1900; - t.month = args.at(1).toInt32(exec); - t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1; - t.hour = args.at(3).toInt32(exec); - t.minute = args.at(4).toInt32(exec); - t.second = args.at(5).toInt32(exec); - t.isDST = -1; - double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0; - value = gregorianDateTimeToMS(t, ms, false); + GregorianDateTime t; + int year = args.at(0).toInt32(exec); + t.year = (year >= 0 && year <= 99) ? year : year - 1900; + t.month = args.at(1).toInt32(exec); + t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1; + t.hour = args.at(3).toInt32(exec); + t.minute = args.at(4).toInt32(exec); + t.second = args.at(5).toInt32(exec); + t.isDST = -1; + double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0; + value = gregorianDateTimeToMS(t, ms, false); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp index e2482f4..c6f7dec 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp @@ -198,8 +198,8 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L { #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; -#elif PLATFORM(WINCE) && !PLATFORM(QT) - // strftime() we are using does not support # +#elif (PLATFORM(WINCE) && !PLATFORM(QT)) || PLATFORM(SYMBIAN) + // strftime() does not support '#' on WinCE or Symbian static const char* const formatStrings[] = { "%c", "%x", "%X" }; #else static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; @@ -407,11 +407,17 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot); } + +bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor); +} + // Functions JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -428,7 +434,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -445,7 +451,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -457,17 +463,17 @@ JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSVal GregorianDateTime t; thisDateObj->msToGregorianDateTime(milli, utc, t); - // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) - // 6 for formatting and one for null termination = 23. We add one extra character to allow us to force null termination. - char buffer[24]; - snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second); + // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) + // 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination. + char buffer[28]; + snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second, static_cast<int>(fmod(milli, 1000))); buffer[sizeof(buffer) - 1] = 0; return jsNontrivialString(exec, buffer); } JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -484,7 +490,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSVa JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -501,7 +507,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSVa JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -514,7 +520,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JS JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -527,7 +533,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -540,7 +546,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -553,7 +559,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue t JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -570,7 +576,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -587,7 +593,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JS JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -604,7 +610,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -621,7 +627,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -638,7 +644,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -655,7 +661,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue t JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -672,7 +678,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValu JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -689,7 +695,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue th JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -706,7 +712,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -723,7 +729,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -740,7 +746,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -757,7 +763,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValu JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -774,7 +780,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSV JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -791,7 +797,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValu JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = true; @@ -808,7 +814,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSV JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -823,7 +829,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, J JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -838,7 +844,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject* JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -855,7 +861,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -868,7 +874,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue t static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -899,7 +905,7 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); @@ -1020,7 +1026,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JS JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; @@ -1062,7 +1068,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&DateInstance::info)) + if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); const bool utc = false; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h index 5f4d0ec..12fabda 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h @@ -32,13 +32,14 @@ namespace JSC { DatePrototype(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultGetPropertyNames)); } }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.cpp index 1aa9034..c094b75 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.cpp @@ -97,6 +97,12 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const char* message) return create(exec, type, message, -1, -1, NULL); } +JSObject* throwError(ExecState* exec, JSObject* error) +{ + exec->setException(error); + return error; +} + JSObject* throwError(ExecState* exec, ErrorType type) { JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.h index fb864ee..d84b81b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Error.h @@ -59,6 +59,7 @@ namespace JSC { JSObject* throwError(ExecState*, ErrorType, const UString& message); JSObject* throwError(ExecState*, ErrorType, const char* message); JSObject* throwError(ExecState*, ErrorType); + JSObject* throwError(ExecState*, JSObject*); #ifdef QT_BUILD_SCRIPT_LIB # define JSC_ERROR_FILENAME_PROPERTYNAME "fileName" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp index e63594c..cc18b95 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -74,7 +74,7 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString message = "Can't find variable: "; message.append(ident.ustring()); - JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); + JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -136,7 +136,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -157,7 +157,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned by startPoint++; UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -171,7 +171,7 @@ JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecod int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -201,7 +201,7 @@ JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object"); - JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL()); + JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h index 09d99dc..4c5bec1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h @@ -29,20 +29,19 @@ #ifndef ExceptionHelpers_h #define ExceptionHelpers_h -#include "JSImmediate.h" namespace JSC { class CodeBlock; class ExecState; class Identifier; - class Instruction; class JSGlobalData; class JSNotAnObjectErrorStub; class JSObject; class JSValue; class Node; - + struct Instruction; + JSValue createInterruptedExecutionException(JSGlobalData*); JSValue createStackOverflowError(ExecState*); JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp new file mode 100644 index 0000000..5e79794 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "Executable.h" + +#include "BytecodeGenerator.h" +#include "CodeBlock.h" +#include "JIT.h" +#include "Parser.h" +#include "Vector.h" + +namespace JSC { + +#if ENABLE(JIT) +NativeExecutable::~NativeExecutable() +{ +} +#endif + +VPtrHackExecutable::~VPtrHackExecutable() +{ +} + +EvalExecutable::~EvalExecutable() +{ + delete m_evalCodeBlock; +} + +ProgramExecutable::~ProgramExecutable() +{ + delete m_programCodeBlock; +} + +FunctionExecutable::~FunctionExecutable() +{ + delete m_codeBlock; +} + +JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + int errLine; + UString errMsg; + RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg); + if (!evalNode) + return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url()); + recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine()); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + ASSERT(!m_evalCodeBlock); + m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()); + OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock)); + generator->generate(); + + evalNode->destroyData(); + return 0; +} + +JSObject* ProgramExecutable::checkSyntax(ExecState* exec) +{ + int errLine; + UString errMsg; + RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg); + if (!programNode) + return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url()); + return 0; +} + +JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + int errLine; + UString errMsg; + RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg); + if (!programNode) + return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url()); + recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine()); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + ASSERT(!m_programCodeBlock); + m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()); + OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock)); + generator->generate(); + + programNode->destroyData(); + return 0; +} + +void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode) +{ + JSGlobalData* globalData = scopeChainNode->globalData; + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); + if (m_forceUsesArguments) + body->setUsesArguments(); + body->finishParsing(m_parameters, m_name); + recordParse(body->features(), body->lineNo(), body->lastLine()); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + ASSERT(!m_codeBlock); + m_codeBlock = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()); + OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlock->symbolTable(), m_codeBlock)); + generator->generate(); + m_numParameters = m_codeBlock->m_numParameters; + ASSERT(m_numParameters); + m_numVariables = m_codeBlock->m_numVars; + + body->destroyData(); +} + +#if ENABLE(JIT) + +void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(exec, scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(exec, scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(exec, scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +#endif + +void FunctionExecutable::markAggregate(MarkStack& markStack) +{ + if (m_codeBlock) + m_codeBlock->markAggregate(markStack); +} + +ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +{ + RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); + if (m_forceUsesArguments) + newFunctionBody->setUsesArguments(); + newFunctionBody->finishParsing(m_parameters, m_name); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset())); + globalData->functionCodeBlockBeingReparsed = newCodeBlock.get(); + + OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())); + generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock)); + generator->generate(); + + ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount()); + +#if ENABLE(JIT) + JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get()); + ASSERT(newJITCode.size() == generatedJITCode().size()); +#endif + + globalData->functionCodeBlockBeingReparsed = 0; + + return newCodeBlock->extractExceptionInfo(); +} + +ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) +{ + RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source); + + ScopeChain scopeChain(scopeChainNode); + JSGlobalObject* globalObject = scopeChain.globalObject(); + + OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); + + OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())); + generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock)); + generator->generate(); + + ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount()); + +#if ENABLE(JIT) + JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get()); + ASSERT(newJITCode.size() == generatedJITCode().size()); +#endif + + return newCodeBlock->extractExceptionInfo(); +} + +void FunctionExecutable::recompile(ExecState*) +{ + delete m_codeBlock; + m_codeBlock = 0; + m_numParameters = NUM_PARAMETERS_NOT_COMPILED; +#if ENABLE(JIT) + m_jitCode = JITCode(); +#endif +} + +PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg) +{ + RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg); + if (!program) + return 0; + + StatementNode* exprStatement = program->singleStatement(); + ASSERT(exprStatement); + ASSERT(exprStatement->isExprStatement()); + if (!exprStatement || !exprStatement->isExprStatement()) + return 0; + + ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); + ASSERT(funcExpr); + ASSERT(funcExpr->isFuncExprNode()); + if (!funcExpr || !funcExpr->isFuncExprNode()) + return 0; + + FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); + ASSERT(body); + return FunctionExecutable::create(functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); +} + +UString FunctionExecutable::paramString() const +{ + FunctionParameters& parameters = *m_parameters; + UString s(""); + for (size_t pos = 0; pos < parameters.size(); ++pos) { + if (!s.isEmpty()) + s += ", "; + s += parameters[pos].ustring(); + } + + return s; +} + +}; + + diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h new file mode 100644 index 0000000..f3003dd --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#ifndef Executable_h +#define Executable_h + +#include "JSFunction.h" +#include "Nodes.h" + +namespace JSC { + + class CodeBlock; + class Debugger; + class EvalCodeBlock; + class ProgramCodeBlock; + class ScopeChainNode; + + struct ExceptionInfo; + + class ExecutableBase : public RefCounted<ExecutableBase> { + friend class JIT; + + protected: + static const int NUM_PARAMETERS_IS_HOST = 0; + static const int NUM_PARAMETERS_NOT_COMPILED = -1; + + public: + ExecutableBase(int numParameters) + : m_numParameters(numParameters) + { + } + + virtual ~ExecutableBase() {} + + bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; } + + protected: + int m_numParameters; + +#if ENABLE(JIT) + public: + JITCode& generatedJITCode() + { + ASSERT(m_jitCode); + return m_jitCode; + } + + ExecutablePool* getExecutablePool() + { + return m_jitCode.getExecutablePool(); + } + + protected: + JITCode m_jitCode; +#endif + }; + +#if ENABLE(JIT) + class NativeExecutable : public ExecutableBase { + public: + NativeExecutable(ExecState* exec) + : ExecutableBase(NUM_PARAMETERS_IS_HOST) + { + m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk())); + } + + ~NativeExecutable(); + }; +#endif + + class VPtrHackExecutable : public ExecutableBase { + public: + VPtrHackExecutable() + : ExecutableBase(NUM_PARAMETERS_IS_HOST) + { + } + + ~VPtrHackExecutable(); + }; + + class ScriptExecutable : public ExecutableBase { + public: + ScriptExecutable(const SourceCode& source) + : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) + , m_source(source) + , m_features(0) + { + } + + const SourceCode& source() { return m_source; } + intptr_t sourceID() const { return m_source.provider()->asID(); } + const UString& sourceURL() const { return m_source.provider()->url(); } + int lineNo() const { return m_firstLine; } + int lastLine() const { return m_lastLine; } + + bool usesEval() const { return m_features & EvalFeature; } + bool usesArguments() const { return m_features & ArgumentsFeature; } + bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); } + + virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0; + + protected: + void recordParse(CodeFeatures features, int firstLine, int lastLine) + { + m_features = features; + m_firstLine = firstLine; + m_lastLine = lastLine; + } + + SourceCode m_source; + CodeFeatures m_features; + int m_firstLine; + int m_lastLine; + }; + + class EvalExecutable : public ScriptExecutable { + public: + EvalExecutable(const SourceCode& source) + : ScriptExecutable(source) + , m_evalCodeBlock(0) + { + } + + ~EvalExecutable(); + + EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + if (!m_evalCodeBlock) { + JSObject* error = compile(exec, scopeChainNode); + ASSERT_UNUSED(!error, error); + } + return *m_evalCodeBlock; + } + + JSObject* compile(ExecState*, ScopeChainNode*); + + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + static PassRefPtr<EvalExecutable> create(const SourceCode& source) { return adoptRef(new EvalExecutable(source)); } + + private: + EvalCodeBlock* m_evalCodeBlock; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(exec, scopeChainNode); + return m_jitCode; + } + + private: + void generateJITCode(ExecState*, ScopeChainNode*); +#endif + }; + + class ProgramExecutable : public ScriptExecutable { + public: + ProgramExecutable(const SourceCode& source) + : ScriptExecutable(source) + , m_programCodeBlock(0) + { + } + + ~ProgramExecutable(); + + ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + if (!m_programCodeBlock) { + JSObject* error = compile(exec, scopeChainNode); + ASSERT_UNUSED(!error, error); + } + return *m_programCodeBlock; + } + + JSObject* checkSyntax(ExecState*); + JSObject* compile(ExecState*, ScopeChainNode*); + + // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information. + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; } + + private: + ProgramCodeBlock* m_programCodeBlock; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(exec, scopeChainNode); + return m_jitCode; + } + + private: + void generateJITCode(ExecState*, ScopeChainNode*); +#endif + }; + + class FunctionExecutable : public ScriptExecutable { + friend class JIT; + public: + static PassRefPtr<FunctionExecutable> create(const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + { + return adoptRef(new FunctionExecutable(name, source, forceUsesArguments, parameters, firstLine, lastLine)); + } + + ~FunctionExecutable(); + + JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain) + { + return new (exec) JSFunction(exec, this, scopeChain); + } + + CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + ASSERT(scopeChainNode); + if (!m_codeBlock) + compile(exec, scopeChainNode); + return *m_codeBlock; + } + + bool isGenerated() const + { + return m_codeBlock; + } + + CodeBlock& generatedBytecode() + { + ASSERT(m_codeBlock); + return *m_codeBlock; + } + + const Identifier& name() { return m_name; } + size_t parameterCount() const { return m_parameters->size(); } + size_t variableCount() const { return m_numVariables; } + UString paramString() const; + UString parameterName(int i) const { return (*m_parameters)[i].ustring(); } + + void recompile(ExecState*); + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + void markAggregate(MarkStack& markStack); + static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0); + + private: + FunctionExecutable(const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + : ScriptExecutable(source) + , m_forceUsesArguments(forceUsesArguments) + , m_parameters(parameters) + , m_codeBlock(0) + , m_name(name) + , m_numVariables(0) + { + m_firstLine = firstLine; + m_lastLine = lastLine; + } + + void compile(ExecState*, ScopeChainNode*); + + bool m_forceUsesArguments; + RefPtr<FunctionParameters> m_parameters; + CodeBlock* m_codeBlock; + Identifier m_name; + size_t m_numVariables; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(exec, scopeChainNode); + return m_jitCode; + } + + private: + void generateJITCode(ExecState*, ScopeChainNode*); +#endif + }; + + inline FunctionExecutable* JSFunction::jsExecutable() const + { + ASSERT(!isHostFunctionNonInline()); + return static_cast<FunctionExecutable*>(m_executable.get()); + } + + inline bool JSFunction::isHostFunction() const + { + ASSERT(m_executable); + return m_executable->isHostFunction(); + } + +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp index f4f5cc8..d5eb20f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -66,32 +66,6 @@ CallType FunctionConstructor::getCallData(CallData& callData) return CallTypeHost; } -FunctionBodyNode* extractFunctionBody(ProgramNode* program) -{ - if (!program) - return 0; - - StatementVector& children = program->children(); - if (children.size() != 1) - return 0; - - StatementNode* exprStatement = children[0]; - ASSERT(exprStatement); - ASSERT(exprStatement->isExprStatement()); - if (!exprStatement || !exprStatement->isExprStatement()) - return 0; - - ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); - ASSERT(funcExpr); - ASSERT(funcExpr->isFuncExprNode()); - if (!funcExpr || !funcExpr->isFuncExprNode()) - return 0; - - FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); - ASSERT(body); - return body; -} - // ECMA 15.3.2 The Function Constructor JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { @@ -113,15 +87,13 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi int errLine; UString errMsg; SourceCode source = makeSource(program, sourceURL, lineNumber); - RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - - FunctionBodyNode* body = extractFunctionBody(programNode.get()); - if (!body) + RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); + if (!function) return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue()); - return new (exec) JSFunction(exec, functionName, body, scopeChain.node()); + return new (exec) JSFunction(exec, function, scopeChain.node()); } // ECMA 15.3.2 The Function Constructor diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h index 124b354..e8486dc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h @@ -26,8 +26,6 @@ namespace JSC { class FunctionPrototype; - class ProgramNode; - class FunctionBodyNode; class FunctionConstructor : public InternalFunction { public: @@ -41,8 +39,6 @@ namespace JSC { JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); JSObject* constructFunction(ExecState*, const ArgList&); - FunctionBodyNode* extractFunctionBody(ProgramNode*); - } // namespace JSC #endif // FunctionConstructor_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp index ff8e57b..1df998d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -84,16 +84,17 @@ static inline void insertSemicolonIfNeeded(UString& functionBody) JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (thisValue.isObject(&JSFunction::info)) { + if (thisValue.inherits(&JSFunction::info)) { JSFunction* function = asFunction(thisValue); if (!function->isHostFunction()) { - UString functionBody = function->body()->toSourceString(); - insertSemicolonIfNeeded(functionBody); - return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + functionBody); + FunctionExecutable* executable = function->jsExecutable(); + UString sourceString = executable->source().toString(); + insertSemicolonIfNeeded(sourceString); + return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + executable->paramString() + ") " + sourceString); } } - if (thisValue.isObject(&InternalFunction::info)) { + if (thisValue.inherits(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}"); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h index 607ddab..469191e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h @@ -34,7 +34,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.cpp index cd1b40a..7e54053 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,52 +28,14 @@ namespace JSC { -void GetterSetter::mark() +void GetterSetter::markChildren(MarkStack& markStack) { - JSCell::mark(); + JSCell::markChildren(markStack); - if (m_getter && !m_getter->marked()) - m_getter->mark(); - if (m_setter && !m_setter->marked()) - m_setter->mark(); -} - -JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const -{ - ASSERT_NOT_REACHED(); - return jsNull(); -} - -bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value) -{ - ASSERT_NOT_REACHED(); - number = 0; - value = JSValue(); - return true; -} - -bool GetterSetter::toBoolean(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return false; -} - -double GetterSetter::toNumber(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return 0.0; -} - -UString GetterSetter::toString(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return UString::null(); -} - -JSObject* GetterSetter::toObject(ExecState* exec) const -{ - ASSERT_NOT_REACHED(); - return jsNull().toObject(exec); + if (m_getter) + markStack.append(m_getter); + if (m_setter) + markStack.append(m_setter); } bool GetterSetter::isGetterSetter() const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h index e6b74a1..73dd854 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,6 +25,8 @@ #include "JSCell.h" +#include "CallFrame.h" + namespace JSC { class JSObject; @@ -33,30 +35,26 @@ namespace JSC { // for a property. class GetterSetter : public JSCell { public: - GetterSetter() - : JSCell(0) + GetterSetter(ExecState* exec) + : JSCell(exec->globalData().getterSetterStructure.get()) , m_getter(0) , m_setter(0) { } - virtual void mark(); + virtual void markChildren(MarkStack&); JSObject* getter() const { return m_getter; } void setGetter(JSObject* getter) { m_getter = getter; } JSObject* setter() const { return m_setter; } void setSetter(JSObject* setter) { m_setter = setter; } - + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(GetterSetterType)); + } private: virtual bool isGetterSetter() const; - virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); - virtual bool toBoolean(ExecState*) const; - virtual double toNumber(ExecState*) const; - virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; - JSObject* m_getter; JSObject* m_setter; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp index b0d4c25..3074f95 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -39,11 +39,10 @@ GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> st ASSERT_ARG(cachedGlobalObject, cachedGlobalObject); } -void GlobalEvalFunction::mark() +void GlobalEvalFunction::markChildren(MarkStack& markStack) { - PrototypeFunction::mark(); - if (!m_cachedGlobalObject->marked()) - m_cachedGlobalObject->mark(); + PrototypeFunction::markChildren(markStack); + markStack.append(m_cachedGlobalObject); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h index 49b1847..c56b0dc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -35,8 +35,13 @@ namespace JSC { GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); + } + private: - virtual void mark(); + virtual void markChildren(MarkStack&); JSGlobalObject* m_cachedGlobalObject; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h index 631cf42..2249179 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h @@ -54,6 +54,8 @@ namespace JSC { const char* ascii() const { return _ustring.ascii(); } static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); } + static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); } + static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); } bool isNull() const { return _ustring.isNull(); } bool isEmpty() const { return _ustring.isEmpty(); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp index a0620e7..fea89f8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp @@ -29,7 +29,6 @@ #include "config.h" #include "InitializeThreading.h" -#include "JSImmediate.h" #include "Collector.h" #include "dtoa.h" #include "Identifier.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h index 310644c..37077f6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h @@ -42,7 +42,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot | HasDefaultMark)); } protected: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.cpp new file mode 100644 index 0000000..e83724a --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "JSAPIValueWrapper.h" + +#include "NumberObject.h" +#include "UString.h" + +namespace JSC { + +} // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h new file mode 100644 index 0000000..88a8493 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSAPIValueWrapper_h +#define JSAPIValueWrapper_h + +#include <wtf/Platform.h> + +#include "JSCell.h" +#include "CallFrame.h" + +namespace JSC { + + class JSAPIValueWrapper : public JSCell { + friend JSValue jsAPIValueWrapper(ExecState*, JSValue); + public: + JSValue value() const { return m_value; } + + virtual bool isAPIValueWrapper() const { return true; } + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(CompoundType)); + } + + + private: + JSAPIValueWrapper(ExecState* exec, JSValue value) + : JSCell(exec->globalData().apiWrapperStructure.get()) + , m_value(value) + { + ASSERT(!value.isCell()); + } + + JSValue m_value; + }; + + inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value) + { + return new (exec) JSAPIValueWrapper(exec, value); + } + +} // namespace JSC + +#endif // JSAPIValueWrapper_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp index 184a9cb..d989a89 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,8 +39,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 }; -JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody) - : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame->registers())) +JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionExecutable> functionExecutable) + : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers())) { } @@ -49,35 +49,23 @@ JSActivation::~JSActivation() delete d(); } -void JSActivation::mark() +void JSActivation::markChildren(MarkStack& markStack) { - Base::mark(); + Base::markChildren(markStack); Register* registerArray = d()->registerArray.get(); if (!registerArray) return; - size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; + size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); - size_t i = 0; - size_t count = numParametersMinusThis; - for ( ; i < count; ++i) { - Register& r = registerArray[i]; - if (!r.marked()) - r.mark(); - } + size_t count = numParametersMinusThis; + markStack.appendValues(registerArray, count); - size_t numVars = d()->functionBody->generatedBytecode().m_numVars; + size_t numVars = d()->functionExecutable->variableCount(); // Skip the call frame, which sits between the parameters and vars. - i += RegisterFile::CallFrameHeaderSize; - count += RegisterFile::CallFrameHeaderSize + numVars; - - for ( ; i < count; ++i) { - Register& r = registerArray[i]; - if (r.jsValue() && !r.marked()) - r.mark(); - } + markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); } bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -148,14 +136,14 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const bool JSActivation::isDynamicScope() const { - return d()->functionBody->usesEval(); + return d()->functionExecutable->usesEval(); } JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) { JSActivation* activation = asActivation(slot.slotBase()); - if (activation->d()->functionBody->usesArguments()) { + if (activation->d()->functionExecutable->usesArguments()) { PropertySlot slot; activation->symbolTableGet(exec->propertyNames().arguments, slot); return slot.getValue(exec, exec->propertyNames().arguments); @@ -168,7 +156,7 @@ JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const arguments->copyRegisters(); callFrame->setCalleeArguments(arguments); } - ASSERT(arguments->isObject(&Arguments::info)); + ASSERT(arguments->inherits(&Arguments::info)); return arguments; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h index b48ef25..90815a1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,10 +43,10 @@ namespace JSC { class JSActivation : public JSVariableObject { typedef JSVariableObject Base; public: - JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>); + JSActivation(CallFrame*, PassRefPtr<FunctionExecutable>); virtual ~JSActivation(); - virtual void mark(); + virtual void markChildren(MarkStack&); virtual bool isDynamicScope() const; @@ -70,13 +70,20 @@ namespace JSC { private: struct JSActivationData : public JSVariableObjectData { - JSActivationData(PassRefPtr<FunctionBodyNode> functionBody, Register* registers) - : JSVariableObjectData(&functionBody->generatedBytecode().symbolTable(), registers) - , functionBody(functionBody) + JSActivationData(PassRefPtr<FunctionExecutable> _functionExecutable, Register* registers) + : JSVariableObjectData(_functionExecutable->generatedBytecode().symbolTable(), registers) + , functionExecutable(_functionExecutable) { + // We have to manually ref and deref the symbol table as JSVariableObjectData + // doesn't know about SharedSymbolTable + functionExecutable->generatedBytecode().sharedSymbolTable()->ref(); + } + ~JSActivationData() + { + static_cast<SharedSymbolTable*>(symbolTable)->deref(); } - RefPtr<FunctionBodyNode> functionBody; + RefPtr<FunctionExecutable> functionExecutable; }; static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp index a8207e3..1a4402c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2003 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * @@ -25,6 +25,8 @@ #include "ArrayPrototype.h" #include "CachedCall.h" +#include "Error.h" +#include "Executable.h" #include "PropertyNameArray.h" #include <wtf/AVLTree.h> #include <wtf/Assertions.h> @@ -134,9 +136,9 @@ JSArray::JSArray(PassRefPtr<Structure> structure) unsigned initialCapacity = 0; m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity))); - m_fastAccessCutoff = 0; m_storage->m_vectorLength = initialCapacity; - m_storage->m_length = 0; + + m_fastAccessCutoff = 0; checkConsistency(); } @@ -146,40 +148,45 @@ JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) { unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); - m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity))); - m_fastAccessCutoff = 0; - m_storage->m_vectorLength = initialCapacity; + m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); m_storage->m_length = initialLength; + m_storage->m_vectorLength = initialCapacity; + m_storage->m_numValuesInVector = 0; + m_storage->m_sparseValueMap = 0; + m_storage->lazyCreationData = 0; - Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue)); + JSValue* vector = m_storage->m_vector; + for (size_t i = 0; i < initialCapacity; ++i) + vector[i] = JSValue(); + + m_fastAccessCutoff = 0; checkConsistency(); + + Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue)); } JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list) : JSObject(structure) { - unsigned length = list.size(); + unsigned initialCapacity = list.size(); - m_fastAccessCutoff = length; - - ArrayStorage* storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(length))); - - storage->m_vectorLength = length; - storage->m_numValuesInVector = length; - storage->m_sparseValueMap = 0; - storage->m_length = length; + m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); + m_storage->m_length = initialCapacity; + m_storage->m_vectorLength = initialCapacity; + m_storage->m_numValuesInVector = initialCapacity; + m_storage->m_sparseValueMap = 0; size_t i = 0; ArgList::const_iterator end = list.end(); for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i) - storage->m_vector[i] = *it; + m_storage->m_vector[i] = *it; - m_storage = storage; - - Heap::heap(this)->reportExtraMemoryCost(storageSize(length)); + m_fastAccessCutoff = initialCapacity; checkConsistency(); + + Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity)); } JSArray::~JSArray() @@ -216,7 +223,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot } } - return false; + return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot); } bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -234,6 +241,37 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName return JSObject::getOwnPropertySlot(exec, propertyName, slot); } +bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (propertyName == exec->propertyNames().length) { + descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum); + return true; + } + + bool isArrayIndex; + unsigned i = propertyName.toArrayIndex(&isArrayIndex); + if (isArrayIndex) { + if (i >= m_storage->m_length) + return false; + if (i < m_storage->m_vectorLength) { + JSValue value = m_storage->m_vector[i]; + if (value) { + descriptor.setDescriptor(value, 0); + return true; + } + } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) { + if (i >= MIN_SPARSE_ARRAY_INDEX) { + SparseArrayValueMap::iterator it = map->find(i); + if (it != map->end()) { + descriptor.setDescriptor(it->second, 0); + return true; + } + } + } + } + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + // ECMA 15.4.5.1 void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { @@ -343,8 +381,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu } } - storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength))); - if (!storage) { + if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) { throwOutOfMemoryError(exec); return; } @@ -427,7 +464,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) return false; } -void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) +void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) { // FIXME: Filling PropertyNameArray with an identifier for every integer // is incredibly inefficient for large arrays. We need a different approach, @@ -447,7 +484,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames propertyNames.add(Identifier::from(exec, it->first)); } - JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } bool JSArray::increaseVectorLength(unsigned newLength) @@ -462,8 +499,7 @@ bool JSArray::increaseVectorLength(unsigned newLength) ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX); unsigned newVectorLength = increasedVectorLength(newLength); - storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength))); - if (!storage) + if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) return false; Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); @@ -596,27 +632,9 @@ void JSArray::push(ExecState* exec, JSValue value) putSlowCase(exec, m_storage->m_length++, value); } -void JSArray::mark() +void JSArray::markChildren(MarkStack& markStack) { - JSObject::mark(); - - ArrayStorage* storage = m_storage; - - unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength); - for (unsigned i = 0; i < usedVectorLength; ++i) { - JSValue value = storage->m_vector[i]; - if (value && !value.marked()) - value.mark(); - } - - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { - SparseArrayValueMap::iterator end = map->end(); - for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) { - JSValue value = it->second; - if (!value.marked()) - value.mark(); - } - } + markChildrenDirect(markStack); } static int compareNumbersForQSort(const void* a, const void* b) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h index 73e1711..37ed72b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,6 +38,7 @@ namespace JSC { class JSArray : public JSObject { friend class JIT; + friend class Walker; public: explicit JSArray(PassRefPtr<Structure>); @@ -47,6 +48,7 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem. static JS_EXPORTDATA const ClassInfo info; @@ -82,13 +84,15 @@ namespace JSC { { return Structure::create(prototype, TypeInfo(ObjectType)); } + + inline void markChildrenDirect(MarkStack& markStack); protected: virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); - virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); - virtual void mark(); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual void markChildren(MarkStack&); void* lazyCreationData(); void setLazyCreationData(void*); @@ -117,14 +121,104 @@ namespace JSC { JSArray* constructArray(ExecState*, JSValue singleItemValue); JSArray* constructArray(ExecState*, const ArgList& values); + inline JSArray* asArray(JSCell* cell) + { + ASSERT(cell->inherits(&JSArray::info)); + return static_cast<JSArray*>(cell); + } + inline JSArray* asArray(JSValue value) { - ASSERT(asObject(value)->inherits(&JSArray::info)); - return static_cast<JSArray*>(asObject(value)); + return asArray(value.asCell()); } - inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; } + inline bool isJSArray(JSGlobalData* globalData, JSValue v) + { + return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; + } + inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; } + inline void JSArray::markChildrenDirect(MarkStack& markStack) + { + JSObject::markChildrenDirect(markStack); + + ArrayStorage* storage = m_storage; + + unsigned usedVectorLength = std::min(storage->m_length, storage->m_vectorLength); + markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues); + + if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + SparseArrayValueMap::iterator end = map->end(); + for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) + markStack.append(it->second); + } + } + + inline void MarkStack::markChildren(JSCell* cell) + { + ASSERT(Heap::isCellMarked(cell)); + if (cell->structure()->typeInfo().hasDefaultMark()) { +#ifdef NDEBUG + asObject(cell)->markChildrenDirect(*this); +#else + ASSERT(!m_isCheckingForDefaultMarkViolation); + m_isCheckingForDefaultMarkViolation = true; + cell->markChildren(*this); + ASSERT(m_isCheckingForDefaultMarkViolation); + m_isCheckingForDefaultMarkViolation = false; +#endif + return; + } + if (cell->vptr() == m_jsArrayVPtr) { + asArray(cell)->markChildrenDirect(*this); + return; + } + cell->markChildren(*this); + } + + inline void MarkStack::drain() + { + while (!m_markSets.isEmpty() || !m_values.isEmpty()) { + while (!m_markSets.isEmpty() && m_values.size() < 50) { + ASSERT(!m_markSets.isEmpty()); + MarkSet& current = m_markSets.last(); + ASSERT(current.m_values); + JSValue* end = current.m_end; + ASSERT(current.m_values); + ASSERT(current.m_values != end); + findNextUnmarkedNullValue: + ASSERT(current.m_values != end); + JSValue value = *current.m_values; + current.m_values++; + + JSCell* cell; + if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + Heap::markCell(cell); + if (cell->structure()->typeInfo().type() < CompoundType) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + if (current.m_values == end) + m_markSets.removeLast(); + + markChildren(cell); + } + while (!m_values.isEmpty()) + markChildren(m_values.removeLast()); + } + } + } // namespace JSC #endif // JSArray_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp index d00b69c..0907099 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp @@ -45,7 +45,7 @@ JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteA PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype) { - PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType)); + PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark)); return result; } @@ -59,7 +59,18 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property } return JSObject::getOwnPropertySlot(exec, propertyName, slot); } - + +bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + bool ok; + unsigned index = propertyName.toUInt32(&ok, false); + if (ok && canAccessIndex(index)) { + descriptor.setDescriptor(getIndex(exec, index), DontDelete); + return true; + } + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (canAccessIndex(propertyName)) { @@ -85,12 +96,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value) setIndex(exec, propertyName, value); } -void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) +void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) { unsigned length = m_storage->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier::from(exec, i)); - JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h index c43c3ea..5ea0505 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h @@ -33,7 +33,7 @@ namespace JSC { class JSByteArray : public JSObject { - friend class VPtrSet; + friend struct VPtrSet; public: bool canAccessIndex(unsigned i) { return i < m_storage->length(); } JSValue getIndex(ExecState* exec, unsigned i) @@ -78,10 +78,11 @@ namespace JSC { virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue); - virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, bool includeNonEnumerable = false); virtual const ClassInfo* classInfo() const { return m_classInfo; } static const ClassInfo s_defaultInfo; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp index 10a91f7..1cfe72d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp @@ -90,16 +90,6 @@ bool JSCell::getUInt32(uint32_t&) const return false; } -bool JSCell::getTruncatedInt32(int32_t&) const -{ - return false; -} - -bool JSCell::getTruncatedUInt32(uint32_t&) const -{ - return false; -} - bool JSCell::getString(UString&stringValue) const { if (!isString()) @@ -115,7 +105,7 @@ UString JSCell::getString() const JSObject* JSCell::getObject() { - return isObject() ? static_cast<JSObject*>(this) : 0; + return isObject() ? asObject(this) : 0; } const JSObject* JSCell::getObject() const @@ -207,4 +197,40 @@ bool JSCell::isGetterSetter() const return false; } +JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const +{ + ASSERT_NOT_REACHED(); + return JSValue(); +} + +bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&) +{ + ASSERT_NOT_REACHED(); + return false; +} + +bool JSCell::toBoolean(ExecState*) const +{ + ASSERT_NOT_REACHED(); + return false; +} + +double JSCell::toNumber(ExecState*) const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +UString JSCell::toString(ExecState*) const +{ + ASSERT_NOT_REACHED(); + return UString(); +} + +JSObject* JSCell::toObject(ExecState*) const +{ + ASSERT_NOT_REACHED(); + return 0; +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h index 4743baf..d015b9c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,11 +23,12 @@ #ifndef JSCell_h #define JSCell_h -#include <wtf/Noncopyable.h> -#include "Structure.h" -#include "JSValue.h" -#include "JSImmediate.h" #include "Collector.h" +#include "JSImmediate.h" +#include "JSValue.h" +#include "MarkStack.h" +#include "Structure.h" +#include <wtf/Noncopyable.h> namespace JSC { @@ -40,19 +41,24 @@ namespace JSC { friend class JSPropertyNameIterator; friend class JSString; friend class JSValue; - friend class VPtrSet; + friend class JSAPIValueWrapper; + friend struct VPtrSet; private: explicit JSCell(Structure*); + JSCell(); // Only used for initializing Collector blocks. virtual ~JSCell(); public: // Querying the type. +#if USE(JSVALUE32) bool isNumber() const; +#endif bool isString() const; bool isObject() const; virtual bool isGetterSetter() const; - virtual bool isObject(const ClassInfo*) const; + bool inherits(const ClassInfo*) const; + virtual bool isAPIValueWrapper() const { return false; } Structure* structure() const; @@ -68,23 +74,21 @@ namespace JSC { // Extracting integer values. // FIXME: remove these methods, can check isNumberCell in JSValue && then call asNumberCell::*. virtual bool getUInt32(uint32_t&) const; - virtual bool getTruncatedInt32(int32_t&) const; - virtual bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. - virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0; - virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0; - virtual bool toBoolean(ExecState*) const = 0; - virtual double toNumber(ExecState*) const = 0; - virtual UString toString(ExecState*) const = 0; - virtual JSObject* toObject(ExecState*) const = 0; + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&); + virtual bool toBoolean(ExecState*) const; + virtual double toNumber(ExecState*) const; + virtual UString toString(ExecState*) const; + virtual JSObject* toObject(ExecState*) const; // Garbage collection. void* operator new(size_t, ExecState*); void* operator new(size_t, JSGlobalData*); void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } - virtual void mark(); - bool marked() const; + + virtual void markChildren(MarkStack&); // Object operations, with the toObject operation included. virtual const ClassInfo* classInfo() const; @@ -108,6 +112,7 @@ namespace JSC { Structure* m_structure; }; + // FIXME: We should deprecate this and just use JSValue::asCell() instead. JSCell* asCell(JSValue); inline JSCell* asCell(JSValue value) @@ -120,14 +125,21 @@ namespace JSC { { } + // Only used for initializing Collector blocks. + inline JSCell::JSCell() + { + } + inline JSCell::~JSCell() { } +#if USE(JSVALUE32) inline bool JSCell::isNumber() const { return Heap::isNumber(const_cast<JSCell*>(this)); } +#endif inline bool JSCell::isObject() const { @@ -144,20 +156,8 @@ namespace JSC { return m_structure; } - inline bool JSCell::marked() const + inline void JSCell::markChildren(MarkStack&) { - return Heap::isCellMarked(this); - } - - inline void JSCell::mark() - { - return Heap::markCell(this); - } - - ALWAYS_INLINE JSCell* JSValue::asCell() const - { - ASSERT(isCell()); - return m_ptr; } inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) @@ -173,126 +173,190 @@ namespace JSC { inline bool JSValue::isString() const { - return !JSImmediate::isImmediate(asValue()) && asCell()->isString(); + return isCell() && asCell()->isString(); } inline bool JSValue::isGetterSetter() const { - return !JSImmediate::isImmediate(asValue()) && asCell()->isGetterSetter(); + return isCell() && asCell()->isGetterSetter(); } inline bool JSValue::isObject() const { - return !JSImmediate::isImmediate(asValue()) && asCell()->isObject(); + return isCell() && asCell()->isObject(); } inline bool JSValue::getString(UString& s) const { - return !JSImmediate::isImmediate(asValue()) && asCell()->getString(s); + return isCell() && asCell()->getString(s); } inline UString JSValue::getString() const { - return JSImmediate::isImmediate(asValue()) ? UString() : asCell()->getString(); + return isCell() ? asCell()->getString() : UString(); } inline JSObject* JSValue::getObject() const { - return JSImmediate::isImmediate(asValue()) ? 0 : asCell()->getObject(); + return isCell() ? asCell()->getObject() : 0; } inline CallType JSValue::getCallData(CallData& callData) { - return JSImmediate::isImmediate(asValue()) ? CallTypeNone : asCell()->getCallData(callData); + return isCell() ? asCell()->getCallData(callData) : CallTypeNone; } inline ConstructType JSValue::getConstructData(ConstructData& constructData) { - return JSImmediate::isImmediate(asValue()) ? ConstructTypeNone : asCell()->getConstructData(constructData); + return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone; } ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getUInt32(asValue(), v) : asCell()->getUInt32(v); + if (isInt32()) { + int32_t i = asInt32(); + v = static_cast<uint32_t>(i); + return i >= 0; + } + if (isDouble()) { + double d = asDouble(); + v = static_cast<uint32_t>(d); + return v == d; + } + return false; } - ALWAYS_INLINE bool JSValue::getTruncatedInt32(int32_t& v) const +#if !USE(JSVALUE32_64) + ALWAYS_INLINE JSCell* JSValue::asCell() const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedInt32(asValue(), v) : asCell()->getTruncatedInt32(v); + ASSERT(isCell()); + return m_ptr; } +#endif // !USE(JSVALUE32_64) - inline bool JSValue::getTruncatedUInt32(uint32_t& v) const + inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::getTruncatedUInt32(asValue(), v) : asCell()->getTruncatedUInt32(v); + return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue(); } - inline void JSValue::mark() + inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) { - asCell()->mark(); // callers should check !marked() before calling mark(), so this should only be called with cells + if (isInt32()) { + number = asInt32(); + value = *this; + return true; + } + if (isDouble()) { + number = asDouble(); + value = *this; + return true; + } + if (isCell()) + return asCell()->getPrimitiveNumber(exec, number, value); + if (isTrue()) { + number = 1.0; + value = *this; + return true; + } + if (isFalse() || isNull()) { + number = 0.0; + value = *this; + return true; + } + ASSERT(isUndefined()); + number = nonInlineNaN(); + value = *this; + return true; } - inline bool JSValue::marked() const + inline bool JSValue::toBoolean(ExecState* exec) const { - return JSImmediate::isImmediate(asValue()) || asCell()->marked(); + if (isInt32()) + return asInt32() != 0; + if (isDouble()) + return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN + if (isCell()) + return asCell()->toBoolean(exec); + return isTrue(); // false, null, and undefined all convert to false. } - inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const + ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const { - return JSImmediate::isImmediate(asValue()) ? asValue() : asCell()->toPrimitive(exec, preferredType); + if (isInt32()) + return asInt32(); + if (isDouble()) + return asDouble(); + if (isCell()) + return asCell()->toNumber(exec); + if (isTrue()) + return 1.0; + return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0. } - inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) + inline bool JSValue::needsThisConversion() const { - if (JSImmediate::isImmediate(asValue())) { - number = JSImmediate::toDouble(asValue()); - value = asValue(); + if (UNLIKELY(!isCell())) return true; - } - return asCell()->getPrimitiveNumber(exec, number, value); + return asCell()->structure()->typeInfo().needsThisConversion(); } - inline bool JSValue::toBoolean(ExecState* exec) const + inline UString JSValue::toThisString(ExecState* exec) const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toBoolean(asValue()) : asCell()->toBoolean(exec); + return isCell() ? asCell()->toThisString(exec) : toString(exec); } - ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const + inline JSValue JSValue::getJSNumber() { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asCell()->toNumber(exec); + if (isInt32() || isDouble()) + return *this; + if (isCell()) + return asCell()->getJSNumber(); + return JSValue(); } - inline UString JSValue::toString(ExecState* exec) const + inline JSObject* JSValue::toObject(ExecState* exec) const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toString(exec); + return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec); } - inline JSObject* JSValue::toObject(ExecState* exec) const + inline JSObject* JSValue::toThisObject(ExecState* exec) const { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toObject(asValue(), exec) : asCell()->toObject(exec); + return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); } - inline JSObject* JSValue::toThisObject(ExecState* exec) const + ALWAYS_INLINE void MarkStack::append(JSCell* cell) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) - return JSImmediate::toThisObject(asValue(), exec); - return asCell()->toThisObject(exec); + ASSERT(!m_isCheckingForDefaultMarkViolation); + ASSERT(cell); + if (Heap::isCellMarked(cell)) + return; + Heap::markCell(cell); + if (cell->structure()->typeInfo().type() >= CompoundType) + m_values.append(cell); } - inline bool JSValue::needsThisConversion() const + ALWAYS_INLINE void MarkStack::append(JSValue value) { - if (UNLIKELY(JSImmediate::isImmediate(asValue()))) - return true; - return asCell()->structure()->typeInfo().needsThisConversion(); + ASSERT(value); + if (value.isCell()) + append(value.asCell()); } - inline UString JSValue::toThisString(ExecState* exec) const + inline void Structure::markAggregate(MarkStack& markStack) { - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toString(asValue()) : asCell()->toThisString(exec); + markStack.append(m_prototype); } - inline JSValue JSValue::getJSNumber() + inline Heap* Heap::heap(JSValue v) + { + if (!v.isCell()) + return 0; + return heap(v.asCell()); + } + + inline Heap* Heap::heap(JSCell* c) { - return JSImmediate::isNumber(asValue()) ? asValue() : JSImmediate::isImmediate(asValue()) ? JSValue() : asCell()->getJSNumber(); + return cellBlock(c)->heap; } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp index c8e137e..bf4e34d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -45,12 +45,21 @@ ASSERT_CLASS_FITS_IN_CELL(JSFunction); const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; +bool JSFunction::isHostFunctionNonInline() const +{ + return isHostFunction(); +} + +JSFunction::JSFunction(PassRefPtr<Structure> structure) + : Base(structure) + , m_executable(adoptRef(new VPtrHackExecutable())) +{ +} + JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(&exec->globalData(), structure, name) #if ENABLE(JIT) - , m_body(FunctionBodyNode::createNativeThunk(&exec->globalData())) -#else - , m_body(0) + , m_executable(adoptRef(new NativeExecutable(exec))) #endif { #if ENABLE(JIT) @@ -63,32 +72,35 @@ JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int len #endif } -JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode) - : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name) - , m_body(body) +JSFunction::JSFunction(ExecState* exec, PassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) + : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name()) + , m_executable(executable) { setScopeChain(scopeChainNode); } JSFunction::~JSFunction() { -#if ENABLE(JIT) // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). - if (m_body && m_body->isGenerated()) - m_body->generatedBytecode().unlinkCallers(); + if (!isHostFunction()) { +#if ENABLE(JIT_OPTIMIZE_CALL) + ASSERT(m_executable); + if (jsExecutable()->isGenerated()) + jsExecutable()->generatedBytecode().unlinkCallers(); #endif - if (!isHostFunction()) - scopeChain().~ScopeChain(); + scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too? + } } -void JSFunction::mark() +void JSFunction::markChildren(MarkStack& markStack) { - Base::mark(); - m_body->mark(); - if (!isHostFunction()) - scopeChain().mark(); + Base::markChildren(markStack); + if (!isHostFunction()) { + jsExecutable()->markAggregate(markStack); + scopeChain().markAggregate(markStack); + } } CallType JSFunction::getCallData(CallData& callData) @@ -97,7 +109,7 @@ CallType JSFunction::getCallData(CallData& callData) callData.native.function = nativeFunction(); return CallTypeHost; } - callData.js.functionBody = m_body.get(); + callData.js.functionExecutable = jsExecutable(); callData.js.scopeChain = scopeChain().node(); return CallTypeJS; } @@ -105,7 +117,7 @@ CallType JSFunction::getCallData(CallData& callData) JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args) { ASSERT(!isHostFunction()); - return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); + return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); } JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) @@ -126,7 +138,7 @@ JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const Prope { JSFunction* thisObj = asFunction(slot.slotBase()); ASSERT(!thisObj->isHostFunction()); - return jsNumber(exec, thisObj->m_body->parameterCount()); + return jsNumber(exec, thisObj->jsExecutable()->parameterCount()); } bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -165,6 +177,35 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertySlot(exec, propertyName, slot); } + bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + if (isHostFunction()) + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + + if (propertyName == exec->propertyNames().prototype) { + PropertySlot slot; + getOwnPropertySlot(exec, propertyName, slot); + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + + if (propertyName == exec->propertyNames().arguments) { + descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); + return true; + } + + if (propertyName == exec->propertyNames().length) { + descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); + return true; + } + + if (propertyName == exec->propertyNames().caller) { + descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); + return true; + } + + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (isHostFunction()) { @@ -190,7 +231,7 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData) { if (isHostFunction()) return ConstructTypeNone; - constructData.js.functionBody = m_body.get(); + constructData.js.functionExecutable = jsExecutable(); constructData.js.scopeChain = scopeChain().node(); return ConstructTypeJS; } @@ -206,7 +247,7 @@ JSObject* JSFunction::construct(ExecState* exec, const ArgList& args) structure = exec->lexicalGlobalObject()->emptyObjectStructure(); JSObject* thisObj = new (exec) JSObject(structure); - JSValue result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); + JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h index 5ddd97c..416a58a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h @@ -25,38 +25,25 @@ #define JSFunction_h #include "InternalFunction.h" -#include "JSVariableObject.h" -#include "SymbolTable.h" -#include "Nodes.h" -#include "JSObject.h" namespace JSC { - class FunctionBodyNode; + class ExecutableBase; + class FunctionExecutable; class FunctionPrototype; class JSActivation; class JSGlobalObject; class JSFunction : public InternalFunction { friend class JIT; - friend class VPtrSet; + friend struct VPtrSet; typedef InternalFunction Base; - JSFunction(PassRefPtr<Structure> structure) - : InternalFunction(structure) - { - clearScopeChain(); - } - public: JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction); - JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*); - ~JSFunction(); - - virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); - virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + JSFunction(ExecState*, PassRefPtr<FunctionExecutable>, ScopeChainNode*); + virtual ~JSFunction(); JSObject* construct(ExecState*, const ArgList&); JSValue call(ExecState*, JSValue thisValue, const ArgList&); @@ -64,11 +51,11 @@ namespace JSC { void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); } ScopeChain& scope() { return scopeChain(); } - void setBody(FunctionBodyNode* body) { m_body = body; } - void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; } - FunctionBodyNode* body() const { return m_body.get(); } + ExecutableBase* executable() const { return m_executable.get(); } - virtual void mark(); + // To call either of these methods include Executable.h + inline bool isHostFunction() const; + FunctionExecutable* jsExecutable() const; static JS_EXPORTDATA const ClassInfo info; @@ -77,11 +64,6 @@ namespace JSC { return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); } -#if ENABLE(JIT) - bool isHostFunction() const { return m_body && m_body->isHostFunction(); } -#else - bool isHostFunction() const { return false; } -#endif NativeFunction nativeFunction() { return *reinterpret_cast<NativeFunction*>(m_data); @@ -91,31 +73,42 @@ namespace JSC { virtual CallType getCallData(CallData&); private: + JSFunction(PassRefPtr<Structure>); + + bool isHostFunctionNonInline() const; + + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + + virtual void markChildren(MarkStack&); + virtual const ClassInfo* classInfo() const { return &info; } static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&); static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&); - RefPtr<FunctionBodyNode> m_body; + RefPtr<ExecutableBase> m_executable; ScopeChain& scopeChain() { - ASSERT(!isHostFunction()); + ASSERT(!isHostFunctionNonInline()); return *reinterpret_cast<ScopeChain*>(m_data); } void clearScopeChain() { - ASSERT(!isHostFunction()); + ASSERT(!isHostFunctionNonInline()); new (m_data) ScopeChain(NoScopeChain()); } void setScopeChain(ScopeChainNode* sc) { - ASSERT(!isHostFunction()); + ASSERT(!isHostFunctionNonInline()); new (m_data) ScopeChain(sc); } void setScopeChain(const ScopeChain& sc) { - ASSERT(!isHostFunction()); + ASSERT(!isHostFunctionNonInline()); *reinterpret_cast<ScopeChain*>(m_data) = sc; } void setNativeFunction(NativeFunction func) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp index 85d881e..4496d6c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp @@ -33,14 +33,17 @@ #include "Collector.h" #include "CommonIdentifiers.h" #include "FunctionConstructor.h" +#include "GetterSetter.h" #include "Interpreter.h" #include "JSActivation.h" +#include "JSAPIValueWrapper.h" #include "JSArray.h" #include "JSByteArray.h" #include "JSClassRef.h" #include "JSFunction.h" #include "JSLock.h" #include "JSNotAnObject.h" +#include "JSPropertyNameIterator.h" #include "JSStaticScopeObject.h" #include "Parser.h" #include "Lexer.h" @@ -118,7 +121,10 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , stringStructure(JSString::createStructure(jsNull())) , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) -#if !USE(ALTERNATE_JSIMMEDIATE) + , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull())) + , getterSetterStructure(GetterSetter::createStructure(jsNull())) + , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) +#if USE(JSVALUE32) , numberStructure(JSNumberCell::createStructure(jsNull())) #endif , jsArrayVPtr(vptrSet.jsArrayVPtr) @@ -139,12 +145,13 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , initializingLazyNumericCompareFunction(false) , head(0) , dynamicGlobalObject(0) - , scopeNodeBeingReparsed(0) + , functionCodeBlockBeingReparsed(0) , firstStringifierToMark(0) -{ -#ifdef QT_BUILD_SCRIPT_LIB - scriptpool = new SourcePool(); + , markStack(vptrSet.jsArrayVPtr) +#ifndef NDEBUG + , mainThreadOnly(false) #endif +{ #if PLATFORM(MAC) startProfilerServerIfNeeded(); #endif @@ -190,10 +197,6 @@ JSGlobalData::~JSGlobalData() deleteIdentifierTable(identifierTable); delete clientData; -#ifdef QT_BUILD_SCRIPT_LIB - if (scriptpool) - delete scriptpool; -#endif } PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared) @@ -238,9 +241,8 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) { if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) { initializingLazyNumericCompareFunction = true; - RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); - RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get()); - lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions(); + RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); + lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions(); initializingLazyNumericCompareFunction = false; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h index fb557af..c9887e8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h @@ -33,36 +33,33 @@ #include "ExecutableAllocator.h" #include "JITStubs.h" #include "JSValue.h" +#include "MarkStack.h" +#include "NumericStrings.h" #include "SmallStrings.h" #include "TimeoutChecker.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> -#ifdef QT_BUILD_SCRIPT_LIB -#include "SourcePoolQt.h" -#endif - struct OpaqueJSClass; struct OpaqueJSClassContextData; namespace JSC { + class CodeBlock; class CommonIdentifiers; - class FunctionBodyNode; class IdentifierTable; - class Instruction; class Interpreter; class JSGlobalObject; class JSObject; class Lexer; class Parser; - class ScopeNode; class Stringifier; class Structure; class UString; struct HashTable; + struct Instruction; struct VPtrSet; class JSGlobalData : public RefCounted<JSGlobalData> { @@ -70,7 +67,7 @@ namespace JSC { struct ClientData { virtual ~ClientData() = 0; #ifdef QT_BUILD_SCRIPT_LIB - virtual void mark() {} + virtual void mark(MarkStack&) {} #endif }; @@ -104,7 +101,11 @@ namespace JSC { RefPtr<Structure> stringStructure; RefPtr<Structure> notAnObjectErrorStubStructure; RefPtr<Structure> notAnObjectStructure; -#if !USE(ALTERNATE_JSIMMEDIATE) + RefPtr<Structure> propertyNameIteratorStructure; + RefPtr<Structure> getterSetterStructure; + RefPtr<Structure> apiWrapperStructure; + +#if USE(JSVALUE32) RefPtr<Structure> numberStructure; #endif @@ -117,6 +118,7 @@ namespace JSC { CommonIdentifiers* propertyNames; const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark. SmallStrings smallStrings; + NumericStrings numericStrings; #if ENABLE(ASSEMBLER) ExecutableAllocator executableAllocator; @@ -125,9 +127,6 @@ namespace JSC { Lexer* lexer; Parser* parser; Interpreter* interpreter; -#ifdef QT_BUILD_SCRIPT_LIB - SourcePool* scriptpool; -#endif #if ENABLE(JIT) JITThunks jitStubs; #endif @@ -150,9 +149,15 @@ namespace JSC { HashSet<JSObject*> arrayVisitedElements; - ScopeNode* scopeNodeBeingReparsed; + CodeBlock* functionCodeBlockBeingReparsed; Stringifier* firstStringifierToMark; + MarkStack markStack; + +#ifndef NDEBUG + bool mainThreadOnly; +#endif + private: JSGlobalData(bool isShared, const VPtrSet&); static JSGlobalData*& sharedInstanceInternal(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp index 55286d3..60eb1b4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -80,16 +80,16 @@ static const int initialTickCountThreshold = 255; // Preferred number of milliseconds between each timeout check static const int preferredScriptCheckTimeInterval = 1000; -static inline void markIfNeeded(JSValue v) +static inline void markIfNeeded(MarkStack& markStack, JSValue v) { - if (v && !v.marked()) - v.mark(); + if (v) + markStack.append(v); } -static inline void markIfNeeded(const RefPtr<Structure>& s) +static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s) { if (s) - s->mark(); + s->markAggregate(markStack); } JSGlobalObject::~JSGlobalObject() @@ -112,8 +112,8 @@ JSGlobalObject::~JSGlobalObject() if (headObject == this) headObject = 0; - HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end(); - for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) + HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); + for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) (*it)->clearGlobalObject(); RegisterFile& registerFile = globalData()->interpreter->registerFile(); @@ -175,18 +175,18 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper } } -void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc) +void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes) { PropertySlot slot; if (!symbolTableGet(propertyName, slot)) - JSVariableObject::defineGetter(exec, propertyName, getterFunc); + JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes); } -void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc) +void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes) { PropertySlot slot; if (!symbolTableGet(propertyName, slot)) - JSVariableObject::defineSetter(exec, propertyName, setterFunc); + JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes); } static inline JSObject* lastInPrototypeChain(JSObject* object) @@ -256,9 +256,9 @@ void JSGlobalObject::reset(JSValue prototype) // Constructors - JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype); + JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get()); JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype); - JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype); + JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get()); JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype); JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype); @@ -359,43 +359,43 @@ void JSGlobalObject::resetPrototype(JSValue prototype) oldLastInPrototypeChain->setPrototype(objectPrototype); } -void JSGlobalObject::mark() +void JSGlobalObject::markChildren(MarkStack& markStack) { - JSVariableObject::mark(); + JSVariableObject::markChildren(markStack); - HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end(); - for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) - (*it)->mark(); + HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); + for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) + (*it)->markAggregate(markStack); RegisterFile& registerFile = globalData()->interpreter->registerFile(); if (registerFile.globalObject() == this) - registerFile.markGlobals(&globalData()->heap); - - markIfNeeded(d()->regExpConstructor); - markIfNeeded(d()->errorConstructor); - markIfNeeded(d()->evalErrorConstructor); - markIfNeeded(d()->rangeErrorConstructor); - markIfNeeded(d()->referenceErrorConstructor); - markIfNeeded(d()->syntaxErrorConstructor); - markIfNeeded(d()->typeErrorConstructor); - markIfNeeded(d()->URIErrorConstructor); - - markIfNeeded(d()->evalFunction); - markIfNeeded(d()->callFunction); - markIfNeeded(d()->applyFunction); - - markIfNeeded(d()->objectPrototype); - markIfNeeded(d()->functionPrototype); - markIfNeeded(d()->arrayPrototype); - markIfNeeded(d()->booleanPrototype); - markIfNeeded(d()->stringPrototype); - markIfNeeded(d()->numberPrototype); - markIfNeeded(d()->datePrototype); - markIfNeeded(d()->regExpPrototype); - - markIfNeeded(d()->methodCallDummy); - - markIfNeeded(d()->errorStructure); + registerFile.markGlobals(markStack, &globalData()->heap); + + markIfNeeded(markStack, d()->regExpConstructor); + markIfNeeded(markStack, d()->errorConstructor); + markIfNeeded(markStack, d()->evalErrorConstructor); + markIfNeeded(markStack, d()->rangeErrorConstructor); + markIfNeeded(markStack, d()->referenceErrorConstructor); + markIfNeeded(markStack, d()->syntaxErrorConstructor); + markIfNeeded(markStack, d()->typeErrorConstructor); + markIfNeeded(markStack, d()->URIErrorConstructor); + + markIfNeeded(markStack, d()->evalFunction); + markIfNeeded(markStack, d()->callFunction); + markIfNeeded(markStack, d()->applyFunction); + + markIfNeeded(markStack, d()->objectPrototype); + markIfNeeded(markStack, d()->functionPrototype); + markIfNeeded(markStack, d()->arrayPrototype); + markIfNeeded(markStack, d()->booleanPrototype); + markIfNeeded(markStack, d()->stringPrototype); + markIfNeeded(markStack, d()->numberPrototype); + markIfNeeded(markStack, d()->datePrototype); + markIfNeeded(markStack, d()->regExpPrototype); + + markIfNeeded(markStack, d()->methodCallDummy); + + markIfNeeded(markStack, d()->errorStructure); // No need to mark the other structures, because their prototypes are all // guaranteed to be referenced elsewhere. @@ -405,11 +405,7 @@ void JSGlobalObject::mark() return; size_t size = d()->registerArraySize; - for (size_t i = 0; i < size; ++i) { - Register& r = registerArray[i]; - if (!r.marked()) - r.mark(); - } + markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size); } ExecState* JSGlobalObject::globalExec() diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h index 98e9b68..7459c2e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -31,10 +31,6 @@ #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> -#ifdef QT_BUILD_SCRIPT_LIB -#include "SourcePoolQt.h" -#endif - namespace JSC { class ArrayPrototype; @@ -43,6 +39,7 @@ namespace JSC { class Debugger; class ErrorConstructor; class FunctionPrototype; + class GlobalCodeBlock; class GlobalEvalFunction; class NativeErrorConstructor; class ProgramCodeBlock; @@ -149,7 +146,7 @@ namespace JSC { RefPtr<JSGlobalData> globalData; - HashSet<ProgramCodeBlock*> codeBlocks; + HashSet<GlobalCodeBlock*> codeBlocks; }; public: @@ -171,15 +168,16 @@ namespace JSC { public: virtual ~JSGlobalObject(); - virtual void mark(); + virtual void markChildren(MarkStack&); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&); virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes); - virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc); - virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc); + virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); + virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); // Linked list of all global objects that use the same JSGlobalData. JSGlobalObject*& head() { return d()->globalData->head; } @@ -233,9 +231,6 @@ namespace JSC { Debugger* debugger() const { return d()->debugger; } void setDebugger(Debugger* debugger) { -#ifdef QT_BUILD_SCRIPT_LIB - globalData()->scriptpool->setDebugger(debugger); -#endif d()->debugger = debugger; } @@ -257,7 +252,7 @@ namespace JSC { virtual bool isDynamicScope() const; - HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; } + HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; } void copyGlobalsFrom(RegisterFile&); void copyGlobalsTo(RegisterFile&); @@ -336,6 +331,13 @@ namespace JSC { return symbolTableGet(propertyName, slot); } + inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + if (symbolTableGet(propertyName, descriptor)) + return true; + return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName) { PropertySlot slot; @@ -358,11 +360,16 @@ namespace JSC { if (typeInfo().type() == ObjectType) return m_prototype; +#if USE(JSVALUE32) if (typeInfo().type() == StringType) return exec->lexicalGlobalObject()->stringPrototype(); ASSERT(typeInfo().type() == NumberType); return exec->lexicalGlobalObject()->numberPrototype(); +#else + ASSERT(typeInfo().type() == StringType); + return exec->lexicalGlobalObject()->stringPrototype(); +#endif } inline StructureChain* Structure::prototypeChain(ExecState* exec) const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 85f92f2..b11070f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -286,16 +286,12 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu if (JSValue parsedObject = preparser.tryLiteralParse()) return parsedObject; - int errLine; - UString errMsg; + EvalExecutable eval(makeSource(s)); + JSObject* error = eval.compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()); + if (error) + return throwError(exec, error); - SourceCode source = makeSource(s); - RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - - if (!evalNode) - return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL); - - return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); + return exec->interpreter()->execute(&eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); } JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -303,14 +299,18 @@ JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, co JSValue value = args.at(0); int32_t radix = args.at(1).toInt32(exec); - if (value.isNumber() && (radix == 0 || radix == 10)) { - if (value.isInt32Fast()) - return value; - double d = value.uncheckedGetNumber(); + if (radix != 0 && radix != 10) + return jsNumber(exec, parseInt(value.toString(exec), radix)); + + if (value.isInt32()) + return value; + + if (value.isDouble()) { + double d = value.asDouble(); if (isfinite(d)) return jsNumber(exec, (d > 0) ? floor(d) : ceil(d)); if (isnan(d) || isinf(d)) - return jsNaN(&exec->globalData()); + return jsNaN(exec); return jsNumber(exec, 0); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.cpp index 201e56c..846238d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.cpp @@ -21,83 +21,6 @@ #include "config.h" #include "JSImmediate.h" -#include "BooleanConstructor.h" -#include "BooleanPrototype.h" -#include "Error.h" -#include "ExceptionHelpers.h" -#include "JSGlobalObject.h" -#include "JSNotAnObject.h" -#include "NumberConstructor.h" -#include "NumberPrototype.h" - namespace JSC { -JSObject* JSImmediate::toThisObject(JSValue v, ExecState* exec) -{ - ASSERT(isImmediate(v)); - if (isNumber(v)) - return constructNumber(exec, v); - if (isBoolean(v)) - return constructBooleanFromImmediateBoolean(exec, v); - ASSERT(v.isUndefinedOrNull()); - return exec->globalThisValue(); -} - -JSObject* JSImmediate::toObject(JSValue v, ExecState* exec) -{ - ASSERT(isImmediate(v)); - if (isNumber(v)) - return constructNumber(exec, v); - if (isBoolean(v)) - return constructBooleanFromImmediateBoolean(exec, v); - - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); -} - -JSObject* JSImmediate::prototype(JSValue v, ExecState* exec) -{ - ASSERT(isImmediate(v)); - if (isNumber(v)) - return exec->lexicalGlobalObject()->numberPrototype(); - if (isBoolean(v)) - return exec->lexicalGlobalObject()->booleanPrototype(); - - JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, v.isNull()); - exec->setException(exception); - return new (exec) JSNotAnObject(exec, exception); -} - -UString JSImmediate::toString(JSValue v) -{ - ASSERT(isImmediate(v)); - if (isIntegerNumber(v)) - return UString::from(getTruncatedInt32(v)); -#if USE(ALTERNATE_JSIMMEDIATE) - if (isNumber(v)) { - ASSERT(isDoubleNumber(v)); - double value = doubleValue(v); - if (value == 0.0) // +0.0 or -0.0 - return "0"; - return UString::from(value); - } -#else - ASSERT(!isNumber(v)); -#endif - if (jsBoolean(false) == v) - return "false"; - if (jsBoolean(true) == v) - return "true"; - if (v.isNull()) - return "null"; - ASSERT(v.isUndefined()); - return "undefined"; -} - -NEVER_INLINE double JSImmediate::nonInlineNaN() -{ - return std::numeric_limits<double>::quiet_NaN(); -} - } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.h index e7d7847..053b4c0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSImmediate.h @@ -22,6 +22,10 @@ #ifndef JSImmediate_h #define JSImmediate_h +#include <wtf/Platform.h> + +#if !USE(JSVALUE32_64) + #include <wtf/Assertions.h> #include <wtf/AlwaysInline.h> #include <wtf/MathExtras.h> @@ -42,7 +46,7 @@ namespace JSC { class JSObject; class UString; -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) inline intptr_t reinterpretDoubleToIntptr(double value) { return WTF::bitwise_cast<intptr_t>(value); @@ -98,7 +102,7 @@ namespace JSC { /* * On 64-bit platforms, we support an alternative encoding form for immediates, if - * USE(ALTERNATE_JSIMMEDIATE) is defined. When this format is used, double precision + * USE(JSVALUE64) is defined. When this format is used, double precision * floating point values may also be encoded as JSImmediates. * * The encoding makes use of unused NaN space in the IEEE754 representation. Any value @@ -159,7 +163,7 @@ namespace JSC { friend JSValue jsNumber(JSGlobalData* globalData, long long i); friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i); -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) // If all bits in the mask are set, this indicates an integer number, // if any but not all are set this value is a double precision number. static const intptr_t TagTypeNumber = 0xffff000000000000ll; @@ -181,7 +185,7 @@ namespace JSC { static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined; static const intptr_t FullTagTypeNull = TagBitTypeOther; -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) static const int32_t IntegerPayloadShift = 0; #else static const int32_t IntegerPayloadShift = 1; @@ -204,15 +208,15 @@ namespace JSC { static ALWAYS_INLINE bool isIntegerNumber(JSValue v) { -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) return (rawValue(v) & TagTypeNumber) == TagTypeNumber; #else return isNumber(v); #endif } -#if USE(ALTERNATE_JSIMMEDIATE) - static ALWAYS_INLINE bool isDoubleNumber(JSValue v) +#if USE(JSVALUE64) + static ALWAYS_INLINE bool isDouble(JSValue v) { return isNumber(v) && !isIntegerNumber(v); } @@ -260,7 +264,7 @@ namespace JSC { static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2) { -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber; #else return rawValue(v1) & rawValue(v2) & TagTypeNumber; @@ -269,9 +273,6 @@ namespace JSC { static double toDouble(JSValue); static bool toBoolean(JSValue); - static JSObject* toObject(JSValue, ExecState*); - static JSObject* toThisObject(JSValue, ExecState*); - static UString toString(JSValue); static bool getUInt32(JSValue, uint32_t&); static bool getTruncatedInt32(JSValue, int32_t&); @@ -287,10 +288,8 @@ namespace JSC { static JSValue zeroImmediate(); static JSValue oneImmediate(); - static JSObject* prototype(JSValue, ExecState*); - private: -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) static const int minImmediateInt = ((-INT_MAX) - 1); static const int maxImmediateInt = INT_MAX; #else @@ -304,10 +303,10 @@ namespace JSC { return JSValue::makeImmediate(integer); } - // With USE(ALTERNATE_JSIMMEDIATE) we want the argument to be zero extended, so the + // With USE(JSVALUE64) we want the argument to be zero extended, so the // integer doesn't interfere with the tag bits in the upper word. In the default encoding, // if intptr_t id larger then int32_t we sign extend the value through the upper word. -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeInt(uint32_t value) #else static ALWAYS_INLINE JSValue makeInt(int32_t value) @@ -316,7 +315,7 @@ namespace JSC { return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber); } -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) static ALWAYS_INLINE JSValue makeDouble(double value) { return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset); @@ -341,7 +340,7 @@ namespace JSC { template<typename T> static JSValue fromNumberOutsideIntegerRange(T); -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) static ALWAYS_INLINE double doubleValue(JSValue v) { return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset); @@ -367,8 +366,6 @@ namespace JSC { { return v.immediateValue(); } - - static double nonInlineNaN(); }; ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); } @@ -378,7 +375,7 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); } ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); } -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) inline bool doubleToBoolean(double value) { return value < 0.0 || value > 0.0; @@ -405,7 +402,7 @@ namespace JSC { return intValue(v); } -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) template<typename T> inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value) { @@ -446,7 +443,7 @@ namespace JSC { ALWAYS_INLINE JSValue JSImmediate::from(int i) { -#if !USE(ALTERNATE_JSIMMEDIATE) +#if !USE(JSVALUE64) if ((i < minImmediateInt) | (i > maxImmediateInt)) return fromNumberOutsideIntegerRange(i); #endif @@ -512,9 +509,9 @@ namespace JSC { if (isIntegerNumber(v)) return intValue(v); -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) if (isNumber(v)) { - ASSERT(isDoubleNumber(v)); + ASSERT(isDouble(v)); return doubleValue(v); } #else @@ -545,12 +542,6 @@ namespace JSC { return getUInt32(v, i); } - // These are identical logic to the JSValue functions above, and faster than jsNumber(number).toInt32(). - int32_t toInt32(double); - uint32_t toUInt32(double); - int32_t toInt32SlowCase(double, bool& ok); - uint32_t toUInt32SlowCase(double, bool& ok); - inline JSValue::JSValue(JSNullTag) { *this = JSImmediate::nullImmediate(); @@ -581,6 +572,16 @@ namespace JSC { return JSImmediate::isBoolean(asValue()); } + inline bool JSValue::isTrue() const + { + return asValue() == JSImmediate::trueImmediate(); + } + + inline bool JSValue::isFalse() const + { + return asValue() == JSImmediate::falseImmediate(); + } + inline bool JSValue::getBoolean(bool& v) const { if (JSImmediate::isBoolean(asValue())) { @@ -596,99 +597,33 @@ namespace JSC { return asValue() == jsBoolean(true); } - ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const - { - int32_t i; - if (getTruncatedInt32(i)) - return i; - bool ignored; - return toInt32SlowCase(toNumber(exec), ignored); - } - - inline uint32_t JSValue::toUInt32(ExecState* exec) const - { - uint32_t i; - if (getTruncatedUInt32(i)) - return i; - bool ignored; - return toUInt32SlowCase(toNumber(exec), ignored); - } - - inline int32_t toInt32(double val) - { - if (!(val >= -2147483648.0 && val < 2147483648.0)) { - bool ignored; - return toInt32SlowCase(val, ignored); - } - return static_cast<int32_t>(val); - } - - inline uint32_t toUInt32(double val) - { - if (!(val >= 0.0 && val < 4294967296.0)) { - bool ignored; - return toUInt32SlowCase(val, ignored); - } - return static_cast<uint32_t>(val); - } - - inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const - { - int32_t i; - if (getTruncatedInt32(i)) { - ok = true; - return i; - } - return toInt32SlowCase(toNumber(exec), ok); - } - - inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const - { - uint32_t i; - if (getTruncatedUInt32(i)) { - ok = true; - return i; - } - return toUInt32SlowCase(toNumber(exec), ok); - } - inline bool JSValue::isCell() const { return !JSImmediate::isImmediate(asValue()); } - inline bool JSValue::isInt32Fast() const + inline bool JSValue::isInt32() const { return JSImmediate::isIntegerNumber(asValue()); } - inline int32_t JSValue::getInt32Fast() const + inline int32_t JSValue::asInt32() const { - ASSERT(isInt32Fast()); + ASSERT(isInt32()); return JSImmediate::getTruncatedInt32(asValue()); } - inline bool JSValue::isUInt32Fast() const + inline bool JSValue::isUInt32() const { return JSImmediate::isPositiveIntegerNumber(asValue()); } - inline uint32_t JSValue::getUInt32Fast() const + inline uint32_t JSValue::asUInt32() const { - ASSERT(isUInt32Fast()); + ASSERT(isUInt32()); return JSImmediate::getTruncatedUInt32(asValue()); } - inline JSValue JSValue::makeInt32Fast(int32_t i) - { - return JSImmediate::from(i); - } - - inline bool JSValue::areBothInt32Fast(JSValue v1, JSValue v2) - { - return JSImmediate::areBothImmediateIntegerNumbers(v1, v2); - } - class JSFastMath { public: static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2) @@ -739,7 +674,7 @@ namespace JSC { static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift) { ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift)); -#if USE(ALTERNATE_JSIMMEDIATE) +#if USE(JSVALUE64) return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber); #else return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber); @@ -787,4 +722,6 @@ namespace JSC { } // namespace JSC +#endif // !USE(JSVALUE32_64) + #endif // JSImmediate_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp index fb9cfe8..321762a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -74,11 +74,10 @@ JSObject* JSNotAnObject::toObject(ExecState* exec) const } // Marking -void JSNotAnObject::mark() +void JSNotAnObject::markChildren(MarkStack& markStack) { - JSCell::mark(); - if (!m_exception->marked()) - m_exception->mark(); + JSObject::markChildren(markStack); + markStack.append(m_exception); } // JSObject methods @@ -94,6 +93,12 @@ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&) return false; } +bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&) +{ + ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); + return false; +} + void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); @@ -116,7 +121,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned) return false; } -void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&, unsigned) +void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, bool) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h index 0aca63b..57347af 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -75,11 +75,12 @@ namespace JSC { virtual JSObject* toObject(ExecState*) const; // Marking - virtual void mark(); + virtual void markChildren(MarkStack&); // JSObject methods virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); @@ -87,7 +88,7 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); JSNotAnObjectErrorStub* m_exception; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.cpp index 669440b..f1009b9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.cpp @@ -23,13 +23,13 @@ #include "config.h" #include "JSNumberCell.h" +#if USE(JSVALUE32) + #include "NumberObject.h" #include "UString.h" namespace JSC { -#if !USE(ALTERNATE_JSIMMEDIATE) - JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSNumberCell*>(this); @@ -54,15 +54,11 @@ double JSNumberCell::toNumber(ExecState*) const UString JSNumberCell::toString(ExecState*) const { - if (m_value == 0.0) // +0.0 or -0.0 - return "0"; return UString::from(m_value); } UString JSNumberCell::toThisString(ExecState*) const { - if (m_value == 0.0) // +0.0 or -0.0 - return "0"; return UString::from(m_value); } @@ -82,22 +78,6 @@ bool JSNumberCell::getUInt32(uint32_t& uint32) const return uint32 == m_value; } -bool JSNumberCell::getTruncatedInt32(int32_t& int32) const -{ - if (!(m_value >= -2147483648.0 && m_value < 2147483648.0)) - return false; - int32 = static_cast<int32_t>(m_value); - return true; -} - -bool JSNumberCell::getTruncatedUInt32(uint32_t& uint32) const -{ - if (!(m_value >= 0.0 && m_value < 4294967296.0)) - return false; - uint32 = static_cast<uint32_t>(m_value); - return true; -} - JSValue JSNumberCell::getJSNumber() { return this; @@ -113,25 +93,21 @@ JSValue jsNumberCell(JSGlobalData* globalData, double d) return new (globalData) JSNumberCell(globalData, d); } -JSValue jsAPIMangledNumber(ExecState* exec, double d) -{ - return new (exec) JSNumberCell(JSNumberCell::APIMangled, d); -} +} // namespace JSC -#else +#else // USE(JSVALUE32) -JSValue jsNumberCell(ExecState*, double) -{ - ASSERT_NOT_REACHED(); - return JSValue(); -} +// Keep our exported symbols lists happy. +namespace JSC { + +JSValue jsNumberCell(ExecState*, double); -JSValue jsAPIMangledNumber(ExecState*, double) +JSValue jsNumberCell(ExecState*, double) { ASSERT_NOT_REACHED(); return JSValue(); } -#endif - } // namespace JSC + +#endif // USE(JSVALUE32) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h index a35e210..6a48081 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h @@ -35,10 +35,8 @@ namespace JSC { extern const double NaN; extern const double Inf; +#if USE(JSVALUE32) JSValue jsNumberCell(ExecState*, double); - JSValue jsAPIMangledNumber(ExecState*, double); - -#if !USE(ALTERNATE_JSIMMEDIATE) class Identifier; class JSCell; @@ -53,7 +51,7 @@ namespace JSC { friend class JIT; friend JSValue jsNumberCell(JSGlobalData*, double); friend JSValue jsNumberCell(ExecState*, double); - friend JSValue jsAPIMangledNumber(ExecState*, double); + public: double value() const { return m_value; } @@ -68,9 +66,6 @@ namespace JSC { virtual JSObject* toThisObject(ExecState*) const; virtual JSValue getJSNumber(); - static const uintptr_t JSAPIMangledMagicNumber = 0xbbadbeef; - bool isAPIMangledNumber() const { return m_structure == reinterpret_cast<Structure*>(JSAPIMangledMagicNumber); } - void* operator new(size_t size, ExecState* exec) { #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE @@ -89,7 +84,7 @@ namespace JSC { #endif } - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion | HasDefaultMark)); } private: JSNumberCell(JSGlobalData* globalData, double value) @@ -104,16 +99,7 @@ namespace JSC { { } - enum APIMangledTag { APIMangled }; - JSNumberCell(APIMangledTag, double value) - : JSCell(reinterpret_cast<Structure*>(JSAPIMangledMagicNumber)) - , m_value(value) - { - } - virtual bool getUInt32(uint32_t&) const; - virtual bool getTruncatedInt32(int32_t&) const; - virtual bool getTruncatedUInt32(uint32_t&) const; double m_value; }; @@ -131,7 +117,6 @@ namespace JSC { return static_cast<JSNumberCell*>(v.asCell()); } - inline JSValue::JSValue(ExecState* exec, double d) { JSValue v = JSImmediate::from(d); @@ -192,59 +177,30 @@ namespace JSC { *this = v ? v : jsNumberCell(globalData, i); } - inline JSValue::JSValue(JSGlobalData* globalData, long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline JSValue::JSValue(JSGlobalData* globalData, unsigned long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, i); - } - - inline JSValue::JSValue(JSGlobalData* globalData, long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, static_cast<double>(i)); - } - - inline JSValue::JSValue(JSGlobalData* globalData, unsigned long long i) - { - JSValue v = JSImmediate::from(i); - *this = v ? v : jsNumberCell(globalData, static_cast<double>(i)); - } - - inline bool JSValue::isDoubleNumber() const + inline bool JSValue::isDouble() const { return isNumberCell(asValue()); } - inline double JSValue::getDoubleNumber() const + inline double JSValue::asDouble() const { return asNumberCell(asValue())->value(); } inline bool JSValue::isNumber() const { - return JSImmediate::isNumber(asValue()) || isDoubleNumber(); + return JSImmediate::isNumber(asValue()) || isDouble(); } inline double JSValue::uncheckedGetNumber() const { ASSERT(isNumber()); - return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : getDoubleNumber(); + return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble(); } - inline bool JSValue::isAPIMangledNumber() - { - ASSERT(isNumber()); - return JSImmediate::isImmediate(asValue()) ? false : asNumberCell(asValue())->isAPIMangledNumber(); - } - -#else +#endif // USE(JSVALUE32) +#if USE(JSVALUE64) inline JSValue::JSValue(ExecState*, double d) { JSValue v = JSImmediate::from(d); @@ -315,40 +271,12 @@ namespace JSC { *this = v; } - inline JSValue::JSValue(JSGlobalData*, long i) - { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(JSGlobalData*, unsigned long i) + inline bool JSValue::isDouble() const { - JSValue v = JSImmediate::from(i); - ASSERT(v); - *this = v; - } - - inline JSValue::JSValue(JSGlobalData*, long long i) - { - JSValue v = JSImmediate::from(static_cast<double>(i)); - ASSERT(v); - *this = v; + return JSImmediate::isDouble(asValue()); } - inline JSValue::JSValue(JSGlobalData*, unsigned long long i) - { - JSValue v = JSImmediate::from(static_cast<double>(i)); - ASSERT(v); - *this = v; - } - - inline bool JSValue::isDoubleNumber() const - { - return JSImmediate::isDoubleNumber(asValue()); - } - - inline double JSValue::getDoubleNumber() const + inline double JSValue::asDouble() const { return JSImmediate::doubleValue(asValue()); } @@ -364,7 +292,9 @@ namespace JSC { return JSImmediate::toDouble(asValue()); } -#endif +#endif // USE(JSVALUE64) + +#if USE(JSVALUE32) || USE(JSVALUE64) inline JSValue::JSValue(ExecState*, char i) { @@ -390,30 +320,6 @@ namespace JSC { *this = JSImmediate::from(i); } - inline JSValue::JSValue(JSGlobalData*, char i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(JSGlobalData*, unsigned char i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(JSGlobalData*, short i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - - inline JSValue::JSValue(JSGlobalData*, unsigned short i) - { - ASSERT(JSImmediate::from(i)); - *this = JSImmediate::from(i); - } - inline JSValue jsNaN(ExecState* exec) { return jsNumber(exec, NaN); @@ -433,23 +339,10 @@ namespace JSC { inline bool JSValue::getNumber(double &result) const { - if (isInt32Fast()) - result = getInt32Fast(); - else if (LIKELY(isDoubleNumber())) - result = getDoubleNumber(); - else { - ASSERT(!isNumber()); - return false; - } - return true; - } - - inline bool JSValue::numberToInt32(int32_t& arg) - { - if (isInt32Fast()) - arg = getInt32Fast(); - else if (LIKELY(isDoubleNumber())) - arg = JSC::toInt32(getDoubleNumber()); + if (isInt32()) + result = asInt32(); + else if (LIKELY(isDouble())) + result = asDouble(); else { ASSERT(!isNumber()); return false; @@ -457,23 +350,7 @@ namespace JSC { return true; } - inline bool JSValue::numberToUInt32(uint32_t& arg) - { - if (isUInt32Fast()) - arg = getUInt32Fast(); - else if (LIKELY(isDoubleNumber())) - arg = JSC::toUInt32(getDoubleNumber()); - else if (isInt32Fast()) { - // FIXME: I think this case can be merged with the uint case; toUInt32SlowCase - // on a negative value is equivalent to simple static_casting. - bool ignored; - arg = toUInt32SlowCase(getInt32Fast(), ignored); - } else { - ASSERT(!isNumber()); - return false; - } - return true; - } +#endif // USE(JSVALUE32) || USE(JSVALUE64) } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp index bbbe3af..377c9d1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp @@ -67,7 +67,7 @@ public: ~Stringifier(); JSValue stringify(JSValue); - void mark(); + void markAggregate(MarkStack&); private: typedef UString StringBuilder; @@ -120,38 +120,47 @@ private: // ------------------------------ helper functions -------------------------------- -static inline JSValue unwrapBoxedPrimitive(JSValue value) +static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value) { if (!value.isObject()) return value; - if (!asObject(value)->inherits(&NumberObject::info) && !asObject(value)->inherits(&StringObject::info) && !asObject(value)->inherits(&BooleanObject::info)) - return value; - return static_cast<JSWrapperObject*>(asObject(value))->internalValue(); + JSObject* object = asObject(value); + if (object->inherits(&NumberObject::info)) + return jsNumber(exec, object->toNumber(exec)); + if (object->inherits(&StringObject::info)) + return jsString(exec, object->toString(exec)); + if (object->inherits(&BooleanObject::info)) + return object->toPrimitive(exec); + return value; } -static inline UString gap(JSValue space) +static inline UString gap(ExecState* exec, JSValue space) { - space = unwrapBoxedPrimitive(space); + const int maxGapLength = 10; + space = unwrapBoxedPrimitive(exec, space); // If the space value is a number, create a gap string with that number of spaces. double spaceCount; if (space.getNumber(spaceCount)) { - const int maxSpaceCount = 100; int count; - if (spaceCount > maxSpaceCount) - count = maxSpaceCount; + if (spaceCount > maxGapLength) + count = maxGapLength; else if (!(spaceCount > 0)) count = 0; else count = static_cast<int>(spaceCount); - UChar spaces[maxSpaceCount]; + UChar spaces[maxGapLength]; for (int i = 0; i < count; ++i) spaces[i] = ' '; return UString(spaces, count); } // If the space value is a string, use it as the gap string, otherwise use no gap string. - return space.getString(); + UString spaces = space.getString(); + if (spaces.size() > maxGapLength) { + spaces = spaces.substr(0, maxGapLength); + } + return spaces; } // ------------------------------ PropertyNameForFunctionCall -------------------------------- @@ -187,7 +196,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) , m_usingArrayReplacer(false) , m_arrayReplacerPropertyNames(exec) , m_replacerCallType(CallTypeNone) - , m_gap(gap(space)) + , m_gap(gap(exec, space)) { exec->globalData().firstStringifierToMark = this; @@ -202,12 +211,27 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) JSValue name = array->get(exec, i); if (exec->hadException()) break; + UString propertyName; - if (!name.getString(propertyName)) + if (name.getString(propertyName)) { + m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); continue; - if (exec->hadException()) - return; - m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); + } + + double value = 0; + if (name.getNumber(value)) { + m_arrayReplacerPropertyNames.add(Identifier::from(exec, value)); + continue; + } + + if (name.isObject()) { + if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info)) + continue; + propertyName = name.toString(exec); + if (exec->hadException()) + break; + m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); + } } return; } @@ -221,15 +245,12 @@ Stringifier::~Stringifier() m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark; } -void Stringifier::mark() +void Stringifier::markAggregate(MarkStack& markStack) { for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) { size_t size = m_holderStack.size(); - for (size_t i = 0; i < size; ++i) { - JSObject* object = m_holderStack[i].object(); - if (!object->marked()) - object->mark(); - } + for (size_t i = 0; i < size; ++i) + markStack.append(m_holderStack[i].object()); } } @@ -339,8 +360,6 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& value = toJSON(value, propertyName); if (m_exec->hadException()) return StringifyFailed; - if (value.isUndefined() && !holder->inherits(&JSArray::info)) - return StringifyFailedDueToUndefinedValue; // Call the replacer function. if (m_replacerCallType != CallTypeNone) { @@ -351,12 +370,18 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& return StringifyFailed; } + if (value.isUndefined() && !holder->inherits(&JSArray::info)) + return StringifyFailedDueToUndefinedValue; + if (value.isNull()) { builder.append("null"); return StringifySucceeded; } - value = unwrapBoxedPrimitive(value); + value = unwrapBoxedPrimitive(m_exec, value); + + if (m_exec->hadException()) + return StringifyFailed; if (value.isBoolean()) { builder.append(value.getBoolean() ? "true" : "false"); @@ -383,9 +408,18 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& JSObject* object = asObject(value); + CallData callData; + if (object->getCallData(callData) != CallTypeNone) { + if (holder->inherits(&JSArray::info)) { + builder.append("null"); + return StringifySucceeded; + } + return StringifyFailedDueToUndefinedValue; + } + // Handle cycle detection, and put the holder on the stack. if (!m_holderCycleDetector.add(object).second) { - throwError(m_exec, TypeError); + throwError(m_exec, TypeError, "JSON.stringify cannot serialize cyclic structures."); return StringifyFailed; } bool holderStackWasEmpty = m_holderStack.isEmpty(); @@ -394,7 +428,9 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& return StringifySucceeded; // If this is the outermost call, then loop to handle everything on the holder stack. - TimeoutChecker localTimeoutChecker(*m_exec->globalData().timeoutChecker); + //TimeoutChecker localTimeoutChecker(*m_exec->globalData().timeoutChecker); + TimeoutChecker localTimeoutChecker; + localTimeoutChecker.copyTimeoutValues(m_exec->globalData().timeoutChecker); localTimeoutChecker.reset(); unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck(); do { @@ -574,18 +610,17 @@ const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable }; bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - const HashEntry* entry = ExecState::jsonTable(exec)->entry(exec, propertyName); - if (!entry) - return JSObject::getOwnPropertySlot(exec, propertyName, slot); + return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, slot); +} - ASSERT(entry->attributes() & Function); - setUpStaticFunctionSlot(exec, entry, this, propertyName, slot); - return true; +bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor); } -void JSONObject::markStringifiers(Stringifier* stringifier) +void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier) { - stringifier->mark(); + stringifier->markAggregate(markStack); } class Walker { @@ -599,11 +634,11 @@ public: } JSValue walk(JSValue unfiltered); private: - JSValue callReviver(JSValue property, JSValue unfiltered) + JSValue callReviver(JSObject* thisObj, JSValue property, JSValue unfiltered) { JSValue args[] = { property, unfiltered }; ArgList argList(args, 2); - return call(m_exec, m_function, m_callType, m_callData, jsNull(), argList); + return call(m_exec, m_function, m_callType, m_callData, thisObj, argList); } friend class Holder; @@ -613,7 +648,10 @@ private: CallType m_callType; CallData m_callData; }; - + +// We clamp recursion well beyond anything reasonable, but we also have a timeout check +// to guard against "infinite" execution by inserting arbitrarily large objects. +static const unsigned maximumFilterRecursion = 40000; enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember, ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember }; NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) @@ -627,12 +665,22 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) WalkerState state = StateUnknown; JSValue inValue = unfiltered; JSValue outValue = jsNull(); + + TimeoutChecker localTimeoutChecker; + localTimeoutChecker.copyTimeoutValues(m_exec->globalData().timeoutChecker); + localTimeoutChecker.reset(); + unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck(); while (1) { switch (state) { arrayStartState: case ArrayStartState: { ASSERT(inValue.isObject()); - ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue))); + ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::info)); + if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) { + m_exec->setException(createStackOverflowError(m_exec)); + return jsUndefined(); + } + JSArray* array = asArray(inValue); arrayStack.append(array); indexStack.append(0); @@ -640,6 +688,14 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) } arrayStartVisitMember: case ArrayStartVisitMember: { + if (!--tickCount) { + if (localTimeoutChecker.didTimeOut(m_exec)) { + m_exec->setException(createInterruptedExecutionException(&m_exec->globalData())); + return jsUndefined(); + } + tickCount = localTimeoutChecker.ticksUntilNextCheck(); + } + JSArray* array = arrayStack.last(); uint32_t index = indexStack.last(); if (index == array->length()) { @@ -648,7 +704,16 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) indexStack.removeLast(); break; } - inValue = array->getIndex(index); + if (isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index)) + inValue = array->getIndex(index); + else { + PropertySlot slot; + if (array->getOwnPropertySlot(m_exec, index, slot)) + inValue = slot.getValue(m_exec, index); + else + inValue = jsUndefined(); + } + if (inValue.isObject()) { stateStack.append(ArrayEndVisitMember); goto stateUnknown; @@ -658,7 +723,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) } case ArrayEndVisitMember: { JSArray* array = arrayStack.last(); - array->setIndex(indexStack.last(), callReviver(jsString(m_exec, UString::from(indexStack.last())), outValue)); + JSValue filteredValue = callReviver(array, jsString(m_exec, UString::from(indexStack.last())), outValue); + if (filteredValue.isUndefined()) + array->deleteProperty(m_exec, indexStack.last()); + else { + if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last())) + array->setIndex(indexStack.last(), filteredValue); + else + array->put(m_exec, indexStack.last(), filteredValue); + } if (m_exec->hadException()) return jsNull(); indexStack.last()++; @@ -667,7 +740,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) objectStartState: case ObjectStartState: { ASSERT(inValue.isObject()); - ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue))); + ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::info)); + if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) { + m_exec->setException(createStackOverflowError(m_exec)); + return jsUndefined(); + } + JSObject* object = asObject(inValue); objectStack.append(object); indexStack.append(0); @@ -677,6 +755,14 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) } objectStartVisitMember: case ObjectStartVisitMember: { + if (!--tickCount) { + if (localTimeoutChecker.didTimeOut(m_exec)) { + m_exec->setException(createInterruptedExecutionException(&m_exec->globalData())); + return jsUndefined(); + } + tickCount = localTimeoutChecker.ticksUntilNextCheck(); + } + JSObject* object = objectStack.last(); uint32_t index = indexStack.last(); PropertyNameArray& properties = propertyStack.last(); @@ -688,9 +774,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) break; } PropertySlot slot; - object->getOwnPropertySlot(m_exec, properties[index], slot); - inValue = slot.getValue(m_exec, properties[index]); - ASSERT(!m_exec->hadException()); + if (object->getOwnPropertySlot(m_exec, properties[index], slot)) + inValue = slot.getValue(m_exec, properties[index]); + else + inValue = jsUndefined(); + + // The holder may be modified by the reviver function so any lookup may throw + if (m_exec->hadException()) + return jsNull(); + if (inValue.isObject()) { stateStack.append(ObjectEndVisitMember); goto stateUnknown; @@ -702,7 +794,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) JSObject* object = objectStack.last(); Identifier prop = propertyStack.last()[indexStack.last()]; PutPropertySlot slot; - object->put(m_exec, prop, callReviver(jsString(m_exec, prop.ustring()), outValue), slot); + JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue); + if (filteredValue.isUndefined()) + object->deleteProperty(m_exec, prop); + else + object->put(m_exec, prop, filteredValue, slot); if (m_exec->hadException()) return jsNull(); indexStack.last()++; @@ -714,16 +810,29 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) outValue = inValue; break; } - if (isJSArray(&m_exec->globalData(), asObject(inValue))) + JSObject* object = asObject(inValue); + if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info)) goto arrayStartState; goto objectStartState; } if (stateStack.isEmpty()) break; + state = stateStack.last(); stateStack.removeLast(); + + if (!--tickCount) { + if (localTimeoutChecker.didTimeOut(m_exec)) { + m_exec->setException(createInterruptedExecutionException(&m_exec->globalData())); + return jsUndefined(); + } + tickCount = localTimeoutChecker.ticksUntilNextCheck(); + } } - return callReviver(jsEmptyString(m_exec), outValue); + JSObject* finalHolder = constructEmptyObject(m_exec); + PutPropertySlot slot; + finalHolder->put(m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot); + return callReviver(finalHolder, jsEmptyString(m_exec), outValue); } // ECMA-262 v5 15.12.2 diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h index 8d5364a..0705a69 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h @@ -41,13 +41,14 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); } - static void markStringifiers(Stringifier*); + static void markStringifiers(MarkStack&, Stringifier*); private: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp index ded842d..d7f5344 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel (eric@webkit.org) * * This library is free software; you can redistribute it and/or @@ -30,6 +30,7 @@ #include "JSGlobalObject.h" #include "NativeErrorConstructor.h" #include "ObjectPrototype.h" +#include "PropertyDescriptor.h" #include "PropertyNameArray.h" #include "Lookup.h" #include "Nodes.h" @@ -37,48 +38,22 @@ #include <math.h> #include <wtf/Assertions.h> -#define JSOBJECT_MARK_TRACING 0 - -#if JSOBJECT_MARK_TRACING - -#define JSOBJECT_MARK_BEGIN() \ - static int markStackDepth = 0; \ - for (int i = 0; i < markStackDepth; i++) \ - putchar('-'); \ - printf("%s (%p)\n", className().UTF8String().c_str(), this); \ - markStackDepth++; \ - -#define JSOBJECT_MARK_END() \ - markStackDepth--; - -#else // JSOBJECT_MARK_TRACING - -#define JSOBJECT_MARK_BEGIN() -#define JSOBJECT_MARK_END() - -#endif // JSOBJECT_MARK_TRACING - namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); -void JSObject::mark() +void JSObject::markChildren(MarkStack& markStack) { - JSOBJECT_MARK_BEGIN(); - - JSCell::mark(); - m_structure->mark(); +#ifndef NDEBUG + bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation; + markStack.m_isCheckingForDefaultMarkViolation = false; +#endif - PropertyStorage storage = propertyStorage(); + markChildrenDirect(markStack); - size_t storageSize = m_structure->propertyStorageSize(); - for (size_t i = 0; i < storageSize; ++i) { - JSValue v = JSValue::decode(storage[i]); - if (!v.marked()) - v.mark(); - } - - JSOBJECT_MARK_END(); +#ifndef NDEBUG + markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation; +#endif } UString JSObject::className() const @@ -300,7 +275,7 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi return 0; } -void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction) +void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) { JSValue object = getDirect(propertyName); if (object && object.isGetterSetter()) { @@ -310,8 +285,8 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO } PutPropertySlot slot; - GetterSetter* getterSetter = new (exec) GetterSetter; - putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot); + GetterSetter* getterSetter = new (exec) GetterSetter(exec); + putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure @@ -327,7 +302,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO getterSetter->setGetter(getterFunction); } -void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction) +void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes) { JSValue object = getDirect(propertyName); if (object && object.isGetterSetter()) { @@ -337,8 +312,8 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO } PutPropertySlot slot; - GetterSetter* getterSetter = new (exec) GetterSetter; - putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot); + GetterSetter* getterSetter = new (exec) GetterSetter(exec); + putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure @@ -447,9 +422,14 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa return false; } -void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) +void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +{ + m_structure->getEnumerablePropertyNames(exec, propertyNames, this); +} + +void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) { - m_structure->getPropertyNames(exec, propertyNames, this, listedAttributes); + m_structure->getOwnPropertyNames(exec, propertyNames, this, includeNonEnumerable); } bool JSObject::toBoolean(ExecState*) const @@ -491,7 +471,7 @@ JSObject* JSObject::unwrappedObject() void JSObject::removeDirect(const Identifier& propertyName) { size_t offset; - if (m_structure->isDictionary()) { + if (m_structure->isUncacheableDictionary()) { offset = m_structure->removePropertyWithoutTransition(propertyName); if (offset != WTF::notFound) putDirectOffset(offset, jsUndefined()); @@ -543,4 +523,154 @@ JSObject* constructEmptyObject(ExecState* exec) return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); } +bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + unsigned attributes = 0; + JSCell* cell = 0; + size_t offset = m_structure->get(propertyName, attributes, cell); + if (offset == WTF::notFound) + return false; + descriptor.setDescriptor(getDirectOffset(offset), attributes); + return true; +} + +bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + JSObject* object = this; + while (true) { + if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor)) + return true; + JSValue prototype = object->prototype(); + if (!prototype.isObject()) + return false; + object = asObject(prototype); + } +} + +static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue) +{ + if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) { + target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter)); + return true; + } + attributes &= ~ReadOnly; + if (descriptor.getter() && descriptor.getter().isObject()) + target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes); + if (exec->hadException()) + return false; + if (descriptor.setter() && descriptor.setter().isObject()) + target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes); + return !exec->hadException(); +} + +bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) +{ + // If we have a new property we can just put it on normally + PropertyDescriptor current; + if (!getOwnPropertyDescriptor(exec, propertyName, current)) + return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined()); + + if (descriptor.isEmpty()) + return true; + + if (current.equalTo(descriptor)) + return true; + + // Filter out invalid changes + if (!current.configurable()) { + if (descriptor.configurable()) { + if (throwException) + throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property."); + return false; + } + if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) { + if (throwException) + throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property."); + return false; + } + } + + // A generic descriptor is simply changing the attributes of an existing property + if (descriptor.isGenericDescriptor()) { + if (!current.attributesEqual(descriptor)) { + deleteProperty(exec, propertyName); + putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value()); + } + return true; + } + + // Changing between a normal property or an accessor property + if (descriptor.isDataDescriptor() != current.isDataDescriptor()) { + if (!current.configurable()) { + if (throwException) + throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property."); + return false; + } + deleteProperty(exec, propertyName); + return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined()); + } + + // Changing the value and attributes of an existing property + if (descriptor.isDataDescriptor()) { + if (!current.configurable()) { + if (!current.writable() && descriptor.writable()) { + if (throwException) + throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property."); + return false; + } + if (!current.writable()) { + if (descriptor.value() || !JSValue::strictEqual(current.value(), descriptor.value())) { + if (throwException) + throwError(exec, TypeError, "Attempting to change value of a readonly property."); + return false; + } + } + } else if (current.attributesEqual(descriptor)) { + if (!descriptor.value()) + return true; + PutPropertySlot slot; + put(exec, propertyName, descriptor.value(), slot); + if (exec->hadException()) + return false; + return true; + } + deleteProperty(exec, propertyName); + return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value()); + } + + // Changing the accessor functions of an existing accessor property + ASSERT(descriptor.isAccessorDescriptor()); + if (!current.configurable()) { + if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(current.setter(), descriptor.setter()))) { + if (throwException) + throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property."); + return false; + } + if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(current.getter(), descriptor.getter()))) { + if (throwException) + throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property."); + return false; + } + } + JSValue accessor = getDirect(propertyName); + if (!accessor) + return false; + GetterSetter* getterSetter = asGetterSetter(accessor); + if (current.attributesEqual(descriptor)) { + if (descriptor.setter()) + getterSetter->setSetter(asObject(descriptor.setter())); + if (descriptor.getter()) + getterSetter->setGetter(asObject(descriptor.getter())); + return true; + } + deleteProperty(exec, propertyName); + unsigned attrs = current.attributesWithOverride(descriptor); + if (descriptor.setter()) + attrs |= Setter; + if (descriptor.getter()) + attrs |= Getter; + putDirect(propertyName, getterSetter, attrs); + return true; +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h index 35f7832..9eb4e3e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -27,12 +27,15 @@ #include "ClassInfo.h" #include "CommonIdentifiers.h" #include "CallFrame.h" +#include "JSCell.h" #include "JSNumberCell.h" +#include "MarkStack.h" #include "PropertySlot.h" #include "PutPropertySlot.h" #include "ScopeChain.h" #include "Structure.h" #include "JSGlobalData.h" +#include <wtf/StdLibExtras.h> namespace JSC { @@ -42,11 +45,12 @@ namespace JSC { return value.asCell(); return 0; } - + + class HashEntry; class InternalFunction; + class PropertyDescriptor; class PropertyNameArray; class Structure; - struct HashEntry; struct HashTable; // ECMA 262-3 8.6.1 @@ -72,14 +76,13 @@ namespace JSC { public: explicit JSObject(PassRefPtr<Structure>); - virtual void mark(); + virtual void markChildren(MarkStack&); + ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack); // The inline virtual destructor cannot be the first virtual function declared // in the class as it results in the vtable being generated as a weak symbol virtual ~JSObject(); - bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); } - JSValue prototype() const; void setPrototype(JSValue prototype); @@ -93,9 +96,11 @@ namespace JSC { bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue value); @@ -116,7 +121,9 @@ namespace JSC { virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty); - virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); + + virtual void getPropertyNames(ExecState*, PropertyNameArray&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); @@ -179,16 +186,18 @@ namespace JSC { void fillGetterPropertySlot(PropertySlot&, JSValue* location); - virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction); - virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction); + virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); + virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName); virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName); + virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } virtual bool isActivationObject() const { return false; } virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } + #ifdef QT_BUILD_SCRIPT_LIB virtual bool compareToObject(ExecState*, JSObject *other) { return other == this; } #endif @@ -197,15 +206,38 @@ namespace JSC { void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } - static const size_t inlineStorageCapacity = 3; + static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; static const size_t nonInlineBaseStorageCapacity = 16; static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + } + + protected: + void addAnonymousSlots(unsigned count); + void putAnonymousValue(unsigned index, JSValue value) + { + *locationForOffset(index) = value; + } + JSValue getAnonymousValue(unsigned index) + { + return *locationForOffset(index); } private: + // Nobody should ever ask any of these questions on something already known to be a JSObject. + using JSCell::isAPIValueWrapper; + using JSCell::isGetterSetter; + using JSCell::toObject; + void getObject(); + void getString(); + void isObject(); + void isString(); +#if USE(JSVALUE32) + void isNumber(); +#endif + ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); } @@ -228,22 +260,25 @@ namespace JSC { const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; Structure* createInheritorID(); - RefPtr<Structure> m_inheritorID; - union { PropertyStorage m_externalStorage; EncodedJSValue m_inlineStorage[inlineStorageCapacity]; }; - }; - JSObject* asObject(JSValue); + RefPtr<Structure> m_inheritorID; + }; + +JSObject* constructEmptyObject(ExecState*); - JSObject* constructEmptyObject(ExecState*); +inline JSObject* asObject(JSCell* cell) +{ + ASSERT(cell->isObject()); + return static_cast<JSObject*>(cell); +} inline JSObject* asObject(JSValue value) { - ASSERT(asCell(value)->isObject()); - return static_cast<JSObject*>(asCell(value)); + return asObject(value.asCell()); } inline JSObject::JSObject(PassRefPtr<Structure> structure) @@ -253,6 +288,9 @@ inline JSObject::JSObject(PassRefPtr<Structure> structure) ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); +#if USE(JSVALUE64) || USE(JSVALUE32_64) + ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0); +#endif } inline JSObject::~JSObject() @@ -293,7 +331,7 @@ inline bool Structure::isUsingInlineStorage() const return (propertyStorageCapacity() == JSObject::inlineStorageCapacity); } -inline bool JSCell::isObject(const ClassInfo* info) const +inline bool JSCell::inherits(const ClassInfo* info) const { for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) { if (ci == info) @@ -302,10 +340,10 @@ inline bool JSCell::isObject(const ClassInfo* info) const return false; } -// this method is here to be after the inline declaration of JSCell::isObject -inline bool JSValue::isObject(const ClassInfo* classInfo) const +// this method is here to be after the inline declaration of JSCell::inherits +inline bool JSValue::inherits(const ClassInfo* classInfo) const { - return isCell() && asCell()->isObject(classInfo); + return isCell() && asCell()->inherits(classInfo); } ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -454,7 +492,18 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue return; } + // If we have a specific function, we may have got to this point if there is + // already a transition with the correct property name and attributes, but + // specialized to a different function. In this case we just want to give up + // and despecialize the transition. + // In this case we clear the value of specificFunction which will result + // in us adding a non-specific transition, and any subsequent lookup in + // Structure::addPropertyTransitionToExistingStructure will just use that. + if (specificFunction && m_structure->hasTransition(propertyName, attributes)) + specificFunction = 0; + RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset); + if (currentCapacity != structure->propertyStorageCapacity()) allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); @@ -480,6 +529,17 @@ inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value)); } +inline void JSObject::addAnonymousSlots(unsigned count) +{ + size_t currentCapacity = m_structure->propertyStorageCapacity(); + RefPtr<Structure> structure = Structure::addAnonymousSlotsTransition(m_structure, count); + + if (currentCapacity != structure->propertyStorageCapacity()) + allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity()); + + setStructure(structure.release()); +} + inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { ASSERT(value); @@ -544,7 +604,7 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) con inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const { if (UNLIKELY(!isCell())) { - JSObject* prototype = JSImmediate::prototype(asValue(), exec); + JSObject* prototype = synthesizePrototype(exec); if (propertyName == exec->propertyNames().underscoreProto) return prototype; if (!prototype->getPropertySlot(exec, propertyName, slot)) @@ -555,8 +615,7 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro while (true) { if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); - ASSERT(cell->isObject()); - JSValue prototype = static_cast<JSObject*>(cell)->prototype(); + JSValue prototype = asObject(cell)->prototype(); if (!prototype.isObject()) return jsUndefined(); cell = asObject(prototype); @@ -572,7 +631,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const { if (UNLIKELY(!isCell())) { - JSObject* prototype = JSImmediate::prototype(asValue(), exec); + JSObject* prototype = synthesizePrototype(exec); if (!prototype->getPropertySlot(exec, propertyName, slot)) return jsUndefined(); return slot.getValue(exec, propertyName); @@ -581,8 +640,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot while (true) { if (cell->getOwnPropertySlot(exec, propertyName, slot)) return slot.getValue(exec, propertyName); - ASSERT(cell->isObject()); - JSValue prototype = static_cast<JSObject*>(cell)->prototype(); + JSValue prototype = asObject(cell)->prototype(); if (!prototype.isObject()) return jsUndefined(); cell = prototype.asCell(); @@ -592,7 +650,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (UNLIKELY(!isCell())) { - JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value, slot); + synthesizeObject(exec)->put(exec, propertyName, value, slot); return; } asCell()->put(exec, propertyName, value, slot); @@ -601,7 +659,7 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) { if (UNLIKELY(!isCell())) { - JSImmediate::toObject(asValue(), exec)->put(exec, propertyName, value); + synthesizeObject(exec)->put(exec, propertyName, value); return; } asCell()->put(exec, propertyName, value); @@ -627,6 +685,17 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_ m_externalStorage = newPropertyStorage; } +ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) +{ + JSCell::markChildren(markStack); + + m_structure->markAggregate(markStack); + + PropertyStorage storage = propertyStorage(); + size_t storageSize = m_structure->propertyStorageSize(); + markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize); +} + } // namespace JSC #endif // JSObject_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index 8c7b53d..e08a3d9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,47 +37,11 @@ JSPropertyNameIterator::~JSPropertyNameIterator() { } -JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const +void JSPropertyNameIterator::markChildren(MarkStack& markStack) { - ASSERT_NOT_REACHED(); - return JSValue(); -} - -bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&) -{ - ASSERT_NOT_REACHED(); - return false; -} - -bool JSPropertyNameIterator::toBoolean(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return false; -} - -double JSPropertyNameIterator::toNumber(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return 0; -} - -UString JSPropertyNameIterator::toString(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return ""; -} - -JSObject* JSPropertyNameIterator::toObject(ExecState*) const -{ - ASSERT_NOT_REACHED(); - return 0; -} - -void JSPropertyNameIterator::mark() -{ - JSCell::mark(); - if (m_object && !m_object->marked()) - m_object->mark(); + JSCell::markChildren(markStack); + if (m_object) + markStack.append(m_object); } void JSPropertyNameIterator::invalidate() diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h index 9817c07..d2849a8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,21 +44,18 @@ namespace JSC { virtual ~JSPropertyNameIterator(); - virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&); - virtual bool toBoolean(ExecState*) const; - virtual double toNumber(ExecState*) const; - virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; - - virtual void mark(); + virtual void markChildren(MarkStack&); JSValue next(ExecState*); void invalidate(); - + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(CompoundType)); + } private: - JSPropertyNameIterator(); - JSPropertyNameIterator(JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData); + JSPropertyNameIterator(ExecState*); + JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData); JSObject* m_object; RefPtr<PropertyNameArrayData> m_data; @@ -66,16 +63,16 @@ namespace JSC { PropertyNameArrayData::const_iterator m_end; }; -inline JSPropertyNameIterator::JSPropertyNameIterator() - : JSCell(0) +inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec) + : JSCell(exec->globalData().propertyNameIteratorStructure.get()) , m_object(0) , m_position(0) , m_end(0) { } -inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData) - : JSCell(0) +inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData) + : JSCell(exec->globalData().propertyNameIteratorStructure.get()) , m_object(object) , m_data(propertyNameArrayData) , m_position(m_data->begin()) @@ -86,12 +83,12 @@ inline JSPropertyNameIterator::JSPropertyNameIterator(JSObject* object, PassRefP inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v) { if (v.isUndefinedOrNull()) - return new (exec) JSPropertyNameIterator; + return new (exec) JSPropertyNameIterator(exec); JSObject* o = v.toObject(exec); PropertyNameArray propertyNames(exec); o->getPropertyNames(exec, propertyNames); - return new (exec) JSPropertyNameIterator(o, propertyNames.releaseData()); + return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData()); } inline JSValue JSPropertyNameIterator::next(ExecState* exec) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 85907c8..a877ec6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,12 +31,10 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject); -void JSStaticScopeObject::mark() +void JSStaticScopeObject::markChildren(MarkStack& markStack) { - JSVariableObject::mark(); - - if (!d()->registerStore.marked()) - d()->registerStore.mark(); + JSVariableObject::markChildren(markStack); + markStack.append(d()->registerStore.jsValue()); } JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h index 2caf540..5eb0e4b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,7 +50,7 @@ namespace JSC{ symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes)); } virtual ~JSStaticScopeObject(); - virtual void mark(); + virtual void markChildren(MarkStack&); bool isDynamicScope() const; virtual JSObject* toThisObject(ExecState*) const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp index e1fc66d..a30f729 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp @@ -103,6 +103,33 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam return true; } +bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (propertyName == exec->propertyNames().length) { + descriptor.setDescriptor(jsNumber(exec, m_value.size()), DontEnum | DontDelete | ReadOnly); + return true; + } + + bool isStrictUInt32; + unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); + if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { + descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly); + return true; + } + + return false; +} + +bool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (getStringPropertyDescriptor(exec, propertyName, descriptor)) + return true; + if (propertyName != exec->propertyNames().underscoreProto) + return false; + descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum); + return true; +} + bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { // The semantics here are really getPropertySlot, not getOwnPropertySlot. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h index 6db9322..eeada2e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h @@ -23,10 +23,11 @@ #ifndef JSString_h #define JSString_h -#include "CommonIdentifiers.h" #include "CallFrame.h" +#include "CommonIdentifiers.h" #include "Identifier.h" #include "JSNumberCell.h" +#include "PropertyDescriptor.h" #include "PropertySlot.h" namespace JSC { @@ -60,7 +61,7 @@ namespace JSC { class JSString : public JSCell { friend class JIT; - friend class VPtrSet; + friend struct VPtrSet; public: JSString(JSGlobalData* globalData, const UString& value) @@ -86,13 +87,14 @@ namespace JSC { bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); bool getStringPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned&) const; bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); } JSString* getIndex(JSGlobalData*, unsigned); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion | HasDefaultMark)); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -115,6 +117,7 @@ namespace JSC { // Actually getPropertySlot, not getOwnPropertySlot (see JSCell). virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); UString m_value; }; @@ -210,7 +213,27 @@ namespace JSC { inline JSString* JSValue::toThisJSString(ExecState* exec) { - return JSImmediate::isImmediate(asValue()) ? jsString(exec, JSImmediate::toString(asValue())) : asCell()->toThisJSString(exec); + return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec)); + } + + inline UString JSValue::toString(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(); + if (isInt32()) + return exec->globalData().numericStrings.add(asInt32()); + if (isDouble()) + return exec->globalData().numericStrings.add(asDouble()); + if (isTrue()) + return "true"; + if (isFalse()) + return "false"; + if (isNull()) + return "null"; + if (isUndefined()) + return "undefined"; + ASSERT(isCell()); + return asCell()->toString(exec); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSType.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSType.h index 68f2890..882b218 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSType.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSType.h @@ -33,8 +33,10 @@ namespace JSC { NumberType = 3, NullType = 4, StringType = 5, - ObjectType = 6, - GetterSetterType = 7 + // The CompoundType value must come before any JSType that may have children + CompoundType = 6, + ObjectType = 7, + GetterSetterType = 8 }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h index bea188b..279510b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h @@ -27,6 +27,9 @@ #ifndef JSTypeInfo_h #define JSTypeInfo_h +// This file would be called TypeInfo.h, but that conflicts with <typeinfo.h> +// in the STL on systems without case-sensitive file systems. + #include "JSType.h" namespace JSC { @@ -38,6 +41,8 @@ namespace JSC { static const unsigned ImplementsDefaultHasInstance = 1 << 3; static const unsigned NeedsThisConversion = 1 << 4; static const unsigned HasStandardGetOwnPropertySlot = 1 << 5; + static const unsigned HasDefaultMark = 1 << 6; + static const unsigned HasDefaultGetPropertyNames = 1 << 7; class TypeInfo { friend class JIT; @@ -59,7 +64,8 @@ namespace JSC { bool overridesHasInstance() const { return m_flags & OverridesHasInstance; } bool needsThisConversion() const { return m_flags & NeedsThisConversion; } bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; } - + bool hasDefaultMark() const { return m_flags & HasDefaultMark; } + bool hasDefaultGetPropertyNames() const { return m_flags & HasDefaultGetPropertyNames; } unsigned flags() const { return m_flags; } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.cpp index 885914d..39a4093 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.cpp @@ -23,8 +23,15 @@ #include "config.h" #include "JSValue.h" +#include "BooleanConstructor.h" +#include "BooleanPrototype.h" +#include "ExceptionHelpers.h" +#include "JSGlobalObject.h" #include "JSFunction.h" +#include "JSNotAnObject.h" +#include "NumberObject.h" #include <wtf/MathExtras.h> +#include <wtf/StringExtras.h> namespace JSC { @@ -33,19 +40,97 @@ static const double D32 = 4294967296.0; // ECMA 9.4 double JSValue::toInteger(ExecState* exec) const { - if (isInt32Fast()) - return getInt32Fast(); + if (isInt32()) + return asInt32(); double d = toNumber(exec); return isnan(d) ? 0.0 : trunc(d); } double JSValue::toIntegerPreserveNaN(ExecState* exec) const { - if (isInt32Fast()) - return getInt32Fast(); + if (isInt32()) + return asInt32(); return trunc(toNumber(exec)); } +JSObject* JSValue::toObjectSlowCase(ExecState* exec) const +{ + ASSERT(!isCell()); + + if (isInt32() || isDouble()) + return constructNumber(exec, asValue()); + if (isTrue() || isFalse()) + return constructBooleanFromImmediateBoolean(exec, asValue()); + ASSERT(isUndefinedOrNull()); + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); + exec->setException(exception); + return new (exec) JSNotAnObject(exec, exception); +} + +JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const +{ + ASSERT(!isCell()); + + if (isInt32() || isDouble()) + return constructNumber(exec, asValue()); + if (isTrue() || isFalse()) + return constructBooleanFromImmediateBoolean(exec, asValue()); + ASSERT(isUndefinedOrNull()); + return exec->globalThisValue(); +} + +JSObject* JSValue::synthesizeObject(ExecState* exec) const +{ + ASSERT(!isCell()); + if (isNumber()) + return constructNumber(exec, asValue()); + if (isBoolean()) + return constructBooleanFromImmediateBoolean(exec, asValue()); + + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); + exec->setException(exception); + return new (exec) JSNotAnObject(exec, exception); +} + +JSObject* JSValue::synthesizePrototype(ExecState* exec) const +{ + ASSERT(!isCell()); + if (isNumber()) + return exec->lexicalGlobalObject()->numberPrototype(); + if (isBoolean()) + return exec->lexicalGlobalObject()->booleanPrototype(); + + JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull()); + exec->setException(exception); + return new (exec) JSNotAnObject(exec, exception); +} + +#ifndef NDEBUG +char* JSValue::description() +{ + static const size_t size = 32; + static char description[size]; + if (isInt32()) + snprintf(description, size, "Int32: %d", asInt32()); + else if (isDouble()) + snprintf(description, size, "Double: %lf", asDouble()); + else if (isCell()) + snprintf(description, size, "Cell: %p", asCell()); + else if (isTrue()) + snprintf(description, size, "True"); + else if (isFalse()) + snprintf(description, size, "False"); + else if (isNull()) + snprintf(description, size, "Null"); + else { + ASSERT(isUndefined()); + snprintf(description, size, "Undefined"); + } + + return description; +} +#endif + int32_t toInt32SlowCase(double d, bool& ok) { ok = true; @@ -84,4 +169,9 @@ uint32_t toUInt32SlowCase(double d, bool& ok) return static_cast<uint32_t>(d32); } +NEVER_INLINE double nonInlineNaN() +{ + return std::numeric_limits<double>::quiet_NaN(); +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h index 391425c..58e74b1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,16 +20,18 @@ * */ -#include <stddef.h> // for size_t -#include <stdint.h> - #ifndef JSValue_h #define JSValue_h #include "CallData.h" #include "ConstructData.h" -#include <wtf/HashTraits.h> +#include <math.h> +#include <stddef.h> // for size_t +#include <stdint.h> #include <wtf/AlwaysInline.h> +#include <wtf/Assertions.h> +#include <wtf/HashTraits.h> +#include <wtf/MathExtras.h> namespace JSC { @@ -48,31 +50,37 @@ namespace JSC { enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; +#if USE(JSVALUE32_64) + typedef int64_t EncodedJSValue; +#else typedef void* EncodedJSValue; +#endif + + double nonInlineNaN(); + int32_t toInt32SlowCase(double, bool& ok); + uint32_t toUInt32SlowCase(double, bool& ok); class JSValue { friend class JSImmediate; - friend struct JSValueHashTraits; - - static JSValue makeImmediate(intptr_t value) - { - return JSValue(reinterpret_cast<JSCell*>(value)); - } + friend struct EncodedJSValueHashTraits; + friend class JIT; + friend class JITStubs; + friend class JITStubCall; - intptr_t immediateValue() - { - return reinterpret_cast<intptr_t>(m_ptr); - } - public: + static EncodedJSValue encode(JSValue value); + static JSValue decode(EncodedJSValue ptr); +#if !USE(JSVALUE32_64) + private: + static JSValue makeImmediate(intptr_t value); + intptr_t immediateValue(); + public: +#endif enum JSNullTag { JSNull }; enum JSUndefinedTag { JSUndefined }; enum JSTrueTag { JSTrue }; enum JSFalseTag { JSFalse }; - static EncodedJSValue encode(JSValue value); - static JSValue decode(EncodedJSValue ptr); - JSValue(); JSValue(JSNullTag); JSValue(JSUndefinedTag); @@ -94,20 +102,22 @@ namespace JSC { JSValue(ExecState*, long long); JSValue(ExecState*, unsigned long long); JSValue(JSGlobalData*, double); - JSValue(JSGlobalData*, char); - JSValue(JSGlobalData*, unsigned char); - JSValue(JSGlobalData*, short); - JSValue(JSGlobalData*, unsigned short); JSValue(JSGlobalData*, int); JSValue(JSGlobalData*, unsigned); - JSValue(JSGlobalData*, long); - JSValue(JSGlobalData*, unsigned long); - JSValue(JSGlobalData*, long long); - JSValue(JSGlobalData*, unsigned long long); operator bool() const; - bool operator==(const JSValue other) const; - bool operator!=(const JSValue other) const; + bool operator==(const JSValue& other) const; + bool operator!=(const JSValue& other) const; + + bool isInt32() const; + bool isUInt32() const; + bool isDouble() const; + bool isTrue() const; + bool isFalse() const; + + int32_t asInt32() const; + uint32_t asUInt32() const; + double asDouble() const; // Querying the type. bool isUndefined() const; @@ -118,7 +128,7 @@ namespace JSC { bool isString() const; bool isGetterSetter() const; bool isObject() const; - bool isObject(const ClassInfo*) const; + bool inherits(const ClassInfo*) const; // Extracting the value. bool getBoolean(bool&) const; @@ -134,8 +144,6 @@ namespace JSC { // Extracting integer values. bool getUInt32(uint32_t&) const; - bool getTruncatedInt32(int32_t&) const; - bool getTruncatedUInt32(uint32_t&) const; // Basic conversions. JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; @@ -151,38 +159,17 @@ namespace JSC { JSObject* toObject(ExecState*) const; // Integer conversions. - // 'x.numberToInt32(output)' is equivalent to 'x.isNumber() && x.toInt32(output)' double toInteger(ExecState*) const; double toIntegerPreserveNaN(ExecState*) const; int32_t toInt32(ExecState*) const; int32_t toInt32(ExecState*, bool& ok) const; - bool numberToInt32(int32_t& arg); uint32_t toUInt32(ExecState*) const; uint32_t toUInt32(ExecState*, bool& ok) const; - bool numberToUInt32(uint32_t& arg); - - // Fast integer operations; these values return results where the value is trivially available - // in a convenient form, for use in optimizations. No assumptions should be made based on the - // results of these operations, for example !isInt32Fast() does not necessarily indicate the - // result of getNumber will not be 0. - bool isInt32Fast() const; - int32_t getInt32Fast() const; - bool isUInt32Fast() const; - uint32_t getUInt32Fast() const; - static JSValue makeInt32Fast(int32_t); - static bool areBothInt32Fast(JSValue, JSValue); // Floating point conversions (this is a convenience method for webcore; // signle precision float is not a representation used in JS or JSC). float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } - // API Mangled Numbers - bool isAPIMangledNumber(); - - // Garbage collection. - void mark(); - bool marked() const; - // Object operations, with the toObject operation included. JSValue get(ExecState*, const Identifier& propertyName) const; JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const; @@ -208,22 +195,72 @@ namespace JSC { bool isCell() const; JSCell* asCell() const; +#ifndef NDEBUG + char* description(); +#endif + private: enum HashTableDeletedValueTag { HashTableDeletedValue }; JSValue(HashTableDeletedValueTag); inline const JSValue asValue() const { return *this; } + JSObject* toObjectSlowCase(ExecState*) const; + JSObject* toThisObjectSlowCase(ExecState*) const; + + enum { Int32Tag = 0xffffffff }; + enum { CellTag = 0xfffffffe }; + enum { TrueTag = 0xfffffffd }; + enum { FalseTag = 0xfffffffc }; + enum { NullTag = 0xfffffffb }; + enum { UndefinedTag = 0xfffffffa }; + enum { DeletedValueTag = 0xfffffff9 }; + + enum { LowestTag = DeletedValueTag }; + + uint32_t tag() const; + int32_t payload() const; + + JSObject* synthesizePrototype(ExecState*) const; + JSObject* synthesizeObject(ExecState*) const; + +#if USE(JSVALUE32_64) + union { + EncodedJSValue asEncodedJSValue; + double asDouble; +#if PLATFORM(BIG_ENDIAN) + struct { + int32_t tag; + int32_t payload; + } asBits; +#else + struct { + int32_t payload; + int32_t tag; + } asBits; +#endif + } u; +#else // USE(JSVALUE32_64) + JSCell* m_ptr; +#endif // USE(JSVALUE32_64) + }; - bool isDoubleNumber() const; - double getDoubleNumber() const; +#if USE(JSVALUE32_64) + typedef IntHash<EncodedJSValue> EncodedJSValueHash; - JSCell* m_ptr; + struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> { + static const bool emptyValueIsZero = false; + static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); } + static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } }; +#else + typedef PtrHash<EncodedJSValue> EncodedJSValueHash; - struct JSValueHashTraits : HashTraits<EncodedJSValue> { + struct EncodedJSValueHashTraits : HashTraits<EncodedJSValue> { static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } }; +#endif // Stand-alone helper functions. inline JSValue jsNull() @@ -301,61 +338,396 @@ namespace JSC { return JSValue(globalData, d); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, char i) + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i) { return JSValue(globalData, i); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned char i) + ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i) { return JSValue(globalData, i); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, short i) + inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); } + inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; } + + inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } + inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } + + inline int32_t toInt32(double val) { - return JSValue(globalData, i); + if (!(val >= -2147483648.0 && val < 2147483648.0)) { + bool ignored; + return toInt32SlowCase(val, ignored); + } + return static_cast<int32_t>(val); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned short i) + inline uint32_t toUInt32(double val) { - return JSValue(globalData, i); + if (!(val >= 0.0 && val < 4294967296.0)) { + bool ignored; + return toUInt32SlowCase(val, ignored); + } + return static_cast<uint32_t>(val); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i) + ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const { - return JSValue(globalData, i); + if (isInt32()) + return asInt32(); + bool ignored; + return toInt32SlowCase(toNumber(exec), ignored); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i) + inline uint32_t JSValue::toUInt32(ExecState* exec) const { - return JSValue(globalData, i); + if (isUInt32()) + return asInt32(); + bool ignored; + return toUInt32SlowCase(toNumber(exec), ignored); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, long i) + inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const { - return JSValue(globalData, i); + if (isInt32()) { + ok = true; + return asInt32(); + } + return toInt32SlowCase(toNumber(exec), ok); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned long i) + inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const { - return JSValue(globalData, i); + if (isUInt32()) { + ok = true; + return asInt32(); + } + return toUInt32SlowCase(toNumber(exec), ok); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, long long i) +#if USE(JSVALUE32_64) + inline JSValue jsNaN(ExecState* exec) { - return JSValue(globalData, i); + return JSValue(exec, nonInlineNaN()); } - ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned long long i) + // JSValue member functions. + inline EncodedJSValue JSValue::encode(JSValue value) { - return JSValue(globalData, i); + return value.u.asEncodedJSValue; } - inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); } - inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; } + inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) + { + JSValue v; + v.u.asEncodedJSValue = encodedJSValue; + return v; + } - inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } - inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } + inline JSValue::JSValue() + { + u.asBits.tag = CellTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSNullTag) + { + u.asBits.tag = NullTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSUndefinedTag) + { + u.asBits.tag = UndefinedTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSTrueTag) + { + u.asBits.tag = TrueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSFalseTag) + { + u.asBits.tag = FalseTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(HashTableDeletedValueTag) + { + u.asBits.tag = DeletedValueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSCell* ptr) + { + u.asBits.tag = CellTag; + u.asBits.payload = reinterpret_cast<int32_t>(ptr); + } + + inline JSValue::JSValue(const JSCell* ptr) + { + u.asBits.tag = CellTag; + u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); + } + + inline JSValue::operator bool() const + { + return u.asBits.payload || tag() != CellTag; + } + + inline bool JSValue::operator==(const JSValue& other) const + { + return u.asEncodedJSValue == other.u.asEncodedJSValue; + } + + inline bool JSValue::operator!=(const JSValue& other) const + { + return u.asEncodedJSValue != other.u.asEncodedJSValue; + } + + inline bool JSValue::isUndefined() const + { + return tag() == UndefinedTag; + } + + inline bool JSValue::isNull() const + { + return tag() == NullTag; + } + + inline bool JSValue::isUndefinedOrNull() const + { + return isUndefined() || isNull(); + } + + inline bool JSValue::isCell() const + { + return tag() == CellTag; + } + + inline bool JSValue::isInt32() const + { + return tag() == Int32Tag; + } + + inline bool JSValue::isUInt32() const + { + return tag() == Int32Tag && asInt32() > -1; + } + + inline bool JSValue::isDouble() const + { + return tag() < LowestTag; + } + + inline bool JSValue::isTrue() const + { + return tag() == TrueTag; + } + + inline bool JSValue::isFalse() const + { + return tag() == FalseTag; + } + + inline uint32_t JSValue::tag() const + { + return u.asBits.tag; + } + + inline int32_t JSValue::payload() const + { + return u.asBits.payload; + } + + inline int32_t JSValue::asInt32() const + { + ASSERT(isInt32()); + return u.asBits.payload; + } + + inline uint32_t JSValue::asUInt32() const + { + ASSERT(isUInt32()); + return u.asBits.payload; + } + + inline double JSValue::asDouble() const + { + ASSERT(isDouble()); + return u.asDouble; + } + + ALWAYS_INLINE JSCell* JSValue::asCell() const + { + ASSERT(isCell()); + return reinterpret_cast<JSCell*>(u.asBits.payload); + } + + inline JSValue::JSValue(ExecState* exec, double d) + { + const int32_t asInt32 = static_cast<int32_t>(d); + if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 + u.asDouble = d; + return; + } + *this = JSValue(exec, static_cast<int32_t>(d)); + } + + inline JSValue::JSValue(ExecState* exec, char i) + { + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, unsigned char i) + { + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, short i) + { + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, unsigned short i) + { + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState*, int i) + { + u.asBits.tag = Int32Tag; + u.asBits.payload = i; + } + + inline JSValue::JSValue(ExecState* exec, unsigned i) + { + if (static_cast<int32_t>(i) < 0) { + *this = JSValue(exec, static_cast<double>(i)); + return; + } + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, long i) + { + if (static_cast<int32_t>(i) != i) { + *this = JSValue(exec, static_cast<double>(i)); + return; + } + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, unsigned long i) + { + if (static_cast<uint32_t>(i) != i) { + *this = JSValue(exec, static_cast<double>(i)); + return; + } + *this = JSValue(exec, static_cast<uint32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, long long i) + { + if (static_cast<int32_t>(i) != i) { + *this = JSValue(exec, static_cast<double>(i)); + return; + } + *this = JSValue(exec, static_cast<int32_t>(i)); + } + + inline JSValue::JSValue(ExecState* exec, unsigned long long i) + { + if (static_cast<uint32_t>(i) != i) { + *this = JSValue(exec, static_cast<double>(i)); + return; + } + *this = JSValue(exec, static_cast<uint32_t>(i)); + } + + inline JSValue::JSValue(JSGlobalData* globalData, double d) + { + const int32_t asInt32 = static_cast<int32_t>(d); + if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 + u.asDouble = d; + return; + } + *this = JSValue(globalData, static_cast<int32_t>(d)); + } + + inline JSValue::JSValue(JSGlobalData*, int i) + { + u.asBits.tag = Int32Tag; + u.asBits.payload = i; + } + + inline JSValue::JSValue(JSGlobalData* globalData, unsigned i) + { + if (static_cast<int32_t>(i) < 0) { + *this = JSValue(globalData, static_cast<double>(i)); + return; + } + *this = JSValue(globalData, static_cast<int32_t>(i)); + } + + inline bool JSValue::isNumber() const + { + return isInt32() || isDouble(); + } + + inline bool JSValue::isBoolean() const + { + return isTrue() || isFalse(); + } + + inline bool JSValue::getBoolean(bool& v) const + { + if (isTrue()) { + v = true; + return true; + } + if (isFalse()) { + v = false; + return true; + } + + return false; + } + + inline bool JSValue::getBoolean() const + { + ASSERT(isBoolean()); + return tag() == TrueTag; + } + + inline double JSValue::uncheckedGetNumber() const + { + ASSERT(isNumber()); + return isInt32() ? asInt32() : asDouble(); + } + + ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const + { + return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec)); + } + + inline bool JSValue::getNumber(double& result) const + { + if (isInt32()) { + result = asInt32(); + return true; + } + if (isDouble()) { + result = asDouble(); + return true; + } + return false; + } + +#else // USE(JSVALUE32_64) // JSValue member functions. inline EncodedJSValue JSValue::encode(JSValue value) @@ -368,6 +740,16 @@ namespace JSC { return JSValue(reinterpret_cast<JSCell*>(ptr)); } + inline JSValue JSValue::makeImmediate(intptr_t value) + { + return JSValue(reinterpret_cast<JSCell*>(value)); + } + + inline intptr_t JSValue::immediateValue() + { + return reinterpret_cast<intptr_t>(m_ptr); + } + // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page. inline JSValue::JSValue() : m_ptr(0) @@ -395,12 +777,12 @@ namespace JSC { return m_ptr; } - inline bool JSValue::operator==(const JSValue other) const + inline bool JSValue::operator==(const JSValue& other) const { return m_ptr == other.m_ptr; } - inline bool JSValue::operator!=(const JSValue other) const + inline bool JSValue::operator!=(const JSValue& other) const { return m_ptr != other.m_ptr; } @@ -414,6 +796,7 @@ namespace JSC { { return asValue() == jsNull(); } +#endif // USE(JSVALUE32_64) } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp index 78993b6..ac193ca 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp @@ -30,6 +30,7 @@ #include "JSVariableObject.h" #include "PropertyNameArray.h" +#include "PropertyDescriptor.h" namespace JSC { @@ -41,15 +42,15 @@ bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propert return JSObject::deleteProperty(exec, propertyName, checkDontDelete); } -void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) +void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) { SymbolTable::const_iterator end = symbolTable().end(); for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) { - if ((listedAttributes & Structure::NonEnumerable) || !(it->second.getAttributes() & DontEnum)) + if (!(it->second.getAttributes() & DontEnum) || includeNonEnumerable) propertyNames.add(Identifier(exec, it->first.get())); } - JSObject::getPropertyNames(exec, propertyNames, listedAttributes); + JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const @@ -67,4 +68,14 @@ bool JSVariableObject::isVariableObject() const return true; } +bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep()); + if (!entry.isNull()) { + descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete); + return true; + } + return false; +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h index 310efb1..fe92729 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h @@ -49,7 +49,7 @@ namespace JSC { virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; virtual bool deleteProperty(ExecState*, const Identifier&, bool checkDontDelete = true); - virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); virtual bool isVariableObject() const; virtual bool isDynamicScope() const = 0; @@ -58,6 +58,11 @@ namespace JSC { Register& registerAt(int index) const { return d->registers[index]; } + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark)); + } + protected: // Subclasses of JSVariableObject can subclass this struct to add data // without increasing their own size (since there's a hard limit on the @@ -89,6 +94,7 @@ namespace JSC { void setRegisters(Register* r, Register* registerArray); bool symbolTableGet(const Identifier&, PropertySlot&); + bool symbolTableGet(const Identifier&, PropertyDescriptor&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); bool symbolTablePut(const Identifier&, JSValue); bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.cpp index fb57018..2c39f5c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2006 Maks Orlovich - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2009 Apple, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,11 +26,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject); -void JSWrapperObject::mark() +void JSWrapperObject::markChildren(MarkStack& markStack) { - JSObject::mark(); - if (m_internalValue && !m_internalValue.marked()) - m_internalValue.mark(); + JSObject::markChildren(markStack); + if (m_internalValue) + markStack.append(m_internalValue); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h index 2a2e3c6..b56a58d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h @@ -25,7 +25,7 @@ #include "JSObject.h" namespace JSC { - + // This class is used as a base for classes such as String, // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSObject { @@ -35,23 +35,31 @@ namespace JSC { public: JSValue internalValue() const { return m_internalValue; } void setInternalValue(JSValue); - - virtual void mark(); - + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames | HasDefaultMark)); + } + private: + virtual void markChildren(MarkStack&); + JSValue m_internalValue; }; - + inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure) : JSObject(structure) { + addAnonymousSlots(1); + putAnonymousValue(0, jsNull()); } - + inline void JSWrapperObject::setInternalValue(JSValue value) { ASSERT(value); ASSERT(!value.isObject()); m_internalValue = value; + putAnonymousValue(0, value); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp index 798013a..d242282 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp @@ -129,7 +129,8 @@ template <LiteralParser::ParserMode mode> static inline bool isSafeStringCharact return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != '"') || c == '\t'; } -template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token) +// "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions. +template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token) { ++m_ptr; const UChar* runStart; @@ -294,7 +295,10 @@ JSValue LiteralParser::parse(ParserState initialState) } doParseArrayStartExpression: case DoParseArrayStartExpression: { + TokenType lastToken = m_lexer.currentToken().type; if (m_lexer.next() == TokRBracket) { + if (lastToken == TokComma) + return JSValue(); m_lexer.next(); lastValue = objectStack.last(); objectStack.removeLast(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.h index bceee7c..0f8072b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.h @@ -89,7 +89,7 @@ namespace JSC { private: TokenType lex(LiteralParserToken&); - template <ParserMode parserMode> TokenType lexString(LiteralParserToken&); + template <ParserMode mode> TokenType lexString(LiteralParserToken&); TokenType lexNumber(LiteralParserToken&); LiteralParserToken m_currentToken; UString m_string; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h index 167f2bc..4d70689 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h @@ -51,7 +51,7 @@ namespace JSC { typedef PropertySlot::GetValueFunc GetFunction; typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value); - class HashEntry { + class HashEntry : public FastAllocBase { public: void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2) { @@ -186,6 +186,24 @@ namespace JSC { return true; } + template <class ThisImp, class ParentImp> + inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor); + + PropertySlot slot; + if (entry->attributes() & Function) + setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + else + slot.setCustom(thisObj, entry->propertyGetter()); + + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return true; + } + /** * Simplified version of getStaticPropertySlot in case there are only functions. * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing @@ -204,6 +222,27 @@ namespace JSC { setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); return true; } + + /** + * Simplified version of getStaticPropertyDescriptor in case there are only functions. + * Using this instead of getStaticPropertyDescriptor allows 'this' to avoid implementing + * a dummy getValueProperty. + */ + template <class ParentImp> + inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor)) + return true; + + const HashEntry* entry = table->entry(exec, propertyName); + if (!entry) + return false; + + PropertySlot slot; + setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return true; + } /** * Simplified version of getStaticPropertySlot in case there are no functions, only "values". @@ -224,6 +263,25 @@ namespace JSC { } /** + * Simplified version of getStaticPropertyDescriptor in case there are no functions, only "values". + * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class. + */ + template <class ThisImp, class ParentImp> + inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor); + + ASSERT(!(entry->attributes() & Function)); + PropertySlot slot; + slot.setCustom(thisObj, entry->propertyGetter()); + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return true; + } + + /** * This one is for "put". * It looks up a hash entry for the property to be set. If an entry * is found it sets the value and returns true, else it returns false. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.d b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.cpp index b9efaff..a350c35 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.d +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,21 +20,21 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -provider JavaScriptCore +#include "config.h" +#include "MarkStack.h" + +namespace JSC { + +size_t MarkStack::s_pageSize = 0; + +void MarkStack::compact() { - probe gc__begin(); - probe gc__marked(); - probe gc__end(int, int); - - probe profile__will_execute(int, char*, char*, int); - probe profile__did_execute(int, char*, char*, int); -}; + ASSERT(s_pageSize); + m_values.shrinkAllocation(s_pageSize); + m_markSets.shrinkAllocation(s_pageSize); +} -#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore provider -#pragma D attributes Private/Private/Unknown provider JavaScriptCore module -#pragma D attributes Private/Private/Unknown provider JavaScriptCore function -#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore name -#pragma D attributes Unstable/Unstable/Common provider JavaScriptCore args +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h new file mode 100644 index 0000000..5bc85fa --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#ifndef MarkStack_h +#define MarkStack_h + +#include "JSValue.h" +#include <wtf/Noncopyable.h> + +namespace JSC { + + class JSGlobalData; + class Register; + + enum MarkSetProperties { MayContainNullValues, NoNullValues }; + + class MarkStack : Noncopyable { + public: + MarkStack(void* jsArrayVPtr) + : m_jsArrayVPtr(jsArrayVPtr) +#ifndef NDEBUG + , m_isCheckingForDefaultMarkViolation(false) +#endif + { + } + + ALWAYS_INLINE void append(JSValue); + ALWAYS_INLINE void append(JSCell*); + + ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues) + { + appendValues(reinterpret_cast<JSValue*>(values), count, properties); + } + + ALWAYS_INLINE void appendValues(JSValue* values, size_t count, MarkSetProperties properties = NoNullValues) + { + if (count) + m_markSets.append(MarkSet(values, values + count, properties)); + } + + inline void drain(); + void compact(); + + ~MarkStack() + { + ASSERT(m_markSets.isEmpty()); + ASSERT(m_values.isEmpty()); + } + + private: + void markChildren(JSCell*); + + struct MarkSet { + MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties) + : m_values(values) + , m_end(end) + , m_properties(properties) + { + ASSERT(values); + } + JSValue* m_values; + JSValue* m_end; + MarkSetProperties m_properties; + }; + + static void* allocateStack(size_t size); + static void releaseStack(void* addr, size_t size); + + static void initializePagesize(); + static size_t pageSize() + { + if (!s_pageSize) + initializePagesize(); + return s_pageSize; + } + + template <typename T> struct MarkStackArray { + MarkStackArray() + : m_top(0) + , m_allocated(MarkStack::pageSize()) + , m_capacity(m_allocated / sizeof(T)) + { + m_data = reinterpret_cast<T*>(allocateStack(m_allocated)); + } + + ~MarkStackArray() + { + releaseStack(m_data, m_allocated); + } + + void expand() + { + size_t oldAllocation = m_allocated; + m_allocated *= 2; + m_capacity = m_allocated / sizeof(T); + void* newData = allocateStack(m_allocated); + memcpy(newData, m_data, oldAllocation); + releaseStack(m_data, oldAllocation); + m_data = reinterpret_cast<T*>(newData); + } + + inline void append(const T& v) + { + if (m_top == m_capacity) + expand(); + m_data[m_top++] = v; + } + + inline T removeLast() + { + ASSERT(m_top); + return m_data[--m_top]; + } + + inline T& last() + { + ASSERT(m_top); + return m_data[m_top - 1]; + } + + inline bool isEmpty() + { + return m_top == 0; + } + + inline size_t size() { return m_top; } + + inline void shrinkAllocation(size_t size) + { + ASSERT(size <= m_allocated); + ASSERT(0 == (size % MarkStack::pageSize())); + if (size == m_allocated) + return; +#if PLATFORM(WIN) + // We cannot release a part of a region with VirtualFree. To get around this, + // we'll release the entire region and reallocate the size that we want. + releaseStack(m_data, m_allocated); + m_data = reinterpret_cast<T*>(allocateStack(size)); +#else + releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size); +#endif + m_allocated = size; + m_capacity = m_allocated / sizeof(T); + } + + private: + size_t m_top; + size_t m_allocated; + size_t m_capacity; + T* m_data; + }; + + void* m_jsArrayVPtr; + MarkStackArray<MarkSet> m_markSets; + MarkStackArray<JSCell*> m_values; + static size_t s_pageSize; + +#ifndef NDEBUG + public: + bool m_isCheckingForDefaultMarkViolation; +#endif + }; +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp new file mode 100644 index 0000000..aec968e --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "MarkStack.h" + +#include <unistd.h> +#if defined (__SYMBIAN32__) +#include "wtf/FastMalloc.h" +#include <e32base.h> +#include <e32std.h> +#include <e32hal.h> +#include <hal.h> +#else +#include <sys/mman.h> +#endif + +namespace JSC { + +void MarkStack::initializePagesize() +{ +#if defined (__SYMBIAN32__) + TInt page_size; + UserHal::PageSizeInBytes(page_size); + MarkStack::s_pageSize = page_size; +#else + MarkStack::s_pageSize = getpagesize(); +#endif +} + +void* MarkStack::allocateStack(size_t size) +{ +#if defined (__SYMBIAN32__) + return fastMalloc(size); +#else + return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); +#endif +} +void MarkStack::releaseStack(void* addr, size_t size) +{ +#if defined (__SYMBIAN32__) + fastFree(addr); +#else + munmap(reinterpret_cast<char*>(addr), size); +#endif +} + +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp new file mode 100644 index 0000000..1fdd06a --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "MarkStack.h" + +#include "windows.h" + +namespace JSC { + +void MarkStack::initializePagesize() +{ + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + MarkStack::s_pageSize = system_info.dwPageSize; +} + +void* MarkStack::allocateStack(size_t size) +{ + return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); +} +void MarkStack::releaseStack(void* addr, size_t) +{ + // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx, + // dwSize must be 0 if dwFreeType is MEM_RELEASE. + VirtualFree(addr, 0, MEM_RELEASE); +} + +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp index 2572bc9..36771ab 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp @@ -103,14 +103,12 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure) bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot) { - const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName); - - if (!entry) - return JSObject::getOwnPropertySlot(exec, propertyName, slot); + return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot); +} - ASSERT(entry->attributes() & Function); - setUpStaticFunctionSlot(exec, entry, this, propertyName, slot); - return true; +bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor); } // ------------------------------ Functions -------------------------------- diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h index 3557d1e..a2e065f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h @@ -30,13 +30,14 @@ namespace JSC { MathObject(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); } }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp index 2840bf0..a95106d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp @@ -68,6 +68,11 @@ bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot); } +bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor); +} + static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) { return jsNaN(exec); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h index b1224ec..710ac86 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h @@ -32,13 +32,14 @@ namespace JSC { NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); JSValue getValueProperty(ExecState*, int token) const; static const ClassInfo info; static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames)); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h index d354b9b..f502bee 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h @@ -30,7 +30,17 @@ namespace JSC { explicit NumberObject(PassRefPtr<Structure>); static const ClassInfo info; - +#if USE(JSVALUE32) + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames)); + } +#else + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + } +#endif private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumericStrings.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumericStrings.h new file mode 100644 index 0000000..c0696a4 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumericStrings.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#ifndef NumericStrings_h +#define NumericStrings_h + +#include "UString.h" +#include <wtf/HashFunctions.h> + +namespace JSC { + + class NumericStrings { + public: + UString add(double d) + { + CacheEntry<double>& entry = lookup(d); + if (d == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = d; + entry.value = UString::from(d); + return entry.value; + } + + UString add(int i) + { + CacheEntry<int>& entry = lookup(i); + if (i == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = i; + entry.value = UString::from(i); + return entry.value; + } + + private: + static const size_t cacheSize = 64; + + template<typename T> + struct CacheEntry { + T key; + UString value; + }; + + CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; } + CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; } + + CacheEntry<double> doubleCache[cacheSize]; + CacheEntry<int> intCache[cacheSize]; + }; + +} // namespace JSC + +#endif // NumericStrings_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp index cf1790f..2992f1b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -21,22 +21,41 @@ #include "config.h" #include "ObjectConstructor.h" +#include "Error.h" #include "JSFunction.h" +#include "JSArray.h" #include "JSGlobalObject.h" #include "ObjectPrototype.h" +#include "PropertyDescriptor.h" +#include "PropertyNameArray.h" +#include "PrototypeFunction.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor); -ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype) - : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object")) +static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&); + +ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure) +: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object")) { // ECMA 15.2.3.1 putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly); - + // no. of arguments for constructor putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete); + + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum); } // ECMA 15.2.2 @@ -70,4 +89,212 @@ CallType ObjectConstructor::getCallData(CallData& callData) return CallTypeHost; } +JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Requested prototype of a value that is not an object."); + return asObject(args.at(0))->prototype(); +} + +JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Requested property descriptor of a value that is not an object."); + UString propertyName = args.at(1).toString(exec); + if (exec->hadException()) + return jsNull(); + JSObject* object = asObject(args.at(0)); + PropertyDescriptor descriptor; + if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor)) + return jsUndefined(); + if (exec->hadException()) + return jsUndefined(); + + JSObject* description = constructEmptyObject(exec); + if (!descriptor.isAccessorDescriptor()) { + description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0); + description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0); + } else { + description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0); + description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0); + } + + description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0); + description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0); + + return description; +} + +JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Requested keys of a value that is not an object."); + PropertyNameArray properties(exec); + asObject(args.at(0))->getOwnPropertyNames(exec, properties); + JSArray* keys = constructEmptyArray(exec); + size_t numProperties = properties.size(); + for (size_t i = 0; i < numProperties; i++) + keys->push(exec, jsOwnedString(exec, properties[i].ustring())); + return keys; +} + +// ES5 8.10.5 ToPropertyDescriptor +static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc) +{ + if (!in.isObject()) { + throwError(exec, TypeError, "Property description must be an object."); + return false; + } + JSObject* description = asObject(in); + + PropertySlot enumerableSlot; + if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { + desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); + if (exec->hadException()) + return false; + } + + PropertySlot configurableSlot; + if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { + desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); + if (exec->hadException()) + return false; + } + + JSValue value; + PropertySlot valueSlot; + if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) { + desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value)); + if (exec->hadException()) + return false; + } + + PropertySlot writableSlot; + if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { + desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); + if (exec->hadException()) + return false; + } + + PropertySlot getSlot; + if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) { + JSValue get = getSlot.getValue(exec, exec->propertyNames().get); + if (exec->hadException()) + return false; + if (!get.isUndefined()) { + CallData callData; + if (get.getCallData(callData) == CallTypeNone) { + throwError(exec, TypeError, "Getter must be a function."); + return false; + } + } else + get = JSValue(); + desc.setGetter(get); + } + + PropertySlot setSlot; + if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) { + JSValue set = setSlot.getValue(exec, exec->propertyNames().set); + if (exec->hadException()) + return false; + if (!set.isUndefined()) { + CallData callData; + if (set.getCallData(callData) == CallTypeNone) { + throwError(exec, TypeError, "Setter must be a function."); + return false; + } + } else + set = JSValue(); + + desc.setSetter(set); + } + + if (!desc.isAccessorDescriptor()) + return true; + + if (desc.value()) { + throwError(exec, TypeError, "Invalid property. 'value' present on property with getter or setter."); + return false; + } + + if (desc.writablePresent()) { + throwError(exec, TypeError, "Invalid property. 'writable' present on property with getter or setter."); + return false; + } + return true; +} + +JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Properties can only be defined on Objects."); + JSObject* O = asObject(args.at(0)); + UString propertyName = args.at(1).toString(exec); + if (exec->hadException()) + return jsNull(); + PropertyDescriptor descriptor; + if (!toPropertyDescriptor(exec, args.at(2), descriptor)) + return jsNull(); + ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor())); + ASSERT(!exec->hadException()); + O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true); + return O; +} + +static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties) +{ + PropertyNameArray propertyNames(exec); + asObject(properties)->getOwnPropertyNames(exec, propertyNames); + size_t numProperties = propertyNames.size(); + Vector<PropertyDescriptor> descriptors; + MarkedArgumentBuffer markBuffer; + for (size_t i = 0; i < numProperties; i++) { + PropertySlot slot; + JSValue prop = properties->get(exec, propertyNames[i]); + if (exec->hadException()) + return jsNull(); + PropertyDescriptor descriptor; + if (!toPropertyDescriptor(exec, prop, descriptor)) + return jsNull(); + descriptors.append(descriptor); + // Ensure we mark all the values that we're accumulating + if (descriptor.isDataDescriptor() && descriptor.value()) + markBuffer.append(descriptor.value()); + if (descriptor.isAccessorDescriptor()) { + if (descriptor.getter()) + markBuffer.append(descriptor.getter()); + if (descriptor.setter()) + markBuffer.append(descriptor.setter()); + } + } + for (size_t i = 0; i < numProperties; i++) { + object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true); + if (exec->hadException()) + return jsNull(); + } + return object; +} + +JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Properties can only be defined on Objects."); + if (!args.at(1).isObject()) + return throwError(exec, TypeError, "Property descriptor list must be an Object."); + return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1))); +} + +JSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject() && !args.at(0).isNull()) + return throwError(exec, TypeError, "Object prototype may only be an Object or null."); + JSObject* newObject = constructEmptyObject(exec); + newObject->setPrototype(args.at(0)); + if (args.at(1).isUndefined()) + return newObject; + if (!args.at(1).isObject()) + return throwError(exec, TypeError, "Property descriptor list must be an Object."); + return defineProperties(exec, newObject, asObject(args.at(1))); +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h index f8c058a..9373781 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ObjectConstructor : public InternalFunction { public: - ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*); + ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp index 98e4713..fccc44a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -42,6 +42,7 @@ static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject* ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure) : JSObject(stucture) + , m_hasNoPropertiesWithUInt32Names(true) { putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum); @@ -57,6 +58,24 @@ ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum); } +void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + JSObject::put(exec, propertyName, value, slot); + + if (m_hasNoPropertiesWithUInt32Names) { + bool isUInt32; + propertyName.toStrictUInt32(&isUInt32); + m_hasNoPropertiesWithUInt32Names = !isUInt32; + } +} + +bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +{ + if (m_hasNoPropertiesWithUInt32Names) + return false; + return JSObject::getOwnPropertySlot(exec, propertyName, slot); +} + // ------------------------------ Functions -------------------------------- // ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7 diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h index 7790ae0..6dd3c28 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h @@ -28,6 +28,12 @@ namespace JSC { class ObjectPrototype : public JSObject { public: ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + + private: + virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); + virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + + bool m_hasNoPropertiesWithUInt32Names; }; JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h index a0caff4..21120f5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h @@ -38,7 +38,7 @@ namespace JSC { // ECMA 11.9.3 inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2) { - if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + if (v1.isInt32() && v2.isInt32()) return v1 == v2; return equalSlowCase(exec, v1, v2); @@ -46,8 +46,6 @@ namespace JSC { ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) { - ASSERT(!JSImmediate::areBothImmediateIntegerNumbers(v1, v2)); - do { if (v1.isNumber() && v2.isNumber()) return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); @@ -60,29 +58,30 @@ namespace JSC { if (v1.isUndefinedOrNull()) { if (v2.isUndefinedOrNull()) return true; - if (JSImmediate::isImmediate(v2)) + if (!v2.isCell()) return false; return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); } if (v2.isUndefinedOrNull()) { - if (JSImmediate::isImmediate(v1)) + if (!v1.isCell()) return false; return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined(); } if (v1.isObject()) { - if (v2.isObject()) + if (v2.isObject()) { return v1 == v2 #ifdef QT_BUILD_SCRIPT_LIB || asObject(v1)->compareToObject(exec, asObject(v2)) #endif ; + } JSValue p1 = v1.toPrimitive(exec); if (exec->hadException()) return false; v1 = p1; - if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + if (v1.isInt32() && v2.isInt32()) return v1 == v2; continue; } @@ -92,7 +91,7 @@ namespace JSC { if (exec->hadException()) return false; v2 = p2; - if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + if (v1.isInt32() && v2.isInt32()) return v1 == v2; continue; } @@ -118,7 +117,7 @@ namespace JSC { // ECMA 11.9.3 ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2) { - ASSERT(!JSImmediate::isEitherImmediate(v1, v2)); + ASSERT(v1.isCell() && v2.isCell()); if (v1.asCell()->isString() && v2.asCell()->isString()) return asString(v1)->value() == asString(v2)->value(); @@ -128,13 +127,13 @@ namespace JSC { inline bool JSValue::strictEqual(JSValue v1, JSValue v2) { - if (JSImmediate::areBothImmediateIntegerNumbers(v1, v2)) + if (v1.isInt32() && v2.isInt32()) return v1 == v2; if (v1.isNumber() && v2.isNumber()) return v1.uncheckedGetNumber() == v2.uncheckedGetNumber(); - if (JSImmediate::isEitherImmediate(v1, v2)) + if (!v1.isCell() || !v2.isCell()) return v1 == v2; return strictEqualSlowCaseInline(v1, v2); @@ -142,8 +141,8 @@ namespace JSC { inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) { - if (JSValue::areBothInt32Fast(v1, v2)) - return v1.getInt32Fast() < v2.getInt32Fast(); + if (v1.isInt32() && v2.isInt32()) + return v1.asInt32() < v2.asInt32(); double n1; double n2; @@ -167,8 +166,8 @@ namespace JSC { inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) { - if (JSValue::areBothInt32Fast(v1, v2)) - return v1.getInt32Fast() <= v2.getInt32Fast(); + if (v1.isInt32() && v2.isInt32()) + return v1.asInt32() <= v2.asInt32(); double n1; double n2; @@ -217,8 +216,8 @@ namespace JSC { } if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = v2.isInt32Fast() ? - concatenate(asString(v1)->value().rep(), v2.getInt32Fast()) : + RefPtr<UString::Rep> value = v2.isInt32() ? + concatenate(asString(v1)->value().rep(), v2.asInt32()) : concatenate(asString(v1)->value().rep(), right); if (!value) @@ -314,20 +313,13 @@ namespace JSC { resultRep = UString::Rep::createEmptyBuffer(bufferSize); UString result(resultRep); - // Loop over the openards, writing them into the output buffer. + // Loop over the operands, writing them into the output buffer. for (unsigned i = 0; i < count; ++i) { JSValue v = strings[i].jsValue(); if (LIKELY(v.isString())) result.append(asString(v)->value()); - else if (v.isInt32Fast()) - result.appendNumeric(v.getInt32Fast()); - else { - double d; - if (v.getNumber(d)) - result.appendNumeric(d); - else - result.append(v.toString(callFrame)); - } + else + result.append(v.toString(callFrame)); } return jsString(callFrame, result); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp new file mode 100644 index 0000000..4db814f --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "PropertyDescriptor.h" + +#include "GetterSetter.h" +#include "JSObject.h" +#include "Operations.h" + +namespace JSC { +unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1; + +bool PropertyDescriptor::writable() const +{ + ASSERT(!isAccessorDescriptor()); + return !(m_attributes & ReadOnly); +} + +bool PropertyDescriptor::enumerable() const +{ + return !(m_attributes & DontEnum); +} + +bool PropertyDescriptor::configurable() const +{ + return !(m_attributes & DontDelete); +} + +bool PropertyDescriptor::isDataDescriptor() const +{ + return m_value || (m_seenAttributes & WritablePresent); +} + +bool PropertyDescriptor::isGenericDescriptor() const +{ + return !isAccessorDescriptor() && !isDataDescriptor(); +} + +bool PropertyDescriptor::isAccessorDescriptor() const +{ + return m_getter || m_setter; +} + +void PropertyDescriptor::setUndefined() +{ + m_value = jsUndefined(); + m_attributes = ReadOnly | DontDelete | DontEnum; +} + +JSValue PropertyDescriptor::getter() const +{ + ASSERT(isAccessorDescriptor()); + return m_getter; +} + +JSValue PropertyDescriptor::setter() const +{ + ASSERT(isAccessorDescriptor()); + return m_setter; +} + +void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes) +{ + ASSERT(value); + m_attributes = attributes; + if (attributes & (Getter | Setter)) { + GetterSetter* accessor = asGetterSetter(value); + m_getter = accessor->getter(); + m_setter = accessor->setter(); + ASSERT(m_getter || m_setter); + m_seenAttributes = EnumerablePresent | ConfigurablePresent; + m_attributes &= ~ReadOnly; + } else { + m_value = value; + m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent; + } +} + +void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes) +{ + ASSERT(attributes & (Getter | Setter)); + ASSERT(getter || setter); + m_attributes = attributes; + m_getter = getter; + m_setter = setter; + m_attributes &= ~ReadOnly; + m_seenAttributes = EnumerablePresent | ConfigurablePresent; +} + +void PropertyDescriptor::setWritable(bool writable) +{ + if (writable) + m_attributes &= ~ReadOnly; + else + m_attributes |= ReadOnly; + m_seenAttributes |= WritablePresent; +} + +void PropertyDescriptor::setEnumerable(bool enumerable) +{ + if (enumerable) + m_attributes &= ~DontEnum; + else + m_attributes |= DontEnum; + m_seenAttributes |= EnumerablePresent; +} + +void PropertyDescriptor::setConfigurable(bool configurable) +{ + if (configurable) + m_attributes &= ~DontDelete; + else + m_attributes |= DontDelete; + m_seenAttributes |= ConfigurablePresent; +} + +void PropertyDescriptor::setSetter(JSValue setter) +{ + m_setter = setter; + m_attributes |= Setter; + m_attributes &= ~ReadOnly; +} + +void PropertyDescriptor::setGetter(JSValue getter) +{ + m_getter = getter; + m_attributes |= Getter; + m_attributes &= ~ReadOnly; +} + +bool PropertyDescriptor::equalTo(const PropertyDescriptor& other) const +{ + if (!other.m_value == m_value || + !other.m_getter == m_getter || + !other.m_setter == m_setter) + return false; + return (!m_value || JSValue::strictEqual(other.m_value, m_value)) && + (!m_getter || JSValue::strictEqual(other.m_getter, m_getter)) && + (!m_setter || JSValue::strictEqual(other.m_setter, m_setter)) && + attributesEqual(other); +} + +bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const +{ + unsigned mismatch = other.m_attributes ^ m_attributes; + unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes; + if (sharedSeen & WritablePresent && mismatch & ReadOnly) + return false; + if (sharedSeen & ConfigurablePresent && mismatch & DontDelete) + return false; + if (sharedSeen & EnumerablePresent && mismatch & DontEnum) + return false; + return true; +} + +unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const +{ + unsigned mismatch = other.m_attributes ^ m_attributes; + unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes; + unsigned newAttributes = m_attributes & defaultAttributes; + if (sharedSeen & WritablePresent && mismatch & ReadOnly) + newAttributes ^= ReadOnly; + if (sharedSeen & ConfigurablePresent && mismatch & DontDelete) + newAttributes ^= DontDelete; + if (sharedSeen & EnumerablePresent && mismatch & DontEnum) + newAttributes ^= DontEnum; + return newAttributes; +} + +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h new file mode 100644 index 0000000..40bec86 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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. + */ + +#ifndef PropertyDescriptor_h +#define PropertyDescriptor_h + +#include "JSValue.h" + +namespace JSC { + class PropertyDescriptor { + public: + PropertyDescriptor() + : m_attributes(defaultAttributes) + , m_seenAttributes(0) + { + } + bool writable() const; + bool enumerable() const; + bool configurable() const; + bool isDataDescriptor() const; + bool isGenericDescriptor() const; + bool isAccessorDescriptor() const; + unsigned attributes() const { return m_attributes; } + JSValue value() const { return m_value; } + JSValue getter() const; + JSValue setter() const; + void setUndefined(); + void setDescriptor(JSValue value, unsigned attributes); + void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes); + void setWritable(bool); + void setEnumerable(bool); + void setConfigurable(bool); + void setValue(JSValue value) { m_value = value; } + void setSetter(JSValue); + void setGetter(JSValue); + bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); } + bool writablePresent() const { return m_seenAttributes & WritablePresent; } + bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; } + bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; } + bool setterPresent() const { return m_setter; } + bool getterPresent() const { return m_getter; } + bool equalTo(const PropertyDescriptor& other) const; + bool attributesEqual(const PropertyDescriptor& other) const; + unsigned attributesWithOverride(const PropertyDescriptor& other) const; + private: + static unsigned defaultAttributes; + bool operator==(const PropertyDescriptor&){ return false; } + enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4}; + // May be a getter/setter + JSValue m_value; + JSValue m_getter; + JSValue m_setter; + unsigned m_attributes; + unsigned m_seenAttributes; + }; +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyMapHashTable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyMapHashTable.h index 44dc2b8..5b63f79 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -61,6 +61,7 @@ namespace JSC { unsigned size; unsigned keyCount; unsigned deletedSentinelCount; + unsigned anonymousSlotCount; unsigned lastIndexUsed; Vector<unsigned>* deletedOffsets; unsigned entryIndices[1]; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.cpp index 36fa5d8..a0a2f48 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.cpp @@ -23,7 +23,6 @@ #include "JSFunction.h" #include "JSGlobalObject.h" -#include "JSObject.h" namespace JSC { @@ -39,7 +38,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const P return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList()); ASSERT(callType == CallTypeJS); // FIXME: Can this be done more efficiently using the callData? - return static_cast<JSFunction*>(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList()); + return asFunction(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList()); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.h index da0d152..15d9034 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertySlot.h @@ -23,7 +23,6 @@ #include "Identifier.h" #include "JSValue.h" -#include "JSImmediate.h" #include "Register.h" #include <wtf/Assertions.h> #include <wtf/NotFound.h> @@ -39,16 +38,16 @@ namespace JSC { class PropertySlot { public: PropertySlot() - : m_offset(WTF::notFound) { clearBase(); + clearOffset(); clearValue(); } explicit PropertySlot(const JSValue base) : m_slotBase(base) - , m_offset(WTF::notFound) { + clearOffset(); clearValue(); } @@ -82,8 +81,9 @@ namespace JSC { void setValueSlot(JSValue* valueSlot) { ASSERT(valueSlot); - m_getValue = JSC_VALUE_SLOT_MARKER; clearBase(); + clearOffset(); + m_getValue = JSC_VALUE_SLOT_MARKER; m_data.valueSlot = valueSlot; } @@ -107,8 +107,9 @@ namespace JSC { void setValue(JSValue value) { ASSERT(value); - m_getValue = JSC_VALUE_SLOT_MARKER; clearBase(); + clearOffset(); + m_getValue = JSC_VALUE_SLOT_MARKER; m_value = value; m_data.valueSlot = &m_value; } @@ -116,8 +117,9 @@ namespace JSC { void setRegisterSlot(Register* registerSlot) { ASSERT(registerSlot); - m_getValue = JSC_REGISTER_SLOT_MARKER; clearBase(); + clearOffset(); + m_getValue = JSC_REGISTER_SLOT_MARKER; m_data.registerSlot = registerSlot; } @@ -147,13 +149,11 @@ namespace JSC { void setUndefined() { - clearBase(); setValue(jsUndefined()); } JSValue slotBase() const { - ASSERT(m_slotBase); return m_slotBase; } @@ -178,6 +178,13 @@ namespace JSC { #endif } + void clearOffset() + { + // Clear offset even in release builds, in case this PropertySlot has been used before. + // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.) + m_offset = WTF::notFound; + } + unsigned index() const { return m_data.index; } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp index e468521..1c95175 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -23,6 +23,7 @@ #include "RegExpConstructor.h" #include "ArrayPrototype.h" +#include "Error.h" #include "JSArray.h" #include "JSFunction.h" #include "JSString.h" @@ -89,7 +90,7 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, @end */ -struct RegExpConstructorPrivate { +struct RegExpConstructorPrivate : FastAllocBase { // Global search cache / settings RegExpConstructorPrivate() : lastNumSubPatterns(0) @@ -233,6 +234,11 @@ bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot); } +bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor); +} + JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) { return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1); @@ -329,7 +335,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) JSValue arg0 = args.at(0); JSValue arg1 = args.at(1); - if (arg0.isObject(&RegExpObject::info)) { + if (arg0.inherits(&RegExpObject::info)) { if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); return asObject(arg0); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h index 6823f3f..4b06b51 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h @@ -36,11 +36,12 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames)); } virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h index cbba85a..c1a5a25 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -44,6 +44,13 @@ namespace JSC { return JSArray::getOwnPropertySlot(exec, propertyName, slot); } + virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + if (lazyCreationData()) + fillArrayInstance(exec); + return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor); + } + virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot) { if (lazyCreationData()) @@ -72,11 +79,11 @@ namespace JSC { return JSArray::deleteProperty(exec, propertyName, checkDontDelete); } - virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr, unsigned listedAttributes) + virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, bool includeNonEnumerable = false) { if (lazyCreationData()) fillArrayInstance(exec); - JSArray::getPropertyNames(exec, arr, listedAttributes); + JSArray::getOwnPropertyNames(exec, arr, includeNonEnumerable); } void fillArrayInstance(ExecState*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp index 687844e..9d9dd7d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp @@ -72,6 +72,11 @@ bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propert return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); } +bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor); +} + JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) { return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global()); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h index fac9978..67113b6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h @@ -41,6 +41,7 @@ namespace JSC { JSValue exec(ExecState*, const ArgList&); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual const ClassInfo* classInfo() const { return &info; } @@ -48,7 +49,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); } private: @@ -56,7 +57,7 @@ namespace JSC { virtual CallType getCallData(CallData&); - struct RegExpObjectData { + struct RegExpObjectData : FastAllocBase { RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex) : regExp(regExp) , lastIndex(lastIndex) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp index e507016..4714171 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -22,6 +22,7 @@ #include "RegExpPrototype.h" #include "ArrayPrototype.h" +#include "Error.h" #include "JSArray.h" #include "JSFunction.h" #include "JSObject.h" @@ -58,28 +59,28 @@ RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structur JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&RegExpObject::info)) + if (!thisValue.inherits(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->test(exec, args); } JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&RegExpObject::info)) + if (!thisValue.inherits(&RegExpObject::info)) return throwError(exec, TypeError); return asRegExpObject(thisValue)->exec(exec, args); } JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - if (!thisValue.isObject(&RegExpObject::info)) + if (!thisValue.inherits(&RegExpObject::info)) return throwError(exec, TypeError); RefPtr<RegExp> regExp; JSValue arg0 = args.at(0); JSValue arg1 = args.at(1); - if (arg0.isObject(&RegExpObject::info)) { + if (arg0.inherits(&RegExpObject::info)) { if (!arg1.isUndefined()) return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another."); regExp = asRegExpObject(arg0)->regExp(); @@ -99,8 +100,8 @@ JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - if (!thisValue.isObject(&RegExpObject::info)) { - if (thisValue.isObject(&RegExpPrototype::info)) + if (!thisValue.inherits(&RegExpObject::info)) { + if (thisValue.inherits(&RegExpPrototype::info)) return jsNontrivialString(exec, "//"); return throwError(exec, TypeError); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp index 5c2edab..960c525 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp @@ -56,7 +56,7 @@ int ScopeChain::localDepth() const int scopeDepth = 0; ScopeChainIterator iter = this->begin(); ScopeChainIterator end = this->end(); - while (!(*iter)->isObject(&JSActivation::info)) { + while (!(*iter)->inherits(&JSActivation::info)) { ++iter; if (iter == end) break; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h index 17aff24..c5e16c9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,6 +28,7 @@ namespace JSC { class JSGlobalData; class JSGlobalObject; class JSObject; + class MarkStack; class ScopeChainIterator; class ScopeChainNode : public FastAllocBase { @@ -204,7 +205,7 @@ namespace JSC { JSGlobalObject* globalObject() const { return m_node->globalObject(); } - void mark() const; + void markAggregate(MarkStack&) const; // Caution: this should only be used if the codeblock this is being used // with needs a full scope chain, otherwise this returns the depth of diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChainMark.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChainMark.h index b80b8ef..984d101 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChainMark.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChainMark.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2008, 2009 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -25,13 +25,10 @@ namespace JSC { - inline void ScopeChain::mark() const + inline void ScopeChain::markAggregate(MarkStack& markStack) const { - for (ScopeChainNode* n = m_node; n; n = n->next) { - JSObject* o = n->object; - if (!o->marked()) - o->mark(); - } + for (ScopeChainNode* n = m_node; n; n = n->next) + markStack.append(n->object); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp index 9d1f01a..04701cb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp @@ -82,13 +82,13 @@ SmallStrings::~SmallStrings() { } -void SmallStrings::mark() +void SmallStrings::markChildren(MarkStack& markStack) { - if (m_emptyString && !m_emptyString->marked()) - m_emptyString->mark(); + if (m_emptyString) + markStack.append(m_emptyString); for (unsigned i = 0; i < numCharactersToStore; ++i) { - if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked()) - m_singleCharacterStrings[i]->mark(); + if (m_singleCharacterStrings[i]) + markStack.append(m_singleCharacterStrings[i]); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.h index f0dd8df..efecbb0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,7 @@ namespace JSC { class JSGlobalData; class JSString; - + class MarkStack; class SmallStringsStorage; class SmallStrings : public Noncopyable { @@ -56,7 +56,7 @@ namespace JSC { UString::Rep* singleCharacterStringRep(unsigned char character); - void mark(); + void markChildren(MarkStack&); unsigned count() const; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp index 4745a98..dd1ac5d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp @@ -61,6 +61,13 @@ bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pr return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } +bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor)) + return true; + return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (propertyName == exec->propertyNames().length) @@ -79,34 +86,12 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam return JSObject::deleteProperty(exec, propertyName, checkDontDelete); } -void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, unsigned listedAttributes) +void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) { int size = internalValue()->value().size(); for (int i = 0; i < size; ++i) propertyNames.add(Identifier(exec, UString::from(i))); - return JSObject::getPropertyNames(exec, propertyNames, listedAttributes); -} - -bool StringObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const -{ - if (internalValue()->getStringPropertyAttributes(exec, propertyName, attributes)) - return true; - return JSObject::getPropertyAttributes(exec, propertyName, attributes); -} - -UString StringObject::toString(ExecState*) const -{ - return internalValue()->value(); -} - -UString StringObject::toThisString(ExecState*) const -{ - return internalValue()->value(); -} - -JSString* StringObject::toThisJSString(ExecState*) -{ - return internalValue(); + return JSObject::getOwnPropertyNames(exec, propertyNames); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h index fdeb2c1..2f5927a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h @@ -35,11 +35,11 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual void getPropertyNames(ExecState*, PropertyNameArray&, unsigned listedAttributes = Structure::Prototype); - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); virtual const ClassInfo* classInfo() const { return &info; } static const JS_EXPORTDATA ClassInfo info; @@ -53,11 +53,6 @@ namespace JSC { protected: StringObject(PassRefPtr<Structure>, JSString*); - - private: - virtual UString toString(ExecState*) const; - virtual UString toThisString(ExecState*) const; - virtual JSString* toThisJSString(ExecState*); }; StringObject* asStringObject(JSValue); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index bc5c0a5..1d2e03f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -44,7 +44,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined)); + return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined | HasDefaultMark)); } virtual bool toBoolean(ExecState*) const { return false; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp index ceb6b1e..c9a32b6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp @@ -23,6 +23,8 @@ #include "StringPrototype.h" #include "CachedCall.h" +#include "Error.h" +#include "Executable.h" #include "JSArray.h" #include "JSFunction.h" #include "ObjectPrototype.h" @@ -131,6 +133,11 @@ bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prop return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot); } +bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, descriptor); +} + // ------------------------------ Functions -------------------------- static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) @@ -220,7 +227,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue if (callType == CallTypeNone) replacementString = replacement.toString(exec); - if (pattern.isObject(&RegExpObject::info)) { + if (pattern.inherits(&RegExpObject::info)) { RegExp* reg = asRegExpObject(pattern)->regExp(); bool global = reg->global(); @@ -365,7 +372,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValu if (thisValue.isString()) return thisValue; - if (thisValue.isObject(&StringObject::info)) + if (thisValue.inherits(&StringObject::info)) return asStringObject(thisValue)->internalValue(); return throwError(exec, TypeError); @@ -376,8 +383,8 @@ JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue UString s = thisValue.toThisString(exec); unsigned len = s.size(); JSValue a0 = args.at(0); - if (a0.isUInt32Fast()) { - uint32_t i = a0.getUInt32Fast(); + if (a0.isUInt32()) { + uint32_t i = a0.asUInt32(); if (i < len) return jsSingleCharacterSubstring(exec, s, i); return jsEmptyString(exec); @@ -393,8 +400,8 @@ JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSVa UString s = thisValue.toThisString(exec); unsigned len = s.size(); JSValue a0 = args.at(0); - if (a0.isUInt32Fast()) { - uint32_t i = a0.getUInt32Fast(); + if (a0.isUInt32()) { + uint32_t i = a0.asUInt32(); if (i < len) return jsNumber(exec, s.data()[i]); return jsNaN(exec); @@ -426,8 +433,8 @@ JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue int pos; if (a1.isUndefined()) pos = 0; - else if (a1.isUInt32Fast()) - pos = min<uint32_t>(a1.getUInt32Fast(), len); + else if (a1.isUInt32()) + pos = min<uint32_t>(a1.asUInt32(), len); else { double dpos = a1.toInteger(exec); if (dpos < 0) @@ -466,7 +473,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t UString u = s; RefPtr<RegExp> reg; RegExpObject* imp = 0; - if (a0.isObject(&RegExpObject::info)) + if (a0.inherits(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -516,7 +523,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue UString u = s; RefPtr<RegExp> reg; - if (a0.isObject(&RegExpObject::info)) + if (a0.inherits(&RegExpObject::info)) reg = asRegExpObject(a0)->regExp(); else { /* @@ -568,7 +575,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue t unsigned i = 0; int p0 = 0; unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec); - if (a0.isObject(&RegExpObject::info)) { + if (a0.inherits(&RegExpObject::info)) { RegExp* reg = asRegExpObject(a0)->regExp(); if (s.isEmpty() && reg->match(s, 0) >= 0) { // empty string matched by regexp -> empty array @@ -821,8 +828,8 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu if (a0.getUInt32(smallInteger) && smallInteger <= 9) { unsigned stringSize = s.size(); unsigned bufferSize = 22 + stringSize; - UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); - if (!buffer) + UChar* buffer; + if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer)) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'f'; @@ -869,8 +876,8 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th unsigned linkTextSize = linkText.size(); unsigned stringSize = s.size(); unsigned bufferSize = 15 + linkTextSize + stringSize; - UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar))); - if (!buffer) + UChar* buffer; + if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer)) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'a'; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h index 6f5344e..580e13d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h @@ -32,6 +32,7 @@ namespace JSC { StringPrototype(ExecState*, PassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp index 38c086e..05e3d7b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -127,17 +127,14 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo) , m_propertyTable(0) , m_propertyStorageCapacity(JSObject::inlineStorageCapacity) , m_offset(noOffset) - , m_isDictionary(false) + , m_dictionaryKind(NoneDictionaryKind) , m_isPinnedPropertyTable(false) , m_hasGetterSetterProperties(false) - , m_usingSingleTransitionSlot(true) , m_attributesInPrevious(0) { ASSERT(m_prototype); ASSERT(m_prototype.isObject() || m_prototype.isNull()); - m_transitions.singleTransition = 0; - #ifndef NDEBUG #if ENABLE(JSC_MULTIPLE_THREADS) MutexLocker protect(ignoreSetMutex); @@ -156,20 +153,16 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo) Structure::~Structure() { if (m_previous) { - if (m_previous->m_usingSingleTransitionSlot) { - m_previous->m_transitions.singleTransition = 0; - } else { - ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious)))); - m_previous->m_transitions.table->remove(make_pair<RefPtr<UString::Rep>, std::pair<unsigned,JSCell*> >(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious))); - } + if (m_nameInPrevious) + m_previous->table.remove(make_pair(RefPtr<UString::Rep>(m_nameInPrevious.get()), m_attributesInPrevious), m_specificValueInPrevious); + else + m_previous->table.removeAnonymousSlotTransition(m_anonymousSlotsInPrevious); + } if (m_cachedPropertyNameArrayData) m_cachedPropertyNameArrayData->setCachedStructure(0); - if (!m_usingSingleTransitionSlot) - delete m_transitions.table; - if (m_propertyTable) { unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { @@ -279,15 +272,25 @@ void Structure::materializePropertyMap() for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) { structure = structures[i]; + if (!structure->m_nameInPrevious) { + m_propertyTable->anonymousSlotCount += structure->m_anonymousSlotsInPrevious; + continue; + } structure->m_nameInPrevious->ref(); PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed); insertIntoPropertyMapHashTable(entry); } } -void Structure::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject, unsigned listedAttributes) +void Structure::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject, bool includeNonEnumerable) { - bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary) && (listedAttributes & Prototype); + getNamesFromPropertyTable(propertyNames, includeNonEnumerable); + getNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames, includeNonEnumerable); +} + +void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) +{ + bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary()); if (shouldCache && m_cachedPropertyNameArrayData) { if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { @@ -296,15 +299,23 @@ void Structure::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNam } clearEnumerationCache(); } - bool includeNonEnumerable = false; - if (listedAttributes & NonEnumerable) - includeNonEnumerable = true; - getNamesFromPropertyTable(propertyNames, includeNonEnumerable); - getNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames, includeNonEnumerable); - if ((listedAttributes & Prototype) && m_prototype.isObject()) { + baseObject->getOwnPropertyNames(exec, propertyNames); + + if (m_prototype.isObject()) { propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. - asObject(m_prototype)->getPropertyNames(exec, propertyNames); + JSObject* prototype = asObject(m_prototype); + while(1) { + if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) { + prototype->getPropertyNames(exec, propertyNames); + break; + } + prototype->getOwnPropertyNames(exec, propertyNames); + JSValue nextProto = prototype->prototype(); + if (!nextProto.isObject()) + break; + prototype = asObject(nextProto); + } } if (shouldCache) { @@ -338,7 +349,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName) materializePropertyMapIfNecessary(); - ASSERT(m_isDictionary); + ASSERT(isDictionary()); ASSERT(m_propertyTable); unsigned i = rep->computedHash(); @@ -380,25 +391,13 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName) PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { - ASSERT(!structure->m_isDictionary); + ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); - if (structure->m_usingSingleTransitionSlot) { - Structure* existingTransition = structure->m_transitions.singleTransition; - if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep() - && existingTransition->m_attributesInPrevious == attributes - && existingTransition->m_specificValueInPrevious == specificValue) { - - ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset); - offset = structure->m_transitions.singleTransition->m_offset; - return existingTransition; - } - } else { - if (Structure* existingTransition = structure->m_transitions.table->get(make_pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> >(propertyName.ustring().rep(), make_pair(attributes, specificValue)))) { - ASSERT(existingTransition->m_offset != noOffset); - offset = existingTransition->m_offset; - return existingTransition; - } + if (Structure* existingTransition = structure->table.get(make_pair(RefPtr<UString::Rep>(propertyName.ustring().rep()), attributes), specificValue)) { + ASSERT(existingTransition->m_offset != noOffset); + offset = existingTransition->m_offset; + return existingTransition; } return 0; @@ -406,12 +405,12 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset) { - ASSERT(!structure->m_isDictionary); + ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset)); if (structure->transitionCount() > s_maxTransitionLength) { - RefPtr<Structure> transition = toDictionaryTransition(structure); + RefPtr<Structure> transition = toCacheableDictionaryTransition(structure); ASSERT(structure != transition); offset = transition->put(propertyName, attributes, specificValue); if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) @@ -449,27 +448,15 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_offset = offset; - if (structure->m_usingSingleTransitionSlot) { - if (!structure->m_transitions.singleTransition) { - structure->m_transitions.singleTransition = transition.get(); - return transition.release(); - } - - Structure* existingTransition = structure->m_transitions.singleTransition; - structure->m_usingSingleTransitionSlot = false; - StructureTransitionTable* transitionTable = new StructureTransitionTable; - structure->m_transitions.table = transitionTable; - transitionTable->add(make_pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> >(existingTransition->m_nameInPrevious.get(), make_pair(existingTransition->m_attributesInPrevious, existingTransition->m_specificValueInPrevious)), existingTransition); - } - structure->m_transitions.table->add(make_pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> >(propertyName.ustring().rep(), make_pair(attributes, specificValue)), transition.get()); + structure->table.add(make_pair(RefPtr<UString::Rep>(propertyName.ustring().rep()), attributes), transition.get(), specificValue); return transition.release(); } PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset) { - ASSERT(!structure->m_isDictionary); + ASSERT(!structure->isUncacheableDictionary()); - RefPtr<Structure> transition = toDictionaryTransition(structure); + RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure); offset = transition->remove(propertyName); @@ -511,6 +498,47 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur return transition.release(); } +PassRefPtr<Structure> Structure::addAnonymousSlotsTransition(Structure* structure, unsigned count) +{ + if (Structure* transition = structure->table.getAnonymousSlotTransition(count)) { + ASSERT(transition->storedPrototype() == structure->storedPrototype()); + return transition; + } + ASSERT(count); + ASSERT(count < ((1<<6) - 2)); + RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo()); + + transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain; + transition->m_previous = structure; + transition->m_nameInPrevious = 0; + transition->m_attributesInPrevious = 0; + transition->m_anonymousSlotsInPrevious = count; + transition->m_specificValueInPrevious = 0; + transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; + transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + + if (structure->m_propertyTable) { + if (structure->m_isPinnedPropertyTable) + transition->m_propertyTable = structure->copyPropertyTable(); + else { + transition->m_propertyTable = structure->m_propertyTable; + structure->m_propertyTable = 0; + } + } else { + if (structure->m_previous) + transition->materializePropertyMap(); + else + transition->createPropertyMapHashTable(); + } + + transition->addAnonymousSlots(count); + if (transition->propertyStorageSize() > transition->propertyStorageCapacity()) + transition->growPropertyStorageCapacity(); + + structure->table.addAnonymousSlotTransition(count, transition.get()); + return transition.release(); +} + PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) { RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); @@ -526,25 +554,35 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) return transition.release(); } -PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure) +PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind) { - ASSERT(!structure->m_isDictionary); - + ASSERT(!structure->isDictionary()); + RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo()); - transition->m_isDictionary = true; + transition->m_dictionaryKind = kind; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; - + structure->materializePropertyMapIfNecessary(); transition->m_propertyTable = structure->copyPropertyTable(); transition->m_isPinnedPropertyTable = true; - + return transition.release(); } +PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure) +{ + return toDictionaryTransition(structure, CachedDictionaryKind); +} + +PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure) +{ + return toDictionaryTransition(structure, UncachedDictionaryKind); +} + PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure) { - ASSERT(structure->m_isDictionary); + ASSERT(structure->isDictionary()); // Since dictionary Structures are not shared, and no opcodes specialize // for them, we don't need to allocate a new Structure when transitioning @@ -553,15 +591,13 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure) // FIMXE: We can make this more efficient by canonicalizing the Structure (draining the // deleted offsets vector) before transitioning from dictionary. if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty()) - structure->m_isDictionary = false; + structure->m_dictionaryKind = NoneDictionaryKind; return structure; } size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { - ASSERT(!m_transitions.singleTransition); - materializePropertyMapIfNecessary(); m_isPinnedPropertyTable = true; @@ -574,8 +610,7 @@ size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, u size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName) { - ASSERT(!m_transitions.singleTransition); - ASSERT(m_isDictionary); + ASSERT(isUncacheableDictionary()); materializePropertyMapIfNecessary(); @@ -638,6 +673,7 @@ PropertyMapHashTable* Structure::copyPropertyTable() if (m_propertyTable->deletedOffsets) newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets); + newTable->anonymousSlotCount = m_propertyTable->anonymousSlotCount; return newTable; } @@ -817,7 +853,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel newOffset = m_propertyTable->deletedOffsets->last(); m_propertyTable->deletedOffsets->removeLast(); } else - newOffset = m_propertyTable->keyCount; + newOffset = m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount; m_propertyTable->entries()[entryIndex - 1].offset = newOffset; ++m_propertyTable->keyCount; @@ -829,6 +865,16 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel return newOffset; } +void Structure::addAnonymousSlots(unsigned count) +{ + m_propertyTable->anonymousSlotCount += count; +} + +bool Structure::hasTransition(UString::Rep* rep, unsigned attributes) +{ + return table.hasTransition(make_pair(RefPtr<UString::Rep>(rep), attributes)); +} + size_t Structure::remove(const Identifier& propertyName) { ASSERT(!propertyName.isNull()); @@ -982,6 +1028,7 @@ void Structure::rehashPropertyMapHashTable(unsigned newTableSize) m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize))); m_propertyTable->size = newTableSize; m_propertyTable->sizeMask = newTableSize - 1; + m_propertyTable->anonymousSlotCount = oldTable->anonymousSlotCount; unsigned lastIndexUsed = 0; unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount; @@ -1021,8 +1068,7 @@ void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool int i = 0; unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned k = 1; k <= entryCount; k++) { - if (m_propertyTable->entries()[k].key - && (includeNonEnumerable || !(m_propertyTable->entries()[k].attributes & DontEnum))) { + if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || includeNonEnumerable)) { PropertyMapEntry* value = &m_propertyTable->entries()[k]; int j; for (j = i - 1; j >= 0 && a[j]->index > value->index; --j) @@ -1049,8 +1095,7 @@ void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool PropertyMapEntry** p = sortedEnumerables.data(); unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { - if (m_propertyTable->entries()[i].key - && (includeNonEnumerable || !(m_propertyTable->entries()[i].attributes & DontEnum))) + if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || includeNonEnumerable)) *p++ = &m_propertyTable->entries()[i]; } @@ -1082,7 +1127,7 @@ void Structure::getNamesFromClassInfoTable(ExecState* exec, const ClassInfo* cla int hashSizeMask = table->compactSize - 1; const HashEntry* entry = table->table; for (int i = 0; i <= hashSizeMask; ++i, ++entry) { - if (entry->key() && (includeNonEnumerable || !(entry->attributes() & DontEnum))) + if (entry->key() && (!(entry->attributes() & DontEnum) || includeNonEnumerable)) propertyNames.add(entry->key()); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h index ca4552b..d012ba9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,18 +44,15 @@ namespace JSC { + class MarkStack; class PropertyNameArray; class PropertyNameArrayData; class StructureChain; class Structure : public RefCounted<Structure> { public: - enum ListedAttribute { - NonEnumerable = 1 << 1, - Prototype = 1 << 2 - }; - friend class JIT; + friend class StructureTransitionTable; static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo) { return adoptRef(new Structure(prototype, typeInfo)); @@ -70,25 +67,24 @@ namespace JSC { static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset); static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype); - static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&); + static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&); + static PassRefPtr<Structure> addAnonymousSlotsTransition(Structure*, unsigned count); static PassRefPtr<Structure> getterSetterTransition(Structure*); - static PassRefPtr<Structure> toDictionaryTransition(Structure*); + static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*); + static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*); static PassRefPtr<Structure> fromDictionaryTransition(Structure*); ~Structure(); - void mark() - { - if (!m_prototype.marked()) - m_prototype.mark(); - } + void markAggregate(MarkStack&); // These should be used with caution. size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t removePropertyWithoutTransition(const Identifier& propertyName); void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; } - - bool isDictionary() const { return m_isDictionary; } + + bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; } + bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; } const TypeInfo& typeInfo() const { return m_typeInfo; } @@ -100,7 +96,7 @@ namespace JSC { void growPropertyStorageCapacity(); size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } - size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } + size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } bool isUsingInlineStorage() const; size_t get(const Identifier& propertyName); @@ -108,10 +104,20 @@ namespace JSC { size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) { ASSERT(!propertyName.isNull()); - return get(propertyName._ustring.rep(), attributes, specificValue); + return get(propertyName.ustring().rep(), attributes, specificValue); + } + bool transitionedFor(const JSCell* specificValue) + { + return m_specificValueInPrevious == specificValue; + } + bool hasTransition(UString::Rep*, unsigned attributes); + bool hasTransition(const Identifier& propertyName, unsigned attributes) + { + return hasTransition(propertyName._ustring.rep(), attributes); } - void getPropertyNames(ExecState*, PropertyNameArray&, JSObject*, unsigned listedAttributes = Prototype); + void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); + void getOwnPropertyNames(ExecState*, PropertyNameArray&, JSObject*, bool includeNonEnumerable = false); bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } @@ -123,9 +129,17 @@ namespace JSC { private: Structure(JSValue prototype, const TypeInfo&); + + typedef enum { + NoneDictionaryKind = 0, + CachedDictionaryKind = 1, + UncachedDictionaryKind = 2 + } DictionaryKind; + static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind); size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t remove(const Identifier& propertyName); + void addAnonymousSlots(unsigned slotCount); void getNamesFromPropertyTable(PropertyNameArray&, bool includeNonEnumerable = false); void getNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&, bool includeNonEnumerable = false); @@ -171,13 +185,10 @@ namespace JSC { RefPtr<Structure> m_previous; RefPtr<UString::Rep> m_nameInPrevious; - - union { - Structure* singleTransition; - StructureTransitionTable* table; - } m_transitions; JSCell* m_specificValueInPrevious; + StructureTransitionTable table; + RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData; PropertyMapHashTable* m_propertyTable; @@ -185,11 +196,18 @@ namespace JSC { size_t m_propertyStorageCapacity; signed char m_offset; - bool m_isDictionary : 1; + unsigned m_dictionaryKind : 2; bool m_isPinnedPropertyTable : 1; bool m_hasGetterSetterProperties : 1; - bool m_usingSingleTransitionSlot : 1; +#if COMPILER(WINSCW) + // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared + // bitfield, when used as argument in make_pair() function calls in structure.ccp. + // This bitfield optimization is insignificant for the Symbian emulator target. + unsigned m_attributesInPrevious; +#else unsigned m_attributesInPrevious : 7; +#endif + unsigned m_anonymousSlotsInPrevious : 6; }; inline size_t Structure::get(const Identifier& propertyName) @@ -236,7 +254,58 @@ namespace JSC { return m_propertyTable->entries()[entryIndex - 1].offset; } } + + bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue) + { + if (usingSingleTransitionSlot()) { + Structure* existingTransition = singleTransition(); + return existingTransition && existingTransition->m_nameInPrevious.get() == key.first + && existingTransition->m_attributesInPrevious == key.second + && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0); + } + TransitionTable::iterator find = table()->find(key); + if (find == table()->end()) + return false; + + return find->second.first || find->second.second->transitionedFor(specificValue); + } + Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const + { + if (usingSingleTransitionSlot()) { + Structure* existingTransition = singleTransition(); + if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first + && existingTransition->m_attributesInPrevious == key.second + && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0)) + return existingTransition; + return 0; + } + + Transition transition = table()->get(key); + if (transition.second && transition.second->transitionedFor(specificValue)) + return transition.second; + return transition.first; + } + + bool StructureTransitionTable::hasTransition(const StructureTransitionTableHash::Key& key) const + { + if (usingSingleTransitionSlot()) { + Structure* transition = singleTransition(); + return transition && transition->m_nameInPrevious == key.first + && transition->m_attributesInPrevious == key.second; + } + return table()->contains(key); + } + + void StructureTransitionTable::reifySingleTransition() + { + ASSERT(usingSingleTransitionSlot()); + Structure* existingTransition = singleTransition(); + TransitionTable* transitionTable = new TransitionTable; + setTransitionTable(transitionTable); + if (existingTransition) + add(make_pair(RefPtr<UString::Rep>(existingTransition->m_nameInPrevious.get()), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious); + } } // namespace JSC #endif // Structure_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp index acebc86..2c38b67 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp @@ -57,7 +57,10 @@ bool StructureChain::isCacheable() const uint32_t i = 0; while (m_vector[i]) { - if (m_vector[i++]->isDictionary()) + // Both classes of dictionary structure may change arbitrarily so we can't cache them + if (m_vector[i]->isDictionary()) + return false; + if (!m_vector[i++]->typeInfo().hasDefaultGetPropertyNames()) return false; } return true; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h index 804cbeb..0fa7b73 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,8 @@ #include <wtf/HashFunctions.h> #include <wtf/HashMap.h> #include <wtf/HashTraits.h> +#include <wtf/PtrAndFlags.h> +#include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> namespace JSC { @@ -37,7 +39,7 @@ namespace JSC { class Structure; struct StructureTransitionTableHash { - typedef std::pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> > Key; + typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; static unsigned hash(const Key& p) { return p.first->computedHash(); @@ -53,20 +55,159 @@ namespace JSC { struct StructureTransitionTableHashTraits { typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits; - typedef WTF::GenericHashTraits<unsigned> SecondFirstTraits; - typedef WTF::GenericHashTraits<JSCell*> SecondSecondTraits; - typedef std::pair<FirstTraits::TraitType, std::pair<SecondFirstTraits::TraitType, SecondSecondTraits::TraitType> > TraitType; + typedef WTF::GenericHashTraits<unsigned> SecondTraits; + typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType; - static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondFirstTraits::emptyValueIsZero && SecondSecondTraits::emptyValueIsZero; - static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), std::make_pair(SecondFirstTraits::emptyValue(), SecondSecondTraits::emptyValue())); } + static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; + static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } - static const bool needsDestruction = FirstTraits::needsDestruction || SecondFirstTraits::needsDestruction || SecondSecondTraits::needsDestruction; + static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } }; - typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable; + class StructureTransitionTable { + typedef std::pair<Structure*, Structure*> Transition; + struct TransitionTable : public HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> { + typedef HashMap<unsigned, Structure*> AnonymousSlotMap; + + void addSlotTransition(unsigned count, Structure* structure) + { + ASSERT(!getSlotTransition(count)); + if (!m_anonymousSlotTable) + m_anonymousSlotTable.set(new AnonymousSlotMap); + m_anonymousSlotTable->add(count, structure); + } + + void removeSlotTransition(unsigned count) + { + ASSERT(getSlotTransition(count)); + m_anonymousSlotTable->remove(count); + } + + Structure* getSlotTransition(unsigned count) + { + if (!m_anonymousSlotTable) + return 0; + + AnonymousSlotMap::iterator find = m_anonymousSlotTable->find(count); + if (find == m_anonymousSlotTable->end()) + return 0; + return find->second; + } + private: + OwnPtr<AnonymousSlotMap> m_anonymousSlotTable; + }; + public: + StructureTransitionTable() { + m_transitions.m_singleTransition.set(0); + m_transitions.m_singleTransition.setFlag(usingSingleSlot); + } + + ~StructureTransitionTable() { + if (!usingSingleTransitionSlot()) + delete table(); + } + + // The contains and get methods accept imprecise matches, so if an unspecialised transition exists + // for the given key they will consider that transition to be a match. If a specialised transition + // exists and it matches the provided specificValue, get will return the specific transition. + inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue); + inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const; + inline bool hasTransition(const StructureTransitionTableHash::Key& key) const; + void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue) + { + if (usingSingleTransitionSlot()) { + ASSERT(contains(key, specificValue)); + setSingleTransition(0); + return; + } + TransitionTable::iterator find = table()->find(key); + if (!specificValue) + find->second.first = 0; + else + find->second.second = 0; + if (!find->second.first && !find->second.second) + table()->remove(find); + } + void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue) + { + if (usingSingleTransitionSlot()) { + if (!singleTransition()) { + setSingleTransition(structure); + return; + } + reifySingleTransition(); + } + if (!specificValue) { + TransitionTable::iterator find = table()->find(key); + if (find == table()->end()) + table()->add(key, Transition(structure, 0)); + else + find->second.first = structure; + } else { + // If we're adding a transition to a specific value, then there cannot be + // an existing transition + ASSERT(!table()->contains(key)); + table()->add(key, Transition(0, structure)); + } + } + + Structure* getAnonymousSlotTransition(unsigned count) + { + if (usingSingleTransitionSlot()) + return 0; + return table()->getSlotTransition(count); + } + + void addAnonymousSlotTransition(unsigned count, Structure* structure) + { + if (usingSingleTransitionSlot()) + reifySingleTransition(); + ASSERT(!table()->getSlotTransition(count)); + table()->addSlotTransition(count, structure); + } + + void removeAnonymousSlotTransition(unsigned count) + { + ASSERT(!usingSingleTransitionSlot()); + table()->removeSlotTransition(count); + } + private: + TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; } + Structure* singleTransition() const { + ASSERT(usingSingleTransitionSlot()); + return m_transitions.m_singleTransition.get(); + } + bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(usingSingleSlot); } + void setSingleTransition(Structure* structure) + { + ASSERT(usingSingleTransitionSlot()); + m_transitions.m_singleTransition.set(structure); + } + + void setTransitionTable(TransitionTable* table) + { + ASSERT(usingSingleTransitionSlot()); +#ifndef NDEBUG + setSingleTransition(0); +#endif + m_transitions.m_table = table; + // This implicitly clears the flag that indicates we're using a single transition + ASSERT(!usingSingleTransitionSlot()); + } + inline void reifySingleTransition(); + + enum UsingSingleSlot { + usingSingleSlot + }; + // Last bit indicates whether we are using the single transition optimisation + union { + TransitionTable* m_table; + PtrAndFlagsBase<Structure, UsingSingleSlot> m_singleTransition; + } m_transitions; + }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SymbolTable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SymbolTable.h index c00f95a..f5e2669 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SymbolTable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SymbolTable.h @@ -121,6 +121,10 @@ namespace JSC { typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable; + class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> + { + }; + } // namespace JSC #endif // SymbolTable_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp index 045a33a..d7fca33 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -120,6 +120,13 @@ void TimeoutChecker::reset() m_timeExecuting = 0; } +void TimeoutChecker::copyTimeoutValues(TimeoutChecker* other) +{ + m_timeoutInterval = other->m_timeoutInterval; + m_startCount = other->m_startCount; + m_intervalBetweenChecks = other->m_intervalBetweenChecks; +} + bool TimeoutChecker::didTimeOut(ExecState* exec) { unsigned currentTime = getCPUTime(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.h index 1680d6d..f9c86ee 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.h @@ -59,6 +59,7 @@ namespace JSC { } void reset(); + void copyTimeoutValues(TimeoutChecker* other); virtual bool didTimeOut(ExecState*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp index fa19932..e66ca93 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp @@ -32,12 +32,14 @@ #include <ctype.h> #include <float.h> #include <limits.h> +#include <limits> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> +#include <wtf/StringExtras.h> #include <wtf/Vector.h> #include <wtf/unicode/UTF8.h> #include <wtf/StringExtras.h> @@ -69,20 +71,20 @@ static const int minLengthToShare = 10; static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); } static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); } -static inline UChar* allocChars(size_t length) +static inline PossiblyNull<UChar*> allocChars(size_t length) { ASSERT(length); if (length > maxUChars()) return 0; - return static_cast<UChar*>(tryFastMalloc(sizeof(UChar) * length)); + return tryFastMalloc(sizeof(UChar) * length); } -static inline UChar* reallocChars(UChar* buffer, size_t length) +static inline PossiblyNull<UChar*> reallocChars(UChar* buffer, size_t length) { ASSERT(length); if (length > maxUChars()) return 0; - return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length)); + return tryFastRealloc(buffer, sizeof(UChar) * length); } static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) @@ -481,8 +483,7 @@ static inline bool expandCapacity(UString::Rep* rep, int requiredLength) if (requiredLength > base->capacity) { size_t newCapacity = expandedSize(requiredLength, base->preCapacity); UChar* oldBuf = base->buf; - base->buf = reallocChars(base->buf, newCapacity); - if (!base->buf) { + if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) { base->buf = oldBuf; return false; } @@ -513,8 +514,7 @@ bool UString::Rep::reserveCapacity(int capacity) size_t newCapacity = expandedSize(capacity, base->preCapacity); UChar* oldBuf = base->buf; - base->buf = reallocChars(base->buf, newCapacity); - if (!base->buf) { + if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) { base->buf = oldBuf; return false; } @@ -541,8 +541,8 @@ void UString::expandPreCapacity(int requiredPreCap) size_t newCapacity = expandedSize(requiredPreCap, base->capacity); int delta = newCapacity - base->capacity - base->preCapacity; - UChar* newBuf = allocChars(newCapacity); - if (!newBuf) { + UChar* newBuf; + if (!allocChars(newCapacity).getValue(newBuf)) { makeNull(); return; } @@ -567,8 +567,8 @@ static PassRefPtr<UString::Rep> createRep(const char* c) return &UString::Rep::empty(); size_t length = strlen(c); - UChar* d = allocChars(length); - if (!d) + UChar* d; + if (!allocChars(length).getValue(d)) return &UString::Rep::null(); else { for (size_t i = 0; i < length; i++) @@ -657,8 +657,8 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re } else { // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); @@ -713,8 +713,8 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re } else { // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) rep = &UString::Rep::null(); else { copyChars(d, rep->data(), thisSize); @@ -801,8 +801,8 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string size_t newCapacity = expandedSize(length, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) return 0; copyChars(d, a->data(), aSize); copyChars(d + aSize, b->data(), bSize); @@ -943,8 +943,7 @@ UString UString::from(int i) return UString(p, static_cast<int>(end - p)); } -#if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC) -UString UString::from(int64_t i) +UString UString::from(long long i) { UChar buf[1 + sizeof(i) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -952,9 +951,13 @@ UString UString::from(int64_t i) if (i == 0) *--p = '0'; - else if (i == LLONG_MIN) { + else if (i == std::numeric_limits<long long>::min()) { char minBuf[1 + sizeof(i) * 3]; - snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", LLONG_MIN); +#if PLATFORM(WIN_OS) + snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min()); +#else + snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min()); +#endif return UString(minBuf); } else { bool negative = false; @@ -972,7 +975,6 @@ UString UString::from(int64_t i) return UString(p, static_cast<int>(end - p)); } -#endif UString UString::from(unsigned int u) { @@ -1026,6 +1028,8 @@ UString UString::from(double d) // avoid ever printing -NaN, in JS conceptually there is only one NaN value if (isnan(d)) return "NaN"; + if (!d) + return "0"; // -0 -> "0" char buf[80]; int decimalPoint; @@ -1108,8 +1112,8 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in if (totalLength == 0) return ""; - UChar* buffer = allocChars(totalLength); - if (!buffer) + UChar* buffer; + if (!allocChars(totalLength).getValue(buffer)) return null(); int maxCount = max(rangeCount, separatorCount); @@ -1137,8 +1141,8 @@ UString UString::replaceRange(int rangeStart, int rangeLength, const UString& re if (totalLength == 0) return ""; - UChar* buffer = allocChars(totalLength); - if (!buffer) + UChar* buffer; + if (!allocChars(totalLength).getValue(buffer)) return null(); copyChars(buffer, data(), rangeStart); @@ -1185,8 +1189,8 @@ UString& UString::append(const UString &t) } else { // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) makeNull(); else { copyChars(d, data(), thisSize); @@ -1208,18 +1212,6 @@ UString& UString::append(const UChar* tData, int tSize) return *this; } -UString& UString::appendNumeric(int i) -{ - m_rep = concatenate(rep(), i); - return *this; -} - -UString& UString::appendNumeric(double d) -{ - m_rep = concatenate(rep(), d); - return *this; -} - UString& UString::append(const char* t) { m_rep = concatenate(m_rep.release(), t); @@ -1238,8 +1230,8 @@ UString& UString::append(UChar c) if (length == 0) { // this is empty - must make a new m_rep because we don't want to pollute the shared empty one size_t newCapacity = expandedSize(1, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) makeNull(); else { d[0] = c; @@ -1266,8 +1258,8 @@ UString& UString::append(UChar c) } else { // This is shared in some way that prevents us from modifying base, so we must make a whole new string. size_t newCapacity = expandedSize(length + 1, 0); - UChar* d = allocChars(newCapacity); - if (!d) + UChar* d; + if (!allocChars(newCapacity).getValue(d)) makeNull(); else { copyChars(d, data(), length); @@ -1345,8 +1337,7 @@ UString& UString::operator=(const char* c) m_rep->_hash = 0; m_rep->len = l; } else { - d = allocChars(l); - if (!d) { + if (!allocChars(l).getValue(d)) { makeNull(); return *this; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h index ab64f52..58c3615 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h @@ -92,7 +92,8 @@ namespace JSC { { // Guard against integer overflow if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) { - if (void * buf = tryFastMalloc(size * sizeof(UChar))) + void* buf = 0; + if (tryFastMalloc(size * sizeof(UChar)).getValue(buf)) return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size)); } return adoptRef(new BaseString(0, 0, 0)); @@ -257,9 +258,7 @@ namespace JSC { } static UString from(int); -#if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC) - static UString from(int64_t i); -#endif + static UString from(long long); static UString from(unsigned int); static UString from(long); static UString from(double); @@ -289,8 +288,6 @@ namespace JSC { UString& append(UChar); UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); } UString& append(const UChar*, int size); - UString& appendNumeric(int); - UString& appendNumeric(double); bool getCString(CStringBuffer&) const; |