summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
authorLeon Clarke <leonclarke@google.com>2010-07-15 12:03:35 +0100
committerLeon Clarke <leonclarke@google.com>2010-07-20 16:57:23 +0100
commite458d70a0d18538346f41b503114c9ebe6b2ce12 (patch)
tree86f1637deca2c524432a822e5fcedd4bef221091 /JavaScriptCore/runtime
parentf43eabc081f7ce6af24b9df4953498a3cd6ca24d (diff)
downloadexternal_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.zip
external_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.tar.gz
external_webkit-e458d70a0d18538346f41b503114c9ebe6b2ce12.tar.bz2
Merge WebKit at r63173 : Initial merge by git.
Change-Id: Ife5af0c7c6261fbbc8ae6bc08c390efa9ef10b44
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/Arguments.h4
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp12
-rw-r--r--JavaScriptCore/runtime/DatePrototype.cpp2
-rw-r--r--JavaScriptCore/runtime/Executable.cpp64
-rw-r--r--JavaScriptCore/runtime/Executable.h18
-rw-r--r--JavaScriptCore/runtime/JSArray.cpp2
-rw-r--r--JavaScriptCore/runtime/JSFunction.cpp3
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp16
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h10
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp24
-rw-r--r--JavaScriptCore/runtime/JSGlobalObjectFunctions.h3
-rw-r--r--JavaScriptCore/runtime/JSObject.h12
-rw-r--r--JavaScriptCore/runtime/JSValue.h1
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpObject.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp4
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.h6
-rw-r--r--JavaScriptCore/runtime/SmallStrings.cpp9
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp34
-rw-r--r--JavaScriptCore/runtime/UString.cpp137
20 files changed, 265 insertions, 102 deletions
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
index 6bb180c..d892de0 100644
--- a/JavaScriptCore/runtime/Arguments.h
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -139,7 +139,7 @@ namespace JSC {
inline Arguments::Arguments(CallFrame* callFrame)
: JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
- , d(new ArgumentsData)
+ , d(adoptPtr(new ArgumentsData))
{
JSFunction* callee;
ptrdiff_t firstParameterIndex;
@@ -176,7 +176,7 @@ namespace JSC {
inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
: JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
- , d(new ArgumentsData)
+ , d(adoptPtr(new ArgumentsData))
{
ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 9407be7..2cb04ff 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -76,8 +76,16 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
#if ENABLE(JIT)
// If the JIT is enabled then we need to preserve the invariant that every
// function with a CodeBlock also has JIT code.
- callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain);
- CodeBlock* codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
+ CodeBlock* codeBlock = 0;
+#if ENABLE(INTERPRETER)
+ if (!exec->globalData().canUseJIT())
+ codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
+ else
+#endif
+ {
+ callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain);
+ codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
+ }
#else
CodeBlock* codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
#endif
diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp
index f8d2224..9dec33b 100644
--- a/JavaScriptCore/runtime/DatePrototype.cpp
+++ b/JavaScriptCore/runtime/DatePrototype.cpp
@@ -411,7 +411,7 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
setUTCFullYear dateProtoFuncSetUTCFullYear DontEnum|Function 3
setYear dateProtoFuncSetYear DontEnum|Function 1
getYear dateProtoFuncGetYear DontEnum|Function 0
- toJSON dateProtoFuncToJSON DontEnum|Function 0
+ toJSON dateProtoFuncToJSON DontEnum|Function 1
@end
*/
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index f33f3b4..355ee86 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -77,7 +77,7 @@ JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNod
ASSERT(!m_evalCodeBlock);
m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth());
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock)));
generator->generate();
evalNode->destroyData();
@@ -112,7 +112,7 @@ JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChain
ASSERT(!m_programCodeBlock);
m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider());
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock)));
generator->generate();
programNode->destroyData();
@@ -135,7 +135,7 @@ bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNo
ASSERT(!m_codeBlockForCall);
m_codeBlockForCall = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), false);
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall)));
generator->generate();
m_numParametersForCall = m_codeBlockForCall->m_numParameters;
ASSERT(m_numParametersForCall);
@@ -162,7 +162,7 @@ bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh
ASSERT(!m_codeBlockForConstruct);
m_codeBlockForConstruct = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), true);
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct)));
generator->generate();
m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
ASSERT(m_numParametersForConstruct);
@@ -177,6 +177,9 @@ bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh
void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+#if ENABLE(INTERPRETER)
+ ASSERT(exec->globalData().canUseJIT());
+#endif
CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock);
@@ -188,6 +191,9 @@ void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChain
void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+#if ENABLE(INTERPRETER)
+ ASSERT(exec->globalData().canUseJIT());
+#endif
CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock);
@@ -199,6 +205,9 @@ void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeCh
void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+#if ENABLE(INTERPRETER)
+ ASSERT(exec->globalData().canUseJIT());
+#endif
CodeBlock* codeBlock = bytecodeForCall(exec, scopeChainNode);
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForCallWithArityCheck);
@@ -210,6 +219,9 @@ void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode*
void FunctionExecutable::generateJITCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
+#if ENABLE(INTERPRETER)
+ ASSERT(exec->globalData().canUseJIT());
+#endif
CodeBlock* codeBlock = bytecodeForConstruct(exec, scopeChainNode);
m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForConstructWithArityCheck);
@@ -229,11 +241,11 @@ void FunctionExecutable::markAggregate(MarkStack& markStack)
m_codeBlockForConstruct->markAggregate(markStack);
}
-ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
if (!newFunctionBody)
- return 0;
+ return PassOwnPtr<ExceptionInfo>();
if (m_forceUsesArguments)
newFunctionBody->setUsesArguments();
newFunctionBody->finishParsing(m_parameters, m_name);
@@ -241,18 +253,23 @@ ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData
ScopeChain scopeChain(scopeChainNode);
JSGlobalObject* globalObject = scopeChain.globalObject();
- OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), codeBlock->m_isConstructor));
+ OwnPtr<CodeBlock> newCodeBlock(adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), codeBlock->m_isConstructor)));
globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())));
generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock));
generator->generate();
ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
#if ENABLE(JIT)
- JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
- ASSERT(codeBlock->m_isConstructor ? newJITCode.size() == generatedJITCodeForConstruct().size() : newJITCode.size() == generatedJITCodeForCall().size());
+#if ENABLE(INTERPRETER)
+ if (globalData->canUseJIT())
+#endif
+ {
+ JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+ ASSERT(codeBlock->m_isConstructor ? newJITCode.size() == generatedJITCodeForConstruct().size() : newJITCode.size() == generatedJITCodeForCall().size());
+ }
#endif
globalData->functionCodeBlockBeingReparsed = 0;
@@ -260,26 +277,31 @@ ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData
return newCodeBlock->extractExceptionInfo();
}
-ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
if (!newEvalBody)
- return 0;
+ return PassOwnPtr<ExceptionInfo>();
ScopeChain scopeChain(scopeChainNode);
JSGlobalObject* globalObject = scopeChain.globalObject();
- OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+ OwnPtr<EvalCodeBlock> newCodeBlock(adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())));
- OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
+ OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())));
generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock));
generator->generate();
ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
#if ENABLE(JIT)
- JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
- ASSERT(newJITCode.size() == generatedJITCodeForCall().size());
+#if ENABLE(INTERPRETER)
+ if (globalData->canUseJIT())
+#endif
+ {
+ JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
+ ASSERT(newJITCode.size() == generatedJITCodeForCall().size());
+ }
#endif
return newCodeBlock->extractExceptionInfo();
@@ -334,6 +356,10 @@ UString FunctionExecutable::paramString() const
return builder.build();
}
-};
-
+PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*)
+{
+ // CodeBlocks for program code are transient and therefore do not gain from from throwing out their exception information.
+ return PassOwnPtr<ExceptionInfo>();
+}
+}
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
index 3320fe1..516d6ce 100644
--- a/JavaScriptCore/runtime/Executable.h
+++ b/JavaScriptCore/runtime/Executable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@
#include "Interpreter.h"
#include "Nodes.h"
#include "SamplingTool.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
@@ -171,7 +172,7 @@ namespace JSC {
bool usesArguments() const { return m_features & ArgumentsFeature; }
bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
- virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
+ virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
protected:
void recordParse(CodeFeatures features, int firstLine, int lastLine)
@@ -203,7 +204,6 @@ namespace JSC {
JSObject* compile(ExecState*, ScopeChainNode*);
- ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
private:
@@ -212,6 +212,9 @@ namespace JSC {
, m_evalCodeBlock(0)
{
}
+
+ virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+
EvalCodeBlock* m_evalCodeBlock;
#if ENABLE(JIT)
@@ -249,15 +252,15 @@ namespace JSC {
JSObject* checkSyntax(ExecState*);
JSObject* compile(ExecState*, ScopeChainNode*);
- // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
- ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }
-
private:
ProgramExecutable(ExecState* exec, const SourceCode& source)
: ScriptExecutable(exec, source)
, m_programCodeBlock(0)
{
}
+
+ virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+
ProgramCodeBlock* m_programCodeBlock;
#if ENABLE(JIT)
@@ -350,7 +353,6 @@ namespace JSC {
SharedSymbolTable* symbolTable() const { return m_symbolTable; }
void recompile(ExecState*);
- ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
void markAggregate(MarkStack& markStack);
static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
@@ -386,6 +388,8 @@ namespace JSC {
bool compileForCall(ExecState*, ScopeChainNode*);
bool compileForConstruct(ExecState*, ScopeChainNode*);
+ virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
+
unsigned m_numVariables : 31;
bool m_forceUsesArguments : 1;
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
index 78667cd..362f89b 100644
--- a/JavaScriptCore/runtime/JSArray.cpp
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -847,7 +847,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));
if (callType == CallTypeJS)
- tree.abstractor().m_cachedCall.set(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot()));
+ tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot()));
if (!tree.abstractor().m_nodes.begin()) {
throwOutOfMemoryError(exec);
diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp
index 7fcd037..49cc8fa 100644
--- a/JavaScriptCore/runtime/JSFunction.cpp
+++ b/JavaScriptCore/runtime/JSFunction.cpp
@@ -42,13 +42,14 @@ using namespace WTF;
using namespace Unicode;
namespace JSC {
-
+#if ENABLE(JIT)
EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
{
CodeBlock* codeBlock = exec->callerFrame()->codeBlock();
unsigned vPCIndex = codeBlock->bytecodeOffset(exec, exec->returnPC());
return throwVMError(exec, createNotAConstructorError(exec, exec->callee(), vPCIndex, codeBlock));
}
+#endif
ASSERT_CLASS_FITS_IN_CELL(JSFunction);
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 30a5ef9..1508750 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -58,6 +58,7 @@
#if PLATFORM(MAC)
#include "ProfilerServer.h"
+#include <CoreFoundation/CoreFoundation.h>
#endif
using namespace WTF;
@@ -156,6 +157,19 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
#if PLATFORM(MAC)
startProfilerServerIfNeeded();
#endif
+#if ENABLE(JIT) && ENABLE(INTERPRETER)
+#if PLATFORM(MAC)
+ CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
+ CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
+ m_canUseJIT = kCFBooleanTrue == canUseJIT;
+ CFRelease(canUseJIT);
+ CFRelease(canUseJITKey);
+#elif OS(UNIX)
+ m_canUseJIT = !getenv("JSC_FORCE_INTERPRETER");
+#else
+ m_canUseJIT = true;
+#endif
+#endif
}
JSGlobalData::~JSGlobalData()
@@ -228,7 +242,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
{
JSGlobalData*& instance = sharedInstanceInternal();
if (!instance) {
- instance = new JSGlobalData(APIShared, ThreadStackTypeSmall);
+ instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
#if ENABLE(JSC_MULTIPLE_THREADS)
instance->makeUsableFromMultipleThreads();
#endif
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index f99c8d6..f3f6cba 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -167,6 +167,13 @@ namespace JSC {
ExecutableAllocator executableAllocator;
#endif
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ bool canUseJIT() { return m_canUseJIT; }
+#endif
+#else
+ bool canUseJIT() { return false; }
+#endif
Lexer* lexer;
Parser* parser;
Interpreter* interpreter;
@@ -233,6 +240,9 @@ namespace JSC {
JSGlobalData(GlobalDataType, ThreadStackType);
static JSGlobalData*& sharedInstanceInternal();
void createNativeThunk();
+#if ENABLE(JIT) && ENABLE(INTERPRETER)
+ bool m_canUseJIT;
+#endif
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index f625323..d88d6a9 100644
--- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -141,6 +141,7 @@ static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
bool isStrWhiteSpace(UChar c)
{
switch (c) {
+ // ECMA-262-5th 7.2 & 7.3
case 0x0009:
case 0x000A:
case 0x000B:
@@ -150,6 +151,7 @@ bool isStrWhiteSpace(UChar c)
case 0x00A0:
case 0x2028:
case 0x2029:
+ case 0xFEFF:
return true;
default:
return c > 0xff && isSeparatorSpace(c);
@@ -194,6 +196,28 @@ double parseIntOverflow(const char* s, int length, int radix)
return number;
}
+double parseIntOverflow(const UChar* s, int length, int radix)
+{
+ double number = 0.0;
+ double radixMultiplier = 1.0;
+
+ for (const UChar* p = s + length - 1; p >= s; p--) {
+ if (radixMultiplier == Inf) {
+ if (*p != '0') {
+ number = Inf;
+ break;
+ }
+ } else {
+ int digit = parseDigit(*p, radix);
+ number += digit * radixMultiplier;
+ }
+
+ radixMultiplier *= radix;
+ }
+
+ return number;
+}
+
static double parseInt(const UString& s, int radix)
{
int length = s.size();
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
index 91dfca8..e634fae 100644
--- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
* Copyright (C) 2007 Maks Orlovich
*
@@ -53,6 +53,7 @@ namespace JSC {
static const double mantissaOverflowLowerBound = 9007199254740992.0;
double parseIntOverflow(const char*, int length, int radix);
+ double parseIntOverflow(const UChar*, int length, int radix);
bool isStrWhiteSpace(UChar);
} // namespace JSC
diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h
index edd376c..4201703 100644
--- a/JavaScriptCore/runtime/JSObject.h
+++ b/JavaScriptCore/runtime/JSObject.h
@@ -177,6 +177,7 @@ namespace JSC {
void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
+ void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&);
void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
@@ -590,6 +591,11 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, u
putDirectInternal(propertyName, value, attributes, false, slot, 0);
}
+inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ putDirectInternal(propertyName, value, 0, false, slot, 0);
+}
+
inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
{
putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value);
@@ -692,6 +698,12 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu
asCell()->put(exec, propertyName, value, slot);
}
+inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ ASSERT(isCell() && isObject());
+ asObject(asCell())->putDirect(propertyName, value, slot);
+}
+
inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
{
if (UNLIKELY(!isCell())) {
diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h
index 9190f70..3c6bc09 100644
--- a/JavaScriptCore/runtime/JSValue.h
+++ b/JavaScriptCore/runtime/JSValue.h
@@ -181,6 +181,7 @@ namespace JSC {
JSValue get(ExecState*, unsigned propertyName) const;
JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
+ void putDirect(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
void put(ExecState*, unsigned propertyName, JSValue);
bool needsThisConversion() const;
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index 166a021..fa2a1e2 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -35,6 +35,7 @@
#include "RegExpPrototype.h"
#include "RegExp.h"
#include "RegExpCache.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
@@ -95,7 +96,7 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
: InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "RegExp"))
- , d(new RegExpConstructorPrivate)
+ , d(adoptPtr(new RegExpConstructorPrivate))
{
// ECMA 15.10.5.1 RegExp.prototype
putDirectWithoutTransition(exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp
index 4824944..0f2c1e1 100644
--- a/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/JavaScriptCore/runtime/RegExpObject.cpp
@@ -29,6 +29,7 @@
#include "Lookup.h"
#include "RegExpConstructor.h"
#include "RegExpPrototype.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
@@ -61,7 +62,7 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
: JSObjectWithGlobalObject(globalObject, structure)
- , d(new RegExpObjectData(regExp, 0))
+ , d(adoptPtr(new RegExpObjectData(regExp, 0)))
{
}
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index 834412b..ac215ec 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -46,10 +46,8 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
// ECMA 15.10.5
-const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
-
RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
- : JSObject(structure)
+ : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", ""))
{
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, globalObject, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
diff --git a/JavaScriptCore/runtime/RegExpPrototype.h b/JavaScriptCore/runtime/RegExpPrototype.h
index 77c1ea7..eb4ae00 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.h
+++ b/JavaScriptCore/runtime/RegExpPrototype.h
@@ -21,16 +21,14 @@
#ifndef RegExpPrototype_h
#define RegExpPrototype_h
+#include "RegExpObject.h"
#include "JSObject.h"
namespace JSC {
- class RegExpPrototype : public JSObject {
+ class RegExpPrototype : public RegExpObject {
public:
RegExpPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
-
- virtual const ClassInfo* classInfo() const { return &info; }
- static const ClassInfo info;
};
} // namespace JSC
diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp
index 0f5df4a..822303c 100644
--- a/JavaScriptCore/runtime/SmallStrings.cpp
+++ b/JavaScriptCore/runtime/SmallStrings.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,10 +28,11 @@
#include "JSGlobalObject.h"
#include "JSString.h"
-
#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
namespace JSC {
+
static const unsigned numCharactersToStore = 0x100;
static inline bool isMarked(JSString* string)
@@ -126,7 +127,7 @@ void SmallStrings::createEmptyString(JSGlobalData* globalData)
void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
{
if (!m_storage)
- m_storage.set(new SmallStringsStorage);
+ m_storage = adoptPtr(new SmallStringsStorage);
ASSERT(!m_singleCharacterStrings[character]);
m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner);
}
@@ -134,7 +135,7 @@ void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigne
UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character)
{
if (!m_storage)
- m_storage.set(new SmallStringsStorage);
+ m_storage = adoptPtr(new SmallStringsStorage);
return m_storage->rep(character);
}
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index 8b56d53..fb6e0f3 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -466,6 +466,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
unsigned len = s.size();
JSValue a0 = exec->argument(0);
@@ -484,6 +486,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
unsigned len = s.size();
JSValue a0 = exec->argument(0);
@@ -508,13 +512,16 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
? jsString(exec, asString(thisValue), asString(v))
: jsString(exec, asString(thisValue), v.toString(exec)));
}
-
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
return JSValue::encode(jsString(exec, thisValue));
}
EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
int len = s.size();
@@ -544,6 +551,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
int len = s.size();
@@ -571,6 +580,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
JSValue a0 = exec->argument(0);
@@ -623,6 +634,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
JSValue a0 = exec->argument(0);
@@ -649,6 +662,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
int len = s.size();
@@ -674,6 +689,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
JSValue a0 = exec->argument(0);
@@ -738,6 +755,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
int len = s.size();
@@ -761,6 +780,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
UString s = thisValue.toThisString(exec);
int len = s.size();
@@ -793,6 +814,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
JSString* sVal = thisValue.toThisJSString(exec);
const UString& s = sVal->value(exec);
@@ -831,6 +854,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
{
JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
JSString* sVal = thisValue.toThisJSString(exec);
const UString& s = sVal->value(exec);
@@ -868,10 +893,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
{
- JSValue thisValue = exec->hostThisValue();
if (exec->argumentCount() < 1)
return JSValue::encode(jsNumber(exec, 0));
+ JSValue thisValue = exec->hostThisValue();
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwVMTypeError(exec);
+
UString s = thisValue.toThisString(exec);
JSValue a0 = exec->argument(0);
return JSValue::encode(jsNumber(exec, localeCompare(s, a0.toString(exec))));
@@ -1045,6 +1073,8 @@ static inline bool isTrimWhitespace(UChar c)
static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind)
{
+ if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+ return throwTypeError(exec);
UString str = thisValue.toThisString(exec);
unsigned left = 0;
if (trimKind & TrimLeft) {
diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp
index 5a6a644..c442500 100644
--- a/JavaScriptCore/runtime/UString.cpp
+++ b/JavaScriptCore/runtime/UString.cpp
@@ -242,13 +242,33 @@ UChar UString::operator[](unsigned pos) const
return data()[pos];
}
+static inline bool isInfinity(double number)
+{
+ return number == Inf || number == -Inf;
+}
+
+static bool isInfinity(const UChar* data, const UChar* end)
+{
+ return data + 7 < end
+ && data[0] == 'I'
+ && data[1] == 'n'
+ && data[2] == 'f'
+ && data[3] == 'i'
+ && data[4] == 'n'
+ && data[5] == 'i'
+ && data[6] == 't'
+ && data[7] == 'y';
+}
+
double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
{
- if (size() == 1) {
+ unsigned size = this->size();
+
+ if (size == 1) {
UChar c = data()[0];
if (isASCIIDigit(c))
return c - '0';
- if (isASCIISpace(c) && tolerateEmptyString)
+ if (isStrWhiteSpace(c) && tolerateEmptyString)
return 0;
return NaN;
}
@@ -264,77 +284,90 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co
// need to skip all StrWhiteSpace. The isStrWhiteSpace function does the
// right thing but requires UChar, not char, for its argument.
- CString s = UTF8String();
- if (s.isNull())
- return NaN;
- const char* c = s.data();
+ const UChar* data = this->data();
+ const UChar* end = data + size;
- // skip leading white space
- while (isASCIISpace(*c))
- c++;
+ // Skip leading white space.
+ for (; data < end; ++data) {
+ if (!isStrWhiteSpace(*data))
+ break;
+ }
- // empty string ?
- if (*c == '\0')
+ // Empty string.
+ if (data == end)
return tolerateEmptyString ? 0.0 : NaN;
- double d;
-
- // hex number ?
- if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
- const char* firstDigitPosition = c + 2;
- c++;
- d = 0.0;
- while (*(++c)) {
- if (*c >= '0' && *c <= '9')
- d = d * 16.0 + *c - '0';
- else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
- d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
- else
+ double number;
+
+ if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2])) {
+ // Hex number.
+ data += 2;
+ const UChar* firstDigitPosition = data;
+ number = 0;
+ while (true) {
+ number = number * 16 + toASCIIHexValue(*data);
+ ++data;
+ if (data == end)
+ break;
+ if (!isASCIIHexDigit(*data))
break;
}
-
- if (d >= mantissaOverflowLowerBound)
- d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
+ if (number >= mantissaOverflowLowerBound)
+ number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16);
} else {
- // regular number ?
- char* end;
- d = WTF::strtod(c, &end);
- if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
- c = end;
- } else {
- double sign = 1.0;
-
- if (*c == '+')
- c++;
- else if (*c == '-') {
- sign = -1.0;
- c++;
- }
+ // Decimal number.
+
+ // Put into a null-terminated byte buffer.
+ Vector<char, 32> byteBuffer;
+ for (const UChar* characters = data; characters < end; ++characters) {
+ UChar character = *characters;
+ byteBuffer.append(isASCII(character) ? character : 0);
+ }
+ byteBuffer.append(0);
+ char* byteBufferEnd;
+ number = WTF::strtod(byteBuffer.data(), &byteBufferEnd);
+ const UChar* pastNumber = data + (byteBufferEnd - byteBuffer.data());
+
+ if ((number || pastNumber != data) && !isInfinity(number))
+ data = pastNumber;
+ else {
// We used strtod() to do the conversion. However, strtod() handles
// infinite values slightly differently than JavaScript in that it
// converts the string "inf" with any capitalization to infinity,
// whereas the ECMA spec requires that it be converted to NaN.
- if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
- d = sign * Inf;
- c += 8;
- } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
- c = end;
+ double signedInfinity = Inf;
+ if (data < end) {
+ if (*data == '+')
+ data++;
+ else if (*data == '-') {
+ signedInfinity = -Inf;
+ data++;
+ }
+ }
+ if (isInfinity(data, end)) {
+ number = signedInfinity;
+ data += 8;
+ } else if (isInfinity(number) && data < end && (*data | 0x20) != 'i')
+ data = pastNumber;
else
return NaN;
}
}
+ // Look for trailing junk.
if (!tolerateTrailingJunk) {
- // allow trailing white space
- while (isASCIISpace(*c))
- c++;
- if (c != s.data() + s.length())
- d = NaN;
+ // Allow trailing white space.
+ for (; data < end; ++data) {
+ if (!isStrWhiteSpace(*data))
+ break;
+ }
+ if (data != end)
+ return NaN;
}
- return d;
+ return number;
}
double UString::toDouble(bool tolerateTrailingJunk) const