diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime')
89 files changed, 981 insertions, 1079 deletions
diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h index ac5a4f271..1512a0fa1 100644 --- a/Source/JavaScriptCore/runtime/ArgList.h +++ b/Source/JavaScriptCore/runtime/ArgList.h @@ -102,7 +102,7 @@ namespace JSC { static void markLists(HeapRootVisitor&, ListSet&); private: - void slowAppend(JSValue); + JS_EXPORT_PRIVATE void slowAppend(JSValue); EncodedJSValue& slotFor(int item) const { @@ -171,7 +171,7 @@ namespace JSC { bool isEmpty() const { return !m_argCount; } size_t size() const { return m_argCount; } - void getSlice(int startIndex, ArgList& result) const; + JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const; private: JSValue* m_args; diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index fc136eb7e..6a675ab84 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -109,7 +109,7 @@ void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) d->overrodeCaller = true; PropertyDescriptor descriptor; - descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter); + descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false); } @@ -120,7 +120,7 @@ void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) d->overrodeCallee = true; PropertyDescriptor descriptor; - descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Getter | Setter); + descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false); } diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index dcf7a2fae..cb9b12a59 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -197,7 +197,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) if (element.isUndefinedOrNull()) continue; - UString str = element.toString(exec); + UString str = element.toString(exec)->value(exec); strBuffer[k] = str.impl(); totalSize += str.length(); allStrings8Bit = allStrings8Bit && str.is8Bit(); @@ -272,9 +272,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) CallData callData; CallType callType = getCallData(conversionFunction, callData); if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec); + str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec); else - str = element.toString(exec); + str = element.toString(exec)->value(exec); strBuffer.append(str); } } @@ -297,7 +297,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) UString separator; if (!exec->argument(0).isUndefined()) - separator = exec->argument(0).toString(exec); + separator = exec->argument(0).toString(exec)->value(exec); unsigned k = 0; if (isJSArray(thisObj)) { @@ -308,7 +308,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) goto skipFirstLoop; JSValue element = array->getIndex(k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)); + strBuffer.append(element.toString(exec)->value(exec)); k++; } @@ -319,7 +319,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) strBuffer.append(','); JSValue element = array->getIndex(k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)); + strBuffer.append(element.toString(exec)->value(exec)); } } else { for (; k < length; k++) { @@ -328,7 +328,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) strBuffer.append(separator); JSValue element = array->getIndex(k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)); + strBuffer.append(element.toString(exec)->value(exec)); } } } @@ -343,7 +343,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) JSValue element = thisObj->get(exec, k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)); + strBuffer.append(element.toString(exec)->value(exec)); } return JSValue::encode(strBuffer.build(exec)); @@ -429,7 +429,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n)); else { PutPropertySlot slot; - Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)); + Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec)); thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot); } } @@ -571,7 +571,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) l.append(minObj); compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec); } else - compareResult = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1; + compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1; if (compareResult < 0) { themin = j; diff --git a/Source/JavaScriptCore/runtime/CallData.h b/Source/JavaScriptCore/runtime/CallData.h index b138f5484..15a6a0a48 100644 --- a/Source/JavaScriptCore/runtime/CallData.h +++ b/Source/JavaScriptCore/runtime/CallData.h @@ -57,7 +57,7 @@ namespace JSC { } js; }; - JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); + JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h index 9fff64e67..3d556d88c 100644 --- a/Source/JavaScriptCore/runtime/ClassInfo.h +++ b/Source/JavaScriptCore/runtime/ClassInfo.h @@ -88,7 +88,7 @@ namespace JSC { HasInstanceFunctionPtr hasInstance; typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - PutWithAttributesFunctionPtr putWithAttributes; + PutWithAttributesFunctionPtr putDirectVirtual; typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool); DefineOwnPropertyFunctionPtr defineOwnProperty; @@ -135,7 +135,7 @@ struct MemberCheck##member { \ &ClassName::getPropertyNames, \ &ClassName::className, \ &ClassName::hasInstance, \ - &ClassName::putWithAttributes, \ + &ClassName::putDirectVirtual, \ &ClassName::defineOwnProperty, \ &ClassName::getOwnPropertyDescriptor, \ }, \ diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h index ab4de7da8..86c4bd5c2 100644 --- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h +++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h @@ -76,7 +76,7 @@ inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) if (propName.getUInt32(i)) return baseObj->hasProperty(exec, i); - Identifier property(exec, propName.toString(exec)); + Identifier property(exec, propName.toString(exec)->value(exec)); if (exec->globalData().exception) return false; return baseObj->hasProperty(exec, property); diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp index c3d9e6947..98a66589a 100644 --- a/Source/JavaScriptCore/runtime/Completion.cpp +++ b/Source/JavaScriptCore/runtime/Completion.cpp @@ -24,6 +24,7 @@ #include "Completion.h" #include "CallFrame.h" +#include "CodeProfiling.h" #include "JSGlobalObject.h" #include "JSLock.h" #include "Interpreter.h" @@ -55,6 +56,8 @@ JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); + CodeProfiling profile(source); + ProgramExecutable* program = ProgramExecutable::create(exec, source); if (!program) { if (returnedException) diff --git a/Source/JavaScriptCore/runtime/Completion.h b/Source/JavaScriptCore/runtime/Completion.h index c3dbdfc58..3d3b86fe4 100644 --- a/Source/JavaScriptCore/runtime/Completion.h +++ b/Source/JavaScriptCore/runtime/Completion.h @@ -31,8 +31,8 @@ namespace JSC { class ScopeChainNode; class SourceCode; - bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0); - JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0); + JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0); + JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ConstructData.h b/Source/JavaScriptCore/runtime/ConstructData.h index cc8f46977..d7a3c73d3 100644 --- a/Source/JavaScriptCore/runtime/ConstructData.h +++ b/Source/JavaScriptCore/runtime/ConstructData.h @@ -56,7 +56,7 @@ namespace JSC { } js; }; - JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&); + JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 79c5181eb..365172294 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -185,7 +185,7 @@ CallType DateConstructor::getCallData(JSCell*, CallData& callData) static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec) { - return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)))); + return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec)->value(exec)))); } static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*) diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h index 3edfb0970..7c976a514 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.h +++ b/Source/JavaScriptCore/runtime/DateInstance.h @@ -31,9 +31,9 @@ namespace JSC { class DateInstance : public JSWrapperObject { protected: - DateInstance(ExecState*, Structure*); + JS_EXPORT_PRIVATE DateInstance(ExecState*, Structure*); void finishCreation(JSGlobalData&); - void finishCreation(JSGlobalData&, double); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, double); static void destroy(JSCell*); diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp index 96dea01db..922fb0a86 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.cpp +++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp @@ -60,8 +60,10 @@ #include <sys/timeb.h> #endif -#if PLATFORM(MAC) || PLATFORM(IOS) +#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN)) #include <CoreFoundation/CoreFoundation.h> +#elif USE(ICU_UNICODE) +#include <unicode/udat.h> #endif #if OS(WINCE) && !PLATFORM(QT) @@ -128,7 +130,7 @@ namespace JSC { enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime }; -#if PLATFORM(MAC) || PLATFORM(IOS) +#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN)) // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)? // Instead we should consider using this whenever USE(CF) is true. @@ -154,13 +156,13 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil bool useCustomFormat = false; UString customFormatString; - UString arg0String = exec->argument(0).toString(exec); + UString arg0String = exec->argument(0).toString(exec)->value(exec); if (arg0String == "custom" && !exec->argument(1).isUndefined()) { useCustomFormat = true; - customFormatString = exec->argument(1).toString(exec); + customFormatString = exec->argument(1).toString(exec)->value(exec); } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) { dateStyle = styleFromArgString(arg0String, dateStyle); - timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle); + timeStyle = styleFromArgString(exec->argument(1).toString(exec)->value(exec), timeStyle); } else if (format != LocaleTime && !exec->argument(0).isUndefined()) dateStyle = styleFromArgString(arg0String, dateStyle); else if (format != LocaleDate && !exec->argument(0).isUndefined()) @@ -195,7 +197,29 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil return jsNontrivialString(exec, UString(buffer, length)); } -#else // !PLATFORM(MAC) && !PLATFORM(IOS) +#elif USE(ICU_UNICODE) && !UCONFIG_NO_FORMATTING + +static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format) +{ + UDateFormatStyle timeStyle = (format != LocaleDate ? UDAT_LONG : UDAT_NONE); + UDateFormatStyle dateStyle = (format != LocaleTime ? UDAT_LONG : UDAT_NONE); + + UErrorCode status = U_ZERO_ERROR; + UDateFormat* df = udat_open(timeStyle, dateStyle, 0, 0, -1, 0, 0, &status); + if (!df) + return jsEmptyString(exec); + + UChar buffer[128]; + int32_t length; + length = udat_format(df, timeInMilliseconds, buffer, 128, 0, &status); + udat_close(df); + if (status != U_ZERO_ERROR) + return jsEmptyString(exec); + + return jsNontrivialString(exec, UString(buffer, length)); +} + +#else static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp index 24f5da4f2..0947e3c20 100644 --- a/Source/JavaScriptCore/runtime/Error.cpp +++ b/Source/JavaScriptCore/runtime/Error.cpp @@ -37,7 +37,6 @@ namespace JSC { static const char* linePropertyName = "line"; -static const char* sourceIdPropertyName = "sourceId"; static const char* sourceURLPropertyName = "sourceURL"; JSObject* createError(JSGlobalObject* globalObject, const UString& message) @@ -119,15 +118,12 @@ JSObject* createURIError(ExecState* exec, const UString& message) JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source) { - intptr_t sourceID = source.provider()->asID(); const UString& sourceURL = source.provider()->url(); if (line != -1) - error->putWithAttributes(globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete); - if (sourceID != -1) - error->putWithAttributes(globalData, Identifier(globalData, sourceIdPropertyName), jsNumber((double)sourceID), ReadOnly | DontDelete); + error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete); if (!sourceURL.isNull()) - error->putWithAttributes(globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete); + error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete); return error; } @@ -140,7 +136,6 @@ JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceC bool hasErrorInfo(ExecState* exec, JSObject* error) { return error->hasProperty(exec, Identifier(exec, linePropertyName)) - || error->hasProperty(exec, Identifier(exec, sourceIdPropertyName)) || error->hasProperty(exec, Identifier(exec, sourceURLPropertyName)); } diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h index b807d4ab4..88b540a35 100644 --- a/Source/JavaScriptCore/runtime/Error.h +++ b/Source/JavaScriptCore/runtime/Error.h @@ -46,12 +46,12 @@ namespace JSC { JSObject* createTypeError(JSGlobalObject*, const UString&); JSObject* createURIError(JSGlobalObject*, const UString&); // ExecState wrappers. - JSObject* createError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createError(ExecState*, const UString&); JSObject* createEvalError(ExecState*, const UString&); - JSObject* createRangeError(ExecState*, const UString&); - JSObject* createReferenceError(ExecState*, const UString&); - JSObject* createSyntaxError(ExecState*, const UString&); - JSObject* createTypeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createRangeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createReferenceError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createSyntaxError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createTypeError(ExecState*, const UString&); JSObject* createURIError(ExecState*, const UString&); // Methods to add @@ -61,12 +61,12 @@ namespace JSC { JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&); // Methods to throw Errors. - JSValue throwError(ExecState*, JSValue); - JSObject* throwError(ExecState*, JSObject*); + JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue); + JS_EXPORT_PRIVATE JSObject* throwError(ExecState*, JSObject*); // Convenience wrappers, create an throw an exception with a default message. - JSObject* throwTypeError(ExecState*); - JSObject* throwSyntaxError(ExecState*); + JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*); + JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*); // Convenience wrappers, wrap result as an EncodedJSValue. inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); } diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h index 888bfe856..d6fa32f99 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.h +++ b/Source/JavaScriptCore/runtime/ErrorInstance.h @@ -42,14 +42,10 @@ namespace JSC { instance->finishCreation(globalData, message); return instance; } + static ErrorInstance* create(ExecState* exec, Structure* structure, JSValue message) { - if (message.isUndefined()) { - ErrorInstance* instance = new (NotNull, allocateCell<ErrorInstance>(*exec->heap())) ErrorInstance(exec->globalData(), structure); - instance->finishCreation(exec->globalData(), UString()); - return instance; - } - return create(exec->globalData(), structure, message.toString(exec)); + return create(exec->globalData(), structure, message.isUndefined() ? UString() : message.toString(exec)->value(exec)); } bool appendSourceToMessage() { return m_appendSourceToMessage; } diff --git a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp index e1a395c0e..7af294782 100644 --- a/Source/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -101,7 +101,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec) if (name.isUndefined()) nameString = "Error"; else { - nameString = name.toString(exec); + nameString = name.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); } @@ -118,7 +118,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec) if (message.isUndefined()) messageString = ""; else { - messageString = message.toString(exec); + messageString = message.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); } diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp index 05e971f7f..ce63ae9af 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -113,7 +113,7 @@ JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident) JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value) { - UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'"); + UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a valid argument for '", op, "'"); JSObject* exception = createTypeError(exec, errorMessage); ASSERT(exception->isErrorInstance()); static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); @@ -122,7 +122,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value JSObject* createNotAConstructorError(ExecState* exec, JSValue value) { - UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor"); + UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a constructor"); JSObject* exception = createTypeError(exec, errorMessage); ASSERT(exception->isErrorInstance()); static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); @@ -131,7 +131,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value) JSObject* createNotAFunctionError(ExecState* exec, JSValue value) { - UString errorMessage = makeUString("'", value.toString(exec), "' is not a function"); + UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not a function"); JSObject* exception = createTypeError(exec, errorMessage); ASSERT(exception->isErrorInstance()); static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); @@ -140,7 +140,7 @@ JSObject* createNotAFunctionError(ExecState* exec, JSValue value) JSObject* createNotAnObjectError(ExecState* exec, JSValue value) { - UString errorMessage = makeUString("'", value.toString(exec), "' is not an object"); + UString errorMessage = makeUString("'", value.toString(exec)->value(exec), "' is not an object"); JSObject* exception = createTypeError(exec, errorMessage); ASSERT(exception->isErrorInstance()); static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage(); diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.h b/Source/JavaScriptCore/runtime/ExceptionHelpers.h index f71d1a308..7bffd294b 100644 --- a/Source/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.h @@ -33,15 +33,15 @@ namespace JSC { -JSObject* createInterruptedExecutionException(JSGlobalData*); +JS_EXPORT_PRIVATE JSObject* createInterruptedExecutionException(JSGlobalData*); bool isInterruptedExecutionException(JSObject*); bool isInterruptedExecutionException(JSValue); JSObject* createTerminatedExecutionException(JSGlobalData*); bool isTerminatedExecutionException(JSObject*); -bool isTerminatedExecutionException(JSValue); +JS_EXPORT_PRIVATE bool isTerminatedExecutionException(JSValue); -JSObject* createStackOverflowError(ExecState*); +JS_EXPORT_PRIVATE JSObject* createStackOverflowError(ExecState*); JSObject* createStackOverflowError(JSGlobalObject*); JSObject* createOutOfMemoryError(JSGlobalObject*); JSObject* createUndefinedVariableError(ExecState*, const Identifier&); @@ -79,7 +79,7 @@ public: return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } - static JS_EXPORTDATA const ClassInfo s_info; + static const ClassInfo s_info; }; class TerminatedExecutionError : public JSNonFinalObject { diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index a364e84da..c67c54cd2 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -30,6 +30,7 @@ #include "CodeBlock.h" #include "DFGDriver.h" #include "JIT.h" +#include "JITDriver.h" #include "Parser.h" #include "UStringBuilder.h" #include "Vector.h" @@ -130,22 +131,24 @@ void ProgramExecutable::destroy(JSCell* cell) const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) }; -FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext) +FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext) : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) , m_name(name) + , m_inferredName(inferredName) , m_symbolTable(0) { } -FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext) +FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext) : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) , m_name(name) + , m_inferredName(inferredName) , m_symbolTable(0) { } @@ -209,27 +212,8 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope } #if ENABLE(JIT) - if (exec->globalData().canUseJIT()) { - bool dfgCompiled = false; - if (jitType == JITCode::DFGJIT) - dfgCompiled = DFG::tryCompile(exec, m_evalCodeBlock.get(), m_jitCodeForCall); - if (dfgCompiled) - ASSERT(!m_evalCodeBlock->alternative() || !m_evalCodeBlock->alternative()->hasIncomingCalls()); - else { - if (m_evalCodeBlock->alternative()) { - // There is already an alternative piece of code compiled with a different - // JIT, so we can silently fail. - m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative()); - return 0; - } - m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get()); - } -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - m_evalCodeBlock->handleBytecodeDiscardingOpportunity(); -#endif - m_evalCodeBlock->setJITCode(m_jitCodeForCall, MacroAssemblerCodePtr()); - } + if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType)) + return 0; #endif #if ENABLE(JIT) @@ -354,26 +338,8 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc } #if ENABLE(JIT) - if (exec->globalData().canUseJIT()) { - bool dfgCompiled = false; - if (jitType == JITCode::DFGJIT) - dfgCompiled = DFG::tryCompile(exec, m_programCodeBlock.get(), m_jitCodeForCall); - if (dfgCompiled) { - if (m_programCodeBlock->alternative()) - m_programCodeBlock->alternative()->unlinkIncomingCalls(); - } else { - if (m_programCodeBlock->alternative()) { - m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative()); - return 0; - } - m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get()); - } -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - m_programCodeBlock->handleBytecodeDiscardingOpportunity(); -#endif - m_programCodeBlock->setJITCode(m_jitCodeForCall, MacroAssemblerCodePtr()); - } + if (!jitCompileIfAppropriate(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType)) + return 0; #endif #if ENABLE(JIT) @@ -540,29 +506,8 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain m_symbolTable = m_codeBlockForCall->sharedSymbolTable(); #if ENABLE(JIT) - JSGlobalData* globalData = scopeChainNode->globalData; - if (globalData->canUseJIT()) { - bool dfgCompiled = false; - if (jitType == JITCode::DFGJIT) - dfgCompiled = DFG::tryCompileFunction(exec, m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck); - if (dfgCompiled) { - if (m_codeBlockForCall->alternative()) - m_codeBlockForCall->alternative()->unlinkIncomingCalls(); - } else { - if (m_codeBlockForCall->alternative()) { - m_codeBlockForCall = static_pointer_cast<FunctionCodeBlock>(m_codeBlockForCall->releaseAlternative()); - m_symbolTable = m_codeBlockForCall->sharedSymbolTable(); - return 0; - } - m_jitCodeForCall = JIT::compile(globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); - } -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - m_codeBlockForCall->handleBytecodeDiscardingOpportunity(); -#endif - - m_codeBlockForCall->setJITCode(m_jitCodeForCall, m_jitCodeForCallWithArityCheck); - } + if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType)) + return 0; #endif #if ENABLE(JIT) @@ -603,29 +548,8 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable(); #if ENABLE(JIT) - JSGlobalData* globalData = scopeChainNode->globalData; - if (globalData->canUseJIT()) { - bool dfgCompiled = false; - if (jitType == JITCode::DFGJIT) - dfgCompiled = DFG::tryCompileFunction(exec, m_codeBlockForConstruct.get(), m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck); - if (dfgCompiled) { - if (m_codeBlockForConstruct->alternative()) - m_codeBlockForConstruct->alternative()->unlinkIncomingCalls(); - } else { - if (m_codeBlockForConstruct->alternative()) { - m_codeBlockForConstruct = static_pointer_cast<FunctionCodeBlock>(m_codeBlockForConstruct->releaseAlternative()); - m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable(); - return 0; - } - m_jitCodeForConstruct = JIT::compile(globalData, m_codeBlockForConstruct.get(), &m_jitCodeForConstructWithArityCheck); - } -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - m_codeBlockForConstruct->handleBytecodeDiscardingOpportunity(); -#endif - - m_codeBlockForConstruct->setJITCode(m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck); - } + if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType)) + return 0; #endif #if ENABLE(JIT) @@ -738,7 +662,7 @@ FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functio FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); - return FunctionExecutable::create(exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); + return FunctionExecutable::create(exec->globalData(), functionName, functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); } UString FunctionExecutable::paramString() const diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index cc44d61a7..6800b5a82 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -87,7 +87,7 @@ namespace JSC { static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); } - static const ClassInfo s_info; + static JS_EXPORTDATA const ClassInfo s_info; protected: static const unsigned StructureFlags = 0; @@ -456,17 +456,17 @@ namespace JSC { public: typedef ScriptExecutable Base; - static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(ExecState* exec, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext); + FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext); executable->finishCreation(exec->globalData(), name, firstLine, lastLine); exec->globalData().heap.addFinalizer(executable, &finalize); return executable; } - static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const Identifier& inferredName, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext); + FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext); executable->finishCreation(globalData, name, firstLine, lastLine); globalData.heap.addFinalizer(executable, &finalize); return executable; @@ -608,6 +608,7 @@ namespace JSC { } const Identifier& name() { return m_name; } + const Identifier& inferredName() { return m_inferredName; } JSString* nameValue() const { return m_nameValue.get(); } size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'! unsigned capturedVariableCount() const { return m_numCapturedVariables; } @@ -639,8 +640,8 @@ namespace JSC { } private: - FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); - FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); + FunctionExecutable(JSGlobalData&, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); + FunctionExecutable(ExecState*, const Identifier& name, const Identifier& inferredName, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType); JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType); @@ -661,6 +662,7 @@ namespace JSC { OwnPtr<FunctionCodeBlock> m_codeBlockForCall; OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct; Identifier m_name; + Identifier m_inferredName; WriteBarrier<JSString> m_nameValue; SharedSymbolTable* m_symbolTable; }; diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index e08e58c83..956b2161d 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -96,17 +96,17 @@ JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObj if (args.isEmpty()) program = "(function() { \n})"; else if (args.size() == 1) - program = makeUString("(function() { ", args.at(0).toString(exec), "\n})"); + program = makeUString("(function() { ", args.at(0).toString(exec)->value(exec), "\n})"); else { UStringBuilder builder; builder.append("(function("); - builder.append(args.at(0).toString(exec)); + builder.append(args.at(0).toString(exec)->value(exec)); for (size_t i = 1; i < args.size() - 1; i++) { builder.append(","); - builder.append(args.at(i).toString(exec)); + builder.append(args.at(i).toString(exec)->value(exec)); } builder.append(") { "); - builder.append(args.at(args.size() - 1).toString(exec)); + builder.append(args.at(args.size() - 1).toString(exec)->value(exec)); builder.append("\n})"); program = builder.toUString(); } diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h index 7141916cf..31986b70a 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.h +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h @@ -59,7 +59,7 @@ namespace JSC { JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, const WTF::TextPosition&); JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&); - JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&); + JS_EXPORT_PRIVATE JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index 049b7b914..266ddc241 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -207,7 +207,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec) length = targetLength - numBoundArgs; } - Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)); + Identifier name(exec, target.get(exec, exec->propertyNames().name).toString(exec)->value(exec)); return JSValue::encode(JSBoundFunction::create(exec, globalObject, targetObject, exec->argument(0), boundArgs, length, name)); } diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h index 293bf6434..b8caf0198 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.h +++ b/Source/JavaScriptCore/runtime/GetterSetter.h @@ -56,9 +56,9 @@ namespace JSC { static void visitChildren(JSCell*, SlotVisitor&); JSObject* getter() const { return m_getter.get(); } - void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); } + void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.setMayBeNull(globalData, this, getter); } JSObject* setter() const { return m_setter.get(); } - void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); } + void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.setMayBeNull(globalData, this, setter); } static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), &s_info); diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h index 2cc88b256..947c95b33 100644 --- a/Source/JavaScriptCore/runtime/Identifier.h +++ b/Source/JavaScriptCore/runtime/Identifier.h @@ -56,14 +56,14 @@ namespace JSC { static Identifier createLCharFromUChar(JSGlobalData* globalData, const UChar* s, int length) { return Identifier(globalData, add8(globalData, s, length)); } - static Identifier from(ExecState* exec, unsigned y); - static Identifier from(ExecState* exec, int y); + JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, unsigned y); + JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, int y); static Identifier from(ExecState* exec, double y); static Identifier from(JSGlobalData*, unsigned y); static Identifier from(JSGlobalData*, int y); static Identifier from(JSGlobalData*, double y); - static uint32_t toUInt32(const UString&, bool& ok); + JS_EXPORT_PRIVATE static uint32_t toUInt32(const UString&, bool& ok); uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); } unsigned toArrayIndex(bool& ok) const; @@ -84,7 +84,7 @@ namespace JSC { static bool equal(const StringImpl*, const UChar*, unsigned length); static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); } - static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals. + JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals. static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals. private: @@ -119,11 +119,11 @@ namespace JSC { return addSlowCase(globalData, r); } - static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r); - static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r); + JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r); + JS_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r); - static void checkCurrentIdentifierTable(ExecState*); - static void checkCurrentIdentifierTable(JSGlobalData*); + JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(ExecState*); + JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(JSGlobalData*); }; template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(LChar) diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.h b/Source/JavaScriptCore/runtime/InitializeThreading.h index 1a93ccb9b..91301a0d8 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.h +++ b/Source/JavaScriptCore/runtime/InitializeThreading.h @@ -33,7 +33,7 @@ namespace JSC { // This function must be called from the main thread. It is safe to call it repeatedly. // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly. - void initializeThreading(); + JS_EXPORT_PRIVATE void initializeThreading(); } diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h index a038b7ae1..532bd0c8d 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.h +++ b/Source/JavaScriptCore/runtime/InternalFunction.h @@ -37,7 +37,7 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - const UString& name(ExecState*); + JS_EXPORT_PRIVATE const UString& name(ExecState*); const UString displayName(ExecState*); const UString calculatedDisplayName(ExecState*); @@ -49,9 +49,9 @@ namespace JSC { protected: static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags; - InternalFunction(JSGlobalObject*, Structure*); + JS_EXPORT_PRIVATE InternalFunction(JSGlobalObject*, Structure*); - void finishCreation(JSGlobalData&, const Identifier& name); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, const Identifier& name); static CallType getCallData(JSCell*, CallData&); }; diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index 83d1ee493..3e05738eb 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -45,7 +45,7 @@ JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExe : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers()) , m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount())) , m_numCapturedVars(functionExecutable->capturedVariableCount()) - , m_requiresDynamicChecks(functionExecutable->usesEval()) + , m_requiresDynamicChecks(functionExecutable->usesEval() && !functionExecutable->isStrictMode()) , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister()) { } @@ -184,11 +184,11 @@ void JSActivation::put(JSCell* cell, ExecState* exec, const Identifier& property // properties are non-standard extensions that other implementations do not // expose in the activation object. ASSERT(!thisObject->hasGetterSetterProperties()); - thisObject->putDirect(exec->globalData(), propertyName, value, 0, true, slot); + thisObject->putOwnDataProperty(exec->globalData(), propertyName, value, slot); } // FIXME: Make this function honor ReadOnly (const) and DontEnum -void JSActivation::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSActivation::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { JSActivation* thisObject = jsCast<JSActivation*>(object); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); @@ -200,7 +200,7 @@ void JSActivation::putWithAttributes(JSObject* object, ExecState* exec, const Id // properties are non-standard extensions that other implementations do not // expose in the activation object. ASSERT(!thisObject->hasGetterSetterProperties()); - JSObject::putWithAttributes(thisObject, exec, propertyName, value, attributes); + JSObject::putDirectVirtual(thisObject, exec, propertyName, value, attributes); } bool JSActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 2ce053e05..c18492344 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -64,7 +64,7 @@ namespace JSC { static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); - static void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); + static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); static JSObject* toThisObject(JSCell*, ExecState*); diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index b3210083d..c84fb5b10 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -24,6 +24,8 @@ #include "JSArray.h" #include "ArrayPrototype.h" +#include "BumpSpace.h" +#include "BumpSpaceInlineMethods.h" #include "CachedCall.h" #include "Error.h" #include "Executable.h" @@ -130,7 +132,10 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) JSArray::JSArray(JSGlobalData& globalData, Structure* structure) : JSNonFinalObject(globalData, structure) + , m_indexBias(0) , m_storage(0) + , m_sparseValueMap(0) + , m_subclassData(0) { } @@ -142,13 +147,14 @@ void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength) unsigned initialVectorLength = BASE_VECTOR_LEN; unsigned initialStorageSize = storageSize(initialVectorLength); - m_storage = static_cast<ArrayStorage*>(fastMalloc(initialStorageSize)); + void* newStorage = 0; + if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage)) + CRASH(); + + m_storage = static_cast<ArrayStorage*>(newStorage); m_storage->m_allocBase = m_storage; m_storage->m_length = initialLength; - m_indexBias = 0; m_vectorLength = initialVectorLength; - m_storage->m_sparseValueMap = 0; - m_storage->subclassData = 0; m_storage->m_numValuesInVector = 0; #if CHECK_ARRAY_CONSISTENCY m_storage->m_inCompactInitialization = false; @@ -159,8 +165,6 @@ void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength) vector[i].clear(); checkConsistency(); - - Heap::heap(this)->reportExtraMemoryCost(initialStorageSize); } JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsigned initialLength) @@ -175,14 +179,16 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig unsigned initialVectorLength = max(initialLength, BASE_VECTOR_LEN); unsigned initialStorageSize = storageSize(initialVectorLength); - m_storage = static_cast<ArrayStorage*>(fastMalloc(initialStorageSize)); + void* newStorage = 0; + if (!globalData.heap.tryAllocateStorage(initialStorageSize, &newStorage)) + CRASH(); + + m_storage = static_cast<ArrayStorage*>(newStorage); m_storage->m_allocBase = m_storage; m_storage->m_length = 0; - m_indexBias = 0; m_vectorLength = initialVectorLength; - m_storage->m_sparseValueMap = 0; - m_storage->subclassData = 0; m_storage->m_numValuesInVector = initialLength; + #if CHECK_ARRAY_CONSISTENCY m_storage->m_inCompactInitialization = true; #endif @@ -191,26 +197,15 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig for (size_t i = initialLength; i < initialVectorLength; ++i) vector[i].clear(); - Heap::heap(this)->reportExtraMemoryCost(initialStorageSize); return this; } -JSArray::~JSArray() -{ - ASSERT(jsCast<JSArray*>(this)); - - // If we are unable to allocate memory for m_storage then this may be null. - if (!m_storage) - return; - - checkConsistency(DestructorConsistencyCheck); - delete m_storage->m_sparseValueMap; - fastFree(m_storage->m_allocBase); -} - -void JSArray::destroy(JSCell* cell) +// This function can be called multiple times on the same object. +void JSArray::finalize(JSCell* cell) { - jsCast<JSArray*>(cell)->JSArray::~JSArray(); + JSArray* thisObject = jsCast<JSArray*>(cell); + thisObject->checkConsistency(DestructorConsistencyCheck); + thisObject->deallocateSparseMap(); } inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(JSArray* array, unsigned i) @@ -229,7 +224,7 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i { SparseArrayEntry& entry = add(array, i).first->second; - if (!(entry.attributes & (Getter | Setter))) { + if (!(entry.attributes & Accessor)) { if (entry.attributes & ReadOnly) { // FIXME: should throw if being called from strict mode. // throwTypeError(exec, StrictModeReadonlyPropertyWriteError); @@ -310,13 +305,27 @@ inline void SparseArrayValueMap::visitChildren(SlotVisitor& visitor) visitor.append(&it->second); } -void JSArray::enterSparseMode(JSGlobalData& globalData) +void JSArray::allocateSparseMap(JSGlobalData& globalData) +{ + m_sparseValueMap = new SparseArrayValueMap; + globalData.heap.addFinalizer(this, finalize); +} + +void JSArray::deallocateSparseMap() +{ + delete m_sparseValueMap; + m_sparseValueMap = 0; +} + +void JSArray::enterDictionaryMode(JSGlobalData& globalData) { ArrayStorage* storage = m_storage; - SparseArrayValueMap* map = storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; - if (!map) - map = storage->m_sparseValueMap = new SparseArrayValueMap; + if (!map) { + allocateSparseMap(globalData); + map = m_sparseValueMap; + } if (map->sparseMode()) return; @@ -332,10 +341,13 @@ void JSArray::enterSparseMode(JSGlobalData& globalData) map->add(this, i).first->second.set(globalData, this, value); } - ArrayStorage* newStorage = static_cast<ArrayStorage*>(fastMalloc(storageSize(0))); + void* newRawStorage = 0; + if (!globalData.heap.tryAllocateStorage(storageSize(0), &newRawStorage)) + CRASH(); + + ArrayStorage* newStorage = static_cast<ArrayStorage*>(newRawStorage); memcpy(newStorage, m_storage, storageSize(0)); newStorage->m_allocBase = newStorage; - fastFree(m_storage); m_storage = newStorage; m_indexBias = 0; m_vectorLength = 0; @@ -348,25 +360,21 @@ void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, Prope entryInMap->set(exec->globalData(), this, descriptor.value()); else if (oldDescriptor.isAccessorDescriptor()) entryInMap->set(exec->globalData(), this, jsUndefined()); - entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~(Getter | Setter); + entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~Accessor; return; } if (descriptor.isAccessorDescriptor()) { JSObject* getter = 0; - if (descriptor.getter() && descriptor.getter().isObject()) - getter = asObject(descriptor.getter()); - if (!getter && oldDescriptor.isAccessorDescriptor()) { - if (oldDescriptor.getter() && oldDescriptor.getter().isObject()) - getter = asObject(oldDescriptor.getter()); - } + if (descriptor.getterPresent()) + getter = descriptor.getterObject(); + else if (oldDescriptor.isAccessorDescriptor()) + getter = oldDescriptor.getterObject(); JSObject* setter = 0; - if (descriptor.setter() && descriptor.setter().isObject()) - setter = asObject(descriptor.setter()); - if (!setter && oldDescriptor.isAccessorDescriptor()) { - if (oldDescriptor.setter() && oldDescriptor.setter().isObject()) - setter = asObject(oldDescriptor.setter()); - } + if (descriptor.setterPresent()) + setter = descriptor.setterObject(); + else if (oldDescriptor.isAccessorDescriptor()) + setter = oldDescriptor.setterObject(); GetterSetter* accessor = GetterSetter::create(exec); if (getter) @@ -406,10 +414,10 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property return true; } - enterSparseMode(exec->globalData()); + enterDictionaryMode(exec->globalData()); } - SparseArrayValueMap* map = m_storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; ASSERT(map); // 1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P. @@ -491,6 +499,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property } // 10.b. else, the [[Configurable]] field of current is true, so any change is acceptable. } else { + ASSERT(current.isAccessorDescriptor() && current.getterPresent() && current.setterPresent()); // 11. Else, IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc) are both true so, if the [[Configurable]] field of current is false, then if (!current.configurable()) { // 11.i. Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false. @@ -515,9 +524,9 @@ void JSArray::setLengthWritable(ExecState* exec, bool writable) if (!isLengthWritable() || writable) return; - enterSparseMode(exec->globalData()); + enterDictionaryMode(exec->globalData()); - SparseArrayValueMap* map = m_storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; ASSERT(map); map->setLengthIsReadOnly(); } @@ -531,10 +540,10 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif if (propertyName == exec->propertyNames().length) { // All paths through length definition call the default [[DefineOwnProperty]], hence: // from ES5.1 8.12.9 7.a. - if (descriptor.configurable()) + if (descriptor.configurablePresent() && descriptor.configurable()) return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property."); // from ES5.1 8.12.9 7.b. - if (descriptor.enumerable()) + if (descriptor.enumerablePresent() && descriptor.enumerable()) return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property."); // a. If the [[Value]] field of Desc is absent, then @@ -542,11 +551,12 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif if (descriptor.isAccessorDescriptor()) return reject(exec, throwException, "Attempting to change access mechanism for an unconfigurable property."); // from ES5.1 8.12.9 10.a. - if (!array->isLengthWritable() && descriptor.writable()) + if (!array->isLengthWritable() && descriptor.writablePresent() && descriptor.writable()) return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property."); // This descriptor is either just making length read-only, or changing nothing! if (!descriptor.value()) { - array->setLengthWritable(exec, descriptor.writable()); + if (descriptor.writablePresent()) + array->setLengthWritable(exec, descriptor.writable()); return true; } @@ -561,7 +571,8 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif // Based on SameValue check in 8.12.9, this is always okay. if (newLen == array->length()) { - array->setLengthWritable(exec, descriptor.writable()); + if (descriptor.writablePresent()) + array->setLengthWritable(exec, descriptor.writable()); return true; } @@ -588,13 +599,17 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identif // 2. If newWritable is false, set newLenDesc.[[Writable] to false. // 3. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and false as arguments. // 4. Reject. - array->setLengthWritable(exec, descriptor.writable()); + if (descriptor.writablePresent()) + array->setLengthWritable(exec, descriptor.writable()); return false; } // m. If newWritable is false, then - // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always return true. - array->setLengthWritable(exec, descriptor.writable()); + // i. Call the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", + // Property Descriptor{[[Writable]]: false}, and false as arguments. This call will always + // return true. + if (descriptor.writablePresent()) + array->setLengthWritable(exec, descriptor.writable()); // n. Return true. return true; } @@ -623,7 +638,7 @@ bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned { JSArray* thisObject = jsCast<JSArray*>(cell); ArrayStorage* storage = thisObject->m_storage; - + if (i >= storage->m_length) { if (i > MAX_ARRAY_INDEX) return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, Identifier::from(exec, i), slot); @@ -636,7 +651,7 @@ bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned slot.setValue(value); return true; } - } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->notFound()) { it->second.get(slot); @@ -684,7 +699,7 @@ bool JSArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const descriptor.setDescriptor(value.get(), 0); return true; } - } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->notFound()) { it->second.get(descriptor); @@ -765,7 +780,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne ASSERT(i <= MAX_ARRAY_INDEX); ArrayStorage* storage = m_storage; - SparseArrayValueMap* map = storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; // First, handle cases where we don't currently have a sparse map. if (LIKELY(!map)) { @@ -774,7 +789,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne storage->m_length = i + 1; // Check that it is sensible to still be using a vector, and then try to grow the vector. - if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(i + 1))) { + if (LIKELY((isDenseEnoughForVector(i, storage->m_numValuesInVector)) && increaseVectorLength(globalData, i + 1))) { // success! - reread m_storage since it has likely been reallocated, and store to the vector. storage = m_storage; storage->m_vector[i].set(globalData, this, value); @@ -782,8 +797,8 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne return; } // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value. - map = new SparseArrayValueMap; - storage->m_sparseValueMap = map; + allocateSparseMap(exec->globalData()); + map = m_sparseValueMap; map->put(exec, this, i, value); return; } @@ -803,7 +818,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne // We are currently using a map - check whether we still want to be doing so. // We will continue to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails. unsigned numValuesInArray = storage->m_numValuesInVector + map->size(); - if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(length)) { + if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->globalData(), length)) { map->put(exec, this, i, value); return; } @@ -817,8 +832,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne SparseArrayValueMap::const_iterator end = map->end(); for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) vector[it->first].set(globalData, this, it->second.getNonSparseMode()); - delete map; - storage->m_sparseValueMap = 0; + deallocateSparseMap(); // Store the new property into the vector. WriteBarrier<Unknown>& valueSlot = vector[i]; @@ -857,7 +871,7 @@ bool JSArray::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) valueSlot.clear(); --storage->m_numValuesInVector; } - } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + } else if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) { SparseArrayValueMap::iterator it = map->find(i); if (it != map->notFound()) { if (it->second.attributes & DontDelete) @@ -892,7 +906,7 @@ void JSArray::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNam propertyNames.add(Identifier::from(exec, i)); } - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) { Vector<unsigned> keys; keys.reserveCapacity(map->size()); @@ -940,7 +954,7 @@ ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength) return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH); } -bool JSArray::increaseVectorLength(unsigned newLength) +bool JSArray::increaseVectorLength(JSGlobalData& globalData, unsigned newLength) { // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map // to the vector. Callers have to account for that, because they can do it more efficiently. @@ -952,15 +966,16 @@ bool JSArray::increaseVectorLength(unsigned newLength) unsigned vectorLength = m_vectorLength; ASSERT(newLength > vectorLength); unsigned newVectorLength = getNewVectorLength(newLength); - void* baseStorage = storage->m_allocBase; // Fast case - there is no precapacity. In these cases a realloc makes sense. if (LIKELY(!m_indexBias)) { - if (!tryFastRealloc(baseStorage, storageSize(newVectorLength)).getValue(baseStorage)) + void* newStorage = storage->m_allocBase; + if (!globalData.heap.tryReallocateStorage(&newStorage, storageSize(vectorLength), storageSize(newVectorLength))) return false; - storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(baseStorage); - m_storage->m_allocBase = baseStorage; + storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newStorage)); + m_storage->m_allocBase = newStorage; + ASSERT(m_storage->m_allocBase); WriteBarrier<Unknown>* vector = storage->m_vector; for (unsigned i = vectorLength; i < newVectorLength; ++i) @@ -968,7 +983,6 @@ bool JSArray::increaseVectorLength(unsigned newLength) m_vectorLength = newVectorLength; - Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); return true; } @@ -976,15 +990,11 @@ bool JSArray::increaseVectorLength(unsigned newLength) unsigned newIndexBias = min(m_indexBias >> 1, MAX_STORAGE_VECTOR_LENGTH - newVectorLength); // Calculate new stoarge capcity, allowing room for the pre-capacity. unsigned newStorageCapacity = newVectorLength + newIndexBias; - void* newAllocBase; - if (!tryFastMalloc(storageSize(newStorageCapacity)).getValue(newAllocBase)) + void* newAllocBase = 0; + if (!globalData.heap.tryAllocateStorage(storageSize(newStorageCapacity), &newAllocBase)) return false; // The sum of m_vectorLength and m_indexBias will never exceed MAX_STORAGE_VECTOR_LENGTH. ASSERT(m_vectorLength <= MAX_STORAGE_VECTOR_LENGTH && (MAX_STORAGE_VECTOR_LENGTH - m_vectorLength) >= m_indexBias); - unsigned currentCapacity = m_vectorLength + m_indexBias; - // Currently there is no way to report to the heap that the extra capacity is shrinking! - if (newStorageCapacity > currentCapacity) - Heap::heap(this)->reportExtraMemoryCost((newStorageCapacity - currentCapacity) * sizeof(WriteBarrier<Unknown>)); m_vectorLength = newVectorLength; m_indexBias = newIndexBias; @@ -996,14 +1006,13 @@ bool JSArray::increaseVectorLength(unsigned newLength) m_storage->m_vector[i].clear(); // Free the old allocation, update m_allocBase. - fastFree(m_storage->m_allocBase); m_storage->m_allocBase = newAllocBase; return true; } // This method makes room in the vector, but leaves the new space uncleared. -bool JSArray::unshiftCountSlowCase(unsigned count) +bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, unsigned count) { // If not, we should have handled this on the fast path. ASSERT(count > m_indexBias); @@ -1034,19 +1043,16 @@ bool JSArray::unshiftCountSlowCase(unsigned count) // Step 2: // We're either going to choose to allocate a new ArrayStorage, or we're going to reuse the existing on. - void* newAllocBase; + void* newAllocBase = 0; unsigned newStorageCapacity; // If the current storage array is sufficiently large (but not too large!) then just keep using it. if (currentCapacity > desiredCapacity && isDenseEnoughForVector(currentCapacity, requiredVectorLength)) { newAllocBase = storage->m_allocBase; newStorageCapacity = currentCapacity; } else { - if (!tryFastMalloc(storageSize(desiredCapacity)).getValue(newAllocBase)) + if (!globalData.heap.tryAllocateStorage(storageSize(desiredCapacity), &newAllocBase)) return false; newStorageCapacity = desiredCapacity; - // Currently there is no way to report to the heap that the extra capacity is shrinking! - if (desiredCapacity > currentCapacity) - Heap::heap(this)->reportExtraMemoryCost((desiredCapacity - currentCapacity) * sizeof(WriteBarrier<Unknown>)); } // Step 3: @@ -1079,7 +1085,6 @@ bool JSArray::unshiftCountSlowCase(unsigned count) // Are we copying into a new allocation? if (newAllocBase != m_storage->m_allocBase) { // Free the old allocation, update m_allocBase. - fastFree(m_storage->m_allocBase); m_storage->m_allocBase = newAllocBase; // We need to clear any entries in the vector beyond length. We only need to @@ -1101,9 +1106,9 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException unsigned length = storage->m_length; // If the length is read only then we enter sparse mode, so should enter the following 'if'. - ASSERT(isLengthWritable() || storage->m_sparseValueMap); + ASSERT(isLengthWritable() || m_sparseValueMap); - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + if (SparseArrayValueMap* map = m_sparseValueMap) { // Fail if the length is not writable. if (map->lengthIsReadOnly()) return reject(exec, throwException, StrictModeReadonlyPropertyWriteError); @@ -1138,10 +1143,8 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException } else { for (unsigned i = 0; i < keys.size(); ++i) map->remove(keys[i]); - if (map->isEmpty()) { - delete map; - storage->m_sparseValueMap = 0; - } + if (map->isEmpty()) + deallocateSparseMap(); } } } @@ -1190,7 +1193,7 @@ JSValue JSArray::pop(ExecState* exec) result = jsUndefined(); } else { result = jsUndefined(); - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + if (SparseArrayValueMap* map = m_sparseValueMap) { SparseArrayValueMap::iterator it = map->find(length); if (it != map->notFound()) { unsigned attributes = it->second.attributes; @@ -1206,10 +1209,8 @@ JSValue JSArray::pop(ExecState* exec) } map->remove(it); - if (map->isEmpty() && !map->sparseMode()) { - delete map; - storage->m_sparseValueMap = 0; - } + if (map->isEmpty() && !map->sparseMode()) + deallocateSparseMap(); } } } @@ -1331,7 +1332,7 @@ void JSArray::unshiftCount(ExecState* exec, unsigned count) memmove(newBaseStorage, storage, storageSize(0)); m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage); m_vectorLength += count; - } else if (!unshiftCountSlowCase(count)) { + } else if (!unshiftCountSlowCase(exec->globalData(), count)) { throwOutOfMemoryError(exec); return; } @@ -1349,13 +1350,21 @@ void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor) ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); JSNonFinalObject::visitChildren(thisObject, visitor); - - ArrayStorage* storage = thisObject->m_storage; - unsigned usedVectorLength = std::min(storage->m_length, thisObject->m_vectorLength); - visitor.appendValues(storage->m_vector, usedVectorLength); + if (thisObject->m_storage) { + ArrayStorage* storage = thisObject->m_storage; + void* baseStorage = storage->m_allocBase; + + visitor.copyAndAppend(reinterpret_cast<void**>(&baseStorage), storageSize(thisObject->m_vectorLength + thisObject->m_indexBias), storage->m_vector->slot(), thisObject->m_vectorLength); + + if (baseStorage != thisObject->m_storage->m_allocBase) { + thisObject->m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(baseStorage) + sizeof(JSValue) * thisObject->m_indexBias); + thisObject->m_storage->m_allocBase = baseStorage; + ASSERT(thisObject->m_storage->m_allocBase); + } + } - if (SparseArrayValueMap* map = storage->m_sparseValueMap) + if (SparseArrayValueMap* map = thisObject->m_sparseValueMap) map->visitChildren(visitor); } @@ -1379,8 +1388,8 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal ArrayStorage* storage = m_storage; - unsigned lengthNotIncludingUndefined = compactForSorting(); - if (storage->m_sparseValueMap) { + unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData()); + if (m_sparseValueMap) { throwOutOfMemoryError(exec); return; } @@ -1412,10 +1421,8 @@ void JSArray::sort(ExecState* exec) { ASSERT(!inSparseMode()); - ArrayStorage* storage = m_storage; - - unsigned lengthNotIncludingUndefined = compactForSorting(); - if (storage->m_sparseValueMap) { + unsigned lengthNotIncludingUndefined = compactForSorting(exec->globalData()); + if (m_sparseValueMap) { throwOutOfMemoryError(exec); return; } @@ -1437,7 +1444,7 @@ void JSArray::sort(ExecState* exec) Heap::heap(this)->pushTempSortVector(&values); for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { - JSValue value = storage->m_vector[i].get(); + JSValue value = m_storage->m_vector[i].get(); ASSERT(!value.isUndefined()); values[i].first = value; } @@ -1446,7 +1453,7 @@ void JSArray::sort(ExecState* exec) // a toString call raises an exception. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - values[i].second = values[i].first.toString(exec); + values[i].second = values[i].first.toString(exec)->value(exec); if (exec->hadException()) { Heap::heap(this)->popTempSortVector(&values); @@ -1467,13 +1474,13 @@ void JSArray::sort(ExecState* exec) // If the toString function changed the length of the array or vector storage, // increase the length to handle the orignal number of actual values. if (m_vectorLength < lengthNotIncludingUndefined) - increaseVectorLength(lengthNotIncludingUndefined); - if (storage->m_length < lengthNotIncludingUndefined) - storage->m_length = lengthNotIncludingUndefined; + increaseVectorLength(exec->globalData(), lengthNotIncludingUndefined); + if (m_storage->m_length < lengthNotIncludingUndefined) + m_storage->m_length = lengthNotIncludingUndefined; JSGlobalData& globalData = exec->globalData(); for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - storage->m_vector[i].set(globalData, this, values[i].first); + m_storage->m_vector[i].set(globalData, this, values[i].first); Heap::heap(this)->popTempSortVector(&values); @@ -1563,18 +1570,16 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, checkConsistency(); - ArrayStorage* storage = m_storage; - // FIXME: This ignores exceptions raised in the compare function or in toNumber. // The maximum tree depth is compiled in - but the caller is clearly up to no good // if a larger array is passed. - ASSERT(storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max())); - if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max())) + ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max())); + if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max())) return; - unsigned usedVectorLength = min(storage->m_length, m_vectorLength); - unsigned nodeCount = usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0); + unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength); + unsigned nodeCount = usedVectorLength + (m_sparseValueMap ? m_sparseValueMap->size() : 0); if (!nodeCount) return; @@ -1602,14 +1607,14 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree. for (; numDefined < usedVectorLength; ++numDefined) { - JSValue v = storage->m_vector[numDefined].get(); + JSValue v = m_storage->m_vector[numDefined].get(); if (!v || v.isUndefined()) break; tree.abstractor().m_nodes[numDefined].value = v; tree.insert(numDefined); } for (unsigned i = numDefined; i < usedVectorLength; ++i) { - JSValue v = storage->m_vector[i].get(); + JSValue v = m_storage->m_vector[i].get(); if (v) { if (v.isUndefined()) ++numUndefined; @@ -1623,17 +1628,15 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, unsigned newUsedVectorLength = numDefined + numUndefined; - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + if (SparseArrayValueMap* map = m_sparseValueMap) { newUsedVectorLength += map->size(); if (newUsedVectorLength > m_vectorLength) { // Check that it is possible to allocate an array large enough to hold all the entries. - if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) { + if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(exec->globalData(), newUsedVectorLength)) { throwOutOfMemoryError(exec); return; } } - - storage = m_storage; SparseArrayValueMap::const_iterator end = map->end(); for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) { @@ -1642,8 +1645,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, ++numDefined; } - delete map; - storage->m_sparseValueMap = 0; + deallocateSparseMap(); } ASSERT(tree.abstractor().m_nodes.size() >= numDefined); @@ -1656,19 +1658,19 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, iter.start_iter_least(tree); JSGlobalData& globalData = exec->globalData(); for (unsigned i = 0; i < numDefined; ++i) { - storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); + m_storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value); ++iter; } // Put undefined values back in. for (unsigned i = numDefined; i < newUsedVectorLength; ++i) - storage->m_vector[i].setUndefined(); + m_storage->m_vector[i].setUndefined(); // Ensure that unused values in the vector are zeroed out. for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i) - storage->m_vector[i].clear(); + m_storage->m_vector[i].clear(); - storage->m_numValuesInVector = newUsedVectorLength; + m_storage->m_numValuesInVector = newUsedVectorLength; checkConsistency(SortConsistencyCheck); } @@ -1709,7 +1711,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le callFrame->setArgument(i, get(exec, i)); } -unsigned JSArray::compactForSorting() +unsigned JSArray::compactForSorting(JSGlobalData& globalData) { ASSERT(!inSparseMode()); @@ -1740,12 +1742,12 @@ unsigned JSArray::compactForSorting() unsigned newUsedVectorLength = numDefined + numUndefined; - if (SparseArrayValueMap* map = storage->m_sparseValueMap) { + if (SparseArrayValueMap* map = m_sparseValueMap) { newUsedVectorLength += map->size(); if (newUsedVectorLength > m_vectorLength) { // Check that it is possible to allocate an array large enough to hold all the entries - if not, // exception is thrown by caller. - if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength)) + if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(globalData, newUsedVectorLength)) return 0; storage = m_storage; @@ -1755,8 +1757,7 @@ unsigned JSArray::compactForSorting() for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode()); - delete map; - storage->m_sparseValueMap = 0; + deallocateSparseMap(); } for (unsigned i = numDefined; i < newUsedVectorLength; ++i) @@ -1773,12 +1774,12 @@ unsigned JSArray::compactForSorting() void* JSArray::subclassData() const { - return m_storage->subclassData; + return m_subclassData; } void JSArray::setSubclassData(void* d) { - m_storage->subclassData = d; + m_subclassData = d; } #if CHECK_ARRAY_CONSISTENCY @@ -1791,7 +1792,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) ASSERT(storage); if (type == SortConsistencyCheck) - ASSERT(!storage->m_sparseValueMap); + ASSERT(!m_sparseValueMap); unsigned numValuesInVector = 0; for (unsigned i = 0; i < m_vectorLength; ++i) { @@ -1808,9 +1809,9 @@ void JSArray::checkConsistency(ConsistencyCheckType type) ASSERT(numValuesInVector == storage->m_numValuesInVector); ASSERT(numValuesInVector <= storage->m_length); - if (storage->m_sparseValueMap) { - SparseArrayValueMap::iterator end = storage->m_sparseValueMap->end(); - for (SparseArrayValueMap::iterator it = storage->m_sparseValueMap->begin(); it != end; ++it) { + if (m_sparseValueMap) { + SparseArrayValueMap::iterator end = m_sparseValueMap->end(); + for (SparseArrayValueMap::iterator it = m_sparseValueMap->begin(); it != end; ++it) { unsigned index = it->first; ASSERT(index < storage->m_length); ASSERT(index >= storage->m_vectorLength); diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index 871cfc882..a3354c602 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -114,8 +114,6 @@ namespace JSC { struct ArrayStorage { unsigned m_length; // The "length" property on the array unsigned m_numValuesInVector; - SparseArrayValueMap* m_sparseValueMap; - void* subclassData; // A JSArray subclass can use this to fill the vector lazily. void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector. #if CHECK_ARRAY_CONSISTENCY bool m_inCompactInitialization; @@ -127,16 +125,15 @@ namespace JSC { friend class Walker; protected: - explicit JSArray(JSGlobalData&, Structure*); + JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*); - void finishCreation(JSGlobalData&, unsigned initialLength = 0); - JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, unsigned initialLength = 0); + JS_EXPORT_PRIVATE JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength); public: typedef JSNonFinalObject Base; - ~JSArray(); - static void destroy(JSCell*); + static void finalize(JSCell*); static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0) { @@ -156,10 +153,10 @@ namespace JSC { return array->tryFinishCreationUninitialized(globalData, initialLength); } - static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException); static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); @@ -232,7 +229,7 @@ namespace JSC { bool inSparseMode() { - SparseArrayValueMap* map = m_storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; return map && map->sparseMode(); } @@ -254,7 +251,7 @@ namespace JSC { return OBJECT_OFFSETOF(JSArray, m_vectorLength); } - static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; @@ -264,29 +261,31 @@ namespace JSC { static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - void* subclassData() const; - void setSubclassData(void*); + JS_EXPORT_PRIVATE void* subclassData() const; + JS_EXPORT_PRIVATE void setSubclassData(void*); private: bool isLengthWritable() { - SparseArrayValueMap* map = m_storage->m_sparseValueMap; + SparseArrayValueMap* map = m_sparseValueMap; return !map || !map->lengthIsReadOnly(); } void setLengthWritable(ExecState*, bool writable); void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old); bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException); - void enterSparseMode(JSGlobalData&); + void enterDictionaryMode(JSGlobalData&); + void allocateSparseMap(JSGlobalData&); + void deallocateSparseMap(); bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue); unsigned getNewVectorLength(unsigned desiredLength); - bool increaseVectorLength(unsigned newLength); - bool unshiftCountSlowCase(unsigned count); + bool increaseVectorLength(JSGlobalData&, unsigned newLength); + bool unshiftCountSlowCase(JSGlobalData&, unsigned count); - unsigned compactForSorting(); + unsigned compactForSorting(JSGlobalData&); enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck }; void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck); @@ -294,6 +293,10 @@ namespace JSC { unsigned m_vectorLength; // The valid length of m_vector unsigned m_indexBias; // The number of JSValue sized blocks before ArrayStorage. ArrayStorage *m_storage; + + // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell? + SparseArrayValueMap* m_sparseValueMap; + void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily. }; JSArray* asArray(JSValue); diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp index 549b6034f..88260ea27 100644 --- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp @@ -111,8 +111,8 @@ void JSBoundFunction::finishCreation(ExecState* exec, NativeExecutable* executab Base::finishCreation(exec, executable, length, name); ASSERT(inherits(&s_info)); - initializeGetterSetterProperty(exec, exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); - initializeGetterSetterProperty(exec, exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); + initializeGetterSetterProperty(exec, exec->propertyNames().arguments, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); + initializeGetterSetterProperty(exec, exec->propertyNames().caller, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); } void JSBoundFunction::visitChildren(JSCell* cell, SlotVisitor& visitor) diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.h b/Source/JavaScriptCore/runtime/JSBoundFunction.h index c60d7db01..e54d45883 100644 --- a/Source/JavaScriptCore/runtime/JSBoundFunction.h +++ b/Source/JavaScriptCore/runtime/JSBoundFunction.h @@ -51,7 +51,7 @@ public: return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info); } - static JS_EXPORTDATA const ClassInfo s_info; + static const ClassInfo s_info; protected: const static unsigned StructureFlags = OverridesHasInstance | OverridesVisitChildren | Base::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h index 754774d3e..d1f4ad630 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ b/Source/JavaScriptCore/runtime/JSByteArray.h @@ -76,7 +76,7 @@ namespace JSC { } private: - JSByteArray(ExecState*, Structure*, ByteArray* storage); + JS_EXPORT_PRIVATE JSByteArray(ExecState*, Structure*, ByteArray* storage); public: static JSByteArray* create(ExecState* exec, Structure* structure, ByteArray* storage) @@ -86,15 +86,15 @@ namespace JSC { return array; } - static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info); + JS_EXPORT_PRIVATE static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info); - static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); - static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); - static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue); + JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); + JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue); - static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode); static JS_EXPORTDATA const ClassInfo s_info; @@ -103,7 +103,7 @@ namespace JSC { WTF::ByteArray* storage() const { return m_storage.get(); } ~JSByteArray(); - static void destroy(JSCell*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); static size_t offsetOfStorage() { return OBJECT_OFFSETOF(JSByteArray, m_storage); } diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index 065fd13ea..9dcd6364b 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -145,13 +145,6 @@ double JSCell::toNumber(ExecState* exec) const return static_cast<const JSObject*>(this)->toNumber(exec); } -UString JSCell::toString(ExecState* exec) const -{ - if (isString()) - return static_cast<const JSString*>(this)->toString(exec); - return static_cast<const JSObject*>(this)->toString(exec); -} - JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const { if (isString()) @@ -203,7 +196,7 @@ bool JSCell::hasInstance(JSObject*, ExecState*, JSValue, JSValue) return false; } -void JSCell::putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned) +void JSCell::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned) { ASSERT_NOT_REACHED(); } diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 47e336a86..a36bb7d58 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -51,6 +51,7 @@ namespace JSC { TypedArrayInt16, TypedArrayInt32, TypedArrayUint8, + TypedArrayUint8Clamped, TypedArrayUint16, TypedArrayUint32, TypedArrayFloat32, @@ -67,7 +68,7 @@ namespace JSC { protected: JSCell(JSGlobalData&, Structure*); - static void destroy(JSCell*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); public: // Querying the type. @@ -82,21 +83,20 @@ namespace JSC { void clearStructure() { m_structure.clear(); } // Extracting the value. - bool getString(ExecState* exec, UString&) const; - UString getString(ExecState* exec) const; // null string if not a string - JSObject* getObject(); // NULL if not an object + JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const; + JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string + JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object const JSObject* getObject() const; // NULL if not an object - static CallType getCallData(JSCell*, CallData&); - static ConstructType getConstructData(JSCell*, ConstructData&); + JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&); + JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&); // Basic conversions. - JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; bool toBoolean(ExecState*) const; - double toNumber(ExecState*) const; - UString toString(ExecState*) const; - JSObject* toObject(ExecState*, JSGlobalObject*) const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; static void visitChildren(JSCell*, SlotVisitor&); @@ -159,7 +159,7 @@ namespace JSC { static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); static UString className(const JSObject*); static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); - static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 65470a53f..15718a176 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -136,7 +136,11 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec) if (!explicitName.isEmpty()) return explicitName; - return name(exec); + const UString actualName = name(exec); + if (!actualName.isEmpty() || isHostFunction()) + return actualName; + + return jsExecutable()->inferredName().ustring(); } const SourceCode* JSFunction::sourceCode() const @@ -175,14 +179,14 @@ JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Ide { JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); - return exec->interpreter()->retrieveArguments(exec, thisObj); + return exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObj); } JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&) { JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); - return exec->interpreter()->retrieveCaller(exec, thisObj); + return exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj); } JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&) @@ -204,8 +208,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif if (!location) { JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure()); prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum); - PutPropertySlot slot; - thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum, false, slot); + thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum); location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype); } @@ -216,7 +219,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); if (!result) { - thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); + thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); ASSERT(result); } @@ -235,7 +238,7 @@ bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identif if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); if (!result) { - thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); + thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); ASSERT(result); } @@ -264,13 +267,13 @@ bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, con if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); if (!result) { - thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); + thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); ASSERT(result); } return result; } - descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, thisObject), ReadOnly | DontEnum | DontDelete); + descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete); return true; } @@ -283,13 +286,13 @@ bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, con if (thisObject->jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); if (!result) { - thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); + thisObject->initializeGetterSetterProperty(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); ASSERT(result); } return result; } - descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, thisObject), ReadOnly | DontEnum | DontDelete); + descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete); return true; } @@ -358,5 +361,15 @@ ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& construc constructData.js.scopeChain = thisObject->scope(); return ConstructTypeJS; } + + +UString getCalculatedDisplayName(CallFrame* callFrame, JSObject* object) +{ + if (JSFunction* function = jsDynamicCast<JSFunction*>(object)) + return function->calculatedDisplayName(callFrame); + if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object)) + return function->calculatedDisplayName(callFrame); + return UString(); +} } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 5118f8b10..a12b079d7 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -40,8 +40,10 @@ namespace JSC { class JITCompiler; } - EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); + JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); + JS_EXPORT_PRIVATE UString getCalculatedDisplayName(CallFrame*, JSObject*); + class JSFunction : public JSNonFinalObject { friend class JIT; friend class DFG::SpeculativeJIT; @@ -51,7 +53,7 @@ namespace JSC { public: typedef JSNonFinalObject Base; - static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor); + JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor); static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeExecutable* nativeExecutable); static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain) @@ -64,8 +66,8 @@ namespace JSC { static void destroy(JSCell*); - const UString& name(ExecState*); - const UString displayName(ExecState*); + JS_EXPORT_PRIVATE const UString& name(ExecState*); + JS_EXPORT_PRIVATE const UString displayName(ExecState*); const UString calculatedDisplayName(ExecState*); ScopeChainNode* scope() @@ -94,7 +96,7 @@ namespace JSC { inline bool isHostFunction() const; FunctionExecutable* jsExecutable() const; - const SourceCode* sourceCode() const; + JS_EXPORT_PRIVATE const SourceCode* sourceCode() const; static JS_EXPORTDATA const ClassInfo s_info; @@ -123,7 +125,7 @@ namespace JSC { protected: const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; - JSFunction(ExecState*, JSGlobalObject*, Structure*); + JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*); JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name); @@ -140,7 +142,7 @@ namespace JSC { static void visitChildren(JSCell*, SlotVisitor&); private: - bool isHostFunctionNonInline() const; + JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const; static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); static JSValue callerGetter(ExecState*, JSValue, const Identifier&); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index dab3f24ba..bbe520a1e 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -101,7 +101,7 @@ extern const HashTable globalObjectTable; extern const HashTable mathTable; extern const HashTable numberConstructorTable; extern const HashTable numberPrototypeTable; -extern const HashTable objectConstructorTable; +JS_EXPORTDATA extern const HashTable objectConstructorTable; extern const HashTable objectPrototypeTable; extern const HashTable regExpTable; extern const HashTable regExpConstructorTable; @@ -162,8 +162,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread #endif { interpreter = new Interpreter; - if (globalDataType == Default) - m_stack = wtfThreadData().stack(); // Need to be careful to keep everything consistent here IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index a6ad8a747..92817f2a2 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -134,18 +134,18 @@ namespace JSC { enum GlobalDataType { Default, APIContextGroup, APIShared }; struct ClientData { - virtual ~ClientData() = 0; + JS_EXPORT_PRIVATE virtual ~ClientData() = 0; }; bool isSharedInstance() { return globalDataType == APIShared; } bool usingAPI() { return globalDataType != Default; } static bool sharedInstanceExists(); - static JSGlobalData& sharedInstance(); + JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance(); - static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap); - static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap); + JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> create(ThreadStackType, HeapSize = SmallHeap); + JS_EXPORT_PRIVATE static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType, HeapSize = SmallHeap); static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType, HeapSize = SmallHeap); - ~JSGlobalData(); + JS_EXPORT_PRIVATE ~JSGlobalData(); void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } @@ -223,13 +223,6 @@ namespace JSC { bool canUseJIT() { return m_canUseJIT; } #endif - const StackBounds& stack() - { - return (globalDataType == Default) - ? m_stack - : wtfThreadData().stack(); - } - OwnPtr<ParserArena> parserArena; OwnPtr<Keywords> keywords; Interpreter* interpreter; @@ -308,21 +301,21 @@ namespace JSC { CachedTranscendentalFunction<sin> cachedSin; - void resetDateCache(); + JS_EXPORT_PRIVATE void resetDateCache(); - void startSampling(); - void stopSampling(); - void dumpSampleData(ExecState* exec); + JS_EXPORT_PRIVATE void startSampling(); + JS_EXPORT_PRIVATE void stopSampling(); + JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec); void recompileAllJSFunctions(); RegExpCache* regExpCache() { return m_regExpCache; } #if ENABLE(REGEXP_TRACING) void addRegExpToTrace(PassRefPtr<RegExp> regExp); #endif - void dumpRegExpTrace(); - void clearBuiltinStructures(); + JS_EXPORT_PRIVATE void dumpRegExpTrace(); + JS_EXPORT_PRIVATE void clearBuiltinStructures(); bool isCollectorBusy() { return heap.isBusy(); } - void releaseExecutableMemory(); + JS_EXPORT_PRIVATE void releaseExecutableMemory(); #if ENABLE(GC_VALIDATION) bool isInitializingObject() const; @@ -345,6 +338,7 @@ namespace JSC { registerTypedArrayFunction(int16, Int16); registerTypedArrayFunction(int32, Int32); registerTypedArrayFunction(uint8, Uint8); + registerTypedArrayFunction(uint8Clamped, Uint8Clamped); registerTypedArrayFunction(uint16, Uint16); registerTypedArrayFunction(uint32, Uint32); registerTypedArrayFunction(float32, Float32); @@ -358,7 +352,6 @@ namespace JSC { #if ENABLE(JIT) && ENABLE(INTERPRETER) bool m_canUseJIT; #endif - StackBounds m_stack; #if ENABLE(GC_VALIDATION) bool m_isInitializingObject; #endif @@ -366,6 +359,7 @@ namespace JSC { TypedArrayDescriptor m_int16ArrayDescriptor; TypedArrayDescriptor m_int32ArrayDescriptor; TypedArrayDescriptor m_uint8ArrayDescriptor; + TypedArrayDescriptor m_uint8ClampedArrayDescriptor; TypedArrayDescriptor m_uint16ArrayDescriptor; TypedArrayDescriptor m_uint32ArrayDescriptor; TypedArrayDescriptor m_float32ArrayDescriptor; diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 5ad53c222..f28139d27 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -153,7 +153,7 @@ void JSGlobalObject::put(JSCell* cell, ExecState* exec, const Identifier& proper JSVariableObject::put(thisObject, exec, propertyName, value, slot); } -void JSGlobalObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); @@ -167,7 +167,7 @@ void JSGlobalObject::putWithAttributes(JSObject* object, ExecState* exec, const if (!valueBefore) { JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName); if (valueAfter) - JSObject::putWithAttributes(thisObject, exec, propertyName, valueAfter, attributes); + JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes); } } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 1caa8b187..70368307d 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -192,20 +192,20 @@ namespace JSC { } public: - ~JSGlobalObject(); - static void destroy(JSCell*); + JS_EXPORT_PRIVATE ~JSGlobalObject(); + JS_EXPORT_PRIVATE static void destroy(JSCell*); - static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); - static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); bool hasOwnPropertyForWrite(ExecState*, const Identifier&); - static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); - static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); - static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); + JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); + JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); // We use this in the code generator as we perform symbol table // lookups prior to initializing the properties @@ -283,7 +283,7 @@ namespace JSC { ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); } - ExecState* globalExec(); + JS_EXPORT_PRIVATE ExecState* globalExec(); static bool shouldInterruptScript(const JSGlobalObject*) { return true; } @@ -332,17 +332,17 @@ namespace JSC { JSValue value; unsigned attributes; }; - void addStaticGlobals(GlobalPropertyInfo*, int count); + JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count); private: // FIXME: Fold reset into init. - void init(JSObject* thisValue); + JS_EXPORT_PRIVATE void init(JSObject* thisValue); void reset(JSValue prototype); void createThrowTypeError(ExecState*); void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count); - static void clearRareData(JSCell*); + JS_EXPORT_PRIVATE static void clearRareData(JSCell*); }; JSGlobalObject* asGlobalObject(JSValue); @@ -488,7 +488,7 @@ namespace JSC { class DynamicGlobalObjectScope { WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope); public: - DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); + JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); ~DynamicGlobalObjectScope() { diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index bf6b31ef1..b82ab62ab 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -51,8 +51,7 @@ namespace JSC { static JSValue encode(ExecState* exec, const char* doNotEscape) { - UString str = exec->argument(0).toString(exec); - CString cstr = str.utf8(true); + CString cstr = exec->argument(0).toString(exec)->value(exec).utf8(true); if (!cstr.data()) return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence.")); @@ -143,7 +142,7 @@ static JSValue decode(ExecState* exec, const CharType* characters, int length, c static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict) { JSStringBuilder builder; - UString str = exec->argument(0).toString(exec); + UString str = exec->argument(0).toString(exec)->value(exec); if (str.is8Bit()) return decode(exec, str.characters8(), str.length(), doNotUnescape, strict); @@ -513,7 +512,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) if (!x.isString()) return JSValue::encode(x); - UString s = x.toString(exec); + UString s = x.toString(exec)->value(exec); if (s.is8Bit()) { LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON); @@ -556,7 +555,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) } // If ToString throws, we shouldn't call ToInt32. - UString s = value.toString(exec); + UString s = value.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -565,7 +564,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec) { - return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec)))); + return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec)->value(exec)))); } EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec) @@ -623,7 +622,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec) "*+-./@_"; JSStringBuilder builder; - UString str = exec->argument(0).toString(exec); + UString str = exec->argument(0).toString(exec)->value(exec); if (str.is8Bit()) { const LChar* c = str.characters8(); for (unsigned k = 0; k < str.length(); k++, c++) { @@ -662,7 +661,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec) EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec) { UStringBuilder builder; - UString str = exec->argument(0).toString(exec); + UString str = exec->argument(0).toString(exec)->value(exec); int k = 0; int len = str.length(); diff --git a/Source/JavaScriptCore/runtime/JSGlobalThis.h b/Source/JavaScriptCore/runtime/JSGlobalThis.h index fa5de0491..fa5c2eb34 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalThis.h +++ b/Source/JavaScriptCore/runtime/JSGlobalThis.h @@ -63,7 +63,7 @@ protected: static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; - static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); WriteBarrier<JSGlobalObject> m_unwrappedObject; }; diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h index 7b07b4fb3..a0eb96975 100644 --- a/Source/JavaScriptCore/runtime/JSLock.h +++ b/Source/JavaScriptCore/runtime/JSLock.h @@ -56,7 +56,7 @@ namespace JSC { class JSLock { WTF_MAKE_NONCOPYABLE(JSLock); public: - JSLock(ExecState*); + JS_EXPORT_PRIVATE JSLock(ExecState*); JSLock(JSGlobalData*); JSLock(JSLockBehavior lockBehavior) @@ -80,22 +80,22 @@ namespace JSC { unlock(m_lockBehavior); } - static void lock(JSLockBehavior); - static void unlock(JSLockBehavior); + JS_EXPORT_PRIVATE static void lock(JSLockBehavior); + JS_EXPORT_PRIVATE static void unlock(JSLockBehavior); static void lock(ExecState*); static void unlock(ExecState*); - static intptr_t lockCount(); - static bool currentThreadIsHoldingLock(); + JS_EXPORT_PRIVATE static intptr_t lockCount(); + JS_EXPORT_PRIVATE static bool currentThreadIsHoldingLock(); JSLockBehavior m_lockBehavior; class DropAllLocks { WTF_MAKE_NONCOPYABLE(DropAllLocks); public: - DropAllLocks(ExecState* exec); - DropAllLocks(JSLockBehavior); - ~DropAllLocks(); + JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec); + JS_EXPORT_PRIVATE DropAllLocks(JSLockBehavior); + JS_EXPORT_PRIVATE ~DropAllLocks(); private: intptr_t m_lockCount; diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 05c6c2953..83b118429 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -142,7 +142,7 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value) if (object->inherits(&NumberObject::s_info)) return jsNumber(object->toNumber(exec)); if (object->inherits(&StringObject::s_info)) - return jsString(exec, object->toString(exec)); + return object->toString(exec); if (object->inherits(&BooleanObject::s_info)) return object->toPrimitive(exec); return value; @@ -223,25 +223,12 @@ Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const if (exec->hadException()) break; - UString propertyName; - if (name.getString(exec, propertyName)) { - m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); - continue; - } - - if (name.isNumber()) { - m_arrayReplacerPropertyNames.add(Identifier::from(exec, name.asNumber())); - continue; - } - if (name.isObject()) { if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info)) continue; - propertyName = name.toString(exec); - if (exec->hadException()) - break; - m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); } + + m_arrayReplacerPropertyNames.add(Identifier(exec, name.toString(exec)->value(exec))); } return; } @@ -825,8 +812,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) { if (!exec->argumentCount()) return throwVMError(exec, createError(exec, "JSON.parse requires at least one parameter")); - JSValue value = exec->argument(0); - UString source = value.toString(exec); + UString source = exec->argument(0).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index a813e8416..a443fda86 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "JSObject.h" +#include "BumpSpaceInlineMethods.h" #include "DatePrototype.h" #include "ErrorConstructor.h" #include "GetterSetter.h" @@ -83,11 +84,6 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class } } -void JSObject::finalize(JSCell* cell) -{ - delete [] jsCast<JSObject*>(cell)->m_propertyStorage.get(); -} - void JSObject::destroy(JSCell* cell) { jsCast<JSObject*>(cell)->JSObject::~JSObject(); @@ -106,7 +102,16 @@ void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor) PropertyStorage storage = thisObject->propertyStorage(); size_t storageSize = thisObject->structure()->propertyStorageSize(); - visitor.appendValues(storage, storageSize); + if (thisObject->isUsingInlineStorage()) + visitor.appendValues(storage, storageSize); + else { + // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. + void* temp = storage; + visitor.copyAndAppend(&temp, thisObject->structure()->propertyStorageCapacity() * sizeof(WriteBarrierBase<Unknown>), storage->slot(), storageSize); + storage = static_cast<PropertyStorage>(temp); + thisObject->m_propertyStorage.set(storage, StorageBarrier::Unchecked); + } + if (thisObject->m_inheritorID) visitor.append(&thisObject->m_inheritorID); @@ -162,7 +167,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName for (JSObject* obj = thisObject; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); if (prototype.isNull()) { - if (!thisObject->putDirectInternal(globalData, propertyName, value, 0, true, slot, getJSFunction(value)) && slot.isStrictMode()) + if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -205,7 +210,7 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName break; } - if (!thisObject->putDirectInternal(globalData, propertyName, value, 0, true, slot, getJSFunction(value)) && slot.isStrictMode()) + if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode()) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -217,16 +222,28 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, thisObject->methodTable()->put(thisObject, exec, Identifier::from(exec, propertyName), value, slot); } -void JSObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - object->putDirectInternal(exec->globalData(), propertyName, value, attributes, true, slot, getJSFunction(value)); + object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value)); } -void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(value.isGetterSetter() && (attributes & Accessor)); + ASSERT(propertyName != globalData.propertyNames->underscoreProto); + PutPropertySlot slot; - putDirectInternal(*globalData, propertyName, value, attributes, true, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); + + // putDirect will change our Structure if we add a new property. For + // getters and setters, though, we also need to change our Structure + // if we override an existing non-getter or non-setter. + if (slot.type() != PutPropertySlot::NewProperty) + setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes)); + + structure()->setHasGetterSetterProperties(true); } bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const @@ -361,15 +378,13 @@ void JSObject::defineGetter(JSObject* thisObject, ExecState* exec, const Identif JSGlobalData& globalData = exec->globalData(); PutPropertySlot slot; GetterSetter* getterSetter = GetterSetter::create(exec); - thisObject->putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot, 0); + thisObject->putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, getterSetter, attributes | Accessor, slot, 0); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. - if (slot.type() != PutPropertySlot::NewProperty) { - if (!thisObject->structure()->isDictionary()) - thisObject->setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, thisObject->structure())); - } + if (slot.type() != PutPropertySlot::NewProperty) + thisObject->setStructure(exec->globalData(), Structure::attributeChangeTransition(globalData, thisObject->structure(), propertyName, attributes | Accessor)); thisObject->structure()->setHasGetterSetterProperties(true); getterSetter->setGetter(globalData, getterFunction); @@ -379,20 +394,17 @@ void JSObject::initializeGetterSetterProperty(ExecState* exec, const Identifier& { // Set an inital property on an object; the property must not already exist & the attribute flags must be set correctly. ASSERT(structure()->get(exec->globalData(), propertyName) == WTF::notFound); - ASSERT(static_cast<bool>(getterSetter->getter()) == static_cast<bool>(attributes & Getter)); - ASSERT(static_cast<bool>(getterSetter->setter()) == static_cast<bool>(attributes & Setter)); + ASSERT(static_cast<bool>(attributes & Accessor)); JSGlobalData& globalData = exec->globalData(); PutPropertySlot slot; - putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot, 0); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, getterSetter, attributes, slot, 0); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. - if (slot.type() != PutPropertySlot::NewProperty) { - if (!structure()->isDictionary()) - setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, structure())); - } + if (slot.type() != PutPropertySlot::NewProperty) + setStructure(exec->globalData(), Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes)); structure()->setHasGetterSetterProperties(true); } @@ -413,15 +425,13 @@ void JSObject::defineSetter(JSObject* thisObject, ExecState* exec, const Identif PutPropertySlot slot; GetterSetter* getterSetter = GetterSetter::create(exec); - thisObject->putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot, 0); + thisObject->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, getterSetter, attributes | Accessor, slot, 0); // putDirect will change our Structure if we add a new property. For // getters and setters, though, we also need to change our Structure // if we override an existing non-getter or non-setter. - if (slot.type() != PutPropertySlot::NewProperty) { - if (!thisObject->structure()->isDictionary()) - thisObject->setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), thisObject->structure())); - } + if (slot.type() != PutPropertySlot::NewProperty) + thisObject->setStructure(exec->globalData(), Structure::attributeChangeTransition(exec->globalData(), thisObject->structure(), propertyName, attributes | Accessor)); thisObject->structure()->setHasGetterSetterProperties(true); getterSetter->setSetter(exec->globalData(), setterFunction); @@ -531,11 +541,11 @@ double JSObject::toNumber(ExecState* exec) const return primitive.toNumber(exec); } -UString JSObject::toString(ExecState* exec) const +JSString* JSObject::toString(ExecState* exec) const { JSValue primitive = toPrimitive(exec, PreferString); if (exec->hadException()) - return ""; + return jsEmptyString(exec); return primitive.toString(exec); } @@ -646,20 +656,28 @@ void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize, // It's important that this function not rely on structure(), since // we might be in the middle of a transition. - PropertyStorage newPropertyStorage = 0; - newPropertyStorage = new WriteBarrierBase<Unknown>[newSize]; PropertyStorage oldPropertyStorage = m_propertyStorage.get(); - ASSERT(newPropertyStorage); + PropertyStorage newPropertyStorage = 0; - for (unsigned i = 0; i < oldSize; ++i) - newPropertyStorage[i] = oldPropertyStorage[i]; + if (isUsingInlineStorage()) { + // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. + void* temp = newPropertyStorage; + if (!globalData.heap.tryAllocateStorage(sizeof(WriteBarrierBase<Unknown>) * newSize, &temp)) + CRASH(); + newPropertyStorage = static_cast<PropertyStorage>(temp); - if (isUsingInlineStorage()) - Heap::heap(this)->addFinalizer(this, &finalize); - else - delete [] oldPropertyStorage; + for (unsigned i = 0; i < oldSize; ++i) + newPropertyStorage[i] = oldPropertyStorage[i]; + } else { + // We have this extra temp here to slake GCC's thirst for the blood of those who dereference type-punned pointers. + void* temp = oldPropertyStorage; + if (!globalData.heap.tryReallocateStorage(&temp, sizeof(WriteBarrierBase<Unknown>) * oldSize, sizeof(WriteBarrierBase<Unknown>) * newSize)) + CRASH(); + newPropertyStorage = static_cast<PropertyStorage>(temp); + } + ASSERT(newPropertyStorage); m_propertyStorage.set(globalData, this, newPropertyStorage); } @@ -692,15 +710,11 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) { if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) { GetterSetter* accessor = GetterSetter::create(exec); - if (oldDescriptor.getter()) { - attributes |= Getter; - accessor->setGetter(exec->globalData(), asObject(oldDescriptor.getter())); - } - if (oldDescriptor.setter()) { - attributes |= Setter; - accessor->setSetter(exec->globalData(), asObject(oldDescriptor.setter())); - } - target->methodTable()->putWithAttributes(target, exec, propertyName, accessor, attributes); + if (oldDescriptor.getterPresent()) + accessor->setGetter(exec->globalData(), oldDescriptor.getterObject()); + if (oldDescriptor.setterPresent()) + accessor->setSetter(exec->globalData(), oldDescriptor.setterObject()); + target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor); return true; } JSValue newValue = jsUndefined(); @@ -708,21 +722,32 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p newValue = descriptor.value(); else if (oldDescriptor.value()) newValue = oldDescriptor.value(); - target->methodTable()->putWithAttributes(target, exec, propertyName, newValue, attributes & ~(Getter | Setter)); + target->putDirect(exec->globalData(), propertyName, newValue, attributes & ~Accessor); return true; } attributes &= ~ReadOnly; - if (descriptor.getter() && descriptor.getter().isObject()) - target->methodTable()->defineGetter(target, exec, propertyName, asObject(descriptor.getter()), attributes); - if (exec->hadException()) - return false; - if (descriptor.setter() && descriptor.setter().isObject()) - target->methodTable()->defineSetter(target, exec, propertyName, asObject(descriptor.setter()), attributes); - return !exec->hadException(); + GetterSetter* accessor = GetterSetter::create(exec); + + if (descriptor.getterPresent()) + accessor->setGetter(exec->globalData(), descriptor.getterObject()); + else if (oldDescriptor.getterPresent()) + accessor->setGetter(exec->globalData(), oldDescriptor.getterObject()); + if (descriptor.setterPresent()) + accessor->setSetter(exec->globalData(), descriptor.setterObject()); + else if (oldDescriptor.setterPresent()) + accessor->setSetter(exec->globalData(), oldDescriptor.setterObject()); + + target->putDirectAccessor(exec->globalData(), propertyName, accessor, attributes | Accessor); + return true; } bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) { + // __proto__ is magic; we don't currently support setting it as a regular property. + // Silent filter out calls to set __proto__ at an early stage; pretend all is okay. + if (propertyName == exec->propertyNames().underscoreProto) + return true; + // If we have a new property we can just put it on normally PropertyDescriptor current; if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, propertyName, current)) { @@ -824,19 +849,15 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi return false; GetterSetter* getterSetter = asGetterSetter(accessor); if (current.attributesEqual(descriptor)) { - if (descriptor.setter()) - getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter())); - if (descriptor.getter()) - getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter())); + if (descriptor.setterPresent()) + getterSetter->setSetter(exec->globalData(), descriptor.setterObject()); + if (descriptor.getterPresent()) + getterSetter->setGetter(exec->globalData(), descriptor.getterObject()); return true; } object->methodTable()->deleteProperty(object, exec, propertyName); unsigned attrs = current.attributesWithOverride(descriptor); - if (descriptor.setter()) - attrs |= Setter; - if (descriptor.getter()) - attrs |= Getter; - object->putDirect(exec->globalData(), propertyName, getterSetter, attrs); + object->putDirectAccessor(exec->globalData(), propertyName, getterSetter, attrs | Accessor); return true; } diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index e26012dd9..433249c20 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -55,7 +55,7 @@ namespace JSC { class Structure; struct HashTable; - JSObject* throwTypeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const UString&); extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError; // ECMA 262-3 8.6.1 @@ -66,8 +66,7 @@ namespace JSC { DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) DontDelete = 1 << 3, // property can't be deleted Function = 1 << 4, // property is a function - only used by static hashtables - Getter = 1 << 5, // property is a getter - Setter = 1 << 6 // property is a setter + Accessor = 1 << 5, // property is a getter/setter }; class JSObject : public JSCell { @@ -75,18 +74,21 @@ namespace JSC { friend class JIT; friend class JSCell; friend class MarkedBlock; - friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + + enum PutMode { + PutModePut, + PutModeDefineOwnProperty, + }; public: typedef JSCell Base; - static void destroy(JSCell*); - - static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void destroy(JSCell*); - static UString className(const JSObject*); + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); - static void finalize(JSCell*); + JS_EXPORT_PRIVATE static UString className(const JSObject*); JSValue prototype() const; void setPrototype(JSGlobalData&, JSValue prototype); @@ -99,43 +101,50 @@ namespace JSC { bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); + JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - - static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); - - static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - void putWithAttributes(JSGlobalData*, const Identifier& propertyName, JSValue, unsigned attributes); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + + // putDirect is effectively an unchecked vesion of 'defineOwnProperty': + // - the prototype chain is not consulted + // - accessors are not called. + // - attributes will be respected (after the call the property will exist with the given attributes) + JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); + void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + void putDirectAccessor(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; - bool hasProperty(ExecState*, const Identifier& propertyName) const; - bool hasProperty(ExecState*, unsigned propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const; bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; - static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); - static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - bool toBoolean(ExecState*) const; + JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; - double toNumber(ExecState*) const; - UString toString(ExecState*) const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSString* toString(ExecState*) const; // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0, // because this call may come from inside the compiler. - static JSObject* toThisObject(JSCell*, ExecState*); + JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*); JSObject* unwrappedObject(); bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; @@ -171,35 +180,37 @@ namespace JSC { bool hasCustomProperties() { return structure()->didTransition(); } bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } - bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&); - void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); - bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); - - void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); + // putOwnDataProperty has 'put' like semantics, however this method: + // - assumes the object contains no own getter/setter properties. + // - provides no special handling for __proto__ + // - does not walk the prototype chain (to check for accessors or non-writable properties). + // This is used by JSActivation. + bool putOwnDataProperty(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); // Fast access to known property offsets. JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); } void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); } void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); } - void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); + JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); void initializeGetterSetterProperty(ExecState*, const Identifier&, GetterSetter*, unsigned attributes); - static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); - static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); - JSValue lookupGetter(ExecState*, const Identifier& propertyName); - JSValue lookupSetter(ExecState*, const Identifier& propertyName); - static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE JSValue lookupGetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE JSValue lookupSetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); bool isGlobalObject() const; bool isVariableObject() const; + bool isStaticScopeObject() const; bool isActivationObject() const; bool isErrorInstance() const; bool isGlobalThis() const; void seal(JSGlobalData&); void freeze(JSGlobalData&); - void preventExtensions(JSGlobalData&); + JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&); bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); } bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); } bool isExtensible() { return structure()->isExtensible(); } @@ -207,7 +218,7 @@ namespace JSC { bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } void reifyStaticFunctionsForDelete(ExecState* exec); - void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); + JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); } void* addressOfPropertyStorage() @@ -281,7 +292,8 @@ namespace JSC { return &propertyStorage()[offset]; } - bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&, JSCell*); + template<PutMode> + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -317,7 +329,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } - static void destroy(JSCell*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); protected: explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure) @@ -417,6 +429,11 @@ inline bool JSObject::isVariableObject() const return structure()->typeInfo().type() >= VariableObjectType; } +inline bool JSObject::isStaticScopeObject() const +{ + return structure()->typeInfo().type() == StaticScopeObjectType; +} + inline bool JSObject::isActivationObject() const { return structure()->typeInfo().type() == ActivationObjectType; @@ -628,9 +645,11 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) +template<JSObject::PutMode mode> +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); + ASSERT(value.isGetterSetter() == !!(attributes & Accessor)); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (structure()->isDictionary()) { @@ -642,7 +661,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) structure()->despecifyDictionaryFunction(globalData, propertyName); - if (checkReadOnly && currentAttributes & ReadOnly) + if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; putDirectOffset(globalData, offset, value); @@ -657,7 +676,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } - if (checkReadOnly && !isExtensible()) + if ((mode == PutModePut) && !isExtensible()) return false; size_t currentCapacity = structure()->propertyStorageCapacity(); @@ -693,7 +712,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi JSCell* currentSpecificFunction; offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { - if (checkReadOnly && currentAttributes & ReadOnly) + if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; // There are three possibilities here: @@ -721,7 +740,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } - if (checkReadOnly && !isExtensible()) + if ((mode == PutModePut) && !isExtensible()) return false; Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); @@ -739,27 +758,31 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } -inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + ASSERT(!structure()->hasGetterSetterProperties()); - return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(value)); + return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); } -inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - return putDirectInternal(globalData, propertyName, value, 0, false, slot, getJSFunction(value)); + ASSERT(!value.isGetterSetter()); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); size_t currentCapacity = structure()->propertyStorageCapacity(); size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); if (currentCapacity != structure()->propertyStorageCapacity()) @@ -841,13 +864,6 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot); } -inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) -{ - ASSERT(isCell() && isObject()); - if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode()) - throwTypeError(exec, StrictModeReadonlyPropertyWriteError); -} - inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) { if (UNLIKELY(!isCell())) { diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp index ada921d0e..f8942b5f8 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -78,7 +78,7 @@ void JSStaticScopeObject::put(JSCell* cell, ExecState* exec, const Identifier& p ASSERT_NOT_REACHED(); } -void JSStaticScopeObject::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) +void JSStaticScopeObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) { JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(object); if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes)) diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h index 6a2e51a15..bbf03a347 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -47,7 +47,7 @@ namespace JSC{ static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); - static void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); + static void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(StaticScopeObjectType, StructureFlags), &s_info); } diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index 93193b5e5..4e98f9d18 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -229,11 +229,6 @@ double JSString::toNumber(ExecState* exec) const return jsToNumber(value(exec)); } -UString JSString::toString(ExecState* exec) const -{ - return value(exec); -} - inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { StringObject* object = new (NotNull, allocateCell<StringObject>(*exec->heap())) StringObject(exec->globalData(), globalObject->stringObjectStructure()); diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index f40455571..c0637a6e0 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -214,10 +214,9 @@ namespace JSC { unsigned length() { return m_length; } JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; - bool toBoolean(ExecState*) const; + JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; JSObject* toObject(ExecState*, JSGlobalObject*) const; - UString toString(ExecState*) const; double toNumber(ExecState*) const; bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -236,12 +235,12 @@ namespace JSC { static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); } static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); } - static const ClassInfo s_info; + static JS_EXPORTDATA const ClassInfo s_info; static void visitChildren(JSCell*, SlotVisitor&); private: - void resolveRope(ExecState*) const; + JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; void resolveRopeSlowCase8(LChar*) const; void resolveRopeSlowCase(UChar*) const; void outOfMemory(ExecState*) const; @@ -453,24 +452,11 @@ namespace JSC { return isTrue(); // false, null, and undefined all convert to false. } - inline UString JSValue::toString(ExecState* exec) const + inline JSString* JSValue::toString(ExecState* exec) const { if (isString()) - return static_cast<JSString*>(asCell())->value(exec); - if (isInt32()) - return exec->globalData().numericStrings.add(asInt32()); - if (isDouble()) - return exec->globalData().numericStrings.add(asDouble()); - if (isTrue()) - return "true"; - if (isFalse()) - return "false"; - if (isNull()) - return "null"; - if (isUndefined()) - return "undefined"; - ASSERT(isCell()); - return asCell()->toString(exec); + return static_cast<JSString*>(asCell()); + return toStringSlowCase(exec); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index a5d3d936a..6b803c316 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -204,10 +204,9 @@ bool JSValue::isValidCallee() return asObject(asCell())->globalObject(); } -JSString* JSValue::toPrimitiveString(ExecState* exec) const +JSString* JSValue::toStringSlowCase(ExecState* exec) const { - if (isString()) - return static_cast<JSString*>(asCell()); + ASSERT(!isString()); if (isInt32()) return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asInt32())); if (isDouble()) @@ -222,10 +221,11 @@ JSString* JSValue::toPrimitiveString(ExecState* exec) const return jsNontrivialString(exec, exec->propertyNames().undefined.ustring()); ASSERT(isCell()); - JSValue v = asCell()->toPrimitive(exec, NoPreference); - if (v.isString()) - return static_cast<JSString*>(v.asCell()); - return jsString(&exec->globalData(), v.toString(exec)); + JSValue value = asCell()->toPrimitive(exec, PreferString); + if (exec->hadException()) + return jsEmptyString(exec); + ASSERT(!value.isObject()); + return value.toString(exec); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index a00106274..79e50fba0 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -93,7 +93,7 @@ namespace JSC { }; // This implements ToInt32, defined in ECMA-262 9.5. - int32_t toInt32(double); + JS_EXPORT_PRIVATE int32_t toInt32(double); // This implements ToUInt32, defined in ECMA-262 9.6. inline uint32_t toUInt32(double number) @@ -197,13 +197,12 @@ namespace JSC { // toNumber conversion is expected to be side effect free if an exception has // been set in the ExecState already. double toNumber(ExecState*) const; - UString toString(ExecState*) const; - JSString* toPrimitiveString(ExecState*) const; + JSString* toString(ExecState*) const; JSObject* toObject(ExecState*) const; JSObject* toObject(ExecState*, JSGlobalObject*) const; // Integer conversions. - double toInteger(ExecState*) const; + JS_EXPORT_PRIVATE double toInteger(ExecState*) const; double toIntegerPreserveNaN(ExecState*) const; int32_t toInt32(ExecState*) const; uint32_t toUInt32(ExecState*) const; @@ -218,7 +217,6 @@ namespace JSC { JSValue get(ExecState*, unsigned propertyName) const; JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); void put(ExecState*, unsigned propertyName, JSValue); JSObject* toThisObject(ExecState*) const; @@ -232,7 +230,7 @@ namespace JSC { bool isCell() const; JSCell* asCell() const; - bool isValidCallee(); + JS_EXPORT_PRIVATE bool isValidCallee(); #ifndef NDEBUG char* description(); @@ -245,11 +243,12 @@ namespace JSC { JSValue(HashTableDeletedValueTag); inline const JSValue asValue() const { return *this; } - double toNumberSlowCase(ExecState*) const; - JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; - JSObject* toThisObjectSlowCase(ExecState*) const; + JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const; + JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; + JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const; - JSObject* synthesizePrototype(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; JSObject* synthesizeObject(ExecState*) const; #if USE(JSVALUE32_64) diff --git a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h index e13d34745..1373558f7 100644 --- a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h +++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h @@ -477,6 +477,7 @@ namespace JSC { inline double JSValue::asDouble() const { + ASSERT(isDouble()); return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset); } diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp index 706e3debb..8ca695074 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp @@ -73,7 +73,7 @@ bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDe return false; } -void JSVariableObject::putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned) +void JSVariableObject::putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned) { ASSERT_NOT_REACHED(); } diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index 78e624e02..c1d05ff74 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -48,12 +48,12 @@ namespace JSC { SymbolTable& symbolTable() const { return *m_symbolTable; } - static void destroy(JSCell*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); - static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); + static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); - static bool deleteProperty(JSCell*, ExecState*, const Identifier&); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); bool isDynamicScope(bool& requiresDynamicChecks) const; @@ -88,7 +88,7 @@ namespace JSC { void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray); bool symbolTableGet(const Identifier&, PropertySlot&); - bool symbolTableGet(const Identifier&, PropertyDescriptor&); + JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow); bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes); diff --git a/Source/JavaScriptCore/runtime/Lookup.h b/Source/JavaScriptCore/runtime/Lookup.h index 8ed70b41d..64d06b503 100644 --- a/Source/JavaScriptCore/runtime/Lookup.h +++ b/Source/JavaScriptCore/runtime/Lookup.h @@ -126,7 +126,7 @@ namespace JSC { createTable(&exec->globalData()); } - void deleteTable() const; + JS_EXPORT_PRIVATE void deleteTable() const; // Find an entry in the table, and return the entry. ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const @@ -218,10 +218,10 @@ namespace JSC { } // Convert the hash table keys to identifiers. - void createTable(JSGlobalData*) const; + JS_EXPORT_PRIVATE void createTable(JSGlobalData*) const; }; - bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&); + JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&); /** * This method does it all (looking in the hashtable, checking for function diff --git a/Source/JavaScriptCore/runtime/MemoryStatistics.h b/Source/JavaScriptCore/runtime/MemoryStatistics.h index d4b8b6fc1..9a86df296 100644 --- a/Source/JavaScriptCore/runtime/MemoryStatistics.h +++ b/Source/JavaScriptCore/runtime/MemoryStatistics.h @@ -37,7 +37,7 @@ struct GlobalMemoryStatistics { size_t JITBytes; }; -GlobalMemoryStatistics globalMemoryStatistics(); +JS_EXPORT_PRIVATE GlobalMemoryStatistics globalMemoryStatistics(); } diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp index 4612b56d2..fb90bcd17 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp @@ -447,7 +447,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec) radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0 if (radix == 10) - return JSValue::encode(jsString(exec, jsNumber(x).toString(exec))); + return JSValue::encode(jsNumber(x).toString(exec)); // Fast path for number to character conversion. if (radix == 36) { @@ -474,7 +474,7 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec) if (!toThisNumber(exec->hostThisValue(), x)) return throwVMTypeError(exec); - return JSValue::encode(jsString(exec, jsNumber(x).toString(exec))); + return JSValue::encode(jsNumber(x).toString(exec)); } EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 65d28c18c..d96c1de7f 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -149,7 +149,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState { if (!exec->argument(0).isObject()) return throwVMError(exec, createTypeError(exec, "Requested property descriptor of a value that is not an object.")); - UString propertyName = exec->argument(1).toString(exec); + UString propertyName = exec->argument(1).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); JSObject* object = asObject(exec->argument(0)); @@ -164,8 +164,10 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0); description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0); } else { - description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0); - description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0); + ASSERT(descriptor.getter()); + ASSERT(descriptor.setter()); + description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter(), 0); + description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter(), 0); } description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0); @@ -251,8 +253,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor throwError(exec, createTypeError(exec, "Getter must be a function.")); return false; } - } else - get = JSValue(); + } desc.setGetter(get); } @@ -267,9 +268,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor throwError(exec, createTypeError(exec, "Setter must be a function.")); return false; } - } else - set = JSValue(); - + } desc.setSetter(set); } @@ -293,13 +292,13 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec) if (!exec->argument(0).isObject()) return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects.")); JSObject* O = asObject(exec->argument(0)); - UString propertyName = exec->argument(1).toString(exec); + UString propertyName = exec->argument(1).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsNull()); PropertyDescriptor descriptor; if (!toPropertyDescriptor(exec, exec->argument(2), descriptor)) return JSValue::encode(jsNull()); - ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor())); + ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor())); ASSERT(!exec->hadException()); O->methodTable()->defineOwnProperty(O, exec, Identifier(exec, propertyName), descriptor, true); return JSValue::encode(O); diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp index 3f4dc19db..7ca7dae61 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -118,7 +118,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec) EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec))))); + return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))))); } EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec) @@ -149,7 +149,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec) CallData callData; if (getCallData(exec->argument(1), callData) == CallTypeNone) return throwVMError(exec, createSyntaxError(exec, "invalid getter usage")); - thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0); + thisObject->methodTable()->defineGetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0); return JSValue::encode(jsUndefined()); } @@ -162,7 +162,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec) CallData callData; if (getCallData(exec->argument(1), callData) == CallTypeNone) return throwVMError(exec, createSyntaxError(exec, "invalid setter usage")); - thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)), 0); + thisObject->methodTable()->defineSetter(thisObject, exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)), asObject(exec->argument(1)), 0); return JSValue::encode(jsUndefined()); } @@ -172,7 +172,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec)))); + return JSValue::encode(thisObject->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))); } EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec) @@ -181,13 +181,13 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec)))); + return JSValue::encode(thisObject->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec)))); } EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec))))); + return JSValue::encode(jsBoolean(thisValue.toObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)->value(exec))))); } // 15.2.4.3 Object.prototype.toLocaleString() diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h index 78b1cbd39..4c49e97a7 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.h +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h @@ -59,7 +59,7 @@ namespace JSC { bool m_hasNoPropertiesWithUInt32Names; }; - EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*); + JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp index b89746f3f..459feb466 100644 --- a/Source/JavaScriptCore/runtime/Operations.cpp +++ b/Source/JavaScriptCore/runtime/Operations.cpp @@ -47,13 +47,11 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2) JSValue p1 = v1.toPrimitive(callFrame); JSValue p2 = v2.toPrimitive(callFrame); - if (p1.isString()) { - return p2.isString() - ? jsString(callFrame, asString(p1), asString(p2)) - : jsString(callFrame, asString(p1), jsString(callFrame, p2.toString(callFrame))); - } + if (p1.isString()) + return jsString(callFrame, asString(p1), p2.toString(callFrame)); + if (p2.isString()) - return jsString(callFrame, jsString(callFrame, p1.toString(callFrame)), asString(p2)); + return jsString(callFrame, p1.toString(callFrame), asString(p2)); return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame)); } diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index ca2174fa1..945283899 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -81,10 +81,7 @@ namespace JSC { for (unsigned i = 0; i < count; ++i) { JSValue v = strings[i].jsValue(); - if (v.isString()) - ropeBuilder.append(asString(v)); - else - ropeBuilder.append(jsString(globalData, v.toString(exec))); + ropeBuilder.append(v.toString(exec)); if (ropeBuilder.length() < oldLength) // True for overflow return throwOutOfMemoryError(exec); @@ -97,20 +94,13 @@ namespace JSC { { JSGlobalData* globalData = &exec->globalData(); JSString::RopeBuilder ropeBuilder(*globalData); - - if (thisValue.isString()) - ropeBuilder.append(asString(thisValue)); - else - ropeBuilder.append(jsString(globalData, thisValue.toString(exec))); + ropeBuilder.append(thisValue.toString(exec)); unsigned oldLength = 0; for (unsigned i = 0; i < exec->argumentCount(); ++i) { JSValue v = exec->argument(i); - if (v.isString()) - ropeBuilder.append(asString(v)); - else - ropeBuilder.append(jsString(globalData, v.toString(exec))); + ropeBuilder.append(v.toString(exec)); if (ropeBuilder.length() < oldLength) // True for overflow return throwOutOfMemoryError(exec); @@ -300,11 +290,8 @@ namespace JSC { if (v1.isNumber() && v2.isNumber()) return jsNumber(v1.asNumber() + v2.asNumber()); - if (v1.isString()) { - return v2.isString() - ? jsString(callFrame, asString(v1), asString(v2)) - : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame)); - } + if (v1.isString() && !v2.isObject()) + return jsString(callFrame, asString(v1), v2.toString(callFrame)); // All other cases are pretty uncommon return jsAddSlowCase(callFrame, v1, v2); diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index 68d10b7bd..ddfba6e7c 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -27,6 +27,7 @@ #include "Options.h" #include <limits> +#include <wtf/NumberOfCores.h> #include <wtf/PageBlock.h> #if OS(DARWIN) && ENABLE(PARALLEL_GC) @@ -129,10 +130,10 @@ void setHeuristic(T& variable, const char* name, U value) void initializeOptions() { - SET(maximumOptimizationCandidateInstructionCount, 1000); + SET(maximumOptimizationCandidateInstructionCount, 1100); - SET(maximumFunctionForCallInlineCandidateInstructionCount, 150); - SET(maximumFunctionForConstructInlineCandidateInstructionCount, 80); + SET(maximumFunctionForCallInlineCandidateInstructionCount, 180); + SET(maximumFunctionForConstructInlineCandidateInstructionCount, 100); SET(maximumInliningDepth, 5); @@ -174,12 +175,8 @@ void initializeOptions() SET(opaqueRootMergeThreshold, 1000); int cpusToUse = 1; -#if OS(DARWIN) && ENABLE(PARALLEL_GC) - int name[2]; - size_t valueSize = sizeof(cpusToUse); - name[0] = CTL_HW; - name[1] = HW_AVAILCPU; - sysctl(name, 2, &cpusToUse, &valueSize, 0, 0); +#if ENABLE(PARALLEL_GC) + cpusToUse = WTF::numberOfProcessorCores(); #endif // We don't scale so well beyond 4. if (cpusToUse > 4) diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index f7cc5f4e8..feebd37bb 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.h @@ -73,8 +73,8 @@ extern unsigned gcMarkStackSegmentSize; extern unsigned minimumNumberOfCellsToKeep; extern unsigned maximumNumberOfSharedSegments; extern unsigned sharedStackWakeupThreshold; -extern unsigned numberOfGCMarkers; -extern unsigned opaqueRootMergeThreshold; +JS_EXPORTDATA extern unsigned numberOfGCMarkers; +JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold; void initializeOptions(); diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp index c664952a5..e3458e4b9 100644 --- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp +++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp @@ -84,24 +84,31 @@ JSValue PropertyDescriptor::setter() const return m_setter; } +JSObject* PropertyDescriptor::getterObject() const +{ + ASSERT(isAccessorDescriptor() && getterPresent()); + return m_getter.isObject() ? asObject(m_getter) : 0; +} + +JSObject* PropertyDescriptor::setterObject() const +{ + ASSERT(isAccessorDescriptor() && setterPresent()); + return m_setter.isObject() ? asObject(m_setter) : 0; +} + void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes) { ASSERT(value); + ASSERT(value.isGetterSetter() == !!(attributes & Accessor)); + m_attributes = attributes; if (value.isGetterSetter()) { - GetterSetter* accessor = asGetterSetter(value); - - m_getter = accessor->getter(); - if (m_getter) - m_attributes |= Getter; + m_attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this! - m_setter = accessor->setter(); - if (m_setter) - m_attributes |= Setter; - - ASSERT(m_getter || m_setter); + GetterSetter* accessor = asGetterSetter(value); + m_getter = accessor->getter() ? accessor->getter() : jsUndefined(); + m_setter = accessor->setter() ? accessor->setter() : jsUndefined(); m_seenAttributes = EnumerablePresent | ConfigurablePresent; - m_attributes &= ~ReadOnly; } else { m_value = value; m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent; @@ -110,14 +117,12 @@ void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes) void PropertyDescriptor::setAccessorDescriptor(GetterSetter* accessor, unsigned attributes) { - ASSERT(attributes & (Getter | Setter)); - ASSERT(accessor->getter() || accessor->setter()); - ASSERT(!accessor->getter() == !(attributes & Getter)); - ASSERT(!accessor->setter() == !(attributes & Setter)); + ASSERT(attributes & Accessor); + attributes &= ~ReadOnly; // FIXME: we should be able to ASSERT this! + m_attributes = attributes; - m_getter = accessor->getter(); - m_setter = accessor->setter(); - m_attributes &= ~ReadOnly; + m_getter = accessor->getter() ? accessor->getter() : jsUndefined(); + m_setter = accessor->setter() ? accessor->setter() : jsUndefined(); m_seenAttributes = EnumerablePresent | ConfigurablePresent; } @@ -151,14 +156,14 @@ void PropertyDescriptor::setConfigurable(bool configurable) void PropertyDescriptor::setSetter(JSValue setter) { m_setter = setter; - m_attributes |= Setter; + m_attributes |= Accessor; m_attributes &= ~ReadOnly; } void PropertyDescriptor::setGetter(JSValue getter) { m_getter = getter; - m_attributes |= Getter; + m_attributes |= Accessor; m_attributes &= ~ReadOnly; } @@ -217,6 +222,7 @@ unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& ot unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const { + unsigned currentAttributes = current.m_attributes; unsigned overrideMask = 0; if (writablePresent()) overrideMask |= ReadOnly; @@ -225,8 +231,8 @@ unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescripto if (configurablePresent()) overrideMask |= DontDelete; if (isAccessorDescriptor()) - overrideMask |= (Getter | Setter); - return (m_attributes & overrideMask) | (current.m_attributes & ~overrideMask); + overrideMask |= Accessor; + return (m_attributes & overrideMask) | (currentAttributes & ~overrideMask); } } diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.h b/Source/JavaScriptCore/runtime/PropertyDescriptor.h index 3d481b25e..98af02e66 100644 --- a/Source/JavaScriptCore/runtime/PropertyDescriptor.h +++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.h @@ -41,25 +41,27 @@ namespace JSC { , m_seenAttributes(0) { } - bool writable() const; - bool enumerable() const; - bool configurable() const; - bool isDataDescriptor() const; + JS_EXPORT_PRIVATE bool writable() const; + JS_EXPORT_PRIVATE bool enumerable() const; + JS_EXPORT_PRIVATE bool configurable() const; + JS_EXPORT_PRIVATE bool isDataDescriptor() const; bool isGenericDescriptor() const; - bool isAccessorDescriptor() const; + JS_EXPORT_PRIVATE bool isAccessorDescriptor() const; unsigned attributes() const { return m_attributes; } JSValue value() const { return m_value; } - JSValue getter() const; - JSValue setter() const; - void setUndefined(); - void setDescriptor(JSValue value, unsigned attributes); + JS_EXPORT_PRIVATE JSValue getter() const; + JS_EXPORT_PRIVATE JSValue setter() const; + JSObject* getterObject() const; + JSObject* setterObject() const; + JS_EXPORT_PRIVATE void setUndefined(); + JS_EXPORT_PRIVATE void setDescriptor(JSValue value, unsigned attributes); void setAccessorDescriptor(GetterSetter* accessor, unsigned attributes); - void setWritable(bool); - void setEnumerable(bool); - void setConfigurable(bool); + JS_EXPORT_PRIVATE void setWritable(bool); + JS_EXPORT_PRIVATE void setEnumerable(bool); + JS_EXPORT_PRIVATE void setConfigurable(bool); void setValue(JSValue value) { m_value = value; } - void setSetter(JSValue); - void setGetter(JSValue); + JS_EXPORT_PRIVATE void setSetter(JSValue); + JS_EXPORT_PRIVATE void setGetter(JSValue); bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); } bool writablePresent() const { return m_seenAttributes & WritablePresent; } bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; } @@ -72,7 +74,7 @@ namespace JSC { unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const; private: - static unsigned defaultAttributes; + JS_EXPORTDATA static unsigned defaultAttributes; bool operator==(const PropertyDescriptor&){ return false; } enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4}; // May be a getter/setter diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.h b/Source/JavaScriptCore/runtime/PropertyNameArray.h index 0da930f17..dabda945b 100644 --- a/Source/JavaScriptCore/runtime/PropertyNameArray.h +++ b/Source/JavaScriptCore/runtime/PropertyNameArray.h @@ -69,7 +69,7 @@ namespace JSC { JSGlobalData* globalData() { return m_globalData; } void add(const Identifier& identifier) { add(identifier.impl()); } - void add(StringImpl*); + JS_EXPORT_PRIVATE void add(StringImpl*); void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } diff --git a/Source/JavaScriptCore/runtime/PropertySlot.h b/Source/JavaScriptCore/runtime/PropertySlot.h index 8557e6d24..cfedf7876 100644 --- a/Source/JavaScriptCore/runtime/PropertySlot.h +++ b/Source/JavaScriptCore/runtime/PropertySlot.h @@ -218,7 +218,7 @@ namespace JSC { return m_getValue; } private: - JSValue functionGetter(ExecState*) const; + JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const; GetValueFunc m_getValue; GetIndexValueFunc m_getIndexValue; diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 0d513d2cc..69bca5df0 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -330,68 +330,52 @@ void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize cha compile(&globalData, charSize); } - -int RegExp::match(JSGlobalData& globalData, const UString& s, int startOffset, Vector<int, 32>* ovector) +int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>* ovector) { - if (startOffset < 0) - startOffset = 0; - #if ENABLE(REGEXP_TRACING) m_rtMatchCallCount++; #endif - if (static_cast<unsigned>(startOffset) > s.length() || s.isNull()) - return -1; - - if (m_state != ParseError) { - compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16); - - int offsetVectorSize = (m_numSubpatterns + 1) * 2; - int* offsetVector; - Vector<int, 32> nonReturnedOvector; - if (ovector) { - ovector->resize(offsetVectorSize); - offsetVector = ovector->data(); - } else { - nonReturnedOvector.resize(offsetVectorSize); - offsetVector = nonReturnedOvector.data(); - } + ASSERT(m_state != ParseError); + compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16); - ASSERT(offsetVector); - // Initialize offsetVector with the return value (index 0) and the - // first subpattern start indicies (even index values) set to -1. - // No need to init the subpattern end indicies. - for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++) - offsetVector[j] = -1; + int offsetVectorSize = (m_numSubpatterns + 1) * 2; + int* offsetVector; + Vector<int, 32> nonReturnedOvector; + if (ovector) { + ovector->resize(offsetVectorSize); + offsetVector = ovector->data(); + } else { + nonReturnedOvector.resize(offsetVectorSize); + offsetVector = nonReturnedOvector.data(); + } + ASSERT(offsetVector); - int result; + int result; #if ENABLE(YARR_JIT) - if (m_state == JITCode) { - if (s.is8Bit()) - result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector); - else - result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector); + if (m_state == JITCode) { + if (s.is8Bit()) + result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector); + else + result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector); #if ENABLE(YARR_JIT_DEBUG) - matchCompareWithInterpreter(s, startOffset, offsetVector, result); + matchCompareWithInterpreter(s, startOffset, offsetVector, result); #endif - } else + } else #endif - result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector); - ASSERT(result >= -1); + result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), offsetVector); + ASSERT(result >= -1); #if REGEXP_FUNC_TEST_DATA_GEN - RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result); + RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result); #endif #if ENABLE(REGEXP_TRACING) - if (result != -1) - m_rtMatchFoundCount++; + if (result != -1) + m_rtMatchFoundCount++; #endif - return result; - } - - return -1; + return result; } void RegExp::invalidateCode() diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h index 65eb48499..d0201cbfb 100644 --- a/Source/JavaScriptCore/runtime/RegExp.h +++ b/Source/JavaScriptCore/runtime/RegExp.h @@ -35,13 +35,13 @@ namespace JSC { struct RegExpRepresentation; class JSGlobalData; - RegExpFlags regExpFlags(const UString&); + JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const UString&); class RegExp : public JSCell { public: typedef JSCell Base; - static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags); + JS_EXPORT_PRIVATE static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags); static void destroy(JSCell*); bool global() const { return m_flags & FlagGlobal; } @@ -53,7 +53,7 @@ namespace JSC { bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; } const char* errorMessage() const { return m_constructionError; } - int match(JSGlobalData&, const UString&, int startOffset, Vector<int, 32>* ovector = 0); + JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>* ovector = 0); unsigned numSubpatterns() const { return m_numSubpatterns; } bool hasCode() @@ -72,7 +72,7 @@ namespace JSC { return Structure::create(globalData, globalObject, prototype, TypeInfo(LeafType, 0), &s_info); } - static JS_EXPORTDATA const ClassInfo s_info; + static const ClassInfo s_info; RegExpKey key() { return RegExpKey(m_flags, m_patternString); } diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 05832ed0c..53e880e70 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -97,9 +97,18 @@ const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, C @end */ +RegExpResult& RegExpResult::operator=(const RegExpConstructorPrivate& rhs) +{ + this->input = rhs.input; + this->ovector = rhs.lastOvector(); + this->lastNumSubPatterns = rhs.lastNumSubPatterns; + + return *this; +} + + RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure) : InternalFunction(globalObject, structure) - , d(adoptPtr(new RegExpConstructorPrivate)) { } @@ -122,27 +131,14 @@ void RegExpConstructor::destroy(JSCell* cell) RegExpMatchesArray::RegExpMatchesArray(ExecState* exec) : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure()) + , m_didFillArrayInstance(false) { } -void RegExpMatchesArray::finishCreation(JSGlobalData& globalData, RegExpConstructorPrivate* data) +void RegExpMatchesArray::finishCreation(JSGlobalData& globalData, const RegExpConstructorPrivate& data) { - Base::finishCreation(globalData, data->lastNumSubPatterns + 1); - RegExpConstructorPrivate* d = new RegExpConstructorPrivate; - d->input = data->lastInput; - d->lastInput = data->lastInput; - d->lastNumSubPatterns = data->lastNumSubPatterns; - unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector - d->lastOvector().resize(offsetVectorSize); - memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int)); - // d->multiline is not needed, and remains uninitialized - - setSubclassData(d); -} - -RegExpMatchesArray::~RegExpMatchesArray() -{ - delete static_cast<RegExpConstructorPrivate*>(subclassData()); + Base::finishCreation(globalData, data.lastNumSubPatterns + 1); + m_regExpResult = data; } void RegExpMatchesArray::destroy(JSCell* cell) @@ -152,65 +148,61 @@ void RegExpMatchesArray::destroy(JSCell* cell) void RegExpMatchesArray::fillArrayInstance(ExecState* exec) { - RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(subclassData()); - ASSERT(d); - - unsigned lastNumSubpatterns = d->lastNumSubPatterns; + unsigned lastNumSubpatterns = m_regExpResult.lastNumSubPatterns; for (unsigned i = 0; i <= lastNumSubpatterns; ++i) { - int start = d->lastOvector()[2 * i]; + int start = m_regExpResult.ovector[2 * i]; if (start >= 0) - JSArray::putByIndex(this, exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start)); + JSArray::putByIndex(this, exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start)); else JSArray::putByIndex(this, exec, i, jsUndefined()); } PutPropertySlot slot; - JSArray::put(this, exec, exec->propertyNames().index, jsNumber(d->lastOvector()[0]), slot); - JSArray::put(this, exec, exec->propertyNames().input, jsString(exec, d->input), slot); + JSArray::put(this, exec, exec->propertyNames().index, jsNumber(m_regExpResult.ovector[0]), slot); + JSArray::put(this, exec, exec->propertyNames().input, jsString(exec, m_regExpResult.input), slot); - delete d; - setSubclassData(0); + m_didFillArrayInstance = true; } JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const { - return RegExpMatchesArray::create(exec, d.get()); + return RegExpMatchesArray::create(exec, d); } JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const { - if (!d->lastOvector().isEmpty() && i <= d->lastNumSubPatterns) { - int start = d->lastOvector()[2 * i]; + if (!d.lastOvector().isEmpty() && i <= d.lastNumSubPatterns) { + int start = d.lastOvector()[2 * i]; if (start >= 0) - return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start); + return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start); } return jsEmptyString(exec); } JSValue RegExpConstructor::getLastParen(ExecState* exec) const { - unsigned i = d->lastNumSubPatterns; + unsigned i = d.lastNumSubPatterns; if (i > 0) { - ASSERT(!d->lastOvector().isEmpty()); - int start = d->lastOvector()[2 * i]; + ASSERT(!d.lastOvector().isEmpty()); + int start = d.lastOvector()[2 * i]; if (start >= 0) - return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start); + return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start); } return jsEmptyString(exec); } JSValue RegExpConstructor::getLeftContext(ExecState* exec) const { - if (!d->lastOvector().isEmpty()) - return jsSubstring(exec, d->lastInput, 0, d->lastOvector()[0]); + if (!d.lastOvector().isEmpty()) + return jsSubstring(exec, d.lastInput, 0, d.lastOvector()[0]); return jsEmptyString(exec); } JSValue RegExpConstructor::getRightContext(ExecState* exec) const { - if (!d->lastOvector().isEmpty()) - return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.length() - d->lastOvector()[1]); + if (!d.lastOvector().isEmpty()) + return jsSubstring(exec, d.lastInput, d.lastOvector()[1], d.lastInput.length() - d.lastOvector()[1]); return jsEmptyString(exec); } @@ -306,7 +298,7 @@ void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& pro void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setInput(value.toString(exec)); + asRegExpConstructor(baseObject)->setInput(value.toString(exec)->value(exec)); } void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value) @@ -331,13 +323,13 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A return asObject(arg0); } - UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); + UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec)->value(exec); if (exec->hadException()) return 0; RegExpFlags flags = NoFlags; if (!arg1.isUndefined()) { - flags = regExpFlags(arg1.toString(exec)); + flags = regExpFlags(arg1.toString(exec)->value(exec)); if (exec->hadException()) return 0; if (flags == InvalidFlags) @@ -377,24 +369,24 @@ CallType RegExpConstructor::getCallData(JSCell*, CallData& callData) void RegExpConstructor::setInput(const UString& input) { - d->input = input; + d.input = input; } const UString& RegExpConstructor::input() const { // Can detect a distinct initial state that is invisible to JavaScript, by checking for null // state (since jsString turns null strings to empty strings). - return d->input; + return d.input; } void RegExpConstructor::setMultiline(bool multiline) { - d->multiline = multiline; + d.multiline = multiline; } bool RegExpConstructor::multiline() const { - return d->multiline; + return d.multiline; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h index 0a43da70a..08a96b544 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.h +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h @@ -55,6 +55,21 @@ namespace JSC { unsigned lastOvectorIndex : 1; }; + struct RegExpResult { + WTF_MAKE_FAST_ALLOCATED; + public: + RegExpResult() + : lastNumSubPatterns(0) + { + } + + RegExpResult& operator=(const RegExpConstructorPrivate&); + + UString input; + unsigned lastNumSubPatterns; + Vector<int, 32> ovector; + }; + class RegExpConstructor : public InternalFunction { public: typedef InternalFunction Base; @@ -102,7 +117,7 @@ namespace JSC { static ConstructType getConstructData(JSCell*, ConstructData&); static CallType getCallData(JSCell*, CallData&); - OwnPtr<RegExpConstructorPrivate> d; + RegExpConstructorPrivate d; }; RegExpConstructor* asRegExpConstructor(JSValue); @@ -122,20 +137,20 @@ namespace JSC { */ ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) { - position = r->match(globalData, s, startOffset, &d->tempOvector()); + position = r->match(globalData, s, startOffset, &d.tempOvector()); if (ovector) - *ovector = d->tempOvector().data(); + *ovector = d.tempOvector().data(); if (position != -1) { - ASSERT(!d->tempOvector().isEmpty()); + ASSERT(!d.tempOvector().isEmpty()); - length = d->tempOvector()[1] - d->tempOvector()[0]; + length = d.tempOvector()[1] - d.tempOvector()[0]; - d->input = s; - d->lastInput = s; - d->changeLastOvector(); - d->lastNumSubPatterns = r->numSubpatterns(); + d.input = s; + d.lastInput = s; + d.changeLastOvector(); + d.lastNumSubPatterns = r->numSubpatterns(); } } diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h index a0a8a8e98..c34920d8d 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -31,30 +31,29 @@ namespace JSC { public: typedef JSArray Base; - static RegExpMatchesArray* create(ExecState* exec, RegExpConstructorPrivate* ctorPrivate) + static RegExpMatchesArray* create(ExecState* exec, const RegExpConstructorPrivate& ctorPrivate) { RegExpMatchesArray* regExp = new (NotNull, allocateCell<RegExpMatchesArray>(*exec->heap())) RegExpMatchesArray(exec); regExp->finishCreation(exec->globalData(), ctorPrivate); return regExp; } - ~RegExpMatchesArray(); static void destroy(JSCell*); - static JS_EXPORTDATA const ClassInfo s_info; - + static const ClassInfo s_info; + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } - + protected: - void finishCreation(JSGlobalData&, RegExpConstructorPrivate* data); + void finishCreation(JSGlobalData&, const RegExpConstructorPrivate& data); private: static bool getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot); } @@ -62,7 +61,7 @@ namespace JSC { static bool getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot); } @@ -70,7 +69,7 @@ namespace JSC { static bool getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); return JSArray::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); } @@ -78,7 +77,7 @@ namespace JSC { static void put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); JSArray::put(thisObject, exec, propertyName, v, slot); } @@ -86,7 +85,7 @@ namespace JSC { static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); JSArray::putByIndex(thisObject, exec, propertyName, v); } @@ -94,7 +93,7 @@ namespace JSC { static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); return JSArray::deleteProperty(thisObject, exec, propertyName); } @@ -102,7 +101,7 @@ namespace JSC { static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); return JSArray::deletePropertyByIndex(thisObject, exec, propertyName); } @@ -110,12 +109,15 @@ namespace JSC { static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - if (thisObject->subclassData()) + if (!thisObject->m_didFillArrayInstance) thisObject->fillArrayInstance(exec); JSArray::getOwnPropertyNames(thisObject, exec, arr, mode); } void fillArrayInstance(ExecState*); + + RegExpResult m_regExpResult; + bool m_didFillArrayInstance; }; } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 4553f7ad0..4c192ff90 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -231,7 +231,7 @@ JSValue RegExpObject::exec(ExecState* exec) bool RegExpObject::match(ExecState* exec) { RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - UString input = exec->argument(0).toString(exec); + UString input = exec->argument(0).toString(exec)->value(exec); JSGlobalData* globalData = &exec->globalData(); if (!regExp()->global()) { int position; diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index 4e84d3831..081a7f111 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -75,8 +75,8 @@ namespace JSC { } protected: - RegExpObject(JSGlobalObject*, Structure*, RegExp*); - void finishCreation(JSGlobalObject*); + JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*); static void destroy(JSCell*); static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 6c79f9428..9074e97c3 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -110,13 +110,13 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another.")); regExp = asRegExpObject(arg0)->regExp(); } else { - UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec); + UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); RegExpFlags flags = NoFlags; if (!arg1.isUndefined()) { - flags = regExpFlags(arg1.toString(exec)); + flags = regExpFlags(arg1.toString(exec)->value(exec)); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (flags == InvalidFlags) @@ -153,7 +153,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec) postfix[index++] = 'i'; if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec)) postfix[index] = 'm'; - UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec); + UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix)); } diff --git a/Source/JavaScriptCore/runtime/SamplingCounter.h b/Source/JavaScriptCore/runtime/SamplingCounter.h index 664b0280e..329a5cfd3 100644 --- a/Source/JavaScriptCore/runtime/SamplingCounter.h +++ b/Source/JavaScriptCore/runtime/SamplingCounter.h @@ -46,7 +46,7 @@ public: m_counter += count; } - static void dump(); + JS_EXPORT_PRIVATE static void dump(); int64_t* addressOfCounter() { return &m_counter; } @@ -74,7 +74,7 @@ protected: AbstractSamplingCounter** m_referer; // Null object used to detect end of static chain. static AbstractSamplingCounter s_abstractSamplingCounterChainEnd; - static AbstractSamplingCounter* s_abstractSamplingCounterChain; + JS_EXPORTDATA static AbstractSamplingCounter* s_abstractSamplingCounterChain; static bool s_completed; }; diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h index 9c6ed9a32..cd8e63095 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.h +++ b/Source/JavaScriptCore/runtime/SmallStrings.h @@ -60,7 +60,7 @@ namespace JSC { return m_singleCharacterStrings[character]; } - StringImpl* singleCharacterStringRep(unsigned char character); + JS_EXPORT_PRIVATE StringImpl* singleCharacterStringRep(unsigned char character); void finalizeSmallStrings(); void clear(); @@ -72,8 +72,8 @@ namespace JSC { private: static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; - void createEmptyString(JSGlobalData*); - void createSingleCharacterString(JSGlobalData*, unsigned char); + JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*); + JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char); JSString* m_emptyString; JSString* m_singleCharacterStrings[singleCharacterStringCount]; diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp index d2f75a060..e03a87f03 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.cpp +++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp @@ -95,10 +95,7 @@ static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* ex if (!exec->argumentCount()) return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure())); - JSString* string = exec->argument(0).isString() - ? asString(exec->argument(0)) - : jsString(exec, exec->argument(0).toString(exec)); - return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), string)); + return JSValue::encode(StringObject::create(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec))); } ConstructType StringConstructor::getConstructData(JSCell*, ConstructData& constructData) @@ -111,7 +108,7 @@ static EncodedJSValue JSC_HOST_CALL callStringConstructor(ExecState* exec) { if (!exec->argumentCount()) return JSValue::encode(jsEmptyString(exec)); - return JSValue::encode(jsString(exec, exec->argument(0).toString(exec))); + return JSValue::encode(exec->argument(0).toString(exec)); } CallType StringConstructor::getCallData(JSCell*, CallData& callData) diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index 528668691..248c71601 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -64,9 +64,9 @@ namespace JSC { } protected: - void finishCreation(JSGlobalData&, JSString*); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSString*); static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; - StringObject(JSGlobalData&, Structure*); + JS_EXPORT_PRIVATE StringObject(JSGlobalData&, Structure*); }; StringObject* asStringObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index 740916a69..63c00e27e 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -170,9 +170,10 @@ static inline JSString* jsStringWithReuse(ExecState* exec, JSValue originalValue return jsString(exec, string); } +template <typename CharType> static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i) { - Vector<UChar> substitutedReplacement; + Vector<CharType> substitutedReplacement; int offset = 0; do { if (i + 1 == replacement.length()) @@ -182,7 +183,7 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem if (ref == '$') { // "$$" -> "$" ++i; - substitutedReplacement.append(replacement.characters() + offset, i - offset); + substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset); offset = i + 1; continue; } @@ -222,15 +223,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem continue; if (i - offset) - substitutedReplacement.append(replacement.characters() + offset, i - offset); + substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, i - offset); i += 1 + advance; offset = i + 1; if (backrefStart >= 0) - substitutedReplacement.append(source.characters() + backrefStart, backrefLength); + substitutedReplacement.append(source.getCharacters<CharType>() + backrefStart, backrefLength); } while ((i = replacement.find('$', i + 1)) != notFound); if (replacement.length() - offset) - substitutedReplacement.append(replacement.characters() + offset, replacement.length() - offset); + substitutedReplacement.append(replacement.getCharacters<CharType>() + offset, replacement.length() - offset); substitutedReplacement.shrinkToFit(); return UString::adopt(substitutedReplacement); @@ -239,8 +240,11 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) { size_t i = replacement.find('$', 0); - if (UNLIKELY(i != notFound)) - return substituteBackreferencesSlow(replacement, source, ovector, reg, i); + if (UNLIKELY(i != notFound)) { + if (replacement.is8Bit() && source.is8Bit()) + return substituteBackreferencesSlow<LChar>(replacement, source, ovector, reg, i); + return substituteBackreferencesSlow<UChar>(replacement, source, ovector, reg, i); + } return replacement; } @@ -398,13 +402,54 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J return jsString(exec, impl.release()); } +static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const UString& source, RegExp* regExp) +{ + int lastIndex = 0; + unsigned startPosition = 0; + + Vector<StringRange, 16> sourceRanges; + JSGlobalData* globalData = &exec->globalData(); + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); + unsigned sourceLen = source.length(); + + while (true) { + int matchIndex; + int matchLen = 0; + int* ovector; + regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); + if (matchIndex < 0) + break; + + if (lastIndex < matchIndex) + sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + + lastIndex = matchIndex + matchLen; + startPosition = lastIndex; + + // special case of empty match + if (!matchLen) { + startPosition++; + if (startPosition > sourceLen) + break; + } + } + + if (!lastIndex) + return JSValue::encode(string); + + if (static_cast<unsigned>(lastIndex) < sourceLen) + sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex)); + + return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size())); +} + static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSString* string, JSValue searchValue, JSValue replaceValue) { UString replacementString; CallData callData; CallType callType = getCallData(replaceValue, callData); if (callType == CallTypeNone) - replacementString = replaceValue.toString(exec); + replacementString = replaceValue.toString(exec)->value(exec); const UString& source = string->value(exec); unsigned sourceLen = source.length(); @@ -413,45 +458,10 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS RegExp* regExp = asRegExpObject(searchValue)->regExp(); bool global = regExp->global(); - RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - - // Optimization for substring removal (replace with empty). - if (global && callType == CallTypeNone && !replacementString.length()) { - int lastIndex = 0; - unsigned startPosition = 0; - - Vector<StringRange, 16> sourceRanges; - JSGlobalData* globalData = &exec->globalData(); - while (true) { - int matchIndex; - int matchLen = 0; - int* ovector; - regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) - break; - - if (lastIndex < matchIndex) - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); - - lastIndex = matchIndex + matchLen; - startPosition = lastIndex; - - // special case of empty match - if (!matchLen) { - startPosition++; - if (startPosition > sourceLen) - break; - } - } - - if (!lastIndex) - return JSValue::encode(string); - - if (static_cast<unsigned>(lastIndex) < sourceLen) - sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex)); + if (global && callType == CallTypeNone && !replacementString.length()) + return removeUsingRegExpSearch(exec, string, source, regExp); - return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size())); - } + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int lastIndex = 0; unsigned startPosition = 0; @@ -496,10 +506,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS cachedCall.setThis(jsUndefined()); JSValue result = cachedCall.call(); - if (LIKELY(result.isString())) - replacements.append(asString(result)->value(exec)); - else - replacements.append(result.toString(cachedCall.newCallFrame(exec))); + replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec)); if (exec->hadException()) break; @@ -541,10 +548,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS cachedCall.setThis(jsUndefined()); JSValue result = cachedCall.call(); - if (LIKELY(result.isString())) - replacements.append(asString(result)->value(exec)); - else - replacements.append(result.toString(cachedCall.newCallFrame(exec))); + replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec)); if (exec->hadException()) break; @@ -588,7 +592,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS args.append(jsNumber(completeMatchStart)); args.append(string); - replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)); + replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec)); if (exec->hadException()) break; } else { @@ -627,7 +631,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue) { const UString& string = jsString->value(exec); - UString searchString = searchValue.toString(exec); + UString searchString = searchValue.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -647,7 +651,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS return JSValue::encode(jsUndefined()); } - UString replaceString = replaceValue.toString(exec); + UString replaceString = replaceValue.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -659,12 +663,9 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - if (!thisValue.isString()) { - if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible - return throwVMTypeError(exec); - thisValue = jsString(exec, thisValue.toString(exec)); - } - JSString* string = asString(thisValue); + if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible + return throwVMTypeError(exec); + JSString* string = thisValue.toString(exec); JSValue searchValue = exec->argument(0); JSValue replaceValue = exec->argument(1); @@ -692,7 +693,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); unsigned len = s.length(); JSValue a0 = exec->argument(0); if (a0.isUInt32()) { @@ -712,7 +713,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); unsigned len = s.length(); JSValue a0 = exec->argument(0); if (a0.isUInt32()) { @@ -733,12 +734,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec) EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - if (thisValue.isString() && (exec->argumentCount() == 1)) { - JSValue v = exec->argument(0); - return JSValue::encode(v.isString() - ? jsString(exec, asString(thisValue), asString(v)) - : jsString(exec, asString(thisValue), jsString(&exec->globalData(), v.toString(exec)))); - } + if (thisValue.isString() && (exec->argumentCount() == 1)) + return JSValue::encode(jsString(exec, asString(thisValue), exec->argument(0).toString(exec))); + if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); return JSValue::encode(jsStringFromArguments(exec, thisValue)); @@ -749,12 +747,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); - UString u2 = a0.toString(exec); + UString u2 = a0.toString(exec)->value(exec); int pos; if (a1.isUndefined()) pos = 0; @@ -780,13 +778,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); - UString u2 = a0.toString(exec); + UString u2 = a0.toString(exec)->value(exec); double dpos = a1.toIntegerPreserveNaN(exec); if (dpos < 0) dpos = 0; @@ -804,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSGlobalData* globalData = &exec->globalData(); JSValue a0 = exec->argument(0); @@ -819,7 +817,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) * replaced with the result of the expression new RegExp(regexp). * Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string. */ - reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags); + reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags); + if (!reg->isValid()) + return throwVMError(exec, createSyntaxError(exec, reg->errorMessage())); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -854,7 +854,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSGlobalData* globalData = &exec->globalData(); JSValue a0 = exec->argument(0); @@ -869,7 +869,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) * replaced with the result of the expression new RegExp(regexp). * Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string. */ - reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec), NoFlags); + reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags); + if (!reg->isValid()) + return throwVMError(exec, createSyntaxError(exec, reg->errorMessage())); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; @@ -883,7 +885,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); int len = s.length(); JSValue a0 = exec->argument(0); @@ -915,7 +917,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // 2. Let S be the result of calling ToString, giving it the this value as its argument. // 6. Let s be the number of characters in S. - UString input = thisValue.toString(exec); + UString input = thisValue.toString(exec)->value(exec); // 3. Let A be a new array created as if by the expression new Array() // where Array is the standard built-in constructor with that name. @@ -1017,7 +1019,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) } } } else { - UString separator = separatorValue.toString(exec); + UString separator = separatorValue.toString(exec)->value(exec); // 9. If lim == 0, return A. if (!limit) @@ -1104,7 +1106,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec) // CheckObjectCoercible return throwVMTypeError(exec); } else { - uString = thisValue.toString(exec); + uString = thisValue.toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); len = uString.length(); @@ -1134,24 +1136,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec) EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - int len; - JSString* jsString = 0; - UString uString; - if (thisValue.isString()) { - jsString = static_cast<JSString*>(thisValue.asCell()); - len = jsString->length(); - } else if (thisValue.isUndefinedOrNull()) { - // CheckObjectCoercible + if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - } else { - uString = thisValue.toString(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - len = uString.length(); - } + + JSString* jsString = thisValue.toString(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); + int len = jsString->length(); double start = a0.toNumber(exec); double end; @@ -1175,9 +1169,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec) } unsigned substringStart = static_cast<unsigned>(start); unsigned substringLength = static_cast<unsigned>(end) - substringStart; - if (jsString) - return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength)); - return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength)); + return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength)); } EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec) @@ -1185,16 +1177,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec)); + JSString* sVal = thisValue.toString(exec); const UString& s = sVal->value(exec); int sSize = s.length(); if (!sSize) return JSValue::encode(sVal); - StringImpl* ourImpl = s.impl(); + StringImpl* ourImpl = s.impl(); RefPtr<StringImpl> lower = ourImpl->lower(); - if (ourImpl == lower.get()) + if (ourImpl == lower) return JSValue::encode(sVal); return JSValue::encode(jsString(exec, UString(lower.release()))); } @@ -1204,39 +1196,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - JSString* sVal = thisValue.isString() ? asString(thisValue) : jsString(exec, thisValue.toString(exec)); + JSString* sVal = thisValue.toString(exec); const UString& s = sVal->value(exec); int sSize = s.length(); if (!sSize) return JSValue::encode(sVal); - const UChar* sData = s.characters(); - Vector<UChar> buffer(sSize); - - UChar ored = 0; - for (int i = 0; i < sSize; i++) { - UChar c = sData[i]; - ored |= c; - buffer[i] = toASCIIUpper(c); - } - if (!(ored & ~0x7f)) - return JSValue::encode(jsString(exec, UString::adopt(buffer))); - - bool error; - int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error); - if (error) { - buffer.resize(length); - length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error); - if (error) - return JSValue::encode(sVal); - } - if (length == sSize) { - if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0) - return JSValue::encode(sVal); - } else - buffer.resize(length); - return JSValue::encode(jsString(exec, UString::adopt(buffer))); + StringImpl* sImpl = s.impl(); + RefPtr<StringImpl> upper = sImpl->upper(); + if (sImpl == upper) + return JSValue::encode(sVal); + return JSValue::encode(jsString(exec, UString(upper.release()))); } EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec) @@ -1247,10 +1218,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec)))); + return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec)->value(exec)))); } EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec) @@ -1258,7 +1229,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>")); } @@ -1267,7 +1238,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>")); } @@ -1276,7 +1247,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>")); } @@ -1285,7 +1256,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>")); } @@ -1294,7 +1265,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>")); } @@ -1303,7 +1274,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>")); } @@ -1312,7 +1283,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>")); } @@ -1321,7 +1292,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>")); } @@ -1330,7 +1301,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>")); } @@ -1339,9 +1310,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec)->value(exec), "\">", s, "</font>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) @@ -1349,7 +1320,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); uint32_t smallInteger; @@ -1386,7 +1357,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec) return JSValue::encode(jsNontrivialString(exec, impl)); } - return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec)->value(exec), "\">", s, "</font>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec) @@ -1394,9 +1365,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>")); + return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec)->value(exec), "\">", s, "</a>")); } EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) @@ -1404,9 +1375,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec); + UString s = thisValue.toString(exec)->value(exec); JSValue a0 = exec->argument(0); - UString linkText = a0.toString(exec); + UString linkText = a0.toString(exec)->value(exec); unsigned linkTextSize = linkText.length(); unsigned stringSize = s.length(); @@ -1449,7 +1420,7 @@ static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKin { if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwTypeError(exec); - UString str = thisValue.toString(exec); + UString str = thisValue.toString(exec)->value(exec); unsigned left = 0; if (trimKind & TrimLeft) { while (left < str.length() && isTrimWhitespace(str[left])) diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index dda8c73e9..f387cf283 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -401,17 +401,26 @@ Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Stru return transition; } -Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure) +Structure* Structure::attributeChangeTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes) { - Structure* transition = create(globalData, structure); + if (!structure->isUncacheableDictionary()) { + Structure* transition = create(globalData, structure); - // Don't set m_offset, as one can not transition to this. + // Don't set m_offset, as one can not transition to this. - structure->materializePropertyMapIfNecessary(globalData); - transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition); - transition->pin(); + structure->materializePropertyMapIfNecessary(globalData); + transition->m_propertyTable = structure->copyPropertyTableForPinning(globalData, transition); + transition->pin(); + + structure = transition; + } - return transition; + ASSERT(structure->m_propertyTable); + PropertyMapEntry* entry = structure->m_propertyTable->find(propertyName.impl()).first; + ASSERT(entry); + entry->attributes = attributes; + + return structure; } Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind) diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 70e968014..ced296856 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -84,12 +84,12 @@ namespace JSC { public: static void dumpStatistics(); - static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); - static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset); - static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype); - static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&); - static Structure* getterSetterTransition(JSGlobalData&, Structure*); + JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype); + JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&); + static Structure* attributeChangeTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes); static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*); static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*); static Structure* sealTransition(JSGlobalData&, Structure*); @@ -106,7 +106,7 @@ namespace JSC { static void destroy(JSCell*); // These should be used with caution. - size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); + JS_EXPORT_PRIVATE size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName); void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); } @@ -136,7 +136,7 @@ namespace JSC { size_t get(JSGlobalData&, const Identifier& propertyName); size_t get(JSGlobalData&, const UString& name); - size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue); + JS_EXPORT_PRIVATE size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue); size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) { ASSERT(!propertyName.isNull()); @@ -151,7 +151,7 @@ namespace JSC { bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; } - void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName); + JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName); void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; } void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. @@ -196,7 +196,7 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; private: - Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*); + JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*); Structure(JSGlobalData&); Structure(JSGlobalData&, const Structure*); @@ -226,7 +226,7 @@ namespace JSC { PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner); PassOwnPtr<PropertyTable> copyPropertyTableForPinning(JSGlobalData&, Structure* owner); - void materializePropertyMap(JSGlobalData&); + JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&); void materializePropertyMapIfNecessary(JSGlobalData& globalData) { ASSERT(structure()->classInfo() == &s_info); diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.h b/Source/JavaScriptCore/runtime/TimeoutChecker.h index 5925641f8..89d6158cc 100644 --- a/Source/JavaScriptCore/runtime/TimeoutChecker.h +++ b/Source/JavaScriptCore/runtime/TimeoutChecker.h @@ -57,9 +57,9 @@ namespace JSC { --m_startCount; } - void reset(); + JS_EXPORT_PRIVATE void reset(); - bool didTimeOut(ExecState*); + JS_EXPORT_PRIVATE bool didTimeOut(ExecState*); private: unsigned m_timeoutInterval; diff --git a/Source/JavaScriptCore/runtime/UString.h b/Source/JavaScriptCore/runtime/UString.h index c05ae5081..668eb0489 100644 --- a/Source/JavaScriptCore/runtime/UString.h +++ b/Source/JavaScriptCore/runtime/UString.h @@ -33,18 +33,18 @@ public: UString() { } // Construct a string with UTF-16 data. - UString(const UChar* characters, unsigned length); + JS_EXPORT_PRIVATE UString(const UChar* characters, unsigned length); // Construct a string with UTF-16 data, from a null-terminated source. - UString(const UChar*); + JS_EXPORT_PRIVATE UString(const UChar*); // Construct a string with latin1 data. UString(const LChar* characters, unsigned length); - UString(const char* characters, unsigned length); + JS_EXPORT_PRIVATE UString(const char* characters, unsigned length); // Construct a string with latin1 data, from a null-terminated source. UString(const LChar* characters); - UString(const char* characters); + JS_EXPORT_PRIVATE UString(const char* characters); // Construct a string referencing an existing StringImpl. UString(StringImpl* impl) : m_impl(impl) { } @@ -99,9 +99,9 @@ public: bool is8Bit() const { return m_impl->is8Bit(); } - CString ascii() const; + JS_EXPORT_PRIVATE CString ascii() const; CString latin1() const; - CString utf8(bool strict = false) const; + JS_EXPORT_PRIVATE CString utf8(bool strict = false) const; UChar operator[](unsigned index) const { @@ -112,11 +112,11 @@ public: return m_impl->characters16()[index]; } - static UString number(int); - static UString number(unsigned); - static UString number(long); + JS_EXPORT_PRIVATE static UString number(int); + JS_EXPORT_PRIVATE static UString number(unsigned); + JS_EXPORT_PRIVATE static UString number(long); static UString number(long long); - static UString number(double); + JS_EXPORT_PRIVATE static UString number(double); // Find a single character or string, also with match function & latin1 forms. size_t find(UChar c, unsigned start = 0) const @@ -132,25 +132,17 @@ public: size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } - UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; + JS_EXPORT_PRIVATE UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; private: RefPtr<StringImpl> m_impl; }; template<> -inline const LChar* UString::getCharacters<LChar>() const -{ - ASSERT(is8Bit()); - return characters8(); -} +inline const LChar* UString::getCharacters<LChar>() const { return characters8(); } template<> -inline const UChar* UString::getCharacters<UChar>() const -{ - ASSERT(!is8Bit()); - return characters16(); -} +inline const UChar* UString::getCharacters<UChar>() const { return characters(); } NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2); @@ -189,10 +181,10 @@ inline bool operator!=(const UString& s1, const UString& s2) return !JSC::operator==(s1, s2); } -bool operator<(const UString& s1, const UString& s2); -bool operator>(const UString& s1, const UString& s2); +JS_EXPORT_PRIVATE bool operator<(const UString& s1, const UString& s2); +JS_EXPORT_PRIVATE bool operator>(const UString& s1, const UString& s2); -bool operator==(const UString& s1, const char* s2); +JS_EXPORT_PRIVATE bool operator==(const UString& s1, const char* s2); inline bool operator!=(const UString& s1, const char* s2) { diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h index 525fc0926..a7bd7a100 100644 --- a/Source/JavaScriptCore/runtime/WriteBarrier.h +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -40,8 +40,8 @@ class JSGlobalObject; template<class T> class WriteBarrierBase; template<> class WriteBarrierBase<JSValue>; -void slowValidateCell(JSCell*); -void slowValidateCell(JSGlobalObject*); +JS_EXPORT_PRIVATE void slowValidateCell(JSCell*); +JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*); #if ENABLE(GC_VALIDATION) template<class T> inline void validateCell(T cell) |