summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/ArgList.h7
-rw-r--r--JavaScriptCore/runtime/Arguments.cpp25
-rw-r--r--JavaScriptCore/runtime/Arguments.h22
-rw-r--r--JavaScriptCore/runtime/ArrayConstructor.cpp14
-rw-r--r--JavaScriptCore/runtime/ArrayConstructor.h2
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp72
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.h3
-rw-r--r--JavaScriptCore/runtime/BatchedTransitionOptimizer.h2
-rw-r--r--JavaScriptCore/runtime/BooleanConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/BooleanConstructor.h2
-rw-r--r--JavaScriptCore/runtime/BooleanObject.cpp2
-rw-r--r--JavaScriptCore/runtime/BooleanObject.h7
-rw-r--r--JavaScriptCore/runtime/BooleanPrototype.cpp6
-rw-r--r--JavaScriptCore/runtime/BooleanPrototype.h2
-rw-r--r--JavaScriptCore/runtime/CallData.h4
-rw-r--r--JavaScriptCore/runtime/Collector.cpp275
-rw-r--r--JavaScriptCore/runtime/Collector.h14
-rw-r--r--JavaScriptCore/runtime/CommonIdentifiers.h12
-rw-r--r--JavaScriptCore/runtime/Completion.cpp25
-rw-r--r--JavaScriptCore/runtime/ConstructData.h4
-rw-r--r--JavaScriptCore/runtime/DateConstructor.cpp4
-rw-r--r--JavaScriptCore/runtime/DateConstructor.h2
-rw-r--r--JavaScriptCore/runtime/DateInstance.cpp11
-rw-r--r--JavaScriptCore/runtime/DateInstance.h5
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp84
-rw-r--r--JavaScriptCore/runtime/DatePrototype.h5
-rw-r--r--JavaScriptCore/runtime/Error.cpp6
-rw-r--r--JavaScriptCore/runtime/Error.h1
-rw-r--r--JavaScriptCore/runtime/ErrorConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/ErrorConstructor.h2
-rw-r--r--JavaScriptCore/runtime/ErrorInstance.cpp2
-rw-r--r--JavaScriptCore/runtime/ErrorInstance.h2
-rw-r--r--JavaScriptCore/runtime/ErrorPrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/ErrorPrototype.h2
-rw-r--r--JavaScriptCore/runtime/ExceptionHelpers.cpp15
-rw-r--r--JavaScriptCore/runtime/ExceptionHelpers.h1
-rw-r--r--JavaScriptCore/runtime/Executable.cpp280
-rw-r--r--JavaScriptCore/runtime/Executable.h356
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.cpp38
-rw-r--r--JavaScriptCore/runtime/FunctionConstructor.h6
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.cpp15
-rw-r--r--JavaScriptCore/runtime/FunctionPrototype.h4
-rw-r--r--JavaScriptCore/runtime/GetterSetter.cpp42
-rw-r--r--JavaScriptCore/runtime/GetterSetter.h7
-rw-r--r--JavaScriptCore/runtime/GlobalEvalFunction.cpp2
-rw-r--r--JavaScriptCore/runtime/GlobalEvalFunction.h7
-rw-r--r--JavaScriptCore/runtime/Identifier.h2
-rw-r--r--JavaScriptCore/runtime/InternalFunction.cpp2
-rw-r--r--JavaScriptCore/runtime/InternalFunction.h6
-rw-r--r--JavaScriptCore/runtime/JSAPIValueWrapper.cpp36
-rw-r--r--JavaScriptCore/runtime/JSAPIValueWrapper.h7
-rw-r--r--JavaScriptCore/runtime/JSActivation.cpp14
-rw-r--r--JavaScriptCore/runtime/JSActivation.h17
-rw-r--r--JavaScriptCore/runtime/JSArray.cpp203
-rw-r--r--JavaScriptCore/runtime/JSArray.h128
-rw-r--r--JavaScriptCore/runtime/JSByteArray.cpp21
-rw-r--r--JavaScriptCore/runtime/JSByteArray.h5
-rw-r--r--JavaScriptCore/runtime/JSCell.cpp38
-rw-r--r--JavaScriptCore/runtime/JSCell.h134
-rw-r--r--JavaScriptCore/runtime/JSFunction.cpp75
-rw-r--r--JavaScriptCore/runtime/JSFunction.h57
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp26
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h15
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.cpp27
-rw-r--r--JavaScriptCore/runtime/JSGlobalObject.h77
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp14
-rw-r--r--JavaScriptCore/runtime/JSNotAnObject.cpp8
-rw-r--r--JavaScriptCore/runtime/JSNotAnObject.h3
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.cpp4
-rw-r--r--JavaScriptCore/runtime/JSNumberCell.h2
-rw-r--r--JavaScriptCore/runtime/JSONObject.cpp180
-rw-r--r--JavaScriptCore/runtime/JSONObject.h5
-rw-r--r--JavaScriptCore/runtime/JSObject.cpp202
-rw-r--r--JavaScriptCore/runtime/JSObject.h104
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.cpp36
-rw-r--r--JavaScriptCore/runtime/JSPropertyNameIterator.h7
-rw-r--r--JavaScriptCore/runtime/JSString.cpp27
-rw-r--r--JavaScriptCore/runtime/JSString.h25
-rw-r--r--JavaScriptCore/runtime/JSType.h1
-rw-r--r--JavaScriptCore/runtime/JSTypeInfo.h (renamed from JavaScriptCore/runtime/TypeInfo.h)14
-rw-r--r--JavaScriptCore/runtime/JSValue.cpp5
-rw-r--r--JavaScriptCore/runtime/JSValue.h32
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.cpp15
-rw-r--r--JavaScriptCore/runtime/JSVariableObject.h10
-rw-r--r--JavaScriptCore/runtime/JSWrapperObject.h22
-rw-r--r--JavaScriptCore/runtime/LiteralParser.cpp3
-rw-r--r--JavaScriptCore/runtime/LiteralParser.h2
-rw-r--r--JavaScriptCore/runtime/Lookup.h60
-rw-r--r--JavaScriptCore/runtime/MarkStack.cpp3
-rw-r--r--JavaScriptCore/runtime/MarkStack.h46
-rw-r--r--JavaScriptCore/runtime/MarkStackSymbian.cpp44
-rw-r--r--JavaScriptCore/runtime/MarkStackWin.cpp6
-rw-r--r--JavaScriptCore/runtime/MathObject.cpp14
-rw-r--r--JavaScriptCore/runtime/MathObject.h5
-rw-r--r--JavaScriptCore/runtime/NativeErrorConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/NativeErrorConstructor.h2
-rw-r--r--JavaScriptCore/runtime/NativeErrorPrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/NativeErrorPrototype.h2
-rw-r--r--JavaScriptCore/runtime/NumberConstructor.cpp7
-rw-r--r--JavaScriptCore/runtime/NumberConstructor.h5
-rw-r--r--JavaScriptCore/runtime/NumberObject.cpp2
-rw-r--r--JavaScriptCore/runtime/NumberObject.h14
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/NumberPrototype.h2
-rw-r--r--JavaScriptCore/runtime/NumericStrings.h74
-rw-r--r--JavaScriptCore/runtime/ObjectConstructor.cpp223
-rw-r--r--JavaScriptCore/runtime/ObjectConstructor.h2
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.cpp21
-rw-r--r--JavaScriptCore/runtime/ObjectPrototype.h8
-rw-r--r--JavaScriptCore/runtime/Operations.h13
-rw-r--r--JavaScriptCore/runtime/PropertyDescriptor.cpp195
-rw-r--r--JavaScriptCore/runtime/PropertyDescriptor.h80
-rw-r--r--JavaScriptCore/runtime/PropertyMapHashTable.h1
-rw-r--r--JavaScriptCore/runtime/PropertyNameArray.h2
-rw-r--r--JavaScriptCore/runtime/PropertySlot.cpp3
-rw-r--r--JavaScriptCore/runtime/PrototypeFunction.cpp2
-rw-r--r--JavaScriptCore/runtime/PrototypeFunction.h2
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp10
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.h5
-rw-r--r--JavaScriptCore/runtime/RegExpMatchesArray.h11
-rw-r--r--JavaScriptCore/runtime/RegExpObject.cpp7
-rw-r--r--JavaScriptCore/runtime/RegExpObject.h7
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp15
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.h2
-rw-r--r--JavaScriptCore/runtime/ScopeChain.cpp6
-rw-r--r--JavaScriptCore/runtime/ScopeChain.h17
-rw-r--r--JavaScriptCore/runtime/SmallStrings.cpp10
-rw-r--r--JavaScriptCore/runtime/SmallStrings.h6
-rw-r--r--JavaScriptCore/runtime/StringConstructor.cpp2
-rw-r--r--JavaScriptCore/runtime/StringConstructor.h2
-rw-r--r--JavaScriptCore/runtime/StringObject.cpp32
-rw-r--r--JavaScriptCore/runtime/StringObject.h14
-rw-r--r--JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h4
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp27
-rw-r--r--JavaScriptCore/runtime/StringPrototype.h3
-rw-r--r--JavaScriptCore/runtime/Structure.cpp181
-rw-r--r--JavaScriptCore/runtime/Structure.h112
-rw-r--r--JavaScriptCore/runtime/StructureChain.cpp5
-rw-r--r--JavaScriptCore/runtime/StructureTransitionTable.h159
-rw-r--r--JavaScriptCore/runtime/SymbolTable.h4
-rw-r--r--JavaScriptCore/runtime/TimeoutChecker.cpp25
-rw-r--r--JavaScriptCore/runtime/UString.cpp107
-rw-r--r--JavaScriptCore/runtime/UString.h6
143 files changed, 3425 insertions, 1214 deletions
diff --git a/JavaScriptCore/runtime/ArgList.h b/JavaScriptCore/runtime/ArgList.h
index ab501b6..3227770 100644
--- a/JavaScriptCore/runtime/ArgList.h
+++ b/JavaScriptCore/runtime/ArgList.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008, 2009 Apple Computer, Inc.
+ * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,13 +23,14 @@
#define ArgList_h
#include "Register.h"
-
#include <wtf/HashSet.h>
#include <wtf/Noncopyable.h>
#include <wtf/Vector.h>
namespace JSC {
-
+
+ class MarkStack;
+
class MarkedArgumentBuffer : public Noncopyable {
private:
static const unsigned inlineCapacity = 8;
diff --git a/JavaScriptCore/runtime/Arguments.cpp b/JavaScriptCore/runtime/Arguments.cpp
index ec9c450..86a8f0a 100644
--- a/JavaScriptCore/runtime/Arguments.cpp
+++ b/JavaScriptCore/runtime/Arguments.cpp
@@ -179,6 +179,31 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNa
return JSObject::getOwnPropertySlot(exec, propertyName, slot);
}
+bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
+ if (i < d->numParameters) {
+ descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
+ } else
+ descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
+ descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
+ descriptor.setDescriptor(d->callee, DontEnum);
+ return true;
+ }
+
+ return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
{
if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
index 79fe720..5be84a2 100644
--- a/JavaScriptCore/runtime/Arguments.h
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -28,6 +28,8 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "Interpreter.h"
+#include "ObjectConstructor.h"
+#include "PrototypeFunction.h"
namespace JSC {
@@ -90,6 +92,7 @@ namespace JSC {
void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -113,18 +116,17 @@ namespace JSC {
ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
{
function = callFrame->callee();
-
- CodeBlock* codeBlock = &function->body()->generatedBytecode();
- int numParameters = codeBlock->m_numParameters;
+
+ int numParameters = function->jsExecutable()->parameterCount();
argc = callFrame->argumentCount();
if (argc <= numParameters)
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
else
- argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
+ argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
argc -= 1; // - 1 to skip "this"
- firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
+ firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
}
inline Arguments::Arguments(CallFrame* callFrame)
@@ -137,7 +139,7 @@ namespace JSC {
int numArguments;
getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
- d->numParameters = callee->body()->parameterCount();
+ d->numParameters = callee->jsExecutable()->parameterCount();
d->firstParameterIndex = firstParameterIndex;
d->numArguments = numArguments;
@@ -168,7 +170,7 @@ namespace JSC {
: JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
, d(new ArgumentsData)
{
- ASSERT(!callFrame->callee()->body()->parameterCount());
+ ASSERT(!callFrame->callee()->jsExecutable()->parameterCount());
unsigned numArguments = callFrame->argumentCount() - 1;
@@ -214,8 +216,8 @@ namespace JSC {
{
ASSERT(!d()->registerArray);
- size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
- size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+ size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1;
+ size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars;
size_t numLocals = numVars + numParametersMinusThis;
if (!numLocals)
diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp
index e96bdfc..0237fd4 100644
--- a/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -25,15 +25,19 @@
#include "ArrayConstructor.h"
#include "ArrayPrototype.h"
+#include "Error.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "Lookup.h"
+#include "PrototypeFunction.h"
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
+
+static JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList&);
-ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype)
+ArrayConstructor::ArrayConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
{
// ECMA 15.4.3.1 Array.prototype
@@ -41,6 +45,9 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> struct
// no. of arguments for constructor
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+
+ // ES5
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
}
static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
@@ -82,4 +89,9 @@ CallType ArrayConstructor::getCallData(CallData& callData)
return CallTypeHost;
}
+JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList& args)
+{
+ return jsBoolean(args.at(0).inherits(&JSArray::info));
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ArrayConstructor.h b/JavaScriptCore/runtime/ArrayConstructor.h
index 8300d8c..6d25400 100644
--- a/JavaScriptCore/runtime/ArrayConstructor.h
+++ b/JavaScriptCore/runtime/ArrayConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class ArrayConstructor : public InternalFunction {
public:
- ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*);
+ ArrayConstructor(ExecState*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*);
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 807e59a..7a89447 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -67,7 +67,7 @@ static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JS
namespace JSC {
-static inline bool isNumericCompareFunction(CallType callType, const CallData& callData)
+static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData& callData)
{
if (callType != CallTypeJS)
return false;
@@ -75,10 +75,10 @@ static inline bool isNumericCompareFunction(CallType callType, const CallData& c
#if ENABLE(JIT)
// If the JIT is enabled then we need to preserve the invariant that every
// function with a CodeBlock also has JIT code.
- callData.js.functionBody->jitCode(callData.js.scopeChain);
- CodeBlock& codeBlock = callData.js.functionBody->generatedBytecode();
+ callData.js.functionExecutable->jitCode(exec, callData.js.scopeChain);
+ CodeBlock& codeBlock = callData.js.functionExecutable->generatedBytecode();
#else
- CodeBlock& codeBlock = callData.js.functionBody->bytecode(callData.js.scopeChain);
+ CodeBlock& codeBlock = callData.js.functionExecutable->bytecode(exec, callData.js.scopeChain);
#endif
return codeBlock.isNumericCompareFunction();
@@ -115,7 +115,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a
*/
// ECMA 15.4.4
-ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure)
+ArrayPrototype::ArrayPrototype(NonNullPassRefPtr<Structure> structure)
: JSArray(structure)
{
}
@@ -125,6 +125,11 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope
return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
}
+bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, descriptor);
+}
+
// ------------------------------ Array Functions ----------------------------
// Helper function
@@ -144,10 +149,11 @@ static void putProperty(ExecState* exec, JSObject* obj, const Identifier& proper
JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&JSArray::info))
+ bool isRealArray = isJSArray(&exec->globalData(), thisValue);
+ if (!isRealArray && !thisValue.inherits(&JSArray::info))
return throwError(exec, TypeError);
- JSObject* thisObj = asArray(thisValue);
-
+ JSArray* thisObj = asArray(thisValue);
+
HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) {
if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth)
@@ -158,39 +164,53 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
if (alreadyVisited)
return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
- Vector<UChar, 256> strBuffer;
unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+ unsigned totalSize = length ? length - 1 : 0;
+ Vector<RefPtr<UString::Rep>, 256> strBuffer(length);
for (unsigned k = 0; k < length; k++) {
- if (k >= 1)
- strBuffer.append(',');
- if (!strBuffer.data()) {
- JSObject* error = Error::create(exec, GeneralError, "Out of memory");
- exec->setException(error);
- break;
- }
-
- JSValue element = thisObj->get(exec, k);
+ JSValue element;
+ if (isRealArray && thisObj->canGetIndex(k))
+ element = thisObj->getIndex(k);
+ else
+ element = thisObj->get(exec, k);
+
if (element.isUndefinedOrNull())
continue;
-
+
UString str = element.toString(exec);
- strBuffer.append(str.data(), str.size());
-
+ strBuffer[k] = str.rep();
+ totalSize += str.size();
+
if (!strBuffer.data()) {
JSObject* error = Error::create(exec, GeneralError, "Out of memory");
exec->setException(error);
}
-
+
if (exec->hadException())
break;
}
arrayVisitedElements.remove(thisObj);
- return jsString(exec, UString(strBuffer.data(), strBuffer.data() ? strBuffer.size() : 0));
+ if (!totalSize)
+ return jsEmptyString(exec);
+ Vector<UChar> buffer;
+ buffer.reserveCapacity(totalSize);
+ if (!buffer.data())
+ return throwError(exec, GeneralError, "Out of memory");
+
+ for (unsigned i = 0; i < length; i++) {
+ if (i)
+ buffer.append(',');
+ if (RefPtr<UString::Rep> rep = strBuffer[i])
+ buffer.append(rep->data(), rep->size());
+ }
+ ASSERT(buffer.size() == totalSize);
+ unsigned finalSize = buffer.size();
+ return jsString(exec, UString(buffer.releaseBuffer(), finalSize, false));
}
JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&JSArray::info))
+ if (!thisValue.inherits(&JSArray::info))
return throwError(exec, TypeError);
JSObject* thisObj = asArray(thisValue);
@@ -298,7 +318,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue t
ArgList::const_iterator it = args.begin();
ArgList::const_iterator end = args.end();
while (1) {
- if (curArg.isObject(&JSArray::info)) {
+ if (curArg.inherits(&JSArray::info)) {
unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
JSObject* curObject = curArg.toObject(exec);
for (unsigned k = 0; k < length; ++k) {
@@ -456,7 +476,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thi
CallType callType = function.getCallData(callData);
if (thisObj->classInfo() == &JSArray::info) {
- if (isNumericCompareFunction(callType, callData))
+ if (isNumericCompareFunction(exec, callType, callData))
asArray(thisObj)->sortNumeric(exec, function, callType, callData);
else if (callType != CallTypeNone)
asArray(thisObj)->sort(exec, function, callType, callData);
diff --git a/JavaScriptCore/runtime/ArrayPrototype.h b/JavaScriptCore/runtime/ArrayPrototype.h
index 2165089..e52914c 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.h
+++ b/JavaScriptCore/runtime/ArrayPrototype.h
@@ -28,9 +28,10 @@ namespace JSC {
class ArrayPrototype : public JSArray {
public:
- explicit ArrayPrototype(PassRefPtr<Structure>);
+ explicit ArrayPrototype(NonNullPassRefPtr<Structure>);
bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
index b9f738f..929a5e7 100644
--- a/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
+++ b/JavaScriptCore/runtime/BatchedTransitionOptimizer.h
@@ -38,7 +38,7 @@ namespace JSC {
: m_object(object)
{
if (!m_object->structure()->isDictionary())
- m_object->setStructure(Structure::toDictionaryTransition(m_object->structure()));
+ m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
}
~BatchedTransitionOptimizer()
diff --git a/JavaScriptCore/runtime/BooleanConstructor.cpp b/JavaScriptCore/runtime/BooleanConstructor.cpp
index 9fcba37..b0d8df3 100644
--- a/JavaScriptCore/runtime/BooleanConstructor.cpp
+++ b/JavaScriptCore/runtime/BooleanConstructor.cpp
@@ -28,7 +28,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
-BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
+BooleanConstructor::BooleanConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
{
putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
diff --git a/JavaScriptCore/runtime/BooleanConstructor.h b/JavaScriptCore/runtime/BooleanConstructor.h
index d9f51ab..1d8a26a 100644
--- a/JavaScriptCore/runtime/BooleanConstructor.h
+++ b/JavaScriptCore/runtime/BooleanConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class BooleanConstructor : public InternalFunction {
public:
- BooleanConstructor(ExecState*, PassRefPtr<Structure>, BooleanPrototype*);
+ BooleanConstructor(ExecState*, NonNullPassRefPtr<Structure>, BooleanPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/JavaScriptCore/runtime/BooleanObject.cpp b/JavaScriptCore/runtime/BooleanObject.cpp
index 01f695a..c9b3846 100644
--- a/JavaScriptCore/runtime/BooleanObject.cpp
+++ b/JavaScriptCore/runtime/BooleanObject.cpp
@@ -27,7 +27,7 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
-BooleanObject::BooleanObject(PassRefPtr<Structure> structure)
+BooleanObject::BooleanObject(NonNullPassRefPtr<Structure> structure)
: JSWrapperObject(structure)
{
}
diff --git a/JavaScriptCore/runtime/BooleanObject.h b/JavaScriptCore/runtime/BooleanObject.h
index cfd55fe..28f796a 100644
--- a/JavaScriptCore/runtime/BooleanObject.h
+++ b/JavaScriptCore/runtime/BooleanObject.h
@@ -27,10 +27,15 @@ namespace JSC {
class BooleanObject : public JSWrapperObject {
public:
- explicit BooleanObject(PassRefPtr<Structure>);
+ explicit BooleanObject(NonNullPassRefPtr<Structure>);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ }
};
BooleanObject* asBooleanObject(JSValue);
diff --git a/JavaScriptCore/runtime/BooleanPrototype.cpp b/JavaScriptCore/runtime/BooleanPrototype.cpp
index 703a568..8d338f9 100644
--- a/JavaScriptCore/runtime/BooleanPrototype.cpp
+++ b/JavaScriptCore/runtime/BooleanPrototype.cpp
@@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSVa
// ECMA 15.6.4
-BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+BooleanPrototype::BooleanPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
: BooleanObject(structure)
{
setInternalValue(jsBoolean(false));
@@ -59,7 +59,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSVal
if (thisValue == jsBoolean(true))
return jsNontrivialString(exec, "true");
- if (!thisValue.isObject(&BooleanObject::info))
+ if (!thisValue.inherits(&BooleanObject::info))
return throwError(exec, TypeError);
if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
@@ -74,7 +74,7 @@ JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValu
if (thisValue.isBoolean())
return thisValue;
- if (!thisValue.isObject(&BooleanObject::info))
+ if (!thisValue.inherits(&BooleanObject::info))
return throwError(exec, TypeError);
return asBooleanObject(thisValue)->internalValue();
diff --git a/JavaScriptCore/runtime/BooleanPrototype.h b/JavaScriptCore/runtime/BooleanPrototype.h
index 16f80b5..cc69b3f 100644
--- a/JavaScriptCore/runtime/BooleanPrototype.h
+++ b/JavaScriptCore/runtime/BooleanPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class BooleanPrototype : public BooleanObject {
public:
- BooleanPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ BooleanPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/CallData.h b/JavaScriptCore/runtime/CallData.h
index d5b0172..24c19f9 100644
--- a/JavaScriptCore/runtime/CallData.h
+++ b/JavaScriptCore/runtime/CallData.h
@@ -35,7 +35,7 @@ namespace JSC {
class ArgList;
class ExecState;
- class FunctionBodyNode;
+ class FunctionExecutable;
class JSObject;
class JSValue;
class ScopeChainNode;
@@ -53,7 +53,7 @@ namespace JSC {
NativeFunction function;
} native;
struct {
- FunctionBodyNode* functionBody;
+ FunctionExecutable* functionExecutable;
ScopeChainNode* scopeChain;
} js;
};
diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp
index c188016..1a5eb89 100644
--- a/JavaScriptCore/runtime/Collector.cpp
+++ b/JavaScriptCore/runtime/Collector.cpp
@@ -23,8 +23,10 @@
#include "ArgList.h"
#include "CallFrame.h"
+#include "CodeBlock.h"
#include "CollectorHeapIterator.h"
#include "Interpreter.h"
+#include "JSArray.h"
#include "JSGlobalObject.h"
#include "JSLock.h"
#include "JSONObject.h"
@@ -58,11 +60,18 @@
#elif PLATFORM(WIN_OS)
#include <windows.h>
+#include <malloc.h>
+
+#elif PLATFORM(HAIKU)
+
+#include <OS.h>
#elif PLATFORM(UNIX)
#include <stdlib.h>
+#if !PLATFORM(HAIKU)
#include <sys/mman.h>
+#endif
#include <unistd.h>
#if PLATFORM(SOLARIS)
@@ -75,9 +84,15 @@
#include <pthread_np.h>
#endif
+#if PLATFORM(QNX)
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <stdio.h>
+#include <errno.h>
+#endif
+
#endif
-#define DEBUG_COLLECTOR 0
#define COLLECT_ON_EVERY_ALLOCATION 0
using std::max;
@@ -86,7 +101,6 @@ namespace JSC {
// tunable parameters
-const size_t SPARE_EMPTY_BLOCKS = 2;
const size_t GROWTH_FACTOR = 2;
const size_t LOW_WATER_FACTOR = 4;
const size_t ALLOCATIONS_PER_COLLECTION = 4000;
@@ -99,8 +113,6 @@ const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB
static RHeap* userChunk = 0;
#endif
-static void freeHeap(CollectorHeap*);
-
#if ENABLE(JSC_MULTIPLE_THREADS)
#if PLATFORM(DARWIN)
@@ -189,8 +201,8 @@ void Heap::destroy()
ASSERT(!primaryHeap.numLiveObjects);
- freeHeap(&primaryHeap);
- freeHeap(&numberHeap);
+ freeBlocks(&primaryHeap);
+ freeBlocks(&numberHeap);
#if ENABLE(JSC_MULTIPLE_THREADS)
if (m_currentThreadRegistrar) {
@@ -210,7 +222,7 @@ void Heap::destroy()
}
template <HeapType heapType>
-static NEVER_INLINE CollectorBlock* allocateBlock()
+NEVER_INLINE CollectorBlock* Heap::allocateBlock()
{
#if PLATFORM(DARWIN)
vm_address_t address = 0;
@@ -224,9 +236,15 @@ static NEVER_INLINE CollectorBlock* allocateBlock()
uintptr_t address = reinterpret_cast<uintptr_t>(mask);
memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
+#elif PLATFORM(WINCE)
+ void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#elif PLATFORM(WIN_OS)
- // windows virtual address granularity is naturally 64k
- LPVOID address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+#if COMPILER(MINGW)
+ void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
+#else
+ void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
+#endif
+ memset(address, 0, BLOCK_SIZE);
#elif HAVE(POSIX_MEMALIGN)
void* address;
posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
@@ -258,18 +276,58 @@ static NEVER_INLINE CollectorBlock* allocateBlock()
address += adjust;
memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE);
#endif
- reinterpret_cast<CollectorBlock*>(address)->type = heapType;
- return reinterpret_cast<CollectorBlock*>(address);
+
+ CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
+ block->freeList = block->cells;
+ block->heap = this;
+ block->type = heapType;
+
+ CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+ size_t numBlocks = heap.numBlocks;
+ if (heap.usedBlocks == numBlocks) {
+ static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
+ if (numBlocks > maxNumBlocks)
+ CRASH();
+ numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
+ heap.numBlocks = numBlocks;
+ heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
+ }
+ heap.blocks[heap.usedBlocks++] = block;
+
+ return block;
+}
+
+template <HeapType heapType>
+NEVER_INLINE void Heap::freeBlock(size_t block)
+{
+ CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
+
+ freeBlock(heap.blocks[block]);
+
+ // swap with the last block so we compact as we go
+ heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
+ heap.usedBlocks--;
+
+ if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
+ heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
+ heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
+ }
}
-static void freeBlock(CollectorBlock* block)
+NEVER_INLINE void Heap::freeBlock(CollectorBlock* block)
{
#if PLATFORM(DARWIN)
vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
#elif PLATFORM(SYMBIAN)
userChunk->Free(reinterpret_cast<TAny*>(block));
-#elif PLATFORM(WIN_OS)
+#elif PLATFORM(WINCE)
VirtualFree(block, 0, MEM_RELEASE);
+#elif PLATFORM(WIN_OS)
+#if COMPILER(MINGW)
+ __mingw_aligned_free(block);
+#else
+ _aligned_free(block);
+#endif
#elif HAVE(POSIX_MEMALIGN)
free(block);
#else
@@ -277,7 +335,7 @@ static void freeBlock(CollectorBlock* block)
#endif
}
-static void freeHeap(CollectorHeap* heap)
+void Heap::freeBlocks(CollectorHeap* heap)
{
for (size_t i = 0; i < heap->usedBlocks; ++i)
if (heap->blocks[i])
@@ -370,38 +428,23 @@ collect:
#ifndef NDEBUG
heap.operationInProgress = NoOperation;
#endif
- bool collected = collect();
+ bool foundGarbage = collect();
+ numLiveObjects = heap.numLiveObjects;
+ usedBlocks = heap.usedBlocks;
+ i = heap.firstBlockWithPossibleSpace;
#ifndef NDEBUG
heap.operationInProgress = Allocation;
#endif
- if (collected) {
- numLiveObjects = heap.numLiveObjects;
- usedBlocks = heap.usedBlocks;
- i = heap.firstBlockWithPossibleSpace;
+ if (foundGarbage)
goto scan;
- }
- }
-
- // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
- size_t numBlocks = heap.numBlocks;
- if (usedBlocks == numBlocks) {
- static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
- if (numBlocks > maxNumBlocks)
- CRASH();
- numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
- heap.numBlocks = numBlocks;
- heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
}
+ // didn't find a block, and GC didn't reclaim anything, need to allocate a new block
targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>());
- targetBlock->freeList = targetBlock->cells;
- targetBlock->heap = this;
+ heap.firstBlockWithPossibleSpace = heap.usedBlocks - 1;
targetBlockUsedCells = 0;
- heap.blocks[usedBlocks] = reinterpret_cast<CollectorBlock*>(targetBlock);
- heap.usedBlocks = usedBlocks + 1;
- heap.firstBlockWithPossibleSpace = usedBlocks;
}
-
+
// find a free spot in the block and detach it from the free list
Cell* newCell = targetBlock->freeList;
@@ -486,6 +529,33 @@ static void* getStackBase(void* previousFrame)
}
#endif
+#if PLATFORM(QNX)
+static inline void *currentThreadStackBaseQNX()
+{
+ static void* stackBase = 0;
+ static size_t stackSize = 0;
+ static pthread_t stackThread;
+ pthread_t thread = pthread_self();
+ if (stackBase == 0 || thread != stackThread) {
+ struct _debug_thread_info threadInfo;
+ memset(&threadInfo, 0, sizeof(threadInfo));
+ threadInfo.tid = pthread_self();
+ int fd = open("/proc/self", O_RDONLY);
+ if (fd == -1) {
+ LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
+ return 0;
+ }
+ devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
+ close(fd);
+ stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
+ stackSize = threadInfo.stksize;
+ ASSERT(stackBase);
+ stackThread = thread;
+ }
+ return static_cast<char*>(stackBase) + stackSize;
+}
+#endif
+
static inline void* currentThreadStackBase()
{
#if PLATFORM(DARWIN)
@@ -511,6 +581,8 @@ static inline void* currentThreadStackBase()
: "=r" (pTib)
);
return static_cast<void*>(pTib->StackBase);
+#elif PLATFORM(QNX)
+ return currentThreadStackBaseQNX();
#elif PLATFORM(SOLARIS)
stack_t s;
thr_stksegment(&s);
@@ -529,6 +601,10 @@ static inline void* currentThreadStackBase()
stackBase = (void*)info.iBase;
}
return (void*)stackBase;
+#elif PLATFORM(HAIKU)
+ thread_info threadInfo;
+ get_thread_info(find_thread(NULL), &threadInfo);
+ return threadInfo.stack_end;
#elif PLATFORM(UNIX)
static void* stackBase = 0;
static size_t stackSize = 0;
@@ -587,6 +663,8 @@ void Heap::makeUsableFromMultipleThreads()
void Heap::registerThread()
{
+ ASSERT(!m_globalData->mainThreadOnly || isMainThread());
+
if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
return;
@@ -683,7 +761,7 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
// Mark the primary heap
for (size_t block = 0; block < usedPrimaryBlocks; block++) {
if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) {
- if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree != 0) {
+ if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree) {
markStack.append(reinterpret_cast<JSCell*>(xAsBits));
markStack.drain();
}
@@ -704,10 +782,16 @@ void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markS
markConservatively(markStack, stackPointer, stackBase);
}
+#if COMPILER(GCC)
+#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
+#else
+#define REGISTER_BUFFER_ALIGNMENT
+#endif
+
void Heap::markCurrentThreadConservatively(MarkStack& markStack)
{
// setjmp forces volatile registers onto the stack
- jmp_buf registers;
+ jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
#if COMPILER(MSVC)
#pragma warning(push)
#pragma warning(disable: 4611)
@@ -896,16 +980,6 @@ void Heap::markStackObjectsConservatively(MarkStack& markStack)
#endif
}
-void Heap::setGCProtectNeedsLocking()
-{
- // Most clients do not need to call this, with the notable exception of WebCore.
- // Clients that use shared heap have JSLock protection, while others are supposed
- // to do explicit locking. WebCore violates this contract in Database code,
- // which calls gcUnprotect from a secondary thread.
- if (!m_protectedValuesMutex)
- m_protectedValuesMutex.set(new Mutex);
-}
-
void Heap::protect(JSValue k)
{
ASSERT(k);
@@ -914,13 +988,7 @@ void Heap::protect(JSValue k)
if (!k.isCell())
return;
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
m_protectedValues.add(k.asCell());
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
}
void Heap::unprotect(JSValue k)
@@ -931,38 +999,16 @@ void Heap::unprotect(JSValue k)
if (!k.isCell())
return;
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
m_protectedValues.remove(k.asCell());
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-}
-
-Heap* Heap::heap(JSValue v)
-{
- if (!v.isCell())
- return 0;
- return Heap::cellBlock(v.asCell())->heap;
}
void Heap::markProtectedObjects(MarkStack& markStack)
{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
ProtectCountSet::iterator end = m_protectedValues.end();
for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
- JSCell* val = it->first;
- if (!val->marked()) {
- markStack.append(val);
- markStack.drain();
- }
+ markStack.append(it->first);
+ markStack.drain();
}
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
}
template <HeapType heapType> size_t Heap::sweep()
@@ -1036,31 +1082,34 @@ template <HeapType heapType> size_t Heap::sweep()
curBlock->freeList = freeList;
curBlock->marked.clearAll();
- if (usedCells == 0) {
- emptyBlocks++;
- if (emptyBlocks > SPARE_EMPTY_BLOCKS) {
-#if !DEBUG_COLLECTOR
- freeBlock(reinterpret_cast<CollectorBlock*>(curBlock));
-#endif
- // swap with the last block so we compact as we go
- heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
- heap.usedBlocks--;
- block--; // Don't move forward a step in this case
-
- if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
- heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
- heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
- }
- }
- }
+ if (!usedCells)
+ ++emptyBlocks;
}
if (heap.numLiveObjects != numLiveObjects)
heap.firstBlockWithPossibleSpace = 0;
-
+
heap.numLiveObjects = numLiveObjects;
heap.numLiveObjectsAtLastCollect = numLiveObjects;
heap.extraCost = 0;
+
+ if (!emptyBlocks)
+ return numLiveObjects;
+
+ size_t neededCells = 1.25f * (numLiveObjects + max(ALLOCATIONS_PER_COLLECTION, numLiveObjects));
+ size_t neededBlocks = (neededCells + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
+ for (size_t block = 0; block < heap.usedBlocks; block++) {
+ if (heap.usedBlocks <= neededBlocks)
+ break;
+
+ Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]);
+ if (curBlock->usedCells)
+ continue;
+
+ freeBlock<heapType>(block);
+ block--; // Don't move forward a step in this case
+ }
+
return numLiveObjects;
}
@@ -1087,12 +1136,12 @@ bool Heap::collect()
markProtectedObjects(markStack);
if (m_markListSet && m_markListSet->size())
MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
- if (m_globalData->exception && !m_globalData->exception.marked())
+ if (m_globalData->exception)
markStack.append(m_globalData->exception);
m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
- m_globalData->smallStrings.mark();
- if (m_globalData->scopeNodeBeingReparsed)
- m_globalData->scopeNodeBeingReparsed->markAggregate(markStack);
+ m_globalData->smallStrings.markChildren(markStack);
+ if (m_globalData->functionCodeBlockBeingReparsed)
+ m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack);
if (m_globalData->firstStringifierToMark)
JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
@@ -1151,9 +1200,6 @@ size_t Heap::globalObjectCount()
size_t Heap::protectedGlobalObjectCount()
{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
size_t count = 0;
if (JSGlobalObject* head = m_globalData->head) {
JSGlobalObject* o = head;
@@ -1164,23 +1210,12 @@ size_t Heap::protectedGlobalObjectCount()
} while (o != head);
}
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
return count;
}
size_t Heap::protectedObjectCount()
{
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
- size_t result = m_protectedValues.size();
-
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
- return result;
+ return m_protectedValues.size();
}
static const char* typeName(JSCell* cell)
@@ -1194,7 +1229,7 @@ static const char* typeName(JSCell* cell)
if (cell->isGetterSetter())
return "gettersetter";
ASSERT(cell->isObject());
- const ClassInfo* info = static_cast<JSObject*>(cell)->classInfo();
+ const ClassInfo* info = cell->classInfo();
return info ? info->className : "Object";
}
@@ -1202,16 +1237,10 @@ HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
{
HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->lock();
-
ProtectCountSet::iterator end = m_protectedValues.end();
for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
counts->add(typeName(it->first));
- if (m_protectedValuesMutex)
- m_protectedValuesMutex->unlock();
-
return counts;
}
diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h
index 877f890..2ce13dc 100644
--- a/JavaScriptCore/runtime/Collector.h
+++ b/JavaScriptCore/runtime/Collector.h
@@ -96,11 +96,11 @@ namespace JSC {
};
Statistics statistics() const;
- void setGCProtectNeedsLocking();
void protect(JSValue);
void unprotect(JSValue);
static Heap* heap(JSValue); // 0 for immediate values
+ static Heap* heap(JSCell*);
size_t globalObjectCount();
size_t protectedObjectCount();
@@ -133,6 +133,11 @@ namespace JSC {
Heap(JSGlobalData*);
~Heap();
+ template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
+ template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
+ NEVER_INLINE void freeBlock(CollectorBlock*);
+ void freeBlocks(CollectorHeap*);
+
void recordExtraCost(size_t);
void markProtectedObjects(MarkStack&);
void markCurrentThreadConservatively(MarkStack&);
@@ -145,7 +150,6 @@ namespace JSC {
CollectorHeap primaryHeap;
CollectorHeap numberHeap;
- OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking().
ProtectCountSet m_protectedValues;
HashSet<MarkedArgumentBuffer*>* m_markListSet;
@@ -175,7 +179,11 @@ namespace JSC {
#endif
template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
- const size_t BLOCK_SIZE = 16 * 4096; // 64k
+#if PLATFORM(WINCE) || PLATFORM(SYMBIAN)
+ const size_t BLOCK_SIZE = 64 * 1024; // 64k
+#else
+ const size_t BLOCK_SIZE = 64 * 4096; // 256k
+#endif
// derived constants
const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h
index 148d3dd..abe5038 100644
--- a/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -37,17 +37,26 @@
macro(callee) \
macro(caller) \
macro(compile) \
+ macro(configurable) \
macro(constructor) \
+ macro(create) \
+ macro(defineProperty) \
+ macro(defineProperties) \
+ macro(enumerable) \
macro(eval) \
macro(exec) \
macro(fromCharCode) \
macro(global) \
+ macro(get) \
macro(getPrototypeOf) \
+ macro(getOwnPropertyDescriptor) \
macro(hasOwnProperty) \
macro(ignoreCase) \
macro(index) \
macro(input) \
+ macro(isArray) \
macro(isPrototypeOf) \
+ macro(keys) \
macro(length) \
macro(message) \
macro(multiline) \
@@ -56,6 +65,7 @@
macro(parse) \
macro(propertyIsEnumerable) \
macro(prototype) \
+ macro(set) \
macro(source) \
macro(test) \
macro(toExponential) \
@@ -66,7 +76,9 @@
macro(toPrecision) \
macro(toString) \
macro(UTC) \
+ macro(value) \
macro(valueOf) \
+ macro(writable) \
macro(displayName)
namespace JSC {
diff --git a/JavaScriptCore/runtime/Completion.cpp b/JavaScriptCore/runtime/Completion.cpp
index b8b1581..2507698 100644
--- a/JavaScriptCore/runtime/Completion.cpp
+++ b/JavaScriptCore/runtime/Completion.cpp
@@ -31,40 +31,33 @@
#include "Debugger.h"
#include <stdio.h>
-#if !PLATFORM(WIN_OS)
-#include <unistd.h>
-#endif
-
namespace JSC {
Completion checkSyntax(ExecState* exec, const SourceCode& source)
{
JSLock lock(exec);
- int errLine;
- UString errMsg;
+ RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+ JSObject* error = program->checkSyntax(exec);
+ if (error)
+ return Completion(Throw, error);
- RefPtr<ProgramNode> progNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
- if (!progNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
return Completion(Normal);
}
Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
{
JSLock lock(exec);
-
- int errLine;
- UString errMsg;
- RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
- if (!programNode)
- return Completion(Throw, Error::create(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()));
+ RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+ JSObject* error = program->compile(exec, scopeChain.node());
+ if (error)
+ return Completion(Throw, error);
JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
JSValue exception;
- JSValue result = exec->interpreter()->execute(programNode.get(), exec, scopeChain.node(), thisObj, &exception);
+ JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception);
if (exception) {
if (exception.isObject() && asObject(exception)->isWatchdogException())
diff --git a/JavaScriptCore/runtime/ConstructData.h b/JavaScriptCore/runtime/ConstructData.h
index 9d580d5..6b954a6 100644
--- a/JavaScriptCore/runtime/ConstructData.h
+++ b/JavaScriptCore/runtime/ConstructData.h
@@ -33,7 +33,7 @@ namespace JSC {
class ArgList;
class ExecState;
- class FunctionBodyNode;
+ class FunctionExecutable;
class JSObject;
class JSValue;
class ScopeChainNode;
@@ -51,7 +51,7 @@ namespace JSC {
NativeConstructor function;
} native;
struct {
- FunctionBodyNode* functionBody;
+ FunctionExecutable* functionExecutable;
ScopeChainNode* scopeChain;
} js;
};
diff --git a/JavaScriptCore/runtime/DateConstructor.cpp b/JavaScriptCore/runtime/DateConstructor.cpp
index 2f52cff..f9b7d84 100644
--- a/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/JavaScriptCore/runtime/DateConstructor.cpp
@@ -57,7 +57,7 @@ static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const Arg
static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&);
-DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
+DateConstructor::DateConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
{
putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
@@ -79,7 +79,7 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
if (numArgs == 0) // new Date() ECMA 15.9.3.3
value = getCurrentUTCTime();
else if (numArgs == 1) {
- if (args.at(0).isObject(&DateInstance::info))
+ if (args.at(0).inherits(&DateInstance::info))
value = asDateInstance(args.at(0))->internalNumber();
else {
JSValue primitive = args.at(0).toPrimitive(exec);
diff --git a/JavaScriptCore/runtime/DateConstructor.h b/JavaScriptCore/runtime/DateConstructor.h
index dcef3cc..10e450e 100644
--- a/JavaScriptCore/runtime/DateConstructor.h
+++ b/JavaScriptCore/runtime/DateConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class DateConstructor : public InternalFunction {
public:
- DateConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+ DateConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/JavaScriptCore/runtime/DateInstance.cpp b/JavaScriptCore/runtime/DateInstance.cpp
index 62791ae..4cd58f5 100644
--- a/JavaScriptCore/runtime/DateInstance.cpp
+++ b/JavaScriptCore/runtime/DateInstance.cpp
@@ -22,6 +22,8 @@
#include "config.h"
#include "DateInstance.h"
+#include "JSGlobalObject.h"
+
#include <math.h>
#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
@@ -39,12 +41,19 @@ struct DateInstance::Cache {
const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
-DateInstance::DateInstance(PassRefPtr<Structure> structure)
+DateInstance::DateInstance(NonNullPassRefPtr<Structure> structure)
: JSWrapperObject(structure)
, m_cache(0)
{
}
+DateInstance::DateInstance(ExecState* exec, double time)
+ : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure())
+ , m_cache(0)
+{
+ setInternalValue(jsNumber(exec, timeClip(time)));
+}
+
DateInstance::~DateInstance()
{
delete m_cache;
diff --git a/JavaScriptCore/runtime/DateInstance.h b/JavaScriptCore/runtime/DateInstance.h
index 3b73521..36d90b1 100644
--- a/JavaScriptCore/runtime/DateInstance.h
+++ b/JavaScriptCore/runtime/DateInstance.h
@@ -31,7 +31,8 @@ namespace JSC {
class DateInstance : public JSWrapperObject {
public:
- explicit DateInstance(PassRefPtr<Structure>);
+ DateInstance(ExecState*, double);
+ explicit DateInstance(NonNullPassRefPtr<Structure>);
virtual ~DateInstance();
double internalNumber() const { return internalValue().uncheckedGetNumber(); }
@@ -41,7 +42,7 @@ namespace JSC {
bool getTime(double& milliseconds, int& offset) const;
bool getUTCTime(double& milliseconds) const;
- static const ClassInfo info;
+ static JS_EXPORTDATA const ClassInfo info;
void msToGregorianDateTime(double, bool outputIsUTC, WTF::GregorianDateTime&) const;
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
index e2482f4..e46ab67 100644
--- a/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -198,8 +198,8 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L
{
#if HAVE(LANGINFO_H)
static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT };
-#elif PLATFORM(WINCE) && !PLATFORM(QT)
- // strftime() we are using does not support #
+#elif (PLATFORM(WINCE) && !PLATFORM(QT)) || PLATFORM(SYMBIAN)
+ // strftime() does not support '#' on WinCE or Symbian
static const char* const formatStrings[] = { "%c", "%x", "%X" };
#else
static const char* const formatStrings[] = { "%#c", "%#x", "%X" };
@@ -395,7 +395,7 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
// ECMA 15.9.4
-DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure)
+DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: DateInstance(structure)
{
setInternalValue(jsNaN(exec));
@@ -407,11 +407,17 @@ bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& proper
return getStaticFunctionSlot<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, slot);
}
+
+bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
+}
+
// Functions
JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -428,7 +434,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue
JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -445,7 +451,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal
JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -457,17 +463,17 @@ JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSVal
GregorianDateTime t;
thisDateObj->msToGregorianDateTime(milli, utc, t);
- // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second)
- // 6 for formatting and one for null termination = 23. We add one extra character to allow us to force null termination.
- char buffer[24];
- snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second);
+ // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
+ // 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination.
+ char buffer[28];
+ snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second, static_cast<int>(fmod(milli, 1000)));
buffer[sizeof(buffer) - 1] = 0;
return jsNontrivialString(exec, buffer);
}
JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -484,7 +490,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSVa
JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -501,7 +507,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSVa
JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -514,7 +520,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JS
JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -527,7 +533,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*
JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -540,7 +546,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*
JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -553,7 +559,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue t
JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -570,7 +576,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSVal
JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -587,7 +593,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JS
JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -604,7 +610,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal
JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -621,7 +627,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue
JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -638,7 +644,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSVal
JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -655,7 +661,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue t
JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -672,7 +678,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValu
JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -689,7 +695,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue th
JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -706,7 +712,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue
JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -723,7 +729,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue
JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -740,7 +746,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSVal
JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -757,7 +763,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValu
JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -774,7 +780,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSV
JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -791,7 +797,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValu
JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = true;
@@ -808,7 +814,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSV
JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -823,7 +829,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, J
JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -838,7 +844,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*
JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -855,7 +861,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*,
JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -868,7 +874,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue t
static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -899,7 +905,7 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const
static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
DateInstance* thisDateObj = asDateInstance(thisValue);
@@ -1020,7 +1026,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JS
JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
@@ -1062,7 +1068,7 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&DateInstance::info))
+ if (!thisValue.inherits(&DateInstance::info))
return throwError(exec, TypeError);
const bool utc = false;
diff --git a/JavaScriptCore/runtime/DatePrototype.h b/JavaScriptCore/runtime/DatePrototype.h
index 5f4d0ec..caed2d4 100644
--- a/JavaScriptCore/runtime/DatePrototype.h
+++ b/JavaScriptCore/runtime/DatePrototype.h
@@ -29,16 +29,17 @@ namespace JSC {
class DatePrototype : public DateInstance {
public:
- DatePrototype(ExecState*, PassRefPtr<Structure>);
+ DatePrototype(ExecState*, NonNullPassRefPtr<Structure>);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultGetPropertyNames));
}
};
diff --git a/JavaScriptCore/runtime/Error.cpp b/JavaScriptCore/runtime/Error.cpp
index db1d8cc..ddd4bc4 100644
--- a/JavaScriptCore/runtime/Error.cpp
+++ b/JavaScriptCore/runtime/Error.cpp
@@ -97,6 +97,12 @@ JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
return create(exec, type, message, -1, -1, NULL);
}
+JSObject* throwError(ExecState* exec, JSObject* error)
+{
+ exec->setException(error);
+ return error;
+}
+
JSObject* throwError(ExecState* exec, ErrorType type)
{
JSObject* error = Error::create(exec, type, UString(), -1, -1, NULL);
diff --git a/JavaScriptCore/runtime/Error.h b/JavaScriptCore/runtime/Error.h
index adf7fdf..e959cff 100644
--- a/JavaScriptCore/runtime/Error.h
+++ b/JavaScriptCore/runtime/Error.h
@@ -59,6 +59,7 @@ namespace JSC {
JSObject* throwError(ExecState*, ErrorType, const UString& message);
JSObject* throwError(ExecState*, ErrorType, const char* message);
JSObject* throwError(ExecState*, ErrorType);
+ JSObject* throwError(ExecState*, JSObject*);
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ErrorConstructor.cpp b/JavaScriptCore/runtime/ErrorConstructor.cpp
index 07b7e23..b9c3f58 100644
--- a/JavaScriptCore/runtime/ErrorConstructor.cpp
+++ b/JavaScriptCore/runtime/ErrorConstructor.cpp
@@ -29,7 +29,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
-ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
+ErrorConstructor::ErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
{
// ECMA 15.11.3.1 Error.prototype
diff --git a/JavaScriptCore/runtime/ErrorConstructor.h b/JavaScriptCore/runtime/ErrorConstructor.h
index 2dd4124..e3d789b 100644
--- a/JavaScriptCore/runtime/ErrorConstructor.h
+++ b/JavaScriptCore/runtime/ErrorConstructor.h
@@ -30,7 +30,7 @@ namespace JSC {
class ErrorConstructor : public InternalFunction {
public:
- ErrorConstructor(ExecState*, PassRefPtr<Structure>, ErrorPrototype*);
+ ErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, ErrorPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/JavaScriptCore/runtime/ErrorInstance.cpp b/JavaScriptCore/runtime/ErrorInstance.cpp
index 2e2cdce..1cdb87a 100644
--- a/JavaScriptCore/runtime/ErrorInstance.cpp
+++ b/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -25,7 +25,7 @@ namespace JSC {
const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
-ErrorInstance::ErrorInstance(PassRefPtr<Structure> structure)
+ErrorInstance::ErrorInstance(NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
{
}
diff --git a/JavaScriptCore/runtime/ErrorInstance.h b/JavaScriptCore/runtime/ErrorInstance.h
index 6f9d262..9f53b51 100644
--- a/JavaScriptCore/runtime/ErrorInstance.h
+++ b/JavaScriptCore/runtime/ErrorInstance.h
@@ -27,7 +27,7 @@ namespace JSC {
class ErrorInstance : public JSObject {
public:
- explicit ErrorInstance(PassRefPtr<Structure>);
+ explicit ErrorInstance(NonNullPassRefPtr<Structure>);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/ErrorPrototype.cpp b/JavaScriptCore/runtime/ErrorPrototype.cpp
index 599390e..a9a7a43 100644
--- a/JavaScriptCore/runtime/ErrorPrototype.cpp
+++ b/JavaScriptCore/runtime/ErrorPrototype.cpp
@@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
// ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+ErrorPrototype::ErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
: ErrorInstance(structure)
{
// The constructor will be added later in ErrorConstructor's constructor
diff --git a/JavaScriptCore/runtime/ErrorPrototype.h b/JavaScriptCore/runtime/ErrorPrototype.h
index 53d12d9..a561590 100644
--- a/JavaScriptCore/runtime/ErrorPrototype.h
+++ b/JavaScriptCore/runtime/ErrorPrototype.h
@@ -29,7 +29,7 @@ namespace JSC {
class ErrorPrototype : public ErrorInstance {
public:
- ErrorPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ ErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp
index e63594c..5bead90 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -66,6 +66,11 @@ JSValue createStackOverflowError(ExecState* exec)
return createError(exec, RangeError, "Maximum call stack size exceeded.");
}
+JSValue createTypeError(ExecState* exec, const char* message)
+{
+ return createError(exec, TypeError, message);
+}
+
JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
int startOffset = 0;
@@ -74,7 +79,7 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u
int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
UString message = "Can't find variable: ";
message.append(ident.ustring());
- JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -136,7 +141,7 @@ JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value
int divotPoint = 0;
int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message);
- JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -157,7 +162,7 @@ JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned by
startPoint++;
UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor");
- JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -171,7 +176,7 @@ JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecod
int divotPoint = 0;
int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function");
- JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
@@ -201,7 +206,7 @@ JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error,
int divotPoint = 0;
int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object");
- JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerNode()->sourceID(), codeBlock->ownerNode()->sourceURL());
+ JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h
index 4c5bec1..e739d09 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -44,6 +44,7 @@ namespace JSC {
JSValue createInterruptedExecutionException(JSGlobalData*);
JSValue createStackOverflowError(ExecState*);
+ JSValue createTypeError(ExecState*, const char* message);
JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
new file mode 100644
index 0000000..7586746
--- /dev/null
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Executable.h"
+
+#include "BytecodeGenerator.h"
+#include "CodeBlock.h"
+#include "JIT.h"
+#include "Parser.h"
+#include "Vector.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+NativeExecutable::~NativeExecutable()
+{
+}
+#endif
+
+VPtrHackExecutable::~VPtrHackExecutable()
+{
+}
+
+EvalExecutable::~EvalExecutable()
+{
+ delete m_evalCodeBlock;
+}
+
+ProgramExecutable::~ProgramExecutable()
+{
+ delete m_programCodeBlock;
+}
+
+FunctionExecutable::~FunctionExecutable()
+{
+ delete m_codeBlock;
+}
+
+JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ int errLine;
+ UString errMsg;
+ RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+ if (!evalNode)
+ return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+ recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ ASSERT(!m_evalCodeBlock);
+ m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth());
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock));
+ generator->generate();
+
+ evalNode->destroyData();
+ return 0;
+}
+
+JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
+{
+ int errLine;
+ UString errMsg;
+ RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+ if (!programNode)
+ return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+ return 0;
+}
+
+JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ int errLine;
+ UString errMsg;
+ RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
+ if (!programNode)
+ return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
+ recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ ASSERT(!m_programCodeBlock);
+ m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider());
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock));
+ generator->generate();
+
+ programNode->destroyData();
+ return 0;
+}
+
+void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode)
+{
+ JSGlobalData* globalData = scopeChainNode->globalData;
+ RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (m_forceUsesArguments)
+ body->setUsesArguments();
+ body->finishParsing(m_parameters, m_name);
+ recordParse(body->features(), body->lineNo(), body->lastLine());
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ ASSERT(!m_codeBlock);
+ m_codeBlock = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset());
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlock->symbolTable(), m_codeBlock));
+ generator->generate();
+ m_numParameters = m_codeBlock->m_numParameters;
+ ASSERT(m_numParameters);
+ m_numVariables = m_codeBlock->m_numVars;
+
+ body->destroyData();
+}
+
+#if ENABLE(JIT)
+
+void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+ m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ codeBlock->discardBytecode();
+#endif
+}
+
+void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+ m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ codeBlock->discardBytecode();
+#endif
+}
+
+void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+ CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
+ m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
+
+#if !ENABLE(OPCODE_SAMPLING)
+ if (!BytecodeGenerator::dumpsGeneratedCode())
+ codeBlock->discardBytecode();
+#endif
+}
+
+#endif
+
+void FunctionExecutable::markAggregate(MarkStack& markStack)
+{
+ if (m_codeBlock)
+ m_codeBlock->markAggregate(markStack);
+}
+
+ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+{
+ RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (m_forceUsesArguments)
+ newFunctionBody->setUsesArguments();
+ newFunctionBody->finishParsing(m_parameters, m_name);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
+ globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+ generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock));
+ generator->generate();
+
+ ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+
+#if ENABLE(JIT)
+ JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+ ASSERT(newJITCode.size() == generatedJITCode().size());
+#endif
+
+ globalData->functionCodeBlockBeingReparsed = 0;
+
+ return newCodeBlock->extractExceptionInfo();
+}
+
+ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+{
+ RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
+
+ ScopeChain scopeChain(scopeChainNode);
+ JSGlobalObject* globalObject = scopeChain.globalObject();
+
+ OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+
+ OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+ generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock));
+ generator->generate();
+
+ ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+
+#if ENABLE(JIT)
+ JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+ ASSERT(newJITCode.size() == generatedJITCode().size());
+#endif
+
+ return newCodeBlock->extractExceptionInfo();
+}
+
+void FunctionExecutable::recompile(ExecState*)
+{
+ delete m_codeBlock;
+ m_codeBlock = 0;
+ m_numParameters = NUM_PARAMETERS_NOT_COMPILED;
+#if ENABLE(JIT)
+ m_jitCode = JITCode();
+#endif
+}
+
+PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+{
+ RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg);
+ if (!program)
+ return 0;
+
+ StatementNode* exprStatement = program->singleStatement();
+ ASSERT(exprStatement);
+ ASSERT(exprStatement->isExprStatement());
+ if (!exprStatement || !exprStatement->isExprStatement())
+ return 0;
+
+ ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+ ASSERT(funcExpr);
+ ASSERT(funcExpr->isFuncExprNode());
+ if (!funcExpr || !funcExpr->isFuncExprNode())
+ return 0;
+
+ FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+ ASSERT(body);
+ return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+}
+
+UString FunctionExecutable::paramString() const
+{
+ FunctionParameters& parameters = *m_parameters;
+ UString s("");
+ for (size_t pos = 0; pos < parameters.size(); ++pos) {
+ if (!s.isEmpty())
+ s += ", ";
+ s += parameters[pos].ustring();
+ }
+
+ return s;
+}
+
+};
+
+
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
new file mode 100644
index 0000000..f74abe9
--- /dev/null
+++ b/JavaScriptCore/runtime/Executable.h
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Executable_h
+#define Executable_h
+
+#include "JSFunction.h"
+#include "Interpreter.h"
+#include "Nodes.h"
+#include "SamplingTool.h"
+
+namespace JSC {
+
+ class CodeBlock;
+ class Debugger;
+ class EvalCodeBlock;
+ class ProgramCodeBlock;
+ class ScopeChainNode;
+
+ struct ExceptionInfo;
+
+ class ExecutableBase : public RefCounted<ExecutableBase> {
+ friend class JIT;
+
+ protected:
+ static const int NUM_PARAMETERS_IS_HOST = 0;
+ static const int NUM_PARAMETERS_NOT_COMPILED = -1;
+
+ public:
+ ExecutableBase(int numParameters)
+ : m_numParameters(numParameters)
+ {
+ }
+
+ virtual ~ExecutableBase() {}
+
+ bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; }
+
+ protected:
+ int m_numParameters;
+
+#if ENABLE(JIT)
+ public:
+ JITCode& generatedJITCode()
+ {
+ ASSERT(m_jitCode);
+ return m_jitCode;
+ }
+
+ ExecutablePool* getExecutablePool()
+ {
+ return m_jitCode.getExecutablePool();
+ }
+
+ protected:
+ JITCode m_jitCode;
+#endif
+ };
+
+#if ENABLE(JIT)
+ class NativeExecutable : public ExecutableBase {
+ public:
+ NativeExecutable(ExecState* exec)
+ : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+ {
+ m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk()));
+ }
+
+ ~NativeExecutable();
+ };
+#endif
+
+ class VPtrHackExecutable : public ExecutableBase {
+ public:
+ VPtrHackExecutable()
+ : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+ {
+ }
+
+ ~VPtrHackExecutable();
+ };
+
+ class ScriptExecutable : public ExecutableBase {
+ public:
+ ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
+ : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+ , m_source(source)
+ , m_features(0)
+ {
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = globalData->interpreter->sampler())
+ sampler->notifyOfScope(this);
+#else
+ UNUSED_PARAM(globalData);
+#endif
+ }
+
+ ScriptExecutable(ExecState* exec, const SourceCode& source)
+ : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+ , m_source(source)
+ , m_features(0)
+ {
+#if ENABLE(CODEBLOCK_SAMPLING)
+ if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
+ sampler->notifyOfScope(this);
+#else
+ UNUSED_PARAM(exec);
+#endif
+ }
+
+ const SourceCode& source() { return m_source; }
+ intptr_t sourceID() const { return m_source.provider()->asID(); }
+ const UString& sourceURL() const { return m_source.provider()->url(); }
+ int lineNo() const { return m_firstLine; }
+ int lastLine() const { return m_lastLine; }
+
+ bool usesEval() const { return m_features & EvalFeature; }
+ bool usesArguments() const { return m_features & ArgumentsFeature; }
+ bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+
+ virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
+
+ protected:
+ void recordParse(CodeFeatures features, int firstLine, int lastLine)
+ {
+ m_features = features;
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
+ }
+
+ SourceCode m_source;
+ CodeFeatures m_features;
+ int m_firstLine;
+ int m_lastLine;
+ };
+
+ class EvalExecutable : public ScriptExecutable {
+ public:
+
+ ~EvalExecutable();
+
+ EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ if (!m_evalCodeBlock) {
+ JSObject* error = compile(exec, scopeChainNode);
+ ASSERT_UNUSED(!error, error);
+ }
+ return *m_evalCodeBlock;
+ }
+
+ JSObject* compile(ExecState*, ScopeChainNode*);
+
+ ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+ static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
+
+ private:
+ EvalExecutable(ExecState* exec, const SourceCode& source)
+ : ScriptExecutable(exec, source)
+ , m_evalCodeBlock(0)
+ {
+ }
+ EvalCodeBlock* m_evalCodeBlock;
+
+#if ENABLE(JIT)
+ public:
+ JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ if (!m_jitCode)
+ generateJITCode(exec, scopeChainNode);
+ return m_jitCode;
+ }
+
+ private:
+ void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+ };
+
+ class ProgramExecutable : public ScriptExecutable {
+ public:
+ static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
+ {
+ return adoptRef(new ProgramExecutable(exec, source));
+ }
+
+ ~ProgramExecutable();
+
+ ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ if (!m_programCodeBlock) {
+ JSObject* error = compile(exec, scopeChainNode);
+ ASSERT_UNUSED(!error, error);
+ }
+ return *m_programCodeBlock;
+ }
+
+ JSObject* checkSyntax(ExecState*);
+ JSObject* compile(ExecState*, ScopeChainNode*);
+
+ // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
+ ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }
+
+ private:
+ ProgramExecutable(ExecState* exec, const SourceCode& source)
+ : ScriptExecutable(exec, source)
+ , m_programCodeBlock(0)
+ {
+ }
+ ProgramCodeBlock* m_programCodeBlock;
+
+#if ENABLE(JIT)
+ public:
+ JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ if (!m_jitCode)
+ generateJITCode(exec, scopeChainNode);
+ return m_jitCode;
+ }
+
+ private:
+ void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+ };
+
+ class FunctionExecutable : public ScriptExecutable {
+ friend class JIT;
+ public:
+ static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ {
+ return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+ }
+
+ static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ {
+ return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+ }
+
+ ~FunctionExecutable();
+
+ JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
+ {
+ return new (exec) JSFunction(exec, this, scopeChain);
+ }
+
+ CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ ASSERT(scopeChainNode);
+ if (!m_codeBlock)
+ compile(exec, scopeChainNode);
+ return *m_codeBlock;
+ }
+
+ bool isGenerated() const
+ {
+ return m_codeBlock;
+ }
+
+ CodeBlock& generatedBytecode()
+ {
+ ASSERT(m_codeBlock);
+ return *m_codeBlock;
+ }
+
+ const Identifier& name() { return m_name; }
+ size_t parameterCount() const { return m_parameters->size(); }
+ size_t variableCount() const { return m_numVariables; }
+ UString paramString() const;
+
+ void recompile(ExecState*);
+ ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+ void markAggregate(MarkStack& markStack);
+ static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+
+ private:
+ FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ : ScriptExecutable(globalData, source)
+ , m_forceUsesArguments(forceUsesArguments)
+ , m_parameters(parameters)
+ , m_codeBlock(0)
+ , m_name(name)
+ , m_numVariables(0)
+ {
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
+ }
+
+ FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+ : ScriptExecutable(exec, source)
+ , m_forceUsesArguments(forceUsesArguments)
+ , m_parameters(parameters)
+ , m_codeBlock(0)
+ , m_name(name)
+ , m_numVariables(0)
+ {
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
+ }
+
+ void compile(ExecState*, ScopeChainNode*);
+
+ bool m_forceUsesArguments;
+ RefPtr<FunctionParameters> m_parameters;
+ CodeBlock* m_codeBlock;
+ Identifier m_name;
+ size_t m_numVariables;
+
+#if ENABLE(JIT)
+ public:
+ JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+ {
+ if (!m_jitCode)
+ generateJITCode(exec, scopeChainNode);
+ return m_jitCode;
+ }
+
+ private:
+ void generateJITCode(ExecState*, ScopeChainNode*);
+#endif
+ };
+
+ inline FunctionExecutable* JSFunction::jsExecutable() const
+ {
+ ASSERT(!isHostFunctionNonInline());
+ return static_cast<FunctionExecutable*>(m_executable.get());
+ }
+
+ inline bool JSFunction::isHostFunction() const
+ {
+ ASSERT(m_executable);
+ return m_executable->isHostFunction();
+ }
+
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp
index f4f5cc8..9d88400 100644
--- a/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -34,7 +34,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
-FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
+FunctionConstructor::FunctionConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
{
putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
@@ -66,32 +66,6 @@ CallType FunctionConstructor::getCallData(CallData& callData)
return CallTypeHost;
}
-FunctionBodyNode* extractFunctionBody(ProgramNode* program)
-{
- if (!program)
- return 0;
-
- StatementVector& children = program->children();
- if (children.size() != 1)
- return 0;
-
- StatementNode* exprStatement = children[0];
- ASSERT(exprStatement);
- ASSERT(exprStatement->isExprStatement());
- if (!exprStatement || !exprStatement->isExprStatement())
- return 0;
-
- ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
- ASSERT(funcExpr);
- ASSERT(funcExpr->isFuncExprNode());
- if (!funcExpr || !funcExpr->isFuncExprNode())
- return 0;
-
- FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
- ASSERT(body);
- return body;
-}
-
// ECMA 15.3.2 The Function Constructor
JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
{
@@ -113,15 +87,13 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
int errLine;
UString errMsg;
SourceCode source = makeSource(program, sourceURL, lineNumber);
- RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
- FunctionBodyNode* body = extractFunctionBody(programNode.get());
- if (!body)
+ RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
+ if (!function)
return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
JSGlobalObject* globalObject = exec->lexicalGlobalObject();
- ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue());
- return new (exec) JSFunction(exec, functionName, body, scopeChain.node());
+ ScopeChain scopeChain(globalObject, globalObject->globalData(), globalObject, exec->globalThisValue());
+ return new (exec) JSFunction(exec, function, scopeChain.node());
}
// ECMA 15.3.2 The Function Constructor
diff --git a/JavaScriptCore/runtime/FunctionConstructor.h b/JavaScriptCore/runtime/FunctionConstructor.h
index 124b354..197f320 100644
--- a/JavaScriptCore/runtime/FunctionConstructor.h
+++ b/JavaScriptCore/runtime/FunctionConstructor.h
@@ -26,12 +26,10 @@
namespace JSC {
class FunctionPrototype;
- class ProgramNode;
- class FunctionBodyNode;
class FunctionConstructor : public InternalFunction {
public:
- FunctionConstructor(ExecState*, PassRefPtr<Structure>, FunctionPrototype*);
+ FunctionConstructor(ExecState*, NonNullPassRefPtr<Structure>, FunctionPrototype*);
private:
virtual ConstructType getConstructData(ConstructData&);
@@ -41,8 +39,6 @@ namespace JSC {
JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
JSObject* constructFunction(ExecState*, const ArgList&);
- FunctionBodyNode* extractFunctionBody(ProgramNode*);
-
} // namespace JSC
#endif // FunctionConstructor_h
diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp
index 9ba2144..45f17b1 100644
--- a/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JS
static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&);
-FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
{
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
@@ -84,16 +84,17 @@ static inline void insertSemicolonIfNeeded(UString& functionBody)
JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (thisValue.isObject(&JSFunction::info)) {
+ if (thisValue.inherits(&JSFunction::info)) {
JSFunction* function = asFunction(thisValue);
if (!function->isHostFunction()) {
- UString functionBody = function->body()->toSourceString();
- insertSemicolonIfNeeded(functionBody);
- return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + functionBody);
+ FunctionExecutable* executable = function->jsExecutable();
+ UString sourceString = executable->source().toString();
+ insertSemicolonIfNeeded(sourceString);
+ return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + executable->paramString() + ") " + sourceString);
}
}
- if (thisValue.isObject(&InternalFunction::info)) {
+ if (thisValue.inherits(&InternalFunction::info)) {
InternalFunction* function = asInternalFunction(thisValue);
return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}");
}
diff --git a/JavaScriptCore/runtime/FunctionPrototype.h b/JavaScriptCore/runtime/FunctionPrototype.h
index 607ddab..0e38549 100644
--- a/JavaScriptCore/runtime/FunctionPrototype.h
+++ b/JavaScriptCore/runtime/FunctionPrototype.h
@@ -29,12 +29,12 @@ namespace JSC {
class FunctionPrototype : public InternalFunction {
public:
- FunctionPrototype(ExecState*, PassRefPtr<Structure>);
+ FunctionPrototype(ExecState*, NonNullPassRefPtr<Structure>);
void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
}
private:
diff --git a/JavaScriptCore/runtime/GetterSetter.cpp b/JavaScriptCore/runtime/GetterSetter.cpp
index cc85354..7e54053 100644
--- a/JavaScriptCore/runtime/GetterSetter.cpp
+++ b/JavaScriptCore/runtime/GetterSetter.cpp
@@ -32,50 +32,12 @@ void GetterSetter::markChildren(MarkStack& markStack)
{
JSCell::markChildren(markStack);
- if (m_getter && !m_getter->marked())
+ if (m_getter)
markStack.append(m_getter);
- if (m_setter && !m_setter->marked())
+ if (m_setter)
markStack.append(m_setter);
}
-JSValue GetterSetter::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
- ASSERT_NOT_REACHED();
- return jsNull();
-}
-
-bool GetterSetter::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
-{
- ASSERT_NOT_REACHED();
- number = 0;
- value = JSValue();
- return true;
-}
-
-bool GetterSetter::toBoolean(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-double GetterSetter::toNumber(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return 0.0;
-}
-
-UString GetterSetter::toString(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return UString::null();
-}
-
-JSObject* GetterSetter::toObject(ExecState* exec) const
-{
- ASSERT_NOT_REACHED();
- return jsNull().toObject(exec);
-}
-
bool GetterSetter::isGetterSetter() const
{
return true;
diff --git a/JavaScriptCore/runtime/GetterSetter.h b/JavaScriptCore/runtime/GetterSetter.h
index b7a8794..73dd854 100644
--- a/JavaScriptCore/runtime/GetterSetter.h
+++ b/JavaScriptCore/runtime/GetterSetter.h
@@ -55,13 +55,6 @@ namespace JSC {
private:
virtual bool isGetterSetter() const;
- virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
- virtual bool toBoolean(ExecState*) const;
- virtual double toNumber(ExecState*) const;
- virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
-
JSObject* m_getter;
JSObject* m_setter;
};
diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/JavaScriptCore/runtime/GlobalEvalFunction.cpp
index 3074f95..c26002b 100644
--- a/JavaScriptCore/runtime/GlobalEvalFunction.cpp
+++ b/JavaScriptCore/runtime/GlobalEvalFunction.cpp
@@ -32,7 +32,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
-GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
+GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
: PrototypeFunction(exec, structure, len, name, function)
, m_cachedGlobalObject(cachedGlobalObject)
{
diff --git a/JavaScriptCore/runtime/GlobalEvalFunction.h b/JavaScriptCore/runtime/GlobalEvalFunction.h
index cdba4a0..b62ad3e 100644
--- a/JavaScriptCore/runtime/GlobalEvalFunction.h
+++ b/JavaScriptCore/runtime/GlobalEvalFunction.h
@@ -32,9 +32,14 @@ namespace JSC {
class GlobalEvalFunction : public PrototypeFunction {
public:
- GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
+ GlobalEvalFunction(ExecState*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ }
+
private:
virtual void markChildren(MarkStack&);
diff --git a/JavaScriptCore/runtime/Identifier.h b/JavaScriptCore/runtime/Identifier.h
index 631cf42..2249179 100644
--- a/JavaScriptCore/runtime/Identifier.h
+++ b/JavaScriptCore/runtime/Identifier.h
@@ -54,6 +54,8 @@ namespace JSC {
const char* ascii() const { return _ustring.ascii(); }
static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); }
+ static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); }
+ static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); }
bool isNull() const { return _ustring.isNull(); }
bool isEmpty() const { return _ustring.isEmpty(); }
diff --git a/JavaScriptCore/runtime/InternalFunction.cpp b/JavaScriptCore/runtime/InternalFunction.cpp
index b5c9571..2ba2984 100644
--- a/JavaScriptCore/runtime/InternalFunction.cpp
+++ b/JavaScriptCore/runtime/InternalFunction.cpp
@@ -37,7 +37,7 @@ const ClassInfo* InternalFunction::classInfo() const
return &info;
}
-InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<Structure> structure, const Identifier& name)
+InternalFunction::InternalFunction(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const Identifier& name)
: JSObject(structure)
{
putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum);
diff --git a/JavaScriptCore/runtime/InternalFunction.h b/JavaScriptCore/runtime/InternalFunction.h
index 310644c..fdd5cc1 100644
--- a/JavaScriptCore/runtime/InternalFunction.h
+++ b/JavaScriptCore/runtime/InternalFunction.h
@@ -42,12 +42,12 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot));
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot | HasDefaultMark));
}
protected:
- InternalFunction(PassRefPtr<Structure> structure) : JSObject(structure) { }
- InternalFunction(JSGlobalData*, PassRefPtr<Structure>, const Identifier&);
+ InternalFunction(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { }
+ InternalFunction(JSGlobalData*, NonNullPassRefPtr<Structure>, const Identifier&);
private:
virtual CallType getCallData(CallData&) = 0;
diff --git a/JavaScriptCore/runtime/JSAPIValueWrapper.cpp b/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
index 475fad5..e83724a 100644
--- a/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
+++ b/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
@@ -28,40 +28,4 @@
namespace JSC {
-JSValue JSAPIValueWrapper::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
- ASSERT_NOT_REACHED();
- return JSValue();
-}
-
-bool JSAPIValueWrapper::getPrimitiveNumber(ExecState*, double&, JSValue&)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool JSAPIValueWrapper::toBoolean(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-double JSAPIValueWrapper::toNumber(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-UString JSAPIValueWrapper::toString(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return UString();
-}
-
-JSObject* JSAPIValueWrapper::toObject(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSAPIValueWrapper.h b/JavaScriptCore/runtime/JSAPIValueWrapper.h
index 21a9710..88a8493 100644
--- a/JavaScriptCore/runtime/JSAPIValueWrapper.h
+++ b/JavaScriptCore/runtime/JSAPIValueWrapper.h
@@ -37,12 +37,6 @@ namespace JSC {
virtual bool isAPIValueWrapper() const { return true; }
- virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
- virtual bool toBoolean(ExecState*) const;
- virtual double toNumber(ExecState*) const;
- virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
return Structure::create(prototype, TypeInfo(CompoundType));
@@ -54,6 +48,7 @@ namespace JSC {
: JSCell(exec->globalData().apiWrapperStructure.get())
, m_value(value)
{
+ ASSERT(!value.isCell());
}
JSValue m_value;
diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp
index 87adbcd..22fdaaf 100644
--- a/JavaScriptCore/runtime/JSActivation.cpp
+++ b/JavaScriptCore/runtime/JSActivation.cpp
@@ -39,8 +39,8 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation);
const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
-JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionBodyNode> functionBody)
- : Base(callFrame->globalData().activationStructure, new JSActivationData(functionBody, callFrame->registers()))
+JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
+ : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
{
}
@@ -57,12 +57,12 @@ void JSActivation::markChildren(MarkStack& markStack)
if (!registerArray)
return;
- size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
+ size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
size_t count = numParametersMinusThis;
markStack.appendValues(registerArray, count);
- size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
+ size_t numVars = d()->functionExecutable->variableCount();
// Skip the call frame, which sits between the parameters and vars.
markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
@@ -136,14 +136,14 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const
bool JSActivation::isDynamicScope() const
{
- return d()->functionBody->usesEval();
+ return d()->functionExecutable->usesEval();
}
JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSActivation* activation = asActivation(slot.slotBase());
- if (activation->d()->functionBody->usesArguments()) {
+ if (activation->d()->functionExecutable->usesArguments()) {
PropertySlot slot;
activation->symbolTableGet(exec->propertyNames().arguments, slot);
return slot.getValue(exec, exec->propertyNames().arguments);
@@ -156,7 +156,7 @@ JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const
arguments->copyRegisters();
callFrame->setCalleeArguments(arguments);
}
- ASSERT(arguments->isObject(&Arguments::info));
+ ASSERT(arguments->inherits(&Arguments::info));
return arguments;
}
diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h
index 6a08439..583b988 100644
--- a/JavaScriptCore/runtime/JSActivation.h
+++ b/JavaScriptCore/runtime/JSActivation.h
@@ -43,7 +43,7 @@ namespace JSC {
class JSActivation : public JSVariableObject {
typedef JSVariableObject Base;
public:
- JSActivation(CallFrame*, PassRefPtr<FunctionBodyNode>);
+ JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
virtual ~JSActivation();
virtual void markChildren(MarkStack&);
@@ -70,13 +70,20 @@ namespace JSC {
private:
struct JSActivationData : public JSVariableObjectData {
- JSActivationData(PassRefPtr<FunctionBodyNode> functionBody, Register* registers)
- : JSVariableObjectData(&functionBody->generatedBytecode().symbolTable(), registers)
- , functionBody(functionBody)
+ JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers)
+ : JSVariableObjectData(_functionExecutable->generatedBytecode().symbolTable(), registers)
+ , functionExecutable(_functionExecutable)
{
+ // We have to manually ref and deref the symbol table as JSVariableObjectData
+ // doesn't know about SharedSymbolTable
+ functionExecutable->generatedBytecode().sharedSymbolTable()->ref();
+ }
+ ~JSActivationData()
+ {
+ static_cast<SharedSymbolTable*>(symbolTable)->deref();
}
- RefPtr<FunctionBodyNode> functionBody;
+ RefPtr<FunctionExecutable> functionExecutable;
};
static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
index 7d7d4c4..fd9e7b2 100644
--- a/JavaScriptCore/runtime/JSArray.cpp
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -25,6 +25,8 @@
#include "ArrayPrototype.h"
#include "CachedCall.h"
+#include "Error.h"
+#include "Executable.h"
#include "PropertyNameArray.h"
#include <wtf/AVLTree.h>
#include <wtf/Assertions.h>
@@ -128,27 +130,25 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
#endif
-JSArray::JSArray(PassRefPtr<Structure> structure)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
{
unsigned initialCapacity = 0;
m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
- m_storage->m_vectorLength = initialCapacity;
-
- m_fastAccessCutoff = 0;
+ m_vectorLength = initialCapacity;
checkConsistency();
}
-JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength)
: JSObject(structure)
{
unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
m_storage->m_length = initialLength;
- m_storage->m_vectorLength = initialCapacity;
+ m_vectorLength = initialCapacity;
m_storage->m_numValuesInVector = 0;
m_storage->m_sparseValueMap = 0;
m_storage->lazyCreationData = 0;
@@ -157,21 +157,19 @@ JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength)
for (size_t i = 0; i < initialCapacity; ++i)
vector[i] = JSValue();
- m_fastAccessCutoff = 0;
-
checkConsistency();
Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue));
}
-JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list)
+JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list)
: JSObject(structure)
{
unsigned initialCapacity = list.size();
m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
m_storage->m_length = initialCapacity;
- m_storage->m_vectorLength = initialCapacity;
+ m_vectorLength = initialCapacity;
m_storage->m_numValuesInVector = initialCapacity;
m_storage->m_sparseValueMap = 0;
@@ -180,8 +178,6 @@ JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list)
for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
m_storage->m_vector[i] = *it;
- m_fastAccessCutoff = initialCapacity;
-
checkConsistency();
Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
@@ -205,7 +201,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
return false;
}
- if (i < storage->m_vectorLength) {
+ if (i < m_vectorLength) {
JSValue& valueSlot = storage->m_vector[i];
if (valueSlot) {
slot.setValueSlot(&valueSlot);
@@ -221,7 +217,7 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
}
}
- return false;
+ return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
}
bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -239,6 +235,37 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName
return JSObject::getOwnPropertySlot(exec, propertyName, slot);
}
+bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (propertyName == exec->propertyNames().length) {
+ descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum);
+ return true;
+ }
+
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+ if (isArrayIndex) {
+ if (i >= m_storage->m_length)
+ return false;
+ if (i < m_vectorLength) {
+ JSValue& value = m_storage->m_vector[i];
+ if (value) {
+ descriptor.setDescriptor(value, 0);
+ return true;
+ }
+ } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+ if (i >= MIN_SPARSE_ARRAY_INDEX) {
+ SparseArrayValueMap::iterator it = map->find(i);
+ if (it != map->end()) {
+ descriptor.setDescriptor(it->second, 0);
+ return true;
+ }
+ }
+ }
+ }
+ return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
// ECMA 15.4.5.1
void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
@@ -272,7 +299,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
m_storage->m_length = length;
}
- if (i < m_storage->m_vectorLength) {
+ if (i < m_vectorLength) {
JSValue& valueSlot = m_storage->m_vector[i];
if (valueSlot) {
valueSlot = value;
@@ -280,8 +307,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
return;
}
valueSlot = value;
- if (++m_storage->m_numValuesInVector == m_storage->m_length)
- m_fastAccessCutoff = m_storage->m_length;
+ ++m_storage->m_numValuesInVector;
checkConsistency();
return;
}
@@ -319,8 +345,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
if (increaseVectorLength(i + 1)) {
storage = m_storage;
storage->m_vector[i] = value;
- if (++storage->m_numValuesInVector == storage->m_length)
- m_fastAccessCutoff = storage->m_length;
+ ++storage->m_numValuesInVector;
checkConsistency();
} else
throwOutOfMemoryError(exec);
@@ -330,7 +355,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
// Decide how many values it would be best to move from the map.
unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
unsigned newVectorLength = increasedVectorLength(i + 1);
- for (unsigned j = max(storage->m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
+ for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
newNumValuesInVector += map->contains(j);
if (i >= MIN_SPARSE_ARRAY_INDEX)
newNumValuesInVector -= map->contains(i);
@@ -348,13 +373,12 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
}
}
- storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
- if (!storage) {
+ if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) {
throwOutOfMemoryError(exec);
return;
}
- unsigned vectorLength = storage->m_vectorLength;
+ unsigned vectorLength = m_vectorLength;
Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
@@ -372,7 +396,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
storage->m_vector[i] = value;
- storage->m_vectorLength = newVectorLength;
+ m_vectorLength = newVectorLength;
storage->m_numValuesInVector = newNumValuesInVector;
m_storage = storage;
@@ -399,7 +423,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
ArrayStorage* storage = m_storage;
- if (i < storage->m_vectorLength) {
+ if (i < m_vectorLength) {
JSValue& valueSlot = storage->m_vector[i];
if (!valueSlot) {
checkConsistency();
@@ -407,8 +431,6 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
}
valueSlot = JSValue();
--storage->m_numValuesInVector;
- if (m_fastAccessCutoff > i)
- m_fastAccessCutoff = i;
checkConsistency();
return true;
}
@@ -432,7 +454,7 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
return false;
}
-void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// FIXME: Filling PropertyNameArray with an identifier for every integer
// is incredibly inefficient for large arrays. We need a different approach,
@@ -440,7 +462,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames
ArrayStorage* storage = m_storage;
- unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
+ unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
for (unsigned i = 0; i < usedVectorLength; ++i) {
if (storage->m_vector[i])
propertyNames.add(Identifier::from(exec, i));
@@ -452,7 +474,7 @@ void JSArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames
propertyNames.add(Identifier::from(exec, it->first));
}
- JSObject::getPropertyNames(exec, propertyNames);
+ JSObject::getOwnPropertyNames(exec, propertyNames);
}
bool JSArray::increaseVectorLength(unsigned newLength)
@@ -462,17 +484,16 @@ bool JSArray::increaseVectorLength(unsigned newLength)
ArrayStorage* storage = m_storage;
- unsigned vectorLength = storage->m_vectorLength;
+ unsigned vectorLength = m_vectorLength;
ASSERT(newLength > vectorLength);
ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
unsigned newVectorLength = increasedVectorLength(newLength);
- storage = static_cast<ArrayStorage*>(tryFastRealloc(storage, storageSize(newVectorLength)));
- if (!storage)
+ if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage))
return false;
Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
- storage->m_vectorLength = newVectorLength;
+ m_vectorLength = newVectorLength;
for (unsigned i = vectorLength; i < newVectorLength; ++i)
storage->m_vector[i] = JSValue();
@@ -490,10 +511,7 @@ void JSArray::setLength(unsigned newLength)
unsigned length = m_storage->m_length;
if (newLength < length) {
- if (m_fastAccessCutoff > newLength)
- m_fastAccessCutoff = newLength;
-
- unsigned usedVectorLength = min(length, storage->m_vectorLength);
+ unsigned usedVectorLength = min(length, m_vectorLength);
for (unsigned i = newLength; i < usedVectorLength; ++i) {
JSValue& valueSlot = storage->m_vector[i];
bool hadValue = valueSlot;
@@ -532,20 +550,13 @@ JSValue JSArray::pop()
JSValue result;
- if (m_fastAccessCutoff > length) {
- JSValue& valueSlot = m_storage->m_vector[length];
- result = valueSlot;
- ASSERT(result);
- valueSlot = JSValue();
- --m_storage->m_numValuesInVector;
- m_fastAccessCutoff = length;
- } else if (length < m_storage->m_vectorLength) {
+ if (length < m_vectorLength) {
JSValue& valueSlot = m_storage->m_vector[length];
- result = valueSlot;
- valueSlot = JSValue();
- if (result)
+ if (valueSlot) {
--m_storage->m_numValuesInVector;
- else
+ result = valueSlot;
+ valueSlot = JSValue();
+ } else
result = jsUndefined();
} else {
result = jsUndefined();
@@ -573,11 +584,10 @@ void JSArray::push(ExecState* exec, JSValue value)
{
checkConsistency();
- if (m_storage->m_length < m_storage->m_vectorLength) {
- ASSERT(!m_storage->m_vector[m_storage->m_length]);
+ if (m_storage->m_length < m_vectorLength) {
m_storage->m_vector[m_storage->m_length] = value;
- if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
- m_fastAccessCutoff = m_storage->m_length;
+ ++m_storage->m_numValuesInVector;
+ ++m_storage->m_length;
checkConsistency();
return;
}
@@ -587,8 +597,8 @@ void JSArray::push(ExecState* exec, JSValue value)
if (!map || map->isEmpty()) {
if (increaseVectorLength(m_storage->m_length + 1)) {
m_storage->m_vector[m_storage->m_length] = value;
- if (++m_storage->m_numValuesInVector == ++m_storage->m_length)
- m_fastAccessCutoff = m_storage->m_length;
+ ++m_storage->m_numValuesInVector;
+ ++m_storage->m_length;
checkConsistency();
return;
}
@@ -603,18 +613,7 @@ void JSArray::push(ExecState* exec, JSValue value)
void JSArray::markChildren(MarkStack& markStack)
{
- JSObject::markChildren(markStack);
-
- ArrayStorage* storage = m_storage;
-
- unsigned usedVectorLength = min(storage->m_length, storage->m_vectorLength);
- markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
-
- if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
- SparseArrayValueMap::iterator end = map->end();
- for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
- markStack.append(it->second);
- }
+ markChildrenDirect(markStack);
}
static int compareNumbersForQSort(const void* a, const void* b)
@@ -817,7 +816,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
if (!m_storage->m_length)
return;
- unsigned usedVectorLength = min(m_storage->m_length, m_storage->m_vectorLength);
+ unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
tree.abstractor().m_exec = exec;
@@ -866,7 +865,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
newUsedVectorLength += map->size();
- if (newUsedVectorLength > m_storage->m_vectorLength) {
+ 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)) {
throwOutOfMemoryError(exec);
@@ -906,7 +905,6 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
m_storage->m_vector[i] = JSValue();
- m_fastAccessCutoff = newUsedVectorLength;
m_storage->m_numValuesInVector = newUsedVectorLength;
checkConsistency(SortConsistencyCheck);
@@ -914,10 +912,16 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
{
- unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+ JSValue* vector = m_storage->m_vector;
+ unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
unsigned i = 0;
- for (; i < fastAccessLength; ++i)
- args.append(getIndex(i));
+ for (; i < vectorEnd; ++i) {
+ JSValue& v = vector[i];
+ if (!v)
+ break;
+ args.append(v);
+ }
+
for (; i < m_storage->m_length; ++i)
args.append(get(exec, i));
}
@@ -926,12 +930,17 @@ void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSiz
{
ASSERT(m_storage->m_length == maxSize);
UNUSED_PARAM(maxSize);
- unsigned fastAccessLength = min(m_storage->m_length, m_fastAccessCutoff);
+ JSValue* vector = m_storage->m_vector;
+ unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
unsigned i = 0;
- for (; i < fastAccessLength; ++i)
- buffer[i] = getIndex(i);
- uint32_t size = m_storage->m_length;
- for (; i < size; ++i)
+ for (; i < vectorEnd; ++i) {
+ JSValue& v = vector[i];
+ if (!v)
+ break;
+ buffer[i] = v;
+ }
+
+ for (; i < m_storage->m_length; ++i)
buffer[i] = get(exec, i);
}
@@ -941,7 +950,7 @@ unsigned JSArray::compactForSorting()
ArrayStorage* storage = m_storage;
- unsigned usedVectorLength = min(m_storage->m_length, storage->m_vectorLength);
+ unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
unsigned numDefined = 0;
unsigned numUndefined = 0;
@@ -965,7 +974,7 @@ unsigned JSArray::compactForSorting()
if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
newUsedVectorLength += map->size();
- if (newUsedVectorLength > storage->m_vectorLength) {
+ 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))
@@ -986,7 +995,6 @@ unsigned JSArray::compactForSorting()
for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
storage->m_vector[i] = JSValue();
- m_fastAccessCutoff = newUsedVectorLength;
storage->m_numValuesInVector = newUsedVectorLength;
checkConsistency(SortConsistencyCheck);
@@ -1012,30 +1020,27 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
if (type == SortConsistencyCheck)
ASSERT(!m_storage->m_sparseValueMap);
- ASSERT(m_fastAccessCutoff <= m_storage->m_length);
- ASSERT(m_fastAccessCutoff <= m_storage->m_numValuesInVector);
-
unsigned numValuesInVector = 0;
- for (unsigned i = 0; i < m_storage->m_vectorLength; ++i) {
+ for (unsigned i = 0; i < m_vectorLength; ++i) {
if (JSValue value = m_storage->m_vector[i]) {
ASSERT(i < m_storage->m_length);
if (type != DestructorConsistencyCheck)
value->type(); // Likely to crash if the object was deallocated.
++numValuesInVector;
} else {
- ASSERT(i >= m_fastAccessCutoff);
if (type == SortConsistencyCheck)
ASSERT(i >= m_storage->m_numValuesInVector);
}
}
ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
+ ASSERT(numValuesInVector <= m_storage->m_length);
if (m_storage->m_sparseValueMap) {
SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
unsigned index = it->first;
ASSERT(index < m_storage->m_length);
- ASSERT(index >= m_storage->m_vectorLength);
+ ASSERT(index >= m_vectorLength);
ASSERT(index <= MAX_ARRAY_INDEX);
ASSERT(it->second);
if (type != DestructorConsistencyCheck)
@@ -1046,26 +1051,4 @@ void JSArray::checkConsistency(ConsistencyCheckType type)
#endif
-JSArray* constructEmptyArray(ExecState* exec)
-{
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
-}
-
-JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
-{
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
-}
-
-JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
-{
- MarkedArgumentBuffer values;
- values.append(singleItemValue);
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
-}
-
-JSArray* constructArray(ExecState* exec, const ArgList& values)
-{
- return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
-}
-
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h
index 49df6c4..66b5a1d 100644
--- a/JavaScriptCore/runtime/JSArray.h
+++ b/JavaScriptCore/runtime/JSArray.h
@@ -29,7 +29,6 @@ namespace JSC {
struct ArrayStorage {
unsigned m_length;
- unsigned m_vectorLength;
unsigned m_numValuesInVector;
SparseArrayValueMap* m_sparseValueMap;
void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily.
@@ -38,15 +37,17 @@ namespace JSC {
class JSArray : public JSObject {
friend class JIT;
+ friend class Walker;
public:
- explicit JSArray(PassRefPtr<Structure>);
- JSArray(PassRefPtr<Structure>, unsigned initialLength);
- JSArray(PassRefPtr<Structure>, const ArgList& initialValues);
+ explicit JSArray(NonNullPassRefPtr<Structure>);
+ JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength);
+ JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues);
virtual ~JSArray();
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
static JS_EXPORTDATA const ClassInfo info;
@@ -61,18 +62,24 @@ namespace JSC {
void push(ExecState*, JSValue);
JSValue pop();
- bool canGetIndex(unsigned i) { return i < m_fastAccessCutoff; }
+ bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
JSValue getIndex(unsigned i)
{
ASSERT(canGetIndex(i));
return m_storage->m_vector[i];
}
- bool canSetIndex(unsigned i) { return i < m_fastAccessCutoff; }
- JSValue setIndex(unsigned i, JSValue v)
+ bool canSetIndex(unsigned i) { return i < m_vectorLength; }
+ void setIndex(unsigned i, JSValue v)
{
ASSERT(canSetIndex(i));
- return m_storage->m_vector[i] = v;
+ JSValue& x = m_storage->m_vector[i];
+ if (!x) {
+ ++m_storage->m_numValuesInVector;
+ if (i >= m_storage->m_length)
+ m_storage->m_length = i + 1;
+ }
+ x = v;
}
void fillArgList(ExecState*, MarkedArgumentBuffer&);
@@ -82,12 +89,14 @@ namespace JSC {
{
return Structure::create(prototype, TypeInfo(ObjectType));
}
+
+ inline void markChildrenDirect(MarkStack& markStack);
protected:
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual void markChildren(MarkStack&);
void* lazyCreationData();
@@ -106,25 +115,110 @@ namespace JSC {
enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
- unsigned m_fastAccessCutoff;
+ unsigned m_vectorLength;
ArrayStorage* m_storage;
};
JSArray* asArray(JSValue);
- JSArray* constructEmptyArray(ExecState*);
- JSArray* constructEmptyArray(ExecState*, unsigned initialLength);
- JSArray* constructArray(ExecState*, JSValue singleItemValue);
- JSArray* constructArray(ExecState*, const ArgList& values);
+ inline JSArray* asArray(JSCell* cell)
+ {
+ ASSERT(cell->inherits(&JSArray::info));
+ return static_cast<JSArray*>(cell);
+ }
inline JSArray* asArray(JSValue value)
{
- ASSERT(asObject(value)->inherits(&JSArray::info));
- return static_cast<JSArray*>(asObject(value));
+ return asArray(value.asCell());
+ }
+
+ inline bool isJSArray(JSGlobalData* globalData, JSValue v)
+ {
+ return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr;
+ }
+ inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
+
+ inline void JSArray::markChildrenDirect(MarkStack& markStack)
+ {
+ JSObject::markChildrenDirect(markStack);
+
+ ArrayStorage* storage = m_storage;
+
+ unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
+ markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
+
+ if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
+ SparseArrayValueMap::iterator end = map->end();
+ for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
+ markStack.append(it->second);
+ }
}
- inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; }
+ inline void MarkStack::markChildren(JSCell* cell)
+ {
+ ASSERT(Heap::isCellMarked(cell));
+ if (cell->structure()->typeInfo().hasDefaultMark()) {
+#ifdef NDEBUG
+ asObject(cell)->markChildrenDirect(*this);
+#else
+ ASSERT(!m_isCheckingForDefaultMarkViolation);
+ m_isCheckingForDefaultMarkViolation = true;
+ cell->markChildren(*this);
+ ASSERT(m_isCheckingForDefaultMarkViolation);
+ m_isCheckingForDefaultMarkViolation = false;
+#endif
+ return;
+ }
+ if (cell->vptr() == m_jsArrayVPtr) {
+ asArray(cell)->markChildrenDirect(*this);
+ return;
+ }
+ cell->markChildren(*this);
+ }
+ inline void MarkStack::drain()
+ {
+ while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
+ while (!m_markSets.isEmpty() && m_values.size() < 50) {
+ ASSERT(!m_markSets.isEmpty());
+ MarkSet& current = m_markSets.last();
+ ASSERT(current.m_values);
+ JSValue* end = current.m_end;
+ ASSERT(current.m_values);
+ ASSERT(current.m_values != end);
+ findNextUnmarkedNullValue:
+ ASSERT(current.m_values != end);
+ JSValue value = *current.m_values;
+ current.m_values++;
+
+ JSCell* cell;
+ if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) {
+ if (current.m_values == end) {
+ m_markSets.removeLast();
+ continue;
+ }
+ goto findNextUnmarkedNullValue;
+ }
+
+ Heap::markCell(cell);
+ if (cell->structure()->typeInfo().type() < CompoundType) {
+ if (current.m_values == end) {
+ m_markSets.removeLast();
+ continue;
+ }
+ goto findNextUnmarkedNullValue;
+ }
+
+ if (current.m_values == end)
+ m_markSets.removeLast();
+
+ markChildren(cell);
+ }
+ while (!m_values.isEmpty())
+ markChildren(m_values.removeLast());
+ }
+ }
+
} // namespace JSC
#endif // JSArray_h
diff --git a/JavaScriptCore/runtime/JSByteArray.cpp b/JavaScriptCore/runtime/JSByteArray.cpp
index 2a5e72f..90d39f0 100644
--- a/JavaScriptCore/runtime/JSByteArray.cpp
+++ b/JavaScriptCore/runtime/JSByteArray.cpp
@@ -35,7 +35,7 @@ namespace JSC {
const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
-JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
+JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
: JSObject(structure)
, m_storage(storage)
, m_classInfo(classInfo)
@@ -45,7 +45,7 @@ JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteA
PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
{
- PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType));
+ PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark));
return result;
}
@@ -59,7 +59,18 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property
}
return JSObject::getOwnPropertySlot(exec, propertyName, slot);
}
-
+
+bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ bool ok;
+ unsigned index = propertyName.toUInt32(&ok, false);
+ if (ok && canAccessIndex(index)) {
+ descriptor.setDescriptor(getIndex(exec, index), DontDelete);
+ return true;
+ }
+ return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
if (canAccessIndex(propertyName)) {
@@ -85,12 +96,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value)
setIndex(exec, propertyName, value);
}
-void JSByteArray::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
unsigned length = m_storage->length();
for (unsigned i = 0; i < length; ++i)
propertyNames.add(Identifier::from(exec, i));
- JSObject::getPropertyNames(exec, propertyNames);
+ JSObject::getOwnPropertyNames(exec, propertyNames);
}
}
diff --git a/JavaScriptCore/runtime/JSByteArray.h b/JavaScriptCore/runtime/JSByteArray.h
index a56aca6..006f4a2 100644
--- a/JavaScriptCore/runtime/JSByteArray.h
+++ b/JavaScriptCore/runtime/JSByteArray.h
@@ -73,15 +73,16 @@ namespace JSC {
setIndex(i, byteValue);
}
- JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
+ JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
static PassRefPtr<Structure> createStructure(JSValue prototype);
virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
- virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
virtual const ClassInfo* classInfo() const { return m_classInfo; }
static const ClassInfo s_defaultInfo;
diff --git a/JavaScriptCore/runtime/JSCell.cpp b/JavaScriptCore/runtime/JSCell.cpp
index c733ed9..aa93252 100644
--- a/JavaScriptCore/runtime/JSCell.cpp
+++ b/JavaScriptCore/runtime/JSCell.cpp
@@ -105,7 +105,7 @@ UString JSCell::getString() const
JSObject* JSCell::getObject()
{
- return isObject() ? static_cast<JSObject*>(this) : 0;
+ return isObject() ? asObject(this) : 0;
}
const JSObject* JSCell::getObject() const
@@ -197,4 +197,40 @@ bool JSCell::isGetterSetter() const
return false;
}
+JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
+{
+ ASSERT_NOT_REACHED();
+ return JSValue();
+}
+
+bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&)
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+bool JSCell::toBoolean(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+double JSCell::toNumber(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+UString JSCell::toString(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return UString();
+}
+
+JSObject* JSCell::toObject(ExecState*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h
index 75ccf7f..503c6c4 100644
--- a/JavaScriptCore/runtime/JSCell.h
+++ b/JavaScriptCore/runtime/JSCell.h
@@ -23,11 +23,12 @@
#ifndef JSCell_h
#define JSCell_h
-#include <wtf/Noncopyable.h>
-#include "Structure.h"
-#include "JSValue.h"
-#include "JSImmediate.h"
#include "Collector.h"
+#include "JSImmediate.h"
+#include "JSValue.h"
+#include "MarkStack.h"
+#include "Structure.h"
+#include <wtf/Noncopyable.h>
namespace JSC {
@@ -45,6 +46,7 @@ namespace JSC {
private:
explicit JSCell(Structure*);
+ JSCell(); // Only used for initializing Collector blocks.
virtual ~JSCell();
public:
@@ -55,7 +57,7 @@ namespace JSC {
bool isString() const;
bool isObject() const;
virtual bool isGetterSetter() const;
- virtual bool isObject(const ClassInfo*) const;
+ bool inherits(const ClassInfo*) const;
virtual bool isAPIValueWrapper() const { return false; }
Structure* structure() const;
@@ -74,21 +76,19 @@ namespace JSC {
virtual bool getUInt32(uint32_t&) const;
// Basic conversions.
- virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
- virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&) = 0;
- virtual bool toBoolean(ExecState*) const = 0;
- virtual double toNumber(ExecState*) const = 0;
- virtual UString toString(ExecState*) const = 0;
- virtual JSObject* toObject(ExecState*) const = 0;
+ virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&);
+ virtual bool toBoolean(ExecState*) const;
+ virtual double toNumber(ExecState*) const;
+ virtual UString toString(ExecState*) const;
+ virtual JSObject* toObject(ExecState*) const;
// Garbage collection.
void* operator new(size_t, ExecState*);
void* operator new(size_t, JSGlobalData*);
void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
- void markCellDirect();
virtual void markChildren(MarkStack&);
- bool marked() const;
// Object operations, with the toObject operation included.
virtual const ClassInfo* classInfo() const;
@@ -112,6 +112,7 @@ namespace JSC {
Structure* m_structure;
};
+ // FIXME: We should deprecate this and just use JSValue::asCell() instead.
JSCell* asCell(JSValue);
inline JSCell* asCell(JSValue value)
@@ -124,6 +125,11 @@ namespace JSC {
{
}
+ // Only used for initializing Collector blocks.
+ inline JSCell::JSCell()
+ {
+ }
+
inline JSCell::~JSCell()
{
}
@@ -150,19 +156,8 @@ namespace JSC {
return m_structure;
}
- inline bool JSCell::marked() const
- {
- return Heap::isCellMarked(this);
- }
-
- inline void JSCell::markCellDirect()
- {
- Heap::markCell(this);
- }
-
inline void JSCell::markChildren(MarkStack&)
{
- ASSERT(marked());
}
inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
@@ -231,23 +226,6 @@ namespace JSC {
return false;
}
- inline void JSValue::markDirect()
- {
- ASSERT(!marked());
- asCell()->markCellDirect();
- }
-
- inline void JSValue::markChildren(MarkStack& markStack)
- {
- ASSERT(marked());
- asCell()->markChildren(markStack);
- }
-
- inline bool JSValue::marked() const
- {
- return !isCell() || asCell()->marked();
- }
-
#if !USE(JSVALUE32_64)
ALWAYS_INLINE JSCell* JSValue::asCell() const
{
@@ -315,24 +293,6 @@ namespace JSC {
return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
}
- inline UString JSValue::toString(ExecState* exec) const
- {
- if (isCell())
- return asCell()->toString(exec);
- if (isInt32())
- return UString::from(asInt32());
- if (isDouble())
- return asDouble() == 0.0 ? "0" : UString::from(asDouble());
- if (isTrue())
- return "true";
- if (isFalse())
- return "false";
- if (isNull())
- return "null";
- ASSERT(isUndefined());
- return "undefined";
- }
-
inline bool JSValue::needsThisConversion() const
{
if (UNLIKELY(!isCell()))
@@ -353,12 +313,6 @@ namespace JSC {
return asCell()->getJSNumber();
return JSValue();
}
-
- inline bool JSValue::hasChildren() const
- {
- return asCell()->structure()->typeInfo().type() >= CompoundType;
- }
-
inline JSObject* JSValue::toObject(ExecState* exec) const
{
@@ -372,37 +326,39 @@ namespace JSC {
ALWAYS_INLINE void MarkStack::append(JSCell* cell)
{
+ ASSERT(!m_isCheckingForDefaultMarkViolation);
ASSERT(cell);
- if (cell->marked())
+ if (Heap::isCellMarked(cell))
return;
- cell->markCellDirect();
+ Heap::markCell(cell);
if (cell->structure()->typeInfo().type() >= CompoundType)
m_values.append(cell);
}
- inline void MarkStack::drain() {
- while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
- while ((!m_markSets.isEmpty()) && m_values.size() < 50) {
- const MarkSet& current = m_markSets.removeLast();
- JSValue* ptr = current.m_values;
- JSValue* end = current.m_end;
- if (current.m_properties == NoNullValues) {
- while (ptr != end)
- append(*ptr++);
- } else {
- while (ptr != end) {
- if (JSValue value = *ptr++)
- append(value);
- }
- }
- }
- while (!m_values.isEmpty()) {
- JSCell* current = m_values.removeLast();
- ASSERT(current->marked());
- current->markChildren(*this);
- }
- }
+ ALWAYS_INLINE void MarkStack::append(JSValue value)
+ {
+ ASSERT(value);
+ if (value.isCell())
+ append(value.asCell());
+ }
+
+ inline void Structure::markAggregate(MarkStack& markStack)
+ {
+ markStack.append(m_prototype);
+ }
+
+ inline Heap* Heap::heap(JSValue v)
+ {
+ if (!v.isCell())
+ return 0;
+ return heap(v.asCell());
+ }
+
+ inline Heap* Heap::heap(JSCell* c)
+ {
+ return cellBlock(c)->heap;
}
+
} // namespace JSC
#endif // JSCell_h
diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp
index 84c6263..024e586 100644
--- a/JavaScriptCore/runtime/JSFunction.cpp
+++ b/JavaScriptCore/runtime/JSFunction.cpp
@@ -45,12 +45,21 @@ ASSERT_CLASS_FITS_IN_CELL(JSFunction);
const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
-JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
+bool JSFunction::isHostFunctionNonInline() const
+{
+ return isHostFunction();
+}
+
+JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
+ : Base(structure)
+ , m_executable(adoptRef(new VPtrHackExecutable()))
+{
+}
+
+JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
: Base(&exec->globalData(), structure, name)
#if ENABLE(JIT)
- , m_body(FunctionBodyNode::createNativeThunk(&exec->globalData()))
-#else
- , m_body(0)
+ , m_executable(adoptRef(new NativeExecutable(exec)))
#endif
{
#if ENABLE(JIT)
@@ -63,9 +72,9 @@ JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int len
#endif
}
-JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode)
- : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name)
- , m_body(body)
+JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
+ : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
+ , m_executable(executable)
{
setScopeChain(scopeChainNode);
}
@@ -75,20 +84,23 @@ JSFunction::~JSFunction()
// JIT code for other functions may have had calls linked directly to the code for this function; these links
// are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
// this memory is freed and may be reused (potentially for another, different JSFunction).
+ if (!isHostFunction()) {
#if ENABLE(JIT_OPTIMIZE_CALL)
- if (m_body && m_body->isGenerated())
- m_body->generatedBytecode().unlinkCallers();
+ ASSERT(m_executable);
+ if (jsExecutable()->isGenerated())
+ jsExecutable()->generatedBytecode().unlinkCallers();
#endif
- if (!isHostFunction())
scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
+ }
}
void JSFunction::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- m_body->markAggregate(markStack);
- if (!isHostFunction())
+ if (!isHostFunction()) {
+ jsExecutable()->markAggregate(markStack);
scopeChain().markAggregate(markStack);
+ }
}
CallType JSFunction::getCallData(CallData& callData)
@@ -97,7 +109,7 @@ CallType JSFunction::getCallData(CallData& callData)
callData.native.function = nativeFunction();
return CallTypeHost;
}
- callData.js.functionBody = m_body.get();
+ callData.js.functionExecutable = jsExecutable();
callData.js.scopeChain = scopeChain().node();
return CallTypeJS;
}
@@ -105,7 +117,7 @@ CallType JSFunction::getCallData(CallData& callData)
JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
{
ASSERT(!isHostFunction());
- return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
+ return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
}
JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
@@ -126,7 +138,7 @@ JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const Prope
{
JSFunction* thisObj = asFunction(slot.slotBase());
ASSERT(!thisObj->isHostFunction());
- return jsNumber(exec, thisObj->m_body->parameterCount());
+ return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
}
bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -165,6 +177,35 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
return Base::getOwnPropertySlot(exec, propertyName, slot);
}
+ bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ if (isHostFunction())
+ return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+
+ if (propertyName == exec->propertyNames().prototype) {
+ PropertySlot slot;
+ getOwnPropertySlot(exec, propertyName, slot);
+ return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ }
+
+ if (propertyName == exec->propertyNames().arguments) {
+ descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().caller) {
+ descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ }
+
void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (isHostFunction()) {
@@ -190,7 +231,7 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData)
{
if (isHostFunction())
return ConstructTypeNone;
- constructData.js.functionBody = m_body.get();
+ constructData.js.functionExecutable = jsExecutable();
constructData.js.scopeChain = scopeChain().node();
return ConstructTypeJS;
}
@@ -206,7 +247,7 @@ JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
structure = exec->lexicalGlobalObject()->emptyObjectStructure();
JSObject* thisObj = new (exec) JSObject(structure);
- JSValue result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
+ JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
if (exec->hadException() || !result.isObject())
return thisObj;
return asObject(result);
diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h
index cab1e5b..a9ac63e 100644
--- a/JavaScriptCore/runtime/JSFunction.h
+++ b/JavaScriptCore/runtime/JSFunction.h
@@ -25,14 +25,11 @@
#define JSFunction_h
#include "InternalFunction.h"
-#include "JSVariableObject.h"
-#include "SymbolTable.h"
-#include "Nodes.h"
-#include "JSObject.h"
namespace JSC {
- class FunctionBodyNode;
+ class ExecutableBase;
+ class FunctionExecutable;
class FunctionPrototype;
class JSActivation;
class JSGlobalObject;
@@ -43,20 +40,10 @@ namespace JSC {
typedef InternalFunction Base;
- JSFunction(PassRefPtr<Structure> structure)
- : InternalFunction(structure)
- {
- clearScopeChain();
- }
-
public:
- JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
- JSFunction(ExecState*, const Identifier&, FunctionBodyNode*, ScopeChainNode*);
- ~JSFunction();
-
- virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
- virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
- virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+ JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
+ JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*);
+ virtual ~JSFunction();
JSObject* construct(ExecState*, const ArgList&);
JSValue call(ExecState*, JSValue thisValue, const ArgList&);
@@ -64,11 +51,11 @@ namespace JSC {
void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); }
ScopeChain& scope() { return scopeChain(); }
- void setBody(FunctionBodyNode* body) { m_body = body; }
- void setBody(PassRefPtr<FunctionBodyNode> body) { m_body = body; }
- FunctionBodyNode* body() const { return m_body.get(); }
+ ExecutableBase* executable() const { return m_executable.get(); }
- virtual void markChildren(MarkStack&);
+ // To call either of these methods include Executable.h
+ inline bool isHostFunction() const;
+ FunctionExecutable* jsExecutable() const;
static JS_EXPORTDATA const ClassInfo info;
@@ -77,11 +64,6 @@ namespace JSC {
return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
}
-#if ENABLE(JIT)
- bool isHostFunction() const { return m_body && m_body->isHostFunction(); }
-#else
- bool isHostFunction() const { return false; }
-#endif
NativeFunction nativeFunction()
{
return *reinterpret_cast<NativeFunction*>(m_data);
@@ -91,31 +73,42 @@ namespace JSC {
virtual CallType getCallData(CallData&);
private:
+ JSFunction(NonNullPassRefPtr<Structure>);
+
+ bool isHostFunctionNonInline() const;
+
+ virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+ virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
+
+ virtual void markChildren(MarkStack&);
+
virtual const ClassInfo* classInfo() const { return &info; }
static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&);
static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
- RefPtr<FunctionBodyNode> m_body;
+ RefPtr<ExecutableBase> m_executable;
ScopeChain& scopeChain()
{
- ASSERT(!isHostFunction());
+ ASSERT(!isHostFunctionNonInline());
return *reinterpret_cast<ScopeChain*>(m_data);
}
void clearScopeChain()
{
- ASSERT(!isHostFunction());
+ ASSERT(!isHostFunctionNonInline());
new (m_data) ScopeChain(NoScopeChain());
}
void setScopeChain(ScopeChainNode* sc)
{
- ASSERT(!isHostFunction());
+ ASSERT(!isHostFunctionNonInline());
new (m_data) ScopeChain(sc);
}
void setScopeChain(const ScopeChain& sc)
{
- ASSERT(!isHostFunction());
+ ASSERT(!isHostFunctionNonInline());
*reinterpret_cast<ScopeChain*>(m_data) = sc;
}
void setNativeFunction(NativeFunction func)
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 03df41d..1221ef2 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -144,8 +144,12 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet)
, initializingLazyNumericCompareFunction(false)
, head(0)
, dynamicGlobalObject(0)
- , scopeNodeBeingReparsed(0)
+ , functionCodeBlockBeingReparsed(0)
, firstStringifierToMark(0)
+ , markStack(vptrSet.jsArrayVPtr)
+#ifndef NDEBUG
+ , mainThreadOnly(false)
+#endif
{
#if PLATFORM(MAC)
startProfilerServerIfNeeded();
@@ -235,9 +239,8 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
{
if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
initializingLazyNumericCompareFunction = true;
- RefPtr<ProgramNode> programNode = parser->parse<ProgramNode>(exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
- RefPtr<FunctionBodyNode> functionBody = extractFunctionBody(programNode.get());
- lazyNumericCompareFunction = functionBody->bytecode(exec->scopeChain()).instructions();
+ RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
+ lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions();
initializingLazyNumericCompareFunction = false;
}
@@ -248,4 +251,19 @@ JSGlobalData::ClientData::~ClientData()
{
}
+void JSGlobalData::startSampling()
+{
+ interpreter->startSampling();
+}
+
+void JSGlobalData::stopSampling()
+{
+ interpreter->stopSampling();
+}
+
+void JSGlobalData::dumpSampleData(ExecState* exec)
+{
+ interpreter->dumpSampleData(exec);
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 88cb516..3ad90ad 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -34,6 +34,7 @@
#include "JITStubs.h"
#include "JSValue.h"
#include "MarkStack.h"
+#include "NumericStrings.h"
#include "SmallStrings.h"
#include "TimeoutChecker.h"
#include <wtf/Forward.h>
@@ -45,15 +46,14 @@ struct OpaqueJSClassContextData;
namespace JSC {
+ class CodeBlock;
class CommonIdentifiers;
- class FunctionBodyNode;
class IdentifierTable;
class Interpreter;
class JSGlobalObject;
class JSObject;
class Lexer;
class Parser;
- class ScopeNode;
class Stringifier;
class Structure;
class UString;
@@ -115,6 +115,7 @@ namespace JSC {
CommonIdentifiers* propertyNames;
const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
SmallStrings smallStrings;
+ NumericStrings numericStrings;
#if ENABLE(ASSEMBLER)
ExecutableAllocator executableAllocator;
@@ -145,10 +146,18 @@ namespace JSC {
HashSet<JSObject*> arrayVisitedElements;
- ScopeNode* scopeNodeBeingReparsed;
+ CodeBlock* functionCodeBlockBeingReparsed;
Stringifier* firstStringifierToMark;
MarkStack markStack;
+
+#ifndef NDEBUG
+ bool mainThreadOnly;
+#endif
+
+ void startSampling();
+ void stopSampling();
+ void dumpSampleData(ExecState* exec);
private:
JSGlobalData(bool isShared, const VPtrSet&);
static JSGlobalData*& sharedInstanceInternal();
diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp
index a90f18f..3bb281e 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -112,8 +112,8 @@ JSGlobalObject::~JSGlobalObject()
if (headObject == this)
headObject = 0;
- HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
- for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
(*it)->clearGlobalObject();
RegisterFile& registerFile = globalData()->interpreter->registerFile();
@@ -121,7 +121,7 @@ JSGlobalObject::~JSGlobalObject()
registerFile.setGlobalObject(0);
registerFile.setNumGlobals(0);
}
- delete d();
+ d()->destructor(d());
}
void JSGlobalObject::init(JSObject* thisValue)
@@ -129,7 +129,7 @@ void JSGlobalObject::init(JSObject* thisValue)
ASSERT(JSLock::currentThreadIsHoldingLock());
d()->globalData = Heap::heap(this)->globalData();
- d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), thisValue);
+ d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue);
JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
@@ -175,18 +175,18 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper
}
}
-void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
+void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes)
{
PropertySlot slot;
if (!symbolTableGet(propertyName, slot))
- JSVariableObject::defineGetter(exec, propertyName, getterFunc);
+ JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes);
}
-void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
+void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes)
{
PropertySlot slot;
if (!symbolTableGet(propertyName, slot))
- JSVariableObject::defineSetter(exec, propertyName, setterFunc);
+ JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes);
}
static inline JSObject* lastInPrototypeChain(JSObject* object)
@@ -258,7 +258,7 @@ void JSGlobalObject::reset(JSValue prototype)
JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get());
JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
- JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype);
+ JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get());
JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
@@ -361,8 +361,8 @@ void JSGlobalObject::markChildren(MarkStack& markStack)
{
JSVariableObject::markChildren(markStack);
- HashSet<ProgramCodeBlock*>::const_iterator end = codeBlocks().end();
- for (HashSet<ProgramCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
+ HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
+ for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
(*it)->markAggregate(markStack);
RegisterFile& registerFile = globalData()->interpreter->registerFile();
@@ -455,4 +455,9 @@ void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
#endif
}
+void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
+{
+ delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData);
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h
index cda49bd..2106783 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/JavaScriptCore/runtime/JSGlobalObject.h
@@ -22,6 +22,7 @@
#ifndef JSGlobalObject_h
#define JSGlobalObject_h
+#include "JSArray.h"
#include "JSGlobalData.h"
#include "JSVariableObject.h"
#include "NativeFunctionWrapper.h"
@@ -38,6 +39,7 @@ namespace JSC {
class Debugger;
class ErrorConstructor;
class FunctionPrototype;
+ class GlobalCodeBlock;
class GlobalEvalFunction;
class NativeErrorConstructor;
class ProgramCodeBlock;
@@ -50,14 +52,22 @@ namespace JSC {
struct HashTable;
typedef Vector<ExecState*, 16> ExecStateStack;
-
+
class JSGlobalObject : public JSVariableObject {
protected:
using JSVariableObject::JSVariableObjectData;
struct JSGlobalObjectData : public JSVariableObjectData {
- JSGlobalObjectData()
+ // We use an explicit destructor function pointer instead of a
+ // virtual destructor because we want to avoid adding a vtable
+ // pointer to this struct. Adding a vtable pointer would force the
+ // compiler to emit costly pointer fixup code when casting from
+ // JSVariableObjectData* to JSGlobalObjectData*.
+ typedef void (*Destructor)(void*);
+
+ JSGlobalObjectData(Destructor destructor)
: JSVariableObjectData(&symbolTable, 0)
+ , destructor(destructor)
, registerArraySize(0)
, globalScopeChain(NoScopeChain())
, regExpConstructor(0)
@@ -83,10 +93,8 @@ namespace JSC {
{
}
- virtual ~JSGlobalObjectData()
- {
- }
-
+ Destructor destructor;
+
size_t registerArraySize;
JSGlobalObject* next;
@@ -144,20 +152,20 @@ namespace JSC {
RefPtr<JSGlobalData> globalData;
- HashSet<ProgramCodeBlock*> codeBlocks;
+ HashSet<GlobalCodeBlock*> codeBlocks;
};
public:
void* operator new(size_t, JSGlobalData*);
explicit JSGlobalObject()
- : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData)
+ : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData))
{
init(this);
}
protected:
- JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
+ JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
: JSVariableObject(structure, data)
{
init(thisValue);
@@ -169,12 +177,13 @@ namespace JSC {
virtual void markChildren(MarkStack&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
- virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
- virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
// Linked list of all global objects that use the same JSGlobalData.
JSGlobalObject*& head() { return d()->globalData->head; }
@@ -246,7 +255,7 @@ namespace JSC {
virtual bool isDynamicScope() const;
- HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+ HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
void copyGlobalsFrom(RegisterFile&);
void copyGlobalsTo(RegisterFile&);
@@ -277,6 +286,8 @@ namespace JSC {
void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
+ static void destroyJSGlobalObjectData(void*);
+
// FIXME: Fold reset into init.
void init(JSObject* thisValue);
void reset(JSValue prototype);
@@ -325,6 +336,13 @@ namespace JSC {
return symbolTableGet(propertyName, slot);
}
+ inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ if (symbolTableGet(propertyName, descriptor))
+ return true;
+ return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ }
+
inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
{
PropertySlot slot;
@@ -334,14 +352,6 @@ namespace JSC {
return symbolTableGet(propertyName, slot, slotIsWriteable);
}
- inline JSGlobalObject* ScopeChainNode::globalObject() const
- {
- const ScopeChainNode* n = this;
- while (n->next)
- n = n->next;
- return asGlobalObject(n->object);
- }
-
inline JSValue Structure::prototypeForLookup(ExecState* exec) const
{
if (typeInfo().type() == ObjectType)
@@ -396,6 +406,33 @@ namespace JSC {
return globalData().dynamicGlobalObject;
}
+ inline JSObject* constructEmptyObject(ExecState* exec)
+ {
+ return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+ }
+
+ inline JSArray* constructEmptyArray(ExecState* exec)
+ {
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+ }
+
+ inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
+ {
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
+ }
+
+ inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
+ {
+ MarkedArgumentBuffer values;
+ values.append(singleItemValue);
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+ }
+
+ inline JSArray* constructArray(ExecState* exec, const ArgList& values)
+ {
+ return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+ }
+
class DynamicGlobalObjectScope : public Noncopyable {
public:
DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index affb99c..dc32718 100644
--- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -286,16 +286,12 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu
if (JSValue parsedObject = preparser.tryLiteralParse())
return parsedObject;
- int errLine;
- UString errMsg;
+ RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s));
+ JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
+ if (error)
+ return throwError(exec, error);
- SourceCode source = makeSource(s);
- RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-
- if (!evalNode)
- return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), NULL);
-
- return exec->interpreter()->execute(evalNode.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
+ return exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
}
JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
diff --git a/JavaScriptCore/runtime/JSNotAnObject.cpp b/JavaScriptCore/runtime/JSNotAnObject.cpp
index a542a9f..c36dc10 100644
--- a/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -93,6 +93,12 @@ bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
return false;
}
+bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
+{
+ ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+ return false;
+}
+
void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
@@ -115,7 +121,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
return false;
}
-void JSNotAnObject::getPropertyNames(ExecState* exec, PropertyNameArray&)
+void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&)
{
ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
}
diff --git a/JavaScriptCore/runtime/JSNotAnObject.h b/JavaScriptCore/runtime/JSNotAnObject.h
index b65ff5f..0d9aca6 100644
--- a/JavaScriptCore/runtime/JSNotAnObject.h
+++ b/JavaScriptCore/runtime/JSNotAnObject.h
@@ -80,6 +80,7 @@ namespace JSC {
// JSObject methods
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual void put(ExecState*, unsigned propertyName, JSValue);
@@ -87,7 +88,7 @@ namespace JSC {
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
virtual bool deleteProperty(ExecState*, unsigned propertyName);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
JSNotAnObjectErrorStub* m_exception;
};
diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp
index 0654da7..f1009b9 100644
--- a/JavaScriptCore/runtime/JSNumberCell.cpp
+++ b/JavaScriptCore/runtime/JSNumberCell.cpp
@@ -54,15 +54,11 @@ double JSNumberCell::toNumber(ExecState*) const
UString JSNumberCell::toString(ExecState*) const
{
- if (m_value == 0.0) // +0.0 or -0.0
- return "0";
return UString::from(m_value);
}
UString JSNumberCell::toThisString(ExecState*) const
{
- if (m_value == 0.0) // +0.0 or -0.0
- return "0";
return UString::from(m_value);
}
diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h
index 04cccef..6a48081 100644
--- a/JavaScriptCore/runtime/JSNumberCell.h
+++ b/JavaScriptCore/runtime/JSNumberCell.h
@@ -84,7 +84,7 @@ namespace JSC {
#endif
}
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion | HasDefaultMark)); }
private:
JSNumberCell(JSGlobalData* globalData, double value)
diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp
index d643808..297d457 100644
--- a/JavaScriptCore/runtime/JSONObject.cpp
+++ b/JavaScriptCore/runtime/JSONObject.cpp
@@ -120,38 +120,47 @@ private:
// ------------------------------ helper functions --------------------------------
-static inline JSValue unwrapBoxedPrimitive(JSValue value)
+static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
{
if (!value.isObject())
return value;
- if (!asObject(value)->inherits(&NumberObject::info) && !asObject(value)->inherits(&StringObject::info) && !asObject(value)->inherits(&BooleanObject::info))
- return value;
- return static_cast<JSWrapperObject*>(asObject(value))->internalValue();
+ JSObject* object = asObject(value);
+ if (object->inherits(&NumberObject::info))
+ return jsNumber(exec, object->toNumber(exec));
+ if (object->inherits(&StringObject::info))
+ return jsString(exec, object->toString(exec));
+ if (object->inherits(&BooleanObject::info))
+ return object->toPrimitive(exec);
+ return value;
}
-static inline UString gap(JSValue space)
+static inline UString gap(ExecState* exec, JSValue space)
{
- space = unwrapBoxedPrimitive(space);
+ const int maxGapLength = 10;
+ space = unwrapBoxedPrimitive(exec, space);
// If the space value is a number, create a gap string with that number of spaces.
double spaceCount;
if (space.getNumber(spaceCount)) {
- const int maxSpaceCount = 100;
int count;
- if (spaceCount > maxSpaceCount)
- count = maxSpaceCount;
+ if (spaceCount > maxGapLength)
+ count = maxGapLength;
else if (!(spaceCount > 0))
count = 0;
else
count = static_cast<int>(spaceCount);
- UChar spaces[maxSpaceCount];
+ UChar spaces[maxGapLength];
for (int i = 0; i < count; ++i)
spaces[i] = ' ';
return UString(spaces, count);
}
// If the space value is a string, use it as the gap string, otherwise use no gap string.
- return space.getString();
+ UString spaces = space.getString();
+ if (spaces.size() > maxGapLength) {
+ spaces = spaces.substr(0, maxGapLength);
+ }
+ return spaces;
}
// ------------------------------ PropertyNameForFunctionCall --------------------------------
@@ -187,7 +196,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
, m_usingArrayReplacer(false)
, m_arrayReplacerPropertyNames(exec)
, m_replacerCallType(CallTypeNone)
- , m_gap(gap(space))
+ , m_gap(gap(exec, space))
{
exec->globalData().firstStringifierToMark = this;
@@ -202,12 +211,27 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
JSValue name = array->get(exec, i);
if (exec->hadException())
break;
+
UString propertyName;
- if (!name.getString(propertyName))
+ if (name.getString(propertyName)) {
+ m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
continue;
- if (exec->hadException())
- return;
- m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
+ }
+
+ double value = 0;
+ if (name.getNumber(value)) {
+ m_arrayReplacerPropertyNames.add(Identifier::from(exec, value));
+ continue;
+ }
+
+ if (name.isObject()) {
+ if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info))
+ continue;
+ propertyName = name.toString(exec);
+ if (exec->hadException())
+ break;
+ m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName));
+ }
}
return;
}
@@ -354,7 +378,10 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
return StringifySucceeded;
}
- value = unwrapBoxedPrimitive(value);
+ value = unwrapBoxedPrimitive(m_exec, value);
+
+ if (m_exec->hadException())
+ return StringifyFailed;
if (value.isBoolean()) {
builder.append(value.getBoolean() ? "true" : "false");
@@ -381,6 +408,15 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
JSObject* object = asObject(value);
+ CallData callData;
+ if (object->getCallData(callData) != CallTypeNone) {
+ if (holder->inherits(&JSArray::info)) {
+ builder.append("null");
+ return StringifySucceeded;
+ }
+ return StringifyFailedDueToUndefinedValue;
+ }
+
// Handle cycle detection, and put the holder on the stack.
if (!m_holderCycleDetector.add(object).second) {
throwError(m_exec, TypeError, "JSON.stringify cannot serialize cyclic structures.");
@@ -572,13 +608,12 @@ const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable };
bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
- const HashEntry* entry = ExecState::jsonTable(exec)->entry(exec, propertyName);
- if (!entry)
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, slot);
+}
- ASSERT(entry->attributes() & Function);
- setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
- return true;
+bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
}
void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
@@ -597,11 +632,11 @@ public:
}
JSValue walk(JSValue unfiltered);
private:
- JSValue callReviver(JSValue property, JSValue unfiltered)
+ JSValue callReviver(JSObject* thisObj, JSValue property, JSValue unfiltered)
{
JSValue args[] = { property, unfiltered };
ArgList argList(args, 2);
- return call(m_exec, m_function, m_callType, m_callData, jsNull(), argList);
+ return call(m_exec, m_function, m_callType, m_callData, thisObj, argList);
}
friend class Holder;
@@ -611,7 +646,10 @@ private:
CallType m_callType;
CallData m_callData;
};
-
+
+// We clamp recursion well beyond anything reasonable, but we also have a timeout check
+// to guard against "infinite" execution by inserting arbitrarily large objects.
+static const unsigned maximumFilterRecursion = 40000;
enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
@@ -625,12 +663,21 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
WalkerState state = StateUnknown;
JSValue inValue = unfiltered;
JSValue outValue = jsNull();
+
+ TimeoutChecker localTimeoutChecker(m_exec->globalData().timeoutChecker);
+ localTimeoutChecker.reset();
+ unsigned tickCount = localTimeoutChecker.ticksUntilNextCheck();
while (1) {
switch (state) {
arrayStartState:
case ArrayStartState: {
ASSERT(inValue.isObject());
- ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)));
+ ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::info));
+ if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
+ m_exec->setException(createStackOverflowError(m_exec));
+ return jsUndefined();
+ }
+
JSArray* array = asArray(inValue);
arrayStack.append(array);
indexStack.append(0);
@@ -638,6 +685,14 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
}
arrayStartVisitMember:
case ArrayStartVisitMember: {
+ if (!--tickCount) {
+ if (localTimeoutChecker.didTimeOut(m_exec)) {
+ m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+ return jsUndefined();
+ }
+ tickCount = localTimeoutChecker.ticksUntilNextCheck();
+ }
+
JSArray* array = arrayStack.last();
uint32_t index = indexStack.last();
if (index == array->length()) {
@@ -646,7 +701,16 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
indexStack.removeLast();
break;
}
- inValue = array->getIndex(index);
+ if (isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index))
+ inValue = array->getIndex(index);
+ else {
+ PropertySlot slot;
+ if (array->getOwnPropertySlot(m_exec, index, slot))
+ inValue = slot.getValue(m_exec, index);
+ else
+ inValue = jsUndefined();
+ }
+
if (inValue.isObject()) {
stateStack.append(ArrayEndVisitMember);
goto stateUnknown;
@@ -656,7 +720,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
}
case ArrayEndVisitMember: {
JSArray* array = arrayStack.last();
- array->setIndex(indexStack.last(), callReviver(jsString(m_exec, UString::from(indexStack.last())), outValue));
+ JSValue filteredValue = callReviver(array, jsString(m_exec, UString::from(indexStack.last())), outValue);
+ if (filteredValue.isUndefined())
+ array->deleteProperty(m_exec, indexStack.last());
+ else {
+ if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last()))
+ array->setIndex(indexStack.last(), filteredValue);
+ else
+ array->put(m_exec, indexStack.last(), filteredValue);
+ }
if (m_exec->hadException())
return jsNull();
indexStack.last()++;
@@ -665,7 +737,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
objectStartState:
case ObjectStartState: {
ASSERT(inValue.isObject());
- ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)));
+ ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::info));
+ if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
+ m_exec->setException(createStackOverflowError(m_exec));
+ return jsUndefined();
+ }
+
JSObject* object = asObject(inValue);
objectStack.append(object);
indexStack.append(0);
@@ -675,6 +752,14 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
}
objectStartVisitMember:
case ObjectStartVisitMember: {
+ if (!--tickCount) {
+ if (localTimeoutChecker.didTimeOut(m_exec)) {
+ m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+ return jsUndefined();
+ }
+ tickCount = localTimeoutChecker.ticksUntilNextCheck();
+ }
+
JSObject* object = objectStack.last();
uint32_t index = indexStack.last();
PropertyNameArray& properties = propertyStack.last();
@@ -686,9 +771,15 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
break;
}
PropertySlot slot;
- object->getOwnPropertySlot(m_exec, properties[index], slot);
- inValue = slot.getValue(m_exec, properties[index]);
- ASSERT(!m_exec->hadException());
+ if (object->getOwnPropertySlot(m_exec, properties[index], slot))
+ inValue = slot.getValue(m_exec, properties[index]);
+ else
+ inValue = jsUndefined();
+
+ // The holder may be modified by the reviver function so any lookup may throw
+ if (m_exec->hadException())
+ return jsNull();
+
if (inValue.isObject()) {
stateStack.append(ObjectEndVisitMember);
goto stateUnknown;
@@ -700,7 +791,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
JSObject* object = objectStack.last();
Identifier prop = propertyStack.last()[indexStack.last()];
PutPropertySlot slot;
- object->put(m_exec, prop, callReviver(jsString(m_exec, prop.ustring()), outValue), slot);
+ JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
+ if (filteredValue.isUndefined())
+ object->deleteProperty(m_exec, prop);
+ else
+ object->put(m_exec, prop, filteredValue, slot);
if (m_exec->hadException())
return jsNull();
indexStack.last()++;
@@ -712,16 +807,29 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
outValue = inValue;
break;
}
- if (isJSArray(&m_exec->globalData(), asObject(inValue)))
+ JSObject* object = asObject(inValue);
+ if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info))
goto arrayStartState;
goto objectStartState;
}
if (stateStack.isEmpty())
break;
+
state = stateStack.last();
stateStack.removeLast();
+
+ if (!--tickCount) {
+ if (localTimeoutChecker.didTimeOut(m_exec)) {
+ m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+ return jsUndefined();
+ }
+ tickCount = localTimeoutChecker.ticksUntilNextCheck();
+ }
}
- return callReviver(jsEmptyString(m_exec), outValue);
+ JSObject* finalHolder = constructEmptyObject(m_exec);
+ PutPropertySlot slot;
+ finalHolder->put(m_exec, m_exec->globalData().propertyNames->emptyIdentifier, outValue, slot);
+ return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
}
// ECMA-262 v5 15.12.2
diff --git a/JavaScriptCore/runtime/JSONObject.h b/JavaScriptCore/runtime/JSONObject.h
index faca7c7..65c9803 100644
--- a/JavaScriptCore/runtime/JSONObject.h
+++ b/JavaScriptCore/runtime/JSONObject.h
@@ -34,20 +34,21 @@ namespace JSC {
class JSONObject : public JSObject {
public:
- JSONObject(PassRefPtr<Structure> structure)
+ JSONObject(NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
{
}
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
}
static void markStringifiers(MarkStack&, Stringifier*);
private:
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp
index 419dfe9..db2a9b2 100644
--- a/JavaScriptCore/runtime/JSObject.cpp
+++ b/JavaScriptCore/runtime/JSObject.cpp
@@ -30,6 +30,7 @@
#include "JSGlobalObject.h"
#include "NativeErrorConstructor.h"
#include "ObjectPrototype.h"
+#include "PropertyDescriptor.h"
#include "PropertyNameArray.h"
#include "Lookup.h"
#include "Nodes.h"
@@ -37,43 +38,22 @@
#include <math.h>
#include <wtf/Assertions.h>
-#define JSOBJECT_MARK_TRACING 0
-
-#if JSOBJECT_MARK_TRACING
-
-#define JSOBJECT_MARK_BEGIN() \
- static int markStackDepth = 0; \
- for (int i = 0; i < markStackDepth; i++) \
- putchar('-'); \
- printf("%s (%p)\n", className().UTF8String().c_str(), this); \
- markStackDepth++; \
-
-#define JSOBJECT_MARK_END() \
- markStackDepth--;
-
-#else // JSOBJECT_MARK_TRACING
-
-#define JSOBJECT_MARK_BEGIN()
-#define JSOBJECT_MARK_END()
-
-#endif // JSOBJECT_MARK_TRACING
-
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSObject);
void JSObject::markChildren(MarkStack& markStack)
{
- JSOBJECT_MARK_BEGIN();
+#ifndef NDEBUG
+ bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation;
+ markStack.m_isCheckingForDefaultMarkViolation = false;
+#endif
- JSCell::markChildren(markStack);
- m_structure->markAggregate(markStack);
+ markChildrenDirect(markStack);
- PropertyStorage storage = propertyStorage();
- size_t storageSize = m_structure->propertyStorageSize();
- markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize);
-
- JSOBJECT_MARK_END();
+#ifndef NDEBUG
+ markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
+#endif
}
UString JSObject::className() const
@@ -295,7 +275,7 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
return 0;
}
-void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
@@ -306,7 +286,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter(exec);
- putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
@@ -322,7 +302,7 @@ void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSO
getterSetter->setGetter(getterFunction);
}
-void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
JSValue object = getDirect(propertyName);
if (object && object.isGetterSetter()) {
@@ -333,7 +313,7 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
PutPropertySlot slot;
GetterSetter* getterSetter = new (exec) GetterSetter(exec);
- putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot);
+ putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
// putDirect will change our Structure if we add a new property. For
// getters and setters, though, we also need to change our Structure
@@ -447,6 +427,11 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName
m_structure->getEnumerablePropertyNames(exec, propertyNames, this);
}
+void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ m_structure->getOwnEnumerablePropertyNames(exec, propertyNames, this);
+}
+
bool JSObject::toBoolean(ExecState*) const
{
return true;
@@ -486,7 +471,7 @@ JSObject* JSObject::unwrappedObject()
void JSObject::removeDirect(const Identifier& propertyName)
{
size_t offset;
- if (m_structure->isDictionary()) {
+ if (m_structure->isUncacheableDictionary()) {
offset = m_structure->removePropertyWithoutTransition(propertyName);
if (offset != WTF::notFound)
putDirectOffset(offset, jsUndefined());
@@ -528,9 +513,154 @@ void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
allocatePropertyStorageInline(oldSize, newSize);
}
-JSObject* constructEmptyObject(ExecState* exec)
+bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ unsigned attributes = 0;
+ JSCell* cell = 0;
+ size_t offset = m_structure->get(propertyName, attributes, cell);
+ if (offset == WTF::notFound)
+ return false;
+ descriptor.setDescriptor(getDirectOffset(offset), attributes);
+ return true;
+}
+
+bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
- return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+ JSObject* object = this;
+ while (true) {
+ if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+ JSValue prototype = object->prototype();
+ if (!prototype.isObject())
+ return false;
+ object = asObject(prototype);
+ }
+}
+
+static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
+{
+ if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
+ target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
+ return true;
+ }
+ attributes &= ~ReadOnly;
+ if (descriptor.getter() && descriptor.getter().isObject())
+ target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
+ if (exec->hadException())
+ return false;
+ if (descriptor.setter() && descriptor.setter().isObject())
+ target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
+ return !exec->hadException();
+}
+
+bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
+{
+ // If we have a new property we can just put it on normally
+ PropertyDescriptor current;
+ if (!getOwnPropertyDescriptor(exec, propertyName, current))
+ return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
+
+ if (descriptor.isEmpty())
+ return true;
+
+ if (current.equalTo(descriptor))
+ return true;
+
+ // Filter out invalid changes
+ if (!current.configurable()) {
+ if (descriptor.configurable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property.");
+ return false;
+ }
+ if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property.");
+ return false;
+ }
+ }
+
+ // A generic descriptor is simply changing the attributes of an existing property
+ if (descriptor.isGenericDescriptor()) {
+ if (!current.attributesEqual(descriptor)) {
+ deleteProperty(exec, propertyName);
+ putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+ }
+ return true;
+ }
+
+ // Changing between a normal property or an accessor property
+ if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
+ if (!current.configurable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property.");
+ return false;
+ }
+ deleteProperty(exec, propertyName);
+ return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
+ }
+
+ // Changing the value and attributes of an existing property
+ if (descriptor.isDataDescriptor()) {
+ if (!current.configurable()) {
+ if (!current.writable() && descriptor.writable()) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property.");
+ return false;
+ }
+ if (!current.writable()) {
+ if (descriptor.value() || !JSValue::strictEqual(current.value(), descriptor.value())) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change value of a readonly property.");
+ return false;
+ }
+ }
+ } else if (current.attributesEqual(descriptor)) {
+ if (!descriptor.value())
+ return true;
+ PutPropertySlot slot;
+ put(exec, propertyName, descriptor.value(), slot);
+ if (exec->hadException())
+ return false;
+ return true;
+ }
+ deleteProperty(exec, propertyName);
+ return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+ }
+
+ // Changing the accessor functions of an existing accessor property
+ ASSERT(descriptor.isAccessorDescriptor());
+ if (!current.configurable()) {
+ if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(current.setter(), descriptor.setter()))) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property.");
+ return false;
+ }
+ if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(current.getter(), descriptor.getter()))) {
+ if (throwException)
+ throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property.");
+ return false;
+ }
+ }
+ JSValue accessor = getDirect(propertyName);
+ if (!accessor)
+ return false;
+ GetterSetter* getterSetter = asGetterSetter(accessor);
+ if (current.attributesEqual(descriptor)) {
+ if (descriptor.setter())
+ getterSetter->setSetter(asObject(descriptor.setter()));
+ if (descriptor.getter())
+ getterSetter->setGetter(asObject(descriptor.getter()));
+ return true;
+ }
+ deleteProperty(exec, propertyName);
+ unsigned attrs = current.attributesWithOverride(descriptor);
+ if (descriptor.setter())
+ attrs |= Setter;
+ if (descriptor.getter())
+ attrs |= Getter;
+ putDirect(propertyName, getterSetter, attrs);
+ return true;
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h
index decd5e9..84b5f4b 100644
--- a/JavaScriptCore/runtime/JSObject.h
+++ b/JavaScriptCore/runtime/JSObject.h
@@ -27,7 +27,9 @@
#include "ClassInfo.h"
#include "CommonIdentifiers.h"
#include "CallFrame.h"
+#include "JSCell.h"
#include "JSNumberCell.h"
+#include "MarkStack.h"
#include "PropertySlot.h"
#include "PutPropertySlot.h"
#include "ScopeChain.h"
@@ -46,6 +48,7 @@ namespace JSC {
class HashEntry;
class InternalFunction;
+ class PropertyDescriptor;
class PropertyNameArray;
class Structure;
struct HashTable;
@@ -71,20 +74,19 @@ namespace JSC {
friend class JSCell;
public:
- explicit JSObject(PassRefPtr<Structure>);
+ explicit JSObject(NonNullPassRefPtr<Structure>);
virtual void markChildren(MarkStack&);
+ ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack);
// The inline virtual destructor cannot be the first virtual function declared
// in the class as it results in the vtable being generated as a weak symbol
virtual ~JSObject();
- bool inherits(const ClassInfo* classInfo) const { return JSCell::isObject(classInfo); }
-
JSValue prototype() const;
void setPrototype(JSValue prototype);
- void setStructure(PassRefPtr<Structure>);
+ void setStructure(NonNullPassRefPtr<Structure>);
Structure* inheritorID();
virtual UString className() const;
@@ -94,9 +96,11 @@ namespace JSC {
bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
virtual void put(ExecState*, unsigned propertyName, JSValue value);
@@ -119,6 +123,7 @@ namespace JSC {
virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty);
virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
@@ -181,10 +186,11 @@ namespace JSC {
void fillGetterPropertySlot(PropertySlot&, JSValue* location);
- virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
- virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
+ virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
+ virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
+ virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
virtual bool isGlobalObject() const { return false; }
virtual bool isVariableObject() const { return false; }
@@ -201,10 +207,33 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot));
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ }
+
+ protected:
+ void addAnonymousSlots(unsigned count);
+ void putAnonymousValue(unsigned index, JSValue value)
+ {
+ *locationForOffset(index) = value;
+ }
+ JSValue getAnonymousValue(unsigned index)
+ {
+ return *locationForOffset(index);
}
private:
+ // Nobody should ever ask any of these questions on something already known to be a JSObject.
+ using JSCell::isAPIValueWrapper;
+ using JSCell::isGetterSetter;
+ using JSCell::toObject;
+ void getObject();
+ void getString();
+ void isObject();
+ void isString();
+#if USE(JSVALUE32)
+ void isNumber();
+#endif
+
ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
@@ -235,18 +264,20 @@ namespace JSC {
RefPtr<Structure> m_inheritorID;
};
-JSObject* constructEmptyObject(ExecState*);
+inline JSObject* asObject(JSCell* cell)
+{
+ ASSERT(cell->isObject());
+ return static_cast<JSObject*>(cell);
+}
inline JSObject* asObject(JSValue value)
{
- ASSERT(asCell(value)->isObject());
- return static_cast<JSObject*>(asCell(value));
+ return asObject(value.asCell());
}
-inline JSObject::JSObject(PassRefPtr<Structure> structure)
+inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure)
: JSCell(structure.releaseRef()) // ~JSObject balances this ref()
{
- ASSERT(m_structure);
ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
ASSERT(m_structure->isEmpty());
ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
@@ -275,7 +306,7 @@ inline void JSObject::setPrototype(JSValue prototype)
setStructure(newStructure.release());
}
-inline void JSObject::setStructure(PassRefPtr<Structure> structure)
+inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure)
{
m_structure->deref();
m_structure = structure.releaseRef(); // ~JSObject balances this ref()
@@ -293,7 +324,7 @@ inline bool Structure::isUsingInlineStorage() const
return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
}
-inline bool JSCell::isObject(const ClassInfo* info) const
+inline bool JSCell::inherits(const ClassInfo* info) const
{
for (const ClassInfo* ci = classInfo(); ci; ci = ci->parentClass) {
if (ci == info)
@@ -302,10 +333,10 @@ inline bool JSCell::isObject(const ClassInfo* info) const
return false;
}
-// this method is here to be after the inline declaration of JSCell::isObject
-inline bool JSValue::isObject(const ClassInfo* classInfo) const
+// this method is here to be after the inline declaration of JSCell::inherits
+inline bool JSValue::inherits(const ClassInfo* classInfo) const
{
- return isCell() && asCell()->isObject(classInfo);
+ return isCell() && asCell()->inherits(classInfo);
}
ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -454,7 +485,18 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue
return;
}
+ // If we have a specific function, we may have got to this point if there is
+ // already a transition with the correct property name and attributes, but
+ // specialized to a different function. In this case we just want to give up
+ // and despecialize the transition.
+ // In this case we clear the value of specificFunction which will result
+ // in us adding a non-specific transition, and any subsequent lookup in
+ // Structure::addPropertyTransitionToExistingStructure will just use that.
+ if (specificFunction && m_structure->hasTransition(propertyName, attributes))
+ specificFunction = 0;
+
RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);
+
if (currentCapacity != structure->propertyStorageCapacity())
allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
@@ -480,6 +522,17 @@ inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
}
+inline void JSObject::addAnonymousSlots(unsigned count)
+{
+ size_t currentCapacity = m_structure->propertyStorageCapacity();
+ RefPtr<Structure> structure = Structure::addAnonymousSlotsTransition(m_structure, count);
+
+ if (currentCapacity != structure->propertyStorageCapacity())
+ allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
+
+ setStructure(structure.release());
+}
+
inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
{
ASSERT(value);
@@ -555,8 +608,7 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro
while (true) {
if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
return slot.getValue(exec, propertyName);
- ASSERT(cell->isObject());
- JSValue prototype = static_cast<JSObject*>(cell)->prototype();
+ JSValue prototype = asObject(cell)->prototype();
if (!prototype.isObject())
return jsUndefined();
cell = asObject(prototype);
@@ -581,8 +633,7 @@ inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot
while (true) {
if (cell->getOwnPropertySlot(exec, propertyName, slot))
return slot.getValue(exec, propertyName);
- ASSERT(cell->isObject());
- JSValue prototype = static_cast<JSObject*>(cell)->prototype();
+ JSValue prototype = asObject(cell)->prototype();
if (!prototype.isObject())
return jsUndefined();
cell = prototype.asCell();
@@ -627,6 +678,17 @@ ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_
m_externalStorage = newPropertyStorage;
}
+ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
+{
+ JSCell::markChildren(markStack);
+
+ m_structure->markAggregate(markStack);
+
+ PropertyStorage storage = propertyStorage();
+ size_t storageSize = m_structure->propertyStorageSize();
+ markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize);
+}
+
} // namespace JSC
#endif // JSObject_h
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index dc0304f..e08a3d9 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -37,42 +37,6 @@ JSPropertyNameIterator::~JSPropertyNameIterator()
{
}
-JSValue JSPropertyNameIterator::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
- ASSERT_NOT_REACHED();
- return JSValue();
-}
-
-bool JSPropertyNameIterator::getPrimitiveNumber(ExecState*, double&, JSValue&)
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-bool JSPropertyNameIterator::toBoolean(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return false;
-}
-
-double JSPropertyNameIterator::toNumber(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
-UString JSPropertyNameIterator::toString(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return "";
-}
-
-JSObject* JSPropertyNameIterator::toObject(ExecState*) const
-{
- ASSERT_NOT_REACHED();
- return 0;
-}
-
void JSPropertyNameIterator::markChildren(MarkStack& markStack)
{
JSCell::markChildren(markStack);
diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h
index 4534528..d2849a8 100644
--- a/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -44,13 +44,6 @@ namespace JSC {
virtual ~JSPropertyNameIterator();
- virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&);
- virtual bool toBoolean(ExecState*) const;
- virtual double toNumber(ExecState*) const;
- virtual UString toString(ExecState*) const;
- virtual JSObject* toObject(ExecState*) const;
-
virtual void markChildren(MarkStack&);
JSValue next(ExecState*);
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
index 86f95e0..91ddaeb 100644
--- a/JavaScriptCore/runtime/JSString.cpp
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -103,6 +103,33 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam
return true;
}
+bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (propertyName == exec->propertyNames().length) {
+ descriptor.setDescriptor(jsNumber(exec, m_value.size()), DontEnum | DontDelete | ReadOnly);
+ return true;
+ }
+
+ bool isStrictUInt32;
+ unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+ if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
+ descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly);
+ return true;
+ }
+
+ return false;
+}
+
+bool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (getStringPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+ if (propertyName != exec->propertyNames().underscoreProto)
+ return false;
+ descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum);
+ return true;
+}
+
bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
// The semantics here are really getPropertySlot, not getOwnPropertySlot.
diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h
index 3daf58a..1e46551 100644
--- a/JavaScriptCore/runtime/JSString.h
+++ b/JavaScriptCore/runtime/JSString.h
@@ -27,6 +27,7 @@
#include "CommonIdentifiers.h"
#include "Identifier.h"
#include "JSNumberCell.h"
+#include "PropertyDescriptor.h"
#include "PropertySlot.h"
namespace JSC {
@@ -86,11 +87,12 @@ namespace JSC {
bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
JSString* getIndex(JSGlobalData*, unsigned);
- static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
+ static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion | HasDefaultMark)); }
private:
enum VPtrStealingHackType { VPtrStealingHack };
@@ -113,6 +115,7 @@ namespace JSC {
// Actually getPropertySlot, not getOwnPropertySlot (see JSCell).
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
UString m_value;
};
@@ -211,6 +214,26 @@ namespace JSC {
return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec));
}
+ inline UString JSValue::toString(ExecState* exec) const
+ {
+ if (isString())
+ return static_cast<JSString*>(asCell())->value();
+ if (isInt32())
+ return exec->globalData().numericStrings.add(asInt32());
+ if (isDouble())
+ return exec->globalData().numericStrings.add(asDouble());
+ if (isTrue())
+ return "true";
+ if (isFalse())
+ return "false";
+ if (isNull())
+ return "null";
+ if (isUndefined())
+ return "undefined";
+ ASSERT(isCell());
+ return asCell()->toString(exec);
+ }
+
} // namespace JSC
#endif // JSString_h
diff --git a/JavaScriptCore/runtime/JSType.h b/JavaScriptCore/runtime/JSType.h
index a118b87..882b218 100644
--- a/JavaScriptCore/runtime/JSType.h
+++ b/JavaScriptCore/runtime/JSType.h
@@ -33,7 +33,6 @@ namespace JSC {
NumberType = 3,
NullType = 4,
StringType = 5,
-
// The CompoundType value must come before any JSType that may have children
CompoundType = 6,
ObjectType = 7,
diff --git a/JavaScriptCore/runtime/TypeInfo.h b/JavaScriptCore/runtime/JSTypeInfo.h
index 70aeed3..279510b 100644
--- a/JavaScriptCore/runtime/TypeInfo.h
+++ b/JavaScriptCore/runtime/JSTypeInfo.h
@@ -24,8 +24,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef TypeInfo_h
-#define TypeInfo_h
+#ifndef JSTypeInfo_h
+#define JSTypeInfo_h
+
+// This file would be called TypeInfo.h, but that conflicts with <typeinfo.h>
+// in the STL on systems without case-sensitive file systems.
#include "JSType.h"
@@ -38,6 +41,8 @@ namespace JSC {
static const unsigned ImplementsDefaultHasInstance = 1 << 3;
static const unsigned NeedsThisConversion = 1 << 4;
static const unsigned HasStandardGetOwnPropertySlot = 1 << 5;
+ static const unsigned HasDefaultMark = 1 << 6;
+ static const unsigned HasDefaultGetPropertyNames = 1 << 7;
class TypeInfo {
friend class JIT;
@@ -59,7 +64,8 @@ namespace JSC {
bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; }
-
+ bool hasDefaultMark() const { return m_flags & HasDefaultMark; }
+ bool hasDefaultGetPropertyNames() const { return m_flags & HasDefaultGetPropertyNames; }
unsigned flags() const { return m_flags; }
private:
@@ -69,4 +75,4 @@ namespace JSC {
}
-#endif // TypeInfo_h
+#endif // JSTypeInfo_h
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
index 39a4093..699c1cd 100644
--- a/JavaScriptCore/runtime/JSValue.cpp
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -110,7 +110,10 @@ char* JSValue::description()
{
static const size_t size = 32;
static char description[size];
- if (isInt32())
+
+ if (!*this)
+ snprintf(description, size, "<JSValue()>");
+ else if (isInt32())
snprintf(description, size, "Int32: %d", asInt32());
else if (isDouble())
snprintf(description, size, "Double: %lf", asDouble());
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
index 408c187..3c511d8 100644
--- a/JavaScriptCore/runtime/JSValue.h
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -20,15 +20,14 @@
*
*/
-#include <stddef.h> // for size_t
-#include <stdint.h>
-
#ifndef JSValue_h
#define JSValue_h
#include "CallData.h"
#include "ConstructData.h"
#include <math.h>
+#include <stddef.h> // for size_t
+#include <stdint.h>
#include <wtf/AlwaysInline.h>
#include <wtf/Assertions.h>
#include <wtf/HashTraits.h>
@@ -42,7 +41,6 @@ namespace JSC {
class JSImmediate;
class JSObject;
class JSString;
- class MarkStack;
class PropertySlot;
class PutPropertySlot;
class UString;
@@ -130,7 +128,7 @@ namespace JSC {
bool isString() const;
bool isGetterSetter() const;
bool isObject() const;
- bool isObject(const ClassInfo*) const;
+ bool inherits(const ClassInfo*) const;
// Extracting the value.
bool getBoolean(bool&) const;
@@ -172,12 +170,6 @@ namespace JSC {
// signle precision float is not a representation used in JS or JSC).
float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); }
- // Garbage collection.
- void markChildren(MarkStack&);
- bool hasChildren() const;
- bool marked() const;
- void markDirect();
-
// Object operations, with the toObject operation included.
JSValue get(ExecState*, const Identifier& propertyName) const;
JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const;
@@ -221,7 +213,8 @@ namespace JSC {
enum { FalseTag = 0xfffffffc };
enum { NullTag = 0xfffffffb };
enum { UndefinedTag = 0xfffffffa };
- enum { DeletedValueTag = 0xfffffff9 };
+ enum { EmptyValueTag = 0xfffffff9 };
+ enum { DeletedValueTag = 0xfffffff8 };
enum { LowestTag = DeletedValueTag };
@@ -435,7 +428,7 @@ namespace JSC {
inline JSValue::JSValue()
{
- u.asBits.tag = CellTag;
+ u.asBits.tag = EmptyValueTag;
u.asBits.payload = 0;
}
@@ -471,19 +464,26 @@ namespace JSC {
inline JSValue::JSValue(JSCell* ptr)
{
- u.asBits.tag = CellTag;
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
u.asBits.payload = reinterpret_cast<int32_t>(ptr);
}
inline JSValue::JSValue(const JSCell* ptr)
{
- u.asBits.tag = CellTag;
+ if (ptr)
+ u.asBits.tag = CellTag;
+ else
+ u.asBits.tag = EmptyValueTag;
u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
}
inline JSValue::operator bool() const
{
- return u.asBits.payload || tag() != CellTag;
+ ASSERT(tag() != DeletedValueTag);
+ return tag() != EmptyValueTag;
}
inline bool JSValue::operator==(const JSValue& other) const
diff --git a/JavaScriptCore/runtime/JSVariableObject.cpp b/JavaScriptCore/runtime/JSVariableObject.cpp
index a36cefa..6586393 100644
--- a/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -30,6 +30,7 @@
#include "JSVariableObject.h"
#include "PropertyNameArray.h"
+#include "PropertyDescriptor.h"
namespace JSC {
@@ -41,7 +42,7 @@ bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propert
return JSObject::deleteProperty(exec, propertyName);
}
-void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
SymbolTable::const_iterator end = symbolTable().end();
for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
@@ -49,7 +50,7 @@ void JSVariableObject::getPropertyNames(ExecState* exec, PropertyNameArray& prop
propertyNames.add(Identifier(exec, it->first.get()));
}
- JSObject::getPropertyNames(exec, propertyNames);
+ JSObject::getOwnPropertyNames(exec, propertyNames);
}
bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
@@ -67,4 +68,14 @@ bool JSVariableObject::isVariableObject() const
return true;
}
+bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+ if (!entry.isNull()) {
+ descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete);
+ return true;
+ }
+ return false;
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSVariableObject.h b/JavaScriptCore/runtime/JSVariableObject.h
index b969da5..66e78c3 100644
--- a/JavaScriptCore/runtime/JSVariableObject.h
+++ b/JavaScriptCore/runtime/JSVariableObject.h
@@ -49,7 +49,7 @@ namespace JSC {
virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
virtual bool deleteProperty(ExecState*, const Identifier&);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual bool isVariableObject() const;
virtual bool isDynamicScope() const = 0;
@@ -58,6 +58,11 @@ namespace JSC {
Register& registerAt(int index) const { return d->registers[index]; }
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark));
+ }
+
protected:
// Subclasses of JSVariableObject can subclass this struct to add data
// without increasing their own size (since there's a hard limit on the
@@ -79,7 +84,7 @@ namespace JSC {
JSVariableObjectData& operator=(const JSVariableObjectData&);
};
- JSVariableObject(PassRefPtr<Structure> structure, JSVariableObjectData* data)
+ JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
: JSObject(structure)
, d(data) // Subclass owns this pointer.
{
@@ -89,6 +94,7 @@ namespace JSC {
void setRegisters(Register* r, Register* registerArray);
bool symbolTableGet(const Identifier&, PropertySlot&);
+ bool symbolTableGet(const Identifier&, PropertyDescriptor&);
bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
bool symbolTablePut(const Identifier&, JSValue);
bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
diff --git a/JavaScriptCore/runtime/JSWrapperObject.h b/JavaScriptCore/runtime/JSWrapperObject.h
index 0b2c680..723b75d 100644
--- a/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/JavaScriptCore/runtime/JSWrapperObject.h
@@ -25,33 +25,41 @@
#include "JSObject.h"
namespace JSC {
-
+
// This class is used as a base for classes such as String,
// Number, Boolean and Date which are wrappers for primitive types.
class JSWrapperObject : public JSObject {
protected:
- explicit JSWrapperObject(PassRefPtr<Structure>);
+ explicit JSWrapperObject(NonNullPassRefPtr<Structure>);
public:
JSValue internalValue() const { return m_internalValue; }
void setInternalValue(JSValue);
-
+
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames | HasDefaultMark));
+ }
+
+ private:
virtual void markChildren(MarkStack&);
- private:
JSValue m_internalValue;
};
-
- inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure)
+
+ inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
{
+ addAnonymousSlots(1);
+ putAnonymousValue(0, jsNull());
}
-
+
inline void JSWrapperObject::setInternalValue(JSValue value)
{
ASSERT(value);
ASSERT(!value.isObject());
m_internalValue = value;
+ putAnonymousValue(0, value);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/LiteralParser.cpp b/JavaScriptCore/runtime/LiteralParser.cpp
index 17ec906..d242282 100644
--- a/JavaScriptCore/runtime/LiteralParser.cpp
+++ b/JavaScriptCore/runtime/LiteralParser.cpp
@@ -295,7 +295,10 @@ JSValue LiteralParser::parse(ParserState initialState)
}
doParseArrayStartExpression:
case DoParseArrayStartExpression: {
+ TokenType lastToken = m_lexer.currentToken().type;
if (m_lexer.next() == TokRBracket) {
+ if (lastToken == TokComma)
+ return JSValue();
m_lexer.next();
lastValue = objectStack.last();
objectStack.removeLast();
diff --git a/JavaScriptCore/runtime/LiteralParser.h b/JavaScriptCore/runtime/LiteralParser.h
index bceee7c..0f8072b 100644
--- a/JavaScriptCore/runtime/LiteralParser.h
+++ b/JavaScriptCore/runtime/LiteralParser.h
@@ -89,7 +89,7 @@ namespace JSC {
private:
TokenType lex(LiteralParserToken&);
- template <ParserMode parserMode> TokenType lexString(LiteralParserToken&);
+ template <ParserMode mode> TokenType lexString(LiteralParserToken&);
TokenType lexNumber(LiteralParserToken&);
LiteralParserToken m_currentToken;
UString m_string;
diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h
index 167f2bc..4d70689 100644
--- a/JavaScriptCore/runtime/Lookup.h
+++ b/JavaScriptCore/runtime/Lookup.h
@@ -51,7 +51,7 @@ namespace JSC {
typedef PropertySlot::GetValueFunc GetFunction;
typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
- class HashEntry {
+ class HashEntry : public FastAllocBase {
public:
void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2)
{
@@ -186,6 +186,24 @@ namespace JSC {
return true;
}
+ template <class ThisImp, class ParentImp>
+ inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ const HashEntry* entry = table->entry(exec, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+
+ PropertySlot slot;
+ if (entry->attributes() & Function)
+ setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+ else
+ slot.setCustom(thisObj, entry->propertyGetter());
+
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+
/**
* Simplified version of getStaticPropertySlot in case there are only functions.
* Using this instead of getStaticPropertySlot allows 'this' to avoid implementing
@@ -204,6 +222,27 @@ namespace JSC {
setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
return true;
}
+
+ /**
+ * Simplified version of getStaticPropertyDescriptor in case there are only functions.
+ * Using this instead of getStaticPropertyDescriptor allows 'this' to avoid implementing
+ * a dummy getValueProperty.
+ */
+ template <class ParentImp>
+ inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+
+ const HashEntry* entry = table->entry(exec, propertyName);
+ if (!entry)
+ return false;
+
+ PropertySlot slot;
+ setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
/**
* Simplified version of getStaticPropertySlot in case there are no functions, only "values".
@@ -224,6 +263,25 @@ namespace JSC {
}
/**
+ * Simplified version of getStaticPropertyDescriptor in case there are no functions, only "values".
+ * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class.
+ */
+ template <class ThisImp, class ParentImp>
+ inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ const HashEntry* entry = table->entry(exec, propertyName);
+
+ if (!entry) // not found, forward to parent
+ return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+
+ ASSERT(!(entry->attributes() & Function));
+ PropertySlot slot;
+ slot.setCustom(thisObj, entry->propertyGetter());
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+
+ /**
* This one is for "put".
* It looks up a hash entry for the property to be set. If an entry
* is found it sets the value and returns true, else it returns false.
diff --git a/JavaScriptCore/runtime/MarkStack.cpp b/JavaScriptCore/runtime/MarkStack.cpp
index 80dbb17..a350c35 100644
--- a/JavaScriptCore/runtime/MarkStack.cpp
+++ b/JavaScriptCore/runtime/MarkStack.cpp
@@ -26,8 +26,7 @@
#include "config.h"
#include "MarkStack.h"
-namespace JSC
-{
+namespace JSC {
size_t MarkStack::s_pageSize = 0;
diff --git a/JavaScriptCore/runtime/MarkStack.h b/JavaScriptCore/runtime/MarkStack.h
index 7a7b3af..ba00057 100644
--- a/JavaScriptCore/runtime/MarkStack.h
+++ b/JavaScriptCore/runtime/MarkStack.h
@@ -27,33 +27,27 @@
#define MarkStack_h
#include "JSValue.h"
-
#include <wtf/Noncopyable.h>
namespace JSC {
+
+ class JSGlobalData;
class Register;
enum MarkSetProperties { MayContainNullValues, NoNullValues };
class MarkStack : Noncopyable {
public:
- MarkStack()
- : m_markSets()
- , m_values()
- {
- }
-
- ALWAYS_INLINE void append(JSValue value)
+ MarkStack(void* jsArrayVPtr)
+ : m_jsArrayVPtr(jsArrayVPtr)
+#ifndef NDEBUG
+ , m_isCheckingForDefaultMarkViolation(false)
+#endif
{
- ASSERT(value);
- if (value.marked())
- return;
- value.markDirect();
- if (value.hasChildren())
- m_values.append(value.asCell());
}
- ALWAYS_INLINE void append(JSCell* cell);
+ ALWAYS_INLINE void append(JSValue);
+ ALWAYS_INLINE void append(JSCell*);
ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
{
@@ -76,12 +70,15 @@ namespace JSC {
}
private:
+ void markChildren(JSCell*);
+
struct MarkSet {
MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
: m_values(values)
, m_end(end)
, m_properties(properties)
{
+ ASSERT(values);
}
JSValue* m_values;
JSValue* m_end;
@@ -136,6 +133,12 @@ namespace JSC {
ASSERT(m_top);
return m_data[--m_top];
}
+
+ inline T& last()
+ {
+ ASSERT(m_top);
+ return m_data[m_top - 1];
+ }
inline bool isEmpty()
{
@@ -150,7 +153,14 @@ namespace JSC {
ASSERT(0 == (size % MarkStack::pageSize()));
if (size == m_allocated)
return;
+#if PLATFORM(WIN) || PLATFORM(SYMBIAN)
+ // We cannot release a part of a region with VirtualFree. To get around this,
+ // we'll release the entire region and reallocate the size that we want.
+ releaseStack(m_data, m_allocated);
+ m_data = reinterpret_cast<T*>(allocateStack(size));
+#else
releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
+#endif
m_allocated = size;
m_capacity = m_allocated / sizeof(T);
}
@@ -162,9 +172,15 @@ namespace JSC {
T* m_data;
};
+ void* m_jsArrayVPtr;
MarkStackArray<MarkSet> m_markSets;
MarkStackArray<JSCell*> m_values;
static size_t s_pageSize;
+
+#ifndef NDEBUG
+ public:
+ bool m_isCheckingForDefaultMarkViolation;
+#endif
};
}
diff --git a/JavaScriptCore/runtime/MarkStackSymbian.cpp b/JavaScriptCore/runtime/MarkStackSymbian.cpp
new file mode 100644
index 0000000..a0ce8f6
--- /dev/null
+++ b/JavaScriptCore/runtime/MarkStackSymbian.cpp
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "MarkStack.h"
+
+#include <e32hal.h>
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+ TInt page_size;
+ UserHal::PageSizeInBytes(page_size);
+ MarkStack::s_pageSize = page_size;
+}
+
+void* MarkStack::allocateStack(size_t size)
+{
+ return fastMalloc(size);
+}
+
+void MarkStack::releaseStack(void* addr, size_t size)
+{
+ return fastFree(addr);
+}
+
+}
diff --git a/JavaScriptCore/runtime/MarkStackWin.cpp b/JavaScriptCore/runtime/MarkStackWin.cpp
index dbc3306..1fdd06a 100644
--- a/JavaScriptCore/runtime/MarkStackWin.cpp
+++ b/JavaScriptCore/runtime/MarkStackWin.cpp
@@ -43,9 +43,11 @@ void* MarkStack::allocateStack(size_t size)
{
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
}
-void MarkStack::releaseStack(void* addr, size_t size)
+void MarkStack::releaseStack(void* addr, size_t)
{
- VirtualFree(addr, size, MEM_RELEASE);
+ // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx,
+ // dwSize must be 0 if dwFreeType is MEM_RELEASE.
+ VirtualFree(addr, 0, MEM_RELEASE);
}
}
diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp
index 2572bc9..e8b7b97 100644
--- a/JavaScriptCore/runtime/MathObject.cpp
+++ b/JavaScriptCore/runtime/MathObject.cpp
@@ -85,7 +85,7 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
@end
*/
-MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
+MathObject::MathObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
{
putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
@@ -103,14 +103,12 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure)
bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
{
- const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
-
- if (!entry)
- return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+ return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot);
+}
- ASSERT(entry->attributes() & Function);
- setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
- return true;
+bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor);
}
// ------------------------------ Functions --------------------------------
diff --git a/JavaScriptCore/runtime/MathObject.h b/JavaScriptCore/runtime/MathObject.h
index 3557d1e..fee5ec5 100644
--- a/JavaScriptCore/runtime/MathObject.h
+++ b/JavaScriptCore/runtime/MathObject.h
@@ -27,16 +27,17 @@ namespace JSC {
class MathObject : public JSObject {
public:
- MathObject(ExecState*, PassRefPtr<Structure>);
+ MathObject(ExecState*, NonNullPassRefPtr<Structure>);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
}
};
diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/JavaScriptCore/runtime/NativeErrorConstructor.cpp
index 0205fc5..c655fae 100644
--- a/JavaScriptCore/runtime/NativeErrorConstructor.cpp
+++ b/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -32,7 +32,7 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
-NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype)
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString()))
, m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype))
{
diff --git a/JavaScriptCore/runtime/NativeErrorConstructor.h b/JavaScriptCore/runtime/NativeErrorConstructor.h
index 118d1f4..152dbac 100644
--- a/JavaScriptCore/runtime/NativeErrorConstructor.h
+++ b/JavaScriptCore/runtime/NativeErrorConstructor.h
@@ -31,7 +31,7 @@ namespace JSC {
class NativeErrorConstructor : public InternalFunction {
public:
- NativeErrorConstructor(ExecState*, PassRefPtr<Structure>, NativeErrorPrototype*);
+ NativeErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, NativeErrorPrototype*);
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
index 84190a0..aa46a6a 100644
--- a/JavaScriptCore/runtime/NativeErrorPrototype.cpp
+++ b/JavaScriptCore/runtime/NativeErrorPrototype.cpp
@@ -29,7 +29,7 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message)
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& name, const UString& message)
: JSObject(structure)
{
putDirect(exec->propertyNames().name, jsString(exec, name), 0);
diff --git a/JavaScriptCore/runtime/NativeErrorPrototype.h b/JavaScriptCore/runtime/NativeErrorPrototype.h
index 77bfe8a..0c65a9c 100644
--- a/JavaScriptCore/runtime/NativeErrorPrototype.h
+++ b/JavaScriptCore/runtime/NativeErrorPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class NativeErrorPrototype : public JSObject {
public:
- NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message);
+ NativeErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, const UString& name, const UString& message);
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumberConstructor.cpp b/JavaScriptCore/runtime/NumberConstructor.cpp
index 2840bf0..cc6c51d 100644
--- a/JavaScriptCore/runtime/NumberConstructor.cpp
+++ b/JavaScriptCore/runtime/NumberConstructor.cpp
@@ -53,7 +53,7 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info,
@end
*/
-NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
+NumberConstructor::NumberConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
{
// Number.Prototype
@@ -68,6 +68,11 @@ bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr
return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
}
+bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor);
+}
+
static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
{
return jsNaN(exec);
diff --git a/JavaScriptCore/runtime/NumberConstructor.h b/JavaScriptCore/runtime/NumberConstructor.h
index b1224ec..908c55f 100644
--- a/JavaScriptCore/runtime/NumberConstructor.h
+++ b/JavaScriptCore/runtime/NumberConstructor.h
@@ -29,16 +29,17 @@ namespace JSC {
class NumberConstructor : public InternalFunction {
public:
- NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*);
+ NumberConstructor(ExecState*, NonNullPassRefPtr<Structure>, NumberPrototype*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
JSValue getValueProperty(ExecState*, int token) const;
static const ClassInfo info;
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance));
+ return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames));
}
enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
diff --git a/JavaScriptCore/runtime/NumberObject.cpp b/JavaScriptCore/runtime/NumberObject.cpp
index 0e8df17..1a7e44c 100644
--- a/JavaScriptCore/runtime/NumberObject.cpp
+++ b/JavaScriptCore/runtime/NumberObject.cpp
@@ -31,7 +31,7 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject);
const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
-NumberObject::NumberObject(PassRefPtr<Structure> structure)
+NumberObject::NumberObject(NonNullPassRefPtr<Structure> structure)
: JSWrapperObject(structure)
{
}
diff --git a/JavaScriptCore/runtime/NumberObject.h b/JavaScriptCore/runtime/NumberObject.h
index d354b9b..ca3923d 100644
--- a/JavaScriptCore/runtime/NumberObject.h
+++ b/JavaScriptCore/runtime/NumberObject.h
@@ -27,10 +27,20 @@ namespace JSC {
class NumberObject : public JSWrapperObject {
public:
- explicit NumberObject(PassRefPtr<Structure>);
+ explicit NumberObject(NonNullPassRefPtr<Structure>);
static const ClassInfo info;
-
+#if USE(JSVALUE32)
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames));
+ }
+#else
+ static PassRefPtr<Structure> createStructure(JSValue prototype)
+ {
+ return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames));
+ }
+#endif
private:
virtual const ClassInfo* classInfo() const { return &info; }
diff --git a/JavaScriptCore/runtime/NumberPrototype.cpp b/JavaScriptCore/runtime/NumberPrototype.cpp
index 947324c..df31404 100644
--- a/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -45,7 +45,7 @@ static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, J
// ECMA 15.7.4
-NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+NumberPrototype::NumberPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
: NumberObject(structure)
{
setInternalValue(jsNumber(exec, 0));
diff --git a/JavaScriptCore/runtime/NumberPrototype.h b/JavaScriptCore/runtime/NumberPrototype.h
index 0a3a544..1fb2077 100644
--- a/JavaScriptCore/runtime/NumberPrototype.h
+++ b/JavaScriptCore/runtime/NumberPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class NumberPrototype : public NumberObject {
public:
- NumberPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ NumberPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/NumericStrings.h b/JavaScriptCore/runtime/NumericStrings.h
new file mode 100644
index 0000000..c0696a4
--- /dev/null
+++ b/JavaScriptCore/runtime/NumericStrings.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NumericStrings_h
+#define NumericStrings_h
+
+#include "UString.h"
+#include <wtf/HashFunctions.h>
+
+namespace JSC {
+
+ class NumericStrings {
+ public:
+ UString add(double d)
+ {
+ CacheEntry<double>& entry = lookup(d);
+ if (d == entry.key && !entry.value.isNull())
+ return entry.value;
+ entry.key = d;
+ entry.value = UString::from(d);
+ return entry.value;
+ }
+
+ UString add(int i)
+ {
+ CacheEntry<int>& entry = lookup(i);
+ if (i == entry.key && !entry.value.isNull())
+ return entry.value;
+ entry.key = i;
+ entry.value = UString::from(i);
+ return entry.value;
+ }
+
+ private:
+ static const size_t cacheSize = 64;
+
+ template<typename T>
+ struct CacheEntry {
+ T key;
+ UString value;
+ };
+
+ CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
+ CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; }
+
+ CacheEntry<double> doubleCache[cacheSize];
+ CacheEntry<int> intCache[cacheSize];
+ };
+
+} // namespace JSC
+
+#endif // NumericStrings_h
diff --git a/JavaScriptCore/runtime/ObjectConstructor.cpp b/JavaScriptCore/runtime/ObjectConstructor.cpp
index 70c7cd1..a456423 100644
--- a/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -21,9 +21,13 @@
#include "config.h"
#include "ObjectConstructor.h"
+#include "Error.h"
#include "JSFunction.h"
+#include "JSArray.h"
#include "JSGlobalObject.h"
#include "ObjectPrototype.h"
+#include "PropertyDescriptor.h"
+#include "PropertyNameArray.h"
#include "PrototypeFunction.h"
namespace JSC {
@@ -31,17 +35,27 @@ namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&);
+static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&);
-ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
- : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
+ObjectConstructor::ObjectConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
+: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
{
// ECMA 15.2.3.1
putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
-
+
// no. of arguments for constructor
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
-
+
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
+ putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum);
}
// ECMA 15.2.2
@@ -82,4 +96,205 @@ JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec, JSObject*
return asObject(args.at(0))->prototype();
}
+JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Requested property descriptor of a value that is not an object.");
+ UString propertyName = args.at(1).toString(exec);
+ if (exec->hadException())
+ return jsNull();
+ JSObject* object = asObject(args.at(0));
+ PropertyDescriptor descriptor;
+ if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
+ return jsUndefined();
+ if (exec->hadException())
+ return jsUndefined();
+
+ JSObject* description = constructEmptyObject(exec);
+ if (!descriptor.isAccessorDescriptor()) {
+ description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
+ description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
+ } else {
+ description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
+ description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
+ }
+
+ description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
+ description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
+
+ return description;
+}
+
+JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Requested keys of a value that is not an object.");
+ PropertyNameArray properties(exec);
+ asObject(args.at(0))->getOwnPropertyNames(exec, properties);
+ JSArray* keys = constructEmptyArray(exec);
+ size_t numProperties = properties.size();
+ for (size_t i = 0; i < numProperties; i++)
+ keys->push(exec, jsOwnedString(exec, properties[i].ustring()));
+ return keys;
+}
+
+// ES5 8.10.5 ToPropertyDescriptor
+static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
+{
+ if (!in.isObject()) {
+ throwError(exec, TypeError, "Property description must be an object.");
+ return false;
+ }
+ JSObject* description = asObject(in);
+
+ PropertySlot enumerableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
+ desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot configurableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
+ desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ JSValue value;
+ PropertySlot valueSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
+ desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot writableSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
+ desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
+ if (exec->hadException())
+ return false;
+ }
+
+ PropertySlot getSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
+ JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
+ if (exec->hadException())
+ return false;
+ if (!get.isUndefined()) {
+ CallData callData;
+ if (get.getCallData(callData) == CallTypeNone) {
+ throwError(exec, TypeError, "Getter must be a function.");
+ return false;
+ }
+ } else
+ get = JSValue();
+ desc.setGetter(get);
+ }
+
+ PropertySlot setSlot;
+ if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
+ JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
+ if (exec->hadException())
+ return false;
+ if (!set.isUndefined()) {
+ CallData callData;
+ if (set.getCallData(callData) == CallTypeNone) {
+ throwError(exec, TypeError, "Setter must be a function.");
+ return false;
+ }
+ } else
+ set = JSValue();
+
+ desc.setSetter(set);
+ }
+
+ if (!desc.isAccessorDescriptor())
+ return true;
+
+ if (desc.value()) {
+ throwError(exec, TypeError, "Invalid property. 'value' present on property with getter or setter.");
+ return false;
+ }
+
+ if (desc.writablePresent()) {
+ throwError(exec, TypeError, "Invalid property. 'writable' present on property with getter or setter.");
+ return false;
+ }
+ return true;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+ JSObject* O = asObject(args.at(0));
+ UString propertyName = args.at(1).toString(exec);
+ if (exec->hadException())
+ return jsNull();
+ PropertyDescriptor descriptor;
+ if (!toPropertyDescriptor(exec, args.at(2), descriptor))
+ return jsNull();
+ ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
+ ASSERT(!exec->hadException());
+ O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
+ return O;
+}
+
+static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
+{
+ PropertyNameArray propertyNames(exec);
+ asObject(properties)->getOwnPropertyNames(exec, propertyNames);
+ size_t numProperties = propertyNames.size();
+ Vector<PropertyDescriptor> descriptors;
+ MarkedArgumentBuffer markBuffer;
+ for (size_t i = 0; i < numProperties; i++) {
+ PropertySlot slot;
+ JSValue prop = properties->get(exec, propertyNames[i]);
+ if (exec->hadException())
+ return jsNull();
+ PropertyDescriptor descriptor;
+ if (!toPropertyDescriptor(exec, prop, descriptor))
+ return jsNull();
+ descriptors.append(descriptor);
+ // Ensure we mark all the values that we're accumulating
+ if (descriptor.isDataDescriptor() && descriptor.value())
+ markBuffer.append(descriptor.value());
+ if (descriptor.isAccessorDescriptor()) {
+ if (descriptor.getter())
+ markBuffer.append(descriptor.getter());
+ if (descriptor.setter())
+ markBuffer.append(descriptor.setter());
+ }
+ }
+ for (size_t i = 0; i < numProperties; i++) {
+ object->defineOwnProperty(exec, propertyNames[i], descriptors[i], true);
+ if (exec->hadException())
+ return jsNull();
+ }
+ return object;
+}
+
+JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError, "Properties can only be defined on Objects.");
+ if (!args.at(1).isObject())
+ return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+ return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1)));
+}
+
+JSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+{
+ if (!args.at(0).isObject() && !args.at(0).isNull())
+ return throwError(exec, TypeError, "Object prototype may only be an Object or null.");
+ JSObject* newObject = constructEmptyObject(exec);
+ newObject->setPrototype(args.at(0));
+ if (args.at(1).isUndefined())
+ return newObject;
+ if (!args.at(1).isObject())
+ return throwError(exec, TypeError, "Property descriptor list must be an Object.");
+ return defineProperties(exec, newObject, asObject(args.at(1)));
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ObjectConstructor.h b/JavaScriptCore/runtime/ObjectConstructor.h
index 9373781..1d2cdde 100644
--- a/JavaScriptCore/runtime/ObjectConstructor.h
+++ b/JavaScriptCore/runtime/ObjectConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class ObjectConstructor : public InternalFunction {
public:
- ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure);
+ ObjectConstructor(ExecState*, NonNullPassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure);
private:
virtual ConstructType getConstructData(ConstructData&);
diff --git a/JavaScriptCore/runtime/ObjectPrototype.cpp b/JavaScriptCore/runtime/ObjectPrototype.cpp
index 98e4713..0970b7c 100644
--- a/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -40,8 +40,9 @@ static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*,
static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
-ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
+ObjectPrototype::ObjectPrototype(ExecState* exec, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
: JSObject(stucture)
+ , m_hasNoPropertiesWithUInt32Names(true)
{
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
@@ -57,6 +58,24 @@ ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
}
+void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ JSObject::put(exec, propertyName, value, slot);
+
+ if (m_hasNoPropertiesWithUInt32Names) {
+ bool isUInt32;
+ propertyName.toStrictUInt32(&isUInt32);
+ m_hasNoPropertiesWithUInt32Names = !isUInt32;
+ }
+}
+
+bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
+{
+ if (m_hasNoPropertiesWithUInt32Names)
+ return false;
+ return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+}
+
// ------------------------------ Functions --------------------------------
// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
diff --git a/JavaScriptCore/runtime/ObjectPrototype.h b/JavaScriptCore/runtime/ObjectPrototype.h
index 7790ae0..489d962 100644
--- a/JavaScriptCore/runtime/ObjectPrototype.h
+++ b/JavaScriptCore/runtime/ObjectPrototype.h
@@ -27,7 +27,13 @@ namespace JSC {
class ObjectPrototype : public JSObject {
public:
- ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ ObjectPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+
+ private:
+ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+ virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+
+ bool m_hasNoPropertiesWithUInt32Names;
};
JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
diff --git a/JavaScriptCore/runtime/Operations.h b/JavaScriptCore/runtime/Operations.h
index c4900d3..5da9e38 100644
--- a/JavaScriptCore/runtime/Operations.h
+++ b/JavaScriptCore/runtime/Operations.h
@@ -308,20 +308,13 @@ namespace JSC {
resultRep = UString::Rep::createEmptyBuffer(bufferSize);
UString result(resultRep);
- // Loop over the openards, writing them into the output buffer.
+ // Loop over the operands, writing them into the output buffer.
for (unsigned i = 0; i < count; ++i) {
JSValue v = strings[i].jsValue();
if (LIKELY(v.isString()))
result.append(asString(v)->value());
- else if (v.isInt32())
- result.appendNumeric(v.asInt32());
- else {
- double d;
- if (v.getNumber(d))
- result.appendNumeric(d);
- else
- result.append(v.toString(callFrame));
- }
+ else
+ result.append(v.toString(callFrame));
}
return jsString(callFrame, result);
diff --git a/JavaScriptCore/runtime/PropertyDescriptor.cpp b/JavaScriptCore/runtime/PropertyDescriptor.cpp
new file mode 100644
index 0000000..4db814f
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#include "PropertyDescriptor.h"
+
+#include "GetterSetter.h"
+#include "JSObject.h"
+#include "Operations.h"
+
+namespace JSC {
+unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
+
+bool PropertyDescriptor::writable() const
+{
+ ASSERT(!isAccessorDescriptor());
+ return !(m_attributes & ReadOnly);
+}
+
+bool PropertyDescriptor::enumerable() const
+{
+ return !(m_attributes & DontEnum);
+}
+
+bool PropertyDescriptor::configurable() const
+{
+ return !(m_attributes & DontDelete);
+}
+
+bool PropertyDescriptor::isDataDescriptor() const
+{
+ return m_value || (m_seenAttributes & WritablePresent);
+}
+
+bool PropertyDescriptor::isGenericDescriptor() const
+{
+ return !isAccessorDescriptor() && !isDataDescriptor();
+}
+
+bool PropertyDescriptor::isAccessorDescriptor() const
+{
+ return m_getter || m_setter;
+}
+
+void PropertyDescriptor::setUndefined()
+{
+ m_value = jsUndefined();
+ m_attributes = ReadOnly | DontDelete | DontEnum;
+}
+
+JSValue PropertyDescriptor::getter() const
+{
+ ASSERT(isAccessorDescriptor());
+ return m_getter;
+}
+
+JSValue PropertyDescriptor::setter() const
+{
+ ASSERT(isAccessorDescriptor());
+ return m_setter;
+}
+
+void PropertyDescriptor::setDescriptor(JSValue value, unsigned attributes)
+{
+ ASSERT(value);
+ m_attributes = attributes;
+ if (attributes & (Getter | Setter)) {
+ GetterSetter* accessor = asGetterSetter(value);
+ m_getter = accessor->getter();
+ m_setter = accessor->setter();
+ ASSERT(m_getter || m_setter);
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+ m_attributes &= ~ReadOnly;
+ } else {
+ m_value = value;
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
+ }
+}
+
+void PropertyDescriptor::setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes)
+{
+ ASSERT(attributes & (Getter | Setter));
+ ASSERT(getter || setter);
+ m_attributes = attributes;
+ m_getter = getter;
+ m_setter = setter;
+ m_attributes &= ~ReadOnly;
+ m_seenAttributes = EnumerablePresent | ConfigurablePresent;
+}
+
+void PropertyDescriptor::setWritable(bool writable)
+{
+ if (writable)
+ m_attributes &= ~ReadOnly;
+ else
+ m_attributes |= ReadOnly;
+ m_seenAttributes |= WritablePresent;
+}
+
+void PropertyDescriptor::setEnumerable(bool enumerable)
+{
+ if (enumerable)
+ m_attributes &= ~DontEnum;
+ else
+ m_attributes |= DontEnum;
+ m_seenAttributes |= EnumerablePresent;
+}
+
+void PropertyDescriptor::setConfigurable(bool configurable)
+{
+ if (configurable)
+ m_attributes &= ~DontDelete;
+ else
+ m_attributes |= DontDelete;
+ m_seenAttributes |= ConfigurablePresent;
+}
+
+void PropertyDescriptor::setSetter(JSValue setter)
+{
+ m_setter = setter;
+ m_attributes |= Setter;
+ m_attributes &= ~ReadOnly;
+}
+
+void PropertyDescriptor::setGetter(JSValue getter)
+{
+ m_getter = getter;
+ m_attributes |= Getter;
+ m_attributes &= ~ReadOnly;
+}
+
+bool PropertyDescriptor::equalTo(const PropertyDescriptor& other) const
+{
+ if (!other.m_value == m_value ||
+ !other.m_getter == m_getter ||
+ !other.m_setter == m_setter)
+ return false;
+ return (!m_value || JSValue::strictEqual(other.m_value, m_value)) &&
+ (!m_getter || JSValue::strictEqual(other.m_getter, m_getter)) &&
+ (!m_setter || JSValue::strictEqual(other.m_setter, m_setter)) &&
+ attributesEqual(other);
+}
+
+bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
+{
+ unsigned mismatch = other.m_attributes ^ m_attributes;
+ unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+ if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+ return false;
+ if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+ return false;
+ if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+ return false;
+ return true;
+}
+
+unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
+{
+ unsigned mismatch = other.m_attributes ^ m_attributes;
+ unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
+ unsigned newAttributes = m_attributes & defaultAttributes;
+ if (sharedSeen & WritablePresent && mismatch & ReadOnly)
+ newAttributes ^= ReadOnly;
+ if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
+ newAttributes ^= DontDelete;
+ if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
+ newAttributes ^= DontEnum;
+ return newAttributes;
+}
+
+}
diff --git a/JavaScriptCore/runtime/PropertyDescriptor.h b/JavaScriptCore/runtime/PropertyDescriptor.h
new file mode 100644
index 0000000..40bec86
--- /dev/null
+++ b/JavaScriptCore/runtime/PropertyDescriptor.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PropertyDescriptor_h
+#define PropertyDescriptor_h
+
+#include "JSValue.h"
+
+namespace JSC {
+ class PropertyDescriptor {
+ public:
+ PropertyDescriptor()
+ : m_attributes(defaultAttributes)
+ , m_seenAttributes(0)
+ {
+ }
+ bool writable() const;
+ bool enumerable() const;
+ bool configurable() const;
+ bool isDataDescriptor() const;
+ bool isGenericDescriptor() const;
+ bool isAccessorDescriptor() const;
+ unsigned attributes() const { return m_attributes; }
+ JSValue value() const { return m_value; }
+ JSValue getter() const;
+ JSValue setter() const;
+ void setUndefined();
+ void setDescriptor(JSValue value, unsigned attributes);
+ void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
+ void setWritable(bool);
+ void setEnumerable(bool);
+ void setConfigurable(bool);
+ void setValue(JSValue value) { m_value = value; }
+ void setSetter(JSValue);
+ void setGetter(JSValue);
+ bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
+ bool writablePresent() const { return m_seenAttributes & WritablePresent; }
+ bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
+ bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; }
+ bool setterPresent() const { return m_setter; }
+ bool getterPresent() const { return m_getter; }
+ bool equalTo(const PropertyDescriptor& other) const;
+ bool attributesEqual(const PropertyDescriptor& other) const;
+ unsigned attributesWithOverride(const PropertyDescriptor& other) const;
+ private:
+ static unsigned defaultAttributes;
+ bool operator==(const PropertyDescriptor&){ return false; }
+ enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
+ // May be a getter/setter
+ JSValue m_value;
+ JSValue m_getter;
+ JSValue m_setter;
+ unsigned m_attributes;
+ unsigned m_seenAttributes;
+ };
+}
+
+#endif
diff --git a/JavaScriptCore/runtime/PropertyMapHashTable.h b/JavaScriptCore/runtime/PropertyMapHashTable.h
index 44dc2b8..5b63f79 100644
--- a/JavaScriptCore/runtime/PropertyMapHashTable.h
+++ b/JavaScriptCore/runtime/PropertyMapHashTable.h
@@ -61,6 +61,7 @@ namespace JSC {
unsigned size;
unsigned keyCount;
unsigned deletedSentinelCount;
+ unsigned anonymousSlotCount;
unsigned lastIndexUsed;
Vector<unsigned>* deletedOffsets;
unsigned entryIndices[1];
diff --git a/JavaScriptCore/runtime/PropertyNameArray.h b/JavaScriptCore/runtime/PropertyNameArray.h
index b4382f4..afcc83f 100644
--- a/JavaScriptCore/runtime/PropertyNameArray.h
+++ b/JavaScriptCore/runtime/PropertyNameArray.h
@@ -44,7 +44,7 @@ namespace JSC {
void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }
Structure* cachedStructure() const { return m_cachedStructure; }
- void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+ void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
private:
diff --git a/JavaScriptCore/runtime/PropertySlot.cpp b/JavaScriptCore/runtime/PropertySlot.cpp
index 36fa5d8..a0a2f48 100644
--- a/JavaScriptCore/runtime/PropertySlot.cpp
+++ b/JavaScriptCore/runtime/PropertySlot.cpp
@@ -23,7 +23,6 @@
#include "JSFunction.h"
#include "JSGlobalObject.h"
-#include "JSObject.h"
namespace JSC {
@@ -39,7 +38,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const P
return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
ASSERT(callType == CallTypeJS);
// FIXME: Can this be done more efficiently using the callData?
- return static_cast<JSFunction*>(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
+ return asFunction(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/PrototypeFunction.cpp b/JavaScriptCore/runtime/PrototypeFunction.cpp
index 8e3d107..38f8adb 100644
--- a/JavaScriptCore/runtime/PrototypeFunction.cpp
+++ b/JavaScriptCore/runtime/PrototypeFunction.cpp
@@ -40,7 +40,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifi
putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
}
-PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
+PrototypeFunction::PrototypeFunction(ExecState* exec, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
: InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
, m_function(function)
{
diff --git a/JavaScriptCore/runtime/PrototypeFunction.h b/JavaScriptCore/runtime/PrototypeFunction.h
index 99ab327..70ee034 100644
--- a/JavaScriptCore/runtime/PrototypeFunction.h
+++ b/JavaScriptCore/runtime/PrototypeFunction.h
@@ -32,7 +32,7 @@ namespace JSC {
class PrototypeFunction : public InternalFunction {
public:
PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
- PrototypeFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
+ PrototypeFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
private:
virtual CallType getCallData(CallData&);
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index 6a8089d..dbf2d44 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -23,6 +23,7 @@
#include "RegExpConstructor.h"
#include "ArrayPrototype.h"
+#include "Error.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "JSString.h"
@@ -111,7 +112,7 @@ struct RegExpConstructorPrivate : FastAllocBase {
unsigned lastOvectorIndex : 1;
};
-RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
+RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
, d(new RegExpConstructorPrivate)
{
@@ -233,6 +234,11 @@ bool RegExpConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& pr
return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
}
+bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor);
+}
+
JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1);
@@ -329,7 +335,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args)
JSValue arg0 = args.at(0);
JSValue arg1 = args.at(1);
- if (arg0.isObject(&RegExpObject::info)) {
+ if (arg0.inherits(&RegExpObject::info)) {
if (!arg1.isUndefined())
return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
return asObject(arg0);
diff --git a/JavaScriptCore/runtime/RegExpConstructor.h b/JavaScriptCore/runtime/RegExpConstructor.h
index 6823f3f..f8bccf4 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/JavaScriptCore/runtime/RegExpConstructor.h
@@ -32,15 +32,16 @@ namespace JSC {
class RegExpConstructor : public InternalFunction {
public:
- RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*);
+ RegExpConstructor(ExecState*, NonNullPassRefPtr<Structure>, RegExpPrototype*);
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+ return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames));
}
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/RegExpMatchesArray.h b/JavaScriptCore/runtime/RegExpMatchesArray.h
index 9ae18b9..829f7cf 100644
--- a/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -44,6 +44,13 @@ namespace JSC {
return JSArray::getOwnPropertySlot(exec, propertyName, slot);
}
+ virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+ {
+ if (lazyCreationData())
+ fillArrayInstance(exec);
+ return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+ }
+
virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
{
if (lazyCreationData())
@@ -72,11 +79,11 @@ namespace JSC {
return JSArray::deleteProperty(exec, propertyName);
}
- virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr)
+ virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr)
{
if (lazyCreationData())
fillArrayInstance(exec);
- JSArray::getPropertyNames(exec, arr);
+ JSArray::getOwnPropertyNames(exec, arr);
}
void fillArrayInstance(ExecState*);
diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp
index 687844e..877d7b6 100644
--- a/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/JavaScriptCore/runtime/RegExpObject.cpp
@@ -57,7 +57,7 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
@end
*/
-RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp)
+RegExpObject::RegExpObject(NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
: JSObject(structure)
, d(new RegExpObjectData(regExp, 0))
{
@@ -72,6 +72,11 @@ bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propert
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
}
+bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
+}
+
JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global());
diff --git a/JavaScriptCore/runtime/RegExpObject.h b/JavaScriptCore/runtime/RegExpObject.h
index e83e0ac..f5a9340 100644
--- a/JavaScriptCore/runtime/RegExpObject.h
+++ b/JavaScriptCore/runtime/RegExpObject.h
@@ -28,7 +28,7 @@ namespace JSC {
class RegExpObject : public JSObject {
public:
- RegExpObject(PassRefPtr<Structure>, PassRefPtr<RegExp>);
+ RegExpObject(NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>);
virtual ~RegExpObject();
void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
@@ -41,6 +41,7 @@ namespace JSC {
JSValue exec(ExecState*, const ArgList&);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual const ClassInfo* classInfo() const { return &info; }
@@ -48,7 +49,7 @@ namespace JSC {
static PassRefPtr<Structure> createStructure(JSValue prototype)
{
- return Structure::create(prototype, TypeInfo(ObjectType));
+ return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames));
}
private:
@@ -57,7 +58,7 @@ namespace JSC {
virtual CallType getCallData(CallData&);
struct RegExpObjectData : FastAllocBase {
- RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex)
+ RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex)
: regExp(regExp)
, lastIndex(lastIndex)
{
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index b1ab889..bbc9e85 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -22,6 +22,7 @@
#include "RegExpPrototype.h"
#include "ArrayPrototype.h"
+#include "Error.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "JSObject.h"
@@ -45,7 +46,7 @@ static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSVa
const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
-RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
+RegExpPrototype::RegExpPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
: JSObject(structure)
{
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
@@ -58,28 +59,28 @@ RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structur
JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::info))
return throwError(exec, TypeError);
return asRegExpObject(thisValue)->test(exec, args);
}
JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::info))
return throwError(exec, TypeError);
return asRegExpObject(thisValue)->exec(exec, args);
}
JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
{
- if (!thisValue.isObject(&RegExpObject::info))
+ if (!thisValue.inherits(&RegExpObject::info))
return throwError(exec, TypeError);
RefPtr<RegExp> regExp;
JSValue arg0 = args.at(0);
JSValue arg1 = args.at(1);
- if (arg0.isObject(&RegExpObject::info)) {
+ if (arg0.inherits(&RegExpObject::info)) {
if (!arg1.isUndefined())
return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
regExp = asRegExpObject(arg0)->regExp();
@@ -99,8 +100,8 @@ JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue
JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
{
- if (!thisValue.isObject(&RegExpObject::info)) {
- if (thisValue.isObject(&RegExpPrototype::info))
+ if (!thisValue.inherits(&RegExpObject::info)) {
+ if (thisValue.inherits(&RegExpPrototype::info))
return jsNontrivialString(exec, "//");
return throwError(exec, TypeError);
}
diff --git a/JavaScriptCore/runtime/RegExpPrototype.h b/JavaScriptCore/runtime/RegExpPrototype.h
index f5db720..d3979bd 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.h
+++ b/JavaScriptCore/runtime/RegExpPrototype.h
@@ -27,7 +27,7 @@ namespace JSC {
class RegExpPrototype : public JSObject {
public:
- RegExpPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+ RegExpPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/ScopeChain.cpp b/JavaScriptCore/runtime/ScopeChain.cpp
index 5c2edab..981794b 100644
--- a/JavaScriptCore/runtime/ScopeChain.cpp
+++ b/JavaScriptCore/runtime/ScopeChain.cpp
@@ -36,8 +36,8 @@ void ScopeChainNode::print() const
ScopeChainIterator scopeEnd = end();
for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
JSObject* o = *scopeIter;
- PropertyNameArray propertyNames(globalObject()->globalExec());
- o->getPropertyNames(globalObject()->globalExec(), propertyNames);
+ PropertyNameArray propertyNames(globalObject->globalExec());
+ o->getPropertyNames(globalObject->globalExec(), propertyNames);
PropertyNameArray::const_iterator propEnd = propertyNames.end();
fprintf(stderr, "----- [scope %p] -----\n", o);
@@ -56,7 +56,7 @@ int ScopeChain::localDepth() const
int scopeDepth = 0;
ScopeChainIterator iter = this->begin();
ScopeChainIterator end = this->end();
- while (!(*iter)->isObject(&JSActivation::info)) {
+ while (!(*iter)->inherits(&JSActivation::info)) {
++iter;
if (iter == end)
break;
diff --git a/JavaScriptCore/runtime/ScopeChain.h b/JavaScriptCore/runtime/ScopeChain.h
index c5e16c9..0b15b67 100644
--- a/JavaScriptCore/runtime/ScopeChain.h
+++ b/JavaScriptCore/runtime/ScopeChain.h
@@ -33,14 +33,16 @@ namespace JSC {
class ScopeChainNode : public FastAllocBase {
public:
- ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis)
+ ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
: next(next)
, object(object)
, globalData(globalData)
+ , globalObject(globalObject)
, globalThis(globalThis)
, refCount(1)
{
ASSERT(globalData);
+ ASSERT(globalObject);
}
#ifndef NDEBUG
// Due to the number of subtle and timing dependent bugs that have occurred due
@@ -51,6 +53,7 @@ namespace JSC {
next = 0;
object = 0;
globalData = 0;
+ globalObject = 0;
globalThis = 0;
}
#endif
@@ -58,6 +61,7 @@ namespace JSC {
ScopeChainNode* next;
JSObject* object;
JSGlobalData* globalData;
+ JSGlobalObject* globalObject;
JSObject* globalThis;
int refCount;
@@ -82,9 +86,6 @@ namespace JSC {
ScopeChainIterator begin() const;
ScopeChainIterator end() const;
- JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h
- JSObject* globalThisObject() const { return globalThis; }
-
#ifndef NDEBUG
void print() const;
#endif
@@ -93,7 +94,7 @@ namespace JSC {
inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
{
ASSERT(o);
- return new ScopeChainNode(this, o, globalData, globalThis);
+ return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
}
inline ScopeChainNode* ScopeChainNode::pop()
@@ -163,8 +164,8 @@ namespace JSC {
{
}
- ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis)
- : m_node(new ScopeChainNode(0, o, globalData, globalThis))
+ ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
+ : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
{
}
@@ -203,7 +204,7 @@ namespace JSC {
void pop() { m_node = m_node->pop(); }
void clear() { m_node->deref(); m_node = 0; }
- JSGlobalObject* globalObject() const { return m_node->globalObject(); }
+ JSGlobalObject* globalObject() const { return m_node->globalObject; }
void markAggregate(MarkStack&) const;
diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp
index 2f92cc1..04701cb 100644
--- a/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/JavaScriptCore/runtime/SmallStrings.cpp
@@ -82,13 +82,13 @@ SmallStrings::~SmallStrings()
{
}
-void SmallStrings::mark()
+void SmallStrings::markChildren(MarkStack& markStack)
{
- if (m_emptyString && !m_emptyString->marked())
- m_emptyString->markCellDirect();
+ if (m_emptyString)
+ markStack.append(m_emptyString);
for (unsigned i = 0; i < numCharactersToStore; ++i) {
- if (m_singleCharacterStrings[i] && !m_singleCharacterStrings[i]->marked())
- m_singleCharacterStrings[i]->markCellDirect();
+ if (m_singleCharacterStrings[i])
+ markStack.append(m_singleCharacterStrings[i]);
}
}
diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h
index f0dd8df..efecbb0 100644
--- a/JavaScriptCore/runtime/SmallStrings.h
+++ b/JavaScriptCore/runtime/SmallStrings.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@ namespace JSC {
class JSGlobalData;
class JSString;
-
+ class MarkStack;
class SmallStringsStorage;
class SmallStrings : public Noncopyable {
@@ -56,7 +56,7 @@ namespace JSC {
UString::Rep* singleCharacterStringRep(unsigned char character);
- void mark();
+ void markChildren(MarkStack&);
unsigned count() const;
diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp
index 6380445..2f3adbe 100644
--- a/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/JavaScriptCore/runtime/StringConstructor.cpp
@@ -47,7 +47,7 @@ static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSVa
ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
-StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
+StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
: InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
{
// ECMA 15.5.3.1 String.prototype
diff --git a/JavaScriptCore/runtime/StringConstructor.h b/JavaScriptCore/runtime/StringConstructor.h
index 7d52c69..e511f7b 100644
--- a/JavaScriptCore/runtime/StringConstructor.h
+++ b/JavaScriptCore/runtime/StringConstructor.h
@@ -29,7 +29,7 @@ namespace JSC {
class StringConstructor : public InternalFunction {
public:
- StringConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
+ StringConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
virtual ConstructType getConstructData(ConstructData&);
virtual CallType getCallData(CallData&);
diff --git a/JavaScriptCore/runtime/StringObject.cpp b/JavaScriptCore/runtime/StringObject.cpp
index fb44498..7216d3a 100644
--- a/JavaScriptCore/runtime/StringObject.cpp
+++ b/JavaScriptCore/runtime/StringObject.cpp
@@ -29,19 +29,19 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject);
const ClassInfo StringObject::info = { "String", 0, 0, 0 };
-StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure)
+StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: JSWrapperObject(structure)
{
setInternalValue(jsEmptyString(exec));
}
-StringObject::StringObject(PassRefPtr<Structure> structure, JSString* string)
+StringObject::StringObject(NonNullPassRefPtr<Structure> structure, JSString* string)
: JSWrapperObject(structure)
{
setInternalValue(string);
}
-StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
: JSWrapperObject(structure)
{
setInternalValue(jsString(exec, string));
@@ -61,6 +61,13 @@ bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pr
return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
}
+bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+ return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (propertyName == exec->propertyNames().length)
@@ -75,27 +82,12 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam
return JSObject::deleteProperty(exec, propertyName);
}
-void StringObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
int size = internalValue()->value().size();
for (int i = 0; i < size; ++i)
propertyNames.add(Identifier(exec, UString::from(i)));
- return JSObject::getPropertyNames(exec, propertyNames);
-}
-
-UString StringObject::toString(ExecState*) const
-{
- return internalValue()->value();
-}
-
-UString StringObject::toThisString(ExecState*) const
-{
- return internalValue()->value();
-}
-
-JSString* StringObject::toThisJSString(ExecState*)
-{
- return internalValue();
+ return JSObject::getOwnPropertyNames(exec, propertyNames);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/StringObject.h b/JavaScriptCore/runtime/StringObject.h
index ea3a045..944f6ba 100644
--- a/JavaScriptCore/runtime/StringObject.h
+++ b/JavaScriptCore/runtime/StringObject.h
@@ -28,17 +28,18 @@ namespace JSC {
class StringObject : public JSWrapperObject {
public:
- StringObject(ExecState*, PassRefPtr<Structure>);
- StringObject(ExecState*, PassRefPtr<Structure>, const UString&);
+ StringObject(ExecState*, NonNullPassRefPtr<Structure>);
+ StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&);
static StringObject* create(ExecState*, JSString*);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
- virtual void getPropertyNames(ExecState*, PropertyNameArray&);
+ virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
virtual const ClassInfo* classInfo() const { return &info; }
static const JS_EXPORTDATA ClassInfo info;
@@ -51,12 +52,7 @@ namespace JSC {
}
protected:
- StringObject(PassRefPtr<Structure>, JSString*);
-
- private:
- virtual UString toString(ExecState*) const;
- virtual UString toThisString(ExecState*) const;
- virtual JSString* toThisJSString(ExecState*);
+ StringObject(NonNullPassRefPtr<Structure>, JSString*);
};
StringObject* asStringObject(JSValue);
diff --git a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
index bc5c0a5..0cba83d 100644
--- a/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
+++ b/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h
@@ -37,14 +37,14 @@ namespace JSC {
}
private:
- StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<Structure> structure, const UString& string)
+ StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
: StringObject(exec, structure, string)
{
}
static PassRefPtr<Structure> createStructure(JSValue proto)
{
- return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined));
+ return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined | HasDefaultMark));
}
virtual bool toBoolean(ExecState*) const { return false; }
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index 531a302..b57732a 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -23,6 +23,8 @@
#include "StringPrototype.h"
#include "CachedCall.h"
+#include "Error.h"
+#include "Executable.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "ObjectPrototype.h"
@@ -119,7 +121,7 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
*/
// ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure)
+StringPrototype::StringPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
: StringObject(exec, structure)
{
// The constructor will be added later, after StringConstructor has been built
@@ -131,6 +133,11 @@ bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prop
return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
}
+bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, descriptor);
+}
+
// ------------------------------ Functions --------------------------
static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
@@ -220,7 +227,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
if (callType == CallTypeNone)
replacementString = replacement.toString(exec);
- if (pattern.isObject(&RegExpObject::info)) {
+ if (pattern.inherits(&RegExpObject::info)) {
RegExp* reg = asRegExpObject(pattern)->regExp();
bool global = reg->global();
@@ -365,7 +372,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValu
if (thisValue.isString())
return thisValue;
- if (thisValue.isObject(&StringObject::info))
+ if (thisValue.inherits(&StringObject::info))
return asStringObject(thisValue)->internalValue();
return throwError(exec, TypeError);
@@ -466,7 +473,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t
UString u = s;
RefPtr<RegExp> reg;
RegExpObject* imp = 0;
- if (a0.isObject(&RegExpObject::info))
+ if (a0.inherits(&RegExpObject::info))
reg = asRegExpObject(a0)->regExp();
else {
/*
@@ -516,7 +523,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue
UString u = s;
RefPtr<RegExp> reg;
- if (a0.isObject(&RegExpObject::info))
+ if (a0.inherits(&RegExpObject::info))
reg = asRegExpObject(a0)->regExp();
else {
/*
@@ -568,7 +575,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue t
unsigned i = 0;
int p0 = 0;
unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
- if (a0.isObject(&RegExpObject::info)) {
+ if (a0.inherits(&RegExpObject::info)) {
RegExp* reg = asRegExpObject(a0)->regExp();
if (s.isEmpty() && reg->match(s, 0) >= 0) {
// empty string matched by regexp -> empty array
@@ -821,8 +828,8 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
unsigned stringSize = s.size();
unsigned bufferSize = 22 + stringSize;
- UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
- if (!buffer)
+ UChar* buffer;
+ if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer))
return jsUndefined();
buffer[0] = '<';
buffer[1] = 'f';
@@ -869,8 +876,8 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th
unsigned linkTextSize = linkText.size();
unsigned stringSize = s.size();
unsigned bufferSize = 15 + linkTextSize + stringSize;
- UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
- if (!buffer)
+ UChar* buffer;
+ if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer))
return jsUndefined();
buffer[0] = '<';
buffer[1] = 'a';
diff --git a/JavaScriptCore/runtime/StringPrototype.h b/JavaScriptCore/runtime/StringPrototype.h
index 6f5344e..3a6a2a3 100644
--- a/JavaScriptCore/runtime/StringPrototype.h
+++ b/JavaScriptCore/runtime/StringPrototype.h
@@ -29,9 +29,10 @@ namespace JSC {
class StringPrototype : public StringObject {
public:
- StringPrototype(ExecState*, PassRefPtr<Structure>);
+ StringPrototype(ExecState*, NonNullPassRefPtr<Structure>);
virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp
index 5dfd919..7209b5f 100644
--- a/JavaScriptCore/runtime/Structure.cpp
+++ b/JavaScriptCore/runtime/Structure.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -127,17 +127,14 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
, m_propertyTable(0)
, m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
, m_offset(noOffset)
- , m_isDictionary(false)
+ , m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
- , m_usingSingleTransitionSlot(true)
, m_attributesInPrevious(0)
{
ASSERT(m_prototype);
ASSERT(m_prototype.isObject() || m_prototype.isNull());
- m_transitions.singleTransition = 0;
-
#ifndef NDEBUG
#if ENABLE(JSC_MULTIPLE_THREADS)
MutexLocker protect(ignoreSetMutex);
@@ -156,20 +153,16 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo)
Structure::~Structure()
{
if (m_previous) {
- if (m_previous->m_usingSingleTransitionSlot) {
- m_previous->m_transitions.singleTransition = 0;
- } else {
- ASSERT(m_previous->m_transitions.table->contains(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious))));
- m_previous->m_transitions.table->remove(make_pair(m_nameInPrevious.get(), make_pair(m_attributesInPrevious, m_specificValueInPrevious)));
- }
+ if (m_nameInPrevious)
+ m_previous->table.remove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
+ else
+ m_previous->table.removeAnonymousSlotTransition(m_anonymousSlotsInPrevious);
+
}
if (m_cachedPropertyNameArrayData)
m_cachedPropertyNameArrayData->setCachedStructure(0);
- if (!m_usingSingleTransitionSlot)
- delete m_transitions.table;
-
if (m_propertyTable) {
unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
for (unsigned i = 1; i <= entryCount; i++) {
@@ -279,15 +272,25 @@ void Structure::materializePropertyMap()
for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
structure = structures[i];
+ if (!structure->m_nameInPrevious) {
+ m_propertyTable->anonymousSlotCount += structure->m_anonymousSlotsInPrevious;
+ continue;
+ }
structure->m_nameInPrevious->ref();
PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
insertIntoPropertyMapHashTable(entry);
}
}
+void Structure::getOwnEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
+{
+ getEnumerableNamesFromPropertyTable(propertyNames);
+ getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
+}
+
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject)
{
- bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_isDictionary);
+ bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary());
if (shouldCache && m_cachedPropertyNameArrayData) {
if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) {
@@ -297,12 +300,22 @@ void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& p
clearEnumerationCache();
}
- getEnumerableNamesFromPropertyTable(propertyNames);
- getEnumerableNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames);
+ baseObject->getOwnPropertyNames(exec, propertyNames);
if (m_prototype.isObject()) {
propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly.
- asObject(m_prototype)->getPropertyNames(exec, propertyNames);
+ JSObject* prototype = asObject(m_prototype);
+ while(1) {
+ if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) {
+ prototype->getPropertyNames(exec, propertyNames);
+ break;
+ }
+ prototype->getOwnPropertyNames(exec, propertyNames);
+ JSValue nextProto = prototype->prototype();
+ if (!nextProto.isObject())
+ break;
+ prototype = asObject(nextProto);
+ }
}
if (shouldCache) {
@@ -336,7 +349,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
materializePropertyMapIfNecessary();
- ASSERT(m_isDictionary);
+ ASSERT(isDictionary());
ASSERT(m_propertyTable);
unsigned i = rep->computedHash();
@@ -378,25 +391,13 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
- if (structure->m_usingSingleTransitionSlot) {
- Structure* existingTransition = structure->m_transitions.singleTransition;
- if (existingTransition && existingTransition->m_nameInPrevious.get() == propertyName.ustring().rep()
- && existingTransition->m_attributesInPrevious == attributes
- && existingTransition->m_specificValueInPrevious == specificValue) {
-
- ASSERT(structure->m_transitions.singleTransition->m_offset != noOffset);
- offset = structure->m_transitions.singleTransition->m_offset;
- return existingTransition;
- }
- } else {
- if (Structure* existingTransition = structure->m_transitions.table->get(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)))) {
- ASSERT(existingTransition->m_offset != noOffset);
- offset = existingTransition->m_offset;
- return existingTransition;
- }
+ if (Structure* existingTransition = structure->table.get(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
+ ASSERT(existingTransition->m_offset != noOffset);
+ offset = existingTransition->m_offset;
+ return existingTransition;
}
return 0;
@@ -404,12 +405,12 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isDictionary());
ASSERT(structure->typeInfo().type() == ObjectType);
ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
if (structure->transitionCount() > s_maxTransitionLength) {
- RefPtr<Structure> transition = toDictionaryTransition(structure);
+ RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
ASSERT(structure != transition);
offset = transition->put(propertyName, attributes, specificValue);
if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
@@ -447,27 +448,15 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
transition->m_offset = offset;
- if (structure->m_usingSingleTransitionSlot) {
- if (!structure->m_transitions.singleTransition) {
- structure->m_transitions.singleTransition = transition.get();
- return transition.release();
- }
-
- Structure* existingTransition = structure->m_transitions.singleTransition;
- structure->m_usingSingleTransitionSlot = false;
- StructureTransitionTable* transitionTable = new StructureTransitionTable;
- structure->m_transitions.table = transitionTable;
- transitionTable->add(make_pair(existingTransition->m_nameInPrevious.get(), make_pair(existingTransition->m_attributesInPrevious, existingTransition->m_specificValueInPrevious)), existingTransition);
- }
- structure->m_transitions.table->add(make_pair(propertyName.ustring().rep(), make_pair(attributes, specificValue)), transition.get());
+ structure->table.add(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
return transition.release();
}
PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
{
- ASSERT(!structure->m_isDictionary);
+ ASSERT(!structure->isUncacheableDictionary());
- RefPtr<Structure> transition = toDictionaryTransition(structure);
+ RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
offset = transition->remove(propertyName);
@@ -509,6 +498,47 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur
return transition.release();
}
+PassRefPtr<Structure> Structure::addAnonymousSlotsTransition(Structure* structure, unsigned count)
+{
+ if (Structure* transition = structure->table.getAnonymousSlotTransition(count)) {
+ ASSERT(transition->storedPrototype() == structure->storedPrototype());
+ return transition;
+ }
+ ASSERT(count);
+ ASSERT(count < ((1<<6) - 2));
+ RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
+
+ transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
+ transition->m_previous = structure;
+ transition->m_nameInPrevious = 0;
+ transition->m_attributesInPrevious = 0;
+ transition->m_anonymousSlotsInPrevious = count;
+ transition->m_specificValueInPrevious = 0;
+ transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
+ transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
+
+ if (structure->m_propertyTable) {
+ if (structure->m_isPinnedPropertyTable)
+ transition->m_propertyTable = structure->copyPropertyTable();
+ else {
+ transition->m_propertyTable = structure->m_propertyTable;
+ structure->m_propertyTable = 0;
+ }
+ } else {
+ if (structure->m_previous)
+ transition->materializePropertyMap();
+ else
+ transition->createPropertyMapHashTable();
+ }
+
+ transition->addAnonymousSlots(count);
+ if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
+ transition->growPropertyStorageCapacity();
+
+ structure->table.addAnonymousSlotTransition(count, transition.get());
+ return transition.release();
+}
+
PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
{
RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo());
@@ -524,25 +554,35 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
return transition.release();
}
-PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure)
+PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
{
- ASSERT(!structure->m_isDictionary);
-
+ ASSERT(!structure->isUncacheableDictionary());
+
RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo());
- transition->m_isDictionary = true;
+ transition->m_dictionaryKind = kind;
transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-
+
structure->materializePropertyMapIfNecessary();
transition->m_propertyTable = structure->copyPropertyTable();
transition->m_isPinnedPropertyTable = true;
-
+
return transition.release();
}
+PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
+{
+ return toDictionaryTransition(structure, CachedDictionaryKind);
+}
+
+PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
+{
+ return toDictionaryTransition(structure, UncachedDictionaryKind);
+}
+
PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
{
- ASSERT(structure->m_isDictionary);
+ ASSERT(structure->isDictionary());
// Since dictionary Structures are not shared, and no opcodes specialize
// for them, we don't need to allocate a new Structure when transitioning
@@ -551,15 +591,13 @@ PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure)
// FIMXE: We can make this more efficient by canonicalizing the Structure (draining the
// deleted offsets vector) before transitioning from dictionary.
if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty())
- structure->m_isDictionary = false;
+ structure->m_dictionaryKind = NoneDictionaryKind;
return structure;
}
size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
{
- ASSERT(!m_transitions.singleTransition);
-
materializePropertyMapIfNecessary();
m_isPinnedPropertyTable = true;
@@ -572,8 +610,7 @@ size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, u
size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
{
- ASSERT(!m_transitions.singleTransition);
- ASSERT(m_isDictionary);
+ ASSERT(isUncacheableDictionary());
materializePropertyMapIfNecessary();
@@ -636,6 +673,7 @@ PropertyMapHashTable* Structure::copyPropertyTable()
if (m_propertyTable->deletedOffsets)
newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets);
+ newTable->anonymousSlotCount = m_propertyTable->anonymousSlotCount;
return newTable;
}
@@ -815,7 +853,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
newOffset = m_propertyTable->deletedOffsets->last();
m_propertyTable->deletedOffsets->removeLast();
} else
- newOffset = m_propertyTable->keyCount;
+ newOffset = m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount;
m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
++m_propertyTable->keyCount;
@@ -827,6 +865,16 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel
return newOffset;
}
+void Structure::addAnonymousSlots(unsigned count)
+{
+ m_propertyTable->anonymousSlotCount += count;
+}
+
+bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
+{
+ return table.hasTransition(make_pair(rep, attributes));
+}
+
size_t Structure::remove(const Identifier& propertyName)
{
ASSERT(!propertyName.isNull());
@@ -980,6 +1028,7 @@ void Structure::rehashPropertyMapHashTable(unsigned newTableSize)
m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
m_propertyTable->size = newTableSize;
m_propertyTable->sizeMask = newTableSize - 1;
+ m_propertyTable->anonymousSlotCount = oldTable->anonymousSlotCount;
unsigned lastIndexUsed = 0;
unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
diff --git a/JavaScriptCore/runtime/Structure.h b/JavaScriptCore/runtime/Structure.h
index f3a0c7c..ed9f6e5 100644
--- a/JavaScriptCore/runtime/Structure.h
+++ b/JavaScriptCore/runtime/Structure.h
@@ -29,11 +29,10 @@
#include "Identifier.h"
#include "JSType.h"
#include "JSValue.h"
-#include "MarkStack.h"
#include "PropertyMapHashTable.h"
#include "StructureChain.h"
#include "StructureTransitionTable.h"
-#include "TypeInfo.h"
+#include "JSTypeInfo.h"
#include "UString.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -46,12 +45,14 @@
namespace JSC {
+ class MarkStack;
class PropertyNameArray;
class PropertyNameArrayData;
class Structure : public RefCounted<Structure> {
public:
friend class JIT;
+ friend class StructureTransitionTable;
static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo)
{
return adoptRef(new Structure(prototype, typeInfo));
@@ -66,24 +67,24 @@ namespace JSC {
static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
- static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
+ static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
+ static PassRefPtr<Structure> addAnonymousSlotsTransition(Structure*, unsigned count);
static PassRefPtr<Structure> getterSetterTransition(Structure*);
- static PassRefPtr<Structure> toDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
+ static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
static PassRefPtr<Structure> fromDictionaryTransition(Structure*);
~Structure();
- void markAggregate(MarkStack& markStack)
- {
- markStack.append(m_prototype);
- }
+ void markAggregate(MarkStack&);
// These should be used with caution.
size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t removePropertyWithoutTransition(const Identifier& propertyName);
void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
-
- bool isDictionary() const { return m_isDictionary; }
+
+ bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
+ bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
const TypeInfo& typeInfo() const { return m_typeInfo; }
@@ -95,7 +96,7 @@ namespace JSC {
void growPropertyStorageCapacity();
size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; }
- size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
+ size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; }
bool isUsingInlineStorage() const;
size_t get(const Identifier& propertyName);
@@ -103,10 +104,20 @@ namespace JSC {
size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
{
ASSERT(!propertyName.isNull());
- return get(propertyName._ustring.rep(), attributes, specificValue);
+ return get(propertyName.ustring().rep(), attributes, specificValue);
+ }
+ bool transitionedFor(const JSCell* specificValue)
+ {
+ return m_specificValueInPrevious == specificValue;
+ }
+ bool hasTransition(UString::Rep*, unsigned attributes);
+ bool hasTransition(const Identifier& propertyName, unsigned attributes)
+ {
+ return hasTransition(propertyName._ustring.rep(), attributes);
}
void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
+ void getOwnEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*);
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
@@ -118,9 +129,17 @@ namespace JSC {
private:
Structure(JSValue prototype, const TypeInfo&);
+
+ typedef enum {
+ NoneDictionaryKind = 0,
+ CachedDictionaryKind = 1,
+ UncachedDictionaryKind = 2
+ } DictionaryKind;
+ static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
size_t remove(const Identifier& propertyName);
+ void addAnonymousSlots(unsigned slotCount);
void getEnumerableNamesFromPropertyTable(PropertyNameArray&);
void getEnumerableNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&);
@@ -166,13 +185,10 @@ namespace JSC {
RefPtr<Structure> m_previous;
RefPtr<UString::Rep> m_nameInPrevious;
-
- union {
- Structure* singleTransition;
- StructureTransitionTable* table;
- } m_transitions;
JSCell* m_specificValueInPrevious;
+ StructureTransitionTable table;
+
RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;
PropertyMapHashTable* m_propertyTable;
@@ -180,11 +196,18 @@ namespace JSC {
size_t m_propertyStorageCapacity;
signed char m_offset;
- bool m_isDictionary : 1;
+ unsigned m_dictionaryKind : 2;
bool m_isPinnedPropertyTable : 1;
bool m_hasGetterSetterProperties : 1;
- bool m_usingSingleTransitionSlot : 1;
+#if COMPILER(WINSCW)
+ // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared
+ // bitfield, when used as argument in make_pair() function calls in structure.ccp.
+ // This bitfield optimization is insignificant for the Symbian emulator target.
+ unsigned m_attributesInPrevious;
+#else
unsigned m_attributesInPrevious : 7;
+#endif
+ unsigned m_anonymousSlotsInPrevious : 6;
};
inline size_t Structure::get(const Identifier& propertyName)
@@ -231,7 +254,58 @@ namespace JSC {
return m_propertyTable->entries()[entryIndex - 1].offset;
}
}
+
+ bool StructureTransitionTable::contains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+ {
+ if (usingSingleTransitionSlot()) {
+ Structure* existingTransition = singleTransition();
+ return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
+ && existingTransition->m_attributesInPrevious == key.second
+ && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
+ }
+ TransitionTable::iterator find = table()->find(key);
+ if (find == table()->end())
+ return false;
+
+ return find->second.first || find->second.second->transitionedFor(specificValue);
+ }
+
+ Structure* StructureTransitionTable::get(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
+ {
+ if (usingSingleTransitionSlot()) {
+ Structure* existingTransition = singleTransition();
+ if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
+ && existingTransition->m_attributesInPrevious == key.second
+ && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
+ return existingTransition;
+ return 0;
+ }
+
+ Transition transition = table()->get(key);
+ if (transition.second && transition.second->transitionedFor(specificValue))
+ return transition.second;
+ return transition.first;
+ }
+ bool StructureTransitionTable::hasTransition(const StructureTransitionTableHash::Key& key) const
+ {
+ if (usingSingleTransitionSlot()) {
+ Structure* transition = singleTransition();
+ return transition && transition->m_nameInPrevious == key.first
+ && transition->m_attributesInPrevious == key.second;
+ }
+ return table()->contains(key);
+ }
+
+ void StructureTransitionTable::reifySingleTransition()
+ {
+ ASSERT(usingSingleTransitionSlot());
+ Structure* existingTransition = singleTransition();
+ TransitionTable* transitionTable = new TransitionTable;
+ setTransitionTable(transitionTable);
+ if (existingTransition)
+ add(make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
+ }
} // namespace JSC
#endif // Structure_h
diff --git a/JavaScriptCore/runtime/StructureChain.cpp b/JavaScriptCore/runtime/StructureChain.cpp
index 85049b1..6e8a0ee 100644
--- a/JavaScriptCore/runtime/StructureChain.cpp
+++ b/JavaScriptCore/runtime/StructureChain.cpp
@@ -51,7 +51,10 @@ bool StructureChain::isCacheable() const
uint32_t i = 0;
while (m_vector[i]) {
- if (m_vector[i++]->isDictionary())
+ // Both classes of dictionary structure may change arbitrarily so we can't cache them
+ if (m_vector[i]->isDictionary())
+ return false;
+ if (!m_vector[i++]->typeInfo().hasDefaultGetPropertyNames())
return false;
}
return true;
diff --git a/JavaScriptCore/runtime/StructureTransitionTable.h b/JavaScriptCore/runtime/StructureTransitionTable.h
index 804cbeb..0fa7b73 100644
--- a/JavaScriptCore/runtime/StructureTransitionTable.h
+++ b/JavaScriptCore/runtime/StructureTransitionTable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +30,8 @@
#include <wtf/HashFunctions.h>
#include <wtf/HashMap.h>
#include <wtf/HashTraits.h>
+#include <wtf/PtrAndFlags.h>
+#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
namespace JSC {
@@ -37,7 +39,7 @@ namespace JSC {
class Structure;
struct StructureTransitionTableHash {
- typedef std::pair<RefPtr<UString::Rep>, std::pair<unsigned, JSCell*> > Key;
+ typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
static unsigned hash(const Key& p)
{
return p.first->computedHash();
@@ -53,20 +55,159 @@ namespace JSC {
struct StructureTransitionTableHashTraits {
typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
- typedef WTF::GenericHashTraits<unsigned> SecondFirstTraits;
- typedef WTF::GenericHashTraits<JSCell*> SecondSecondTraits;
- typedef std::pair<FirstTraits::TraitType, std::pair<SecondFirstTraits::TraitType, SecondSecondTraits::TraitType> > TraitType;
+ typedef WTF::GenericHashTraits<unsigned> SecondTraits;
+ typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
- static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondFirstTraits::emptyValueIsZero && SecondSecondTraits::emptyValueIsZero;
- static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), std::make_pair(SecondFirstTraits::emptyValue(), SecondSecondTraits::emptyValue())); }
+ static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
+ static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
- static const bool needsDestruction = FirstTraits::needsDestruction || SecondFirstTraits::needsDestruction || SecondSecondTraits::needsDestruction;
+ static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
};
- typedef HashMap<StructureTransitionTableHash::Key, Structure*, StructureTransitionTableHash, StructureTransitionTableHashTraits> StructureTransitionTable;
+ class StructureTransitionTable {
+ typedef std::pair<Structure*, Structure*> Transition;
+ struct TransitionTable : public HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> {
+ typedef HashMap<unsigned, Structure*> AnonymousSlotMap;
+
+ void addSlotTransition(unsigned count, Structure* structure)
+ {
+ ASSERT(!getSlotTransition(count));
+ if (!m_anonymousSlotTable)
+ m_anonymousSlotTable.set(new AnonymousSlotMap);
+ m_anonymousSlotTable->add(count, structure);
+ }
+
+ void removeSlotTransition(unsigned count)
+ {
+ ASSERT(getSlotTransition(count));
+ m_anonymousSlotTable->remove(count);
+ }
+
+ Structure* getSlotTransition(unsigned count)
+ {
+ if (!m_anonymousSlotTable)
+ return 0;
+
+ AnonymousSlotMap::iterator find = m_anonymousSlotTable->find(count);
+ if (find == m_anonymousSlotTable->end())
+ return 0;
+ return find->second;
+ }
+ private:
+ OwnPtr<AnonymousSlotMap> m_anonymousSlotTable;
+ };
+ public:
+ StructureTransitionTable() {
+ m_transitions.m_singleTransition.set(0);
+ m_transitions.m_singleTransition.setFlag(usingSingleSlot);
+ }
+
+ ~StructureTransitionTable() {
+ if (!usingSingleTransitionSlot())
+ delete table();
+ }
+
+ // The contains and get methods accept imprecise matches, so if an unspecialised transition exists
+ // for the given key they will consider that transition to be a match. If a specialised transition
+ // exists and it matches the provided specificValue, get will return the specific transition.
+ inline bool contains(const StructureTransitionTableHash::Key&, JSCell* specificValue);
+ inline Structure* get(const StructureTransitionTableHash::Key&, JSCell* specificValue) const;
+ inline bool hasTransition(const StructureTransitionTableHash::Key& key) const;
+ void remove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+ {
+ if (usingSingleTransitionSlot()) {
+ ASSERT(contains(key, specificValue));
+ setSingleTransition(0);
+ return;
+ }
+ TransitionTable::iterator find = table()->find(key);
+ if (!specificValue)
+ find->second.first = 0;
+ else
+ find->second.second = 0;
+ if (!find->second.first && !find->second.second)
+ table()->remove(find);
+ }
+ void add(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
+ {
+ if (usingSingleTransitionSlot()) {
+ if (!singleTransition()) {
+ setSingleTransition(structure);
+ return;
+ }
+ reifySingleTransition();
+ }
+ if (!specificValue) {
+ TransitionTable::iterator find = table()->find(key);
+ if (find == table()->end())
+ table()->add(key, Transition(structure, 0));
+ else
+ find->second.first = structure;
+ } else {
+ // If we're adding a transition to a specific value, then there cannot be
+ // an existing transition
+ ASSERT(!table()->contains(key));
+ table()->add(key, Transition(0, structure));
+ }
+ }
+
+ Structure* getAnonymousSlotTransition(unsigned count)
+ {
+ if (usingSingleTransitionSlot())
+ return 0;
+ return table()->getSlotTransition(count);
+ }
+
+ void addAnonymousSlotTransition(unsigned count, Structure* structure)
+ {
+ if (usingSingleTransitionSlot())
+ reifySingleTransition();
+ ASSERT(!table()->getSlotTransition(count));
+ table()->addSlotTransition(count, structure);
+ }
+
+ void removeAnonymousSlotTransition(unsigned count)
+ {
+ ASSERT(!usingSingleTransitionSlot());
+ table()->removeSlotTransition(count);
+ }
+ private:
+ TransitionTable* table() const { ASSERT(!usingSingleTransitionSlot()); return m_transitions.m_table; }
+ Structure* singleTransition() const {
+ ASSERT(usingSingleTransitionSlot());
+ return m_transitions.m_singleTransition.get();
+ }
+ bool usingSingleTransitionSlot() const { return m_transitions.m_singleTransition.isFlagSet(usingSingleSlot); }
+ void setSingleTransition(Structure* structure)
+ {
+ ASSERT(usingSingleTransitionSlot());
+ m_transitions.m_singleTransition.set(structure);
+ }
+
+ void setTransitionTable(TransitionTable* table)
+ {
+ ASSERT(usingSingleTransitionSlot());
+#ifndef NDEBUG
+ setSingleTransition(0);
+#endif
+ m_transitions.m_table = table;
+ // This implicitly clears the flag that indicates we're using a single transition
+ ASSERT(!usingSingleTransitionSlot());
+ }
+ inline void reifySingleTransition();
+
+ enum UsingSingleSlot {
+ usingSingleSlot
+ };
+ // Last bit indicates whether we are using the single transition optimisation
+ union {
+ TransitionTable* m_table;
+ PtrAndFlagsBase<Structure, UsingSingleSlot> m_singleTransition;
+ } m_transitions;
+ };
} // namespace JSC
diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h
index c00f95a..f5e2669 100644
--- a/JavaScriptCore/runtime/SymbolTable.h
+++ b/JavaScriptCore/runtime/SymbolTable.h
@@ -121,6 +121,10 @@ namespace JSC {
typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
+ class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable>
+ {
+ };
+
} // namespace JSC
#endif // SymbolTable_h
diff --git a/JavaScriptCore/runtime/TimeoutChecker.cpp b/JavaScriptCore/runtime/TimeoutChecker.cpp
index 30ba6e9..2a056c9 100644
--- a/JavaScriptCore/runtime/TimeoutChecker.cpp
+++ b/JavaScriptCore/runtime/TimeoutChecker.cpp
@@ -35,18 +35,10 @@
#if PLATFORM(DARWIN)
#include <mach/mach.h>
-#endif
-
-#if HAVE(SYS_TIME_H)
-#include <sys/time.h>
-#endif
-
-#if PLATFORM(WIN_OS)
+#elif PLATFORM(WIN_OS)
#include <windows.h>
-#endif
-
-#if PLATFORM(QT)
-#include <QDateTime>
+#else
+#include "CurrentTime.h"
#endif
using namespace std;
@@ -75,14 +67,6 @@ static inline unsigned getCPUTime()
time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
return time;
-#elif HAVE(SYS_TIME_H)
- // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
- struct timeval tv;
- gettimeofday(&tv, 0);
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-#elif PLATFORM(QT)
- QDateTime t = QDateTime::currentDateTime();
- return t.toTime_t() * 1000 + t.time().msec();
#elif PLATFORM(WIN_OS)
union {
FILETIME fileTime;
@@ -97,7 +81,8 @@ static inline unsigned getCPUTime()
return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
#else
-#error Platform does not have getCurrentTime function
+ // FIXME: We should return the time the current thread has spent executing.
+ return currentTime() * 1000;
#endif
}
diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp
index 118751e..e66ca93 100644
--- a/JavaScriptCore/runtime/UString.cpp
+++ b/JavaScriptCore/runtime/UString.cpp
@@ -32,14 +32,17 @@
#include <ctype.h>
#include <float.h>
#include <limits.h>
+#include <limits>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <wtf/ASCIICType.h>
#include <wtf/Assertions.h>
#include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
#include <wtf/Vector.h>
#include <wtf/unicode/UTF8.h>
+#include <wtf/StringExtras.h>
#if HAVE(STRING_H)
#include <string.h>
@@ -68,20 +71,20 @@ static const int minLengthToShare = 10;
static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); }
static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); }
-static inline UChar* allocChars(size_t length)
+static inline PossiblyNull<UChar*> allocChars(size_t length)
{
ASSERT(length);
if (length > maxUChars())
return 0;
- return static_cast<UChar*>(tryFastMalloc(sizeof(UChar) * length));
+ return tryFastMalloc(sizeof(UChar) * length);
}
-static inline UChar* reallocChars(UChar* buffer, size_t length)
+static inline PossiblyNull<UChar*> reallocChars(UChar* buffer, size_t length)
{
ASSERT(length);
if (length > maxUChars())
return 0;
- return static_cast<UChar*>(tryFastRealloc(buffer, sizeof(UChar) * length));
+ return tryFastRealloc(buffer, sizeof(UChar) * length);
}
static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
@@ -480,8 +483,7 @@ static inline bool expandCapacity(UString::Rep* rep, int requiredLength)
if (requiredLength > base->capacity) {
size_t newCapacity = expandedSize(requiredLength, base->preCapacity);
UChar* oldBuf = base->buf;
- base->buf = reallocChars(base->buf, newCapacity);
- if (!base->buf) {
+ if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) {
base->buf = oldBuf;
return false;
}
@@ -512,8 +514,7 @@ bool UString::Rep::reserveCapacity(int capacity)
size_t newCapacity = expandedSize(capacity, base->preCapacity);
UChar* oldBuf = base->buf;
- base->buf = reallocChars(base->buf, newCapacity);
- if (!base->buf) {
+ if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) {
base->buf = oldBuf;
return false;
}
@@ -540,8 +541,8 @@ void UString::expandPreCapacity(int requiredPreCap)
size_t newCapacity = expandedSize(requiredPreCap, base->capacity);
int delta = newCapacity - base->capacity - base->preCapacity;
- UChar* newBuf = allocChars(newCapacity);
- if (!newBuf) {
+ UChar* newBuf;
+ if (!allocChars(newCapacity).getValue(newBuf)) {
makeNull();
return;
}
@@ -566,8 +567,8 @@ static PassRefPtr<UString::Rep> createRep(const char* c)
return &UString::Rep::empty();
size_t length = strlen(c);
- UChar* d = allocChars(length);
- if (!d)
+ UChar* d;
+ if (!allocChars(length).getValue(d))
return &UString::Rep::null();
else {
for (size_t i = 0; i < length; i++)
@@ -656,8 +657,8 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re
} else {
// This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
rep = &UString::Rep::null();
else {
copyChars(d, rep->data(), thisSize);
@@ -712,8 +713,8 @@ static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Re
} else {
// This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
rep = &UString::Rep::null();
else {
copyChars(d, rep->data(), thisSize);
@@ -800,8 +801,8 @@ PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b)
// a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string
size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
return 0;
copyChars(d, a->data(), aSize);
copyChars(d + aSize, b->data(), bSize);
@@ -942,6 +943,39 @@ UString UString::from(int i)
return UString(p, static_cast<int>(end - p));
}
+UString UString::from(long long i)
+{
+ UChar buf[1 + sizeof(i) * 3];
+ UChar* end = buf + sizeof(buf) / sizeof(UChar);
+ UChar* p = end;
+
+ if (i == 0)
+ *--p = '0';
+ else if (i == std::numeric_limits<long long>::min()) {
+ char minBuf[1 + sizeof(i) * 3];
+#if PLATFORM(WIN_OS)
+ snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
+#else
+ snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min());
+#endif
+ return UString(minBuf);
+ } else {
+ bool negative = false;
+ if (i < 0) {
+ negative = true;
+ i = -i;
+ }
+ while (i) {
+ *--p = static_cast<unsigned short>((i % 10) + '0');
+ i /= 10;
+ }
+ if (negative)
+ *--p = '-';
+ }
+
+ return UString(p, static_cast<int>(end - p));
+}
+
UString UString::from(unsigned int u)
{
UChar buf[sizeof(u) * 3];
@@ -994,6 +1028,8 @@ UString UString::from(double d)
// avoid ever printing -NaN, in JS conceptually there is only one NaN value
if (isnan(d))
return "NaN";
+ if (!d)
+ return "0"; // -0 -> "0"
char buf[80];
int decimalPoint;
@@ -1076,8 +1112,8 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in
if (totalLength == 0)
return "";
- UChar* buffer = allocChars(totalLength);
- if (!buffer)
+ UChar* buffer;
+ if (!allocChars(totalLength).getValue(buffer))
return null();
int maxCount = max(rangeCount, separatorCount);
@@ -1105,8 +1141,8 @@ UString UString::replaceRange(int rangeStart, int rangeLength, const UString& re
if (totalLength == 0)
return "";
- UChar* buffer = allocChars(totalLength);
- if (!buffer)
+ UChar* buffer;
+ if (!allocChars(totalLength).getValue(buffer))
return null();
copyChars(buffer, data(), rangeStart);
@@ -1153,8 +1189,8 @@ UString& UString::append(const UString &t)
} else {
// This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
makeNull();
else {
copyChars(d, data(), thisSize);
@@ -1176,18 +1212,6 @@ UString& UString::append(const UChar* tData, int tSize)
return *this;
}
-UString& UString::appendNumeric(int i)
-{
- m_rep = concatenate(rep(), i);
- return *this;
-}
-
-UString& UString::appendNumeric(double d)
-{
- m_rep = concatenate(rep(), d);
- return *this;
-}
-
UString& UString::append(const char* t)
{
m_rep = concatenate(m_rep.release(), t);
@@ -1206,8 +1230,8 @@ UString& UString::append(UChar c)
if (length == 0) {
// this is empty - must make a new m_rep because we don't want to pollute the shared empty one
size_t newCapacity = expandedSize(1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
makeNull();
else {
d[0] = c;
@@ -1234,8 +1258,8 @@ UString& UString::append(UChar c)
} else {
// This is shared in some way that prevents us from modifying base, so we must make a whole new string.
size_t newCapacity = expandedSize(length + 1, 0);
- UChar* d = allocChars(newCapacity);
- if (!d)
+ UChar* d;
+ if (!allocChars(newCapacity).getValue(d))
makeNull();
else {
copyChars(d, data(), length);
@@ -1313,8 +1337,7 @@ UString& UString::operator=(const char* c)
m_rep->_hash = 0;
m_rep->len = l;
} else {
- d = allocChars(l);
- if (!d) {
+ if (!allocChars(l).getValue(d)) {
makeNull();
return *this;
}
diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h
index d01b75d..c4dad2a 100644
--- a/JavaScriptCore/runtime/UString.h
+++ b/JavaScriptCore/runtime/UString.h
@@ -91,7 +91,8 @@ namespace JSC {
{
// Guard against integer overflow
if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) {
- if (void * buf = tryFastMalloc(size * sizeof(UChar)))
+ void* buf = 0;
+ if (tryFastMalloc(size * sizeof(UChar)).getValue(buf))
return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size));
}
return adoptRef(new BaseString(0, 0, 0));
@@ -256,6 +257,7 @@ namespace JSC {
}
static UString from(int);
+ static UString from(long long);
static UString from(unsigned int);
static UString from(long);
static UString from(double);
@@ -285,8 +287,6 @@ namespace JSC {
UString& append(UChar);
UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); }
UString& append(const UChar*, int size);
- UString& appendNumeric(int);
- UString& appendNumeric(double);
bool getCString(CStringBuffer&) const;