diff options
author | Ben Murdoch <benm@google.com> | 2009-08-18 15:36:45 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2009-08-18 19:20:06 +0100 |
commit | d227fc870c7a697500a3c900c31baf05fb9a8524 (patch) | |
tree | a3fa109aa5bf52fef562ac49d97a2f723889cc71 /JavaScriptCore/runtime | |
parent | f2c627513266faa73f7669058d98c60769fb3524 (diff) | |
download | external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.zip external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.gz external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.bz2 |
Merge WebKit r47420
Diffstat (limited to 'JavaScriptCore/runtime')
62 files changed, 969 insertions, 340 deletions
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h index 79fe720..390f7e2 100644 --- a/JavaScriptCore/runtime/Arguments.h +++ b/JavaScriptCore/runtime/Arguments.h @@ -28,6 +28,8 @@ #include "JSFunction.h" #include "JSGlobalObject.h" #include "Interpreter.h" +#include "ObjectConstructor.h" +#include "PrototypeFunction.h" namespace JSC { @@ -114,7 +116,7 @@ namespace JSC { { function = callFrame->callee(); - CodeBlock* codeBlock = &function->body()->generatedBytecode(); + CodeBlock* codeBlock = &function->executable()->generatedBytecode(); int numParameters = codeBlock->m_numParameters; argc = callFrame->argumentCount(); @@ -137,7 +139,7 @@ namespace JSC { int numArguments; getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments); - d->numParameters = callee->body()->parameterCount(); + d->numParameters = callee->executable()->parameterCount(); d->firstParameterIndex = firstParameterIndex; d->numArguments = numArguments; @@ -168,7 +170,7 @@ namespace JSC { : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure()) , d(new ArgumentsData) { - ASSERT(!callFrame->callee()->body()->parameterCount()); + ASSERT(!callFrame->callee()->executable()->parameterCount()); unsigned numArguments = callFrame->argumentCount() - 1; @@ -214,8 +216,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) diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp index e96bdfc..c60cb0e 100644 --- a/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/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/JavaScriptCore/runtime/ArrayConstructor.h b/JavaScriptCore/runtime/ArrayConstructor.h index 8300d8c..2b79510 100644 --- a/JavaScriptCore/runtime/ArrayConstructor.h +++ b/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/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 807e59a..95d3ffc 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -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(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(callData.js.scopeChain); #endif return codeBlock.isNumericCompareFunction(); @@ -144,7 +144,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 +190,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 +298,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) { diff --git a/JavaScriptCore/runtime/BooleanObject.h b/JavaScriptCore/runtime/BooleanObject.h index cfd55fe..1361e46 100644 --- a/JavaScriptCore/runtime/BooleanObject.h +++ b/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)); + } }; BooleanObject* asBooleanObject(JSValue); diff --git a/JavaScriptCore/runtime/BooleanPrototype.cpp b/JavaScriptCore/runtime/BooleanPrototype.cpp index 703a568..cf4fbd7 100644 --- a/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/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/JavaScriptCore/runtime/CallData.h b/JavaScriptCore/runtime/CallData.h index d5b0172..24c19f9 100644 --- a/JavaScriptCore/runtime/CallData.h +++ b/JavaScriptCore/runtime/CallData.h @@ -35,7 +35,7 @@ namespace JSC { class ArgList; class ExecState; - class FunctionBodyNode; + class FunctionExecutable; class JSObject; class JSValue; class ScopeChainNode; @@ -53,7 +53,7 @@ namespace JSC { NativeFunction function; } native; struct { - FunctionBodyNode* functionBody; + FunctionExecutable* functionExecutable; ScopeChainNode* scopeChain; } js; }; diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index c188016..f48e243 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -23,8 +23,10 @@ #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" @@ -59,10 +61,16 @@ #include <windows.h> +#elif PLATFORM(HAIKU) + +#include <OS.h> + #elif PLATFORM(UNIX) #include <stdlib.h> +#if !PLATFORM(HAIKU) #include <sys/mman.h> +#endif #include <unistd.h> #if PLATFORM(SOLARIS) @@ -75,6 +83,13 @@ #include <pthread_np.h> #endif +#if PLATFORM(QNX) +#include <fcntl.h> +#include <sys/procfs.h> +#include <stdio.h> +#include <errno.h> +#endif + #endif #define DEBUG_COLLECTOR 0 @@ -486,6 +501,33 @@ static void* getStackBase(void* previousFrame) } #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) @@ -511,6 +553,8 @@ static inline void* currentThreadStackBase() : "=r" (pTib) ); return static_cast<void*>(pTib->StackBase); +#elif PLATFORM(QNX) + return currentThreadStackBaseQNX(); #elif PLATFORM(SOLARIS) stack_t s; thr_stksegment(&s); @@ -529,6 +573,10 @@ 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) static void* stackBase = 0; static size_t stackSize = 0; @@ -1091,8 +1139,8 @@ bool Heap::collect() markStack.append(m_globalData->exception); m_globalData->interpreter->registerFile().markCallFrames(markStack, this); m_globalData->smallStrings.mark(); - if (m_globalData->scopeNodeBeingReparsed) - m_globalData->scopeNodeBeingReparsed->markAggregate(markStack); + if (m_globalData->functionCodeBlockBeingReparsed) + m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack); if (m_globalData->firstStringifierToMark) JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index 148d3dd..678e109 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -47,6 +47,7 @@ macro(ignoreCase) \ macro(index) \ macro(input) \ + macro(isArray) \ macro(isPrototypeOf) \ macro(length) \ macro(message) \ diff --git a/JavaScriptCore/runtime/Completion.cpp b/JavaScriptCore/runtime/Completion.cpp index b8b1581..6ae5aa2 100644 --- a/JavaScriptCore/runtime/Completion.cpp +++ b/JavaScriptCore/runtime/Completion.cpp @@ -41,30 +41,27 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) { JSLock lock(exec); - int errLine; - UString errMsg; + ProgramExecutable program(source); + JSObject* error = program.parse(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); - - int errLine; - UString errMsg; - RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (!programNode) - return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url())); + ProgramExecutable program(source); + JSObject* error = program.parse(exec); + 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/JavaScriptCore/runtime/ConstructData.h b/JavaScriptCore/runtime/ConstructData.h index 9d580d5..6b954a6 100644 --- a/JavaScriptCore/runtime/ConstructData.h +++ b/JavaScriptCore/runtime/ConstructData.h @@ -33,7 +33,7 @@ namespace JSC { class ArgList; class ExecState; - class FunctionBodyNode; + class FunctionExecutable; class JSObject; class JSValue; class ScopeChainNode; @@ -51,7 +51,7 @@ namespace JSC { NativeConstructor function; } native; struct { - FunctionBodyNode* functionBody; + FunctionExecutable* functionExecutable; ScopeChainNode* scopeChain; } js; }; diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp index 2f52cff..1879c3f 100644 --- a/JavaScriptCore/runtime/DateConstructor.cpp +++ b/JavaScriptCore/runtime/DateConstructor.cpp @@ -79,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); diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index e2482f4..54d3cf3 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -411,7 +411,7 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper 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 +428,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 +445,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; @@ -467,7 +467,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSVal 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 +484,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 +501,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 +514,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 +527,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 +540,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 +553,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 +570,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 +587,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 +604,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 +621,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 +638,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 +655,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 +672,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 +689,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 +706,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 +723,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 +740,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 +757,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 +774,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 +791,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 +808,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 +823,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 +838,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 +855,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 +868,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 +899,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 +1020,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 +1062,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/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp index db1d8cc..ddd4bc4 100644 --- a/JavaScriptCore/runtime/Error.cpp +++ b/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/JavaScriptCore/runtime/Error.h b/JavaScriptCore/runtime/Error.h index adf7fdf..e959cff 100644 --- a/JavaScriptCore/runtime/Error.h +++ b/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*); } // namespace JSC diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index e63594c..cc18b95 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/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/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp new file mode 100644 index 0000000..053dbfb --- /dev/null +++ b/JavaScriptCore/runtime/Executable.cpp @@ -0,0 +1,216 @@ +/* + * 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" + +namespace JSC { + +EvalExecutable::~EvalExecutable() +{ + delete m_evalCodeBlock; +} + +ProgramExecutable::~ProgramExecutable() +{ + delete m_programCodeBlock; +} + +FunctionExecutable::~FunctionExecutable() +{ + delete m_codeBlock; +} + +void EvalExecutable::generateBytecode(ScopeChainNode* scopeChainNode) +{ + 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(), globalObject->debugger(), scopeChain, &m_evalCodeBlock->symbolTable(), m_evalCodeBlock)); + generator->generate(); + + evalNode()->partialDestroyData(); +} + +void ProgramExecutable::generateBytecode(ScopeChainNode* scopeChainNode) +{ + 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(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock)); + generator->generate(); + + programNode()->destroyData(); +} + +void FunctionExecutable::generateBytecode(ScopeChainNode* scopeChainNode) +{ + body()->reparseDataIfNecessary(scopeChainNode); + + 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(), globalObject->debugger(), scopeChain, &m_codeBlock->symbolTable(), m_codeBlock)); + generator->generate(); + + body()->destroyData(); +} + +#if ENABLE(JIT) + +void EvalExecutable::generateJITCode(ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +void ProgramExecutable::generateJITCode(ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +void FunctionExecutable::generateJITCode(ScopeChainNode* scopeChainNode) +{ + CodeBlock* codeBlock = &bytecode(scopeChainNode); + m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock); + +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->discardBytecode(); +#endif +} + +#endif + +bool FunctionExecutable::isHostFunction() const +{ + return m_codeBlock && m_codeBlock->codeType() == NativeCode; +} + +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->reparse<FunctionBodyNode>(globalData, body()); + ASSERT(newFunctionBody); + newFunctionBody->finishParsing(body()->copyParameters(), body()->parameterCount(), body()->ident()); + + 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->reparse<EvalNode>(globalData, evalNode()); + + 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* exec) +{ + FunctionBodyNode* oldBody = body(); + RefPtr<FunctionBodyNode> newBody = exec->globalData().parser->parse<FunctionBodyNode>(exec, 0, m_source); + ASSERT(newBody); + newBody->finishParsing(oldBody->copyParameters(), oldBody->parameterCount(), oldBody->ident()); + m_node = newBody; + delete m_codeBlock; + m_codeBlock = 0; +#if ENABLE(JIT) + m_jitCode = JITCode(); +#endif +} + +#if ENABLE(JIT) +FunctionExecutable::FunctionExecutable(ExecState* exec) + : m_codeBlock(new NativeCodeBlock(this)) + , m_name(Identifier(exec, "<native thunk>")) +{ + m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk())); +} +#endif + +}; + + diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h new file mode 100644 index 0000000..29288df --- /dev/null +++ b/JavaScriptCore/runtime/Executable.h @@ -0,0 +1,268 @@ +/* + * 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 "Nodes.h" + +namespace JSC { + + class CodeBlock; + class EvalCodeBlock; + class ProgramCodeBlock; + class ScopeChainNode; + + struct ExceptionInfo; + + class ExecutableBase { + friend class JIT; + public: + virtual ~ExecutableBase() {} + + ExecutableBase(const SourceCode& source) + : m_source(source) + { + } + + const SourceCode& source() { return m_source; } + intptr_t sourceID() const { return m_node->sourceID(); } + const UString& sourceURL() const { return m_node->sourceURL(); } + int lineNo() const { return m_node->lineNo(); } + int lastLine() const { return m_node->lastLine(); } + + bool usesEval() const { return m_node->usesEval(); } + bool usesArguments() const { return m_node->usesArguments(); } + bool needsActivation() const { return m_node->needsActivation(); } + + virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0; + + ScopeNode* astNode() { return m_node.get(); } + + protected: + RefPtr<ScopeNode> m_node; + SourceCode m_source; + + private: + // For use making native thunk. + friend class FunctionExecutable; + ExecutableBase() + { + } + +#if ENABLE(JIT) + public: + JITCode& generatedJITCode() + { + ASSERT(m_jitCode); + return m_jitCode; + } + + ExecutablePool* getExecutablePool() + { + return m_jitCode.getExecutablePool(); + } + + protected: + JITCode m_jitCode; +#endif + }; + + class EvalExecutable : public ExecutableBase { + public: + EvalExecutable(const SourceCode& source) + : ExecutableBase(source) + , m_evalCodeBlock(0) + { + } + + ~EvalExecutable(); + + JSObject* parse(ExecState* exec, bool allowDebug = true); + + EvalCodeBlock& bytecode(ScopeChainNode* scopeChainNode) + { + if (!m_evalCodeBlock) + generateBytecode(scopeChainNode); + return *m_evalCodeBlock; + } + + DeclarationStacks::VarStack& varStack() { return m_node->varStack(); } + + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + + private: + EvalNode* evalNode() { return static_cast<EvalNode*>(m_node.get()); } + + void generateBytecode(ScopeChainNode*); + + EvalCodeBlock* m_evalCodeBlock; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(scopeChainNode); + return m_jitCode; + } + + private: + void generateJITCode(ScopeChainNode*); +#endif + }; + + class CacheableEvalExecutable : public EvalExecutable, public RefCounted<CacheableEvalExecutable> { + public: + static PassRefPtr<CacheableEvalExecutable> create(const SourceCode& source) { return adoptRef(new CacheableEvalExecutable(source)); } + + private: + CacheableEvalExecutable(const SourceCode& source) + : EvalExecutable(source) + { + } + }; + + class ProgramExecutable : public ExecutableBase { + public: + ProgramExecutable(const SourceCode& source) + : ExecutableBase(source) + , m_programCodeBlock(0) + { + } + + ~ProgramExecutable(); + + JSObject* parse(ExecState* exec, bool allowDebug = true); + + // CodeBlocks for program code are transient and therefore to not gain from from throwing out there exception information. + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; } + + ProgramCodeBlock& bytecode(ScopeChainNode* scopeChainNode) + { + if (!m_programCodeBlock) + generateBytecode(scopeChainNode); + return *m_programCodeBlock; + } + + private: + ProgramNode* programNode() { return static_cast<ProgramNode*>(m_node.get()); } + + void generateBytecode(ScopeChainNode*); + + ProgramCodeBlock* m_programCodeBlock; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(scopeChainNode); + return m_jitCode; + } + + private: + void generateJITCode(ScopeChainNode*); +#endif + }; + + class FunctionExecutable : public ExecutableBase, public RefCounted<FunctionExecutable> { + friend class JIT; + public: + FunctionExecutable(const Identifier& name, FunctionBodyNode* body) + : ExecutableBase(body->source()) + , m_codeBlock(0) + , m_name(name) + { + m_node = body; + } + + ~FunctionExecutable(); + + const Identifier& name() { return m_name; } + + JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain); + + CodeBlock& bytecode(ScopeChainNode* scopeChainNode) + { + ASSERT(scopeChainNode); + if (!m_codeBlock) + generateBytecode(scopeChainNode); + return *m_codeBlock; + } + CodeBlock& generatedBytecode() + { + ASSERT(m_codeBlock); + return *m_codeBlock; + } + + bool usesEval() const { return body()->usesEval(); } + bool usesArguments() const { return body()->usesArguments(); } + size_t parameterCount() const { return body()->parameterCount(); } + UString paramString() const { return body()->paramString(); } + + bool isHostFunction() const; + bool isGenerated() const + { + return m_codeBlock; + } + + void recompile(ExecState* exec); + + ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + + void markAggregate(MarkStack& markStack); + + private: + FunctionBodyNode* body() const { return static_cast<FunctionBodyNode*>(m_node.get()); } + + void generateBytecode(ScopeChainNode*); + + CodeBlock* m_codeBlock; + const Identifier& m_name; + +#if ENABLE(JIT) + public: + JITCode& jitCode(ScopeChainNode* scopeChainNode) + { + if (!m_jitCode) + generateJITCode(scopeChainNode); + return m_jitCode; + } + + static PassRefPtr<FunctionExecutable> createNativeThunk(ExecState* exec) + { + return adoptRef(new FunctionExecutable(exec)); + } + + private: + FunctionExecutable(ExecState* exec); + void generateJITCode(ScopeChainNode*); +#endif + }; + +}; + +#endif diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index f4f5cc8..2783b35 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/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()); + RefPtr<FunctionBodyNode> body = exec->globalData().parser->parseFunctionFromGlobalCode(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); if (!body) 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, adoptRef(new FunctionExecutable(functionName, body.get())), scopeChain.node()); } // ECMA 15.3.2 The Function Constructor diff --git a/JavaScriptCore/runtime/FunctionConstructor.h b/JavaScriptCore/runtime/FunctionConstructor.h index 124b354..e8486dc 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.h +++ b/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/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index 9ba2144..d911f2f 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/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->executable(); + if (!executable->isHostFunction()) { + 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/JavaScriptCore/runtime/FunctionPrototype.h b/JavaScriptCore/runtime/FunctionPrototype.h index 607ddab..4f674f5 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.h +++ b/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)); } private: diff --git a/JavaScriptCore/runtime/InternalFunction.h b/JavaScriptCore/runtime/InternalFunction.h index 310644c..37077f6 100644 --- a/JavaScriptCore/runtime/InternalFunction.h +++ b/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/JavaScriptCore/runtime/JSAPIValueWrapper.h b/JavaScriptCore/runtime/JSAPIValueWrapper.h index 21a9710..5cd4bdd 100644 --- a/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -54,6 +54,7 @@ namespace JSC { : JSCell(exec->globalData().apiWrapperStructure.get()) , m_value(value) { + ASSERT(!value.isCell()); } JSValue m_value; diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index 87adbcd..d025abb 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -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())) { } @@ -57,12 +57,12 @@ void JSActivation::markChildren(MarkStack& markStack) if (!registerArray) return; - size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1; + size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1; size_t count = numParametersMinusThis; markStack.appendValues(registerArray, count); - size_t numVars = d()->functionBody->generatedBytecode().m_numVars; + size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars; // Skip the call frame, which sits between the parameters and vars. markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); @@ -136,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); @@ -156,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/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 6a08439..285ae67 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -43,7 +43,7 @@ namespace JSC { class JSActivation : public JSVariableObject { typedef JSVariableObject Base; public: - JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>); + JSActivation(CallFrame*, PassRefPtr<FunctionExecutable>); virtual ~JSActivation(); virtual void markChildren(MarkStack&); @@ -70,13 +70,13 @@ 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) { } - RefPtr<FunctionBodyNode> functionBody; + RefPtr<FunctionExecutable> functionExecutable; }; static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index 7d7d4c4..90e0434 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -25,6 +25,7 @@ #include "ArrayPrototype.h" #include "CachedCall.h" +#include "Error.h" #include "PropertyNameArray.h" #include <wtf/AVLTree.h> #include <wtf/Assertions.h> @@ -348,8 +349,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; } @@ -467,8 +467,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)); @@ -603,18 +602,7 @@ void JSArray::push(ExecState* exec, JSValue value) void JSArray::markChildren(MarkStack& markStack) { - JSObject::markChildren(markStack); - - ArrayStorage* storage = m_storage; - - unsigned usedVectorLength = 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); - } + markChildrenDirect(markStack); } static int compareNumbersForQSort(const void* a, const void* b) diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index 49df6c4..88d8ee4 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -82,6 +82,8 @@ namespace JSC { { return Structure::create(prototype, TypeInfo(ObjectType)); } + + inline void markChildrenDirect(MarkStack& markStack); protected: virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -125,6 +127,77 @@ namespace JSC { inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; } + 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::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 v = *current.m_values; + current.m_values++; + + if (!v || v.marked()) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + JSCell* currentCell = v.asCell(); + currentCell->markCellDirect(); + if (currentCell->structure()->typeInfo().type() < CompoundType) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + if (current.m_values == end) + m_markSets.removeLast(); + + if (currentCell->structure()->typeInfo().hasDefaultMark()) + static_cast<JSObject*>(currentCell)->markChildrenDirect(*this); + else if (currentCell->vptr() == m_jsArrayVPtr) + static_cast<JSArray*>(currentCell)->markChildrenDirect(*this); + else + currentCell->markChildren(*this); + } + while (!m_values.isEmpty()) { + JSCell* current = m_values.removeLast(); + ASSERT(current->marked()); + if (current->structure()->typeInfo().hasDefaultMark()) + static_cast<JSObject*>(current)->markChildrenDirect(*this); + else if (current->vptr() == m_jsArrayVPtr) + static_cast<JSArray*>(current)->markChildrenDirect(*this); + else + current->markChildren(*this); + } + } + } + } // namespace JSC #endif // JSArray_h diff --git a/JavaScriptCore/runtime/JSByteArray.cpp b/JavaScriptCore/runtime/JSByteArray.cpp index 2a5e72f..f832578 100644 --- a/JavaScriptCore/runtime/JSByteArray.cpp +++ b/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; } diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index 75ccf7f..485ad2e 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -55,7 +55,7 @@ namespace JSC { 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; @@ -379,30 +379,6 @@ namespace JSC { if (cell->structure()->typeInfo().type() >= CompoundType) m_values.append(cell); } - - inline void MarkStack::drain() { - while (!m_markSets.isEmpty() || !m_values.isEmpty()) { - while ((!m_markSets.isEmpty()) && m_values.size() < 50) { - const MarkSet& current = m_markSets.removeLast(); - JSValue* ptr = current.m_values; - JSValue* end = current.m_end; - if (current.m_properties == NoNullValues) { - while (ptr != end) - append(*ptr++); - } else { - while (ptr != end) { - if (JSValue value = *ptr++) - append(value); - } - } - } - while (!m_values.isEmpty()) { - JSCell* current = m_values.removeLast(); - ASSERT(current->marked()); - current->markChildren(*this); - } - } - } } // namespace JSC #endif // JSCell_h diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index 84c6263..f8e3d82 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -45,12 +45,26 @@ ASSERT_CLASS_FITS_IN_CELL(JSFunction); const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; +inline bool JSFunction::isHostFunction() const +{ + return m_executable && m_executable->isHostFunction(); +} + +bool JSFunction::isHostFunctionNonInline() const +{ + return isHostFunction(); +} + +JSFunction::JSFunction(PassRefPtr<Structure> structure) + : Base(structure) +{ + clearScopeChain(); +} + 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(FunctionExecutable::createNativeThunk(exec)) #endif { #if ENABLE(JIT) @@ -63,9 +77,9 @@ 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); } @@ -76,8 +90,8 @@ JSFunction::~JSFunction() // 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 ENABLE(JIT_OPTIMIZE_CALL) - if (m_body && m_body->isGenerated()) - m_body->generatedBytecode().unlinkCallers(); + if (m_executable && m_executable->isGenerated()) + m_executable->generatedBytecode().unlinkCallers(); #endif if (!isHostFunction()) scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too? @@ -86,7 +100,7 @@ JSFunction::~JSFunction() void JSFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - m_body->markAggregate(markStack); + m_executable->markAggregate(markStack); if (!isHostFunction()) scopeChain().markAggregate(markStack); } @@ -97,7 +111,7 @@ CallType JSFunction::getCallData(CallData& callData) callData.native.function = nativeFunction(); return CallTypeHost; } - callData.js.functionBody = m_body.get(); + callData.js.functionExecutable = m_executable.get(); callData.js.scopeChain = scopeChain().node(); return CallTypeJS; } @@ -105,7 +119,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(m_executable.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); } JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) @@ -126,7 +140,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->m_executable->parameterCount()); } bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -190,7 +204,7 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData) { if (isHostFunction()) return ConstructTypeNone; - constructData.js.functionBody = m_body.get(); + constructData.js.functionExecutable = m_executable.get(); constructData.js.scopeChain = scopeChain().node(); return ConstructTypeJS; } @@ -206,7 +220,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(m_executable.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h index cab1e5b..71998dc 100644 --- a/JavaScriptCore/runtime/JSFunction.h +++ b/JavaScriptCore/runtime/JSFunction.h @@ -24,15 +24,11 @@ #ifndef JSFunction_h #define JSFunction_h +#include "Executable.h" #include "InternalFunction.h" -#include "JSVariableObject.h" -#include "SymbolTable.h" -#include "Nodes.h" -#include "JSObject.h" namespace JSC { - class FunctionBodyNode; class FunctionPrototype; class JSActivation; class JSGlobalObject; @@ -43,20 +39,10 @@ namespace JSC { 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); + JSFunction(ExecState*, PassRefPtr<FunctionExecutable>, ScopeChainNode*); + virtual ~JSFunction(); JSObject* construct(ExecState*, const ArgList&); JSValue call(ExecState*, JSValue thisValue, const ArgList&); @@ -64,11 +50,7 @@ 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(); } - - virtual void markChildren(MarkStack&); + FunctionExecutable* executable() const { return m_executable.get(); } static JS_EXPORTDATA const ClassInfo info; @@ -77,11 +59,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 +68,42 @@ namespace JSC { virtual CallType getCallData(CallData&); private: + JSFunction(PassRefPtr<Structure>); + + bool isHostFunction() const; + bool isHostFunctionNonInline() const; + + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); + virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + + 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<FunctionExecutable> 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) @@ -133,6 +121,11 @@ namespace JSC { return static_cast<JSFunction*>(asObject(value)); } + inline JSFunction* FunctionExecutable::make(ExecState* exec, ScopeChainNode* scopeChain) + { + return new (exec) JSFunction(exec, this, scopeChain); + } + } // namespace JSC #endif // JSFunction_h diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 03df41d..38ee1d0 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -144,8 +144,9 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , initializingLazyNumericCompareFunction(false) , head(0) , dynamicGlobalObject(0) - , scopeNodeBeingReparsed(0) + , functionCodeBlockBeingReparsed(0) , firstStringifierToMark(0) + , markStack(vptrSet.jsArrayVPtr) { #if PLATFORM(MAC) startProfilerServerIfNeeded(); @@ -235,9 +236,9 @@ 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<FunctionBodyNode> functionBody = parser->parseFunctionFromGlobalCode(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); + FunctionExecutable function(functionBody->ident(), functionBody.get()); + lazyNumericCompareFunction = function.bytecode(exec->scopeChain()).instructions(); initializingLazyNumericCompareFunction = false; } diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index 88cb516..77556b7 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -45,15 +45,14 @@ struct OpaqueJSClassContextData; namespace JSC { + class CodeBlock; class CommonIdentifiers; - class FunctionBodyNode; class IdentifierTable; class Interpreter; class JSGlobalObject; class JSObject; class Lexer; class Parser; - class ScopeNode; class Stringifier; class Structure; class UString; @@ -145,7 +144,7 @@ namespace JSC { HashSet<JSObject*> arrayVisitedElements; - ScopeNode* scopeNodeBeingReparsed; + CodeBlock* functionCodeBlockBeingReparsed; Stringifier* firstStringifierToMark; MarkStack markStack; diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index a90f18f..3a1909d 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -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(); @@ -258,7 +258,7 @@ void JSGlobalObject::reset(JSValue prototype) 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); @@ -361,8 +361,8 @@ void JSGlobalObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - 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)->markAggregate(markStack); RegisterFile& registerFile = globalData()->interpreter->registerFile(); diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index cda49bd..cc36ada 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -38,6 +38,7 @@ namespace JSC { class Debugger; class ErrorConstructor; class FunctionPrototype; + class GlobalCodeBlock; class GlobalEvalFunction; class NativeErrorConstructor; class ProgramCodeBlock; @@ -144,7 +145,7 @@ namespace JSC { RefPtr<JSGlobalData> globalData; - HashSet<ProgramCodeBlock*> codeBlocks; + HashSet<GlobalCodeBlock*> codeBlocks; }; public: @@ -246,7 +247,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&); diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index affb99c..50ea27f 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/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.parse(exec); + 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) diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h index 04cccef..6a48081 100644 --- a/JavaScriptCore/runtime/JSNumberCell.h +++ b/JavaScriptCore/runtime/JSNumberCell.h @@ -84,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) diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index d643808..fed9fc3 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -381,6 +381,15 @@ 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, "JSON.stringify cannot serialize cyclic structures."); diff --git a/JavaScriptCore/runtime/JSONObject.h b/JavaScriptCore/runtime/JSONObject.h index faca7c7..c61b0dd 100644 --- a/JavaScriptCore/runtime/JSONObject.h +++ b/JavaScriptCore/runtime/JSONObject.h @@ -41,7 +41,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark)); } static void markStringifiers(MarkStack&, Stringifier*); diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index 419dfe9..57624fb 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -37,26 +37,6 @@ #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 { @@ -64,16 +44,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSObject); void JSObject::markChildren(MarkStack& markStack) { - JSOBJECT_MARK_BEGIN(); - - JSCell::markChildren(markStack); - m_structure->markAggregate(markStack); - - PropertyStorage storage = propertyStorage(); - size_t storageSize = m_structure->propertyStorageSize(); - markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize); - - JSOBJECT_MARK_END(); + markChildrenDirect(markStack); } UString JSObject::className() const diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index decd5e9..856c5a1 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -27,7 +27,9 @@ #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" @@ -74,13 +76,12 @@ namespace JSC { explicit JSObject(PassRefPtr<Structure>); 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); @@ -201,10 +202,22 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot)); + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark)); } 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); } @@ -293,7 +306,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 +315,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) @@ -627,6 +640,16 @@ 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/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index 3daf58a..f9b0a8f 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -90,7 +90,7 @@ namespace JSC { 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 }; diff --git a/JavaScriptCore/runtime/JSType.h b/JavaScriptCore/runtime/JSType.h index a118b87..882b218 100644 --- a/JavaScriptCore/runtime/JSType.h +++ b/JavaScriptCore/runtime/JSType.h @@ -33,7 +33,6 @@ namespace JSC { NumberType = 3, NullType = 4, StringType = 5, - // The CompoundType value must come before any JSType that may have children CompoundType = 6, ObjectType = 7, diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index 408c187..b72cc6e 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -130,7 +130,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; diff --git a/JavaScriptCore/runtime/MarkStack.h b/JavaScriptCore/runtime/MarkStack.h index 7a7b3af..a97aa7e 100644 --- a/JavaScriptCore/runtime/MarkStack.h +++ b/JavaScriptCore/runtime/MarkStack.h @@ -31,15 +31,15 @@ #include <wtf/Noncopyable.h> namespace JSC { + class JSGlobalData; class Register; enum MarkSetProperties { MayContainNullValues, NoNullValues }; class MarkStack : Noncopyable { public: - MarkStack() - : m_markSets() - , m_values() + MarkStack(void* jsArrayVPtr) + : m_jsArrayVPtr(jsArrayVPtr) { } @@ -82,6 +82,7 @@ namespace JSC { , m_end(end) , m_properties(properties) { + ASSERT(values); } JSValue* m_values; JSValue* m_end; @@ -136,6 +137,12 @@ namespace JSC { ASSERT(m_top); return m_data[--m_top]; } + + inline T& last() + { + ASSERT(m_top); + return m_data[m_top - 1]; + } inline bool isEmpty() { @@ -150,7 +157,14 @@ namespace JSC { 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); } @@ -162,6 +176,7 @@ namespace JSC { T* m_data; }; + void* m_jsArrayVPtr; MarkStackArray<MarkSet> m_markSets; MarkStackArray<JSCell*> m_values; static size_t s_pageSize; diff --git a/JavaScriptCore/runtime/MarkStackWin.cpp b/JavaScriptCore/runtime/MarkStackWin.cpp index dbc3306..1fdd06a 100644 --- a/JavaScriptCore/runtime/MarkStackWin.cpp +++ b/JavaScriptCore/runtime/MarkStackWin.cpp @@ -43,9 +43,11 @@ void* MarkStack::allocateStack(size_t size) { return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); } -void MarkStack::releaseStack(void* addr, size_t size) +void MarkStack::releaseStack(void* addr, size_t) { - VirtualFree(addr, size, MEM_RELEASE); + // 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/JavaScriptCore/runtime/MathObject.h b/JavaScriptCore/runtime/MathObject.h index 3557d1e..06aa54b 100644 --- a/JavaScriptCore/runtime/MathObject.h +++ b/JavaScriptCore/runtime/MathObject.h @@ -36,7 +36,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark)); } }; diff --git a/JavaScriptCore/runtime/NumberConstructor.h b/JavaScriptCore/runtime/NumberConstructor.h index b1224ec..6e67840 100644 --- a/JavaScriptCore/runtime/NumberConstructor.h +++ b/JavaScriptCore/runtime/NumberConstructor.h @@ -38,7 +38,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark)); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h index d354b9b..07a013f 100644 --- a/JavaScriptCore/runtime/NumberObject.h +++ b/JavaScriptCore/runtime/NumberObject.h @@ -30,6 +30,11 @@ namespace JSC { explicit NumberObject(PassRefPtr<Structure>); static const ClassInfo info; + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark)); + } private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp index 70c7cd1..b05b910 100644 --- a/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "ObjectConstructor.h" +#include "Error.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "ObjectPrototype.h" diff --git a/JavaScriptCore/runtime/PropertySlot.cpp b/JavaScriptCore/runtime/PropertySlot.cpp index 36fa5d8..a0a2f48 100644 --- a/JavaScriptCore/runtime/PropertySlot.cpp +++ b/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/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index 6a8089d..62d56e9 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/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" @@ -329,7 +330,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/JavaScriptCore/runtime/RegExpConstructor.h b/JavaScriptCore/runtime/RegExpConstructor.h index 6823f3f..30b9750 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.h +++ b/JavaScriptCore/runtime/RegExpConstructor.h @@ -36,7 +36,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark)); } virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h index e83e0ac..5ca3b3f 100644 --- a/JavaScriptCore/runtime/RegExpObject.h +++ b/JavaScriptCore/runtime/RegExpObject.h @@ -48,7 +48,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark)); } private: diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp index b1ab889..30420e9 100644 --- a/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/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/JavaScriptCore/runtime/ScopeChain.cpp b/JavaScriptCore/runtime/ScopeChain.cpp index 5c2edab..960c525 100644 --- a/JavaScriptCore/runtime/ScopeChain.cpp +++ b/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/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index bc5c0a5..1d2e03f 100644 --- a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/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/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index 531a302..b4f7634 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -23,6 +23,7 @@ #include "StringPrototype.h" #include "CachedCall.h" +#include "Error.h" #include "JSArray.h" #include "JSFunction.h" #include "ObjectPrototype.h" @@ -220,7 +221,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 +366,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); @@ -466,7 +467,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 +517,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 +569,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 +822,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 +870,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/JavaScriptCore/runtime/TypeInfo.h b/JavaScriptCore/runtime/TypeInfo.h index 70aeed3..20c13ea 100644 --- a/JavaScriptCore/runtime/TypeInfo.h +++ b/JavaScriptCore/runtime/TypeInfo.h @@ -38,6 +38,7 @@ 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; class TypeInfo { friend class JIT; @@ -59,7 +60,7 @@ 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; } unsigned flags() const { return m_flags; } private: diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index 118751e..9977f12 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/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> @@ -68,20 +70,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) @@ -480,8 +482,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; } @@ -512,8 +513,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; } @@ -540,8 +540,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; } @@ -566,8 +566,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++) @@ -656,8 +656,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); @@ -712,8 +712,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); @@ -800,8 +800,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); @@ -942,6 +942,39 @@ UString UString::from(int i) return UString(p, static_cast<int>(end - p)); } +UString UString::from(long long i) +{ + UChar buf[1 + sizeof(i) * 3]; + UChar* end = buf + sizeof(buf) / sizeof(UChar); + UChar* p = end; + + if (i == 0) + *--p = '0'; + else if (i == std::numeric_limits<long long>::min()) { + char minBuf[1 + sizeof(i) * 3]; +#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; + if (i < 0) { + negative = true; + i = -i; + } + while (i) { + *--p = static_cast<unsigned short>((i % 10) + '0'); + i /= 10; + } + if (negative) + *--p = '-'; + } + + return UString(p, static_cast<int>(end - p)); +} + UString UString::from(unsigned int u) { UChar buf[sizeof(u) * 3]; @@ -1076,8 +1109,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); @@ -1105,8 +1138,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); @@ -1153,8 +1186,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); @@ -1206,8 +1239,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; @@ -1234,8 +1267,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); @@ -1313,8 +1346,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/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h index d01b75d..2dbca1f 100644 --- a/JavaScriptCore/runtime/UString.h +++ b/JavaScriptCore/runtime/UString.h @@ -91,7 +91,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)); @@ -256,6 +257,7 @@ namespace JSC { } static UString from(int); + static UString from(long long); static UString from(unsigned int); static UString from(long); static UString from(double); |