summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-24 16:36:50 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-24 16:36:50 +0100
commitad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch)
treeb34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/JavaScriptCore/runtime
parent03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff)
downloadqtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.cpp73
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h1
-rw-r--r--Source/JavaScriptCore/runtime/CodeSpecializationKind.h36
-rw-r--r--Source/JavaScriptCore/runtime/CommonIdentifiers.h1
-rw-r--r--Source/JavaScriptCore/runtime/CommonSlowPaths.h33
-rw-r--r--Source/JavaScriptCore/runtime/DatePrototype.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/Error.cpp29
-rw-r--r--Source/JavaScriptCore/runtime/Error.h5
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp80
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h30
-rw-r--r--Source/JavaScriptCore/runtime/ExecutionHarness.h72
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp108
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h35
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h30
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp8
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp26
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h34
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp40
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp158
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h51
-rw-r--r--Source/JavaScriptCore/runtime/JSPropertyNameIterator.h3
-rw-r--r--Source/JavaScriptCore/runtime/JSString.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h3
-rw-r--r--Source/JavaScriptCore/runtime/JSTypeInfo.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSVariableObject.h2
-rw-r--r--Source/JavaScriptCore/runtime/LiteralParser.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/ObjectConstructor.cpp126
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.cpp18
-rw-r--r--Source/JavaScriptCore/runtime/ObjectPrototype.h1
-rw-r--r--Source/JavaScriptCore/runtime/Options.cpp10
-rw-r--r--Source/JavaScriptCore/runtime/Options.h4
-rw-r--r--Source/JavaScriptCore/runtime/PropertyDescriptor.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/RegExp.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/RegExpCache.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/SamplingCounter.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/SamplingCounter.h2
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/ScopeChain.h3
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp46
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h16
-rw-r--r--Source/JavaScriptCore/runtime/StructureChain.h3
-rw-r--r--Source/JavaScriptCore/runtime/StructureTransitionTable.h19
-rw-r--r--Source/JavaScriptCore/runtime/WriteBarrier.h8
50 files changed, 881 insertions, 317 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp
index 6a675ab84..a099adb75 100644
--- a/Source/JavaScriptCore/runtime/Arguments.cpp
+++ b/Source/JavaScriptCore/runtime/Arguments.cpp
@@ -243,6 +243,9 @@ bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
{
Arguments* thisObject = jsCast<Arguments*>(cell);
if (i < thisObject->d->numArguments) {
+ if (!Base::deletePropertyByIndex(cell, exec, i))
+ return false;
+
if (!thisObject->d->deletedArguments) {
thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
@@ -258,10 +261,16 @@ bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
{
+ if (exec->globalData().isInDefineOwnProperty())
+ return Base::deleteProperty(cell, exec, propertyName);
+
Arguments* thisObject = jsCast<Arguments*>(cell);
bool isArrayIndex;
unsigned i = propertyName.toArrayIndex(isArrayIndex);
if (isArrayIndex && i < thisObject->d->numArguments) {
+ if (!Base::deleteProperty(cell, exec, propertyName))
+ return false;
+
if (!thisObject->d->deletedArguments) {
thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
@@ -285,12 +294,74 @@ bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, const Identifier&
thisObject->createStrictModeCalleeIfNecessary(exec);
}
- if (propertyName == exec->propertyNames().caller && !thisObject->d->isStrictMode)
+ if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
thisObject->createStrictModeCallerIfNecessary(exec);
return JSObject::deleteProperty(thisObject, exec, propertyName);
}
+bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ Arguments* thisObject = jsCast<Arguments*>(object);
+ bool isArrayIndex;
+ unsigned i = propertyName.toArrayIndex(isArrayIndex);
+ if (isArrayIndex && i < thisObject->d->numArguments) {
+ if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow))
+ return false;
+
+ if (!thisObject->d->deletedArguments) {
+ thisObject->d->deletedArguments = adoptArrayPtr(new bool[thisObject->d->numArguments]);
+ memset(thisObject->d->deletedArguments.get(), 0, sizeof(bool) * thisObject->d->numArguments);
+ }
+ // From ES 5.1, 10.6 Arguments Object
+ // 5. If the value of isMapped is not undefined, then
+ if (!thisObject->d->deletedArguments[i]) {
+ // a. If IsAccessorDescriptor(Desc) is true, then
+ if (descriptor.isAccessorDescriptor()) {
+ // i. Call the [[Delete]] internal method of map passing P, and false as the arguments.
+ thisObject->d->deletedArguments[i] = true;
+ } else if (descriptor.value()) { // b. Else i. If Desc.[[Value]] is present, then
+ // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments.
+ // ii. If Desc.[[Writable]] is present and its value is false, then
+ thisObject->argument(i).set(exec->globalData(), thisObject, descriptor.value());
+ if (descriptor.writablePresent() && !descriptor.writable())
+ thisObject->d->deletedArguments[i] = true; // 1. Call the [[Delete]] internal method of map passing P and false as arguments.
+ }
+ }
+
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) {
+ thisObject->d->overrodeLength = true;
+ if (!descriptor.isAccessorDescriptor()) {
+ if (!descriptor.value())
+ descriptor.setValue(jsNumber(thisObject->d->numArguments));
+ if (!descriptor.configurablePresent())
+ descriptor.setConfigurable(true);
+ }
+ if (!descriptor.configurablePresent())
+ descriptor.setConfigurable(true);
+ }
+
+ if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) {
+ thisObject->d->overrodeCallee = true;
+ if (!descriptor.isAccessorDescriptor()) {
+ if (!descriptor.value())
+ descriptor.setValue(thisObject->d->callee.get());
+ if (!descriptor.configurablePresent())
+ descriptor.setConfigurable(true);
+ }
+ if (!descriptor.configurablePresent())
+ descriptor.setConfigurable(true);
+ }
+
+ if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode)
+ thisObject->createStrictModeCallerIfNecessary(exec);
+
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
+}
+
void Arguments::tearOff(CallFrame* callFrame)
{
if (isTornOff())
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h
index 3564fe447..ee54a49eb 100644
--- a/Source/JavaScriptCore/runtime/Arguments.h
+++ b/Source/JavaScriptCore/runtime/Arguments.h
@@ -117,6 +117,7 @@ namespace JSC {
static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName);
static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+ static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
void createStrictModeCallerIfNecessary(ExecState*);
void createStrictModeCalleeIfNecessary(ExecState*);
diff --git a/Source/JavaScriptCore/runtime/CodeSpecializationKind.h b/Source/JavaScriptCore/runtime/CodeSpecializationKind.h
new file mode 100644
index 000000000..ba2a54f37
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/CodeSpecializationKind.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 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 CodeSpecializationKind_h
+#define CodeSpecializationKind_h
+
+namespace JSC {
+
+enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
+
+} // namespace JSC
+
+#endif // CodeSpecializationKind_h
+
diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
index 08d8644b5..d79e5c783 100644
--- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h
+++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h
@@ -62,6 +62,7 @@
macro(prototype) \
macro(set) \
macro(source) \
+ macro(stack) \
macro(test) \
macro(toExponential) \
macro(toFixed) \
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
index 86c4bd5c2..345af2ebe 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -27,6 +27,7 @@
#define CommonSlowPaths_h
#include "CodeBlock.h"
+#include "CodeSpecializationKind.h"
#include "ExceptionHelpers.h"
#include "JSArray.h"
@@ -41,6 +42,38 @@ namespace JSC {
namespace CommonSlowPaths {
+ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFile, CodeSpecializationKind kind)
+{
+ JSFunction* callee = asFunction(exec->callee());
+ ASSERT(!callee->isHostFunction());
+ CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind);
+ int argumentCountIncludingThis = exec->argumentCountIncludingThis();
+
+ // This ensures enough space for the worst case scenario of zero arguments passed by the caller.
+ if (!registerFile->grow(exec->registers() + newCodeBlock->numParameters() + newCodeBlock->m_numCalleeRegisters))
+ return 0;
+
+ ASSERT(argumentCountIncludingThis < newCodeBlock->numParameters());
+
+ // Too few arguments -- copy call frame and arguments, then fill in missing arguments with undefined.
+ size_t delta = newCodeBlock->numParameters() - argumentCountIncludingThis;
+ Register* src = exec->registers();
+ Register* dst = exec->registers() + delta;
+
+ int i;
+ int end = -ExecState::offsetFor(argumentCountIncludingThis);
+ for (i = -1; i >= end; --i)
+ dst[i] = src[i];
+
+ end -= delta;
+ for ( ; i >= end; --i)
+ dst[i] = jsUndefined();
+
+ ExecState* newExec = ExecState::create(dst);
+ ASSERT((void*)newExec <= registerFile->end());
+ return newExec;
+}
+
ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto)
{
ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell()
diff --git a/Source/JavaScriptCore/runtime/DatePrototype.cpp b/Source/JavaScriptCore/runtime/DatePrototype.cpp
index 922fb0a86..ddea33786 100644
--- a/Source/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/Source/JavaScriptCore/runtime/DatePrototype.cpp
@@ -60,7 +60,7 @@
#include <sys/timeb.h>
#endif
-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN))
+#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WX) && OS(DARWIN)) || (PLATFORM(QT) && OS(DARWIN))
#include <CoreFoundation/CoreFoundation.h>
#elif USE(ICU_UNICODE)
#include <unicode/udat.h>
@@ -130,7 +130,7 @@ namespace JSC {
enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
-#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(WX) || (PLATFORM(QT) && OS(DARWIN))
+#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WX) && OS(DARWIN)) || (PLATFORM(QT) && OS(DARWIN))
// FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
// Instead we should consider using this whenever USE(CF) is true.
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index 0947e3c20..243dc8856 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -26,7 +26,9 @@
#include "ConstructData.h"
#include "ErrorConstructor.h"
+#include "ExceptionHelpers.h"
#include "FunctionPrototype.h"
+#include "JSArray.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSObject.h"
@@ -116,7 +118,7 @@ JSObject* createURIError(ExecState* exec, const UString& message)
return createURIError(exec->lexicalGlobalObject(), message);
}
-JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source)
+JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
{
const UString& sourceURL = source.provider()->url();
@@ -124,13 +126,34 @@ JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, cons
error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
if (!sourceURL.isNull())
error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
+ if (!stackTrace.isEmpty()) {
+ JSGlobalObject* globalObject = 0;
+ if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
+ globalObject = globalData->dynamicGlobalObject;
+ else
+ globalObject = error->globalObject();
+ // We use the tryCreateUninitialized creation mechanism and related initialization
+ // functions as they're the only mechanism we currently have that will guarantee we
+ // don't call setters on the prototype. Technically it's faster than the alternative,
+ // but the numerous allocations that take place in this loop makes that last bit
+ // somewhat moot.
+ JSArray* stackTraceArray = JSArray::tryCreateUninitialized(*globalData, globalObject->arrayStructure(), stackTrace.size());
+ if (!stackTraceArray)
+ return error;
+ for (unsigned i = 0; i < stackTrace.size(); i++) {
+ UString stackLevel = stackTrace[i].toString(globalObject->globalExec());
+ stackTraceArray->initializeIndex(*globalData, i, jsString(globalData, stackLevel));
+ }
+ stackTraceArray->completeInitialization(stackTrace.size());
+ error->putDirect(*globalData, globalData->propertyNames->stack, stackTraceArray, ReadOnly | DontDelete);
+ }
return error;
}
-JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
+JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace)
{
- return addErrorInfo(&exec->globalData(), error, line, source);
+ return addErrorInfo(&exec->globalData(), error, line, source, stackTrace);
}
bool hasErrorInfo(ExecState* exec, JSObject* error)
diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h
index 88b540a35..59b39495f 100644
--- a/Source/JavaScriptCore/runtime/Error.h
+++ b/Source/JavaScriptCore/runtime/Error.h
@@ -24,6 +24,7 @@
#define Error_h
#include "InternalFunction.h"
+#include "Interpreter.h"
#include "JSObject.h"
#include <stdint.h>
@@ -56,9 +57,9 @@ namespace JSC {
// Methods to add
bool hasErrorInfo(ExecState*, JSObject* error);
- JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&);
+ JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
// ExecState wrappers.
- JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
+ JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&);
// Methods to throw Errors.
JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue);
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index bf49767ab..25ddf764a 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -29,6 +29,7 @@
#include "BytecodeGenerator.h"
#include "CodeBlock.h"
#include "DFGDriver.h"
+#include "ExecutionHarness.h"
#include "JIT.h"
#include "JITDriver.h"
#include "Parser.h"
@@ -39,10 +40,12 @@ namespace JSC {
const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
+#if ENABLE(JIT)
void ExecutableBase::destroy(JSCell* cell)
{
jsCast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
}
+#endif
inline void ExecutableBase::clearCode()
{
@@ -67,10 +70,12 @@ Intrinsic ExecutableBase::intrinsic() const
const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
+#if ENABLE(JIT)
void NativeExecutable::destroy(JSCell* cell)
{
jsCast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
}
+#endif
#if ENABLE(DFG_JIT)
Intrinsic NativeExecutable::intrinsic() const
@@ -84,7 +89,7 @@ Intrinsic NativeExecutable::intrinsic() const
template<typename T>
static void jettisonCodeBlock(JSGlobalData& globalData, OwnPtr<T>& codeBlock)
{
- ASSERT(codeBlock->getJITType() != JITCode::BaselineJIT);
+ ASSERT(JITCode::isOptimizingJIT(codeBlock->getJITType()));
ASSERT(codeBlock->alternative());
OwnPtr<T> codeBlockToJettison = codeBlock.release();
codeBlock = static_pointer_cast<T>(codeBlockToJettison->releaseAlternative());
@@ -100,10 +105,12 @@ void NativeExecutable::finalize(JSCell* cell)
const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
+#if ENABLE(JIT)
void ScriptExecutable::destroy(JSCell* cell)
{
jsCast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
}
+#endif
const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
@@ -169,9 +176,32 @@ JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scop
return error;
}
+#if ENABLE(JIT)
+void EvalExecutable::jitCompile(JSGlobalData& globalData)
+{
+ bool result = jitCompileIfAppropriate(globalData, m_evalCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
+ ASSERT_UNUSED(result, result);
+}
+#endif
+
+inline const char* samplingDescription(JITCode::JITType jitType)
+{
+ switch (jitType) {
+ case JITCode::InterpreterThunk:
+ return "Interpreter Compilation (TOTAL)";
+ case JITCode::BaselineJIT:
+ return "Baseline Compilation (TOTAL)";
+ case JITCode::DFGJIT:
+ return "DFG Compilation (TOTAL)";
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
+
JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
+ SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
@@ -212,12 +242,12 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
}
#if ENABLE(JIT)
- if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
+ if (!prepareForExecution(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType))
return 0;
#endif
#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (!m_jitCodeForCall)
Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
else
@@ -297,9 +327,17 @@ JSObject* ProgramExecutable::compileOptimized(ExecState* exec, ScopeChainNode* s
return error;
}
+#if ENABLE(JIT)
+void ProgramExecutable::jitCompile(JSGlobalData& globalData)
+{
+ bool result = jitCompileIfAppropriate(globalData, m_programCodeBlock, m_jitCodeForCall, JITCode::bottomTierJIT());
+ ASSERT_UNUSED(result, result);
+}
+#endif
+
JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
+ SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
@@ -338,12 +376,12 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
}
#if ENABLE(JIT)
- if (!jitCompileIfAppropriate(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
+ if (!prepareForExecution(*globalData, m_programCodeBlock, m_jitCodeForCall, jitType))
return 0;
#endif
#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (!m_jitCodeForCall)
Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
else
@@ -414,7 +452,7 @@ FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKi
while (result->alternative())
result = static_cast<FunctionCodeBlock*>(result->alternative());
ASSERT(result);
- ASSERT(result->getJITType() == JITCode::BaselineJIT);
+ ASSERT(JITCode::isBaselineCode(result->getJITType()));
return result;
}
@@ -440,6 +478,20 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, Scop
return error;
}
+#if ENABLE(JIT)
+void FunctionExecutable::jitCompileForCall(JSGlobalData& globalData)
+{
+ bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
+ ASSERT_UNUSED(result, result);
+}
+
+void FunctionExecutable::jitCompileForConstruct(JSGlobalData& globalData)
+{
+ bool result = jitCompileFunctionIfAppropriate(globalData, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT());
+ ASSERT_UNUSED(result, result);
+}
+#endif
+
FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializationKind kind)
{
FunctionCodeBlock* codeBlock = baselineCodeBlockFor(kind);
@@ -484,7 +536,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChain
JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
+ SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(exec);
@@ -506,12 +558,12 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
#if ENABLE(JIT)
- if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType))
+ if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, CodeForCall))
return 0;
#endif
#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (!m_jitCodeForCall)
Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
else
@@ -526,7 +578,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType)
{
- SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)");
+ SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
UNUSED_PARAM(jitType);
@@ -548,12 +600,12 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
#if ENABLE(JIT)
- if (!jitCompileFunctionIfAppropriate(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType))
+ if (!prepareFunctionForExecution(exec->globalData(), m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, CodeForConstruct))
return 0;
#endif
#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (!m_jitCodeForConstruct)
Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
else
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 6800b5a82..69e80b28e 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -27,6 +27,7 @@
#define Executable_h
#include "CallData.h"
+#include "CodeSpecializationKind.h"
#include "JSFunction.h"
#include "Interpreter.h"
#include "Nodes.h"
@@ -39,12 +40,12 @@ namespace JSC {
class Debugger;
class EvalCodeBlock;
class FunctionCodeBlock;
+ class LLIntOffsetsExtractor;
class ProgramCodeBlock;
class ScopeChainNode;
struct ExceptionInfo;
- enum CodeSpecializationKind { CodeForCall, CodeForConstruct };
enum CompilationKind { FirstCompilation, OptimizingCompilation };
inline bool isCall(CodeSpecializationKind kind)
@@ -77,7 +78,9 @@ namespace JSC {
public:
typedef JSCell Base;
+#if ENABLE(JIT)
static void destroy(JSCell*);
+#endif
bool isHostFunction() const
{
@@ -197,7 +200,7 @@ namespace JSC {
}
#endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
{
ASSERT(!globalData.canUseJIT());
@@ -208,7 +211,9 @@ namespace JSC {
}
#endif
+#if ENABLE(JIT)
static void destroy(JSCell*);
+#endif
NativeFunction function() { return m_function; }
NativeFunction constructor() { return m_constructor; }
@@ -233,7 +238,7 @@ namespace JSC {
}
#endif
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
void finishCreation(JSGlobalData& globalData)
{
ASSERT(!globalData.canUseJIT());
@@ -276,7 +281,9 @@ namespace JSC {
{
}
+#if ENABLE(JIT)
static void destroy(JSCell*);
+#endif
const SourceCode& source() { return m_source; }
intptr_t sourceID() const { return m_source.provider()->asID(); }
@@ -319,6 +326,7 @@ namespace JSC {
};
class EvalExecutable : public ScriptExecutable {
+ friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
@@ -338,6 +346,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
+ void jitCompile(JSGlobalData&);
#endif
EvalCodeBlock& generatedBytecode()
@@ -384,6 +393,7 @@ namespace JSC {
};
class ProgramExecutable : public ScriptExecutable {
+ friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
@@ -411,6 +421,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCode(JSGlobalData&);
+ void jitCompile(JSGlobalData&);
#endif
ProgramCodeBlock& generatedBytecode()
@@ -453,6 +464,7 @@ namespace JSC {
class FunctionExecutable : public ScriptExecutable {
friend class JIT;
+ friend class LLIntOffsetsExtractor;
public:
typedef ScriptExecutable Base;
@@ -508,6 +520,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCodeForCall(JSGlobalData&);
+ void jitCompileForCall(JSGlobalData&);
#endif
bool isGeneratedForCall() const
@@ -535,6 +548,7 @@ namespace JSC {
#if ENABLE(JIT)
void jettisonOptimizedCodeForConstruct(JSGlobalData&);
+ void jitCompileForConstruct(JSGlobalData&);
#endif
bool isGeneratedForConstruct() const
@@ -582,6 +596,16 @@ namespace JSC {
jettisonOptimizedCodeForConstruct(globalData);
}
}
+
+ void jitCompileFor(JSGlobalData& globalData, CodeSpecializationKind kind)
+ {
+ if (kind == CodeForCall) {
+ jitCompileForCall(globalData);
+ return;
+ }
+ ASSERT(kind == CodeForConstruct);
+ jitCompileForConstruct(globalData);
+ }
#endif
bool isGeneratedFor(CodeSpecializationKind kind)
diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h
new file mode 100644
index 000000000..774c5bf6b
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 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 ExecutionHarness_h
+#define ExecutionHarness_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(JIT)
+
+#include "JITDriver.h"
+#include "LLIntEntrypoints.h"
+
+namespace JSC {
+
+template<typename CodeBlockType>
+inline bool prepareForExecution(JSGlobalData& globalData, OwnPtr<CodeBlockType>& codeBlock, JITCode& jitCode, JITCode::JITType jitType)
+{
+#if ENABLE(LLINT)
+ if (JITCode::isBaselineCode(jitType)) {
+ // Start off in the low level interpreter.
+ LLInt::getEntrypoint(globalData, codeBlock.get(), jitCode);
+ codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr());
+ return true;
+ }
+#endif // ENABLE(LLINT)
+ return jitCompileIfAppropriate(globalData, codeBlock, jitCode, jitType);
+}
+
+inline bool prepareFunctionForExecution(JSGlobalData& globalData, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType, CodeSpecializationKind kind)
+{
+#if ENABLE(LLINT)
+ if (JITCode::isBaselineCode(jitType)) {
+ // Start off in the low level interpreter.
+ LLInt::getFunctionEntrypoint(globalData, kind, jitCode, jitCodeWithArityCheck);
+ codeBlock->setJITCode(jitCode, jitCodeWithArityCheck);
+ return true;
+ }
+#else
+ UNUSED_PARAM(kind);
+#endif // ENABLE(LLINT)
+ return jitCompileFunctionIfAppropriate(globalData, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType);
+}
+
+} // namespace JSC
+
+#endif // ENABLE(JIT)
+
+#endif // ExecutionHarness_h
+
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index c18492344..80c8aa8d0 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -75,6 +75,8 @@ namespace JSC {
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); }
+ bool isValidScopedLookup(int index) { return index < m_numCapturedVars; }
+
protected:
void finishCreation(CallFrame*);
static const unsigned StructureFlags = IsEnvironmentRecord | OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index c84fb5b10..71d520018 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -24,8 +24,8 @@
#include "JSArray.h"
#include "ArrayPrototype.h"
-#include "BumpSpace.h"
-#include "BumpSpaceInlineMethods.h"
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlineMethods.h"
#include "CachedCall.h"
#include "Error.h"
#include "Executable.h"
@@ -42,6 +42,7 @@ using namespace WTF;
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSArray);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSArray);
// Overview of JSArray
//
@@ -160,10 +161,6 @@ void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength)
m_storage->m_inCompactInitialization = false;
#endif
- WriteBarrier<Unknown>* vector = m_storage->m_vector;
- for (size_t i = 0; i < initialVectorLength; ++i)
- vector[i].clear();
-
checkConsistency();
}
@@ -193,10 +190,6 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig
m_storage->m_inCompactInitialization = true;
#endif
- WriteBarrier<Unknown>* vector = m_storage->m_vector;
- for (size_t i = initialLength; i < initialVectorLength; ++i)
- vector[i].clear();
-
return this;
}
@@ -222,7 +215,17 @@ inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(J
inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value)
{
- SparseArrayEntry& entry = add(array, i).first->second;
+ std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i);
+ SparseArrayEntry& entry = result.first->second;
+
+ // To save a separate find & add, we first always add to the sparse map.
+ // In the uncommon case that this is a new property, and the array is not
+ // extensible, this is not the right thing to have done - so remove again.
+ if (result.second && !array->isExtensible()) {
+ remove(result.first);
+ // FIXME: should throw in strict mode.
+ return;
+ }
if (!(entry.attributes & Accessor)) {
if (entry.attributes & ReadOnly) {
@@ -240,7 +243,8 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i
JSObject* setter = asGetterSetter(accessor)->setter();
if (!setter) {
- throwTypeError(exec, "setting a property that has only a getter");
+ // FIXME: should throw if being called from strict mode.
+ // throwTypeError(exec, "setting a property that has only a getter");
return;
}
@@ -383,7 +387,7 @@ void JSArray::putDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, Prope
accessor->setSetter(exec->globalData(), setter);
entryInMap->set(exec->globalData(), this, accessor);
- entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~DontDelete;
+ entryInMap->attributes = descriptor.attributesOverridingCurrent(oldDescriptor) & ~ReadOnly;
return;
}
@@ -464,7 +468,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
// 7. If the [[Configurable]] field of current is false then
if (!current.configurable()) {
// 7.a. Reject, if the [[Configurable]] field of Desc is true.
- if (descriptor.configurablePresent() && !descriptor.configurable())
+ if (descriptor.configurablePresent() && descriptor.configurable())
return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
// 7.b. Reject, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.
if (descriptor.enumerablePresent() && current.enumerable() != descriptor.enumerable())
@@ -682,7 +686,7 @@ bool JSArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const
{
JSArray* thisObject = jsCast<JSArray*>(object);
if (propertyName == exec->propertyNames().length) {
- descriptor.setDescriptor(jsNumber(thisObject->length()), DontDelete | DontEnum);
+ descriptor.setDescriptor(jsNumber(thisObject->length()), thisObject->isLengthWritable() ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
return true;
}
@@ -784,6 +788,9 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
// First, handle cases where we don't currently have a sparse map.
if (LIKELY(!map)) {
+ // If the array is not extensible, we should have entered dictionary mode, and created the spare map.
+ ASSERT(isExtensible());
+
// Update m_length if necessary.
if (i >= storage->m_length)
storage->m_length = i + 1;
@@ -807,7 +814,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
unsigned length = storage->m_length;
if (i >= length) {
// Prohibit growing the array if length is not writable.
- if (map->lengthIsReadOnly()) {
+ if (map->lengthIsReadOnly() || !isExtensible()) {
// FIXME: should throw in strict mode.
return;
}
@@ -977,10 +984,6 @@ bool JSArray::increaseVectorLength(JSGlobalData& globalData, unsigned newLength)
m_storage->m_allocBase = newStorage;
ASSERT(m_storage->m_allocBase);
- WriteBarrier<Unknown>* vector = storage->m_vector;
- for (unsigned i = vectorLength; i < newVectorLength; ++i)
- vector[i].clear();
-
m_vectorLength = newVectorLength;
return true;
@@ -1000,10 +1003,8 @@ bool JSArray::increaseVectorLength(JSGlobalData& globalData, unsigned newLength)
m_indexBias = newIndexBias;
m_storage = reinterpret_cast_ptr<ArrayStorage*>(reinterpret_cast<WriteBarrier<Unknown>*>(newAllocBase) + m_indexBias);
- // Copy the ArrayStorage header & current contents of the vector, clear the new post-capacity.
+ // Copy the ArrayStorage header & current contents of the vector.
memmove(m_storage, storage, storageSize(vectorLength));
- for (unsigned i = vectorLength; i < m_vectorLength; ++i)
- m_storage->m_vector[i].clear();
// Free the old allocation, update m_allocBase.
m_storage->m_allocBase = newAllocBase;
@@ -1086,13 +1087,6 @@ bool JSArray::unshiftCountSlowCase(JSGlobalData& globalData, unsigned count)
if (newAllocBase != m_storage->m_allocBase) {
// Free the old allocation, update m_allocBase.
m_storage->m_allocBase = newAllocBase;
-
- // We need to clear any entries in the vector beyond length. We only need to
- // do this if this was a new allocation, because if we're using an existing
- // allocation the post-capacity will already be cleared, and in an existing
- // allocation we can only beshrinking the amount of post capacity.
- for (unsigned i = requiredVectorLength; i < m_vectorLength; ++i)
- m_storage->m_vector[i].clear();
}
return true;
@@ -1169,7 +1163,6 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
JSValue JSArray::pop(ExecState* exec)
{
checkConsistency();
-
ArrayStorage* storage = m_storage;
unsigned length = storage->m_length;
@@ -1179,47 +1172,32 @@ JSValue JSArray::pop(ExecState* exec)
return jsUndefined();
}
- --length;
-
- JSValue result;
-
- if (length < m_vectorLength) {
- WriteBarrier<Unknown>& valueSlot = storage->m_vector[length];
+ unsigned index = length - 1;
+ if (index < m_vectorLength) {
+ WriteBarrier<Unknown>& valueSlot = storage->m_vector[index];
if (valueSlot) {
--storage->m_numValuesInVector;
- result = valueSlot.get();
+ JSValue element = valueSlot.get();
valueSlot.clear();
- } else
- result = jsUndefined();
- } else {
- result = jsUndefined();
- if (SparseArrayValueMap* map = m_sparseValueMap) {
- SparseArrayValueMap::iterator it = map->find(length);
- if (it != map->notFound()) {
- unsigned attributes = it->second.attributes;
-
- result = it->second.get(exec, this);
- if (exec->hadException())
- return jsUndefined();
-
- if (attributes & DontDelete) {
- throwError(exec, createTypeError(exec, "Unable to delete property."));
- checkConsistency();
- return result;
- }
-
- map->remove(it);
- if (map->isEmpty() && !map->sparseMode())
- deallocateSparseMap();
- }
+
+ ASSERT(isLengthWritable());
+ storage->m_length = index;
+ checkConsistency();
+ return element;
}
}
- storage->m_length = length;
-
+ // Let element be the result of calling the [[Get]] internal method of O with argument indx.
+ JSValue element = get(exec, index);
+ if (exec->hadException())
+ return jsUndefined();
+ // Call the [[Delete]] internal method of O with arguments indx and true.
+ deletePropertyByIndex(this, exec, index);
+ // Call the [[Put]] internal method of O with arguments "length", indx, and true.
+ setLength(exec, index, true);
+ // Return element.
checkConsistency();
-
- return result;
+ return element;
}
// Push & putIndex are almost identical, with two small differences.
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index a3354c602..3bb4c6320 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -28,6 +28,7 @@
namespace JSC {
class JSArray;
+ class LLIntOffsetsExtractor;
struct SparseArrayEntry : public WriteBarrier<Unknown> {
typedef WriteBarrier<Unknown> Base;
@@ -116,12 +117,15 @@ namespace JSC {
unsigned m_numValuesInVector;
void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector.
#if CHECK_ARRAY_CONSISTENCY
- bool m_inCompactInitialization;
+ uintptr_t m_inCompactInitialization; // Needs to be a uintptr_t for alignment purposes.
+#else
+ uintptr_t m_padding;
#endif
WriteBarrier<Unknown> m_vector[1];
};
class JSArray : public JSNonFinalObject {
+ friend class LLIntOffsetsExtractor;
friend class Walker;
protected:
@@ -135,23 +139,14 @@ namespace JSC {
static void finalize(JSCell*);
- static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0)
- {
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
- array->finishCreation(globalData, initialLength);
- return array;
- }
+ static JSArray* create(JSGlobalData&, Structure*, unsigned initialLength = 0);
// tryCreateUninitialized is used for fast construction of arrays whose size and
// contents are known at time of creation. Clients of this interface must:
// - null-check the result (indicating out of memory, or otherwise unable to allocate vector).
// - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength.
// - called 'completeInitialization' after all properties have been initialized.
- static JSArray* tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
- {
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
- return array->tryFinishCreationUninitialized(globalData, initialLength);
- }
+ static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException);
@@ -253,6 +248,8 @@ namespace JSC {
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+ void enterDictionaryMode(JSGlobalData&);
+
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
@@ -274,7 +271,6 @@ namespace JSC {
void setLengthWritable(ExecState*, bool writable);
void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
- void enterDictionaryMode(JSGlobalData&);
void allocateSparseMap(JSGlobalData&);
void deallocateSparseMap();
@@ -299,6 +295,19 @@ namespace JSC {
void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily.
};
+ inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+ {
+ JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
+ array->finishCreation(globalData, initialLength);
+ return array;
+ }
+
+ inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+ {
+ JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure);
+ return array->tryFinishCreationUninitialized(globalData, initialLength);
+ }
+
JSArray* asArray(JSValue);
inline JSArray* asArray(JSCell* cell)
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 74833d12f..78d2d0801 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -36,9 +36,10 @@
namespace JSC {
class JSGlobalObject;
- class Structure;
+ class LLIntOffsetsExtractor;
class PropertyDescriptor;
class PropertyNameArray;
+ class Structure;
enum EnumerationMode {
ExcludeDontEnumProperties,
@@ -61,6 +62,7 @@ namespace JSC {
class JSCell {
friend class JSValue;
friend class MarkedBlock;
+ template<typename T> friend void* allocateCell(Heap&);
public:
enum CreatingEarlyCellTag { CreatingEarlyCell };
@@ -162,6 +164,8 @@ namespace JSC {
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
private:
+ friend class LLIntOffsetsExtractor;
+
const ClassInfo* m_classInfo;
WriteBarrier<Structure> m_structure;
};
@@ -307,14 +311,34 @@ namespace JSC {
return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
}
- template <typename T> void* allocateCell(Heap& heap)
+#if COMPILER(CLANG)
+ template<class T>
+ struct NeedsDestructor {
+ static const bool value = !__has_trivial_destructor(T);
+ };
+#else
+ // Write manual specializations for this struct template if you care about non-clang compilers.
+ template<class T>
+ struct NeedsDestructor {
+ static const bool value = true;
+ };
+#endif
+
+ template<typename T>
+ void* allocateCell(Heap& heap)
{
#if ENABLE(GC_VALIDATION)
ASSERT(sizeof(T) == T::s_info.cellSize);
ASSERT(!heap.globalData()->isInitializingObject());
heap.globalData()->setInitializingObject(true);
#endif
- JSCell* result = static_cast<JSCell*>(heap.allocate(sizeof(T)));
+ JSCell* result = 0;
+ if (NeedsDestructor<T>::value)
+ result = static_cast<JSCell*>(heap.allocateWithDestructor(sizeof(T)));
+ else {
+ ASSERT(T::s_info.methodTable.destroy == JSCell::destroy);
+ result = static_cast<JSCell*>(heap.allocateWithoutDestructor(sizeof(T)));
+ }
result->clearStructure();
return result;
}
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 72e1ce14f..253128279 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -50,6 +50,7 @@ EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
}
ASSERT_CLASS_FITS_IN_CELL(JSFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFunction);
const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFunction) };
@@ -108,13 +109,6 @@ void JSFunction::finishCreation(ExecState* exec, FunctionExecutable* executable,
putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
}
-void JSFunction::destroy(JSCell* cell)
-{
- JSFunction* thisObject = jsCast<JSFunction*>(cell);
- ASSERT(thisObject->classInfo()->isSubClassOf(&JSFunction::s_info));
- thisObject->JSFunction::~JSFunction();
-}
-
const UString& JSFunction::name(ExecState* exec)
{
return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index a12b079d7..6e8557f59 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -33,6 +33,7 @@ namespace JSC {
class FunctionPrototype;
class JSActivation;
class JSGlobalObject;
+ class LLIntOffsetsExtractor;
class NativeExecutable;
class SourceCode;
namespace DFG {
@@ -64,8 +65,6 @@ namespace JSC {
return function;
}
- static void destroy(JSCell*);
-
JS_EXPORT_PRIVATE const UString& name(ExecState*);
JS_EXPORT_PRIVATE const UString displayName(ExecState*);
const UString calculatedDisplayName(ExecState*);
@@ -142,6 +141,8 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&);
private:
+ friend class LLIntOffsetsExtractor;
+
JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index bbe520a1e..2bdc28ab7 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -35,6 +35,7 @@
#include "DebuggerActivation.h"
#include "FunctionConstructor.h"
#include "GetterSetter.h"
+#include "HostCallReturnValue.h"
#include "Interpreter.h"
#include "JSActivation.h"
#include "JSAPIValueWrapper.h"
@@ -141,6 +142,8 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, keywords(adoptPtr(new Keywords(this)))
, interpreter(0)
, heap(this, heapSize)
+ , jsArrayClassInfo(&JSArray::s_info)
+ , jsFinalObjectClassInfo(&JSFinalObject::s_info)
#if ENABLE(DFG_JIT)
, sizeOfLastScratchBuffer(0)
#endif
@@ -160,6 +163,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#if ENABLE(GC_VALIDATION)
, m_isInitializingObject(false)
#endif
+ , m_inDefineOwnProperty(false)
{
interpreter = new Interpreter;
@@ -189,7 +193,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
-#if ENABLE(JIT) && ENABLE(INTERPRETER)
+#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
#if USE(CF)
CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
@@ -209,16 +213,20 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#endif
#endif
#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (m_canUseJIT)
m_canUseJIT = executableAllocator.isValid();
#endif
jitStubs = adoptPtr(new JITThunks(this));
#endif
- interpreter->initialize(this->canUseJIT());
+ interpreter->initialize(&llintData, this->canUseJIT());
+
+ initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
heap.notifyIsSafeToCollect();
+
+ llintData.performAssertions(*this);
}
void JSGlobalData::clearBuiltinStructures()
@@ -383,7 +391,7 @@ static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
{
-#if ENABLE(INTERPRETER)
+#if ENABLE(CLASSIC_INTERPRETER)
if (!canUseJIT())
return NativeExecutable::create(*this, function, constructor);
#endif
@@ -502,17 +510,17 @@ void JSGlobalData::dumpRegExpTrace()
RTTraceList::iterator iter = ++m_rtTraceList->begin();
if (iter != m_rtTraceList->end()) {
- printf("\nRegExp Tracing\n");
- printf(" match() matches\n");
- printf("Regular Expression JIT Address calls found\n");
- printf("----------------------------------------+----------------+----------+----------\n");
+ dataLog("\nRegExp Tracing\n");
+ dataLog(" match() matches\n");
+ dataLog("Regular Expression JIT Address calls found\n");
+ dataLog("----------------------------------------+----------------+----------+----------\n");
unsigned reCount = 0;
for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
(*iter)->printTraceData();
- printf("%d Regular Expressions\n", reCount);
+ dataLog("%d Regular Expressions\n", reCount);
}
m_rtTraceList->clear();
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 92817f2a2..7e54c00db 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -30,15 +30,16 @@
#define JSGlobalData_h
#include "CachedTranscendentalFunction.h"
-#include "Intrinsic.h"
#include "DateInstanceCache.h"
#include "ExecutableAllocator.h"
#include "Heap.h"
-#include "Strong.h"
+#include "Intrinsic.h"
#include "JITStubs.h"
#include "JSValue.h"
+#include "LLIntData.h"
#include "NumericStrings.h"
#include "SmallStrings.h"
+#include "Strong.h"
#include "Terminator.h"
#include "TimeoutChecker.h"
#include "WeakRandom.h"
@@ -65,6 +66,7 @@ namespace JSC {
class JSGlobalObject;
class JSObject;
class Keywords;
+ class LLIntOffsetsExtractor;
class NativeExecutable;
class ParserArena;
class RegExpCache;
@@ -211,13 +213,23 @@ namespace JSC {
codeBlocksBeingCompiled.removeLast();
}
+ void setInDefineOwnProperty(bool inDefineOwnProperty)
+ {
+ m_inDefineOwnProperty = inDefineOwnProperty;
+ }
+
+ bool isInDefineOwnProperty()
+ {
+ return m_inDefineOwnProperty;
+ }
+
#if ENABLE(ASSEMBLER)
ExecutableAllocator executableAllocator;
#endif
#if !ENABLE(JIT)
bool canUseJIT() { return false; } // interpreter only
-#elif !ENABLE(INTERPRETER)
+#elif !ENABLE(CLASSIC_INTERPRETER)
bool canUseJIT() { return true; } // jit only
#else
bool canUseJIT() { return m_canUseJIT; }
@@ -241,7 +253,12 @@ namespace JSC {
Heap heap;
JSValue exception;
-#if ENABLE(JIT)
+
+ const ClassInfo* const jsArrayClassInfo;
+ const ClassInfo* const jsFinalObjectClassInfo;
+
+ LLInt::Data llintData;
+
ReturnAddressPtr exceptionLocation;
JSValue hostCallReturnValue;
CallFrame* callFrameForThrow;
@@ -271,7 +288,6 @@ namespace JSC {
return scratchBuffers.last();
}
#endif
-#endif
HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;
@@ -332,7 +348,7 @@ namespace JSC {
ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
m_##type##ArrayDescriptor = descriptor; \
} \
- const TypedArrayDescriptor& type##ArrayDescriptor() const { return m_##type##ArrayDescriptor; }
+ const TypedArrayDescriptor& type##ArrayDescriptor() const { ASSERT(m_##type##ArrayDescriptor.m_classInfo); return m_##type##ArrayDescriptor; }
registerTypedArrayFunction(int8, Int8);
registerTypedArrayFunction(int16, Int16);
@@ -346,15 +362,19 @@ namespace JSC {
#undef registerTypedArrayFunction
private:
+ friend class LLIntOffsetsExtractor;
+
JSGlobalData(GlobalDataType, ThreadStackType, HeapSize);
static JSGlobalData*& sharedInstanceInternal();
void createNativeThunk();
-#if ENABLE(JIT) && ENABLE(INTERPRETER)
+#if ENABLE(JIT) && ENABLE(CLASSIC_INTERPRETER)
bool m_canUseJIT;
#endif
#if ENABLE(GC_VALIDATION)
bool m_isInitializingObject;
#endif
+ bool m_inDefineOwnProperty;
+
TypedArrayDescriptor m_int8ArrayDescriptor;
TypedArrayDescriptor m_int16ArrayDescriptor;
TypedArrayDescriptor m_int32ArrayDescriptor;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index e648fbe21..8d3975848 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -78,7 +78,7 @@ namespace JSC {
const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) };
-const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript };
+const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript };
/* Source for JSGlobalObject.lut.h
@begin globalObjectTable
@@ -205,6 +205,10 @@ void JSGlobalObject::reset(JSValue prototype)
m_callFunction.set(exec->globalData(), this, callFunction);
m_applyFunction.set(exec->globalData(), this, applyFunction);
m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull())));
+ GetterSetter* protoAccessor = GetterSetter::create(exec);
+ protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoGetter));
+ protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoSetter));
+ m_objectPrototype->putDirectAccessor(exec->globalData(), exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum);
m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index b67ccb764..cbc436e1a 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -44,6 +44,7 @@ namespace JSC {
class FunctionPrototype;
class GetterSetter;
class GlobalCodeBlock;
+ class LLIntOffsetsExtractor;
class NativeErrorConstructor;
class ProgramCodeBlock;
class RegExpConstructor;
@@ -56,6 +57,9 @@ namespace JSC {
typedef Vector<ExecState*, 16> ExecStateStack;
struct GlobalObjectMethodTable {
+ typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);
+ AllowsAccessFromFunctionPtr allowsAccessFrom;
+
typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*);
SupportsProfilingFunctionPtr supportsProfiling;
@@ -279,6 +283,7 @@ namespace JSC {
const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
+ static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }
static bool supportsProfiling(const JSGlobalObject*) { return false; }
static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
@@ -336,6 +341,8 @@ namespace JSC {
JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count);
private:
+ friend class LLIntOffsetsExtractor;
+
// FIXME: Fold reset into init.
JS_EXPORT_PRIVATE void init(JSObject* thisValue);
void reset(JSValue prototype);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index b82ab62ab..db8ee1d85 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -297,7 +297,7 @@ static double parseInt(const UString& s, const CharType* data, int radix)
}
if (number >= mantissaOverflowLowerBound) {
if (radix == 10)
- number = WTF::strtod(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0);
+ number = WTF::strtod<WTF::AllowTrailingJunk>(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0);
else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix);
}
@@ -369,7 +369,7 @@ static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
}
byteBuffer.append(0);
char* endOfNumber;
- double number = WTF::strtod(byteBuffer.data(), &endOfNumber);
+ double number = WTF::strtod<WTF::AllowTrailingJunk>(byteBuffer.data(), &endOfNumber);
// Check if strtod found a number; if so return it.
ptrdiff_t consumed = endOfNumber - byteBuffer.data();
@@ -714,4 +714,40 @@ EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState* exec)
return throwVMTypeError(exec);
}
+EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
+{
+ if (!exec->thisValue().isObject())
+ return JSValue::encode(exec->thisValue().synthesizePrototype(exec));
+
+ JSObject* thisObject = asObject(exec->thisValue());
+ if (!thisObject->allowsAccessFrom(exec->trueCallerFrame()))
+ return JSValue::encode(jsUndefined());
+
+ return JSValue::encode(thisObject->prototype());
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
+{
+ JSValue value = exec->argument(0);
+
+ // Setting __proto__ of a primitive should have no effect.
+ if (!exec->thisValue().isObject())
+ return JSValue::encode(jsUndefined());
+
+ JSObject* thisObject = asObject(exec->thisValue());
+ if (!thisObject->allowsAccessFrom(exec->trueCallerFrame()))
+ return JSValue::encode(jsUndefined());
+
+ // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
+ if (!value.isObject() && !value.isNull())
+ return JSValue::encode(jsUndefined());
+
+ if (!thisObject->isExtensible())
+ return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+
+ if (!thisObject->setPrototypeWithCycleCheck(exec->globalData(), value))
+ throwError(exec, createError(exec, "cyclic __proto__ value"));
+ return JSValue::encode(jsUndefined());
+}
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
index 1183dfac5..8833bf6d0 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
@@ -48,6 +48,8 @@ namespace JSC {
EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState*);
+ EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
+ EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
static const double mantissaOverflowLowerBound = 9007199254740992.0;
double parseIntOverflow(const LChar*, int length, int radix);
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index ba2d2a52a..acc4a181e 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -24,7 +24,7 @@
#include "config.h"
#include "JSObject.h"
-#include "BumpSpaceInlineMethods.h"
+#include "CopiedSpaceInlineMethods.h"
#include "DatePrototype.h"
#include "ErrorConstructor.h"
#include "GetterSetter.h"
@@ -48,6 +48,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFinalObject);
const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
@@ -55,16 +56,6 @@ const ClassInfo JSObject::s_info = { "Object", 0, 0, 0, CREATE_METHOD_TABLE(JSOb
const ClassInfo JSFinalObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFinalObject) };
-void JSFinalObject::destroy(JSCell* cell)
-{
- jsCast<JSFinalObject*>(cell)->JSFinalObject::~JSFinalObject();
-}
-
-void JSNonFinalObject::destroy(JSCell* cell)
-{
- jsCast<JSNonFinalObject*>(cell)->JSNonFinalObject::~JSNonFinalObject();
-}
-
static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
{
// Add properties from the static hashtables of properties
@@ -84,11 +75,6 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
}
}
-void JSObject::destroy(JSCell* cell)
-{
- jsCast<JSObject*>(cell)->JSObject::~JSObject();
-}
-
void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSObject* thisObject = jsCast<JSObject*>(cell);
@@ -146,47 +132,36 @@ void JSObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
JSGlobalData& globalData = exec->globalData();
- if (propertyName == exec->propertyNames().underscoreProto) {
- // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
- if (!value.isObject() && !value.isNull())
- return;
-
- if (!thisObject->isExtensible()) {
- if (slot.isStrictMode())
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
- return;
- }
-
- if (!thisObject->setPrototypeWithCycleCheck(globalData, value))
- throwError(exec, createError(exec, "cyclic __proto__ value"));
- return;
- }
-
// Check if there are any setters or getters in the prototype chain
JSValue prototype;
- for (JSObject* obj = thisObject; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
- prototype = obj->prototype();
- if (prototype.isNull()) {
- if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
- return;
+ if (propertyName != exec->propertyNames().underscoreProto) {
+ for (JSObject* obj = thisObject; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
+ prototype = obj->prototype();
+ if (prototype.isNull()) {
+ if (!thisObject->putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)) && slot.isStrictMode())
+ throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ return;
+ }
}
}
-
- unsigned attributes;
- JSCell* specificValue;
- if ((thisObject->structure()->get(globalData, propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
- if (slot.isStrictMode())
- throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
- return;
- }
for (JSObject* obj = thisObject; ; obj = asObject(prototype)) {
- if (JSValue gs = obj->getDirect(globalData, propertyName)) {
+ unsigned attributes;
+ JSCell* specificValue;
+ size_t offset = obj->structure()->get(globalData, propertyName, attributes, specificValue);
+ if (offset != WTF::notFound) {
+ if (attributes & ReadOnly) {
+ if (slot.isStrictMode())
+ throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+ return;
+ }
+
+ JSValue gs = obj->getDirectOffset(offset);
if (gs.isGetterSetter()) {
JSObject* setterFunc = asGetterSetter(gs)->setter();
if (!setterFunc) {
- throwSetterError(exec);
+ if (slot.isStrictMode())
+ throwSetterError(exec);
return;
}
@@ -229,10 +204,31 @@ void JSObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identif
object->putDirectInternal<PutModeDefineOwnProperty>(exec->globalData(), propertyName, value, attributes, slot, getJSFunction(value));
}
+bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
+{
+ JSValue checkFor = this;
+ if (this->isGlobalObject())
+ checkFor = static_cast<JSGlobalObject*>(this)->globalExec()->thisValue();
+
+ JSValue nextPrototype = prototype;
+ while (nextPrototype && nextPrototype.isObject()) {
+ if (nextPrototype == checkFor)
+ return false;
+ nextPrototype = asObject(nextPrototype)->prototype();
+ }
+ setPrototype(globalData, prototype);
+ return true;
+}
+
+bool JSObject::allowsAccessFrom(ExecState* exec)
+{
+ JSGlobalObject* globalObject = isGlobalThis() ? static_cast<JSGlobalThis*>(this)->unwrappedObject() : this->globalObject();
+ return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec);
+}
+
void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(value.isGetterSetter() && (attributes & Accessor));
- ASSERT(propertyName != globalData.propertyNames->underscoreProto);
PutPropertySlot slot;
putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value));
@@ -243,7 +239,10 @@ void JSObject::putDirectAccessor(JSGlobalData& globalData, const Identifier& pro
if (slot.type() != PutPropertySlot::NewProperty)
setStructure(globalData, Structure::attributeChangeTransition(globalData, structure(), propertyName, attributes));
- structure()->setHasGetterSetterProperties(true);
+ if (attributes & ReadOnly)
+ structure()->setContainsReadOnlyProperties();
+
+ structure()->setHasGetterSetterProperties(propertyName == globalData.propertyNames->underscoreProto);
}
bool JSObject::hasProperty(ExecState* exec, const Identifier& propertyName) const
@@ -269,7 +268,7 @@ bool JSObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& p
unsigned attributes;
JSCell* specificValue;
if (thisObject->structure()->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
- if ((attributes & DontDelete))
+ if (attributes & DontDelete && !exec->globalData().isInDefineOwnProperty())
return false;
thisObject->removeDirect(exec->globalData(), propertyName);
return true;
@@ -277,7 +276,7 @@ bool JSObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& p
// Look in the static hashtable of properties
const HashEntry* entry = thisObject->findPropertyHashEntry(exec, propertyName);
- if (entry && entry->attributes() & DontDelete)
+ if (entry && entry->attributes() & DontDelete && !exec->globalData().isInDefineOwnProperty())
return false; // this builtin property can't be deleted
// FIXME: Should the code here actually do some deletion?
@@ -479,6 +478,8 @@ void JSObject::freeze(JSGlobalData& globalData)
void JSObject::preventExtensions(JSGlobalData& globalData)
{
+ if (isJSArray(this))
+ asArray(this)->enterDictionaryMode(globalData);
if (isExtensible())
setStructure(globalData, Structure::preventExtensionsTransition(globalData, structure()));
}
@@ -623,6 +624,8 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
else if (oldDescriptor.value())
newValue = oldDescriptor.value();
target->putDirect(exec->globalData(), propertyName, newValue, attributes & ~Accessor);
+ if (attributes & ReadOnly)
+ target->structure()->setContainsReadOnlyProperties();
return true;
}
attributes &= ~ReadOnly;
@@ -641,12 +644,30 @@ static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& p
return true;
}
+class DefineOwnPropertyScope {
+public:
+ DefineOwnPropertyScope(ExecState* exec)
+ : m_globalData(exec->globalData())
+ {
+ m_globalData.setInDefineOwnProperty(true);
+ }
+
+ ~DefineOwnPropertyScope()
+ {
+ m_globalData.setInDefineOwnProperty(false);
+ }
+
+private:
+ JSGlobalData& m_globalData;
+};
+
bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
{
- // __proto__ is magic; we don't currently support setting it as a regular property.
- // Silent filter out calls to set __proto__ at an early stage; pretend all is okay.
- if (propertyName == exec->propertyNames().underscoreProto)
- return true;
+ // Track on the globaldata that we're in define property.
+ // Currently DefineOwnProperty uses delete to remove properties when they are being replaced
+ // (particularly when changing attributes), however delete won't allow non-configurable (i.e.
+ // DontDelete) properties to be deleted. For now, we can use this flag to make this work.
+ DefineOwnPropertyScope scope(exec);
// If we have a new property we can just put it on normally
PropertyDescriptor current;
@@ -711,21 +732,15 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
return false;
}
if (!current.writable()) {
- if (descriptor.value() || !sameValue(exec, current.value(), descriptor.value())) {
+ if (descriptor.value() && !sameValue(exec, current.value(), descriptor.value())) {
if (throwException)
throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
return false;
}
}
- } else if (current.attributesEqual(descriptor)) {
- if (!descriptor.value())
- return true;
- PutPropertySlot slot;
- object->methodTable()->put(object, exec, propertyName, descriptor.value(), slot);
- if (exec->hadException())
- return false;
- return true;
}
+ if (current.attributesEqual(descriptor) && !descriptor.value())
+ return true;
object->methodTable()->deleteProperty(object, exec, propertyName);
return putDescriptor(exec, object, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
}
@@ -748,15 +763,14 @@ bool JSObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identi
if (!accessor)
return false;
GetterSetter* getterSetter = asGetterSetter(accessor);
- if (current.attributesEqual(descriptor)) {
- if (descriptor.setterPresent())
- getterSetter->setSetter(exec->globalData(), descriptor.setterObject());
- if (descriptor.getterPresent())
- getterSetter->setGetter(exec->globalData(), descriptor.getterObject());
+ if (descriptor.setterPresent())
+ getterSetter->setSetter(exec->globalData(), descriptor.setterObject());
+ if (descriptor.getterPresent())
+ getterSetter->setGetter(exec->globalData(), descriptor.getterObject());
+ if (current.attributesEqual(descriptor))
return true;
- }
object->methodTable()->deleteProperty(object, exec, propertyName);
- unsigned attrs = current.attributesWithOverride(descriptor);
+ unsigned attrs = descriptor.attributesOverridingCurrent(current);
object->putDirectAccessor(exec->globalData(), propertyName, getterSetter, attrs | Accessor);
return true;
}
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index e9194fa01..c117cffaf 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -49,6 +49,7 @@ namespace JSC {
class GetterSetter;
class HashEntry;
class InternalFunction;
+ class LLIntOffsetsExtractor;
class MarkedBlock;
class PropertyDescriptor;
class PropertyNameArray;
@@ -84,8 +85,6 @@ namespace JSC {
public:
typedef JSCell Base;
- JS_EXPORT_PRIVATE static void destroy(JSCell*);
-
JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
JS_EXPORT_PRIVATE static UString className(const JSObject*);
@@ -107,6 +106,8 @@ namespace JSC {
JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+ bool allowsAccessFrom(ExecState*);
+
JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
@@ -264,6 +265,8 @@ namespace JSC {
JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
private:
+ friend class LLIntOffsetsExtractor;
+
// Nobody should ever ask any of these questions on something already known to be a JSObject.
using JSCell::isAPIValueWrapper;
using JSCell::isGetterSetter;
@@ -323,8 +326,6 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
- JS_EXPORT_PRIVATE static void destroy(JSCell*);
-
protected:
explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
: JSObject(globalData, structure, m_inlineStorage)
@@ -343,6 +344,8 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
};
+ class JSFinalObject;
+
// JSFinalObject is a type of JSObject that contains sufficent internal
// storage to fully make use of the colloctor cell containing it.
class JSFinalObject : public JSObject {
@@ -351,13 +354,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
public:
typedef JSObject Base;
- static JSFinalObject* create(ExecState* exec, Structure* structure)
- {
- JSFinalObject* finalObject = new (NotNull, allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
- finalObject->finishCreation(exec->globalData());
- return finalObject;
- }
-
+ static JSFinalObject* create(ExecState*, Structure*);
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info);
@@ -374,9 +371,9 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
ASSERT(classInfo());
}
- static void destroy(JSCell*);
-
private:
+ friend class LLIntOffsetsExtractor;
+
explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
: JSObject(globalData, structure, m_inlineStorage)
{
@@ -387,6 +384,13 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
};
+inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure)
+{
+ JSFinalObject* finalObject = new (NotNull, allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
+ finalObject->finishCreation(exec->globalData());
+ return finalObject;
+}
+
inline bool isJSFinalObject(JSCell* cell)
{
return cell->classInfo() == &JSFinalObject::s_info;
@@ -489,19 +493,6 @@ inline JSValue JSObject::prototype() const
return structure()->storedPrototype();
}
-inline bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
-{
- JSValue nextPrototypeValue = prototype;
- while (nextPrototypeValue && nextPrototypeValue.isObject()) {
- JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
- if (nextPrototype == this)
- return false;
- nextPrototypeValue = nextPrototype->prototype();
- }
- setPrototype(globalData, prototype);
- return true;
-}
-
inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
{
ASSERT(prototype);
@@ -553,12 +544,6 @@ ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Ide
return true;
}
- // non-standard Netscape extension
- if (propertyName == exec->propertyNames().underscoreProto) {
- slot.setValue(prototype());
- return true;
- }
-
return false;
}
@@ -806,8 +791,6 @@ inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, Pro
{
if (UNLIKELY(!isCell())) {
JSObject* prototype = synthesizePrototype(exec);
- if (propertyName == exec->propertyNames().underscoreProto)
- return prototype;
if (!prototype->getPropertySlot(exec, propertyName, slot))
return jsUndefined();
return slot.getValue(exec, propertyName);
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
index d52e3ea61..7530d7532 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -38,6 +38,7 @@ namespace JSC {
class Identifier;
class JSObject;
+ class LLIntOffsetsExtractor;
class JSPropertyNameIterator : public JSCell {
friend class JIT;
@@ -96,6 +97,8 @@ namespace JSC {
}
private:
+ friend class LLIntOffsetsExtractor;
+
JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
WriteBarrier<Structure> m_cachedStructure;
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 4e98f9d18..cfa7d03b4 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -189,7 +189,7 @@ void JSString::outOfMemory(ExecState* exec) const
{
for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i)
m_fibers[i].clear();
- ASSERT(!isRope());
+ ASSERT(isRope());
ASSERT(m_value == UString());
if (exec)
throwOutOfMemoryError(exec);
@@ -253,10 +253,6 @@ bool JSString::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifie
// This function should only be called by JSValue::get.
if (thisObject->getStringPropertySlot(exec, propertyName, slot))
return true;
- if (propertyName == exec->propertyNames().underscoreProto) {
- slot.setValue(exec->lexicalGlobalObject()->stringPrototype());
- return true;
- }
slot.setBase(thisObject);
JSObject* object;
for (JSValue prototype = exec->lexicalGlobalObject()->stringPrototype(); !prototype.isNull(); prototype = object->prototype()) {
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index c0637a6e0..32a32788a 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -32,6 +32,7 @@
namespace JSC {
class JSString;
+ class LLIntOffsetsExtractor;
JSString* jsEmptyString(JSGlobalData*);
JSString* jsEmptyString(ExecState*);
@@ -240,6 +241,8 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&);
private:
+ friend class LLIntOffsetsExtractor;
+
JS_EXPORT_PRIVATE void resolveRope(ExecState*) const;
void resolveRopeSlowCase8(LChar*) const;
void resolveRopeSlowCase(UChar*) const;
diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h
index 3e23aa253..83a3594db 100644
--- a/Source/JavaScriptCore/runtime/JSTypeInfo.h
+++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h
@@ -34,6 +34,8 @@
namespace JSC {
+ class LLIntOffsetsExtractor;
+
static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable.
static const unsigned ImplementsHasInstance = 1 << 1;
static const unsigned OverridesHasInstance = 1 << 2;
@@ -87,6 +89,8 @@ namespace JSC {
}
private:
+ friend class LLIntOffsetsExtractor;
+
bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; }
bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); }
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index 72cf5a8d5..e3843f02b 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -118,7 +118,7 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const
char* JSValue::description()
{
- static const size_t size = 64;
+ static const size_t size = 128;
static char description[size];
if (!*this)
@@ -127,14 +127,14 @@ char* JSValue::description()
snprintf(description, size, "Int32: %d", asInt32());
else if (isDouble()) {
#if USE(JSVALUE64)
- snprintf(description, size, "Double: %lf, %lx", asDouble(), reinterpretDoubleToIntptr(asDouble()));
+ snprintf(description, size, "Double: %lx, %lf", reinterpretDoubleToIntptr(asDouble()), asDouble());
#else
union {
double asDouble;
uint32_t asTwoInt32s[2];
} u;
u.asDouble = asDouble();
- snprintf(description, size, "Double: %lf, %08x:%08x", asDouble(), u.asTwoInt32s[1], u.asTwoInt32s[0]);
+ snprintf(description, size, "Double: %08x:%08x, %lf", u.asTwoInt32s[1], u.asTwoInt32s[0], asDouble());
#endif
} else if (isCell())
snprintf(description, size, "Cell: %p", asCell());
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index b18c181f5..9f797e05d 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -55,6 +55,9 @@ namespace JSC {
class SpeculativeJIT;
}
#endif
+ namespace LLInt {
+ class Data;
+ }
struct ClassInfo;
struct Instruction;
@@ -118,6 +121,7 @@ namespace JSC {
friend class DFG::OSRExitCompiler;
friend class DFG::SpeculativeJIT;
#endif
+ friend class LLInt::Data;
public:
static EncodedJSValue encode(JSValue);
@@ -234,6 +238,8 @@ namespace JSC {
char* description();
+ JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
+
private:
template <class T> JSValue(WriteBarrierBase<T>);
@@ -246,7 +252,6 @@ namespace JSC {
JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
- JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const;
JSObject* synthesizeObject(ExecState*) const;
#if USE(JSVALUE32_64)
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index c1d05ff74..8d058f1fc 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -38,10 +38,12 @@
namespace JSC {
+ class LLIntOffsetsExtractor;
class Register;
class JSVariableObject : public JSNonFinalObject {
friend class JIT;
+ friend class LLIntOffsetsExtractor;
public:
typedef JSNonFinalObject Base;
diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp
index b22b81503..3bde3ff08 100644
--- a/Source/JavaScriptCore/runtime/LiteralParser.cpp
+++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -294,7 +295,7 @@ ALWAYS_INLINE TokenType LiteralParser<LChar>::Lexer::lexIdentifier(LiteralParser
template <>
ALWAYS_INLINE TokenType LiteralParser<UChar>::Lexer::lexIdentifier(LiteralParserToken<UChar>& token)
{
- while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
+ while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$' || *m_ptr == 0x200C || *m_ptr == 0x200D))
m_ptr++;
token.stringIs8Bit = 0;
token.stringToken16 = token.start;
@@ -536,7 +537,7 @@ TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType>
}
buffer[i] = 0;
char* end;
- token.numberToken = WTF::strtod(buffer.data(), &end);
+ token.numberToken = WTF::strtod<WTF::AllowTrailingJunk>(buffer.data(), &end);
ASSERT(buffer.data() + (token.end - token.start) == end);
return TokNumber;
}
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index d96c1de7f..b7dd71655 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -138,11 +138,10 @@ EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec)
{
if (!exec->argument(0).isObject())
return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object."));
-
- // This uses JSValue::get() instead of directly accessing the prototype from the object
- // (using JSObject::prototype()) in order to allow objects to override the behavior, such
- // as returning jsUndefined() for cross-origin access.
- return JSValue::encode(exec->argument(0).get(exec, exec->propertyNames().underscoreProto));
+ JSObject* object = asObject(exec->argument(0));
+ if (!object->allowsAccessFrom(exec->trueCallerFrame()))
+ return JSValue::encode(jsUndefined());
+ return JSValue::encode(object->prototype());
}
EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec)
@@ -342,9 +341,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec)
{
if (!exec->argument(0).isObject())
return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
- if (!exec->argument(1).isObject())
- return throwVMError(exec, createTypeError(exec, "Property descriptor list must be an Object."));
- return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), asObject(exec->argument(1))));
+ return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), exec->argument(1).toObject(exec)));
}
EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
@@ -362,19 +359,79 @@ EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
{
+ // 1. If Type(O) is not Object throw a TypeError exception.
JSValue obj = exec->argument(0);
if (!obj.isObject())
return throwVMError(exec, createTypeError(exec, "Object.seal can only be called on Objects."));
- asObject(obj)->seal(exec->globalData());
+ JSObject* object = asObject(obj);
+
+ if (isJSFinalObject(object)) {
+ object->seal(exec->globalData());
+ return JSValue::encode(obj);
+ }
+
+ // 2. For each named own property name P of O,
+ PropertyNameArray properties(exec);
+ object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+ PropertyNameArray::const_iterator end = properties.end();
+ for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+ // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+ PropertyDescriptor desc;
+ if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+ continue;
+ // b. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
+ desc.setConfigurable(false);
+ // c. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
+ object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
+ if (exec->hadException())
+ return JSValue::encode(obj);
+ }
+
+ // 3. Set the [[Extensible]] internal property of O to false.
+ object->preventExtensions(exec->globalData());
+
+ // 4. Return O.
return JSValue::encode(obj);
}
EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
{
+ // 1. If Type(O) is not Object throw a TypeError exception.
JSValue obj = exec->argument(0);
if (!obj.isObject())
return throwVMError(exec, createTypeError(exec, "Object.freeze can only be called on Objects."));
- asObject(obj)->freeze(exec->globalData());
+ JSObject* object = asObject(obj);
+
+ if (isJSFinalObject(object)) {
+ object->freeze(exec->globalData());
+ return JSValue::encode(obj);
+ }
+
+ // 2. For each named own property name P of O,
+ PropertyNameArray properties(exec);
+ object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+ PropertyNameArray::const_iterator end = properties.end();
+ for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+ // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+ PropertyDescriptor desc;
+ if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+ continue;
+ // b. If IsDataDescriptor(desc) is true, then
+ // i. If desc.[[Writable]] is true, set desc.[[Writable]] to false.
+ if (desc.isDataDescriptor())
+ desc.setWritable(false);
+ // c. If desc.[[Configurable]] is true, set desc.[[Configurable]] to false.
+ desc.setConfigurable(false);
+ // d. Call the [[DefineOwnProperty]] internal method of O with P, desc, and true as arguments.
+ object->methodTable()->defineOwnProperty(object, exec, *iter, desc, true);
+ if (exec->hadException())
+ return JSValue::encode(obj);
+ }
+
+ // 3. Set the [[Extensible]] internal property of O to false.
+ object->preventExtensions(exec->globalData());
+
+ // 4. Return O.
return JSValue::encode(obj);
}
@@ -389,18 +446,63 @@ EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
{
+ // 1. If Type(O) is not Object throw a TypeError exception.
JSValue obj = exec->argument(0);
if (!obj.isObject())
return throwVMError(exec, createTypeError(exec, "Object.isSealed can only be called on Objects."));
- return JSValue::encode(jsBoolean(asObject(obj)->isSealed(exec->globalData())));
+ JSObject* object = asObject(obj);
+
+ if (isJSFinalObject(object))
+ return JSValue::encode(jsBoolean(object->isSealed(exec->globalData())));
+
+ // 2. For each named own property name P of O,
+ PropertyNameArray properties(exec);
+ object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+ PropertyNameArray::const_iterator end = properties.end();
+ for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+ // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+ PropertyDescriptor desc;
+ if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+ continue;
+ // b. If desc.[[Configurable]] is true, then return false.
+ if (desc.configurable())
+ return JSValue::encode(jsBoolean(false));
+ }
+
+ // 3. If the [[Extensible]] internal property of O is false, then return true.
+ // 4. Otherwise, return false.
+ return JSValue::encode(jsBoolean(!object->isExtensible()));
}
EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
{
+ // 1. If Type(O) is not Object throw a TypeError exception.
JSValue obj = exec->argument(0);
if (!obj.isObject())
return throwVMError(exec, createTypeError(exec, "Object.isFrozen can only be called on Objects."));
- return JSValue::encode(jsBoolean(asObject(obj)->isFrozen(exec->globalData())));
+ JSObject* object = asObject(obj);
+
+ if (isJSFinalObject(object))
+ return JSValue::encode(jsBoolean(object->isFrozen(exec->globalData())));
+
+ // 2. For each named own property name P of O,
+ PropertyNameArray properties(exec);
+ object->methodTable()->getOwnPropertyNames(object, exec, properties, IncludeDontEnumProperties);
+ PropertyNameArray::const_iterator end = properties.end();
+ for (PropertyNameArray::const_iterator iter = properties.begin(); iter != end; ++iter) {
+ // a. Let desc be the result of calling the [[GetOwnProperty]] internal method of O with P.
+ PropertyDescriptor desc;
+ if (!object->methodTable()->getOwnPropertyDescriptor(object, exec, *iter, desc))
+ continue;
+ // b. If IsDataDescriptor(desc) is true then
+ // i. If desc.[[Writable]] is true, return false. c. If desc.[[Configurable]] is true, then return false.
+ if ((desc.isDataDescriptor() && desc.writable()) || desc.configurable())
+ return JSValue::encode(jsBoolean(false));
+ }
+
+ // 3. If the [[Extensible]] internal property of O is false, then return true.
+ // 4. Otherwise, return false.
+ return JSValue::encode(jsBoolean(!object->isExtensible()));
}
EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index 674bd7b7d..6ad312c7c 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -80,7 +80,7 @@ void ObjectPrototype::finishCreation(JSGlobalData& globalData, JSGlobalObject*)
void ObjectPrototype::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(cell);
- JSNonFinalObject::put(cell, exec, propertyName, value, slot);
+ Base::put(cell, exec, propertyName, value, slot);
if (thisObject->m_hasNoPropertiesWithUInt32Names) {
bool isUInt32;
@@ -89,12 +89,26 @@ void ObjectPrototype::put(JSCell* cell, ExecState* exec, const Identifier& prope
}
}
+bool ObjectPrototype::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(object);
+ bool result = Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow);
+
+ if (thisObject->m_hasNoPropertiesWithUInt32Names) {
+ bool isUInt32;
+ propertyName.toUInt32(isUInt32);
+ thisObject->m_hasNoPropertiesWithUInt32Names = !isUInt32;
+ }
+
+ return result;
+}
+
bool ObjectPrototype::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
ObjectPrototype* thisObject = jsCast<ObjectPrototype*>(cell);
if (thisObject->m_hasNoPropertiesWithUInt32Names)
return false;
- return JSNonFinalObject::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
+ return Base::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot);
}
bool ObjectPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.h b/Source/JavaScriptCore/runtime/ObjectPrototype.h
index 4c49e97a7..b9b8a30d4 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.h
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.h
@@ -51,6 +51,7 @@ namespace JSC {
private:
ObjectPrototype(ExecState*, Structure*);
static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+ static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp
index ddfba6e7c..5500508cf 100644
--- a/Source/JavaScriptCore/runtime/Options.cpp
+++ b/Source/JavaScriptCore/runtime/Options.cpp
@@ -52,6 +52,10 @@ unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
unsigned maximumInliningDepth;
+int32_t executionCounterValueForJITAfterWarmUp;
+int32_t executionCounterValueForDontJITAnytimeSoon;
+int32_t executionCounterValueForJITSoon;
+
int32_t executionCounterValueForOptimizeAfterWarmUp;
int32_t executionCounterValueForOptimizeAfterLongWarmUp;
int32_t executionCounterValueForDontOptimizeAnytimeSoon;
@@ -137,6 +141,10 @@ void initializeOptions()
SET(maximumInliningDepth, 5);
+ SET(executionCounterValueForJITAfterWarmUp, -100);
+ SET(executionCounterValueForDontJITAnytimeSoon, std::numeric_limits<int32_t>::min());
+ SET(executionCounterValueForJITSoon, -100);
+
SET(executionCounterValueForOptimizeAfterWarmUp, -1000);
SET(executionCounterValueForOptimizeAfterLongWarmUp, -5000);
SET(executionCounterValueForDontOptimizeAnytimeSoon, std::numeric_limits<int32_t>::min());
@@ -185,6 +193,8 @@ void initializeOptions()
if (cpusToUse < 1)
cpusToUse = 1;
+ cpusToUse = 1;
+
SET(numberOfGCMarkers, cpusToUse);
ASSERT(executionCounterValueForDontOptimizeAnytimeSoon <= executionCounterValueForOptimizeAfterLongWarmUp);
diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h
index feebd37bb..b9e68f90c 100644
--- a/Source/JavaScriptCore/runtime/Options.h
+++ b/Source/JavaScriptCore/runtime/Options.h
@@ -37,6 +37,10 @@ extern unsigned maximumFunctionForConstructInlineCandidateInstructionCount;
extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc.
+extern int32_t executionCounterValueForJITAfterWarmUp;
+extern int32_t executionCounterValueForDontJITAnytimeSoon;
+extern int32_t executionCounterValueForJITSoon;
+
extern int32_t executionCounterValueForOptimizeAfterWarmUp;
extern int32_t executionCounterValueForOptimizeAfterLongWarmUp;
extern int32_t executionCounterValueForDontOptimizeAnytimeSoon;
diff --git a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
index e3458e4b9..0cb629584 100644
--- a/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
+++ b/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp
@@ -217,12 +217,16 @@ unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& ot
newAttributes ^= DontDelete;
if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
newAttributes ^= DontEnum;
+ if (isAccessorDescriptor() && other.isDataDescriptor())
+ newAttributes |= ReadOnly;
return newAttributes;
}
unsigned PropertyDescriptor::attributesOverridingCurrent(const PropertyDescriptor& current) const
{
unsigned currentAttributes = current.m_attributes;
+ if (isDataDescriptor() && current.isAccessorDescriptor())
+ currentAttributes |= ReadOnly;
unsigned overrideMask = 0;
if (writablePresent())
overrideMask |= ReadOnly;
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 69bca5df0..2b7feb4b5 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -413,24 +413,24 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int*
differences++;
if (differences) {
- fprintf(stderr, "RegExp Discrepency for /%s/\n string input ", pattern().utf8().data());
+ dataLog("RegExp Discrepency for /%s/\n string input ", pattern().utf8().data());
unsigned segmentLen = s.length() - static_cast<unsigned>(startOffset);
- fprintf(stderr, (segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
+ dataLog((segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
if (jitResult != interpreterResult) {
- fprintf(stderr, " JIT result = %d, blah interpreted result = %d\n", jitResult, interpreterResult);
+ dataLog(" JIT result = %d, blah interpreted result = %d\n", jitResult, interpreterResult);
differences--;
} else {
- fprintf(stderr, " Correct result = %d\n", jitResult);
+ dataLog(" Correct result = %d\n", jitResult);
}
if (differences) {
for (unsigned j = 2, i = 0; i < m_numSubpatterns; j +=2, i++) {
if (offsetVector[j] != interpreterOffsetVector[j])
- fprintf(stderr, " JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j, offsetVector[j], j, interpreterOffsetVector[j]);
+ dataLog(" JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j, offsetVector[j], j, interpreterOffsetVector[j]);
if ((offsetVector[j] >= 0) && (offsetVector[j+1] != interpreterOffsetVector[j+1]))
- fprintf(stderr, " JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j+1, offsetVector[j+1], j+1, interpreterOffsetVector[j+1]);
+ dataLog(" JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j+1, offsetVector[j+1], j+1, interpreterOffsetVector[j+1]);
}
}
}
diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp
index cd96301db..d5edbbc7f 100644
--- a/Source/JavaScriptCore/runtime/RegExpCache.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp
@@ -46,7 +46,7 @@ RegExp* RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags fl
// We need to do a second lookup to add the RegExp as
// allocating it may have caused a gc cycle, which in
// turn may have removed items from the cache.
- m_weakCache.add(key, Weak<RegExp>(*m_globalData, regExp, this));
+ m_weakCache.add(key, PassWeak<RegExp>(*m_globalData, regExp, this));
return regExp;
}
diff --git a/Source/JavaScriptCore/runtime/SamplingCounter.cpp b/Source/JavaScriptCore/runtime/SamplingCounter.cpp
index e5fb25a93..abed763ca 100644
--- a/Source/JavaScriptCore/runtime/SamplingCounter.cpp
+++ b/Source/JavaScriptCore/runtime/SamplingCounter.cpp
@@ -35,10 +35,10 @@ void AbstractSamplingCounter::dump()
{
#if ENABLE(SAMPLING_COUNTERS)
if (s_abstractSamplingCounterChain != &s_abstractSamplingCounterChainEnd) {
- printf("\nSampling Counter Values:\n");
+ dataLog("\nSampling Counter Values:\n");
for (AbstractSamplingCounter* currCounter = s_abstractSamplingCounterChain; (currCounter != &s_abstractSamplingCounterChainEnd); currCounter = currCounter->m_next)
- printf("\t%s\t: %lld\n", currCounter->m_name, currCounter->m_counter);
- printf("\n\n");
+ dataLog("\t%s\t: %lld\n", currCounter->m_name, currCounter->m_counter);
+ dataLog("\n\n");
}
s_completed = true;
#endif
diff --git a/Source/JavaScriptCore/runtime/SamplingCounter.h b/Source/JavaScriptCore/runtime/SamplingCounter.h
index 329a5cfd3..8413b5458 100644
--- a/Source/JavaScriptCore/runtime/SamplingCounter.h
+++ b/Source/JavaScriptCore/runtime/SamplingCounter.h
@@ -159,7 +159,7 @@ public:
~DeletableSamplingCounter()
{
if (!s_completed)
- fprintf(stderr, "DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
+ dataFile("DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
// Our m_referer pointer should know where the pointer to this node is,
// and m_next should know that this node is the previous node in the list.
ASSERT(*m_referer == this);
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp
index 099f7fde6..e7ea07508 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.cpp
+++ b/Source/JavaScriptCore/runtime/ScopeChain.cpp
@@ -42,12 +42,12 @@ void ScopeChainNode::print()
o->methodTable()->getPropertyNames(o, globalObject->globalExec(), propertyNames, ExcludeDontEnumProperties);
PropertyNameArray::const_iterator propEnd = propertyNames.end();
- fprintf(stderr, "----- [scope %p] -----\n", o);
+ dataLog("----- [scope %p] -----\n", o);
for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
Identifier name = *propIter;
- fprintf(stderr, "%s, ", name.ustring().utf8().data());
+ dataLog("%s, ", name.ustring().utf8().data());
}
- fprintf(stderr, "\n");
+ dataLog("\n");
}
}
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h
index 6e358d779..c382008f1 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.h
+++ b/Source/JavaScriptCore/runtime/ScopeChain.h
@@ -30,6 +30,7 @@ namespace JSC {
class JSGlobalData;
class JSGlobalObject;
class JSObject;
+ class LLIntOffsetsExtractor;
class ScopeChainIterator;
class SlotVisitor;
@@ -91,6 +92,8 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
private:
+ friend class LLIntOffsetsExtractor;
+
static const unsigned StructureFlags = OverridesVisitChildren;
};
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index f387cf283..6ee419da6 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -142,17 +142,17 @@ void Structure::dumpStatistics()
}
}
- printf("Number of live Structures: %d\n", liveStructureSet.size());
- printf("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
- printf("Number of Structures that are leaf nodes: %d\n", numberLeaf);
- printf("Number of Structures that singletons: %d\n", numberSingletons);
- printf("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps);
-
- printf("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure)));
- printf("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
- printf("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size()));
+ dataLog("Number of live Structures: %d\n", liveStructureSet.size());
+ dataLog("Number of Structures using the single item optimization for transition map: %d\n", numberUsingSingleSlot);
+ dataLog("Number of Structures that are leaf nodes: %d\n", numberLeaf);
+ dataLog("Number of Structures that singletons: %d\n", numberSingletons);
+ dataLog("Number of Structures with PropertyMaps: %d\n", numberWithPropertyMaps);
+
+ dataLog("Size of a single Structures: %d\n", static_cast<unsigned>(sizeof(Structure)));
+ dataLog("Size of sum of all property maps: %d\n", totalPropertyMapsSize);
+ dataLog("Size of average of all property maps: %f\n", static_cast<double>(totalPropertyMapsSize) / static_cast<double>(liveStructureSet.size()));
#else
- printf("Dumping Structure statistics is not enabled.\n");
+ dataLog("Dumping Structure statistics is not enabled.\n");
#endif
}
@@ -167,6 +167,7 @@ Structure::Structure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSV
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
+ , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
, m_hasNonEnumerableProperties(false)
, m_attributesInPrevious(0)
, m_specificFunctionThrashCount(0)
@@ -188,6 +189,7 @@ Structure::Structure(JSGlobalData& globalData)
, m_dictionaryKind(NoneDictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(false)
+ , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(false)
, m_hasNonEnumerableProperties(false)
, m_attributesInPrevious(0)
, m_specificFunctionThrashCount(0)
@@ -207,6 +209,7 @@ Structure::Structure(JSGlobalData& globalData, const Structure* previous)
, m_dictionaryKind(previous->m_dictionaryKind)
, m_isPinnedPropertyTable(false)
, m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
+ , m_hasReadOnlyOrGetterSetterPropertiesExcludingProto(previous->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto)
, m_hasNonEnumerableProperties(previous->m_hasNonEnumerableProperties)
, m_attributesInPrevious(0)
, m_specificFunctionThrashCount(previous->m_specificFunctionThrashCount)
@@ -322,7 +325,7 @@ Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure*
transition->growPropertyStorageCapacity();
return transition;
}
-
+
Structure* transition = create(globalData, structure);
transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
@@ -467,9 +470,12 @@ Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* stru
Structure* transition = preventExtensionsTransition(globalData, structure);
if (transition->m_propertyTable) {
+ PropertyTable::iterator iter = transition->m_propertyTable->begin();
PropertyTable::iterator end = transition->m_propertyTable->end();
- for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
- iter->attributes |= (DontDelete | ReadOnly);
+ if (iter != end)
+ transition->m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+ for (; iter != end; ++iter)
+ iter->attributes |= iter->attributes & Accessor ? DontDelete : (DontDelete | ReadOnly);
}
return transition;
@@ -520,7 +526,9 @@ bool Structure::isFrozen(JSGlobalData& globalData)
PropertyTable::iterator end = m_propertyTable->end();
for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
- if ((iter->attributes & (DontDelete | ReadOnly)) != (DontDelete | ReadOnly))
+ if (!(iter->attributes & DontDelete))
+ return false;
+ if (!(iter->attributes & (ReadOnly | Accessor)))
return false;
}
return true;
@@ -601,11 +609,11 @@ static PropertyMapStatisticsExitLogger logger;
PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
{
- printf("\nJSC::PropertyMap statistics\n\n");
- printf("%d probes\n", numProbes);
- printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
- printf("%d rehashes\n", numRehashes);
- printf("%d removes\n", numRemoves);
+ dataLog("\nJSC::PropertyMap statistics\n\n");
+ dataLog("%d probes\n", numProbes);
+ dataLog("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
+ dataLog("%d rehashes\n", numRehashes);
+ dataLog("%d removes\n", numRemoves);
}
#endif
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index ced296856..46cf732e1 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -45,6 +45,7 @@
namespace JSC {
+ class LLIntOffsetsExtractor;
class PropertyNameArray;
class PropertyNameArrayData;
class StructureChain;
@@ -145,7 +146,17 @@ namespace JSC {
}
bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
- void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; }
+ bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
+ void setHasGetterSetterProperties(bool is__proto__)
+ {
+ m_hasGetterSetterProperties = true;
+ if (!is__proto__)
+ m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+ }
+ void setContainsReadOnlyProperties()
+ {
+ m_hasReadOnlyOrGetterSetterPropertiesExcludingProto = true;
+ }
bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; }
@@ -196,6 +207,8 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
private:
+ friend class LLIntOffsetsExtractor;
+
JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*);
Structure(JSGlobalData&);
Structure(JSGlobalData&, const Structure*);
@@ -282,6 +295,7 @@ namespace JSC {
unsigned m_dictionaryKind : 2;
bool m_isPinnedPropertyTable : 1;
bool m_hasGetterSetterProperties : 1;
+ bool m_hasReadOnlyOrGetterSetterPropertiesExcludingProto : 1;
bool m_hasNonEnumerableProperties : 1;
unsigned m_attributesInPrevious : 7;
unsigned m_specificFunctionThrashCount : 2;
diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h
index df7a37fa7..3b19d4cf1 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.h
+++ b/Source/JavaScriptCore/runtime/StructureChain.h
@@ -37,6 +37,7 @@
namespace JSC {
+ class LLIntOffsetsExtractor;
class Structure;
class StructureChain : public JSCell {
@@ -74,6 +75,8 @@ namespace JSC {
}
private:
+ friend class LLIntOffsetsExtractor;
+
StructureChain(JSGlobalData&, Structure*);
static void destroy(JSCell*);
OwnArrayPtr<WriteBarrier<Structure> > m_vector;
diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
index 536237a33..517992470 100644
--- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h
+++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h
@@ -29,7 +29,6 @@
#include "UString.h"
#include "WeakGCMap.h"
#include <wtf/HashFunctions.h>
-#include <wtf/HashTraits.h>
#include <wtf/OwnPtr.h>
#include <wtf/RefPtr.h>
@@ -55,22 +54,6 @@ class StructureTransitionTable {
static const bool safeToCompareToEmptyOrDeleted = true;
};
- struct HashTraits {
- typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
- typedef WTF::GenericHashTraits<unsigned> SecondTraits;
- typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
-
- 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 || SecondTraits::needsDestruction;
-
- static const int minimumTableSize = FirstTraits::minimumTableSize;
-
- static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
- static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
- };
-
struct WeakGCMapFinalizerCallback {
static void* finalizerContextFor(Hash::Key)
{
@@ -83,7 +66,7 @@ class StructureTransitionTable {
}
};
- typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
+ typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash> TransitionMap;
static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
index 6ac52b7c7..7e9db12fb 100644
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
@@ -26,6 +26,7 @@
#ifndef WriteBarrier_h
#define WriteBarrier_h
+#include "GCAssertions.h"
#include "HandleTypes.h"
#include "Heap.h"
#include "SamplingCounter.h"
@@ -73,6 +74,13 @@ public:
validateCell(value);
setEarlyValue(globalData, owner, value);
}
+
+ // This is meant to be used like operator=, but is called copyFrom instead, in
+ // order to kindly inform the C++ compiler that its advice is not appreciated.
+ void copyFrom(const WriteBarrierBase<T>& other)
+ {
+ m_cell = other.m_cell;
+ }
void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
{