summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime')
-rw-r--r--Source/JavaScriptCore/runtime/Arguments.h3
-rw-r--r--Source/JavaScriptCore/runtime/ArrayConventions.h2
-rw-r--r--Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h4
-rw-r--r--Source/JavaScriptCore/runtime/CodeCache.cpp186
-rw-r--r--Source/JavaScriptCore/runtime/CodeCache.h93
-rw-r--r--Source/JavaScriptCore/runtime/DateConstructor.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/DateInstanceCache.h6
-rw-r--r--Source/JavaScriptCore/runtime/ExceptionHelpers.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp247
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h68
-rw-r--r--Source/JavaScriptCore/runtime/ExecutionHarness.h4
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSActivation.h7
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSArray.h460
-rw-r--r--Source/JavaScriptCore/runtime/JSCell.h589
-rw-r--r--Source/JavaScriptCore/runtime/JSDateMath.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.cpp14
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalData.h12
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.cpp55
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObject.h19
-rw-r--r--Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp16
-rw-r--r--Source/JavaScriptCore/runtime/JSONObject.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h1394
-rw-r--r--Source/JavaScriptCore/runtime/JSScope.cpp5
-rw-r--r--Source/JavaScriptCore/runtime/JSType.h5
-rw-r--r--Source/JavaScriptCore/runtime/JSTypeInfo.h2
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/JSValue.h4
-rw-r--r--Source/JavaScriptCore/runtime/JSValueInlineMethods.h2
-rw-r--r--Source/JavaScriptCore/runtime/MathObject.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/Operations.h11
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp56
-rw-r--r--Source/JavaScriptCore/runtime/StringPrototype.cpp2
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp9
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h5
-rw-r--r--Source/JavaScriptCore/runtime/SymbolTable.h2
38 files changed, 1889 insertions, 1427 deletions
diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h
index 7c8b69bd1..7961d4bc8 100644
--- a/Source/JavaScriptCore/runtime/Arguments.h
+++ b/Source/JavaScriptCore/runtime/Arguments.h
@@ -267,8 +267,7 @@ namespace JSC {
m_overrodeCallee = false;
m_overrodeCaller = false;
m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode();
-
- ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable()->slowArguments());
+ ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->slowArguments());
// The bytecode generator omits op_tear_off_activation in cases of no
// declared parameters, so we need to tear off immediately.
diff --git a/Source/JavaScriptCore/runtime/ArrayConventions.h b/Source/JavaScriptCore/runtime/ArrayConventions.h
index a557b1ef9..3177c6c97 100644
--- a/Source/JavaScriptCore/runtime/ArrayConventions.h
+++ b/Source/JavaScriptCore/runtime/ArrayConventions.h
@@ -58,7 +58,7 @@ namespace JSC {
// These values have to be macros to be used in max() and min() without introducing
// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
-#define MIN_SPARSE_ARRAY_INDEX 10000U
+#define MIN_SPARSE_ARRAY_INDEX 100000U
#define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1)
// 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
#define MAX_ARRAY_INDEX 0xFFFFFFFEU
diff --git a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h b/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h
index f31b4a07f..62a01dbcb 100644
--- a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h
+++ b/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h
@@ -74,8 +74,8 @@ private:
// Lazily allocate the table, populate with NaN->NaN mapping.
m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry)));
for (unsigned x = 0; x < s_cacheSize; ++x) {
- m_cache[x].operand = std::numeric_limits<double>::quiet_NaN();
- m_cache[x].result = std::numeric_limits<double>::quiet_NaN();
+ m_cache[x].operand = QNaN;
+ m_cache[x].result = QNaN;
}
}
diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp
new file mode 100644
index 000000000..4de760e49
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/CodeCache.cpp
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "CodeCache.h"
+
+#include "BytecodeGenerator.h"
+#include "CodeSpecializationKind.h"
+#include "Parser.h"
+#include "StrongInlines.h"
+#include "UnlinkedCodeBlock.h"
+
+namespace JSC {
+
+CodeCache::CodeCache()
+ : m_randomGenerator(static_cast<uint32_t>(randomNumber() * UINT32_MAX))
+{
+}
+
+CodeCache::~CodeCache()
+{
+}
+
+CodeCache::CodeBlockKey CodeCache::makeCodeBlockKey(const SourceCode& source, CodeCache::CodeType type, JSParserStrictness strictness)
+{
+ return std::make_pair(source.toString(), (type << 1) | strictness);
+}
+
+template <typename T> struct CacheTypes { };
+
+template <> struct CacheTypes<UnlinkedProgramCodeBlock> {
+ typedef JSC::ProgramNode RootNode;
+ static const CodeCache::CodeType codeType = CodeCache::ProgramType;
+};
+
+template <> struct CacheTypes<UnlinkedEvalCodeBlock> {
+ typedef JSC::EvalNode RootNode;
+ static const CodeCache::CodeType codeType = CodeCache::EvalType;
+};
+
+template <class UnlinkedCodeBlockType, class ExecutableType>
+UnlinkedCodeBlockType* CodeCache::getCodeBlock(JSGlobalData& globalData, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+ CodeBlockKey key = makeCodeBlockKey(source, CacheTypes<UnlinkedCodeBlockType>::codeType, strictness);
+ bool storeInCache = false;
+ if (debuggerMode == DebuggerOff && profilerMode == ProfilerOff) {
+ CodeBlockIndicesMap::iterator result = m_cachedCodeBlockIndices.find(key);
+ if (result != m_cachedCodeBlockIndices.end()) {
+ UnlinkedCodeBlockType* unlinkedCode = jsCast<UnlinkedCodeBlockType*>(m_cachedCodeBlocks[result->value].second.get());
+ unsigned firstLine = source.firstLine() + unlinkedCode->firstLine();
+ executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount());
+ return unlinkedCode;
+ }
+ storeInCache = true;
+ }
+
+ typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode;
+ RefPtr<RootNode> rootNode = parse<RootNode>(&globalData, source, 0, Identifier(), strictness, JSParseProgramCode, error);
+ if (!rootNode)
+ return 0;
+ executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine());
+
+ UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&globalData, executable->executableInfo());
+ unlinkedCode->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), rootNode->lastLine() - rootNode->lineNo());
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(globalData, rootNode.get(), unlinkedCode, debuggerMode, profilerMode)));
+ error = generator->generate();
+ rootNode->destroyData();
+ if (error.m_type != ParserError::ErrorNone)
+ return 0;
+
+ if (storeInCache) {
+ size_t index = m_randomGenerator.getUint32() % kMaxCodeBlockEntries;
+ if (m_cachedCodeBlocks[index].second)
+ m_cachedCodeBlockIndices.remove(m_cachedCodeBlocks[index].first);
+ m_cachedCodeBlockIndices.set(key, index);
+ m_cachedCodeBlocks[index].second.set(globalData, unlinkedCode);
+ m_cachedCodeBlocks[index].first = key;
+ }
+
+ return unlinkedCode;
+}
+
+UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(JSGlobalData& globalData, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+ return getCodeBlock<UnlinkedProgramCodeBlock>(globalData, executable, source, strictness, debuggerMode, profilerMode, error);
+}
+
+UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(JSGlobalData& globalData, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+ return getCodeBlock<UnlinkedEvalCodeBlock>(globalData, executable, source, strictness, debuggerMode, profilerMode, error);
+}
+
+UnlinkedFunctionCodeBlock* CodeCache::generateFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+ RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&globalData, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error);
+
+ if (!body) {
+ ASSERT(error.m_type != ParserError::ErrorNone);
+ return 0;
+ }
+
+ if (executable->forceUsesArguments())
+ body->setUsesArguments();
+ body->finishParsing(executable->parameters(), executable->name(), executable->functionNameIsInScopeToggle());
+ executable->recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
+
+ UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&globalData, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(globalData, body.get(), result, debuggerMode, profilerMode)));
+ error = generator->generate();
+ body->destroyData();
+ if (error.m_type != ParserError::ErrorNone)
+ return 0;
+ return result;
+}
+
+UnlinkedFunctionCodeBlock* CodeCache::getFunctionCodeBlock(JSGlobalData& globalData, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+{
+ return generateFunctionCodeBlock(globalData, executable, source, kind, debuggerMode, profilerMode, error);
+}
+
+CodeCache::GlobalFunctionKey CodeCache::makeGlobalFunctionKey(const SourceCode& source, const String& name)
+{
+ return GlobalFunctionKey(source.toString(), name);
+}
+
+UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, ParserError& error)
+{
+ GlobalFunctionKey key = makeGlobalFunctionKey(source, name.string());
+ GlobalFunctionIndicesMap::iterator result = m_cachedGlobalFunctionIndices.find(key);
+ if (result != m_cachedGlobalFunctionIndices.end())
+ return m_cachedGlobalFunctions[result->value].second.get();
+
+ RefPtr<ProgramNode> program = parse<ProgramNode>(&globalData, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error);
+ if (!program) {
+ ASSERT(error.m_type != ParserError::ErrorNone);
+ return 0;
+ }
+
+ // This function assumes an input string that would result in a single anonymous function expression.
+ StatementNode* exprStatement = program->singleStatement();
+ ASSERT(exprStatement);
+ ASSERT(exprStatement->isExprStatement());
+ ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+ ASSERT(funcExpr);
+ ASSERT(funcExpr->isFuncExprNode());
+ FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+ ASSERT(body);
+ ASSERT(body->ident().isNull());
+
+ UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&globalData, source, body);
+ functionExecutable->m_nameValue.set(globalData, functionExecutable, jsString(&globalData, name.string()));
+
+ size_t index = m_randomGenerator.getUint32() % kMaxGlobalFunctionEntries;
+ if (m_cachedGlobalFunctions[index].second)
+ m_cachedGlobalFunctionIndices.remove(m_cachedGlobalFunctions[index].first);
+ m_cachedGlobalFunctionIndices.set(key, index);
+ m_cachedGlobalFunctions[index].second.set(globalData, functionExecutable);
+ m_cachedGlobalFunctions[index].first = key;
+
+ return functionExecutable;
+}
+
+}
diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h
new file mode 100644
index 000000000..4d4617189
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/CodeCache.h
@@ -0,0 +1,93 @@
+/*
+ * 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 CodeCache_h
+#define CodeCache_h
+
+#include "CodeSpecializationKind.h"
+#include "ParserModes.h"
+#include "Strong.h"
+#include "WeakRandom.h"
+
+#include <wtf/FixedArray.h>
+#include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class EvalExecutable;
+class Identifier;
+class ProgramExecutable;
+class UnlinkedCodeBlock;
+class UnlinkedEvalCodeBlock;
+class UnlinkedFunctionCodeBlock;
+class UnlinkedFunctionExecutable;
+class UnlinkedProgramCodeBlock;
+class JSGlobalData;
+struct ParserError;
+class SourceCode;
+class SourceProvider;
+
+class CodeCache {
+public:
+ static PassOwnPtr<CodeCache> create() { return adoptPtr(new CodeCache); }
+
+ UnlinkedProgramCodeBlock* getProgramCodeBlock(JSGlobalData&, ProgramExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+ UnlinkedEvalCodeBlock* getEvalCodeBlock(JSGlobalData&, EvalExecutable*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+ UnlinkedFunctionCodeBlock* getFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+ UnlinkedFunctionExecutable* getFunctionExecutableFromGlobalCode(JSGlobalData&, const Identifier&, const SourceCode&, ParserError&);
+ ~CodeCache();
+
+ enum CodeType { EvalType, ProgramType, FunctionType };
+ typedef std::pair<String, unsigned> CodeBlockKey;
+ typedef HashMap<CodeBlockKey, unsigned> CodeBlockIndicesMap;
+ typedef std::pair<String, String> GlobalFunctionKey;
+ typedef HashMap<GlobalFunctionKey, unsigned> GlobalFunctionIndicesMap;
+
+private:
+ CodeCache();
+
+ UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(JSGlobalData&, UnlinkedFunctionExecutable*, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
+
+ template <class UnlinkedCodeBlockType, class ExecutableType> inline UnlinkedCodeBlockType* getCodeBlock(JSGlobalData&, ExecutableType*, const SourceCode&, JSParserStrictness, DebuggerMode, ProfilerMode, ParserError&);
+ CodeBlockKey makeCodeBlockKey(const SourceCode&, CodeType, JSParserStrictness);
+ CodeBlockIndicesMap m_cachedCodeBlockIndices;
+ GlobalFunctionKey makeGlobalFunctionKey(const SourceCode&, const String&);
+ GlobalFunctionIndicesMap m_cachedGlobalFunctionIndices;
+
+ enum {
+ kMaxCodeBlockEntries = 1024,
+ kMaxGlobalFunctionEntries = 1024
+ };
+
+ FixedArray<std::pair<CodeBlockKey, Strong<UnlinkedCodeBlock> >, kMaxCodeBlockEntries> m_cachedCodeBlocks;
+ FixedArray<std::pair<GlobalFunctionKey, Strong<UnlinkedFunctionExecutable> >, kMaxGlobalFunctionEntries> m_cachedGlobalFunctions;
+ WeakRandom m_randomGenerator;
+};
+
+}
+
+#endif
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index f78e8bf55..9a162e9e7 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -131,7 +131,7 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg
|| (numArgs >= 5 && !isfinite(doubleArguments[4]))
|| (numArgs >= 6 && !isfinite(doubleArguments[5]))
|| (numArgs >= 7 && !isfinite(doubleArguments[6])))
- value = std::numeric_limits<double>::quiet_NaN();
+ value = QNaN;
else {
GregorianDateTime t;
int year = JSC::toInt32(doubleArguments[0]);
diff --git a/Source/JavaScriptCore/runtime/DateInstanceCache.h b/Source/JavaScriptCore/runtime/DateInstanceCache.h
index 153582f67..e186516e8 100644
--- a/Source/JavaScriptCore/runtime/DateInstanceCache.h
+++ b/Source/JavaScriptCore/runtime/DateInstanceCache.h
@@ -45,8 +45,8 @@ namespace JSC {
private:
DateInstanceData()
- : m_gregorianDateTimeCachedForMS(std::numeric_limits<double>::quiet_NaN())
- , m_gregorianDateTimeUTCCachedForMS(std::numeric_limits<double>::quiet_NaN())
+ : m_gregorianDateTimeCachedForMS(QNaN)
+ , m_gregorianDateTimeUTCCachedForMS(QNaN)
{
}
};
@@ -61,7 +61,7 @@ namespace JSC {
void reset()
{
for (size_t i = 0; i < cacheSize; ++i)
- m_cache[i].key = std::numeric_limits<double>::quiet_NaN();
+ m_cache[i].key = QNaN;
}
DateInstanceData* add(double d)
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index a3281b6d6..a4368a2bb 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -48,7 +48,7 @@ JSValue InterruptedExecutionError::defaultValue(const JSObject*, ExecState* exec
{
if (hint == PreferString)
return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution exceeded timeout.")));
- return JSValue(std::numeric_limits<double>::quiet_NaN());
+ return JSValue(QNaN);
}
JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
@@ -75,7 +75,7 @@ JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec,
{
if (hint == PreferString)
return jsNontrivialString(exec, String(ASCIILiteral("JavaScript execution terminated.")));
- return JSValue(std::numeric_limits<double>::quiet_NaN());
+ return JSValue(QNaN);
}
JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 0a453eea0..20a2e2acb 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "Executable.h"
+#include "BatchedTransitionOptimizer.h"
#include "BytecodeGenerator.h"
#include "CodeBlock.h"
#include "DFGDriver.h"
@@ -133,16 +134,14 @@ void ProgramExecutable::destroy(JSCell* cell)
const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
-FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, FunctionBodyNode* node)
- : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, node->source(), node->isStrictMode())
- , m_forceUsesArguments(node->usesArguments())
- , m_parameters(node->parameters())
- , m_name(node->ident())
- , m_inferredName(node->inferredName().isNull() ? globalData.propertyNames->emptyIdentifier : node->inferredName())
- , m_functionNameIsInScopeToggle(node->functionNameIsInScopeToggle())
+FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
+ : ScriptExecutable(globalData.functionExecutableStructure.get(), globalData, source, unlinkedExecutable->isInStrictContext())
+ , m_unlinkedExecutable(globalData, this, unlinkedExecutable)
{
- m_firstLine = node->lineNo();
- m_lastLine = node->lastLine();
+ ASSERT(!source.isNull());
+ ASSERT(source.length());
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
}
void FunctionExecutable::destroy(JSCell* cell)
@@ -191,7 +190,6 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
UNUSED_PARAM(jitType);
UNUSED_PARAM(bytecodeIndex);
#endif
- JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
@@ -200,28 +198,21 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCo
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release()));
m_evalCodeBlock = newCodeBlock.release();
} else {
+ UNUSED_PARAM(scope);
+ UNUSED_PARAM(globalData);
+ UNUSED_PARAM(lexicalGlobalObject);
if (!lexicalGlobalObject->evalEnabled())
return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage()));
- RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
- if (!evalNode) {
- ASSERT(exception);
+
+ JSObject* exception = 0;
+ UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(exec, this, &exception);
+ if (!unlinkedEvalCode)
return exception;
- }
- recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
-
- JSGlobalObject* globalObject = scope->globalObject();
-
+
OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release();
ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
- m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scope, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
- if ((exception = generator->generate())) {
- m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative());
- evalNode->destroyData();
- return exception;
- }
-
- evalNode->destroyData();
+ m_unlinkedEvalCodeBlock.set(*globalData, this, unlinkedEvalCode);
+ m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release()));
m_evalCodeBlock->copyPostParseDataFromAlternative();
}
@@ -257,6 +248,7 @@ void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
ScriptExecutable::visitChildren(thisObject, visitor);
if (thisObject->m_evalCodeBlock)
thisObject->m_evalCodeBlock->visitAggregate(visitor);
+ visitor.append(&thisObject->m_unlinkedEvalCodeBlock);
}
void EvalExecutable::unlinkCalls()
@@ -272,19 +264,20 @@ void EvalExecutable::unlinkCalls()
void EvalExecutable::clearCode()
{
m_evalCodeBlock.clear();
+ m_unlinkedEvalCodeBlock.clear();
Base::clearCode();
}
JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
{
- JSObject* exception = 0;
+ ParserError error;
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
+ RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, m_source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, error);
if (programNode)
return 0;
- ASSERT(exception);
- return exception;
+ ASSERT(error.m_type != ParserError::ErrorNone);
+ return error.toErrorObject(lexicalGlobalObject, m_source);
}
JSObject* ProgramExecutable::compileOptimized(ExecState* exec, JSScope* scope, unsigned bytecodeIndex)
@@ -310,38 +303,17 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, JSScope* scope, JI
SamplingRegion samplingRegion(samplingDescription(jitType));
#if !ENABLE(JIT)
+ UNUSED_PARAM(exec);
UNUSED_PARAM(jitType);
UNUSED_PARAM(bytecodeIndex);
#endif
- JSObject* exception = 0;
- JSGlobalData* globalData = &exec->globalData();
- JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
-
if (!!m_programCodeBlock) {
OwnPtr<ProgramCodeBlock> newCodeBlock = adoptPtr(new ProgramCodeBlock(CodeBlock::CopyParsedBlock, *m_programCodeBlock));
newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_programCodeBlock.release()));
m_programCodeBlock = newCodeBlock.release();
} else {
- RefPtr<ProgramNode> programNode = parse<ProgramNode>(globalData, lexicalGlobalObject, m_source, 0, Identifier(), isStrictMode() ? JSParseStrict : JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception);
- if (!programNode) {
- ASSERT(exception);
- return exception;
- }
- recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
-
JSGlobalObject* globalObject = scope->globalObject();
-
- OwnPtr<CodeBlock> previousCodeBlock = m_programCodeBlock.release();
- ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock);
- m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider(), previousCodeBlock.release()));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scope, globalObject->symbolTable(), m_programCodeBlock.get(), !!m_programCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation)));
- if ((exception = generator->generate())) {
- m_programCodeBlock = static_pointer_cast<ProgramCodeBlock>(m_programCodeBlock->releaseAlternative());
- programNode->destroyData();
- return exception;
- }
-
- programNode->destroyData();
+ m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, m_unlinkedProgramCodeBlock.get(), globalObject, source().provider(), m_programCodeBlock.release()));
m_programCodeBlock->copyPostParseDataFromAlternative();
}
@@ -378,6 +350,67 @@ void ProgramExecutable::unlinkCalls()
#endif
}
+int ProgramExecutable::addGlobalVar(JSGlobalObject* globalObject, const Identifier& ident, ConstantMode constantMode, FunctionMode functionMode)
+{
+ // Try to share the symbolTable if possible
+ SharedSymbolTable* symbolTable = globalObject->symbolTable();
+ UNUSED_PARAM(functionMode);
+ int index = symbolTable->size();
+ SymbolTableEntry newEntry(index, (constantMode == IsConstant) ? ReadOnly : 0);
+ if (functionMode == IsFunctionToSpecialize)
+ newEntry.attemptToWatch();
+ SymbolTable::AddResult result = symbolTable->add(ident.impl(), newEntry);
+ if (!result.isNewEntry) {
+ result.iterator->value.notifyWrite();
+ index = result.iterator->value.getIndex();
+ }
+ return index;
+}
+
+JSObject* ProgramExecutable::initalizeGlobalProperties(JSGlobalData& globalData, CallFrame* callFrame, JSScope* scope)
+{
+ ASSERT(scope);
+ JSGlobalObject* globalObject = scope->globalObject();
+ ASSERT(globalObject);
+ ASSERT(&globalObject->globalData() == &globalData);
+
+ JSObject* exception = 0;
+ UnlinkedProgramCodeBlock* unlinkedCode = globalObject->createProgramCodeBlock(callFrame, this, &exception);
+ if (exception)
+ return exception;
+
+ m_unlinkedProgramCodeBlock.set(globalData, this, unlinkedCode);
+
+ BatchedTransitionOptimizer optimizer(globalData, globalObject);
+
+ const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCode->variableDeclarations();
+ const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCode->functionDeclarations();
+
+ size_t newGlobals = variableDeclarations.size() + functionDeclarations.size();
+ if (!newGlobals)
+ return 0;
+ globalObject->addRegisters(newGlobals);
+ CallFrame* globalExec = globalObject->globalExec();
+
+ for (size_t i = 0; i < functionDeclarations.size(); ++i) {
+ bool propertyDidExist = globalObject->removeDirect(globalData, functionDeclarations[i].first); // Newly declared functions overwrite existing properties.
+ UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
+ JSValue value = JSFunction::create(globalExec, unlinkedFunctionExecutable->link(globalData, m_source, lineNo(), 0), scope);
+ int index = addGlobalVar(globalObject, functionDeclarations[i].first, IsVariable,
+ !propertyDidExist ? IsFunctionToSpecialize : NotFunctionOrNotSpecializable);
+ globalObject->registerAt(index).set(globalData, globalObject, value);
+ }
+
+ for (size_t i = 0; i < variableDeclarations.size(); ++i) {
+ if (globalObject->hasProperty(globalExec, variableDeclarations[i].first))
+ continue;
+ addGlobalVar(globalObject, variableDeclarations[i].first,
+ (variableDeclarations[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
+ NotFunctionOrNotSpecializable);
+ }
+ return 0;
+}
+
void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);
@@ -385,6 +418,7 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
ScriptExecutable::visitChildren(thisObject, visitor);
+ visitor.append(&thisObject->m_unlinkedProgramCodeBlock);
if (thisObject->m_programCodeBlock)
thisObject->m_programCodeBlock->visitAggregate(visitor);
}
@@ -392,6 +426,7 @@ void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
void ProgramExecutable::clearCode()
{
m_programCodeBlock.clear();
+ m_unlinkedProgramCodeBlock.clear();
Base::clearCode();
}
@@ -438,12 +473,12 @@ JSObject* FunctionExecutable::compileOptimizedForConstruct(ExecState* exec, JSSc
#if ENABLE(JIT)
bool FunctionExecutable::jitCompileForCall(ExecState* exec)
{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
bool FunctionExecutable::jitCompileForConstruct(ExecState* exec)
{
- return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, JITCode::bottomTierJIT(), UINT_MAX, JITCompilationCanFail);
}
#endif
@@ -452,49 +487,30 @@ FunctionCodeBlock* FunctionExecutable::codeBlockWithBytecodeFor(CodeSpecializati
return baselineCodeBlockFor(kind);
}
-PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CompilationKind compilationKind, CodeSpecializationKind specializationKind, JSObject*& exception)
+PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(JSScope* scope, CodeSpecializationKind specializationKind, JSObject*& exception)
{
if (!!codeBlockFor(specializationKind))
return adoptPtr(new FunctionCodeBlock(CodeBlock::CopyParsedBlock, *codeBlockFor(specializationKind)));
-
- exception = 0;
+
JSGlobalData* globalData = scope->globalData();
JSGlobalObject* globalObject = scope->globalObject();
- RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(
- globalData,
- globalObject,
- m_source,
- m_parameters.get(),
- name(),
- isStrictMode() ? JSParseStrict : JSParseNormal,
- FunctionBodyNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode,
- 0,
- 0,
- &exception
- );
-
- if (!body) {
- ASSERT(exception);
+ ParserError error;
+ DebuggerMode debuggerMode = globalObject->hasDebugger() ? DebuggerOn : DebuggerOff;
+ ProfilerMode profilerMode = globalObject->hasProfiler() ? ProfilerOn : ProfilerOff;
+ UnlinkedFunctionCodeBlock* unlinkedCodeBlock = m_unlinkedExecutable->codeBlockFor(*globalData, m_source, specializationKind, debuggerMode, profilerMode, error);
+ recordParse(m_unlinkedExecutable->features(), m_unlinkedExecutable->hasCapturedVariables(), lineNo(), lastLine());
+
+ if (!unlinkedCodeBlock) {
+ exception = error.toErrorObject(globalObject, m_source);
return nullptr;
}
- if (m_forceUsesArguments)
- body->setUsesArguments();
- body->finishParsing(m_parameters, m_name, m_functionNameIsInScopeToggle);
- recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
-
- OwnPtr<FunctionCodeBlock> result;
- ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
- result = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), specializationKind == CodeForConstruct));
- OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scope, result->symbolTable(), result.get(), compilationKind)));
- exception = generator->generate();
- body->destroyData();
- if (exception)
- return nullptr;
+ OwnPtr<FunctionCodeBlock> result = adoptPtr(new FunctionCodeBlock(this, unlinkedCodeBlock, globalObject, source().provider(), source().startOffset()));
result->copyPostParseDataFrom(codeBlockFor(specializationKind).get());
return result.release();
}
+
JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex)
{
SamplingRegion samplingRegion(samplingDescription(jitType));
@@ -507,7 +523,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s
#endif
ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForCall);
JSObject* exception;
- OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, !!m_codeBlockForCall ? OptimizingCompilation : FirstCompilation, CodeForCall, exception);
+ OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForCall, exception);
if (!newCodeBlock)
return exception;
@@ -516,10 +532,9 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, JSScope* s
m_numParametersForCall = m_codeBlockForCall->numParameters();
ASSERT(m_numParametersForCall);
- m_symbolTable.set(exec->globalData(), this, m_codeBlockForCall->symbolTable());
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForCall))
+ if (!prepareFunctionForExecution(exec, m_codeBlockForCall, m_jitCodeForCall, m_jitCodeForCallWithArityCheck, jitType, bytecodeIndex, CodeForCall))
return 0;
#endif
@@ -544,7 +559,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
ASSERT((jitType == JITCode::bottomTierJIT()) == !m_codeBlockForConstruct);
JSObject* exception;
- OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, !!m_codeBlockForConstruct ? OptimizingCompilation : FirstCompilation, CodeForConstruct, exception);
+ OwnPtr<FunctionCodeBlock> newCodeBlock = produceCodeBlockFor(scope, CodeForConstruct, exception);
if (!newCodeBlock)
return exception;
@@ -553,10 +568,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, JSSco
m_numParametersForConstruct = m_codeBlockForConstruct->numParameters();
ASSERT(m_numParametersForConstruct);
- m_symbolTable.set(exec->globalData(), this, m_codeBlockForConstruct->symbolTable());
#if ENABLE(JIT)
- if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, m_symbolTable, jitType, bytecodeIndex, CodeForConstruct))
+ if (!prepareFunctionForExecution(exec, m_codeBlockForConstruct, m_jitCodeForConstruct, m_jitCodeForConstructWithArityCheck, jitType, bytecodeIndex, CodeForConstruct))
return 0;
#endif
@@ -592,12 +606,11 @@ void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
ScriptExecutable::visitChildren(thisObject, visitor);
- visitor.append(&thisObject->m_nameValue);
- visitor.append(&thisObject->m_symbolTable);
if (thisObject->m_codeBlockForCall)
thisObject->m_codeBlockForCall->visitAggregate(visitor);
if (thisObject->m_codeBlockForConstruct)
thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
+ visitor.append(&thisObject->m_unlinkedExecutable);
}
void FunctionExecutable::clearCodeIfNotCompiling()
@@ -607,10 +620,18 @@ void FunctionExecutable::clearCodeIfNotCompiling()
clearCode();
}
+void FunctionExecutable::clearUnlinkedCodeIfNotCompiling()
+{
+ if (isCompiling())
+ return;
+ m_unlinkedExecutable->clearCode();
+}
+
void FunctionExecutable::clearCode()
{
m_codeBlockForCall.clear();
m_codeBlockForConstruct.clear();
+ m_unlinkedExecutable->clearCode();
Base::clearCode();
}
@@ -630,39 +651,19 @@ void FunctionExecutable::unlinkCalls()
FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& name, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
{
- JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
- RefPtr<ProgramNode> program = parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, source, 0, Identifier(), JSParseNormal, ProgramNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, debugger, exec, exception);
- if (!program) {
- ASSERT(*exception);
+ UnlinkedFunctionExecutable* unlinkedFunction = UnlinkedFunctionExecutable::fromGlobalCode(name, exec, debugger, source, exception);
+ if (!unlinkedFunction)
return 0;
- }
-
- // This function assumes an input string that would result in a single anonymous function expression.
- StatementNode* exprStatement = program->singleStatement();
- ASSERT(exprStatement);
- ASSERT(exprStatement->isExprStatement());
- ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
- ASSERT(funcExpr);
- ASSERT(funcExpr->isFuncExprNode());
- FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
- ASSERT(body);
- ASSERT(body->ident().isNull());
-
- FunctionExecutable* functionExecutable = FunctionExecutable::create(exec->globalData(), body);
- functionExecutable->m_nameValue.set(exec->globalData(), functionExecutable, jsString(&exec->globalData(), name.string()));
- return functionExecutable;
+ unsigned firstLine = source.firstLine() + unlinkedFunction->firstLineOffset();
+ unsigned startOffset = source.startOffset() + unlinkedFunction->startOffset();
+ unsigned sourceLength = unlinkedFunction->sourceLength();
+ SourceCode functionSource(source.provider(), startOffset, startOffset + sourceLength, firstLine);
+ return FunctionExecutable::create(exec->globalData(), functionSource, unlinkedFunction, firstLine, unlinkedFunction->lineCount());
}
String FunctionExecutable::paramString() const
{
- FunctionParameters& parameters = *m_parameters;
- StringBuilder builder;
- for (size_t pos = 0; pos < parameters.size(); ++pos) {
- if (!builder.isEmpty())
- builder.appendLiteral(", ");
- builder.append(parameters[pos].string());
- }
- return builder.toString();
+ return m_unlinkedExecutable->paramString();
}
}
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 76a537da3..74b4add75 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -35,6 +35,7 @@
#include "LLIntCLoop.h"
#include "Nodes.h"
#include "SamplingTool.h"
+#include "UnlinkedCodeBlock.h"
#include <wtf/PassOwnPtr.h>
namespace JSC {
@@ -364,9 +365,19 @@ namespace JSC {
bool isStrictMode() const { return m_features & StrictModeFeature; }
void unlinkCalls();
+
+ CodeFeatures features() const { return m_features; }
static const ClassInfo s_info;
+ void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
+ {
+ m_features = features;
+ m_hasCapturedVariables = hasCapturedVariables;
+ m_firstLine = firstLine;
+ m_lastLine = lastLine;
+ }
+
protected:
void finishCreation(JSGlobalData& globalData)
{
@@ -379,14 +390,6 @@ namespace JSC {
#endif
}
- void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
- {
- m_features = features;
- m_hasCapturedVariables = hasCapturedVariables;
- m_firstLine = firstLine;
- m_lastLine = lastLine;
- }
-
SourceCode m_source;
CodeFeatures m_features;
bool m_hasCapturedVariables;
@@ -448,6 +451,8 @@ namespace JSC {
void clearCode();
+ ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
EvalExecutable(ExecState*, const SourceCode&, bool);
@@ -456,6 +461,7 @@ namespace JSC {
static void visitChildren(JSCell*, SlotVisitor&);
OwnPtr<EvalCodeBlock> m_evalCodeBlock;
+ WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock;
};
class ProgramExecutable : public ScriptExecutable {
@@ -470,6 +476,9 @@ namespace JSC {
return executable;
}
+
+ JSObject* initalizeGlobalProperties(JSGlobalData&, CallFrame*, JSScope*);
+
static void destroy(JSCell*);
JSObject* compile(ExecState* exec, JSScope* scope)
@@ -515,13 +524,21 @@ namespace JSC {
void clearCode();
+ ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+
private:
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+
ProgramExecutable(ExecState*, const SourceCode&);
+ enum ConstantMode { IsConstant, IsVariable };
+ enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
+ int addGlobalVar(JSGlobalObject*, const Identifier&, ConstantMode, FunctionMode);
+
JSObject* compileInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
static void visitChildren(JSCell*, SlotVisitor&);
+ WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock;
OwnPtr<ProgramCodeBlock> m_programCodeBlock;
};
@@ -531,9 +548,9 @@ namespace JSC {
public:
typedef ScriptExecutable Base;
- static FunctionExecutable* create(JSGlobalData& globalData, FunctionBodyNode* node)
+ static FunctionExecutable* create(JSGlobalData& globalData, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine)
{
- FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, node);
+ FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, source, unlinkedExecutable, firstLine, lastLine);
executable->finishCreation(globalData);
return executable;
}
@@ -554,7 +571,7 @@ namespace JSC {
FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind);
- PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CompilationKind, CodeSpecializationKind, JSObject*& exception);
+ PassOwnPtr<FunctionCodeBlock> produceCodeBlockFor(JSScope*, CodeSpecializationKind, JSObject*& exception);
JSObject* compileForCall(ExecState* exec, JSScope* scope)
{
@@ -679,14 +696,15 @@ namespace JSC {
return baselineCodeBlockFor(kind);
}
- const Identifier& name() { return m_name; }
- const Identifier& inferredName() { return m_inferredName; }
- JSString* nameValue() const { return m_nameValue.get(); }
- size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'!
+ const Identifier& name() { return m_unlinkedExecutable->name(); }
+ const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
+ JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
+ size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'!
String paramString() const;
- SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
+ SharedSymbolTable* symbolTable(CodeSpecializationKind kind) const { return m_unlinkedExecutable->symbolTable(kind); }
void clearCodeIfNotCompiling();
+ void clearUnlinkedCodeIfNotCompiling();
static void visitChildren(JSCell*, SlotVisitor&);
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
{
@@ -699,15 +717,8 @@ namespace JSC {
void clearCode();
- protected:
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- m_nameValue.set(globalData, this, jsString(&globalData, name().string()));
- }
-
private:
- FunctionExecutable(JSGlobalData&, FunctionBodyNode*);
+ FunctionExecutable(JSGlobalData&, const SourceCode&, UnlinkedFunctionExecutable*, unsigned firstLine, unsigned lastLine);
JSObject* compileForCallInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
JSObject* compileForConstructInternal(ExecState*, JSScope*, JITCode::JITType, unsigned bytecodeIndex = UINT_MAX);
@@ -732,16 +743,9 @@ namespace JSC {
}
static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
- bool m_forceUsesArguments;
-
- RefPtr<FunctionParameters> m_parameters;
+ WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable;
OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
- Identifier m_name;
- Identifier m_inferredName;
- FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
- WriteBarrier<JSString> m_nameValue;
- WriteBarrier<SharedSymbolTable> m_symbolTable;
};
inline JSFunction::JSFunction(JSGlobalData& globalData, FunctionExecutable* executable, JSScope* scope)
diff --git a/Source/JavaScriptCore/runtime/ExecutionHarness.h b/Source/JavaScriptCore/runtime/ExecutionHarness.h
index 065788aee..b71b60217 100644
--- a/Source/JavaScriptCore/runtime/ExecutionHarness.h
+++ b/Source/JavaScriptCore/runtime/ExecutionHarness.h
@@ -49,7 +49,7 @@ inline bool prepareForExecution(ExecState* exec, OwnPtr<CodeBlockType>& codeBloc
return jitCompileIfAppropriate(exec, codeBlock, jitCode, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
-inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, WriteBarrier<SharedSymbolTable>& symbolTable, JITCode::JITType jitType, unsigned bytecodeIndex, CodeSpecializationKind kind)
+inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBlock>& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, JITCode::JITType jitType, unsigned bytecodeIndex, CodeSpecializationKind kind)
{
#if ENABLE(LLINT)
if (JITCode::isBaselineCode(jitType)) {
@@ -61,7 +61,7 @@ inline bool prepareFunctionForExecution(ExecState* exec, OwnPtr<FunctionCodeBloc
#else
UNUSED_PARAM(kind);
#endif // ENABLE(LLINT)
- return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, symbolTable, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
+ return jitCompileFunctionIfAppropriate(exec, codeBlock, jitCode, jitCodeWithArityCheck, jitType, bytecodeIndex, JITCode::isBaselineCode(jitType) ? JITCompilationMustSucceed : JITCompilationCanFail);
}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index 45dd0bbde..583c12bb1 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -128,7 +128,7 @@ PassRefPtr<StringImpl> Identifier::add8(JSGlobalData* globalData, const UChar* s
if (!length)
return StringImpl::empty();
- CharBuffer<UChar> buf = {s, length};
+ CharBuffer<UChar> buf = { s, static_cast<unsigned>(length) };
HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf);
// If the string is newly-translated, then we need to adopt it.
diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h
index bdcfbd187..dcb739ec3 100644
--- a/Source/JavaScriptCore/runtime/Identifier.h
+++ b/Source/JavaScriptCore/runtime/Identifier.h
@@ -180,7 +180,7 @@ namespace JSC {
if (!length)
return StringImpl::empty();
- CharBuffer<T> buf = {s, length};
+ CharBuffer<T> buf = { s, static_cast<unsigned>(length) };
HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(buf);
// If the string is newly-translated, then we need to adopt it.
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index fa2291813..fc6336463 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -46,15 +46,16 @@ namespace JSC {
public:
typedef JSVariableObject Base;
- static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, FunctionExecutable* functionExecutable)
+ static JSActivation* create(JSGlobalData& globalData, CallFrame* callFrame, CodeBlock* codeBlock)
{
+ SharedSymbolTable* symbolTable = codeBlock->symbolTable();
JSActivation* activation = new (
NotNull,
allocateCell<JSActivation>(
globalData.heap,
- allocationSize(functionExecutable->symbolTable())
+ allocationSize(symbolTable)
)
- ) JSActivation(globalData, callFrame, functionExecutable->symbolTable());
+ ) JSActivation(globalData, callFrame, symbolTable);
activation->finishCreation(globalData);
return activation;
}
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index 7028c3b95..d1ece1a36 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -1092,7 +1092,7 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call
for (; numDefined < usedVectorLength; ++numDefined) {
if (numDefined > m_butterfly->vectorLength())
break;
- JSValue v = indexingData<indexingType>()[numDefined].get();
+ JSValue v = currentIndexingData()[numDefined].get();
if (!v || v.isUndefined())
break;
tree.abstractor().m_nodes[numDefined].value = v;
@@ -1101,7 +1101,7 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call
for (unsigned i = numDefined; i < usedVectorLength; ++i) {
if (i > m_butterfly->vectorLength())
break;
- JSValue v = indexingData<indexingType>()[i].get();
+ JSValue v = currentIndexingData()[i].get();
if (v) {
if (v.isUndefined())
++numUndefined;
@@ -1116,7 +1116,7 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call
unsigned newUsedVectorLength = numDefined + numUndefined;
// The array size may have changed. Figure out the new bounds.
- unsigned newestUsedVectorLength = relevantLength<indexingType>();
+ unsigned newestUsedVectorLength = currentRelevantLength();
unsigned elementsToExtractThreshold = min(min(newestUsedVectorLength, numDefined), static_cast<unsigned>(tree.abstractor().m_nodes.size()));
unsigned undefinedElementsThreshold = min(newestUsedVectorLength, newUsedVectorLength);
@@ -1127,18 +1127,18 @@ void JSArray::sortVector(ExecState* exec, JSValue compareFunction, CallType call
iter.start_iter_least(tree);
JSGlobalData& globalData = exec->globalData();
for (unsigned i = 0; i < elementsToExtractThreshold; ++i) {
- indexingData<indexingType>()[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
+ currentIndexingData()[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
++iter;
}
// Put undefined values back in.
for (unsigned i = elementsToExtractThreshold; i < undefinedElementsThreshold; ++i)
- indexingData<indexingType>()[i].setUndefined();
+ currentIndexingData()[i].setUndefined();
// Ensure that unused values in the vector are zeroed out.
for (unsigned i = undefinedElementsThreshold; i < clearElementsThreshold; ++i)
- indexingData<indexingType>()[i].clear();
+ currentIndexingData()[i].clear();
- if (hasArrayStorage(indexingType))
+ if (hasArrayStorage(structure()->indexingType()))
arrayStorage()->m_numValuesInVector = newUsedVectorLength;
}
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index d4622aacc..1d1e64173 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -27,273 +27,273 @@
namespace JSC {
- class JSArray;
- class LLIntOffsetsExtractor;
+class JSArray;
+class LLIntOffsetsExtractor;
- class JSArray : public JSNonFinalObject {
- friend class LLIntOffsetsExtractor;
- friend class Walker;
- friend class JIT;
+class JSArray : public JSNonFinalObject {
+ friend class LLIntOffsetsExtractor;
+ friend class Walker;
+ friend class JIT;
- public:
- typedef JSNonFinalObject Base;
+public:
+ typedef JSNonFinalObject Base;
- protected:
- explicit JSArray(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly)
- : JSNonFinalObject(globalData, structure, butterfly)
- {
- }
+protected:
+ explicit JSArray(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly)
+ : JSNonFinalObject(globalData, structure, butterfly)
+ {
+ }
- public:
- static JSArray* create(JSGlobalData&, Structure*, unsigned initialLength = 0);
+public:
+ 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.
- static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
+ // 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.
+ static JSArray* tryCreateUninitialized(JSGlobalData&, Structure*, unsigned initialLength);
- JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+ static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
+ static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
- static JS_EXPORTDATA const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
- unsigned length() const { return getArrayLength(); }
- // OK to use on new arrays, but not if it might be a RegExpMatchArray.
- bool setLength(ExecState*, unsigned, bool throwException = false);
+ unsigned length() const { return getArrayLength(); }
+ // OK to use on new arrays, but not if it might be a RegExpMatchArray.
+ bool setLength(ExecState*, unsigned, bool throwException = false);
- void sort(ExecState*);
- void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
- void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
+ void sort(ExecState*);
+ void sort(ExecState*, JSValue compareFunction, CallType, const CallData&);
+ void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&);
- void push(ExecState*, JSValue);
- JSValue pop(ExecState*);
+ void push(ExecState*, JSValue);
+ JSValue pop(ExecState*);
- enum ShiftCountMode {
- // This form of shift hints that we're doing queueing. With this assumption in hand,
- // we convert to ArrayStorage, which has queue optimizations.
- ShiftCountForShift,
+ enum ShiftCountMode {
+ // This form of shift hints that we're doing queueing. With this assumption in hand,
+ // we convert to ArrayStorage, which has queue optimizations.
+ ShiftCountForShift,
- // This form of shift hints that we're just doing care and feeding on an array that
- // is probably typically used for ordinary accesses. With this assumption in hand,
- // we try to preserve whatever indexing type it has already.
- ShiftCountForSplice
- };
-
- bool shiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
- {
- return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData()));
- }
- bool shiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
- {
- return shiftCountWithAnyIndexingType(exec, startIndex, count);
- }
- template<ShiftCountMode shiftCountMode>
- bool shiftCount(ExecState* exec, unsigned startIndex, unsigned count)
- {
- switch (shiftCountMode) {
- case ShiftCountForShift:
- return shiftCountForShift(exec, startIndex, count);
- case ShiftCountForSplice:
- return shiftCountForSplice(exec, startIndex, count);
- default:
- CRASH();
- return false;
- }
- }
-
- bool unshiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
- {
- return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData()));
- }
- bool unshiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
- {
- return unshiftCountWithAnyIndexingType(exec, startIndex, count);
- }
- template<ShiftCountMode shiftCountMode>
- bool unshiftCount(ExecState* exec, unsigned startIndex, unsigned count)
- {
- switch (shiftCountMode) {
- case ShiftCountForShift:
- return unshiftCountForShift(exec, startIndex, count);
- case ShiftCountForSplice:
- return unshiftCountForSplice(exec, startIndex, count);
- default:
- CRASH();
- return false;
- }
- }
-
- void fillArgList(ExecState*, MarkedArgumentBuffer&);
- void copyToArguments(ExecState*, CallFrame*, uint32_t length);
-
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, indexingType);
- }
-
- protected:
- static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
- static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
-
- static bool deleteProperty(JSCell*, ExecState*, PropertyName);
- JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-
- private:
- bool isLengthWritable()
- {
- ArrayStorage* storage = arrayStorageOrNull();
- if (!storage)
- return true;
- SparseArrayValueMap* map = storage->m_sparseMap.get();
- return !map || !map->lengthIsReadOnly();
- }
-
- bool shiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
- bool shiftCountWithArrayStorage(unsigned startIndex, unsigned count, ArrayStorage*);
-
- bool unshiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
- bool unshiftCountWithArrayStorage(ExecState*, unsigned startIndex, unsigned count, ArrayStorage*);
- bool unshiftCountSlowCase(JSGlobalData&, bool, unsigned);
-
- template<IndexingType indexingType>
- void sortNumericVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
-
- template<IndexingType indexingType>
- void sortCompactedVector(ExecState*, WriteBarrier<Unknown>* begin, unsigned relevantLength);
-
- template<IndexingType indexingType>
- void sortVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
-
- bool setLengthWithArrayStorage(ExecState*, unsigned newLength, bool throwException, ArrayStorage*);
- void setLengthWritable(ExecState*, bool writable);
-
- template<IndexingType indexingType>
- void compactForSorting(unsigned& numDefined, unsigned& newRelevantLength);
+ // This form of shift hints that we're just doing care and feeding on an array that
+ // is probably typically used for ordinary accesses. With this assumption in hand,
+ // we try to preserve whatever indexing type it has already.
+ ShiftCountForSplice
};
- inline Butterfly* createContiguousArrayButterfly(JSGlobalData& globalData, unsigned length)
+ bool shiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
{
- IndexingHeader header;
- header.setVectorLength(std::max(length, BASE_VECTOR_LEN));
- header.setPublicLength(length);
- Butterfly* result = Butterfly::create(
- globalData, 0, 0, true, header, header.vectorLength() * sizeof(EncodedJSValue));
- return result;
+ return shiftCountWithArrayStorage(startIndex, count, ensureArrayStorage(exec->globalData()));
}
-
- inline Butterfly* createArrayButterfly(JSGlobalData& globalData, unsigned initialLength)
+ bool shiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
{
- Butterfly* butterfly = Butterfly::create(
- globalData, 0, 0, true, baseIndexingHeaderForArray(initialLength), ArrayStorage::sizeFor(BASE_VECTOR_LEN));
- ArrayStorage* storage = butterfly->arrayStorage();
- storage->m_indexBias = 0;
- storage->m_sparseMap.clear();
- storage->m_numValuesInVector = 0;
- return butterfly;
+ return shiftCountWithAnyIndexingType(exec, startIndex, count);
}
-
- Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData&, unsigned initialLength);
-
- inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+ template<ShiftCountMode shiftCountMode>
+ bool shiftCount(ExecState* exec, unsigned startIndex, unsigned count)
{
- Butterfly* butterfly;
- if (LIKELY(structure->indexingType() == ArrayWithContiguous)) {
- butterfly = createContiguousArrayButterfly(globalData, initialLength);
- ASSERT(initialLength < MIN_SPARSE_ARRAY_INDEX);
- } else {
- ASSERT(
- structure->indexingType() == ArrayWithSlowPutArrayStorage
- || (initialLength && structure->indexingType() == ArrayWithArrayStorage));
- butterfly = createArrayButterfly(globalData, initialLength);
+ switch (shiftCountMode) {
+ case ShiftCountForShift:
+ return shiftCountForShift(exec, startIndex, count);
+ case ShiftCountForSplice:
+ return shiftCountForSplice(exec, startIndex, count);
+ default:
+ CRASH();
+ return false;
}
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
- array->finishCreation(globalData);
- return array;
}
-
- inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
- {
- unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
- if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
- return 0;
- Butterfly* butterfly;
- if (LIKELY(structure->indexingType() == ArrayWithContiguous)) {
-
- void* temp;
- if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, vectorLength * sizeof(EncodedJSValue)), &temp))
- return 0;
- butterfly = Butterfly::fromBase(temp, 0, 0);
- butterfly->setVectorLength(vectorLength);
- butterfly->setPublicLength(initialLength);
- } else {
- void* temp;
- if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(vectorLength)), &temp))
- return 0;
- butterfly = Butterfly::fromBase(temp, 0, 0);
- *butterfly->indexingHeader() = indexingHeaderForArray(initialLength, vectorLength);
- ArrayStorage* storage = butterfly->arrayStorage();
- storage->m_indexBias = 0;
- storage->m_sparseMap.clear();
- storage->m_numValuesInVector = initialLength;
+ bool unshiftCountForShift(ExecState* exec, unsigned startIndex, unsigned count)
+ {
+ return unshiftCountWithArrayStorage(exec, startIndex, count, ensureArrayStorage(exec->globalData()));
+ }
+ bool unshiftCountForSplice(ExecState* exec, unsigned startIndex, unsigned count)
+ {
+ return unshiftCountWithAnyIndexingType(exec, startIndex, count);
+ }
+ template<ShiftCountMode shiftCountMode>
+ bool unshiftCount(ExecState* exec, unsigned startIndex, unsigned count)
+ {
+ switch (shiftCountMode) {
+ case ShiftCountForShift:
+ return unshiftCountForShift(exec, startIndex, count);
+ case ShiftCountForSplice:
+ return unshiftCountForSplice(exec, startIndex, count);
+ default:
+ CRASH();
+ return false;
}
-
- JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
- array->finishCreation(globalData);
- return array;
}
- JSArray* asArray(JSValue);
+ void fillArgList(ExecState*, MarkedArgumentBuffer&);
+ void copyToArguments(ExecState*, CallFrame*, uint32_t length);
- inline JSArray* asArray(JSCell* cell)
+ static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
{
- ASSERT(cell->inherits(&JSArray::s_info));
- return jsCast<JSArray*>(cell);
+ return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, indexingType);
}
+
+protected:
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
+ static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
- inline JSArray* asArray(JSValue value)
+ static bool deleteProperty(JSCell*, ExecState*, PropertyName);
+ JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+
+private:
+ bool isLengthWritable()
{
- return asArray(value.asCell());
+ ArrayStorage* storage = arrayStorageOrNull();
+ if (!storage)
+ return true;
+ SparseArrayValueMap* map = storage->m_sparseMap.get();
+ return !map || !map->lengthIsReadOnly();
}
+
+ bool shiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
+ bool shiftCountWithArrayStorage(unsigned startIndex, unsigned count, ArrayStorage*);
- inline bool isJSArray(JSCell* cell) { return cell->classInfo() == &JSArray::s_info; }
- inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); }
+ bool unshiftCountWithAnyIndexingType(ExecState*, unsigned startIndex, unsigned count);
+ bool unshiftCountWithArrayStorage(ExecState*, unsigned startIndex, unsigned count, ArrayStorage*);
+ bool unshiftCountSlowCase(JSGlobalData&, bool, unsigned);
- inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const ArgList& values)
- {
- JSGlobalData& globalData = exec->globalData();
- unsigned length = values.size();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
-
- // FIXME: we should probably throw an out of memory error here, but
- // when making this change we should check that all clients of this
- // function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
+ template<IndexingType indexingType>
+ void sortNumericVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
+
+ template<IndexingType indexingType>
+ void sortCompactedVector(ExecState*, WriteBarrier<Unknown>* begin, unsigned relevantLength);
+
+ template<IndexingType indexingType>
+ void sortVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
- for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values.at(i));
- return array;
+ bool setLengthWithArrayStorage(ExecState*, unsigned newLength, bool throwException, ArrayStorage*);
+ void setLengthWritable(ExecState*, bool writable);
+
+ template<IndexingType indexingType>
+ void compactForSorting(unsigned& numDefined, unsigned& newRelevantLength);
+};
+
+inline Butterfly* createContiguousArrayButterfly(JSGlobalData& globalData, unsigned length)
+{
+ IndexingHeader header;
+ header.setVectorLength(std::max(length, BASE_VECTOR_LEN));
+ header.setPublicLength(length);
+ Butterfly* result = Butterfly::create(
+ globalData, 0, 0, true, header, header.vectorLength() * sizeof(EncodedJSValue));
+ return result;
+}
+
+inline Butterfly* createArrayButterfly(JSGlobalData& globalData, unsigned initialLength)
+{
+ Butterfly* butterfly = Butterfly::create(
+ globalData, 0, 0, true, baseIndexingHeaderForArray(initialLength), ArrayStorage::sizeFor(BASE_VECTOR_LEN));
+ ArrayStorage* storage = butterfly->arrayStorage();
+ storage->m_indexBias = 0;
+ storage->m_sparseMap.clear();
+ storage->m_numValuesInVector = 0;
+ return butterfly;
+}
+
+Butterfly* createArrayButterflyInDictionaryIndexingMode(JSGlobalData&, unsigned initialLength);
+
+inline JSArray* JSArray::create(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+{
+ Butterfly* butterfly;
+ if (LIKELY(structure->indexingType() == ArrayWithContiguous)) {
+ butterfly = createContiguousArrayButterfly(globalData, initialLength);
+ ASSERT(initialLength < MIN_SPARSE_ARRAY_INDEX);
+ } else {
+ ASSERT(
+ structure->indexingType() == ArrayWithSlowPutArrayStorage
+ || (initialLength && structure->indexingType() == ArrayWithArrayStorage));
+ butterfly = createArrayButterfly(globalData, initialLength);
}
-
- inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
- {
- JSGlobalData& globalData = exec->globalData();
- JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
-
- // FIXME: we should probably throw an out of memory error here, but
- // when making this change we should check that all clients of this
- // function will correctly handle an exception being thrown from here.
- if (!array)
- CRASH();
-
- for (unsigned i = 0; i < length; ++i)
- array->initializeIndex(globalData, i, values[i]);
- return array;
+ JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
+ array->finishCreation(globalData);
+ return array;
+}
+
+inline JSArray* JSArray::tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength)
+{
+ unsigned vectorLength = std::max(BASE_VECTOR_LEN, initialLength);
+ if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
+ return 0;
+
+ Butterfly* butterfly;
+ if (LIKELY(structure->indexingType() == ArrayWithContiguous)) {
+
+ void* temp;
+ if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, vectorLength * sizeof(EncodedJSValue)), &temp))
+ return 0;
+ butterfly = Butterfly::fromBase(temp, 0, 0);
+ butterfly->setVectorLength(vectorLength);
+ butterfly->setPublicLength(initialLength);
+ } else {
+ void* temp;
+ if (!globalData.heap.tryAllocateStorage(Butterfly::totalSize(0, 0, true, ArrayStorage::sizeFor(vectorLength)), &temp))
+ return 0;
+ butterfly = Butterfly::fromBase(temp, 0, 0);
+ *butterfly->indexingHeader() = indexingHeaderForArray(initialLength, vectorLength);
+ ArrayStorage* storage = butterfly->arrayStorage();
+ storage->m_indexBias = 0;
+ storage->m_sparseMap.clear();
+ storage->m_numValuesInVector = initialLength;
}
+
+ JSArray* array = new (NotNull, allocateCell<JSArray>(globalData.heap)) JSArray(globalData, structure, butterfly);
+ array->finishCreation(globalData);
+ return array;
+}
+
+JSArray* asArray(JSValue);
+
+inline JSArray* asArray(JSCell* cell)
+{
+ ASSERT(cell->inherits(&JSArray::s_info));
+ return jsCast<JSArray*>(cell);
+}
+
+inline JSArray* asArray(JSValue value)
+{
+ return asArray(value.asCell());
+}
+
+inline bool isJSArray(JSCell* cell) { return cell->classInfo() == &JSArray::s_info; }
+inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); }
+
+inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const ArgList& values)
+{
+ JSGlobalData& globalData = exec->globalData();
+ unsigned length = values.size();
+ JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+
+ // FIXME: we should probably throw an out of memory error here, but
+ // when making this change we should check that all clients of this
+ // function will correctly handle an exception being thrown from here.
+ if (!array)
+ CRASH();
+
+ for (unsigned i = 0; i < length; ++i)
+ array->initializeIndex(globalData, i, values.at(i));
+ return array;
+}
+
+inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
+{
+ JSGlobalData& globalData = exec->globalData();
+ JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
+
+ // FIXME: we should probably throw an out of memory error here, but
+ // when making this change we should check that all clients of this
+ // function will correctly handle an exception being thrown from here.
+ if (!array)
+ CRASH();
+
+ for (unsigned i = 0; i < length; ++i)
+ array->initializeIndex(globalData, i, values[i]);
+ return array;
+}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index a39af1283..3b37613d1 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -38,326 +38,327 @@
namespace JSC {
- class CopyVisitor;
- class JSDestructibleObject;
- class JSGlobalObject;
- class LLIntOffsetsExtractor;
- class PropertyDescriptor;
- class PropertyNameArray;
- class Structure;
-
- enum EnumerationMode {
- ExcludeDontEnumProperties,
- IncludeDontEnumProperties
- };
-
- class JSCell {
- friend class JSValue;
- friend class MarkedBlock;
- template<typename T> friend void* allocateCell(Heap&);
- template<typename T> friend void* allocateCell(Heap&, size_t);
-
- public:
- static const unsigned StructureFlags = 0;
-
- static const bool needsDestruction = false;
- static const bool hasImmortalStructure = false;
-
- enum CreatingEarlyCellTag { CreatingEarlyCell };
- JSCell(CreatingEarlyCellTag);
-
- protected:
- JSCell(JSGlobalData&, Structure*);
- JS_EXPORT_PRIVATE static void destroy(JSCell*);
-
- public:
- // Querying the type.
- bool isString() const;
- bool isObject() const;
- bool isGetterSetter() const;
- bool inherits(const ClassInfo*) const;
- bool isAPIValueWrapper() const;
-
- Structure* structure() const;
- void setStructure(JSGlobalData&, Structure*);
- void clearStructure() { m_structure.clear(); }
-
- const char* className();
-
- // Extracting the value.
- JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const;
- JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string
- JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
- const JSObject* getObject() const; // NULL if not an object
+class CopyVisitor;
+class JSDestructibleObject;
+class JSGlobalObject;
+class LLIntOffsetsExtractor;
+class PropertyDescriptor;
+class PropertyNameArray;
+class Structure;
+
+enum EnumerationMode {
+ ExcludeDontEnumProperties,
+ IncludeDontEnumProperties
+};
+
+class JSCell {
+ friend class JSValue;
+ friend class MarkedBlock;
+ template<typename T> friend void* allocateCell(Heap&);
+ template<typename T> friend void* allocateCell(Heap&, size_t);
+
+public:
+ static const unsigned StructureFlags = 0;
+
+ static const bool needsDestruction = false;
+ static const bool hasImmortalStructure = false;
+
+ enum CreatingEarlyCellTag { CreatingEarlyCell };
+ JSCell(CreatingEarlyCellTag);
+
+protected:
+ JSCell(JSGlobalData&, Structure*);
+ JS_EXPORT_PRIVATE static void destroy(JSCell*);
+
+public:
+ // Querying the type.
+ bool isString() const;
+ bool isObject() const;
+ bool isGetterSetter() const;
+ bool isProxy() const;
+ bool inherits(const ClassInfo*) const;
+ bool isAPIValueWrapper() const;
+
+ Structure* structure() const;
+ void setStructure(JSGlobalData&, Structure*);
+ void clearStructure() { m_structure.clear(); }
+
+ const char* className();
+
+ // Extracting the value.
+ JS_EXPORT_PRIVATE bool getString(ExecState*, String&) const;
+ JS_EXPORT_PRIVATE String getString(ExecState*) const; // null string if not a string
+ JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object
+ const JSObject* getObject() const; // NULL if not an object
- JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
- JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
-
- // Basic conversions.
- JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
- bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
- bool toBoolean(ExecState*) const;
- JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
- JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
-
- static void visitChildren(JSCell*, SlotVisitor&);
- JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
-
- // Object operations, with the toObject operation included.
- const ClassInfo* classInfo() const;
- const MethodTable* methodTable() const;
- static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
- static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&);
+ JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&);
+
+ // Basic conversions.
+ JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+ bool toBoolean(ExecState*) const;
+ JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+ JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const;
+
+ static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
+
+ // Object operations, with the toObject operation included.
+ const ClassInfo* classInfo() const;
+ const MethodTable* methodTable() const;
+ static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
- static bool deleteProperty(JSCell*, ExecState*, PropertyName);
- static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
-
- static JSObject* toThisObject(JSCell*, ExecState*);
-
- void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
- bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
-
- // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
- // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
- // call this function, not its slower virtual counterpart. (For integer
- // property names, we want a similar interface with appropriate optimizations.)
- bool fastGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
- JSValue fastGetOwnProperty(ExecState*, const String&);
-
- static ptrdiff_t structureOffset()
- {
- return OBJECT_OFFSETOF(JSCell, m_structure);
- }
-
- void* structureAddress()
- {
- return &m_structure;
- }
-
-#if ENABLE(GC_VALIDATION)
- Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
-#endif
-
- static const TypedArrayType TypedArrayStorageType = TypedArrayNone;
- protected:
-
- void finishCreation(JSGlobalData&);
- void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag);
-
- // Base implementation; for non-object classes implements getPropertySlot.
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
-
- // Dummy implementations of override-able static functions for classes to put in their MethodTable
- static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
- static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static NO_RETURN_DUE_TO_ASSERT void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- static String className(const JSObject*);
- JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
- static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
- static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
- static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
-
- private:
- friend class LLIntOffsetsExtractor;
-
- WriteBarrier<Structure> m_structure;
- };
-
- inline JSCell::JSCell(CreatingEarlyCellTag)
- {
- }
-
- inline void JSCell::finishCreation(JSGlobalData& globalData)
- {
-#if ENABLE(GC_VALIDATION)
- ASSERT(globalData.isInitializingObject());
- globalData.setInitializingObjectClass(0);
-#else
- UNUSED_PARAM(globalData);
-#endif
- ASSERT(m_structure);
- }
-
- inline Structure* JSCell::structure() const
- {
- return m_structure.get();
- }
-
- inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
- {
- MARK_LOG_PARENT(visitor, cell);
-
- visitor.append(&cell->m_structure);
- }
-
- // --- JSValue inlines ----------------------------
-
- inline bool JSValue::isString() const
- {
- return isCell() && asCell()->isString();
- }
+ static bool deleteProperty(JSCell*, ExecState*, PropertyName);
+ static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
- inline bool JSValue::isPrimitive() const
- {
- return !isCell() || asCell()->isString();
- }
+ static JSObject* toThisObject(JSCell*, ExecState*);
- inline bool JSValue::isGetterSetter() const
- {
- return isCell() && asCell()->isGetterSetter();
- }
+ void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
+ bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
- inline bool JSValue::isObject() const
- {
- return isCell() && asCell()->isObject();
- }
+ // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and
+ // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always
+ // call this function, not its slower virtual counterpart. (For integer
+ // property names, we want a similar interface with appropriate optimizations.)
+ bool fastGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
+ JSValue fastGetOwnProperty(ExecState*, const String&);
- inline bool JSValue::getString(ExecState* exec, String& s) const
+ static ptrdiff_t structureOffset()
{
- return isCell() && asCell()->getString(exec, s);
+ return OBJECT_OFFSETOF(JSCell, m_structure);
}
- inline String JSValue::getString(ExecState* exec) const
+ void* structureAddress()
{
- return isCell() ? asCell()->getString(exec) : String();
+ return &m_structure;
}
+
+#if ENABLE(GC_VALIDATION)
+ Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
+#endif
+
+ static const TypedArrayType TypedArrayStorageType = TypedArrayNone;
+protected:
+
+ void finishCreation(JSGlobalData&);
+ void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag);
+
+ // Base implementation; for non-object classes implements getPropertySlot.
+ static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
+ static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+
+ // Dummy implementations of override-able static functions for classes to put in their MethodTable
+ static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+ static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static NO_RETURN_DUE_TO_ASSERT void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static String className(const JSObject*);
+ JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
+ static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+ static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
+ static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+
+private:
+ friend class LLIntOffsetsExtractor;
+
+ WriteBarrier<Structure> m_structure;
+};
- template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
- {
- return jsValue().getString(exec);
- }
+inline JSCell::JSCell(CreatingEarlyCellTag)
+{
+}
- inline JSObject* JSValue::getObject() const
- {
- return isCell() ? asCell()->getObject() : 0;
- }
-
- ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
- {
- if (isInt32()) {
- int32_t i = asInt32();
- v = static_cast<uint32_t>(i);
- return i >= 0;
- }
- if (isDouble()) {
- double d = asDouble();
- v = static_cast<uint32_t>(d);
- return v == d;
- }
- return false;
+inline void JSCell::finishCreation(JSGlobalData& globalData)
+{
+#if ENABLE(GC_VALIDATION)
+ ASSERT(globalData.isInitializingObject());
+ globalData.setInitializingObjectClass(0);
+#else
+ UNUSED_PARAM(globalData);
+#endif
+ ASSERT(m_structure);
+}
+
+inline Structure* JSCell::structure() const
+{
+ return m_structure.get();
+}
+
+inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ MARK_LOG_PARENT(visitor, cell);
+
+ visitor.append(&cell->m_structure);
+}
+
+// --- JSValue inlines ----------------------------
+
+inline bool JSValue::isString() const
+{
+ return isCell() && asCell()->isString();
+}
+
+inline bool JSValue::isPrimitive() const
+{
+ return !isCell() || asCell()->isString();
+}
+
+inline bool JSValue::isGetterSetter() const
+{
+ return isCell() && asCell()->isGetterSetter();
+}
+
+inline bool JSValue::isObject() const
+{
+ return isCell() && asCell()->isObject();
+}
+
+inline bool JSValue::getString(ExecState* exec, String& s) const
+{
+ return isCell() && asCell()->getString(exec, s);
+}
+
+inline String JSValue::getString(ExecState* exec) const
+{
+ return isCell() ? asCell()->getString(exec) : String();
+}
+
+template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
+{
+ return jsValue().getString(exec);
+}
+
+inline JSObject* JSValue::getObject() const
+{
+ return isCell() ? asCell()->getObject() : 0;
+}
+
+ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
+{
+ if (isInt32()) {
+ int32_t i = asInt32();
+ v = static_cast<uint32_t>(i);
+ return i >= 0;
}
-
- inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
- {
- return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
+ if (isDouble()) {
+ double d = asDouble();
+ v = static_cast<uint32_t>(d);
+ return v == d;
}
-
- inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
- {
- if (isInt32()) {
- number = asInt32();
- value = *this;
- return true;
- }
- if (isDouble()) {
- number = asDouble();
- value = *this;
- return true;
- }
- if (isCell())
- return asCell()->getPrimitiveNumber(exec, number, value);
- if (isTrue()) {
- number = 1.0;
- value = *this;
- return true;
- }
- if (isFalse() || isNull()) {
- number = 0.0;
- value = *this;
- return true;
- }
- ASSERT(isUndefined());
- number = std::numeric_limits<double>::quiet_NaN();
+ return false;
+}
+
+inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
+{
+ return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
+}
+
+inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
+{
+ if (isInt32()) {
+ number = asInt32();
value = *this;
return true;
}
-
- ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
- {
- if (isInt32())
- return asInt32();
- if (isDouble())
- return asDouble();
- return toNumberSlowCase(exec);
+ if (isDouble()) {
+ number = asDouble();
+ value = *this;
+ return true;
}
-
- inline JSObject* JSValue::toObject(ExecState* exec) const
- {
- return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
+ if (isCell())
+ return asCell()->getPrimitiveNumber(exec, number, value);
+ if (isTrue()) {
+ number = 1.0;
+ value = *this;
+ return true;
}
-
- inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
- {
- return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
+ if (isFalse() || isNull()) {
+ number = 0.0;
+ value = *this;
+ return true;
}
-
- template<typename T>
- void* allocateCell(Heap& heap, size_t size)
- {
- ASSERT(size >= sizeof(T));
+ ASSERT(isUndefined());
+ number = QNaN;
+ value = *this;
+ return true;
+}
+
+ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
+{
+ if (isInt32())
+ return asInt32();
+ if (isDouble())
+ return asDouble();
+ return toNumberSlowCase(exec);
+}
+
+inline JSObject* JSValue::toObject(ExecState* exec) const
+{
+ return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
+}
+
+inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
+{
+ return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
+}
+
+template<typename T>
+void* allocateCell(Heap& heap, size_t size)
+{
+ ASSERT(size >= sizeof(T));
#if ENABLE(GC_VALIDATION)
- ASSERT(!heap.globalData()->isInitializingObject());
- heap.globalData()->setInitializingObjectClass(&T::s_info);
+ ASSERT(!heap.globalData()->isInitializingObject());
+ heap.globalData()->setInitializingObjectClass(&T::s_info);
#endif
- JSCell* result = 0;
- if (T::needsDestruction && T::hasImmortalStructure)
- result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
- else if (T::needsDestruction && !T::hasImmortalStructure)
- result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
- else
- result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
- result->clearStructure();
- return result;
- }
+ JSCell* result = 0;
+ if (T::needsDestruction && T::hasImmortalStructure)
+ result = static_cast<JSCell*>(heap.allocateWithImmortalStructureDestructor(size));
+ else if (T::needsDestruction && !T::hasImmortalStructure)
+ result = static_cast<JSCell*>(heap.allocateWithNormalDestructor(size));
+ else
+ result = static_cast<JSCell*>(heap.allocateWithoutDestructor(size));
+ result->clearStructure();
+ return result;
+}
- template<typename T>
- void* allocateCell(Heap& heap)
- {
- return allocateCell<T>(heap, sizeof(T));
- }
+template<typename T>
+void* allocateCell(Heap& heap)
+{
+ return allocateCell<T>(heap, sizeof(T));
+}
- inline bool isZapped(const JSCell* cell)
- {
- return cell->isZapped();
- }
-
- template<typename To, typename From>
- inline To jsCast(From* from)
- {
- ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
- return static_cast<To>(from);
- }
+inline bool isZapped(const JSCell* cell)
+{
+ return cell->isZapped();
+}
+
+template<typename To, typename From>
+inline To jsCast(From* from)
+{
+ ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
+ return static_cast<To>(from);
+}
- template<typename To>
- inline To jsCast(JSValue from)
- {
- ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
- return static_cast<To>(from.asCell());
- }
-
- template<typename To, typename From>
- inline To jsDynamicCast(From* from)
- {
- return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0;
- }
-
- template<typename To>
- inline To jsDynamicCast(JSValue from)
- {
- return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from.asCell()) : 0;
- }
+template<typename To>
+inline To jsCast(JSValue from)
+{
+ ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info));
+ return static_cast<To>(from.asCell());
+}
+
+template<typename To, typename From>
+inline To jsDynamicCast(From* from)
+{
+ return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0;
+}
+
+template<typename To>
+inline To jsDynamicCast(JSValue from)
+{
+ return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from.asCell()) : 0;
+}
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index c54147ef2..cd3948fcf 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -247,7 +247,7 @@ double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateSt
int offset;
double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
if (isnan(ms))
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
// fall back to local timezone
if (!haveTZ) {
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index 5fb682bdb..4dca5b0f6 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -30,6 +30,7 @@
#include "JSGlobalData.h"
#include "ArgList.h"
+#include "CodeCache.h"
#include "CommonIdentifiers.h"
#include "DebuggerActivation.h"
#include "FunctionConstructor.h"
@@ -57,6 +58,7 @@
#include "RegExpObject.h"
#include "StrictEvalActivation.h"
#include "StrongInlines.h"
+#include "UnlinkedCodeBlock.h"
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
#include <wtf/WTFThreadData.h>
@@ -170,7 +172,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, sizeOfLastScratchBuffer(0)
#endif
, dynamicGlobalObject(0)
- , cachedUTCOffset(std::numeric_limits<double>::quiet_NaN())
+ , cachedUTCOffset(QNaN)
, m_enabledProfiler(0)
, m_regExpCache(new RegExpCache(this))
#if ENABLE(REGEXP_TRACING)
@@ -196,6 +198,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
, m_initializingObjectClass(0)
#endif
, m_inDefineOwnProperty(false)
+ , m_codeCache(CodeCache::create())
{
interpreter = new Interpreter(*this);
@@ -221,6 +224,11 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull()));
structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
+ withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull()));
+ unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
+ unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
+ unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
+ unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
@@ -400,10 +408,10 @@ JSGlobalData::ClientData::~ClientData()
void JSGlobalData::resetDateCache()
{
- cachedUTCOffset = std::numeric_limits<double>::quiet_NaN();
+ cachedUTCOffset = QNaN;
dstOffsetCache.reset();
cachedDateString = String();
- cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
+ cachedDateStringValue = QNaN;
dateInstanceCache.reset();
}
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index e97c0a015..0ffaccb6a 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -63,6 +63,7 @@ struct OpaqueJSClassContextData;
namespace JSC {
class CodeBlock;
+ class CodeCache;
class CommonIdentifiers;
class HandleStack;
class IdentifierTable;
@@ -80,6 +81,10 @@ namespace JSC {
#if ENABLE(REGEXP_TRACING)
class RegExp;
#endif
+ class UnlinkedCodeBlock;
+ class UnlinkedEvalCodeBlock;
+ class UnlinkedFunctionExecutable;
+ class UnlinkedProgramCodeBlock;
struct HashTable;
struct Instruction;
@@ -223,6 +228,11 @@ namespace JSC {
Strong<Structure> sharedSymbolTableStructure;
Strong<Structure> structureChainStructure;
Strong<Structure> sparseArrayValueMapStructure;
+ Strong<Structure> withScopeStructure;
+ Strong<Structure> unlinkedFunctionExecutableStructure;
+ Strong<Structure> unlinkedProgramCodeBlockStructure;
+ Strong<Structure> unlinkedEvalCodeBlockStructure;
+ Strong<Structure> unlinkedFunctionCodeBlockStructure;
IdentifierTable* identifierTable;
CommonIdentifiers* propertyNames;
@@ -436,6 +446,7 @@ namespace JSC {
}
JSLock& apiLock() { return m_apiLock; }
+ CodeCache* codeCache() { return m_codeCache.get(); }
private:
friend class LLIntOffsetsExtractor;
@@ -456,6 +467,7 @@ namespace JSC {
const ClassInfo* m_initializingObjectClass;
#endif
bool m_inDefineOwnProperty;
+ OwnPtr<CodeCache> m_codeCache;
TypedArrayDescriptor m_int8ArrayDescriptor;
TypedArrayDescriptor m_int16ArrayDescriptor;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 03252fad1..c466a2b04 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -36,6 +36,7 @@
#include "BooleanConstructor.h"
#include "BooleanPrototype.h"
#include "CodeBlock.h"
+#include "CodeCache.h"
#include "DateConstructor.h"
#include "DatePrototype.h"
#include "Debugger.h"
@@ -580,4 +581,58 @@ void slowValidateCell(JSGlobalObject* globalObject)
ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
}
+UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* callFrame, ProgramExecutable* executable, JSObject** exception)
+{
+ ParserError error;
+ JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
+ DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
+ ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
+ UnlinkedProgramCodeBlock* unlinkedCode = globalData().codeCache()->getProgramCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+
+ if (hasDebugger())
+ debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
+
+ if (error.m_type != ParserError::ErrorNone) {
+ *exception = error.toErrorObject(this, executable->source());
+ return 0;
+ }
+
+ return unlinkedCode;
+}
+
+UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CallFrame* callFrame, EvalExecutable* executable, JSObject** exception)
+{
+ ParserError error;
+ JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal;
+ DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff;
+ ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff;
+ UnlinkedEvalCodeBlock* unlinkedCode = globalData().codeCache()->getEvalCodeBlock(globalData(), executable, executable->source(), strictness, debuggerMode, profilerMode, error);
+
+ if (hasDebugger())
+ debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message);
+
+ if (error.m_type != ParserError::ErrorNone) {
+ *exception = error.toErrorObject(this, executable->source());
+ return 0;
+ }
+
+ return unlinkedCode;
+}
+
+UnlinkedFunctionExecutable* JSGlobalObject::createFunctionExecutableFromGlobalCode(CallFrame* callFrame, const Identifier& name, const SourceCode& code, JSObject** exception)
+{
+ ParserError error;
+ UnlinkedFunctionExecutable* executable = globalData().codeCache()->getFunctionExecutableFromGlobalCode(globalData(), name, code, error);
+ if (hasDebugger())
+ debugger()->sourceParsed(callFrame, code.provider(), error.m_line, error.m_message);
+
+ if (error.m_type != ParserError::ErrorNone) {
+ *exception = error.toErrorObject(this, code);
+ return 0;
+ }
+
+ return executable;
+}
+
+
} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 2994aa64b..3212363ab 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -43,6 +43,10 @@ namespace JSC {
class Debugger;
class ErrorConstructor;
class ErrorPrototype;
+ class EvalCodeBlock;
+ class EvalExecutable;
+ class FunctionCodeBlock;
+ class FunctionExecutable;
class FunctionPrototype;
class GetterSetter;
class GlobalCodeBlock;
@@ -50,9 +54,10 @@ namespace JSC {
class LLIntOffsetsExtractor;
class NativeErrorConstructor;
class ProgramCodeBlock;
+ class ProgramExecutable;
class RegExpConstructor;
class RegExpPrototype;
-
+ class SourceCode;
struct ActivationStackNode;
struct HashTable;
@@ -185,6 +190,9 @@ namespace JSC {
static JS_EXPORTDATA const ClassInfo s_info;
+ bool hasDebugger() const { return m_debugger; }
+ bool hasProfiler() const { return globalObjectMethodTable()->supportsProfiling(this); }
+
protected:
JS_EXPORT_PRIVATE explicit JSGlobalObject(JSGlobalData&, Structure*, const GlobalObjectMethodTable* = 0);
@@ -271,6 +279,10 @@ namespace JSC {
Structure* arrayStructureWithArrayStorage() const { return m_arrayStructureWithArrayStorage.get(); }
void* addressOfArrayStructure() { return &m_arrayStructure; }
void* addressOfArrayStructureWithArrayStorage() { return &m_arrayStructureWithArrayStorage; }
+ bool isOriginalArrayStructure(Structure* structure)
+ {
+ return structure == m_arrayStructure.get() || structure == m_arrayStructureWithArrayStorage.get();
+ }
Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
@@ -362,6 +374,11 @@ namespace JSC {
double weakRandomNumber() { return m_weakRandom.get(); }
unsigned weakRandomInteger() { return m_weakRandom.getUint32(); }
+
+ UnlinkedProgramCodeBlock* createProgramCodeBlock(CallFrame*, ProgramExecutable*, JSObject** exception);
+ UnlinkedEvalCodeBlock* createEvalCodeBlock(CallFrame*, EvalExecutable*, JSObject** exception);
+ UnlinkedFunctionExecutable* createFunctionExecutableFromGlobalCode(CallFrame*, const Identifier&, const SourceCode&, JSObject** exception);
+
protected:
static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index 8b1acb25a..7ac76d350 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -276,7 +276,7 @@ static double parseInt(const String& s, const CharType* data, int radix)
// 8.a If R < 2 or R > 36, then return NaN.
if (radix < 2 || radix > 36)
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
// 13. Let mathInt be the mathematical integer value that is represented by Z in radix-R notation, using the letters
// A-Z and a-z for digits with values 10 through 35. (However, if R is 10 and Z contains more than 20 significant
@@ -299,7 +299,7 @@ static double parseInt(const String& s, const CharType* data, int radix)
// 12. If Z is empty, return NaN.
if (!sawDigit)
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
// Alternate code path for certain large numbers.
if (number >= mantissaOverflowLowerBound) {
@@ -397,7 +397,7 @@ static double jsStrDecimalLiteral(const CharType*& data, const CharType* end)
}
// Not a number.
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
}
template <typename CharType>
@@ -427,7 +427,7 @@ static double toDouble(const CharType* characters, unsigned size)
break;
}
if (characters != endCharacters)
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
return number;
}
@@ -443,7 +443,7 @@ double jsToNumber(const String& s)
return c - '0';
if (isStrWhiteSpace(c))
return 0;
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
}
if (s.is8Bit())
@@ -459,7 +459,7 @@ static double parseFloat(const String& s)
UChar c = s[0];
if (isASCIIDigit(c))
return c - '0';
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
}
if (s.is8Bit()) {
@@ -474,7 +474,7 @@ static double parseFloat(const String& s)
// Empty string.
if (data == end)
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
return jsStrDecimalLiteral(data, end);
}
@@ -490,7 +490,7 @@ static double parseFloat(const String& s)
// Empty string.
if (data == end)
- return std::numeric_limits<double>::quiet_NaN();
+ return QNaN;
return jsStrDecimalLiteral(data, end);
}
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index fd939934e..e051ec7d9 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -294,7 +294,7 @@ static void appendStringToStringBuilder(StringBuilder& builder, const CharType*
default:
static const char hexDigits[] = "0123456789abcdef";
UChar ch = data[i];
- LChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
+ LChar hex[] = { '\\', 'u', static_cast<LChar>(hexDigits[(ch >> 12) & 0xF]), static_cast<LChar>(hexDigits[(ch >> 8) & 0xF]), static_cast<LChar>(hexDigits[(ch >> 4) & 0xF]), static_cast<LChar>(hexDigits[ch & 0xF]) };
builder.append(hex, WTF_ARRAY_LENGTH(hex));
break;
}
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index 9204099cb..82455390f 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -44,810 +44,841 @@
namespace JSC {
- inline JSCell* getJSFunction(JSValue value)
- {
- if (value.isCell() && (value.asCell()->structure()->typeInfo().type() == JSFunctionType))
- return value.asCell();
- return 0;
- }
+inline JSCell* getJSFunction(JSValue value)
+{
+ if (value.isCell() && (value.asCell()->structure()->typeInfo().type() == JSFunctionType))
+ return value.asCell();
+ return 0;
+}
- JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*);
+JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*);
- inline JSCell* getCallableObject(JSValue value)
- {
- if (!value.isCell())
- return 0;
- return getCallableObjectSlow(value.asCell());
- }
-
- class GetterSetter;
- class HashEntry;
- class InternalFunction;
- class LLIntOffsetsExtractor;
- class MarkedBlock;
- class PropertyDescriptor;
- class PropertyNameArray;
- class Structure;
- struct HashTable;
-
- JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const String&);
- extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError;
-
- // ECMA 262-3 8.6.1
- // Property attributes
- enum Attribute {
- None = 0,
- ReadOnly = 1 << 1, // property can be only read, not written
- DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
- DontDelete = 1 << 3, // property can't be deleted
- Function = 1 << 4, // property is a function - only used by static hashtables
- Accessor = 1 << 5, // property is a getter/setter
+inline JSCell* getCallableObject(JSValue value)
+{
+ if (!value.isCell())
+ return 0;
+ return getCallableObjectSlow(value.asCell());
+}
+
+class GetterSetter;
+class HashEntry;
+class InternalFunction;
+class LLIntOffsetsExtractor;
+class MarkedBlock;
+class PropertyDescriptor;
+class PropertyNameArray;
+class Structure;
+struct HashTable;
+
+JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const String&);
+extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError;
+
+// ECMA 262-3 8.6.1
+// Property attributes
+enum Attribute {
+ None = 0,
+ ReadOnly = 1 << 1, // property can be only read, not written
+ DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
+ DontDelete = 1 << 3, // property can't be deleted
+ Function = 1 << 4, // property is a function - only used by static hashtables
+ Accessor = 1 << 5, // property is a getter/setter
+};
+
+COMPILE_ASSERT(None < FirstInternalAttribute, None_is_below_FirstInternalAttribute);
+COMPILE_ASSERT(ReadOnly < FirstInternalAttribute, ReadOnly_is_below_FirstInternalAttribute);
+COMPILE_ASSERT(DontEnum < FirstInternalAttribute, DontEnum_is_below_FirstInternalAttribute);
+COMPILE_ASSERT(DontDelete < FirstInternalAttribute, DontDelete_is_below_FirstInternalAttribute);
+COMPILE_ASSERT(Function < FirstInternalAttribute, Function_is_below_FirstInternalAttribute);
+COMPILE_ASSERT(Accessor < FirstInternalAttribute, Accessor_is_below_FirstInternalAttribute);
+
+class JSFinalObject;
+
+class JSObject : public JSCell {
+ friend class BatchedTransitionOptimizer;
+ friend class JIT;
+ friend class JSCell;
+ friend class JSFinalObject;
+ friend class MarkedBlock;
+ JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject*, PropertyName, PropertySlot&);
+
+ enum PutMode {
+ PutModePut,
+ PutModeDefineOwnProperty,
};
- COMPILE_ASSERT(None < FirstInternalAttribute, None_is_below_FirstInternalAttribute);
- COMPILE_ASSERT(ReadOnly < FirstInternalAttribute, ReadOnly_is_below_FirstInternalAttribute);
- COMPILE_ASSERT(DontEnum < FirstInternalAttribute, DontEnum_is_below_FirstInternalAttribute);
- COMPILE_ASSERT(DontDelete < FirstInternalAttribute, DontDelete_is_below_FirstInternalAttribute);
- COMPILE_ASSERT(Function < FirstInternalAttribute, Function_is_below_FirstInternalAttribute);
- COMPILE_ASSERT(Accessor < FirstInternalAttribute, Accessor_is_below_FirstInternalAttribute);
-
- class JSFinalObject;
-
- class JSObject : public JSCell {
- friend class BatchedTransitionOptimizer;
- friend class JIT;
- friend class JSCell;
- friend class JSFinalObject;
- friend class MarkedBlock;
- JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject*, PropertyName, PropertySlot&);
-
- enum PutMode {
- PutModePut,
- PutModeDefineOwnProperty,
- };
-
- public:
- typedef JSCell Base;
+public:
+ typedef JSCell Base;
- static size_t allocationSize(size_t inlineCapacity)
- {
- return sizeof(JSObject) + inlineCapacity * sizeof(WriteBarrierBase<Unknown>);
- }
+ static size_t allocationSize(size_t inlineCapacity)
+ {
+ return sizeof(JSObject) + inlineCapacity * sizeof(WriteBarrierBase<Unknown>);
+ }
- JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void copyBackingStore(JSCell*, CopyVisitor&);
- JS_EXPORT_PRIVATE static String className(const JSObject*);
+ JS_EXPORT_PRIVATE static String className(const JSObject*);
- JSValue prototype() const;
- void setPrototype(JSGlobalData&, JSValue prototype);
- bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
+ JSValue prototype() const;
+ void setPrototype(JSGlobalData&, JSValue prototype);
+ bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
- Structure* inheritorID(JSGlobalData&);
- void notifyUsedAsPrototype(JSGlobalData&);
+ Structure* inheritorID(JSGlobalData&);
+ void notifyUsedAsPrototype(JSGlobalData&);
- bool mayBeUsedAsPrototype(JSGlobalData& globalData)
- {
- return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey));
- }
+ bool mayBeUsedAsPrototype(JSGlobalData& globalData)
+ {
+ return isValidOffset(structure()->get(globalData, globalData.m_inheritorIDKey));
+ }
- bool mayInterceptIndexedAccesses()
- {
- return structure()->mayInterceptIndexedAccesses();
- }
+ bool mayInterceptIndexedAccesses()
+ {
+ return structure()->mayInterceptIndexedAccesses();
+ }
- JSValue get(ExecState*, PropertyName) const;
- JSValue get(ExecState*, unsigned propertyName) const;
-
- bool getPropertySlot(ExecState*, PropertyName, PropertySlot&);
- bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
- JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
-
- static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
- JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
- JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
-
- bool allowsAccessFrom(ExecState*);
-
- unsigned getArrayLength() const
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- return 0;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->publicLength();
- default:
- ASSERT_NOT_REACHED();
- return 0;
- }
+ JSValue get(ExecState*, PropertyName) const;
+ JSValue get(ExecState*, unsigned propertyName) const;
+
+ bool getPropertySlot(ExecState*, PropertyName, PropertySlot&);
+ bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&);
+
+ static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
+
+ bool allowsAccessFrom(ExecState*);
+
+ unsigned getArrayLength() const
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ return 0;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->publicLength();
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
}
+ }
- unsigned getVectorLength()
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- return 0;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->vectorLength();
- default:
- ASSERT_NOT_REACHED();
- return 0;
- }
+ unsigned getVectorLength()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ return 0;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->vectorLength();
+ default:
+ ASSERT_NOT_REACHED();
+ return 0;
}
+ }
- JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
- JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
+ JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
- void putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
- {
- if (canSetIndexQuickly(propertyName)) {
- setIndexQuickly(exec->globalData(), propertyName, value);
- return;
- }
- methodTable()->putByIndex(this, exec, propertyName, value, shouldThrow);
+ void putByIndexInline(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
+ {
+ if (canSetIndexQuickly(propertyName)) {
+ setIndexQuickly(exec->globalData(), propertyName, value);
+ return;
}
+ methodTable()->putByIndex(this, exec, propertyName, value, shouldThrow);
+ }
- // This is similar to the putDirect* methods:
- // - the prototype chain is not consulted
- // - accessors are not called.
- // - it will ignore extensibility and read-only properties if PutDirectIndexLikePutDirect is passed as the mode (the default).
- // This method creates a property with attributes writable, enumerable and configurable all set to true.
- bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
- {
- if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) {
- setIndexQuickly(exec->globalData(), propertyName, value);
- return true;
- }
- return putDirectIndexBeyondVectorLength(exec, propertyName, value, attributes, mode);
- }
- bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value)
- {
- return putDirectIndex(exec, propertyName, value, 0, PutDirectIndexLikePutDirect);
+ // This is similar to the putDirect* methods:
+ // - the prototype chain is not consulted
+ // - accessors are not called.
+ // - it will ignore extensibility and read-only properties if PutDirectIndexLikePutDirect is passed as the mode (the default).
+ // This method creates a property with attributes writable, enumerable and configurable all set to true.
+ bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
+ {
+ if (!attributes && canSetIndexQuicklyForPutDirect(propertyName)) {
+ setIndexQuickly(exec->globalData(), propertyName, value);
+ return true;
}
+ return putDirectIndexBeyondVectorLength(exec, propertyName, value, attributes, mode);
+ }
+ bool putDirectIndex(ExecState* exec, unsigned propertyName, JSValue value)
+ {
+ return putDirectIndex(exec, propertyName, value, 0, PutDirectIndexLikePutDirect);
+ }
- // A non-throwing version of putDirect and putDirectIndex.
- JS_EXPORT_PRIVATE void putDirectMayBeIndex(ExecState*, PropertyName, JSValue);
+ // A non-throwing version of putDirect and putDirectIndex.
+ JS_EXPORT_PRIVATE void putDirectMayBeIndex(ExecState*, PropertyName, JSValue);
- bool canGetIndexQuickly(unsigned i)
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- return false;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- return i < m_butterfly->vectorLength() && m_butterfly->contiguous()[i];
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i];
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ bool canGetIndexQuickly(unsigned i)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ return false;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return i < m_butterfly->vectorLength() && m_butterfly->contiguous()[i];
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return i < m_butterfly->arrayStorage()->vectorLength() && m_butterfly->arrayStorage()->m_vector[i];
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
}
+ }
- JSValue getIndexQuickly(unsigned i)
- {
- switch (structure()->indexingType()) {
- case ALL_CONTIGUOUS_INDEXING_TYPES:
+ JSValue getIndexQuickly(unsigned i)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->contiguous()[i].get();
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->m_vector[i].get();
+ default:
+ ASSERT_NOT_REACHED();
+ return JSValue();
+ }
+ }
+
+ JSValue tryGetIndexQuickly(unsigned i)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ break;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ if (i < m_butterfly->publicLength())
return m_butterfly->contiguous()[i].get();
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ break;
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ if (i < m_butterfly->arrayStorage()->vectorLength())
return m_butterfly->arrayStorage()->m_vector[i].get();
- default:
- ASSERT_NOT_REACHED();
- return JSValue();
- }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
}
+ return JSValue();
+ }
- JSValue tryGetIndexQuickly(unsigned i)
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- break;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- if (i < m_butterfly->publicLength())
- return m_butterfly->contiguous()[i].get();
- break;
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- if (i < m_butterfly->arrayStorage()->vectorLength())
- return m_butterfly->arrayStorage()->m_vector[i].get();
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
- return JSValue();
- }
+ JSValue getDirectIndex(ExecState* exec, unsigned i)
+ {
+ if (JSValue result = tryGetIndexQuickly(i))
+ return result;
+ PropertySlot slot(this);
+ if (methodTable()->getOwnPropertySlotByIndex(this, exec, i, slot))
+ return slot.getValue(exec, i);
+ return JSValue();
+ }
- JSValue getDirectIndex(ExecState* exec, unsigned i)
- {
- if (JSValue result = tryGetIndexQuickly(i))
- return result;
- PropertySlot slot(this);
- if (methodTable()->getOwnPropertySlotByIndex(this, exec, i, slot))
- return slot.getValue(exec, i);
- return JSValue();
- }
+ JSValue getIndex(ExecState* exec, unsigned i)
+ {
+ if (JSValue result = tryGetIndexQuickly(i))
+ return result;
+ return get(exec, i);
+ }
- JSValue getIndex(ExecState* exec, unsigned i)
- {
- if (JSValue result = tryGetIndexQuickly(i))
- return result;
- return get(exec, i);
+ bool canSetIndexQuickly(unsigned i)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ return false;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case NonArrayWithArrayStorage:
+ case ArrayWithArrayStorage:
+ return i < m_butterfly->vectorLength();
+ case NonArrayWithSlowPutArrayStorage:
+ case ArrayWithSlowPutArrayStorage:
+ return i < m_butterfly->arrayStorage()->vectorLength()
+ && !!m_butterfly->arrayStorage()->m_vector[i];
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
}
+ }
- bool canSetIndexQuickly(unsigned i)
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- return false;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case NonArrayWithArrayStorage:
- case ArrayWithArrayStorage:
- return i < m_butterfly->vectorLength();
- case NonArrayWithSlowPutArrayStorage:
- case ArrayWithSlowPutArrayStorage:
- return i < m_butterfly->arrayStorage()->vectorLength()
- && !!m_butterfly->arrayStorage()->m_vector[i];
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ bool canSetIndexQuicklyForPutDirect(unsigned i)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ return false;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return i < m_butterfly->vectorLength();
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
}
+ }
- bool canSetIndexQuicklyForPutDirect(unsigned i)
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- return false;
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return i < m_butterfly->vectorLength();
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES: {
+ ASSERT(i < m_butterfly->vectorLength());
+ m_butterfly->contiguous()[i].set(globalData, this, v);
+ if (i >= m_butterfly->publicLength())
+ m_butterfly->setPublicLength(i + 1);
+ break;
}
-
- void setIndexQuickly(JSGlobalData& globalData, unsigned i, JSValue v)
- {
- switch (structure()->indexingType()) {
- case ALL_CONTIGUOUS_INDEXING_TYPES: {
- ASSERT(i < m_butterfly->vectorLength());
- m_butterfly->contiguous()[i].set(globalData, this, v);
- if (i >= m_butterfly->publicLength())
- m_butterfly->setPublicLength(i + 1);
- break;
- }
- case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
- ArrayStorage* storage = m_butterfly->arrayStorage();
- WriteBarrier<Unknown>& x = storage->m_vector[i];
- JSValue old = x.get();
- x.set(globalData, this, v);
- if (!old) {
- ++storage->m_numValuesInVector;
- if (i >= storage->length())
- storage->setLength(i + 1);
- }
- break;
- }
- default:
- ASSERT_NOT_REACHED();
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+ ArrayStorage* storage = m_butterfly->arrayStorage();
+ WriteBarrier<Unknown>& x = storage->m_vector[i];
+ JSValue old = x.get();
+ x.set(globalData, this, v);
+ if (!old) {
+ ++storage->m_numValuesInVector;
+ if (i >= storage->length())
+ storage->setLength(i + 1);
}
+ break;
}
-
- void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v)
- {
- switch (structure()->indexingType()) {
- case ALL_CONTIGUOUS_INDEXING_TYPES: {
- ASSERT(i < m_butterfly->publicLength());
- ASSERT(i < m_butterfly->vectorLength());
- m_butterfly->contiguous()[i].set(globalData, this, v);
- break;
- }
- case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
- ArrayStorage* storage = m_butterfly->arrayStorage();
- ASSERT(i < storage->length());
- ASSERT(i < storage->m_numValuesInVector);
- storage->m_vector[i].set(globalData, this, v);
- break;
- }
- default:
- ASSERT_NOT_REACHED();
- }
+ default:
+ ASSERT_NOT_REACHED();
}
+ }
- bool hasSparseMap()
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- return false;
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage()->m_sparseMap;
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v)
+ {
+ switch (structure()->indexingType()) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES: {
+ ASSERT(i < m_butterfly->publicLength());
+ ASSERT(i < m_butterfly->vectorLength());
+ m_butterfly->contiguous()[i].set(globalData, this, v);
+ break;
+ }
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+ ArrayStorage* storage = m_butterfly->arrayStorage();
+ ASSERT(i < storage->length());
+ ASSERT(i < storage->m_numValuesInVector);
+ storage->m_vector[i].set(globalData, this, v);
+ break;
}
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
- bool inSparseIndexingMode()
- {
- switch (structure()->indexingType()) {
- case ALL_BLANK_INDEXING_TYPES:
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- return false;
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage()->inSparseMode();
- default:
- ASSERT_NOT_REACHED();
- return false;
- }
+ bool hasSparseMap()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return false;
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->m_sparseMap;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
}
+ }
- void enterDictionaryIndexingMode(JSGlobalData&);
-
- // putDirect is effectively an unchecked vesion of 'defineOwnProperty':
- // - the prototype chain is not consulted
- // - accessors are not called.
- // - attributes will be respected (after the call the property will exist with the given attributes)
- // - the property name is assumed to not be an index.
- JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
- void putDirect(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
- void putDirect(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
- void putDirectWithoutTransition(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
- void putDirectAccessor(ExecState*, PropertyName, JSValue, unsigned attributes);
-
- bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
-
- JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const;
- JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
- bool hasOwnProperty(ExecState*, PropertyName) const;
-
- JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
- JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
-
- JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
-
- bool hasInstance(ExecState*, JSValue);
- static bool defaultHasInstance(ExecState*, JSValue, JSValue prototypeProperty);
-
- JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-
- JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
- bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
- JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
- JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
-
- // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0,
- // because this call may come from inside the compiler.
- JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*);
-
- bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const;
-
- // This get function only looks at the property map.
- JSValue getDirect(JSGlobalData& globalData, PropertyName propertyName) const
- {
- PropertyOffset offset = structure()->get(globalData, propertyName);
- checkOffset(offset, structure()->typeInfo().type());
- return offset != invalidOffset ? getDirectOffset(offset) : JSValue();
+ bool inSparseIndexingMode()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return false;
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->inSparseMode();
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
}
+ }
+
+ void enterDictionaryIndexingMode(JSGlobalData&);
- WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName)
- {
- PropertyOffset offset = structure()->get(globalData, propertyName);
- checkOffset(offset, structure()->typeInfo().type());
- return isValidOffset(offset) ? locationForOffset(offset) : 0;
- }
+ // putDirect is effectively an unchecked vesion of 'defineOwnProperty':
+ // - the prototype chain is not consulted
+ // - accessors are not called.
+ // - attributes will be respected (after the call the property will exist with the given attributes)
+ // - the property name is assumed to not be an index.
+ JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+ void putDirect(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
+ void putDirect(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
+ void putDirectWithoutTransition(JSGlobalData&, PropertyName, JSValue, unsigned attributes = 0);
+ void putDirectAccessor(ExecState*, PropertyName, JSValue, unsigned attributes);
- WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes)
- {
- JSCell* specificFunction;
- PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction);
- return isValidOffset(offset) ? locationForOffset(offset) : 0;
- }
+ bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const;
- bool hasInlineStorage() const { return structure()->hasInlineStorage(); }
- ConstPropertyStorage inlineStorageUnsafe() const
- {
- return bitwise_cast<ConstPropertyStorage>(this + 1);
- }
- PropertyStorage inlineStorageUnsafe()
- {
- return bitwise_cast<PropertyStorage>(this + 1);
- }
- ConstPropertyStorage inlineStorage() const
- {
- ASSERT(hasInlineStorage());
- return inlineStorageUnsafe();
- }
- PropertyStorage inlineStorage()
- {
- ASSERT(hasInlineStorage());
- return inlineStorageUnsafe();
- }
+ JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const;
+ JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
+ bool hasOwnProperty(ExecState*, PropertyName) const;
+
+ JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
+ JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
+
+ JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType);
+
+ bool hasInstance(ExecState*, JSValue);
+ static bool defaultHasInstance(ExecState*, JSValue, JSValue prototypeProperty);
+
+ JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+
+ JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
+ bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const;
+ JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
+ JS_EXPORT_PRIVATE JSString* toString(ExecState*) const;
+
+ // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0,
+ // because this call may come from inside the compiler.
+ JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*);
+
+ bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const;
+
+ // This get function only looks at the property map.
+ JSValue getDirect(JSGlobalData& globalData, PropertyName propertyName) const
+ {
+ PropertyOffset offset = structure()->get(globalData, propertyName);
+ checkOffset(offset, structure()->typeInfo().type());
+ return offset != invalidOffset ? getDirectOffset(offset) : JSValue();
+ }
+
+ WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName)
+ {
+ PropertyOffset offset = structure()->get(globalData, propertyName);
+ checkOffset(offset, structure()->typeInfo().type());
+ return isValidOffset(offset) ? locationForOffset(offset) : 0;
+ }
+
+ WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, PropertyName propertyName, unsigned& attributes)
+ {
+ JSCell* specificFunction;
+ PropertyOffset offset = structure()->get(globalData, propertyName, attributes, specificFunction);
+ return isValidOffset(offset) ? locationForOffset(offset) : 0;
+ }
+
+ bool hasInlineStorage() const { return structure()->hasInlineStorage(); }
+ ConstPropertyStorage inlineStorageUnsafe() const
+ {
+ return bitwise_cast<ConstPropertyStorage>(this + 1);
+ }
+ PropertyStorage inlineStorageUnsafe()
+ {
+ return bitwise_cast<PropertyStorage>(this + 1);
+ }
+ ConstPropertyStorage inlineStorage() const
+ {
+ ASSERT(hasInlineStorage());
+ return inlineStorageUnsafe();
+ }
+ PropertyStorage inlineStorage()
+ {
+ ASSERT(hasInlineStorage());
+ return inlineStorageUnsafe();
+ }
- const Butterfly* butterfly() const { return m_butterfly; }
- Butterfly* butterfly() { return m_butterfly; }
+ const Butterfly* butterfly() const { return m_butterfly; }
+ Butterfly* butterfly() { return m_butterfly; }
- ConstPropertyStorage outOfLineStorage() const { return m_butterfly->propertyStorage(); }
- PropertyStorage outOfLineStorage() { return m_butterfly->propertyStorage(); }
-
- const WriteBarrierBase<Unknown>* locationForOffset(PropertyOffset offset) const
- {
- if (isInlineOffset(offset))
- return &inlineStorage()[offsetInInlineStorage(offset)];
- return &outOfLineStorage()[offsetInOutOfLineStorage(offset)];
- }
+ ConstPropertyStorage outOfLineStorage() const { return m_butterfly->propertyStorage(); }
+ PropertyStorage outOfLineStorage() { return m_butterfly->propertyStorage(); }
- WriteBarrierBase<Unknown>* locationForOffset(PropertyOffset offset)
- {
- if (isInlineOffset(offset))
- return &inlineStorage()[offsetInInlineStorage(offset)];
- return &outOfLineStorage()[offsetInOutOfLineStorage(offset)];
- }
+ const WriteBarrierBase<Unknown>* locationForOffset(PropertyOffset offset) const
+ {
+ if (isInlineOffset(offset))
+ return &inlineStorage()[offsetInInlineStorage(offset)];
+ return &outOfLineStorage()[offsetInOutOfLineStorage(offset)];
+ }
- PropertyOffset offsetForLocation(WriteBarrierBase<Unknown>* location) const
- {
- PropertyOffset result;
- size_t offsetInInlineStorage = location - inlineStorageUnsafe();
- if (offsetInInlineStorage < static_cast<size_t>(firstOutOfLineOffset))
- result = offsetInInlineStorage;
- else
- result = outOfLineStorage() - location + (firstOutOfLineOffset - 1);
- validateOffset(result, structure()->typeInfo().type());
- return result;
- }
+ WriteBarrierBase<Unknown>* locationForOffset(PropertyOffset offset)
+ {
+ if (isInlineOffset(offset))
+ return &inlineStorage()[offsetInInlineStorage(offset)];
+ return &outOfLineStorage()[offsetInOutOfLineStorage(offset)];
+ }
- void transitionTo(JSGlobalData&, Structure*);
-
- bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed.
- bool hasCustomProperties() { return structure()->didTransition(); }
- bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
-
- // putOwnDataProperty has 'put' like semantics, however this method:
- // - assumes the object contains no own getter/setter properties.
- // - provides no special handling for __proto__
- // - does not walk the prototype chain (to check for accessors or non-writable properties).
- // This is used by JSActivation.
- bool putOwnDataProperty(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
-
- // Fast access to known property offsets.
- JSValue getDirectOffset(PropertyOffset offset) const { return locationForOffset(offset)->get(); }
- void putDirectOffset(JSGlobalData& globalData, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(globalData, this, value); }
- void putUndefinedAtDirectOffset(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
-
- JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
-
- bool isGlobalObject() const;
- bool isVariableObject() const;
- bool isNameScopeObject() const;
- bool isActivationObject() const;
- bool isErrorInstance() const;
- bool isProxy() const;
-
- void seal(JSGlobalData&);
- void freeze(JSGlobalData&);
- JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&);
- bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); }
- bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); }
- bool isExtensible() { return structure()->isExtensible(); }
- bool indexingShouldBeSparse()
- {
- return !isExtensible()
- || structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
- }
+ PropertyOffset offsetForLocation(WriteBarrierBase<Unknown>* location) const
+ {
+ PropertyOffset result;
+ size_t offsetInInlineStorage = location - inlineStorageUnsafe();
+ if (offsetInInlineStorage < static_cast<size_t>(firstOutOfLineOffset))
+ result = offsetInInlineStorage;
+ else
+ result = outOfLineStorage() - location + (firstOutOfLineOffset - 1);
+ validateOffset(result, structure()->typeInfo().type());
+ return result;
+ }
+
+ void transitionTo(JSGlobalData&, Structure*);
+
+ bool removeDirect(JSGlobalData&, PropertyName); // Return true if anything is removed.
+ bool hasCustomProperties() { return structure()->didTransition(); }
+ bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); }
+
+ // putOwnDataProperty has 'put' like semantics, however this method:
+ // - assumes the object contains no own getter/setter properties.
+ // - provides no special handling for __proto__
+ // - does not walk the prototype chain (to check for accessors or non-writable properties).
+ // This is used by JSActivation.
+ bool putOwnDataProperty(JSGlobalData&, PropertyName, JSValue, PutPropertySlot&);
+
+ // Fast access to known property offsets.
+ JSValue getDirectOffset(PropertyOffset offset) const { return locationForOffset(offset)->get(); }
+ void putDirectOffset(JSGlobalData& globalData, PropertyOffset offset, JSValue value) { locationForOffset(offset)->set(globalData, this, value); }
+ void putUndefinedAtDirectOffset(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
+
+ JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
+
+ bool isGlobalObject() const;
+ bool isVariableObject() const;
+ bool isNameScopeObject() const;
+ bool isActivationObject() const;
+ bool isErrorInstance() const;
+
+ void seal(JSGlobalData&);
+ void freeze(JSGlobalData&);
+ JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&);
+ bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); }
+ bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); }
+ bool isExtensible() { return structure()->isExtensible(); }
+ bool indexingShouldBeSparse()
+ {
+ return !isExtensible()
+ || structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
+ }
- bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
- void reifyStaticFunctionsForDelete(ExecState* exec);
+ bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
+ void reifyStaticFunctionsForDelete(ExecState* exec);
- JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(JSGlobalData&, size_t oldSize, size_t newSize);
- void setButterfly(JSGlobalData&, Butterfly*, Structure*);
- void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this.
+ JS_EXPORT_PRIVATE Butterfly* growOutOfLineStorage(JSGlobalData&, size_t oldSize, size_t newSize);
+ void setButterfly(JSGlobalData&, Butterfly*, Structure*);
+ void setButterflyWithoutChangingStructure(Butterfly*); // You probably don't want to call this.
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
- void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*);
+ void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, unsigned oldCapacity, Structure*);
+ void setStructureAndReallocateStorageIfNecessary(JSGlobalData&, Structure*);
- void flattenDictionaryObject(JSGlobalData& globalData)
- {
- structure()->flattenDictionaryStructure(globalData, this);
- }
+ void flattenDictionaryObject(JSGlobalData& globalData)
+ {
+ structure()->flattenDictionaryStructure(globalData, this);
+ }
- JSGlobalObject* globalObject() const
- {
- ASSERT(structure()->globalObject());
- ASSERT(!isGlobalObject() || ((JSObject*)structure()->globalObject()) == this);
- return structure()->globalObject();
- }
+ JSGlobalObject* globalObject() const
+ {
+ ASSERT(structure()->globalObject());
+ ASSERT(!isGlobalObject() || ((JSObject*)structure()->globalObject()) == this);
+ return structure()->globalObject();
+ }
- void switchToSlowPutArrayStorage(JSGlobalData&);
+ void switchToSlowPutArrayStorage(JSGlobalData&);
- // The receiver is the prototype in this case. The following:
- //
- // asObject(foo->structure()->storedPrototype())->attemptToInterceptPutByIndexOnHoleForPrototype(...)
- //
- // is equivalent to:
- //
- // foo->attemptToInterceptPutByIndexOnHole(...);
- bool attemptToInterceptPutByIndexOnHoleForPrototype(ExecState*, JSValue thisValue, unsigned propertyName, JSValue, bool shouldThrow);
+ // The receiver is the prototype in this case. The following:
+ //
+ // asObject(foo->structure()->storedPrototype())->attemptToInterceptPutByIndexOnHoleForPrototype(...)
+ //
+ // is equivalent to:
+ //
+ // foo->attemptToInterceptPutByIndexOnHole(...);
+ bool attemptToInterceptPutByIndexOnHoleForPrototype(ExecState*, JSValue thisValue, unsigned propertyName, JSValue, bool shouldThrow);
- // Returns 0 if contiguous storage cannot be created - either because
- // indexing should be sparse or because we're having a bad time.
- WriteBarrier<Unknown>* ensureContiguous(JSGlobalData& globalData)
- {
- if (LIKELY(hasContiguous(structure()->indexingType())))
- return m_butterfly->contiguous();
+ // Returns 0 if contiguous storage cannot be created - either because
+ // indexing should be sparse or because we're having a bad time.
+ WriteBarrier<Unknown>* ensureContiguous(JSGlobalData& globalData)
+ {
+ if (LIKELY(hasContiguous(structure()->indexingType())))
+ return m_butterfly->contiguous();
- return ensureContiguousSlow(globalData);
- }
+ return ensureContiguousSlow(globalData);
+ }
- // Ensure that the object is in a mode where it has array storage. Use
- // this if you're about to perform actions that would have required the
- // object to be converted to have array storage, if it didn't have it
- // already.
- ArrayStorage* ensureArrayStorage(JSGlobalData& globalData)
- {
- if (LIKELY(hasArrayStorage(structure()->indexingType())))
- return m_butterfly->arrayStorage();
+ // Ensure that the object is in a mode where it has array storage. Use
+ // this if you're about to perform actions that would have required the
+ // object to be converted to have array storage, if it didn't have it
+ // already.
+ ArrayStorage* ensureArrayStorage(JSGlobalData& globalData)
+ {
+ if (LIKELY(hasArrayStorage(structure()->indexingType())))
+ return m_butterfly->arrayStorage();
- return ensureArrayStorageSlow(globalData);
- }
+ return ensureArrayStorageSlow(globalData);
+ }
- Butterfly* ensureIndexedStorage(JSGlobalData& globalData)
- {
- if (LIKELY(hasIndexedProperties(structure()->indexingType())))
- return m_butterfly;
+ Butterfly* ensureIndexedStorage(JSGlobalData& globalData)
+ {
+ if (LIKELY(hasIndexedProperties(structure()->indexingType())))
+ return m_butterfly;
- return ensureIndexedStorageSlow(globalData);
- }
+ return ensureIndexedStorageSlow(globalData);
+ }
- static size_t offsetOfInlineStorage();
+ static size_t offsetOfInlineStorage();
- static ptrdiff_t butterflyOffset()
- {
- return OBJECT_OFFSETOF(JSObject, m_butterfly);
- }
+ static ptrdiff_t butterflyOffset()
+ {
+ return OBJECT_OFFSETOF(JSObject, m_butterfly);
+ }
- void* butterflyAddress()
- {
- return &m_butterfly;
- }
+ void* butterflyAddress()
+ {
+ return &m_butterfly;
+ }
- static JS_EXPORTDATA const ClassInfo s_info;
-
- protected:
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- ASSERT(inherits(&s_info));
- ASSERT(!structure()->outOfLineCapacity());
- ASSERT(structure()->isEmpty());
- ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
- ASSERT(structure()->isObject());
- ASSERT(classInfo());
- }
+ static JS_EXPORTDATA const ClassInfo s_info;
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
- }
+protected:
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ ASSERT(inherits(&s_info));
+ ASSERT(!structure()->outOfLineCapacity());
+ ASSERT(structure()->isEmpty());
+ ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
+ ASSERT(structure()->isObject());
+ ASSERT(classInfo());
+ }
- // To instantiate objects you likely want JSFinalObject, below.
- // To create derived types you likely want JSNonFinalObject, below.
- JSObject(JSGlobalData&, Structure*, Butterfly* = 0);
+ static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+ }
+
+ // To instantiate objects you likely want JSFinalObject, below.
+ // To create derived types you likely want JSNonFinalObject, below.
+ JSObject(JSGlobalData&, Structure*, Butterfly* = 0);
- void resetInheritorID(JSGlobalData&);
+ void resetInheritorID(JSGlobalData&);
- void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize);
- void copyButterfly(CopyVisitor&, Butterfly*, size_t storageSize);
-
- // Call this if you know that the object is in a mode where it has array
- // storage. This will assert otherwise.
- ArrayStorage* arrayStorage()
- {
- ASSERT(hasArrayStorage(structure()->indexingType()));
- return m_butterfly->arrayStorage();
- }
+ void visitButterfly(SlotVisitor&, Butterfly*, size_t storageSize);
+ void copyButterfly(CopyVisitor&, Butterfly*, size_t storageSize);
+
+ // Call this if you know that the object is in a mode where it has array
+ // storage. This will assert otherwise.
+ ArrayStorage* arrayStorage()
+ {
+ ASSERT(hasArrayStorage(structure()->indexingType()));
+ return m_butterfly->arrayStorage();
+ }
- // Call this if you want to predicate some actions on whether or not the
- // object is in a mode where it has array storage.
- ArrayStorage* arrayStorageOrNull()
- {
- switch (structure()->indexingType()) {
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage();
+ // Call this if you want to predicate some actions on whether or not the
+ // object is in a mode where it has array storage.
+ ArrayStorage* arrayStorageOrNull()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage();
- default:
- return 0;
- }
+ default:
+ return 0;
}
+ }
- ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength);
- ArrayStorage* createInitialArrayStorage(JSGlobalData&);
- WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition);
- ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&);
+ ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength);
+ ArrayStorage* createInitialArrayStorage(JSGlobalData&);
+ WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length);
+ ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
+ ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&, NonPropertyTransition);
+ ArrayStorage* convertContiguousToArrayStorage(JSGlobalData&);
- ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData&);
+ ArrayStorage* ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData&);
- bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
+ bool defineOwnNonIndexProperty(ExecState*, PropertyName, PropertyDescriptor&, bool throwException);
- void putByIndexBeyondVectorLengthContiguousWithoutAttributes(ExecState*, unsigned propertyName, JSValue);
- void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*);
+ void putByIndexBeyondVectorLengthContiguousWithoutAttributes(ExecState*, unsigned propertyName, JSValue);
+ void putByIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, bool shouldThrow, ArrayStorage*);
- bool increaseVectorLength(JSGlobalData&, unsigned newLength);
- void deallocateSparseIndexMap();
- bool defineOwnIndexedProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
- SparseArrayValueMap* allocateSparseIndexMap(JSGlobalData&);
+ bool increaseVectorLength(JSGlobalData&, unsigned newLength);
+ void deallocateSparseIndexMap();
+ bool defineOwnIndexedProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
+ SparseArrayValueMap* allocateSparseIndexMap(JSGlobalData&);
- void notifyPresenceOfIndexedAccessors(JSGlobalData&);
+ void notifyPresenceOfIndexedAccessors(JSGlobalData&);
- bool attemptToInterceptPutByIndexOnHole(ExecState*, unsigned index, JSValue, bool shouldThrow);
+ bool attemptToInterceptPutByIndexOnHole(ExecState*, unsigned index, JSValue, bool shouldThrow);
- // Call this if you want setIndexQuickly to succeed and you're sure that
- // the array is contiguous.
- void ensureContiguousLength(JSGlobalData& globalData, unsigned length)
- {
- ASSERT(length < MAX_ARRAY_INDEX);
- ASSERT(hasContiguous(structure()->indexingType()));
+ // Call this if you want setIndexQuickly to succeed and you're sure that
+ // the array is contiguous.
+ void ensureContiguousLength(JSGlobalData& globalData, unsigned length)
+ {
+ ASSERT(length < MAX_ARRAY_INDEX);
+ ASSERT(hasContiguous(structure()->indexingType()));
- if (m_butterfly->vectorLength() < length)
- ensureContiguousLengthSlow(globalData, length);
+ if (m_butterfly->vectorLength() < length)
+ ensureContiguousLengthSlow(globalData, length);
- if (m_butterfly->publicLength() < length)
- m_butterfly->setPublicLength(length);
- }
+ if (m_butterfly->publicLength() < length)
+ m_butterfly->setPublicLength(length);
+ }
- unsigned countElementsInContiguous(Butterfly*);
+ unsigned countElementsInContiguous(Butterfly*);
- template<IndexingType indexingType>
- WriteBarrier<Unknown>* indexingData()
- {
- switch (indexingType) {
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- return m_butterfly->contiguous();
+ template<IndexingType indexingType>
+ WriteBarrier<Unknown>* indexingData()
+ {
+ switch (indexingType) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->contiguous();
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return m_butterfly->arrayStorage()->m_vector;
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->m_vector;
- default:
- CRASH();
- return 0;
- }
+ default:
+ CRASH();
+ return 0;
}
+ }
+
+ WriteBarrier<Unknown>* currentIndexingData()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->contiguous();
+
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->m_vector;
+
+ default:
+ CRASH();
+ return 0;
+ }
+ }
- template<IndexingType indexingType>
- unsigned relevantLength()
- {
- switch (indexingType) {
- case ALL_CONTIGUOUS_INDEXING_TYPES:
- return m_butterfly->publicLength();
+ template<IndexingType indexingType>
+ unsigned relevantLength()
+ {
+ switch (indexingType) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->publicLength();
- case ALL_ARRAY_STORAGE_INDEXING_TYPES:
- return std::min(
- m_butterfly->arrayStorage()->length(),
- m_butterfly->arrayStorage()->vectorLength());
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return std::min(
+ m_butterfly->arrayStorage()->length(),
+ m_butterfly->arrayStorage()->vectorLength());
- default:
- CRASH();
- return 0;
- }
+ default:
+ CRASH();
+ return 0;
}
+ }
- private:
- friend class LLIntOffsetsExtractor;
+ unsigned currentRelevantLength()
+ {
+ switch (structure()->indexingType()) {
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->publicLength();
+
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return std::min(
+ m_butterfly->arrayStorage()->length(),
+ m_butterfly->arrayStorage()->vectorLength());
+
+ default:
+ CRASH();
+ return 0;
+ }
+ }
+
+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;
- void getObject();
- void getString(ExecState* exec);
- void isObject();
- void isString();
+ // Nobody should ever ask any of these questions on something already known to be a JSObject.
+ using JSCell::isAPIValueWrapper;
+ using JSCell::isGetterSetter;
+ void getObject();
+ void getString(ExecState* exec);
+ void isObject();
+ void isString();
- ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData&, ArrayStorage*);
+ ArrayStorage* enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(JSGlobalData&, ArrayStorage*);
- template<PutMode>
- bool putDirectInternal(JSGlobalData&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
+ template<PutMode>
+ bool putDirectInternal(JSGlobalData&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
- bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
- JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, PropertyOffset);
+ bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, PropertyOffset);
- const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const;
- Structure* createInheritorID(JSGlobalData&);
+ const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const;
+ Structure* createInheritorID(JSGlobalData&);
- void putIndexedDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
+ void putIndexedDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
- void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
- bool putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode, ArrayStorage*);
- JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode);
+ void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
+ bool putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode, ArrayStorage*);
+ JS_EXPORT_PRIVATE bool putDirectIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue, unsigned attributes, PutDirectIndexMode);
- unsigned getNewVectorLength(unsigned currentVectorLength, unsigned currentLength, unsigned desiredLength);
- unsigned getNewVectorLength(unsigned desiredLength);
+ unsigned getNewVectorLength(unsigned currentVectorLength, unsigned currentLength, unsigned desiredLength);
+ unsigned getNewVectorLength(unsigned desiredLength);
- JS_EXPORT_PRIVATE bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&);
+ JS_EXPORT_PRIVATE bool getOwnPropertySlotSlow(ExecState*, PropertyName, PropertySlot&);
- void ensureContiguousLengthSlow(JSGlobalData&, unsigned length);
+ void ensureContiguousLengthSlow(JSGlobalData&, unsigned length);
- WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&);
- ArrayStorage* ensureArrayStorageSlow(JSGlobalData&);
- Butterfly* ensureIndexedStorageSlow(JSGlobalData&);
+ WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&);
+ ArrayStorage* ensureArrayStorageSlow(JSGlobalData&);
+ Butterfly* ensureIndexedStorageSlow(JSGlobalData&);
- protected:
- Butterfly* m_butterfly;
- };
+protected:
+ Butterfly* m_butterfly;
+};
- // JSNonFinalObject is a type of JSObject that has some internal storage,
- // but also preserves some space in the collector cell for additional
- // data members in derived types.
- class JSNonFinalObject : public JSObject {
- friend class JSObject;
+// JSNonFinalObject is a type of JSObject that has some internal storage,
+// but also preserves some space in the collector cell for additional
+// data members in derived types.
+class JSNonFinalObject : public JSObject {
+ friend class JSObject;
- public:
- typedef JSObject Base;
+public:
+ typedef JSObject Base;
- static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
- {
- return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
- }
+ static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+ }
- protected:
- explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0)
- : JSObject(globalData, structure, butterfly)
- {
- }
+protected:
+ explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure, Butterfly* butterfly = 0)
+ : JSObject(globalData, structure, butterfly)
+ {
+ }
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- ASSERT(!this->structure()->totalStorageCapacity());
- ASSERT(classInfo());
- }
- };
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ ASSERT(!this->structure()->totalStorageCapacity());
+ ASSERT(classInfo());
+ }
+};
- class JSFinalObject;
+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 {
- friend class JSObject;
+// 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 {
+ friend class JSObject;
- public:
- typedef JSObject Base;
+public:
+ typedef JSObject Base;
- 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, NonArray, INLINE_STORAGE_CAPACITY);
- }
+ 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, NonArray, INLINE_STORAGE_CAPACITY);
+ }
- JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
+ JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&);
- static JS_EXPORTDATA const ClassInfo s_info;
+ static JS_EXPORTDATA const ClassInfo s_info;
- protected:
- void visitChildrenCommon(SlotVisitor&);
+protected:
+ void visitChildrenCommon(SlotVisitor&);
- void finishCreation(JSGlobalData& globalData)
- {
- Base::finishCreation(globalData);
- ASSERT(structure()->totalStorageCapacity() == structure()->inlineCapacity());
- ASSERT(classInfo());
- }
+ void finishCreation(JSGlobalData& globalData)
+ {
+ Base::finishCreation(globalData);
+ ASSERT(structure()->totalStorageCapacity() == structure()->inlineCapacity());
+ ASSERT(classInfo());
+ }
- private:
- friend class LLIntOffsetsExtractor;
+private:
+ friend class LLIntOffsetsExtractor;
- explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
- : JSObject(globalData, structure)
- {
- }
+ explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
+ : JSObject(globalData, structure)
+ {
+ }
- static const unsigned StructureFlags = JSObject::StructureFlags;
- };
+ static const unsigned StructureFlags = JSObject::StructureFlags;
+};
inline JSFinalObject* JSFinalObject::create(ExecState* exec, Structure* structure)
{
@@ -902,11 +933,6 @@ inline bool JSObject::isErrorInstance() const
return structure()->typeInfo().type() == ErrorInstanceType;
}
-inline bool JSObject::isProxy() const
-{
- return structure()->typeInfo().type() == ProxyType;
-}
-
inline void JSObject::setButterfly(JSGlobalData& globalData, Butterfly* butterfly, Structure* structure)
{
ASSERT(structure);
diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp
index 508a90540..8651a76ba 100644
--- a/Source/JavaScriptCore/runtime/JSScope.cpp
+++ b/Source/JavaScriptCore/runtime/JSScope.cpp
@@ -334,11 +334,14 @@ template <JSScope::LookupMode mode, JSScope::ReturnValues returnValues> JSObject
ASSERT(variableObject);
ASSERT(variableObject->symbolTable());
SymbolTableEntry entry = variableObject->symbolTable()->get(identifier.impl());
- // Variable was actually inserted by eval
+ // Defend against the variable being actually inserted by eval.
if (entry.isNull()) {
ASSERT(!jsDynamicCast<JSNameScope*>(variableObject));
goto fail;
}
+ // If we're getting the 'arguments' then give up on life.
+ if (identifier == callFrame->propertyNames().arguments)
+ goto fail;
if (putToBaseOperation) {
putToBaseOperation->m_kind = entry.isReadOnly() ? PutToBaseOperation::Readonly : PutToBaseOperation::VariablePut;
diff --git a/Source/JavaScriptCore/runtime/JSType.h b/Source/JavaScriptCore/runtime/JSType.h
index 03f4a7790..10d98d2bd 100644
--- a/Source/JavaScriptCore/runtime/JSType.h
+++ b/Source/JavaScriptCore/runtime/JSType.h
@@ -41,6 +41,11 @@ enum JSType {
ProgramExecutableType,
FunctionExecutableType,
+ UnlinkedFunctionExecutableType,
+ UnlinkedProgramCodeBlockType,
+ UnlinkedEvalCodeBlockType,
+ UnlinkedFunctionCodeBlockType,
+
// The ObjectType value must come before any JSType that is a subclass of JSObject.
ObjectType,
FinalObjectType,
diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h
index d9b3585a0..6f63260fe 100644
--- a/Source/JavaScriptCore/runtime/JSTypeInfo.h
+++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h
@@ -55,7 +55,7 @@ namespace JSC {
, m_flags2(flags >> 8)
{
ASSERT(flags <= 0x3ff);
- ASSERT(type <= 0xff);
+ ASSERT(static_cast<int>(type) <= 0xff);
ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren));
// No object that doesn't ImplementsHasInstance should override it!
ASSERT((m_flags & (ImplementsHasInstance | OverridesHasInstance)) != OverridesHasInstance);
diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp
index a5cdf700b..e7f8cad17 100644
--- a/Source/JavaScriptCore/runtime/JSValue.cpp
+++ b/Source/JavaScriptCore/runtime/JSValue.cpp
@@ -62,7 +62,7 @@ double JSValue::toNumberSlowCase(ExecState* exec) const
return asCell()->toNumber(exec);
if (isTrue())
return 1.0;
- return isUndefined() ? std::numeric_limits<double>::quiet_NaN() : 0; // null and false both convert to 0.
+ return isUndefined() ? QNaN : 0; // null and false both convert to 0.
}
JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h
index 7b5c81aa9..bd9b90466 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -35,6 +35,10 @@
namespace JSC {
+// This is used a lot throughout JavaScriptCore for everything from value boxing to marking
+// values as being missing, so it is useful to have it abbreviated.
+#define QNaN (std::numeric_limits<double>::quiet_NaN())
+
class ExecState;
class JSCell;
class JSGlobalData;
diff --git a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
index 52b747890..224982e9e 100644
--- a/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
+++ b/Source/JavaScriptCore/runtime/JSValueInlineMethods.h
@@ -62,7 +62,7 @@ namespace JSC {
inline JSValue jsNaN()
{
- return JSValue(std::numeric_limits<double>::quiet_NaN());
+ return JSValue(QNaN);
}
inline JSValue::JSValue(char i)
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index 2f4df375a..7634487ad 100644
--- a/Source/JavaScriptCore/runtime/MathObject.cpp
+++ b/Source/JavaScriptCore/runtime/MathObject.cpp
@@ -175,7 +175,7 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
for (unsigned k = 0; k < argsCount; ++k) {
double val = exec->argument(k).toNumber(exec);
if (isnan(val)) {
- result = std::numeric_limits<double>::quiet_NaN();
+ result = QNaN;
break;
}
if (val > result || (val == 0 && result == 0 && !signbit(val)))
@@ -191,7 +191,7 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
for (unsigned k = 0; k < argsCount; ++k) {
double val = exec->argument(k).toNumber(exec);
if (isnan(val)) {
- result = std::numeric_limits<double>::quiet_NaN();
+ result = QNaN;
break;
}
if (val < result || (val == 0 && result == 0 && signbit(val)))
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index 30ba0b27d..01df7e98c 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -24,6 +24,7 @@
#include "ExceptionHelpers.h"
#include "Interpreter.h"
+#include "JSProxy.h"
#include "JSString.h"
#include "JSValueInlineMethods.h"
@@ -297,19 +298,24 @@ namespace JSC {
return jsAddSlowCase(callFrame, v1, v2);
}
+#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
+
inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
{
JSCell* cell = base.asCell();
size_t count = 0;
while (slotBase != cell) {
+ if (cell->isProxy())
+ return InvalidPrototypeChain;
+
JSValue v = cell->structure()->prototypeForLookup(callFrame);
// If we didn't find slotBase in base's prototype chain, then base
// must be a proxy for another object.
if (v.isNull())
- return 0;
+ return InvalidPrototypeChain;
cell = v.asCell();
@@ -332,6 +338,9 @@ namespace JSC {
{
size_t count = 0;
while (1) {
+ if (base->isProxy())
+ return InvalidPrototypeChain;
+
JSValue v = base->structure()->prototypeForLookup(callFrame);
if (v.isNull())
return count;
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index dfbf533f7..35de40912 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -178,11 +178,34 @@ JSValue regExpObjectMultiline(ExecState*, JSValue slotBase, PropertyName)
return jsBoolean(asRegExpObject(slotBase)->regExp()->multiline());
}
-JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
+template <typename CharacterType>
+static inline void appendLineTerminatorEscape(StringBuilder&, CharacterType);
+
+template <>
+inline void appendLineTerminatorEscape<LChar>(StringBuilder& builder, LChar lineTerminator)
+{
+ if (lineTerminator == '\n')
+ builder.append('n');
+ else
+ builder.append('r');
+}
+
+template <>
+inline void appendLineTerminatorEscape<UChar>(StringBuilder& builder, UChar lineTerminator)
+{
+ if (lineTerminator == '\n')
+ builder.append('n');
+ else if (lineTerminator == '\r')
+ builder.append('r');
+ else if (lineTerminator == 0x2028)
+ builder.appendLiteral("u2028");
+ else
+ builder.appendLiteral("u2029");
+}
+
+template <typename CharacterType>
+static inline JSValue regExpObjectSourceInternal(ExecState* exec, String pattern, const CharacterType* characters, unsigned length)
{
- String pattern = asRegExpObject(slotBase)->regExp()->pattern();
- unsigned length = pattern.length();
- const UChar* characters = pattern.characters();
bool previousCharacterWasBackslash = false;
bool inBrackets = false;
bool shouldEscape = false;
@@ -197,7 +220,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
// early return for strings that don't contain a forwards slash and LineTerminator
for (unsigned i = 0; i < length; ++i) {
- UChar ch = characters[i];
+ CharacterType ch = characters[i];
if (!previousCharacterWasBackslash) {
if (inBrackets) {
if (ch == ']')
@@ -212,7 +235,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
}
}
- if (Lexer<UChar>::isLineTerminator(ch)) {
+ if (Lexer<CharacterType>::isLineTerminator(ch)) {
shouldEscape = true;
break;
}
@@ -230,7 +253,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
inBrackets = false;
StringBuilder result;
for (unsigned i = 0; i < length; ++i) {
- UChar ch = characters[i];
+ CharacterType ch = characters[i];
if (!previousCharacterWasBackslash) {
if (inBrackets) {
if (ch == ']')
@@ -244,18 +267,11 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
}
// escape LineTerminator
- if (Lexer<UChar>::isLineTerminator(ch)) {
+ if (Lexer<CharacterType>::isLineTerminator(ch)) {
if (!previousCharacterWasBackslash)
result.append('\\');
- if (ch == '\n')
- result.append('n');
- else if (ch == '\r')
- result.append('r');
- else if (ch == 0x2028)
- result.appendLiteral("u2028");
- else
- result.appendLiteral("u2029");
+ appendLineTerminatorEscape<CharacterType>(result, ch);
} else
result.append(ch);
@@ -268,6 +284,14 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
return jsString(exec, result.toString());
}
+JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, PropertyName)
+{
+ String pattern = asRegExpObject(slotBase)->regExp()->pattern();
+ if (pattern.is8Bit())
+ return regExpObjectSourceInternal(exec, pattern, pattern.characters8(), pattern.length());
+ return regExpObjectSourceInternal(exec, pattern, pattern.characters16(), pattern.length());
+}
+
void RegExpObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
if (propertyName == exec->propertyNames().lastIndex) {
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 4d3ccfda2..5aafe8bb3 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -666,7 +666,7 @@ static inline EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString*
String leftPart(StringImpl::create(stringImpl, 0, matchStart));
size_t matchEnd = matchStart + searchString.impl()->length();
- int ovector[2] = { matchStart, matchEnd};
+ int ovector[2] = { static_cast<int>(matchStart), static_cast<int>(matchEnd)};
String middlePart = substituteBackreferences(replaceString, string, ovector, 0);
size_t leftLength = stringImpl->length() - matchEnd;
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index a931def27..e733c7e23 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -543,6 +543,15 @@ Structure* Structure::nonPropertyTransition(JSGlobalData& globalData, Structure*
unsigned attributes = toAttributes(transitionKind);
IndexingType indexingType = newIndexingType(structure->indexingTypeIncludingHistory(), transitionKind);
+ JSGlobalObject* globalObject = structure->globalObject();
+ if (structure == globalObject->arrayStructure()) {
+ Structure* transition = globalObject->arrayStructureWithArrayStorage();
+ if (transition->indexingTypeIncludingHistory() == indexingType) {
+ structure->notifyTransitionFromThisStructure();
+ return transition;
+ }
+ }
+
if (Structure* existingTransition = structure->m_transitionTable.get(0, attributes)) {
ASSERT(existingTransition->m_attributesInPrevious == attributes);
ASSERT(existingTransition->indexingTypeIncludingHistory() == indexingType);
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 5f1299766..2b25803a6 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -521,6 +521,11 @@ namespace JSC {
return m_structure->typeInfo().type() == GetterSetterType;
}
+ inline bool JSCell::isProxy() const
+ {
+ return structure()->typeInfo().type() == ProxyType;
+ }
+
inline bool JSCell::isAPIValueWrapper() const
{
return m_structure->typeInfo().type() == APIValueWrapperType;
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index debb76499..87d1c8be5 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -337,7 +337,7 @@ namespace JSC {
struct SymbolTableIndexHashTraits : HashTraits<SymbolTableEntry> {
static const bool emptyValueIsZero = true;
- static const bool needsDestruction = false;
+ static const bool needsDestruction = true;
};
typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable;