summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore')
-rw-r--r--JavaScriptCore/API/JSCallbackObject.h5
-rw-r--r--JavaScriptCore/API/JSCallbackObjectFunctions.h4
-rw-r--r--JavaScriptCore/ChangeLog824
-rw-r--r--JavaScriptCore/Configurations/FeatureDefines.xcconfig5
-rw-r--r--JavaScriptCore/Configurations/JavaScriptCore.xcconfig2
-rw-r--r--JavaScriptCore/GNUmakefile.am10
-rw-r--r--JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops4
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.cpp23
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.h26
-rw-r--r--JavaScriptCore/bytecode/Instruction.h2
-rw-r--r--JavaScriptCore/bytecode/Opcode.h10
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.cpp21
-rw-r--r--JavaScriptCore/bytecompiler/BytecodeGenerator.h1
-rw-r--r--JavaScriptCore/bytecompiler/NodesCodegen.cpp2
-rw-r--r--JavaScriptCore/interpreter/CallFrame.h5
-rw-r--r--JavaScriptCore/interpreter/Interpreter.cpp273
-rw-r--r--JavaScriptCore/interpreter/Interpreter.h10
-rw-r--r--JavaScriptCore/jit/ExecutableAllocator.cpp36
-rw-r--r--JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp30
-rw-r--r--JavaScriptCore/jit/ExecutableAllocatorPosix.cpp42
-rw-r--r--JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp2
-rw-r--r--JavaScriptCore/jit/ExecutableAllocatorWin.cpp2
-rw-r--r--JavaScriptCore/jit/JIT.h49
-rw-r--r--JavaScriptCore/jit/JITPropertyAccess.cpp20
-rw-r--r--JavaScriptCore/jit/JITPropertyAccess32_64.cpp23
-rw-r--r--JavaScriptCore/jit/JITStubs.cpp63
-rw-r--r--JavaScriptCore/jit/JITStubs.h5
-rw-r--r--JavaScriptCore/parser/ASTBuilder.h37
-rw-r--r--JavaScriptCore/parser/JSParser.cpp349
-rw-r--r--JavaScriptCore/parser/JSParser.h179
-rw-r--r--JavaScriptCore/parser/Lexer.cpp344
-rw-r--r--JavaScriptCore/parser/Lexer.h21
-rw-r--r--JavaScriptCore/parser/Nodes.cpp2
-rw-r--r--JavaScriptCore/parser/Nodes.h3
-rw-r--r--JavaScriptCore/parser/Parser.cpp2
-rw-r--r--JavaScriptCore/parser/ParserArena.cpp5
-rw-r--r--JavaScriptCore/parser/SourceProvider.h5
-rw-r--r--JavaScriptCore/parser/SyntaxChecker.h51
-rw-r--r--JavaScriptCore/qt/ChangeLog97
-rw-r--r--JavaScriptCore/qt/api/qscriptconverter_p.h14
-rw-r--r--JavaScriptCore/qt/api/qscriptengine_p.cpp21
-rw-r--r--JavaScriptCore/qt/api/qscriptengine_p.h12
-rw-r--r--JavaScriptCore/qt/api/qscriptstring_p.h12
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.cpp112
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue.h30
-rw-r--r--JavaScriptCore/qt/api/qscriptvalue_p.h282
-rw-r--r--JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp33
-rw-r--r--JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp684
-rw-r--r--JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h10
-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
-rw-r--r--JavaScriptCore/wtf/CrossThreadRefCounted.h11
-rw-r--r--JavaScriptCore/wtf/MessageQueue.h6
-rw-r--r--JavaScriptCore/wtf/OwnArrayPtr.h25
-rw-r--r--JavaScriptCore/wtf/OwnPtr.h99
-rw-r--r--JavaScriptCore/wtf/PassOwnPtr.h107
-rw-r--r--JavaScriptCore/wtf/PassRefPtr.h27
-rw-r--r--JavaScriptCore/wtf/Platform.h26
-rw-r--r--JavaScriptCore/wtf/RefCounted.h22
-rw-r--r--JavaScriptCore/wtf/RefPtr.h11
-rw-r--r--JavaScriptCore/wtf/RetainPtr.h2
-rw-r--r--JavaScriptCore/wtf/SizeLimits.cpp3
-rw-r--r--JavaScriptCore/wtf/StringExtras.h4
-rw-r--r--JavaScriptCore/wtf/TCSystemAlloc.cpp1
-rw-r--r--JavaScriptCore/wtf/Vector.h13
-rw-r--r--JavaScriptCore/wtf/gobject/GOwnPtr.h3
-rw-r--r--JavaScriptCore/wtf/gobject/GRefPtr.h5
-rw-r--r--JavaScriptCore/wtf/text/WTFString.cpp2
-rw-r--r--JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp11
-rw-r--r--JavaScriptCore/yarr/RegexInterpreter.cpp13
-rw-r--r--JavaScriptCore/yarr/RegexInterpreter.h7
89 files changed, 3635 insertions, 934 deletions
diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h
index dfb9fa2..cf42818 100644
--- a/JavaScriptCore/API/JSCallbackObject.h
+++ b/JavaScriptCore/API/JSCallbackObject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
#include "JSObjectRef.h"
#include "JSValueRef.h"
#include "JSObject.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
@@ -56,7 +57,7 @@ struct JSCallbackObjectData {
void setPrivateProperty(const Identifier& propertyName, JSValue value)
{
if (!m_privateProperties)
- m_privateProperties.set(new JSPrivatePropertyMap);
+ m_privateProperties = adoptPtr(new JSPrivatePropertyMap);
m_privateProperties->setPrivateProperty(propertyName, value);
}
diff --git a/JavaScriptCore/API/JSCallbackObjectFunctions.h b/JavaScriptCore/API/JSCallbackObjectFunctions.h
index 3a15bbe..9a3e448 100644
--- a/JavaScriptCore/API/JSCallbackObjectFunctions.h
+++ b/JavaScriptCore/API/JSCallbackObjectFunctions.h
@@ -52,7 +52,7 @@ inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue
template <class Base>
JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
: Base(globalObject, structure)
- , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
+ , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data, jsClass)))
{
init(exec);
}
@@ -62,7 +62,7 @@ JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSGlobalObject* global
template <class Base>
JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass, NonNullPassRefPtr<Structure> structure)
: Base(structure)
- , m_callbackObjectData(new JSCallbackObjectData(0, jsClass))
+ , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass)))
{
ASSERT(Base::isGlobalObject());
init(static_cast<JSGlobalObject*>(this)->globalExec());
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index c6cbd6d..0acccc8 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,827 @@
+2010-07-09 Darin Adler <darin@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ String to number coercion is not spec compliant
+ https://bugs.webkit.org/show_bug.cgi?id=31349
+
+ ToNumber should ignore NBSP (\u00a0)
+ https://bugs.webkit.org/show_bug.cgi?id=25490
+
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::parseIntOverflow): Added a version that works on UChar.
+ * runtime/JSGlobalObjectFunctions.h: Ditto.
+
+ * runtime/UString.cpp:
+ (JSC::isInfinity): Added helper functions.
+ (JSC::UString::toDouble): Use isStrWhiteSpace instead of
+ isSASCIISpace to define what we should skip. Got rid of the
+ code that used CString and UTF8String, instead processing the
+ UChar of the string directly, except for when we call strtod.
+ For strtod, use our own home-grown conversion function that
+ does not try to do any UTF-16 processing. Tidied up the logic
+ a bit as well.
+
+2010-07-12 Martin Robinson <mrobinson@igalia.com>
+
+ Reviewed by Xan Lopez.
+
+ [GTK] make dist is broken because of missing headers and other miscellaneous reasons
+ https://bugs.webkit.org/show_bug.cgi?id=42107
+
+ * GNUmakefile.am: Add missing header to the sources list.
+
+2010-07-12 Adam Roben <aroben@apple.com>
+
+ Stop generating stripped symbols for Release builds
+
+ It turns out we can strip the symbols after-the-fact using PDBCopy.
+
+ Fixes <http://webkit.org/b/42085>.
+
+ Reviewed by Steve Falkenburg.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops:
+ Removed the pre-link event, which just created the public\sym
+ directory.
+
+2010-07-12 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Dan Bernstein.
+
+ Add WARN_UNUSED_RETURN to the smart pointer "leak" member functions
+ https://bugs.webkit.org/show_bug.cgi?id=42086
+
+ * wtf/OwnPtr.h:
+ * wtf/PassOwnPtr.h:
+ * wtf/PassRefPtr.h:
+ (WTF::PassRefPtr::releaseRef):
+ (WTF::NonNullPassRefPtr::leakRef):
+ (WTF::NonNullPassRefPtr::releaseRef):
+ * wtf/RetainPtr.h:
+ (WTF::RetainPtr::releaseRef):
+
+2010-07-10 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ HAVE_COMPUTED_GOTO is dependent on the interpreter being enabled
+ https://bugs.webkit.org/show_bug.cgi?id=42039
+
+ Separate the existence of computed goto support in the compiler
+ from whether or not we are using the interpreter. All the current
+ HAVE(COMPUTED_GOTO) guards are for the interpreter, but I'd like
+ the option of using it elsewhere. The interpreter now uses
+ ENABLE(COMPUTED_GOTO_INTERPRETER)
+
+ * bytecode/Instruction.h:
+ (JSC::Instruction::Instruction):
+ * bytecode/Opcode.h:
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::Interpreter):
+ (JSC::Interpreter::isOpcode):
+ (JSC::Interpreter::privateExecute):
+ * interpreter/Interpreter.h:
+ (JSC::Interpreter::getOpcode):
+ (JSC::Interpreter::getOpcodeID):
+ * wtf/Platform.h:
+
+2010-07-10 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Gavin Barraclough.
+
+ Remove switches from inner expression loops in the parser
+ https://bugs.webkit.org/show_bug.cgi?id=42035
+
+ Use bitmasks and flags on the token types to identify unary and
+ binary operators, rather than switching on the token type to
+ identify them.
+
+ * parser/JSParser.cpp:
+ (JSC::isUnaryOp):
+ (JSC::JSParser::isBinaryOperator):
+ * parser/JSParser.h:
+ (JSC::):
+
+2010-07-09 Leon Clarke <leonclarke@google.com>
+
+ Reviewed by Adam Barth.
+
+ add support for link prefetching
+ https://bugs.webkit.org/show_bug.cgi?id=3652
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2010-07-09 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Tidy up lexer token ids
+ https://bugs.webkit.org/show_bug.cgi?id=42014
+
+ Stop using character literals to identify single character tokens
+ and instead use symbolic names for all tokens.
+
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::makeBinaryNode):
+ * parser/JSParser.cpp:
+ (JSC::JSParser::consume):
+ (JSC::JSParser::match):
+ (JSC::JSParser::autoSemiColon):
+ (JSC::JSParser::JSParser):
+ (JSC::JSParser::parseProgram):
+ (JSC::JSParser::allowAutomaticSemicolon):
+ (JSC::JSParser::parseDoWhileStatement):
+ (JSC::JSParser::parseWhileStatement):
+ (JSC::JSParser::parseVarDeclarationList):
+ (JSC::JSParser::parseConstDeclarationList):
+ (JSC::JSParser::parseForStatement):
+ (JSC::JSParser::parseReturnStatement):
+ (JSC::JSParser::parseWithStatement):
+ (JSC::JSParser::parseSwitchStatement):
+ (JSC::JSParser::parseSwitchClauses):
+ (JSC::JSParser::parseSwitchDefaultClause):
+ (JSC::JSParser::parseTryStatement):
+ (JSC::JSParser::parseDebuggerStatement):
+ (JSC::JSParser::parseStatement):
+ (JSC::JSParser::parseFormalParameters):
+ (JSC::JSParser::parseFunctionInfo):
+ (JSC::JSParser::parseExpressionOrLabelStatement):
+ (JSC::JSParser::parseIfStatement):
+ (JSC::JSParser::parseExpression):
+ (JSC::JSParser::parseAssignmentExpression):
+ (JSC::JSParser::parseConditionalExpression):
+ (JSC::isUnaryOp):
+ (JSC::JSParser::isBinaryOperator):
+ (JSC::JSParser::parseBinaryExpression):
+ (JSC::JSParser::parseProperty):
+ (JSC::JSParser::parseObjectLiteral):
+ (JSC::JSParser::parseStrictObjectLiteral):
+ (JSC::JSParser::parseArrayLiteral):
+ (JSC::JSParser::parsePrimaryExpression):
+ (JSC::JSParser::parseArguments):
+ (JSC::JSParser::parseMemberExpression):
+ (JSC::JSParser::parseUnaryExpression):
+ * parser/JSParser.h:
+ (JSC::):
+ * parser/Lexer.cpp:
+ (JSC::):
+ (JSC::Lexer::lex):
+ * parser/Lexer.h:
+
+2010-07-09 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Bug 42015 - Enable JSValue32_64 on ARMv7
+
+ * Configurations/JavaScriptCore.xcconfig:
+ * jit/JIT.h:
+ * jit/JITStubs.cpp:
+ * wtf/Platform.h:
+
+2010-07-09 Kenneth Russell <kbr@google.com>
+
+ Reviewed by Dimitri Glazkov.
+
+ Assertion failure in String::utf8() for certain invalid UTF16 inputs
+ https://bugs.webkit.org/show_bug.cgi?id=41983
+
+ * wtf/text/WTFString.cpp:
+ (WebCore::String::utf8):
+ - Fixed assertion when sourceExhausted is returned from convertUTF16ToUTF8.
+
+2010-07-09 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Remove a couple of excess writes from the lexer
+ https://bugs.webkit.org/show_bug.cgi?id=41981
+
+ Remove a couple of fields from JSTokenInfo, and rename the remaining ones
+ to something more accurate
+
+ * parser/JSParser.cpp:
+ (JSC::JSParser::next):
+ (JSC::JSParser::tokenStart):
+ (JSC::JSParser::tokenLine):
+ (JSC::JSParser::tokenEnd):
+ * parser/JSParser.h:
+ (JSC::JSTokenInfo::JSTokenInfo):
+ * parser/Lexer.cpp:
+ (JSC::Lexer::lex):
+
+2010-07-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Property declarations in an object literal should not consider the prototype chain when being added to the new object
+ https://bugs.webkit.org/show_bug.cgi?id=41929
+
+ To fix this all we need to do is ensure that all new properties are
+ added with putDirect rather than a fully generic call to put. This
+ is safe as an object literal is by definition going to produce a
+ completely normal object.
+
+ Rather than duplicating all the put_by_id logic we add an additional
+ flag to op_put_by_id to indicate it should be using putDirect. In
+ the interpreter this adds a runtime branch, but in the jit this is
+ essentially free as the branch is taken at compile time. This does
+ actually improve object literal creation time even in the interpreter
+ as we no longer need to walk the prototype chain to verify that the
+ cached put is safe.
+
+ We still emit normal put_by_id code when emitting __proto__ as we want
+ to get the correct handling for changing the prototype.
+
+ Sunspider claims this is a 0.7% speedup which is conceivably real due
+ to the performance improvement in object literals, but I suspect its
+ really just the result of code motion.
+
+ * bytecode/Opcode.h:
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitPutById):
+ (JSC::BytecodeGenerator::emitDirectPutById):
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::PropertyListNode::emitBytecode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.h:
+ (JSC::JIT::compilePutByIdTransition):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_put_by_id):
+ (JSC::JIT::emitSlow_op_put_by_id):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::patchPutByIdReplace):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emitSlow_op_put_by_id):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::patchPutByIdReplace):
+ * jit/JITStubs.cpp:
+ (JSC::JITThunks::tryCachePutByID):
+ (JSC::DEFINE_STUB_FUNCTION):
+ * jit/JITStubs.h:
+ (JSC::):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ * runtime/JSObject.h:
+ (JSC::JSObject::putDirect):
+ (JSC::JSValue::putDirect):
+ * runtime/JSValue.h:
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ String.prototype methods should CheckObjectCoercible (test this is not null or undefined).
+
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncCharAt):
+ (JSC::stringProtoFuncCharCodeAt):
+ (JSC::stringProtoFuncConcat):
+ (JSC::stringProtoFuncIndexOf):
+ (JSC::stringProtoFuncLastIndexOf):
+ (JSC::stringProtoFuncMatch):
+ (JSC::stringProtoFuncSearch):
+ (JSC::stringProtoFuncSlice):
+ (JSC::stringProtoFuncSplit):
+ (JSC::stringProtoFuncSubstr):
+ (JSC::stringProtoFuncSubstring):
+ (JSC::stringProtoFuncToLowerCase):
+ (JSC::stringProtoFuncToUpperCase):
+ (JSC::stringProtoFuncLocaleCompare):
+ (JSC::trimString):
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Date.prototype.toJSON takes one argument, report this correctly.
+
+ * runtime/DatePrototype.cpp:
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ RegExp's prototype should be an object of type RegExp.
+
+ * runtime/RegExpPrototype.cpp:
+ (JSC::RegExpPrototype::RegExpPrototype):
+ * runtime/RegExpPrototype.h:
+
+2010-07-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Gavin Barraclough.
+
+ JavaScript parser violates ECMA automatic semicolon insertion rule
+ https://bugs.webkit.org/show_bug.cgi?id=41844
+
+ Remove (very) old and bogus logic that automatically inserted a semicolon
+ at the end of a script's source.
+
+ * parser/Lexer.cpp:
+ (JSC::Lexer::lex):
+
+2010-07-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Anders Carlson.
+
+ Tidy up the lexer
+
+ Remove some of the old yacc/lex-isms still present in the lexer
+
+ * parser/JSParser.h:
+ (JSC::):
+ * parser/Lexer.cpp:
+ (JSC::Lexer::parseString):
+ (JSC::Lexer::lex):
+ * parser/Lexer.h:
+
+2010-07-08 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Gavin Barraclough.
+
+ Make object-literal parsing conformant with the spec.
+ https://bugs.webkit.org/show_bug.cgi?id=41892
+
+ Bring our parsing of object literals into conformance with the ES5 spec.
+ Basically disallow conflicting accessor vs. normal property definitions
+ The bulk of this patch is just fiddling to maintain performance.
+
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ (JSC::ASTBuilder::createProperty):
+ (JSC::ASTBuilder::getName):
+ (JSC::ASTBuilder::getType):
+ * parser/JSParser.cpp:
+ (JSC::jsParse):
+ (JSC::JSParser::JSParser):
+ (JSC::JSParser::parseProperty):
+ (JSC::JSParser::parseObjectLiteral):
+ (JSC::JSParser::parseStrictObjectLiteral):
+ * parser/JSParser.h:
+ * parser/Lexer.cpp:
+ (JSC::Lexer::clear):
+ * parser/Lexer.h:
+ (JSC::Lexer::currentOffset):
+ (JSC::Lexer::setOffset):
+ Add logic to allow us to roll the lexer back in the input stream.
+ * parser/Nodes.h:
+ (JSC::PropertyNode::):
+ (JSC::PropertyNode::type):
+ * parser/Parser.cpp:
+ (JSC::Parser::parse):
+ * parser/SourceProvider.h:
+ (JSC::SourceProvider::SourceProvider):
+ (JSC::SourceProvider::isValid):
+ (JSC::SourceProvider::setValid):
+ SourceProvider now records whether the input text
+ has already been validated.
+ * parser/SyntaxChecker.h:
+ (JSC::SyntaxChecker::SyntaxChecker):
+ (JSC::SyntaxChecker::Property::Property):
+ (JSC::SyntaxChecker::Property::operator!):
+ (JSC::SyntaxChecker::createProperty):
+ (JSC::SyntaxChecker::createPropertyList):
+ (JSC::SyntaxChecker::createGetterOrSetterProperty):
+ The SyntaxChecker mode now needs to maintain a bit more information
+ to ensure that we can validate object literals correctly.
+
+2010-07-08 Darin Adler <darin@apple.com>
+
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::sharedInstance): Fix typo.
+
+2010-07-08 Darin Adler <darin@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Fix assertion seen on the Leopard buildbot.
+ The single shared instance of JSGlobalData was not being
+ adopted after creation.
+
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::sharedInstance): Do adoptRef and then leakRef.
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ BOMs are whitespace.
+
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::isStrWhiteSpace):
+
+2010-07-08 Martin Robinson <mrobinson@igalia.com>
+
+ Unreviewed.
+
+ Try fix the GTK+ build by touching this file.
+
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ GTK build fix take two.
+
+ * GNUmakefile.am:
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ GTK build fix.
+
+ * GNUmakefile.am:
+
+2010-07-08 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ https://bugs.webkit.org/show_bug.cgi?id=41641
+
+ Update compile flags to allow use of ExecutableAllocatorFixedVMPool on platforms
+ other than x86-64 (this may be useful on 32-bit platforms, too).
+
+ Simplify ifdefs by dividing into thwo broad allocation strategies
+ (ENABLE_EXECUTABLE_ALLOCATOR_FIXED & ENABLE_EXECUTABLE_ALLOCATOR_DEMAND).
+
+ Rename constant used in the code to have names descriptive of their purpose,
+ rather than their specific value on a given platform.
+
+ * jit/ExecutableAllocator.cpp:
+ (JSC::ExecutableAllocator::reprotectRegion):
+ (JSC::ExecutableAllocator::cacheFlush):
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
+ (JSC::FixedVMPoolAllocator::free):
+ (JSC::ExecutablePool::systemAlloc):
+ * jit/ExecutableAllocatorPosix.cpp:
+ * jit/ExecutableAllocatorSymbian.cpp:
+ * jit/ExecutableAllocatorWin.cpp:
+ * wtf/Platform.h:
+
+2010-07-08 Xan Lopez <xlopez@igalia.com>
+
+ Reviewed by Gustavo Noronha.
+
+ Silence a few noisy build rules.
+
+ * GNUmakefile.am:
+
+2010-07-08 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r62765.
+ http://trac.webkit.org/changeset/62765
+ https://bugs.webkit.org/show_bug.cgi?id=41840
+
+ All jscore and layout tests crash on Qt bot (Requested by Ossy
+ on #webkit).
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::initializeScavenger):
+ (WTF::TCMalloc_PageHeap::signalScavenger):
+ (WTF::TCMalloc_PageHeap::scavengerThread):
+
+2010-07-08 Andreas Kling <andreas.kling@nokia.com>
+
+ Reviewed by Oliver Hunt.
+
+ Interpreter: Crash in op_load_varargs on 64-bit
+ https://bugs.webkit.org/show_bug.cgi?id=41795
+
+ Added missing cast of argCount to int32_t in op_load_varargs.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+
+2010-07-08 Patrick Gansterer <paroga@paroga.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Make FastMalloc more portable.
+ https://bugs.webkit.org/show_bug.cgi?id=41790
+
+ Use WTF::Mutex instead of pthread_mutex_t and
+ replace pthread_cond_t with WTF::ThreadCondition.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::initializeScavenger):
+ (WTF::TCMalloc_PageHeap::signalScavenger):
+ (WTF::TCMalloc_PageHeap::scavengerThread):
+
+2010-07-08 Patrick Gansterer <paroga@paroga.com>
+
+ Reviewed by Darin Adler.
+
+ Remove needless #include <fcntl.h> from TCSystemAlloc.cpp.
+ https://bugs.webkit.org/show_bug.cgi?id=41777
+
+ * wtf/TCSystemAlloc.cpp:
+
+2010-07-07 Darin Adler <darin@apple.com>
+
+ Fixed build in configurations like PowerPC.
+
+ * runtime/RegExpConstructor.cpp: Added include of PassOwnPtr.h.
+ * runtime/RegExpObject.cpp: Ditto.
+ * wtf/SizeLimits.cpp: Changed compile time assertion to work
+ even on platforms where two bool members do not end up taking
+ the same size as one int member!
+
+2010-07-07 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ Lazy mode of parser allows invalid syntax in object literals.
+ https://bugs.webkit.org/show_bug.cgi?id=41809
+
+ Make the parser itself validate getter and setter syntax rather
+ than offloading it to the AST builder.
+
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::createGetterOrSetterProperty):
+ * parser/JSParser.cpp:
+ (JSC::JSParser::parseProperty):
+
+2010-07-07 Dumitru Daniliuc <dumi@chromium.org>
+
+ Reviewed by Adam Roben.
+
+ Revert r62689.
+ https://bugs.webkit.org/show_bug.cgi?id=41804
+
+ * runtime/Collector.cpp:
+ (JSC::Heap::freeBlocks):
+
+2010-07-07 Adam Barth <abarth@webkit.org>
+
+ Reviewed by Sam Weinig.
+
+ Add reverseFind to Vector and deploy in HTML5 parser
+ https://bugs.webkit.org/show_bug.cgi?id=41778
+
+ This method seems generally useful. I'm slightly surprised we don't
+ have it already.
+
+ * wtf/Vector.h:
+ (WTF::::reverseFind):
+
+2010-07-07 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam Barth.
+
+ Turn on adoptRef assertion for RefCounted
+ https://bugs.webkit.org/show_bug.cgi?id=41547
+
+ * wtf/CrossThreadRefCounted.h: Fixed include style. Includes of other
+ WTF headers should use "" includes; consistent in most WTF headers.
+ Added a call to relaxAdoptionRequirement.
+
+ * wtf/RefCounted.h: Fixed include style. Removed LOOSE_REF_COUNTED.
+ Added relaxAdoptionRequirement.
+
+2010-07-07 Anders Carlsson <andersca@apple.com>
+
+ Try to fix the Windows build.
+
+ * runtime/Collector.cpp:
+ (JSC::Heap::freeBlocks):
+
+2010-07-07 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam Barth.
+
+ More OwnPtr work
+ https://bugs.webkit.org/show_bug.cgi?id=41727
+
+ * API/JSCallbackObject.h:
+ (JSC::JSCallbackObjectData::setPrivateProperty): Use adoptPtr.
+ * API/JSCallbackObjectFunctions.h:
+ (JSC::JSCallbackObject::JSCallbackObject): Ditto.
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::CodeBlock): Ditto.
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::createRareDataIfNecessary): Ditto.
+ * parser/Nodes.cpp:
+ (JSC::ScopeNode::ScopeNode): Ditto.
+ * parser/ParserArena.cpp:
+ (JSC::ParserArena::ParserArena): Ditto.
+ * runtime/Arguments.h:
+ (JSC::Arguments::Arguments): Ditto.
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::compile): Ditto.
+ (JSC::ProgramExecutable::compile): Ditto.
+ (JSC::FunctionExecutable::compileForCall): Ditto.
+ (JSC::FunctionExecutable::compileForConstruct): Ditto.
+ (JSC::FunctionExecutable::reparseExceptionInfo): Ditto.
+ (JSC::EvalExecutable::reparseExceptionInfo): Ditto.
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::sort): Ditto.
+ * runtime/RegExpConstructor.cpp:
+ (JSC::RegExpConstructor::RegExpConstructor): Ditto.
+ * runtime/RegExpObject.cpp:
+ (JSC::RegExpObject::RegExpObject): Ditto.
+ * runtime/SmallStrings.cpp:
+ (JSC::SmallStrings::createSingleCharacterString): Ditto.
+ (JSC::SmallStrings::singleCharacterStringRep): Ditto.
+
+ * wtf/unicode/icu/CollatorICU.cpp:
+ (WTF::Collator::userDefault): Use adoptPtr.
+ * yarr/RegexInterpreter.cpp:
+ (JSC::Yarr::ByteCompiler::ByteCompiler): Ditto.
+ (JSC::Yarr::ByteCompiler::compile): Ditto.
+ (JSC::Yarr::ByteCompiler::regexBegin): Ditto.
+ (JSC::Yarr::byteCompileRegex): Ditto.
+ * yarr/RegexInterpreter.h:
+ (JSC::Yarr::BytecodePattern::BytecodePattern): Ditto.
+
+2010-07-07 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam Barth.
+
+ Make clear set the pointer to 0 before deletion
+ https://bugs.webkit.org/show_bug.cgi?id=41727
+
+ * wtf/OwnArrayPtr.h: Changed code so we always set the pointer to its new
+ value before deleting the old one, including in the set function and the
+ clear function. This required changing safeDelete.
+ * wtf/OwnPtr.h: Ditto. Also removed some extra null checks.
+ * wtf/PassOwnPtr.h: Ditto.
+
+ * wtf/PassRefPtr.h: Changed code so we always set the pointer to its new
+ value before deref'ing the old one in the clear function. Also added a
+ leakRef function for NonNullPassRefPtr.
+ * wtf/RefPtr.h: Ditto.
+
+ * wtf/gobject/GOwnPtr.h: More of the same.
+ * wtf/gobject/GRefPtr.h: Ditto.
+
+2010-07-07 Zoltan Herczeg <zherczeg@webkit.org>
+
+ Reviewed by Oliver Hunt.
+
+ Refactored string parsing inside the lexer
+ https://bugs.webkit.org/show_bug.cgi?id=41606
+
+ Does not use goto. Although the last sunspider
+ parse-only tests yields 1.044x speedup, I think the
+ patch can have a slight improvement at most.
+
+ * parser/Lexer.cpp:
+ (JSC::singleEscape):
+ (JSC::Lexer::parseString):
+ (JSC::Lexer::lex):
+ * parser/Lexer.h:
+
+2010-07-06 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Maciej Stachowiak.
+
+ Make it possible to have both the JIT and Interpreter available in a single build
+ https://bugs.webkit.org/show_bug.cgi?id=41722
+
+ Separate the concept of !ENABLE(JIT) and ENABLE(INTERPRETER) and make it possible
+ to have both JIT and INTERPRETER enabled at the same time. This doesn't add
+ support for mix mode execution, but it does allow a single build to contain all
+ the code needed to use either the interpreter or the jit.
+
+ If both ENABLE(INTERPRETER) and ENABLE(JIT) are true then setting the environment
+ variable JSC_FORCE_INTERPRETER will force JSC to use the interpreter.
+
+ This patch basically consists of replacing !ENABLE(JIT) with ENABLE(INTERPRETER),
+ or converting #if ENABLE(JIT) ... #else ... into #if ENABLE(JIT) ... #endif
+ #if ENABLE(INTERPRETER), etc. There are also a few functions that need to be
+ renamed to resolve return type ambiguity.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::~CodeBlock):
+ (JSC::CodeBlock::shrinkToFit):
+ * bytecode/CodeBlock.h:
+ * interpreter/CallFrame.h:
+ (JSC::ExecState::returnVPC):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::unwindCallFrame):
+ (JSC::Interpreter::throwException):
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::prepareForRepeatCall):
+ (JSC::Interpreter::privateExecute):
+ (JSC::Interpreter::retrieveLastCaller):
+ * interpreter/Interpreter.h:
+ * runtime/ArrayPrototype.cpp:
+ (JSC::isNumericCompareFunction):
+ * runtime/Executable.cpp:
+ (JSC::EvalExecutable::generateJITCode):
+ (JSC::ProgramExecutable::generateJITCode):
+ (JSC::FunctionExecutable::generateJITCodeForCall):
+ (JSC::FunctionExecutable::generateJITCodeForConstruct):
+ (JSC::FunctionExecutable::reparseExceptionInfo):
+ (JSC::EvalExecutable::reparseExceptionInfo):
+ * runtime/JSFunction.cpp:
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::JSGlobalData):
+ * runtime/JSGlobalData.h:
+ (JSC::JSGlobalData::canUseJIT):
+ * wtf/Platform.h:
+
+2010-07-06 Darin Adler <darin@apple.com>
+
+ Reviewed by Adam Barth.
+
+ Add adoptPtr and leakPtr functions for OwnPtr and PassOwnPtr
+ https://bugs.webkit.org/show_bug.cgi?id=41320
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): Use assignment
+ instead of set since the result of reparseExceptionInfo is now a
+ PassOwnPtr.
+
+ * bytecode/CodeBlock.h: Change extractExceptionInfo to return a
+ PassOwnPtr instead of a raw pointer.
+
+ * runtime/Executable.cpp:
+ (JSC::FunctionExecutable::reparseExceptionInfo): Return a PassOwnPtr.
+ (JSC::EvalExecutable::reparseExceptionInfo): Ditto.
+ (JSC::ProgramExecutable::reparseExceptionInfo): Added. This was
+ in the header before, but it's better to not have it there to reduce
+ header dependencies. Return a PassOwnPtr.
+
+ * runtime/Executable.h: Made reparseExceptionInfo return a PassOwnPtr,
+ and put it in the private sections of classes other than the base class.
+
+ * wtf/MessageQueue.h:
+ (WTF::MessageQueue::append): Use leakPtr instead of release.
+ (WTF::MessageQueue::appendAndCheckEmpty): Ditto.
+ (WTF::MessageQueue::prepend): Ditto.
+
+ * wtf/OwnPtr.h: Tweaked formatting. Changed the release function to return
+ a PassOwnPtr rather than a raw pointer. Added a leakPtr function that
+ returns a raw pointer. Put the constructor that takes a raw pointer and
+ the set function into a section guarded by LOOSE_OWN_PTR. Adapted to the
+ new adoptPtr function from PassOwnPtr.h.
+
+ * wtf/PassOwnPtr.h: Tweaked formatting. Renamed the release function
+ to leakPtr. Added an adoptPtr function that creates a new PassOwnPtr.
+ Put the constructor and assignment operators that take a raw pointer
+ into a section guarded by LOOSE_PASS_OWN_PTR.
+
+2010-07-06 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Darin Adler
+
+ Update comment in StringExtras.h to be more accurate.
+
+ * wtf/StringExtras.h:
+
+2010-07-06 Sheriff Bot <webkit.review.bot@gmail.com>
+
+ Unreviewed, rolling out r62511.
+ http://trac.webkit.org/changeset/62511
+ https://bugs.webkit.org/show_bug.cgi?id=41686
+
+ Breaks Linux/64bit compilation (Requested by xan_ on #webkit).
+
+ * jit/ExecutableAllocator.cpp:
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
+ (JSC::FixedVMPoolAllocator::free):
+ (JSC::ExecutablePool::systemAlloc):
+ * jit/ExecutableAllocatorPosix.cpp:
+ (JSC::ExecutableAllocator::reprotectRegion):
+ (JSC::ExecutableAllocator::cacheFlush):
+ * jit/ExecutableAllocatorSymbian.cpp:
+ * jit/ExecutableAllocatorWin.cpp:
+ * wtf/Platform.h:
+
+2010-07-05 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ https://bugs.webkit.org/show_bug.cgi?id=41641
+
+ Update compile flags to allow use of ExecutableAllocatorFixedVMPool on platforms
+ other than x86-64 (this may be useful on 32-bit platforms, too).
+
+ Simplify ifdefs by dividing into thwo broad allocation strategies
+ (ENABLE_EXECUTABLE_ALLOCATOR_FIXED & ENABLE_EXECUTABLE_ALLOCATOR_DEMAND).
+
+ Rename constant used in the code to have names descriptive of their purpose,
+ rather than their specific value on a given platform.
+
+ * jit/ExecutableAllocator.cpp:
+ (JSC::ExecutableAllocator::reprotectRegion):
+ (JSC::ExecutableAllocator::cacheFlush):
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
+ (JSC::FixedVMPoolAllocator::free):
+ (JSC::ExecutablePool::systemAlloc):
+ * jit/ExecutableAllocatorPosix.cpp:
+ * jit/ExecutableAllocatorSymbian.cpp:
+ * jit/ExecutableAllocatorWin.cpp:
+ * wtf/Platform.h:
+
2010-07-05 Steve Block <steveblock@google.com>
Reviewed by Darin Adler.
diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index 8f86fc3..9a3ec0b 100644
--- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -31,6 +31,8 @@
// Set any ENABLE_FEATURE_NAME macro to an empty string to disable that feature.
+ENABLE_LINK_PREFETCH = ;
+
ENABLE_3D_CANVAS = $(ENABLE_3D_CANVAS_$(TARGET_MAC_OS_X_VERSION_MAJOR));
ENABLE_3D_CANVAS_1050 = ENABLE_3D_CANVAS;
ENABLE_3D_CANVAS_1060 = ENABLE_3D_CANVAS;
@@ -84,5 +86,4 @@ ENABLE_XHTMLMP = ;
ENABLE_XPATH = ENABLE_XPATH;
ENABLE_XSLT = ENABLE_XSLT;
-FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_READER) $(ENABLE_FILE_WRITER) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
-
+FEATURE_DEFINES = $(ENABLE_LINK_PREFETCH) $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_READER) $(ENABLE_FILE_WRITER) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_IMAGE_RESIZER) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_SPEECH) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_METER_TAG) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT);
diff --git a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
index 8c2f26d..5db3e00 100644
--- a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
+++ b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig
@@ -27,7 +27,7 @@
JSVALUE_MODEL = $(JSVALUE_MODEL_$(CURRENT_ARCH));
JSVALUE_MODEL_ = UNKNOWN_JSVALUE_MODEL;
JSVALUE_MODEL_armv6 = 32;
-JSVALUE_MODEL_armv7 = 32;
+JSVALUE_MODEL_armv7 = 32_64;
JSVALUE_MODEL_i386 = 32_64;
JSVALUE_MODEL_ppc = 32_64;
JSVALUE_MODEL_ppc64 = 32;
diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am
index aefc4fb..28cff47 100644
--- a/JavaScriptCore/GNUmakefile.am
+++ b/JavaScriptCore/GNUmakefile.am
@@ -423,6 +423,7 @@ javascriptcore_sources += \
JavaScriptCore/wtf/FastAllocBase.h \
JavaScriptCore/wtf/FastMalloc.cpp \
JavaScriptCore/wtf/FastMalloc.h \
+ JavaScriptCore/wtf/FixedArray.h \
JavaScriptCore/wtf/Forward.h \
JavaScriptCore/wtf/GetPtr.h \
JavaScriptCore/wtf/gobject/GOwnPtr.cpp \
@@ -529,6 +530,7 @@ javascriptcore_sources += \
JavaScriptCore/runtime/MarkStackWin.cpp
else
javascriptcore_sources += \
+ JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp \
JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \
JavaScriptCore/runtime/MarkStackPosix.cpp
endif
@@ -553,16 +555,16 @@ javascriptcore_sources += \
endif
JavaScriptCore/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser/Keywords.table
- $(PERL) $^ > $@
+ $(AM_V_GEN)$(PERL) $^ > $@
JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp
- $(PERL) $^ -i > $@
+ $(AM_V_GEN)$(PERL) $^ -i > $@
JavaScriptCore/RegExpJitTables.h: $(srcdir)/JavaScriptCore/create_regex_tables
- $(PYTHON) $(CREATE_REGEXP_TABLES) > $@
+ $(AM_V_GEN)$(PYTHON) $(CREATE_REGEXP_TABLES) > $@
JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables
- $(PERL) $^ $@
+ $(AM_V_GEN)$(PERL) $^ $@
bin_PROGRAMS += \
Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
index e940511..ad81c36 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops
@@ -23,8 +23,4 @@
Name="VCPreBuildEventTool"
CommandLine="%SystemDrive%\cygwin\bin\which.exe bash&#x0D;&#x0A;if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%&#x0D;&#x0A;cmd /c&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; grep XX$(ProjectName)XX &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;if errorlevel 1 exit 1&#x0D;&#x0A;echo XX$(ProjectName)XX &gt; &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;&#x0D;&#x0A;bash &quot;$(WebKitLibrariesDir)\tools\scripts\auto-version.sh&quot; &quot;$(IntDir)&quot;&#x0D;&#x0A;"
/>
- <Tool
- Name="VCPreLinkEventTool"
- CommandLine="if not exist &quot;$(WebKitOutputDir)\public\sym&quot; mkdir &quot;$(WebKitOutputDir)\public\sym&quot;"
- />
</VisualStudioPropertySheet>
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 30d101c..a664719 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
@@ -1362,7 +1362,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassR
, m_source(sourceProvider)
, m_sourceOffset(sourceOffset)
, m_symbolTable(symTab)
- , m_exceptionInfo(new ExceptionInfo)
+ , m_exceptionInfo(adoptPtr(new ExceptionInfo))
{
ASSERT(m_source);
@@ -1373,13 +1373,14 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassR
CodeBlock::~CodeBlock()
{
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
-#else
+#endif
+#if ENABLE(JIT)
for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
if (m_globalResolveInfos[i].structure)
m_globalResolveInfos[i].structure->deref();
@@ -1407,7 +1408,7 @@ CodeBlock::~CodeBlock()
unlinkCallers();
#endif
-#endif // !ENABLE(JIT)
+#endif // ENABLE(JIT)
#if DUMP_CODE_BLOCK_STATISTICS
liveCodeBlockSet.remove(this);
@@ -1538,7 +1539,7 @@ bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
scopeChain = scopeChain->next;
}
- m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this));
+ m_exceptionInfo = m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this);
return m_exceptionInfo;
}
@@ -1669,7 +1670,7 @@ bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int&
}
#endif
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
{
if (m_globalResolveInstructions.isEmpty())
@@ -1689,7 +1690,8 @@ bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOff
return false;
return true;
}
-#else
+#endif
+#if ENABLE(JIT)
bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
{
if (m_globalResolveInfos.isEmpty())
@@ -1715,10 +1717,11 @@ void CodeBlock::shrinkToFit()
{
m_instructions.shrinkToFit();
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
m_propertyAccessInstructions.shrinkToFit();
m_globalResolveInstructions.shrinkToFit();
-#else
+#endif
+#if ENABLE(JIT)
m_structureStubInfos.shrinkToFit();
m_globalResolveInfos.shrinkToFit();
m_callLinkInfos.shrinkToFit();
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index 590fe2e..2f22dd0 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
*
* Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
#include "RegExp.h"
#include "UString.h"
#include <wtf/FastAllocBase.h>
+#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
@@ -357,7 +358,8 @@ namespace JSC {
}
bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
-#else
+#endif
+#if ENABLE(INTERPRETER)
unsigned bytecodeOffset(CallFrame*, Instruction* returnAddress)
{
return static_cast<Instruction*>(returnAddress) - instructions().begin();
@@ -415,11 +417,12 @@ namespace JSC {
unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
-#else
+#endif
+#if ENABLE(JIT)
size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
@@ -446,7 +449,7 @@ namespace JSC {
bool hasExceptionInfo() const { return m_exceptionInfo; }
void clearExceptionInfo() { m_exceptionInfo.clear(); }
- ExceptionInfo* extractExceptionInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo.release(); }
+ PassOwnPtr<ExceptionInfo> extractExceptionInfo();
void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
@@ -527,7 +530,7 @@ namespace JSC {
void createRareDataIfNecessary()
{
if (!m_rareData)
- m_rareData.set(new RareData);
+ m_rareData = adoptPtr(new RareData);
}
ScriptExecutable* m_ownerExecutable;
@@ -550,10 +553,11 @@ namespace JSC {
RefPtr<SourceProvider> m_source;
unsigned m_sourceOffset;
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
Vector<unsigned> m_propertyAccessInstructions;
Vector<unsigned> m_globalResolveInstructions;
-#else
+#endif
+#if ENABLE(JIT)
Vector<StructureStubInfo> m_structureStubInfos;
Vector<GlobalResolveInfo> m_globalResolveInfos;
Vector<CallLinkInfo> m_callLinkInfos;
@@ -665,6 +669,12 @@ namespace JSC {
}
};
+ inline PassOwnPtr<ExceptionInfo> CodeBlock::extractExceptionInfo()
+ {
+ ASSERT(m_exceptionInfo);
+ return m_exceptionInfo.release();
+ }
+
inline Register& ExecState::r(int index)
{
CodeBlock* codeBlock = this->codeBlock();
diff --git a/JavaScriptCore/bytecode/Instruction.h b/JavaScriptCore/bytecode/Instruction.h
index ab6659f..c6468a5 100644
--- a/JavaScriptCore/bytecode/Instruction.h
+++ b/JavaScriptCore/bytecode/Instruction.h
@@ -125,7 +125,7 @@ namespace JSC {
struct Instruction {
Instruction(Opcode opcode)
{
-#if !HAVE(COMPUTED_GOTO)
+#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
// We have to initialize one of the pointer members to ensure that
// the entire struct is initialized, when opcode is not a pointer.
u.jsCell = 0;
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index f845a34..ca5feeb 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -120,10 +120,10 @@ namespace JSC {
macro(op_get_by_id_generic, 8) \
macro(op_get_array_length, 8) \
macro(op_get_string_length, 8) \
- macro(op_put_by_id, 8) \
- macro(op_put_by_id_transition, 8) \
- macro(op_put_by_id_replace, 8) \
- macro(op_put_by_id_generic, 8) \
+ macro(op_put_by_id, 9) \
+ macro(op_put_by_id_transition, 9) \
+ macro(op_put_by_id_replace, 9) \
+ macro(op_put_by_id_generic, 9) \
macro(op_del_by_id, 4) \
macro(op_get_by_val, 4) \
macro(op_get_by_pname, 7) \
@@ -210,7 +210,7 @@ namespace JSC {
FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
#undef VERIFY_OPCODE_ID
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
#if COMPILER(RVCT) || COMPILER(INTEL)
typedef void* Opcode;
#else
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 16ef357..8ff1b5d 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -1280,6 +1280,27 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p
instructions().append(0);
instructions().append(0);
instructions().append(0);
+ instructions().append(0);
+ return value;
+}
+
+RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value)
+{
+#if ENABLE(JIT)
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
+#else
+ m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
+
+ emitOpcode(op_put_by_id);
+ instructions().append(base->index());
+ instructions().append(addConstant(property));
+ instructions().append(value->index());
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(0);
+ instructions().append(property != m_globalData->propertyNames->underscoreProto);
return value;
}
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 8b6ab77..2b231a7 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -328,6 +328,7 @@ namespace JSC {
RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
+ RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index cdf3e49..e50ce2d 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -266,7 +266,7 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
switch (p->m_node->m_type) {
case PropertyNode::Constant: {
- generator.emitPutById(newObj.get(), p->m_node->name(), value);
+ generator.emitDirectPutById(newObj.get(), p->m_node->name(), value);
break;
}
case PropertyNode::Getter: {
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h
index 7ea59fb..bde9786 100644
--- a/JavaScriptCore/interpreter/CallFrame.h
+++ b/JavaScriptCore/interpreter/CallFrame.h
@@ -106,8 +106,9 @@ namespace JSC {
CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
#if ENABLE(JIT)
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
-#else
- Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); }
+#endif
+#if ENABLE(INTERPRETER)
+ Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
#endif
void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 8160249..26f7a6b 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -79,7 +79,7 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc)
return sc.localDepth();
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
{
int dst = vPC[1].u.operand;
@@ -294,7 +294,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
return false;
}
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc)
{
@@ -333,7 +333,7 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC
return CallFrame::create(r);
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
{
if (value.isObject())
@@ -384,12 +384,12 @@ Interpreter::Interpreter()
: m_sampleEntryDepth(0)
, m_reentryDepth(0)
{
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
privateExecute(InitializeAndReturn, 0, 0, 0);
for (int i = 0; i < numOpcodeIDs; ++i)
m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
-#endif // HAVE(COMPUTED_GOTO)
+#endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
#if ENABLE(OPCODE_SAMPLING)
enableSampler();
@@ -497,7 +497,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
bool Interpreter::isOpcode(Opcode opcode)
{
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
return opcode != HashTraits<Opcode>::emptyValue()
&& !HashTraits<Opcode>::isDeletedValue(opcode)
&& m_opcodeIDTable.contains(opcode);
@@ -547,7 +547,18 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
return false;
codeBlock = callerFrame->codeBlock();
- bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callerFrame->globalData().canUseJIT())
+#endif
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#if ENABLE(INTERPRETER)
+ else
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#endif
+#else
+ bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#endif
callFrame = callerFrame;
return true;
}
@@ -594,16 +605,24 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
// the profiler manually that the call instruction has returned, since
// we'll never reach the relevant op_profile_did_call.
if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-#if !ENABLE(JIT)
- // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
- if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
- profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
- else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
- profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
-#else
- int functionRegisterIndex;
- if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
- profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
+#if ENABLE(INTERPRETER)
+ if (!callFrame->globalData().canUseJIT()) {
+ // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
+ if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
+ else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
+ profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
+ }
+#if ENABLE(JIT)
+ else
+#endif
+#endif
+#if ENABLE(JIT)
+ {
+ int functionRegisterIndex;
+ if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
+ profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
+ }
#endif
}
@@ -676,12 +695,20 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
+ m_reentryDepth++;
#if ENABLE(JIT)
- result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
#endif
+ result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
+
m_reentryDepth--;
}
@@ -749,12 +776,19 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
- #if ENABLE(JIT)
- result = callData.js.functionExecutable->jitCodeForCall(newCallFrame, callDataScopeChain).execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
- #else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
- #endif
+ m_reentryDepth++;
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = callData.js.functionExecutable->jitCodeForCall(newCallFrame, callDataScopeChain).execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
m_reentryDepth--;
}
@@ -841,12 +875,19 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
- #if ENABLE(JIT)
- result = constructData.js.functionExecutable->jitCodeForConstruct(newCallFrame, constructDataScopeChain).execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
- #else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
- #endif
+ m_reentryDepth++;
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = constructData.js.functionExecutable->jitCodeForConstruct(newCallFrame, constructDataScopeChain).execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#endif
m_reentryDepth--;
}
@@ -922,11 +963,13 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
return CallFrameClosure();
}
// a 0 codeBlock indicates a built-in caller
- newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
+ newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
#if ENABLE(JIT)
- FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain);
#endif
-
CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
return result;
}
@@ -942,11 +985,18 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
{
SamplingTool::CallRecord callRecord(m_sampler.get());
- m_reentryDepth++;
+ m_reentryDepth++;
#if ENABLE(JIT)
- result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (closure.newCallFrame->globalData().canUseJIT())
+#endif
+ result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
#endif
m_reentryDepth--;
}
@@ -1041,10 +1091,18 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
SamplingTool::CallRecord callRecord(m_sampler.get());
m_reentryDepth++;
+
#if ENABLE(JIT)
- result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#else
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+#if ENABLE(INTERPRETER)
+ if (callFrame->globalData().canUseJIT())
+#endif
+ result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+#if ENABLE(INTERPRETER)
+ else
+#endif
+#endif
+#if ENABLE(INTERPRETER)
+ result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
m_reentryDepth--;
}
@@ -1084,7 +1142,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook
}
}
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC)
{
int dst = vPC[1].u.operand;
@@ -1320,28 +1378,32 @@ NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction*
vPC[4] = 0;
}
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
{
// One-time initialization of our address tables. We have to put this code
// here because our labels are only in scope inside this function.
if (UNLIKELY(flag == InitializeAndReturn)) {
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
#define LIST_OPCODE_LABEL(id, length) &&id,
static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i)
m_opcodeTable[i] = labels[i];
#undef LIST_OPCODE_LABEL
- #endif // HAVE(COMPUTED_GOTO)
+ #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
return JSValue();
}
-
+
#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
// Mixing Interpreter + JIT is not supported.
- ASSERT_NOT_REACHED();
+ if (callFrame->globalData().canUseJIT())
+#endif
+ ASSERT_NOT_REACHED();
#endif
-#if !!ENABLE(JIT)
+
+#if !ENABLE(INTERPRETER)
UNUSED_PARAM(registerFile);
UNUSED_PARAM(callFrame);
UNUSED_PARAM(exception);
@@ -1385,7 +1447,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
#define SAMPLE(codeBlock, vPC)
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
#define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
#if ENABLE(OPCODE_STATS)
#define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
@@ -2417,7 +2479,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_proto);
#endif
DEFINE_OPCODE(op_get_by_id_getter_proto) {
@@ -2459,10 +2521,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_proto:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_proto);
#endif
DEFINE_OPCODE(op_get_by_id_custom_proto) {
@@ -2501,7 +2563,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_proto:
#endif
DEFINE_OPCODE(op_get_by_id_self_list) {
@@ -2592,7 +2654,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_self);
#endif
DEFINE_OPCODE(op_get_by_id_getter_self) {
@@ -2632,10 +2694,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_self:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_self);
#endif
DEFINE_OPCODE(op_get_by_id_custom_self) {
@@ -2669,7 +2731,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_self:
#endif
DEFINE_OPCODE(op_get_by_id_generic) {
@@ -2692,7 +2754,7 @@ skip_id_custom_self:
vPC += OPCODE_LENGTH(op_get_by_id_generic);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_getter_chain);
#endif
DEFINE_OPCODE(op_get_by_id_getter_chain) {
@@ -2744,10 +2806,10 @@ skip_id_custom_self:
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_getter_chain:
#endif
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
goto *(&&skip_id_custom_chain);
#endif
DEFINE_OPCODE(op_get_by_id_custom_chain) {
@@ -2796,7 +2858,7 @@ skip_id_custom_self:
uncacheGetByID(codeBlock, vPC);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_id_custom_chain:
#endif
DEFINE_OPCODE(op_get_array_length) {
@@ -2840,23 +2902,31 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id) {
- /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+ /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
Generic property access: Sets the property named by identifier
property, belonging to register base, to register value.
Unlike many opcodes, this one does not write any output to
the register file.
+
+ The "direct" flag should only be set this put_by_id is to initialize
+ an object literal.
*/
int base = vPC[1].u.operand;
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
+ int direct = vPC[8].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ if (direct) {
+ baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ ASSERT(slot.base() == baseValue);
+ } else
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot);
@@ -2865,7 +2935,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_transition) {
- /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n)
+ /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
Cached property access: Attempts to set a new property with a cached transition
property named by identifier property, belonging to register base,
@@ -2886,19 +2956,21 @@ skip_id_custom_self:
if (LIKELY(baseCell->structure() == oldStructure)) {
ASSERT(baseCell->isObject());
JSObject* baseObject = asObject(baseCell);
-
- RefPtr<Structure>* it = vPC[6].u.structureChain->head();
-
- JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
- while (!proto.isNull()) {
- if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
- uncachePutByID(codeBlock, vPC);
- NEXT_INSTRUCTION();
+ int direct = vPC[8].u.operand;
+
+ if (direct) {
+ RefPtr<Structure>* it = vPC[6].u.structureChain->head();
+
+ JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
+ while (!proto.isNull()) {
+ if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
+ uncachePutByID(codeBlock, vPC);
+ NEXT_INSTRUCTION();
+ }
+ ++it;
+ proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
}
- ++it;
- proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
}
-
baseObject->transitionTo(newStructure);
int value = vPC[3].u.operand;
@@ -2915,7 +2987,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_replace) {
- /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n)
+ /* op_put_by_id_replace base(r) property(id) value(r) structure(sID) offset(n) nop(n) nop(n) direct(b)
Cached property access: Attempts to set a pre-existing, cached
property named by identifier property, belonging to register base,
@@ -2950,7 +3022,7 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
DEFINE_OPCODE(op_put_by_id_generic) {
- /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n)
+ /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
Generic property access: Sets the property named by identifier
property, belonging to register base, to register value.
@@ -2961,11 +3033,16 @@ skip_id_custom_self:
int base = vPC[1].u.operand;
int property = vPC[2].u.operand;
int value = vPC[3].u.operand;
+ int direct = vPC[8].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
Identifier& ident = codeBlock->identifier(property);
PutPropertySlot slot;
- baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ if (direct) {
+ baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
+ ASSERT(slot.base() == baseValue);
+ } else
+ baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot);
CHECK_FOR_EXCEPTION();
vPC += OPCODE_LENGTH(op_put_by_id_generic);
@@ -3704,17 +3781,17 @@ skip_id_custom_self:
goto vm_throw;
}
ASSERT(!asFunction(callFrame->callee())->isHostFunction());
- uint32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
- uint32_t inplaceArgs = min(argCount, expectedParams);
- uint32_t i = 0;
+ int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
+ int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
+ int32_t i = 0;
Register* argStore = callFrame->registers() + argsOffset;
// First step is to copy the "expected" parameters from their normal location relative to the callframe
for (; i < inplaceArgs; i++)
argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
// Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
- for (; i < argCount; i++)
- argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
+ for (; i < static_cast<int32_t>(argCount); i++)
+ argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
} else if (!arguments.isUndefinedOrNull()) {
if (!arguments.isObject()) {
exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - codeBlock->instructions().begin(), codeBlock);
@@ -3907,7 +3984,7 @@ skip_id_custom_self:
JSValue returnValue = callFrame->r(result).jsValue();
- vPC = callFrame->returnPC();
+ vPC = callFrame->returnVPC();
callFrame = callFrame->callerFrame();
if (callFrame->hasHostCallFrameFlag())
@@ -3951,7 +4028,7 @@ skip_id_custom_self:
if (UNLIKELY(!returnValue.isObject()))
returnValue = callFrame->r(vPC[2].u.operand).jsValue();
- vPC = callFrame->returnPC();
+ vPC = callFrame->returnVPC();
callFrame = callFrame->callerFrame();
if (callFrame->hasHostCallFrameFlag())
@@ -4136,7 +4213,6 @@ skip_id_custom_self:
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
vPC = newCodeBlock->instructions().begin();
-
#if ENABLE(OPCODE_STATS)
OpcodeStats::resetLastInstruction();
#endif
@@ -4299,7 +4375,7 @@ skip_id_custom_self:
vPC += target;
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
// Appease GCC
goto *(&&skip_new_scope);
#endif
@@ -4315,7 +4391,7 @@ skip_id_custom_self:
vPC += OPCODE_LENGTH(op_push_new_scope);
NEXT_INSTRUCTION();
}
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
skip_new_scope:
#endif
DEFINE_OPCODE(op_catch) {
@@ -4529,14 +4605,14 @@ skip_id_custom_self:
NEXT_INSTRUCTION();
}
}
-#if !HAVE(COMPUTED_GOTO)
+#if !ENABLE(COMPUTED_GOTO_INTERPRETER)
} // iterator loop ends
#endif
#undef NEXT_INSTRUCTION
#undef DEFINE_OPCODE
#undef CHECK_FOR_EXCEPTION
#undef CHECK_FOR_TIMEOUT
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
}
JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* function) const
@@ -4592,8 +4668,17 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
CodeBlock* callerCodeBlock = callerFrame->codeBlock();
if (!callerCodeBlock)
return;
-
- unsigned bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+ unsigned bytecodeOffset = 0;
+#if ENABLE(INTERPRETER)
+ if (!callerFrame->globalData().canUseJIT())
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+#if ENABLE(JIT)
+ else
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#endif
+#else
+ bytecodeOffset = callerCodeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
+#endif
lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
sourceID = callerCodeBlock->ownerExecutable()->sourceID();
sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h
index 555bbf9..50f07b3 100644
--- a/JavaScriptCore/interpreter/Interpreter.h
+++ b/JavaScriptCore/interpreter/Interpreter.h
@@ -75,7 +75,7 @@ namespace JSC {
Opcode getOpcode(OpcodeID id)
{
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
return m_opcodeTable[id];
#else
return id;
@@ -84,7 +84,7 @@ namespace JSC {
OpcodeID getOpcodeID(Opcode opcode)
{
- #if HAVE(COMPUTED_GOTO)
+ #if ENABLE(COMPUTED_GOTO_INTERPRETER)
ASSERT(isOpcode(opcode));
return m_opcodeIDTable.get(opcode);
#else
@@ -123,7 +123,7 @@ namespace JSC {
JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
-#if !ENABLE(JIT)
+#if ENABLE(INTERPRETER)
NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue);
NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue);
@@ -136,7 +136,7 @@ namespace JSC {
void uncacheGetByID(CodeBlock*, Instruction* vPC);
void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&);
void uncachePutByID(CodeBlock*, Instruction* vPC);
-#endif // !ENABLE(JIT)
+#endif // ENABLE(INTERPRETER)
NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&);
@@ -159,7 +159,7 @@ namespace JSC {
RegisterFile m_registerFile;
-#if HAVE(COMPUTED_GOTO)
+#if ENABLE(COMPUTED_GOTO_INTERPRETER)
Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling
HashMap<Opcode, OpcodeID> m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling
#endif
diff --git a/JavaScriptCore/jit/ExecutableAllocator.cpp b/JavaScriptCore/jit/ExecutableAllocator.cpp
index f6b27ec..5e10e86 100644
--- a/JavaScriptCore/jit/ExecutableAllocator.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocator.cpp
@@ -33,6 +33,42 @@ namespace JSC {
size_t ExecutableAllocator::pageSize = 0;
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
+{
+ if (!pageSize)
+ intializePageSize();
+
+ // Calculate the start of the page containing this region,
+ // and account for this extra memory within size.
+ intptr_t startPtr = reinterpret_cast<intptr_t>(start);
+ intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
+ void* pageStart = reinterpret_cast<void*>(pageStartPtr);
+ size += (startPtr - pageStartPtr);
+
+ // Round size up
+ size += (pageSize - 1);
+ size &= ~(pageSize - 1);
+
+ mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
+}
+#endif
+
+#if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
+__asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
+{
+ ARM
+ push {r7}
+ add r1, r1, r0
+ mov r7, #0xf0000
+ add r7, r7, #0x2
+ mov r2, #0x0
+ svc #0x0
+ pop {r7}
+ bx lr
+}
+#endif
+
}
#endif // HAVE(ASSEMBLER)
diff --git a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
index 4d3c847..7846a25 100644
--- a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
@@ -27,25 +27,33 @@
#include "ExecutableAllocator.h"
-#if ENABLE(ASSEMBLER) && OS(DARWIN) && CPU(X86_64)
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
#include <errno.h>
#include "TCSpinLock.h"
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wtf/AVLTree.h>
#include <wtf/VMTags.h>
+#if CPU(X86_64)
+ // These limits suitable on 64-bit platforms (particularly x86-64, where we require all jumps to have a 2Gb max range).
+ #define VM_POOL_SIZE (2u * 1024u * 1024u * 1024u) // 2Gb
+ #define COALESCE_LIMIT (16u * 1024u * 1024u) // 16Mb
+#else
+ // These limits are hopefully sensible on embedded platforms.
+ #define VM_POOL_SIZE (32u * 1024u * 1024u) // 32Mb
+ #define COALESCE_LIMIT (4u * 1024u * 1024u) // 4Mb
+#endif
+
+// ASLR currently only works on darwin (due to arc4random) & 64-bit (due to address space size).
+#define VM_POOL_ASLR (OS(DARWIN) && CPU(X86_64))
+
using namespace WTF;
namespace JSC {
-#define TWO_GB (2u * 1024u * 1024u * 1024u)
-#define SIXTEEN_MB (16u * 1024u * 1024u)
-
// FreeListEntry describes a free chunk of memory, stored in the freeList.
struct FreeListEntry {
FreeListEntry(void* pointer, size_t size)
@@ -291,9 +299,12 @@ public:
// for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
// 2^24, which should put up somewhere in the middle of usespace (in the address range
// 0x200000000000 .. 0x5fffffffffff).
- intptr_t randomLocation = arc4random() & ((1 << 25) - 1);
+ intptr_t randomLocation = 0;
+#if VM_POOL_ASLR
+ randomLocation = arc4random() & ((1 << 25) - 1);
randomLocation += (1 << 24);
randomLocation <<= 21;
+#endif
m_base = mmap(reinterpret_cast<void*>(randomLocation), m_totalHeapSize, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
if (!m_base)
CRASH();
@@ -387,7 +398,7 @@ public:
// 16MB of allocations have been freed, sweep m_freeList
// coalescing any neighboring fragments.
m_countFreedSinceLastCoalesce += size;
- if (m_countFreedSinceLastCoalesce >= SIXTEEN_MB) {
+ if (m_countFreedSinceLastCoalesce >= COALESCE_LIMIT) {
m_countFreedSinceLastCoalesce = 0;
coalesceFreeSpace();
}
@@ -429,7 +440,7 @@ ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
SpinLockHolder lock_holder(&spinlock);
if (!allocator)
- allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, TWO_GB);
+ allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, VM_POOL_SIZE);
ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocator->alloc(size)), size};
return alloc;
}
@@ -444,4 +455,5 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& allocation)
}
+
#endif // HAVE(ASSEMBLER)
diff --git a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
index eee8a7e..b04049c 100644
--- a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp
@@ -27,7 +27,7 @@
#include "ExecutableAllocator.h"
-#if ENABLE(ASSEMBLER) && OS(UNIX) && !OS(SYMBIAN)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && !OS(WINDOWS) && !OS(SYMBIAN)
#include <sys/mman.h>
#include <unistd.h>
@@ -35,8 +35,6 @@
namespace JSC {
-#if !(OS(DARWIN) && CPU(X86_64))
-
void ExecutableAllocator::intializePageSize()
{
ExecutableAllocator::pageSize = getpagesize();
@@ -57,44 +55,6 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
ASSERT_UNUSED(result, !result);
}
-#endif // !(OS(DARWIN) && CPU(X86_64))
-
-#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
-{
- if (!pageSize)
- intializePageSize();
-
- // Calculate the start of the page containing this region,
- // and account for this extra memory within size.
- intptr_t startPtr = reinterpret_cast<intptr_t>(start);
- intptr_t pageStartPtr = startPtr & ~(pageSize - 1);
- void* pageStart = reinterpret_cast<void*>(pageStartPtr);
- size += (startPtr - pageStartPtr);
-
- // Round size up
- size += (pageSize - 1);
- size &= ~(pageSize - 1);
-
- mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
}
-#endif
-#if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
-__asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
-{
- ARM
- push {r7}
- add r1, r1, r0
- mov r7, #0xf0000
- add r7, r7, #0x2
- mov r2, #0x0
- svc #0x0
- pop {r7}
- bx lr
-}
#endif
-
-}
-
-#endif // HAVE(ASSEMBLER)
diff --git a/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp b/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp
index e82975c..9028f50 100644
--- a/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp
@@ -22,7 +22,7 @@
#include "ExecutableAllocator.h"
-#if ENABLE(ASSEMBLER) && OS(SYMBIAN)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(SYMBIAN)
#include <e32hal.h>
#include <e32std.h>
diff --git a/JavaScriptCore/jit/ExecutableAllocatorWin.cpp b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp
index e38323c..72a1d5f 100644
--- a/JavaScriptCore/jit/ExecutableAllocatorWin.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp
@@ -27,7 +27,7 @@
#include "ExecutableAllocator.h"
-#if ENABLE(ASSEMBLER) && OS(WINDOWS)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(WINDOWS)
#include "windows.h"
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 529a1d6..0980be2 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -211,10 +211,10 @@ namespace JSC {
jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame);
}
- static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
+ static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
{
JIT jit(globalData, codeBlock);
- jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
+ jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress, direct);
}
static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, TrampolineStructure *trampolines)
@@ -230,7 +230,7 @@ namespace JSC {
}
static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
- static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
+ static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct);
static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
@@ -266,7 +266,7 @@ namespace JSC {
void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
- void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
+ void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines);
Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false);
@@ -407,6 +407,47 @@ namespace JSC {
// sequencePutById
static const int sequencePutByIdInstructionSpace = 36;
static const int sequencePutByIdConstantSpace = 4;
+#elif CPU(ARM_THUMB2)
+ // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+ static const int patchOffsetPutByIdStructure = 10;
+ static const int patchOffsetPutByIdExternalLoad = 26;
+ static const int patchLengthPutByIdExternalLoad = 12;
+ static const int patchOffsetPutByIdPropertyMapOffset1 = 46;
+ static const int patchOffsetPutByIdPropertyMapOffset2 = 58;
+ // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+ static const int patchOffsetGetByIdStructure = 10;
+ static const int patchOffsetGetByIdBranchToSlowCase = 26;
+ static const int patchOffsetGetByIdExternalLoad = 26;
+ static const int patchLengthGetByIdExternalLoad = 12;
+ static const int patchOffsetGetByIdPropertyMapOffset1 = 46;
+ static const int patchOffsetGetByIdPropertyMapOffset2 = 58;
+ static const int patchOffsetGetByIdPutResult = 62;
+#if ENABLE(OPCODE_SAMPLING)
+ #error "OPCODE_SAMPLING is not yet supported"
+#else
+ static const int patchOffsetGetByIdSlowCaseCall = 30;
+#endif
+ static const int patchOffsetOpCallCompareToJump = 16;
+
+ static const int patchOffsetMethodCheckProtoObj = 24;
+ static const int patchOffsetMethodCheckProtoStruct = 34;
+ static const int patchOffsetMethodCheckPutFunction = 58;
+
+ // sequenceOpCall
+ static const int sequenceOpCallInstructionSpace = 12;
+ static const int sequenceOpCallConstantSpace = 2;
+ // sequenceMethodCheck
+ static const int sequenceMethodCheckInstructionSpace = 40;
+ static const int sequenceMethodCheckConstantSpace = 6;
+ // sequenceGetByIdHotPath
+ static const int sequenceGetByIdHotPathInstructionSpace = 36;
+ static const int sequenceGetByIdHotPathConstantSpace = 4;
+ // sequenceGetByIdSlowCase
+ static const int sequenceGetByIdSlowCaseInstructionSpace = 40;
+ static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+ // sequencePutById
+ static const int sequencePutByIdInstructionSpace = 36;
+ static const int sequencePutByIdConstantSpace = 4;
#else
#error "JSVALUE32_64 not supported on this platform."
#endif
diff --git a/JavaScriptCore/jit/JITPropertyAccess.cpp b/JavaScriptCore/jit/JITPropertyAccess.cpp
index 4d36cfa..580e73f 100644
--- a/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -307,10 +307,11 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
unsigned baseVReg = currentInstruction[1].u.operand;
Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
unsigned valueVReg = currentInstruction[3].u.operand;
+ unsigned direct = currentInstruction[8].u.operand;
emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);
- JITStubCall stubCall(this, cti_op_put_by_id_generic);
+ JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct_generic, cti_op_put_by_id_generic);
stubCall.addArgument(regT0);
stubCall.addArgument(ImmPtr(ident));
stubCall.addArgument(regT1);
@@ -530,13 +531,14 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
{
unsigned baseVReg = currentInstruction[1].u.operand;
Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
+ unsigned direct = currentInstruction[8].u.operand;
unsigned propertyAccessInstructionIndex = m_propertyAccessInstructionIndex++;
linkSlowCaseIfNotJSCell(iter, baseVReg);
linkSlowCase(iter);
- JITStubCall stubCall(this, cti_op_put_by_id);
+ JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
stubCall.addArgument(regT0);
stubCall.addArgument(ImmPtr(ident));
stubCall.addArgument(regT1);
@@ -590,7 +592,7 @@ void JIT::testPrototype(Structure* structure, JumpList& failureCases)
failureCases.append(branchPtr(NotEqual, Address(regT2), regT3));
}
-void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
+void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
{
JumpList failureCases;
// Check eax is an object of the right Structure.
@@ -599,8 +601,10 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
testPrototype(oldStructure, failureCases);
// ecx = baseObject->m_structure
- for (RefPtr<Structure>* it = chain->head(); *it; ++it)
- testPrototype(it->get(), failureCases);
+ if (!direct) {
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it)
+ testPrototype(it->get(), failureCases);
+ }
Call callTarget;
@@ -641,7 +645,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
- patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
+ patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
if (willNeedStorageRealloc) {
ASSERT(m_calls.size() == 1);
@@ -694,13 +698,13 @@ void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodC
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
}
-void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
+void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
{
RepatchBuffer repatchBuffer(codeBlock);
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
// Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
- repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
int offset = sizeof(JSValue) * cachedOffset;
diff --git a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index 16cf84a..6234842 100644
--- a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -531,11 +531,12 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
{
int base = currentInstruction[1].u.operand;
int ident = currentInstruction[2].u.operand;
-
+ int direct = currentInstruction[8].u.operand;
+
linkSlowCaseIfNotJSCell(iter, base);
linkSlowCase(iter);
- JITStubCall stubCall(this, cti_op_put_by_id);
+ JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
stubCall.addArgument(regT1, regT0);
stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
stubCall.addArgument(regT3, regT2);
@@ -592,7 +593,7 @@ void JIT::testPrototype(Structure* structure, JumpList& failureCases)
failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(structure->m_prototype)->m_structure), ImmPtr(asCell(structure->m_prototype)->m_structure)));
}
-void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
+void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
{
// It is assumed that regT0 contains the basePayload and regT1 contains the baseTag. The value can be found on the stack.
@@ -601,10 +602,12 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
testPrototype(oldStructure, failureCases);
- // Verify that nothing in the prototype chain has a setter for this property.
- for (RefPtr<Structure>* it = chain->head(); *it; ++it)
- testPrototype(it->get(), failureCases);
-
+ if (!direct) {
+ // Verify that nothing in the prototype chain has a setter for this property.
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it)
+ testPrototype(it->get(), failureCases);
+ }
+
// Reallocate property storage if needed.
Call callTarget;
bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
@@ -643,7 +646,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
- patchBuffer.link(failureCall, FunctionPtr(cti_op_put_by_id_fail));
+ patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
if (willNeedStorageRealloc) {
ASSERT(m_calls.size() == 1);
@@ -697,13 +700,13 @@ void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodC
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
}
-void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress)
+void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
{
RepatchBuffer repatchBuffer(codeBlock);
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
// Should probably go to cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
- repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
int offset = sizeof(JSValue) * cachedOffset;
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 30a9898..85bd54f 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -247,7 +247,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
#define REGISTER_FILE_OFFSET 0x50
#define CALLFRAME_OFFSET 0x54
#define EXCEPTION_OFFSET 0x58
-#define ENABLE_PROFILER_REFERENCE_OFFSET 0x64
+#define ENABLE_PROFILER_REFERENCE_OFFSET 0x60
#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
@@ -844,7 +844,7 @@ JITThunks::~JITThunks()
#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo)
+NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
{
// The interpreter checks for recursion here; I do not believe this can occur in CTI.
@@ -853,7 +853,7 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
// Uncacheable: give up.
if (!slot.isCacheable()) {
- ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
return;
}
@@ -861,13 +861,13 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
Structure* structure = baseCell->structure();
if (structure->isUncacheableDictionary()) {
- ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
return;
}
// If baseCell != base, then baseCell must be a proxy for another object.
if (baseCell != slot.base()) {
- ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
return;
}
@@ -876,7 +876,7 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
// Structure transition, cache transition info
if (slot.type() == PutPropertySlot::NewProperty) {
if (structure->isDictionary()) {
- ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic));
+ ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
return;
}
@@ -885,13 +885,13 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
StructureChain* prototypeChain = structure->prototypeChain(callFrame);
stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
- JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress);
+ JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
return;
}
stubInfo->initPutByIdReplace(structure);
- JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
+ JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
}
NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
@@ -1344,6 +1344,15 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
CHECK_FOR_EXCEPTION_AT_END();
}
+DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
{
STUB_INIT_STACK_FRAME(stackFrame);
@@ -1366,17 +1375,36 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id)
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
Identifier& ident = stackFrame.args[1].identifier();
-
+
PutPropertySlot slot;
stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
-
+
CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
if (!stubInfo->seenOnce())
stubInfo->setSeen();
else
- JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo);
+ JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+
+ CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
+ StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
+ if (!stubInfo->seenOnce())
+ stubInfo->setSeen();
+ else
+ JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
+
CHECK_FOR_EXCEPTION_AT_END();
}
@@ -1393,6 +1421,19 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
CHECK_FOR_EXCEPTION_AT_END();
}
+DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
+{
+ STUB_INIT_STACK_FRAME(stackFrame);
+
+ CallFrame* callFrame = stackFrame.callFrame;
+ Identifier& ident = stackFrame.args[1].identifier();
+
+ PutPropertySlot slot;
+ stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
+
+ CHECK_FOR_EXCEPTION_AT_END();
+}
+
DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
{
STUB_INIT_STACK_FRAME(stackFrame);
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index 6d627a1..a5b21e5 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -257,7 +257,7 @@ namespace JSC {
~JITThunks();
static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo);
- static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo);
+ static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo, bool direct);
MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
@@ -378,6 +378,9 @@ extern "C" {
void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_direct(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_direct_fail(STUB_ARGS_DECLARATION);
+ void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
diff --git a/JavaScriptCore/parser/ASTBuilder.h b/JavaScriptCore/parser/ASTBuilder.h
index 7dcdff0..3b7ffb5 100644
--- a/JavaScriptCore/parser/ASTBuilder.h
+++ b/JavaScriptCore/parser/ASTBuilder.h
@@ -249,16 +249,9 @@ public:
return FunctionBodyNode::create(m_globalData);
}
- PropertyNode* createGetterOrSetterProperty(const Identifier* getOrSet, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+ template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
{
ASSERT(name);
- PropertyNode::Type type;
- if (*getOrSet == "get")
- type = PropertyNode::Getter;
- else if (*getOrSet == "set")
- type = PropertyNode::Setter;
- else
- return 0;
body->setLoc(bodyStartLine, bodyEndLine);
return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(m_globalData, m_globalData->propertyNames->nullIdentifier, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), params), type);
}
@@ -269,8 +262,8 @@ public:
ArgumentListNode* createArgumentsList(ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, arg); }
ArgumentListNode* createArgumentsList(ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, args, arg); }
- PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
- PropertyNode* createProperty(double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
+ template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+ template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
PropertyListNode* createPropertyList(PropertyNode* property) { return new (m_globalData) PropertyListNode(m_globalData, property); }
PropertyListNode* createPropertyList(PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(m_globalData, property, tail); }
@@ -576,7 +569,9 @@ public:
assignmentStackDepth--;
return result;
}
-
+
+ const Identifier& getName(Property property) { return property->name(); }
+ PropertyNode::Type getType(Property property) { return property->type(); }
private:
struct Scope {
Scope(JSGlobalData* globalData)
@@ -767,13 +762,13 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case AND:
return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd);
- case '|':
+ case BITOR:
return new (m_globalData) BitOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '^':
+ case BITXOR:
return new (m_globalData) BitXOrNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '&':
+ case BITAND:
return new (m_globalData) BitAndNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
case EQEQ:
@@ -788,10 +783,10 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case STRNEQ:
return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '<':
+ case LT:
return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '>':
+ case GT:
return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
case LE:
@@ -821,19 +816,19 @@ ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, Bina
case URSHIFT:
return new (m_globalData) UnsignedRightShiftNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
- case '+':
+ case PLUS:
return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '-':
+ case MINUS:
return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '*':
+ case TIMES:
return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '/':
+ case DIVIDE:
return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment);
- case '%':
+ case MOD:
return new (m_globalData) ModNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
}
CRASH();
diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp
index 5825270..1fb1a9187 100644
--- a/JavaScriptCore/parser/JSParser.cpp
+++ b/JavaScriptCore/parser/JSParser.cpp
@@ -32,6 +32,7 @@ using namespace JSC;
#include "JSGlobalData.h"
#include "NodeInfo.h"
#include "ASTBuilder.h"
+#include <wtf/HashFunctions.h>
#include <utility>
using namespace std;
@@ -58,12 +59,14 @@ namespace JSC {
#define TreeProperty typename TreeBuilder::Property
#define TreePropertyList typename TreeBuilder::PropertyList
+COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
+
// This matches v8
static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;
class JSParser {
public:
- JSParser(Lexer*, JSGlobalData*);
+ JSParser(Lexer*, JSGlobalData*, SourceProvider*);
bool parseProgram();
private:
struct AllowInOverride {
@@ -84,14 +87,14 @@ private:
const JSToken& token() { return m_token; }
void next()
{
- m_lastLine = token().m_info.last_line;
- m_lastTokenEnd = token().m_info.last_column;
+ m_lastLine = token().m_info.line;
+ m_lastTokenEnd = token().m_info.endOffset;
m_lexer->setLastLineNumber(m_lastLine);
m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info);
m_tokenCount++;
}
- bool consume(int expected)
+ bool consume(JSTokenType expected)
{
bool result = m_token.m_type == expected;
failIfFalse(result);
@@ -99,24 +102,24 @@ private:
return result;
}
- bool match(int expected)
+ bool match(JSTokenType expected)
{
return m_token.m_type == expected;
}
int tokenStart()
{
- return token().m_info.first_column;
+ return token().m_info.startOffset;
}
int tokenLine()
{
- return token().m_info.first_line;
+ return token().m_info.line;
}
int tokenEnd()
{
- return token().m_info.last_column;
+ return token().m_info.endOffset;
}
template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
@@ -150,20 +153,21 @@ private:
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
- template <class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
+ template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&, bool& usesArguments);
template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
template <FunctionRequirements, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
- int isBinaryOperator(int token);
+ ALWAYS_INLINE int isBinaryOperator(JSTokenType token);
bool allowAutomaticSemicolon();
bool autoSemiColon()
{
- if (token().m_type == ';') {
+ if (token().m_type == SEMICOLON) {
next();
return true;
}
@@ -194,15 +198,16 @@ private:
int m_lastTokenEnd;
int m_assignmentCount;
int m_nonLHSCount;
+ bool m_syntaxAlreadyValidated;
};
-int jsParse(JSGlobalData* globalData)
+int jsParse(JSGlobalData* globalData, const SourceCode* source)
{
- JSParser parser(globalData->lexer, globalData);
+ JSParser parser(globalData->lexer, globalData, source->provider());
return parser.parseProgram();
}
-JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
+JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, SourceProvider* provider)
: m_lexer(lexer)
, m_endAddress(0)
, m_error(false)
@@ -213,6 +218,7 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData)
, m_lastTokenEnd(0)
, m_assignmentCount(0)
, m_nonLHSCount(0)
+ , m_syntaxAlreadyValidated(provider->isValid())
{
m_endAddress = *(globalData->stackGuards);
if (!m_endAddress) {
@@ -228,7 +234,7 @@ bool JSParser::parseProgram()
{
ASTBuilder context(m_globalData, m_lexer);
SourceElements* sourceElements = parseSourceElements<ASTBuilder>(context);
- if (!sourceElements || !consume(0))
+ if (!sourceElements || !consume(EOFTOK))
return true;
m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), context.features(),
m_lastLine, context.numConstants());
@@ -237,7 +243,7 @@ bool JSParser::parseProgram()
bool JSParser::allowAutomaticSemicolon()
{
- return match(CLOSEBRACE) || match(0) || m_lexer->prevTerminator();
+ return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
}
template <class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
@@ -288,11 +294,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeB
failIfFalse(statement);
int endLine = tokenLine();
consumeOrFail(WHILE);
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
- consumeOrFail(')');
- if (match(';'))
+ consumeOrFail(CLOSEPAREN);
+ if (match(SEMICOLON))
next(); // Always performs automatic semicolon insertion.
return context.createDoWhileStatement(statement, expr, startLine, endLine);
}
@@ -302,11 +308,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBui
ASSERT(match(WHILE));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createWhileStatement(expr, statement, startLine, endLine);
@@ -325,7 +331,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr
const Identifier* name = token().m_data.ident;
lastIdent = name;
next();
- bool hasInitializer = match('=');
+ bool hasInitializer = match(EQUAL);
context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
if (hasInitializer) {
int varDivot = tokenStart() + 1;
@@ -343,7 +349,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(Tr
else
varDecls = context.combineCommaNodes(varDecls, node);
}
- } while (match(','));
+ } while (match(COMMA));
return varDecls;
}
@@ -356,7 +362,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi
matchOrFail(IDENT);
const Identifier* name = token().m_data.ident;
next();
- bool hasInitializer = match('=');
+ bool hasInitializer = match(EQUAL);
context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
TreeExpression initializer = 0;
if (hasInitializer) {
@@ -366,7 +372,7 @@ template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationLi
tail = context.appendConstDecl(tail, name, initializer);
if (!constDecls)
constDecls = tail;
- } while (match(','));
+ } while (match(COMMA));
return constDecls;
}
@@ -375,7 +381,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
ASSERT(match(FOR));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
int nonLHSCount = m_nonLHSCount;
int declarations = 0;
int declsStart = 0;
@@ -400,7 +406,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
fail();
// Remainder of a standard for loop is handled identically
- if (declarations > 1 || match(';'))
+ if (declarations > 1 || match(SEMICOLON))
goto standardForLoop;
// Handle for-in with var declaration
@@ -413,7 +419,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
int exprEnd = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -421,7 +427,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
}
- if (!match(';')) {
+ if (!match(SEMICOLON)) {
m_allowsIn = false;
declsStart = tokenStart();
decls = parseExpression(context);
@@ -430,25 +436,25 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
failIfFalse(decls);
}
- if (match(';')) {
+ if (match(SEMICOLON)) {
standardForLoop:
// Standard for loop
next();
TreeExpression condition = 0;
- if (!match(';')) {
+ if (!match(SEMICOLON)) {
condition = parseExpression(context);
failIfFalse(condition);
}
- consumeOrFail(';');
+ consumeOrFail(SEMICOLON);
TreeExpression increment = 0;
- if (!match(')')) {
+ if (!match(CLOSEPAREN)) {
increment = parseExpression(context);
failIfFalse(increment);
}
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
@@ -461,7 +467,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuild
failIfFalse(expr);
int exprEnd = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -519,14 +525,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBu
// We do the auto semicolon check before attempting to parse an expression
// as we need to ensure the a line break after the return correctly terminates
// the statement
- if (match(';'))
+ if (match(SEMICOLON))
endLine = tokenLine();
if (autoSemiColon())
return context.createReturnStatement(0, start, end, startLine, endLine);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
end = lastTokenEnd();
- if (match(';'))
+ if (match(SEMICOLON))
endLine = tokenLine();
failIfFalse(autoSemiColon());
return context.createReturnStatement(expr, start, end, startLine, endLine);
@@ -553,14 +559,14 @@ template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuil
ASSERT(match(WITH));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
int start = tokenStart();
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int end = lastTokenEnd();
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
@@ -573,11 +579,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBu
ASSERT(match(SWITCH));
int startLine = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression expr = parseExpression(context);
failIfFalse(expr);
int endLine = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
consumeOrFail(OPENBRACE);
TreeClauseList firstClauses = parseSwitchClauses(context);
@@ -601,7 +607,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui
next();
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
TreeClause clause = context.createClause(condition, statements);
@@ -612,7 +618,7 @@ template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBui
next();
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
clause = context.createClause(condition, statements);
@@ -626,7 +632,7 @@ template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeB
if (!match(DEFAULT))
return 0;
next();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeSourceElements statements = parseSourceElements(context);
failIfFalse(statements);
return context.createClause(0, statements);
@@ -650,11 +656,11 @@ template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuild
if (match(CATCH)) {
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
matchOrFail(IDENT);
ident = token().m_data.ident;
next();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
int initialEvalCount = context.evalCount();
catchBlock = parseBlockStatement(context);
@@ -678,7 +684,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(Tree
int startLine = tokenLine();
int endLine = startLine;
next();
- if (match(';'))
+ if (match(SEMICOLON))
startLine = tokenLine();
failIfFalse(autoSemiColon());
return context.createDebugger(startLine, endLine);
@@ -712,7 +718,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder&
return parseConstDeclaration(context);
case FUNCTION:
return parseFunctionDeclaration(context);
- case ';':
+ case SEMICOLON:
next();
return context.createEmptyStatement();
case IF:
@@ -739,7 +745,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder&
return parseTryStatement(context);
case DEBUGGER:
return parseDebuggerStatement(context);
- case 0:
+ case EOFTOK:
case CASE:
case CLOSEBRACE:
case DEFAULT:
@@ -759,7 +765,7 @@ template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParame
TreeFormalParameterList list = context.createFormalParameterList(*token().m_data.ident);
TreeFormalParameterList tail = list;
next();
- while (match(',')) {
+ while (match(COMMA)) {
next();
matchOrFail(IDENT);
const Identifier* ident = token().m_data.ident;
@@ -786,13 +792,13 @@ template <JSParser::FunctionRequirements requirements, class TreeBuilder> bool J
next();
} else if (requirements == FunctionNeedsName)
return false;
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
bool usesArguments = false;
- if (!match(')')) {
+ if (!match(CLOSEPAREN)) {
parameters = parseFormalParameters(context, usesArguments);
failIfFalse(parameters);
}
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
openBracePos = token().m_data.intValue;
@@ -843,7 +849,7 @@ template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelState
return context.createExprStatement(expression, startLine, m_lastLine);
failIfFalse(currentToken + 1 == m_tokenCount);
int end = tokenEnd();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeStatement statement = parseStatement(context);
failIfFalse(statement);
return context.createLabelStatement(ident, statement, start, end);
@@ -865,12 +871,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde
int start = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression condition = parseExpression(context);
failIfFalse(condition);
int end = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement trueBlock = parseStatement(context);
failIfFalse(trueBlock);
@@ -894,12 +900,12 @@ template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilde
int innerStart = tokenLine();
next();
- consumeOrFail('(');
+ consumeOrFail(OPENPAREN);
TreeExpression innerCondition = parseExpression(context);
failIfFalse(innerCondition);
int innerEnd = tokenLine();
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
TreeStatement innerTrueBlock = parseStatement(context);
failIfFalse(innerTrueBlock);
@@ -938,14 +944,14 @@ template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilde
failIfStackOverflow();
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- if (!match(','))
+ if (!match(COMMA))
return node;
next();
m_nonLHSCount++;
TreeExpression right = parseAssignmentExpression(context);
failIfFalse(right);
typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
- while (match(',')) {
+ while (match(COMMA)) {
next();
right = parseAssignmentExpression(context);
failIfFalse(right);
@@ -971,7 +977,7 @@ template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpressi
bool hadAssignment = false;
while (true) {
switch (token().m_type) {
- case '=': op = OpEqual; break;
+ case EQUAL: op = OpEqual; break;
case PLUSEQUAL: op = OpPlusEq; break;
case MINUSEQUAL: op = OpMinusEq; break;
case MULTEQUAL: op = OpMultEq; break;
@@ -1013,92 +1019,28 @@ template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression
{
TreeExpression cond = parseBinaryExpression(context);
failIfFalse(cond);
- if (!match('?'))
+ if (!match(QUESTION))
return cond;
m_nonLHSCount++;
next();
TreeExpression lhs = parseAssignmentExpression(context);
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeExpression rhs = parseAssignmentExpression(context);
failIfFalse(rhs);
return context.createConditionalExpr(cond, lhs, rhs);
}
-static bool isUnaryOp(int token)
+ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
{
- switch (token) {
- case '!':
- case '~':
- case '-':
- case '+':
- case PLUSPLUS:
- case AUTOPLUSPLUS:
- case MINUSMINUS:
- case AUTOMINUSMINUS:
- case TYPEOF:
- case VOIDTOKEN:
- case DELETETOKEN:
- return true;
- default:
- return false;
- }
+ return token & UnaryOpTokenFlag;
}
-int JSParser::isBinaryOperator(int token)
+int JSParser::isBinaryOperator(JSTokenType token)
{
- switch (token) {
- case OR:
- return 1;
-
- case AND:
- return 2;
-
- case '|':
- return 3;
-
- case '^':
- return 4;
-
- case '&':
- return 5;
-
- case EQEQ:
- case NE:
- case STREQ:
- case STRNEQ:
- return 6;
-
- case '<':
- case '>':
- case LE:
- case GE:
- case INSTANCEOF:
- return 7;
-
- case INTOKEN:
- // same precedence as the above but needs a validity check
- if (m_allowsIn)
- return 7;
- return 0;
-
- case LSHIFT:
- case RSHIFT:
- case URSHIFT:
- return 8;
-
- case '+':
- case '-':
- return 9;
-
- case '*':
- case '/':
- case '%':
- return 10;
-
- default:
- return 0;
- }
+ if (m_allowsIn)
+ return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
+ return token & BinaryOpTokenPrecedenceMask;
}
template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
@@ -1145,7 +1087,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(Tree
}
-template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
+template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
{
bool wasIdent = false;
switch (token().m_type) {
@@ -1154,11 +1096,11 @@ template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& c
case STRING: {
const Identifier* ident = token().m_data.ident;
next();
- if (match(':')) {
+ if (match(COLON)) {
next();
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- return context.createProperty(ident, node, PropertyNode::Constant);
+ return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
}
failIfFalse(wasIdent);
matchOrFail(IDENT);
@@ -1168,23 +1110,32 @@ template <class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& c
int openBracePos = 0;
int closeBracePos = 0;
int bodyStartLine = 0;
+ PropertyNode::Type type;
+ if (*ident == m_globalData->propertyNames->get)
+ type = PropertyNode::Getter;
+ else if (*ident == m_globalData->propertyNames->set)
+ type = PropertyNode::Setter;
+ else
+ fail();
failIfFalse(parseFunctionInfo<FunctionNeedsName>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine));
- return context.createGetterOrSetterProperty(ident, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+ return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
}
case NUMBER: {
double propertyName = token().m_data.doubleValue;
next();
- consumeOrFail(':');
+ consumeOrFail(COLON);
TreeExpression node = parseAssignmentExpression(context);
failIfFalse(node);
- return context.createProperty(propertyName, node, PropertyNode::Constant);
+ return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant);
}
+ default:
+ fail();
}
- fail();
}
template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
{
+ int startOffset = token().m_data.intValue;
consumeOrFail(OPENBRACE);
if (match(CLOSEBRACE)) {
@@ -1192,20 +1143,27 @@ template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBui
return context.createObjectLiteral();
}
- TreeProperty property = parseProperty(context);
+ TreeProperty property = parseProperty<false>(context);
failIfFalse(property);
-
+ if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+ m_lexer->setOffset(startOffset);
+ next();
+ return parseStrictObjectLiteral(context);
+ }
TreePropertyList propertyList = context.createPropertyList(property);
TreePropertyList tail = propertyList;
-
- while (match(',')) {
+ while (match(COMMA)) {
next();
// allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
if (match(CLOSEBRACE))
break;
- property = parseProperty(context);
+ property = parseProperty<false>(context);
failIfFalse(property);
-
+ if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+ m_lexer->setOffset(startOffset);
+ next();
+ return parseStrictObjectLiteral(context);
+ }
tail = context.createPropertyList(property, tail);
}
@@ -1214,16 +1172,62 @@ template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBui
return context.createObjectLiteral(propertyList);
}
+template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(TreeBuilder& context)
+{
+ consumeOrFail(OPENBRACE);
+
+ if (match(CLOSEBRACE)) {
+ next();
+ return context.createObjectLiteral();
+ }
+
+ TreeProperty property = parseProperty<true>(context);
+ failIfFalse(property);
+
+ typedef HashMap<RefPtr<UString::Rep>, unsigned, IdentifierRepHash> ObjectValidationMap;
+ ObjectValidationMap objectValidator;
+ // Add the first property
+ if (!m_syntaxAlreadyValidated)
+ objectValidator.add(context.getName(property).ustring().rep(), context.getType(property));
+
+ TreePropertyList propertyList = context.createPropertyList(property);
+ TreePropertyList tail = propertyList;
+ while (match(COMMA)) {
+ next();
+ // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
+ if (match(CLOSEBRACE))
+ break;
+ property = parseProperty<true>(context);
+ failIfFalse(property);
+ if (!m_syntaxAlreadyValidated) {
+ std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).ustring().rep(), context.getType(property));
+ if (!propertyEntryIter.second) {
+ if ((context.getType(property) & propertyEntryIter.first->second) != PropertyNode::Constant) {
+ // Can't have multiple getters or setters with the same name, nor can we define
+ // a property as both an accessor and a constant value
+ failIfTrue(context.getType(property) & propertyEntryIter.first->second);
+ failIfTrue((context.getType(property) | propertyEntryIter.first->second) & PropertyNode::Constant);
+ }
+ }
+ }
+ tail = context.createPropertyList(property, tail);
+ }
+
+ consumeOrFail(CLOSEBRACE);
+
+ return context.createObjectLiteral(propertyList);
+}
+
template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
{
- consumeOrFail('[');
+ consumeOrFail(OPENBRACKET);
int elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions++;
}
- if (match(']')) {
+ if (match(CLOSEBRACKET)) {
next();
return context.createArray(elisions);
}
@@ -1233,16 +1237,16 @@ template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuil
typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
typename TreeBuilder::ElementList tail = elementList;
elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions = 0;
- while (match(',')) {
+ while (match(COMMA)) {
next();
elisions++;
}
- if (match(']')) {
+ if (match(CLOSEBRACKET)) {
next();
return context.createArray(elisions, elementList);
}
@@ -1251,7 +1255,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuil
tail = context.createElementList(tail, elisions, elem);
}
- consumeOrFail(']');
+ consumeOrFail(CLOSEBRACKET);
return context.createArray(elementList);
}
@@ -1261,14 +1265,14 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
switch (token().m_type) {
case OPENBRACE:
return parseObjectLiteral(context);
- case '[':
+ case OPENBRACKET:
return parseArrayLiteral(context);
- case '(': {
+ case OPENPAREN: {
next();
int oldNonLHSCount = m_nonLHSCount;
TreeExpression result = parseExpression(context);
m_nonLHSCount = oldNonLHSCount;
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
return result;
}
@@ -1305,7 +1309,7 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
return context.createBoolean(false);
}
case DIVEQUAL:
- case '/': {
+ case DIVIDE: {
/* regexp */
const Identifier* pattern;
const Identifier* flags;
@@ -1318,14 +1322,15 @@ template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(Tre
next();
return context.createRegex(*pattern, *flags, start);
}
+ default:
+ fail();
}
- fail();
}
template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
{
- consumeOrFail('(');
- if (match(')')) {
+ consumeOrFail(OPENPAREN);
+ if (match(CLOSEPAREN)) {
next();
return context.createArguments();
}
@@ -1334,13 +1339,13 @@ template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder&
TreeArgumentsList argList = context.createArgumentsList(firstArg);
TreeArgumentsList tail = argList;
- while (match(',')) {
+ while (match(COMMA)) {
next();
TreeExpression arg = parseAssignmentExpression(context);
failIfFalse(arg);
tail = context.createArgumentsList(tail, arg);
}
- consumeOrFail(')');
+ consumeOrFail(CLOSEPAREN);
return context.createArguments(argList);
}
@@ -1370,7 +1375,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
failIfFalse(base);
while (true) {
switch (token().m_type) {
- case '[': {
+ case OPENBRACKET: {
int expressionEnd = lastTokenEnd();
next();
int nonLHSCount = m_nonLHSCount;
@@ -1378,15 +1383,15 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
TreeExpression property = parseExpression(context);
failIfFalse(property);
base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
- if (!consume(']'))
+ if (!consume(CLOSEBRACKET))
fail();
m_nonLHSCount = nonLHSCount;
break;
}
- case '(': {
+ case OPENPAREN: {
if (newCount) {
newCount--;
- if (match('(')) {
+ if (match(OPENPAREN)) {
int exprEnd = lastTokenEnd();
TreeArguments arguments = parseArguments(context);
failIfFalse(arguments);
@@ -1403,7 +1408,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree
}
break;
}
- case '.': {
+ case DOT: {
int expressionEnd = lastTokenEnd();
next();
matchOrFail(IDENT);
@@ -1446,6 +1451,8 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
m_assignmentCount++;
next();
break;
+ default:
+ break;
}
int end = lastTokenEnd();
@@ -1455,16 +1462,16 @@ template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeB
while (tokenStackDepth) {
switch (context.unaryTokenStackLastType(tokenStackDepth)) {
- case '!':
+ case EXCLAMATION:
expr = context.createLogicalNot(expr);
break;
- case '~':
+ case TILDE:
expr = context.makeBitwiseNotNode(expr);
break;
- case '-':
+ case MINUS:
expr = context.makeNegateNode(expr);
break;
- case '+':
+ case PLUS:
expr = context.createUnaryPlus(expr);
break;
case PLUSPLUS:
diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h
index 554556f..60f284c 100644
--- a/JavaScriptCore/parser/JSParser.h
+++ b/JavaScriptCore/parser/JSParser.h
@@ -30,71 +30,108 @@ namespace JSC {
class Identifier;
class JSGlobalData;
+class SourceCode;
+
+enum {
+ UnaryOpTokenFlag = 64,
+ BinaryOpTokenPrecedenceShift = 7,
+ BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
+ BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift
+};
+
+#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
+#define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))
enum JSTokenType {
- NULLTOKEN = 258,
- TRUETOKEN = 259,
- FALSETOKEN = 260,
- BREAK = 261,
- CASE = 262,
- DEFAULT = 263,
- FOR = 264,
- NEW = 265,
- VAR = 266,
- CONSTTOKEN = 267,
- CONTINUE = 268,
- FUNCTION = 269,
- RETURN = 270,
- VOIDTOKEN = 271,
- DELETETOKEN = 272,
- IF = 273,
- THISTOKEN = 274,
- DO = 275,
- WHILE = 276,
- INTOKEN = 277,
- INSTANCEOF = 278,
- TYPEOF = 279,
- SWITCH = 280,
- WITH = 281,
- RESERVED = 282,
- THROW = 283,
- TRY = 284,
- CATCH = 285,
- FINALLY = 286,
- DEBUGGER = 287,
- IF_WITHOUT_ELSE = 288,
- ELSE = 289,
- EQEQ = 290,
- NE = 291,
- STREQ = 292,
- STRNEQ = 293,
- LE = 294,
- GE = 295,
- OR = 296,
- AND = 297,
- PLUSPLUS = 298,
- MINUSMINUS = 299,
- LSHIFT = 300,
- RSHIFT = 301,
- URSHIFT = 302,
- PLUSEQUAL = 303,
- MINUSEQUAL = 304,
- MULTEQUAL = 305,
- DIVEQUAL = 306,
- LSHIFTEQUAL = 307,
- RSHIFTEQUAL = 308,
- URSHIFTEQUAL = 309,
- ANDEQUAL = 310,
- MODEQUAL = 311,
- XOREQUAL = 312,
- OREQUAL = 313,
- OPENBRACE = 314,
- CLOSEBRACE = 315,
- NUMBER = 316,
- IDENT = 317,
- STRING = 318,
- AUTOPLUSPLUS = 319,
- AUTOMINUSMINUS = 320
+ NULLTOKEN,
+ TRUETOKEN,
+ FALSETOKEN,
+ BREAK,
+ CASE,
+ DEFAULT,
+ FOR,
+ NEW,
+ VAR,
+ CONSTTOKEN,
+ CONTINUE,
+ FUNCTION,
+ RETURN,
+ IF,
+ THISTOKEN,
+ DO,
+ WHILE,
+ SWITCH,
+ WITH,
+ RESERVED,
+ THROW,
+ TRY,
+ CATCH,
+ FINALLY,
+ DEBUGGER,
+ ELSE,
+ OPENBRACE,
+ CLOSEBRACE,
+ OPENPAREN,
+ CLOSEPAREN,
+ OPENBRACKET,
+ CLOSEBRACKET,
+ COMMA,
+ QUESTION,
+ NUMBER,
+ IDENT,
+ STRING,
+ SEMICOLON,
+ COLON,
+ DOT,
+ ERRORTOK,
+ EOFTOK,
+ EQUAL,
+ PLUSEQUAL,
+ MINUSEQUAL,
+ MULTEQUAL,
+ DIVEQUAL,
+ LSHIFTEQUAL,
+ RSHIFTEQUAL,
+ URSHIFTEQUAL,
+ ANDEQUAL,
+ MODEQUAL,
+ XOREQUAL,
+ OREQUAL,
+ LastUntaggedToken,
+
+ // Begin tagged tokens
+ PLUSPLUS = 0 | UnaryOpTokenFlag,
+ MINUSMINUS = 1 | UnaryOpTokenFlag,
+ EXCLAMATION = 2 | UnaryOpTokenFlag,
+ TILDE = 3 | UnaryOpTokenFlag,
+ AUTOPLUSPLUS = 4 | UnaryOpTokenFlag,
+ AUTOMINUSMINUS = 5 | UnaryOpTokenFlag,
+ TYPEOF = 6 | UnaryOpTokenFlag,
+ VOIDTOKEN = 7 | UnaryOpTokenFlag,
+ DELETETOKEN = 8 | UnaryOpTokenFlag,
+ OR = 0 | BINARY_OP_PRECEDENCE(1),
+ AND = 1 | BINARY_OP_PRECEDENCE(2),
+ BITOR = 2 | BINARY_OP_PRECEDENCE(3),
+ BITXOR = 3 | BINARY_OP_PRECEDENCE(4),
+ BITAND = 4 | BINARY_OP_PRECEDENCE(5),
+ EQEQ = 5 | BINARY_OP_PRECEDENCE(6),
+ NE = 6 | BINARY_OP_PRECEDENCE(6),
+ STREQ = 7 | BINARY_OP_PRECEDENCE(6),
+ STRNEQ = 8 | BINARY_OP_PRECEDENCE(6),
+ LT = 9 | BINARY_OP_PRECEDENCE(7),
+ GT = 10 | BINARY_OP_PRECEDENCE(7),
+ LE = 11 | BINARY_OP_PRECEDENCE(7),
+ GE = 12 | BINARY_OP_PRECEDENCE(7),
+ INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7),
+ INTOKEN = 14 | IN_OP_PRECEDENCE(7),
+ LSHIFT = 15 | BINARY_OP_PRECEDENCE(8),
+ RSHIFT = 16 | BINARY_OP_PRECEDENCE(8),
+ URSHIFT = 17 | BINARY_OP_PRECEDENCE(8),
+ PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+ MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+ TIMES = 20 | BINARY_OP_PRECEDENCE(10),
+ DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
+ MOD = 22 | BINARY_OP_PRECEDENCE(10)
};
union JSTokenData {
@@ -102,22 +139,20 @@ union JSTokenData {
double doubleValue;
const Identifier* ident;
};
-typedef JSTokenData YYSTYPE;
struct JSTokenInfo {
- JSTokenInfo() : last_line(0) {}
- int first_line;
- int last_line;
- int first_column;
- int last_column;
+ JSTokenInfo() : line(0) {}
+ int line;
+ int startOffset;
+ int endOffset;
};
-typedef JSTokenInfo YYLTYPE;
+
struct JSToken {
- int m_type;
+ JSTokenType m_type;
JSTokenData m_data;
JSTokenInfo m_info;
};
-int jsParse(JSGlobalData*);
+int jsParse(JSGlobalData*, const SourceCode*);
}
#endif // JSParser_h
diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp
index 660b1a4..45fe007 100644
--- a/JavaScriptCore/parser/Lexer.cpp
+++ b/JavaScriptCore/parser/Lexer.cpp
@@ -56,7 +56,14 @@ enum CharacterTypes {
CharacterLineTerminator,
CharacterExclamationMark,
- CharacterSimple,
+ CharacterOpenParen,
+ CharacterCloseParen,
+ CharacterOpenBracket,
+ CharacterCloseBracket,
+ CharacterComma,
+ CharacterColon,
+ CharacterQuestion,
+ CharacterTilde,
CharacterQuote,
CharacterDot,
CharacterSlash,
@@ -81,7 +88,7 @@ enum CharacterTypes {
};
// 128 ascii codes
-static unsigned char AsciiCharacters[128] = {
+static unsigned short AsciiCharacters[128] = {
/* 0 - Null */ CharacterInvalid,
/* 1 - Start of Heading */ CharacterInvalid,
/* 2 - Start of Text */ CharacterInvalid,
@@ -122,11 +129,11 @@ static unsigned char AsciiCharacters[128] = {
/* 37 - % */ CharacterModulo,
/* 38 - & */ CharacterAnd,
/* 39 - ' */ CharacterQuote,
-/* 40 - ( */ CharacterSimple,
-/* 41 - ) */ CharacterSimple,
+/* 40 - ( */ CharacterOpenParen,
+/* 41 - ) */ CharacterCloseParen,
/* 42 - * */ CharacterMultiply,
/* 43 - + */ CharacterAdd,
-/* 44 - , */ CharacterSimple,
+/* 44 - , */ CharacterComma,
/* 45 - - */ CharacterSub,
/* 46 - . */ CharacterDot,
/* 47 - / */ CharacterSlash,
@@ -140,12 +147,12 @@ static unsigned char AsciiCharacters[128] = {
/* 55 - 7 */ CharacterNumber,
/* 56 - 8 */ CharacterNumber,
/* 57 - 9 */ CharacterNumber,
-/* 58 - : */ CharacterSimple,
+/* 58 - : */ CharacterColon,
/* 59 - ; */ CharacterSemicolon,
/* 60 - < */ CharacterLess,
/* 61 - = */ CharacterEqual,
/* 62 - > */ CharacterGreater,
-/* 63 - ? */ CharacterSimple,
+/* 63 - ? */ CharacterQuestion,
/* 64 - @ */ CharacterInvalid,
/* 65 - A */ CharacterAlpha,
/* 66 - B */ CharacterAlpha,
@@ -173,9 +180,9 @@ static unsigned char AsciiCharacters[128] = {
/* 88 - X */ CharacterAlpha,
/* 89 - Y */ CharacterAlpha,
/* 90 - Z */ CharacterAlpha,
-/* 91 - [ */ CharacterSimple,
+/* 91 - [ */ CharacterOpenBracket,
/* 92 - \ */ CharacterBackSlash,
-/* 93 - ] */ CharacterSimple,
+/* 93 - ] */ CharacterCloseBracket,
/* 94 - ^ */ CharacterXor,
/* 95 - _ */ CharacterAlpha,
/* 96 - ` */ CharacterInvalid,
@@ -208,7 +215,7 @@ static unsigned char AsciiCharacters[128] = {
/* 123 - { */ CharacterOpenBrace,
/* 124 - | */ CharacterOr,
/* 125 - } */ CharacterCloseBrace,
-/* 126 - ~ */ CharacterSimple,
+/* 126 - ~ */ CharacterTilde,
/* 127 - Delete */ CharacterInvalid,
};
@@ -357,8 +364,14 @@ static inline int singleEscape(int c)
return 0x0C;
case 'r':
return 0x0D;
+ case '\\':
+ return '\\';
+ case '\'':
+ return '\'';
+ case '"':
+ return '"';
default:
- return c;
+ return 0;
}
}
@@ -381,15 +394,92 @@ inline void Lexer::record16(int c)
record16(UChar(static_cast<unsigned short>(c)));
}
-int Lexer::lex(void* p1, void* p2)
+ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp)
+{
+ int stringQuoteCharacter = m_current;
+ shift();
+
+ const UChar* stringStart = currentCharacter();
+
+ while (m_current != stringQuoteCharacter) {
+ if (UNLIKELY(m_current == '\\')) {
+ if (stringStart != currentCharacter())
+ m_buffer16.append(stringStart, currentCharacter() - stringStart);
+ shift();
+
+ int escape = singleEscape(m_current);
+
+ // Most common escape sequences first
+ if (escape) {
+ record16(escape);
+ shift();
+ } else if (UNLIKELY(isLineTerminator(m_current)))
+ shiftLineTerminator();
+ else if (m_current == 'x') {
+ shift();
+ if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
+ int prev = m_current;
+ shift();
+ record16(convertHex(prev, m_current));
+ shift();
+ } else
+ record16('x');
+ } else if (m_current == 'u') {
+ shift();
+ int character = getUnicodeCharacter();
+ if (character != -1)
+ record16(character);
+ else if (m_current == stringQuoteCharacter)
+ record16('u');
+ else // Only stringQuoteCharacter allowed after \u
+ return false;
+ } else if (isASCIIOctalDigit(m_current)) {
+ // Octal character sequences
+ int character1 = m_current;
+ shift();
+ if (isASCIIOctalDigit(m_current)) {
+ // Two octal characters
+ int character2 = m_current;
+ shift();
+ if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
+ record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
+ shift();
+ } else
+ record16((character1 - '0') * 8 + character2 - '0');
+ } else
+ record16(character1 - '0');
+ } else if (m_current != -1) {
+ record16(m_current);
+ shift();
+ } else
+ return false;
+
+ stringStart = currentCharacter();
+ continue;
+ } else if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
+ // New-line or end of input is not allowed
+ if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
+ return false;
+ // Anything else is just a normal character
+ }
+ shift();
+ }
+
+ if (currentCharacter() != stringStart)
+ m_buffer16.append(stringStart, currentCharacter() - stringStart);
+ lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+ m_buffer16.resize(0);
+ return true;
+}
+
+JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp)
{
ASSERT(!m_error);
ASSERT(m_buffer8.isEmpty());
ASSERT(m_buffer16.isEmpty());
- YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
- YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
- int token = 0;
+ JSTokenType token = ERRORTOK;
+ int identChar = 0;
m_terminator = false;
start:
@@ -398,20 +488,13 @@ start:
int startOffset = currentOffset();
- if (UNLIKELY(m_current == -1)) {
- if (!m_terminator && !m_delimited && !m_isReparsing) {
- // automatic semicolon insertion if program incomplete
- token = ';';
- goto doneSemicolon;
- }
- return 0;
- }
+ if (UNLIKELY(m_current == -1))
+ return EOFTOK;
m_delimited = false;
- ASSERT(m_current >= 0);
- if (m_current < 128) {
- ASSERT(isASCII(m_current));
+ if (isASCII(m_current)) {
+ ASSERT(m_current >= 0 && m_current < 128);
switch (AsciiCharacters[m_current]) {
case CharacterGreater:
@@ -441,7 +524,7 @@ start:
token = GE;
break;
}
- token = '>';
+ token = GT;
break;
case CharacterEqual:
shift();
@@ -455,7 +538,7 @@ start:
token = EQEQ;
break;
}
- token = '=';
+ token = EQUAL;
break;
case CharacterLess:
shift();
@@ -478,7 +561,7 @@ start:
token = LE;
break;
}
- token = '<';
+ token = LT;
break;
case CharacterExclamationMark:
shift();
@@ -492,7 +575,7 @@ start:
token = NE;
break;
}
- token = '!';
+ token = EXCLAMATION;
break;
case CharacterAdd:
shift();
@@ -506,7 +589,7 @@ start:
token = PLUSEQUAL;
break;
}
- token = '+';
+ token = PLUS;
break;
case CharacterSub:
shift();
@@ -524,7 +607,7 @@ start:
token = MINUSEQUAL;
break;
}
- token = '-';
+ token = MINUS;
break;
case CharacterMultiply:
shift();
@@ -533,7 +616,7 @@ start:
token = MULTEQUAL;
break;
}
- token = '*';
+ token = TIMES;
break;
case CharacterSlash:
shift();
@@ -550,7 +633,7 @@ start:
token = DIVEQUAL;
break;
}
- token = '/';
+ token = DIVIDE;
break;
case CharacterAnd:
shift();
@@ -564,7 +647,7 @@ start:
token = ANDEQUAL;
break;
}
- token = '&';
+ token = BITAND;
break;
case CharacterXor:
shift();
@@ -573,7 +656,7 @@ start:
token = XOREQUAL;
break;
}
- token = '^';
+ token = BITXOR;
break;
case CharacterModulo:
shift();
@@ -582,7 +665,7 @@ start:
token = MODEQUAL;
break;
}
- token = '%';
+ token = MOD;
break;
case CharacterOr:
shift();
@@ -596,7 +679,7 @@ start:
token = OR;
break;
}
- token = '|';
+ token = BITOR;
break;
case CharacterDot:
shift();
@@ -604,16 +687,44 @@ start:
record8('.');
goto inNumberAfterDecimalPoint;
}
- token = '.';
+ token = DOT;
+ break;
+ case CharacterOpenParen:
+ token = OPENPAREN;
+ shift();
+ break;
+ case CharacterCloseParen:
+ token = CLOSEPAREN;
+ shift();
+ break;
+ case CharacterOpenBracket:
+ token = OPENBRACKET;
+ shift();
break;
- case CharacterSimple:
- token = m_current;
+ case CharacterCloseBracket:
+ token = CLOSEBRACKET;
+ shift();
+ break;
+ case CharacterComma:
+ token = COMMA;
+ shift();
+ break;
+ case CharacterColon:
+ token = COLON;
+ shift();
+ break;
+ case CharacterQuestion:
+ token = QUESTION;
+ shift();
+ break;
+ case CharacterTilde:
+ token = TILDE;
shift();
break;
case CharacterSemicolon:
m_delimited = true;
shift();
- token = ';';
+ token = SEMICOLON;
break;
case CharacterOpenBrace:
lvalp->intValue = currentOffset();
@@ -633,7 +744,12 @@ start:
case CharacterNumber:
goto startNumber;
case CharacterQuote:
- goto startString;
+ if (UNLIKELY(!parseString(lvalp)))
+ goto returnError;
+ shift();
+ m_delimited = false;
+ token = STRING;
+ break;
case CharacterAlpha:
ASSERT(isIdentStart(m_current));
goto startIdentifierOrKeyword;
@@ -643,7 +759,7 @@ start:
m_atLineStart = true;
m_terminator = true;
if (lastTokenWasRestrKeyword()) {
- token = ';';
+ token = SEMICOLON;
goto doneSemicolon;
}
goto start;
@@ -655,7 +771,6 @@ start:
}
} else {
// Rare characters
- ASSERT(!isASCII(m_current));
if (isNonASCIIIdentStart(m_current))
goto startIdentifierOrKeyword;
@@ -663,10 +778,8 @@ start:
shiftLineTerminator();
m_atLineStart = true;
m_terminator = true;
- if (lastTokenWasRestrKeyword()) {
- token = ';';
+ if (lastTokenWasRestrKeyword())
goto doneSemicolon;
- }
goto start;
}
goto returnError;
@@ -675,109 +788,16 @@ start:
m_atLineStart = false;
goto returnToken;
-startString: {
- int stringQuoteCharacter = m_current;
- shift();
-
- const UChar* stringStart = currentCharacter();
- while (m_current != stringQuoteCharacter) {
- // Fast check for characters that require special handling.
- // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
- // as possible, and lets through all common ASCII characters.
- if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
- m_buffer16.append(stringStart, currentCharacter() - stringStart);
- goto inString;
- }
- shift();
- }
- lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
- shift();
- m_atLineStart = false;
- m_delimited = false;
- token = STRING;
- goto returnToken;
-
-inString:
- while (m_current != stringQuoteCharacter) {
- if (m_current == '\\')
- goto inStringEscapeSequence;
- if (UNLIKELY(isLineTerminator(m_current)))
- goto returnError;
- if (UNLIKELY(m_current == -1))
- goto returnError;
- record16(m_current);
- shift();
- }
- goto doneString;
-
-inStringEscapeSequence:
- shift();
- if (m_current == 'x') {
- shift();
- if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
- int prev = m_current;
- shift();
- record16(convertHex(prev, m_current));
- shift();
- goto inString;
- }
- record16('x');
- if (m_current == stringQuoteCharacter)
- goto doneString;
- goto inString;
- }
- if (m_current == 'u') {
- shift();
- token = getUnicodeCharacter();
- if (token != -1) {
- record16(token);
- goto inString;
- }
- if (m_current == stringQuoteCharacter) {
- record16('u');
- goto doneString;
- }
- goto returnError;
- }
- if (isASCIIOctalDigit(m_current)) {
- int char1 = m_current;
- shift();
- if (char1 >= '0' && char1 <= '3' && isASCIIOctalDigit(m_current) && isASCIIOctalDigit(peek(1))) {
- int char2 = m_current;
- shift();
- record16((char1 - '0') * 64 + (char2 - '0') * 8 + m_current - '0');
- shift();
- goto inString;
- }
- if (isASCIIOctalDigit(m_current)) {
- record16((char1 - '0') * 8 + m_current - '0');
- shift();
- goto inString;
- }
- record16(char1 - '0');
- goto inString;
- }
- if (isLineTerminator(m_current)) {
- shiftLineTerminator();
- goto inString;
- }
- if (m_current == -1)
- goto returnError;
- record16(singleEscape(m_current));
- shift();
- goto inString;
-}
-
startIdentifierWithBackslash: {
shift();
if (UNLIKELY(m_current != 'u'))
goto returnError;
shift();
- token = getUnicodeCharacter();
- if (UNLIKELY(token == -1))
+ identChar = getUnicodeCharacter();
+ if (UNLIKELY(identChar == -1))
goto returnError;
- if (UNLIKELY(!isIdentStart(token)))
+ if (UNLIKELY(!isIdentStart(identChar)))
goto returnError;
goto inIdentifierAfterCharacterCheck;
}
@@ -800,13 +820,13 @@ startIdentifierOrKeyword: {
if (UNLIKELY(m_current != 'u'))
goto returnError;
shift();
- token = getUnicodeCharacter();
- if (UNLIKELY(token == -1))
+ identChar = getUnicodeCharacter();
+ if (UNLIKELY(identChar == -1))
goto returnError;
- if (UNLIKELY(!isIdentPart(token)))
+ if (UNLIKELY(!isIdentPart(identChar)))
goto returnError;
inIdentifierAfterCharacterCheck:
- record16(token);
+ record16(identChar);
while (isIdentPart(m_current)) {
record16(m_current);
@@ -818,7 +838,7 @@ inIdentifierAfterCharacterCheck:
inSingleLineComment:
while (!isLineTerminator(m_current)) {
if (UNLIKELY(m_current == -1))
- return 0;
+ return EOFTOK;
shift();
}
shiftLineTerminator();
@@ -985,7 +1005,7 @@ doneNumeric:
goto returnToken;
doneSemicolon:
- token = ';';
+ token = SEMICOLON;
m_delimited = true;
goto returnToken;
@@ -1002,34 +1022,23 @@ doneIdentifierOrKeyword: {
m_delimited = false;
m_buffer16.resize(0);
const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
- token = entry ? entry->lexerValue() : static_cast<int>(IDENT);
- goto returnToken;
-}
-
-doneString:
- // Atomize constant strings in case they're later used in property lookup.
- shift();
- m_atLineStart = false;
- m_delimited = false;
- lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
- m_buffer16.resize(0);
- token = STRING;
+ token = entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
// Fall through into returnToken.
+}
returnToken: {
int lineNumber = m_lineNumber;
- llocp->first_line = lineNumber;
- llocp->last_line = lineNumber;
- llocp->first_column = startOffset;
- llocp->last_column = currentOffset();
+ llocp->line = lineNumber;
+ llocp->startOffset = startOffset;
+ llocp->endOffset = currentOffset();
m_lastToken = token;
return token;
}
returnError:
m_error = true;
- return -1;
+ return ERRORTOK;
}
bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
@@ -1136,7 +1145,6 @@ bool Lexer::skipRegExp()
void Lexer::clear()
{
m_arena = 0;
- m_codeWithoutBOMs.clear();
Vector<char> newBuffer8;
m_buffer8.swap(newBuffer8);
diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h
index ec254ce..5ab7ad7 100644
--- a/JavaScriptCore/parser/Lexer.h
+++ b/JavaScriptCore/parser/Lexer.h
@@ -23,6 +23,7 @@
#ifndef Lexer_h
#define Lexer_h
+#include "JSParser.h"
#include "Lookup.h"
#include "ParserArena.h"
#include "SourceCode.h"
@@ -49,7 +50,7 @@ namespace JSC {
void setIsReparsing() { m_isReparsing = true; }
// Functions for the parser itself.
- int lex(void* lvalp, void* llocp);
+ JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp);
int lineNumber() const { return m_lineNumber; }
void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
int lastLineNumber() const { return m_lastLineNumber; }
@@ -61,6 +62,12 @@ namespace JSC {
// Functions for use after parsing.
bool sawError() const { return m_error; }
void clear();
+ int currentOffset() { return m_code - m_codeStart; }
+ void setOffset(int offset)
+ {
+ m_code = m_codeStart + offset;
+ m_current = *m_code;
+ }
private:
friend class JSGlobalData;
@@ -86,8 +93,10 @@ namespace JSC {
ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
+ ALWAYS_INLINE bool parseString(JSTokenData* lvalp);
+
static const size_t initialReadBufferCapacity = 32;
-
+
int m_lineNumber;
int m_lastLineNumber;
@@ -113,8 +122,6 @@ namespace JSC {
JSGlobalData* m_globalData;
const HashTable m_keywordTable;
-
- Vector<UChar> m_codeWithoutBOMs;
};
inline bool Lexer::isWhiteSpace(int ch)
@@ -137,12 +144,6 @@ namespace JSC {
return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
}
- // A bridge for yacc from the C world to the C++ world.
- inline int jscyylex(void* lvalp, void* llocp, void* globalData)
- {
- return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
- }
-
} // namespace JSC
#endif // Lexer_h
diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp
index 4b97e9a..ffea524 100644
--- a/JavaScriptCore/parser/Nodes.cpp
+++ b/JavaScriptCore/parser/Nodes.cpp
@@ -98,7 +98,7 @@ ScopeNode::ScopeNode(JSGlobalData* globalData)
ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
: StatementNode(globalData)
, ParserArenaRefCounted(globalData)
- , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
+ , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants)))
, m_features(features)
, m_source(source)
{
diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h
index 57c8f4f..6206384 100644
--- a/JavaScriptCore/parser/Nodes.h
+++ b/JavaScriptCore/parser/Nodes.h
@@ -404,12 +404,13 @@ namespace JSC {
class PropertyNode : public ParserArenaFreeable {
public:
- enum Type { Constant, Getter, Setter };
+ enum Type { Constant = 1, Getter = 2, Setter = 4 };
PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
const Identifier& name() const { return m_name; }
+ Type type() const { return m_type; }
private:
friend class PropertyListNode;
diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp
index b97754f..39ff597 100644
--- a/JavaScriptCore/parser/Parser.cpp
+++ b/JavaScriptCore/parser/Parser.cpp
@@ -60,7 +60,7 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
Lexer& lexer = *globalData->lexer;
lexer.setCode(*m_source, m_arena);
- int parseError = jsParse(globalData);
+ int parseError = jsParse(globalData, m_source);
int lineNumber = lexer.lineNumber();
bool lexError = lexer.sawError();
lexer.clear();
diff --git a/JavaScriptCore/parser/ParserArena.cpp b/JavaScriptCore/parser/ParserArena.cpp
index a8e8159..9c96de7 100644
--- a/JavaScriptCore/parser/ParserArena.cpp
+++ b/JavaScriptCore/parser/ParserArena.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
@@ -27,13 +27,14 @@
#include "ParserArena.h"
#include "Nodes.h"
+#include <wtf/PassOwnPtr.h>
namespace JSC {
ParserArena::ParserArena()
: m_freeableMemory(0)
, m_freeablePoolEnd(0)
- , m_identifierArena(new IdentifierArena)
+ , m_identifierArena(adoptPtr(new IdentifierArena))
{
}
diff --git a/JavaScriptCore/parser/SourceProvider.h b/JavaScriptCore/parser/SourceProvider.h
index 87ea960..6b9c028 100644
--- a/JavaScriptCore/parser/SourceProvider.h
+++ b/JavaScriptCore/parser/SourceProvider.h
@@ -38,6 +38,7 @@ namespace JSC {
public:
SourceProvider(const UString& url)
: m_url(url)
+ , m_validated(false)
{
}
virtual ~SourceProvider() { }
@@ -49,8 +50,12 @@ namespace JSC {
const UString& url() { return m_url; }
intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
+ bool isValid() const { return m_validated; }
+ void setValid() { m_validated = true; }
+
private:
UString m_url;
+ bool m_validated;
};
class UStringSourceProvider : public SourceProvider {
diff --git a/JavaScriptCore/parser/SyntaxChecker.h b/JavaScriptCore/parser/SyntaxChecker.h
index cad89f6..e05facd 100644
--- a/JavaScriptCore/parser/SyntaxChecker.h
+++ b/JavaScriptCore/parser/SyntaxChecker.h
@@ -29,7 +29,7 @@
namespace JSC {
class SyntaxChecker {
public:
- SyntaxChecker(JSGlobalData*, Lexer*)
+ SyntaxChecker(JSGlobalData* , Lexer*)
{
}
@@ -39,7 +39,25 @@ public:
typedef int SourceElements;
typedef int Arguments;
typedef int Comma;
- typedef int Property;
+ struct Property {
+ ALWAYS_INLINE Property(void* = 0)
+ : type((PropertyNode::Type)0)
+ {
+ }
+ ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
+ : name(ident)
+ , type(ty)
+ {
+ }
+ ALWAYS_INLINE Property(PropertyNode::Type ty)
+ : name(0)
+ , type(ty)
+ {
+ }
+ ALWAYS_INLINE bool operator!() { return !type; }
+ const Identifier* name;
+ PropertyNode::Type type;
+ };
typedef int PropertyList;
typedef int ElementList;
typedef int ArgumentsList;
@@ -90,10 +108,21 @@ public:
int createArguments(int) { return 1; }
int createArgumentsList(int) { return 1; }
int createArgumentsList(int, int) { return 1; }
- int createProperty(const Identifier*, int, PropertyNode::Type) { return 1; }
- int createProperty(double, int, PropertyNode::Type) { return 1; }
- int createPropertyList(int) { return 1; }
- int createPropertyList(int, int) { return 1; }
+ template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
+ {
+ ASSERT(name);
+ if (!complete)
+ return Property(type);
+ return Property(name, type);
+ }
+ template <bool complete> Property createProperty(JSGlobalData* globalData, double name, int, PropertyNode::Type type)
+ {
+ if (!complete)
+ return Property(type);
+ return Property(&globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name), type);
+ }
+ int createPropertyList(Property) { return 1; }
+ int createPropertyList(Property, int) { return 1; }
int createElementList(int, int) { return 1; }
int createElementList(int, int, int) { return 1; }
int createFormalParameterList(const Identifier&) { return 1; }
@@ -127,7 +156,13 @@ public:
int createDebugger(int, int) { return 1; }
int createConstStatement(int, int, int) { return 1; }
int appendConstDecl(int, const Identifier*, int) { return 1; }
- int createGetterOrSetterProperty(const Identifier*, const Identifier*, int, int, int, int, int, int) { return 1; }
+ template <bool strict> Property createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int)
+ {
+ ASSERT(name);
+ if (!strict)
+ return Property(type);
+ return Property(name, type);
+ }
void appendStatement(int, int) { }
void addVar(const Identifier*, bool) { }
@@ -151,6 +186,8 @@ public:
void assignmentStackAppend(int, int, int, int, int, Operator) { }
int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; }
+ const Identifier& getName(const Property& property) { ASSERT(property.name); return *property.name; }
+ PropertyNode::Type getType(const Property& property) { return property.type; }
};
}
diff --git a/JavaScriptCore/qt/ChangeLog b/JavaScriptCore/qt/ChangeLog
index 8f2d423..71b4a21 100644
--- a/JavaScriptCore/qt/ChangeLog
+++ b/JavaScriptCore/qt/ChangeLog
@@ -1,3 +1,100 @@
+2010-07-09 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ Implementation of the QScriptValue::propertyFlags function.
+
+ The function returns the flags of a property with the given name,
+ using a given mode to resolve the property. This is a simple
+ implementation that is sufficient to test the QScriptValueIterator.
+
+ [Qt] QScriptValue API should have a property flag accessor.
+ https://bugs.webkit.org/show_bug.cgi?id=41769
+
+ * api/qscriptvalue.cpp:
+ (QScriptValue::propertyFlags):
+ * api/qscriptvalue.h:
+ * api/qscriptvalue_p.h:
+ (QScriptValuePrivate::propertyFlags):
+ * tests/qscriptvalue/tst_qscriptvalue.cpp:
+ (tst_QScriptValue::propertyFlag_data):
+ (tst_QScriptValue::propertyFlag):
+ * tests/qscriptvalue/tst_qscriptvalue.h:
+
+2010-07-07 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Implementation of QScriptValue::isArray()
+ https://bugs.webkit.org/show_bug.cgi?id=41713
+
+ Since we don't have access to the [[Class]] internal property of
+ builtins (including Array), the solution was to keep the original 'Array'
+ (constructor) and 'Array.prototype' objects and use them to identify
+ if a given object is an Array.
+
+ Also uncomment some tests and add some tests of newArray() that
+ depended on isArray().
+
+ * api/qscriptengine_p.cpp:
+ (QScriptEnginePrivate::QScriptEnginePrivate):
+ (QScriptEnginePrivate::~QScriptEnginePrivate):
+ * api/qscriptengine_p.h:
+ (QScriptEnginePrivate::isArray):
+ * api/qscriptvalue.cpp:
+ (QScriptValue::isArray):
+ * api/qscriptvalue.h:
+ * api/qscriptvalue_p.h:
+ (QScriptValuePrivate::isArray):
+ * tests/qscriptengine/tst_qscriptengine.cpp:
+ (tst_QScriptEngine::newArray):
+
+2010-07-06 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ Implementation of QScriptValue properties accessors.
+
+ The patch contains implementation of the QScriptValue::property() and
+ the QScriptValue::setProperty(). It is not full functionality, as these
+ method are too complex for one patch, but it is enough to cover about
+ 95% of use cases.
+
+ Missing functionality:
+ - Few of the PropertyFlags are ignored.
+ - Only a public part of the ResolveFlags can be used (ResolveLocal,
+ ResolvePrototype).
+
+ A lot of new test cases were added.
+
+ [Qt] QScriptValue should have API for accessing object properties
+ https://bugs.webkit.org/show_bug.cgi?id=40903
+
+ * api/qscriptconverter_p.h:
+ (QScriptConverter::toPropertyFlags):
+ * api/qscriptstring_p.h:
+ (QScriptStringPrivate::operator JSStringRef):
+ * api/qscriptvalue.cpp:
+ (QScriptValue::property):
+ (QScriptValue::setProperty):
+ * api/qscriptvalue.h:
+ (QScriptValue::):
+ * api/qscriptvalue_p.h:
+ (QScriptValuePrivate::assignEngine):
+ (QScriptValuePrivate::property):
+ (QScriptValuePrivate::hasOwnProperty):
+ (QScriptValuePrivate::setProperty):
+ (QScriptValuePrivate::deleteProperty):
+ * tests/qscriptvalue/tst_qscriptvalue.cpp:
+ (tst_QScriptValue::getPropertySimple_data):
+ (tst_QScriptValue::getPropertySimple):
+ (tst_QScriptValue::setPropertySimple):
+ (tst_QScriptValue::getPropertyResolveFlag):
+ (tst_QScriptValue::getSetProperty):
+ (tst_QScriptValue::setProperty_data):
+ (tst_QScriptValue::setProperty):
+ * tests/qscriptvalue/tst_qscriptvalue.h:
+
2010-07-02 Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
Reviewed by Simon Hausmann.
diff --git a/JavaScriptCore/qt/api/qscriptconverter_p.h b/JavaScriptCore/qt/api/qscriptconverter_p.h
index cd86e20..0c57d95 100644
--- a/JavaScriptCore/qt/api/qscriptconverter_p.h
+++ b/JavaScriptCore/qt/api/qscriptconverter_p.h
@@ -20,7 +20,9 @@
#ifndef qscriptconverter_p_h
#define qscriptconverter_p_h
+#include "qscriptvalue.h"
#include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qglobal.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qstring.h>
#include <QtCore/qvarlengtharray.h>
@@ -127,6 +129,18 @@ public:
buf.append(0);
return QString::fromLatin1(buf.constData());
}
+
+ static JSPropertyAttributes toPropertyFlags(const QFlags<QScriptValue::PropertyFlag>& flags)
+ {
+ JSPropertyAttributes attr = 0;
+ if (flags.testFlag(QScriptValue::ReadOnly))
+ attr |= kJSPropertyAttributeReadOnly;
+ if (flags.testFlag(QScriptValue::Undeletable))
+ attr |= kJSPropertyAttributeDontDelete;
+ if (flags.testFlag(QScriptValue::SkipInEnumeration))
+ attr |= kJSPropertyAttributeDontEnum;
+ return attr;
+ }
};
#endif // qscriptconverter_p_h
diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp
index 23e41c4..360de29 100644
--- a/JavaScriptCore/qt/api/qscriptengine_p.cpp
+++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp
@@ -32,11 +32,32 @@ QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine)
: q_ptr(const_cast<QScriptEngine*>(engine))
, m_context(JSGlobalContextCreate(0))
, m_exception(0)
+ , m_arrayConstructor(0)
+ , m_arrayPrototype(0)
{
+ JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
+
+ // Save references to the Array constructor and prototype.
+ JSRetainPtr<JSStringRef> arrayName(Adopt, JSStringCreateWithUTF8CString("Array"));
+ JSValueRef arrayConstructor = JSObjectGetProperty(m_context, globalObject, arrayName.get(), /* exception */ 0);
+ Q_ASSERT(JSValueIsObject(m_context, arrayConstructor));
+ m_arrayConstructor = JSValueToObject(m_context, arrayConstructor, /* exception */ 0);
+ JSValueProtect(m_context, m_arrayConstructor);
+
+ // Note that this is not the [[Prototype]] internal property (which we could
+ // get via JSObjectGetPrototype), but the Array.prototype, that will be set
+ // as [[Prototype]] of Array instances.
+ JSRetainPtr<JSStringRef> prototypeName(Adopt, JSStringCreateWithUTF8CString("prototype"));
+ JSValueRef arrayPrototype = JSObjectGetProperty(m_context, m_arrayConstructor, prototypeName.get(), /* exception */ 0);
+ Q_ASSERT(JSValueIsObject(m_context, arrayPrototype));
+ m_arrayPrototype = arrayPrototype;
+ JSValueProtect(m_context, m_arrayPrototype);
}
QScriptEnginePrivate::~QScriptEnginePrivate()
{
+ JSValueUnprotect(m_context, m_arrayConstructor);
+ JSValueUnprotect(m_context, m_arrayPrototype);
if (m_exception)
JSValueUnprotect(m_context, m_exception);
JSGlobalContextRelease(m_context);
diff --git a/JavaScriptCore/qt/api/qscriptengine_p.h b/JavaScriptCore/qt/api/qscriptengine_p.h
index 30ee039..401c051 100644
--- a/JavaScriptCore/qt/api/qscriptengine_p.h
+++ b/JavaScriptCore/qt/api/qscriptengine_p.h
@@ -77,10 +77,15 @@ public:
inline QScriptStringPrivate* toStringHandle(const QString& str) const;
inline operator JSGlobalContextRef() const;
+
+ inline bool isArray(JSValueRef value) const;
private:
QScriptEngine* q_ptr;
JSGlobalContextRef m_context;
JSValueRef m_exception;
+
+ JSObjectRef m_arrayConstructor;
+ JSValueRef m_arrayPrototype;
};
@@ -211,4 +216,11 @@ QScriptEnginePrivate::operator JSGlobalContextRef() const
return m_context;
}
+bool QScriptEnginePrivate::isArray(JSValueRef value) const
+{
+ // JSC API doesn't export the [[Class]] information for the builtins. But we know that a value
+ // is an array if it was created with the Array constructor or if it is the Array.prototype.
+ return JSValueIsInstanceOfConstructor(m_context, value, m_arrayConstructor, /* exception */ 0) || JSValueIsStrictEqual(m_context, value, m_arrayPrototype);
+}
+
#endif
diff --git a/JavaScriptCore/qt/api/qscriptstring_p.h b/JavaScriptCore/qt/api/qscriptstring_p.h
index d4fc88e..fe84f4d 100644
--- a/JavaScriptCore/qt/api/qscriptstring_p.h
+++ b/JavaScriptCore/qt/api/qscriptstring_p.h
@@ -46,6 +46,8 @@ public:
inline quint64 id() const;
+ inline operator JSStringRef() const;
+
private:
JSStringRef m_string;
};
@@ -109,4 +111,14 @@ quint64 QScriptStringPrivate::id() const
return reinterpret_cast<quint32>(m_string);
}
+/*!
+ \internal
+ This method should be used for invoking JSC functions.
+ \note This method keeps ownership of an internal JSStringRef.
+*/
+QScriptStringPrivate::operator JSStringRef() const
+{
+ return m_string;
+}
+
#endif // qscriptstring_p_h
diff --git a/JavaScriptCore/qt/api/qscriptvalue.cpp b/JavaScriptCore/qt/api/qscriptvalue.cpp
index e309fb7..a7d0b7b 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.cpp
+++ b/JavaScriptCore/qt/api/qscriptvalue.cpp
@@ -313,6 +313,17 @@ bool QScriptValue::isError() const
}
/*!
+ Returns true if this QScriptValue is an object of the Array class;
+ otherwise returns false.
+
+ \sa QScriptEngine::newArray()
+*/
+bool QScriptValue::isArray() const
+{
+ return d_ptr->isArray();
+}
+
+/*!
Returns true if this QScriptValue is of the Object type; otherwise
returns false.
@@ -651,6 +662,23 @@ QScriptValue QScriptValue::property(const QString& name, const ResolveFlags& mod
/*!
\overload
+ Returns the value of this QScriptValue's property with the given \a name,
+ using the given \a mode to resolve the property.
+
+ This overload of property() is useful when you need to look up the
+ same property repeatedly, since the lookup can be performed faster
+ when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle(), setProperty()
+*/
+QScriptValue QScriptValue::property(const QScriptString& name, const ResolveFlags& mode) const
+{
+ return QScriptValuePrivate::get(d_ptr->property(QScriptStringPrivate::get(name).constData(), mode));
+}
+
+/*!
+ \overload
+
Returns the property at the given \a arrayIndex, using the given \a
mode to resolve the property.
@@ -665,3 +693,87 @@ QScriptValue QScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode
{
return QScriptValuePrivate::get(d_ptr->property(arrayIndex, mode));
}
+
+/*!
+ Sets the value of this QScriptValue's property with the given \a name to
+ the given \a value.
+
+ If this QScriptValue is not an object, this function does nothing.
+
+ If this QScriptValue does not already have a property with name \a name,
+ a new property is created; the given \a flags then specify how this
+ property may be accessed by script code.
+
+ If \a value is invalid, the property is removed.
+
+ If the property is implemented using a setter function (i.e. has the
+ PropertySetter flag set), calling setProperty() has side-effects on
+ the script engine, since the setter function will be called with the
+ given \a value as argument (possibly resulting in an uncaught script
+ exception).
+
+ Note that you cannot specify custom getter or setter functions for
+ built-in properties, such as the \c{length} property of Array objects
+ or meta properties of QObject objects.
+
+ \sa property()
+*/
+void QScriptValue::setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(name, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ \overload
+
+ Sets the property at the given \a arrayIndex to the given \a value.
+
+ This function is provided for convenience and performance when
+ working with array objects.
+
+ If this QScriptValue is not an Array object, this function behaves
+ as if setProperty() was called with the string representation of \a
+ arrayIndex.
+*/
+void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(arrayIndex, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ Sets the value of this QScriptValue's property with the given \a
+ name to the given \a value. The given \a flags specify how this
+ property may be accessed by script code.
+
+ This overload of setProperty() is useful when you need to set the
+ same property repeatedly, since the operation can be performed
+ faster when the name is represented as an interned string.
+
+ \sa QScriptEngine::toStringHandle()
+*/
+void QScriptValue::setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+ d_ptr->setProperty(QScriptStringPrivate::get(name).constData(), QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString& name, const ResolveFlags& mode) const
+{
+ return d_ptr->propertyFlags(name, mode);
+}
+
+/*!
+ Returns the flags of the property with the given \a name, using the
+ given \a mode to resolve the property.
+
+ \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString& name, const ResolveFlags& mode) const
+{
+ return d_ptr->propertyFlags(QScriptStringPrivate::get(name).constData(), mode);
+}
diff --git a/JavaScriptCore/qt/api/qscriptvalue.h b/JavaScriptCore/qt/api/qscriptvalue.h
index c55d461..991a6a0 100644
--- a/JavaScriptCore/qt/api/qscriptvalue.h
+++ b/JavaScriptCore/qt/api/qscriptvalue.h
@@ -20,6 +20,7 @@
#ifndef qscriptvalue_h
#define qscriptvalue_h
+#include "qscriptstring.h"
#include <QtCore/qlist.h>
#include <QtCore/qshareddata.h>
@@ -34,12 +35,25 @@ typedef double qsreal;
class QScriptValue {
public:
enum ResolveFlag {
- ResolveLocal = 0x00,
- ResolvePrototype = 0x01
+ ResolveLocal = 0x00,
+ ResolvePrototype = 0x01,
+ ResolveScope = 0x02,
+ ResolveFull = ResolvePrototype | ResolveScope
};
-
Q_DECLARE_FLAGS(ResolveFlags, ResolveFlag)
+ enum PropertyFlag {
+ ReadOnly = 0x00000001,
+ Undeletable = 0x00000002,
+ SkipInEnumeration = 0x00000004,
+ PropertyGetter = 0x00000008,
+ PropertySetter = 0x00000010,
+ QObjectMember = 0x00000020,
+ KeepExistingFlags = 0x00000800,
+ UserRange = 0xff000000 // Users may use these as they see fit.
+ };
+ Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
+
enum SpecialValue {
NullValue,
UndefinedValue
@@ -75,8 +89,16 @@ public:
bool instanceOf(const QScriptValue& other) const;
QScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+ QScriptValue property(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
QScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;
+ void setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+ void setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+ void setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+
+ PropertyFlags propertyFlags(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+ PropertyFlags propertyFlags(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
+
QScriptEngine* engine() const;
bool isValid() const;
@@ -89,6 +111,7 @@ public:
bool isUndefined() const;
bool isObject() const;
bool isError() const;
+ bool isArray() const;
QString toString() const;
qsreal toNumber() const;
@@ -102,7 +125,6 @@ public:
QScriptValue call(const QScriptValue& thisObject = QScriptValue(),
const QScriptValueList& args = QScriptValueList());
-
private:
QScriptValue(void*);
QScriptValue(QScriptValuePrivate*);
diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h
index 49bec97..1d319ba 100644
--- a/JavaScriptCore/qt/api/qscriptvalue_p.h
+++ b/JavaScriptCore/qt/api/qscriptvalue_p.h
@@ -101,6 +101,7 @@ public:
inline bool isError();
inline bool isObject();
inline bool isFunction();
+ inline bool isArray();
inline QString toString() const;
inline qsreal toNumber() const;
@@ -121,7 +122,28 @@ public:
inline bool assignEngine(QScriptEnginePrivate* engine);
inline QScriptValuePrivate* property(const QString& name, const QScriptValue::ResolveFlags& mode);
+ inline QScriptValuePrivate* property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
inline QScriptValuePrivate* property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode);
+ inline JSValueRef property(quint32 property, JSValueRef* exception);
+ inline JSValueRef property(JSStringRef property, JSValueRef* exception);
+ inline bool hasOwnProperty(quint32 property);
+ inline bool hasOwnProperty(JSStringRef property);
+ template<typename T>
+ inline QScriptValuePrivate* property(T name, const QScriptValue::ResolveFlags& mode);
+
+ inline void setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(const quint32 indexArray, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+ inline void setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+ inline void setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+ inline void deleteProperty(quint32 property, JSValueRef* exception);
+ inline void deleteProperty(JSStringRef property, JSValueRef* exception);
+ template<typename T>
+ inline void setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+
+ QScriptValue::PropertyFlags propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode);
+ QScriptValue::PropertyFlags propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
+ QScriptValue::PropertyFlags propertyFlags(const JSStringRef name, const QScriptValue::ResolveFlags& mode);
inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
@@ -427,6 +449,20 @@ bool QScriptValuePrivate::isFunction()
}
}
+bool QScriptValuePrivate::isArray()
+{
+ switch (m_state) {
+ case JSValue:
+ if (refinedJSValue() != JSObject)
+ return false;
+ // Fall-through.
+ case JSObject:
+ return m_engine->isArray(*this);
+ default:
+ return false;
+ }
+}
+
QString QScriptValuePrivate::toString() const
{
switch (m_state) {
@@ -744,6 +780,7 @@ inline bool QScriptValuePrivate::instanceOf(QScriptValuePrivate* other)
*/
bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
{
+ Q_ASSERT(engine);
JSValueRef value;
switch (m_state) {
case CBool:
@@ -778,31 +815,252 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
inline QScriptValuePrivate* QScriptValuePrivate::property(const QString& name, const QScriptValue::ResolveFlags& mode)
{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ return property<JSStringRef>(propertyName.get(), mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+ return property<JSStringRef>(*name, mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
+{
+ return property<quint32>(arrayIndex, mode);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(quint32 property, JSValueRef* exception)
+{
+ return JSObjectGetPropertyAtIndex(*m_engine, *this, property, exception);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(JSStringRef property, JSValueRef* exception)
+{
+ return JSObjectGetProperty(*m_engine, *this, property, exception);
+}
+
+/*!
+ \internal
+ This method was created to unify acccess to hasOwnProperty, same function for an array index
+ and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(quint32 property)
+{
+ Q_ASSERT(isObject());
+ // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ return hasOwnProperty(propertyName.get());
+}
+
+/*!
+ \internal
+ This method was created to unify acccess to hasOwnProperty, same function for an array index
+ and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(JSStringRef property)
+{
+ Q_ASSERT(isObject());
+ // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
+ JSRetainPtr<JSStringRef> hasOwnPropertyName(Adopt, JSStringCreateWithUTF8CString("hasOwnProperty"));
+ JSValueRef exception = 0;
+ JSValueRef hasOwnProperty = JSObjectGetProperty(*m_engine, *this, hasOwnPropertyName.get(), &exception);
+ JSValueRef propertyName[] = { JSValueMakeString(*m_engine, property) };
+ JSValueRef result = JSObjectCallAsFunction(*m_engine, const_cast<JSObjectRef>(hasOwnProperty), *this, 1, propertyName, &exception);
+ return exception ? false : JSValueToBoolean(*m_engine, result);
+}
+
+/*!
+ \internal
+ This function gets property of an object.
+ \arg propertyName could be type of quint32 (an array index) or JSStringRef (a property name).
+*/
+template<typename T>
+inline QScriptValuePrivate* QScriptValuePrivate::property(T propertyName, const QScriptValue::ResolveFlags& mode)
+{
if (!isObject())
- return new QScriptValuePrivate;
+ return new QScriptValuePrivate();
- if (mode & QScriptValue::ResolveLocal) {
- qWarning("QScriptValue::property(): ResolveLocal not supported yet.");
+ if ((mode == QScriptValue::ResolveLocal) && (!hasOwnProperty(propertyName)))
+ return new QScriptValuePrivate();
+
+ JSValueRef exception = 0;
+ JSValueRef value = property(propertyName, &exception);
+
+ if (exception) {
+ m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
+ return new QScriptValuePrivate(engine(), exception);
+ }
+ if (JSValueIsUndefined(*m_engine, value))
return new QScriptValuePrivate;
+ return new QScriptValuePrivate(engine(), value);
+}
+
+inline void QScriptValuePrivate::setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ setProperty<JSStringRef>(propertyName.get(), value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(quint32 arrayIndex, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ setProperty<quint32>(arrayIndex, value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+ setProperty<JSStringRef>(*name, value, flags);
+}
+
+/*!
+ \internal
+ This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ if (flags) {
+ // FIXME This could be better, but JSC C API doesn't expose needed functionality. It is
+ // not possible to create / modify a property attribute via an array index.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ JSObjectSetProperty(*m_engine, *this, propertyName.get(), value, flags, exception);
+ return;
}
+ JSObjectSetPropertyAtIndex(*m_engine, *this, property, value, exception);
+}
- JSRetainPtr<JSStringRef> nameRef(Adopt, QScriptConverter::toString(name));
- QScriptValuePrivate* result = new QScriptValuePrivate(m_engine.constData(), JSObjectGetProperty(*m_engine, *this, nameRef.get(), /* exception */ 0));
+/*!
+ \internal
+ This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ JSObjectSetProperty(*m_engine, *this, property, value, flags, exception);
+}
- return result;
+/*!
+ \internal
+ This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex
+ which doesn't exist now.
+*/
+inline void QScriptValuePrivate::deleteProperty(quint32 property, JSValueRef* exception)
+{
+ // FIXME It could be faster, we need a JSC C API for deleting array index properties.
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+ JSObjectDeleteProperty(*m_engine, *this, propertyName.get(), exception);
}
-inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
+/*!
+ \internal
+ This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex.
+*/
+inline void QScriptValuePrivate::deleteProperty(JSStringRef property, JSValueRef* exception)
+{
+ Q_ASSERT(isObject());
+ JSObjectDeleteProperty(*m_engine, *this, property, exception);
+}
+
+template<typename T>
+inline void QScriptValuePrivate::setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
{
if (!isObject())
- return new QScriptValuePrivate;
+ return;
- if (mode & QScriptValue::ResolveLocal) {
- qWarning("QScriptValue::property(): ResolveLocal not supported yet.");
- return new QScriptValuePrivate;
+ if (!value->isJSBased())
+ value->assignEngine(engine());
+
+ JSValueRef exception = 0;
+ if (!value->isValid()) {
+ // Remove the property.
+ deleteProperty(name, &exception);
+ m_engine->setException(exception);
+ return;
+ }
+ if (m_engine != value->m_engine) {
+ qWarning("QScriptValue::setProperty() failed: cannot set value created in a different engine");
+ return;
+ }
+
+ setProperty(name, *value, QScriptConverter::toPropertyFlags(flags), &exception);
+ m_engine->setException(exception);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode)
+{
+ JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+ return propertyFlags(propertyName.get(), mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+ return propertyFlags(*name, mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(JSStringRef name, const QScriptValue::ResolveFlags& mode)
+{
+ unsigned flags = 0;
+ if (!isObject())
+ return QScriptValue::PropertyFlags(flags);
+
+ // FIXME It could be faster and nicer, but new JSC C API should be created.
+ static JSStringRef objectName = QScriptConverter::toString("Object");
+ static JSStringRef propertyDescriptorName = QScriptConverter::toString("getOwnPropertyDescriptor");
+
+ // FIXME This is dangerous if global object was modified (bug 41839).
+ JSValueRef exception = 0;
+ JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine);
+ JSValueRef objectConstructor = JSObjectGetProperty(*m_engine, globalObject, objectName, &exception);
+ Q_ASSERT(JSValueIsObject(*m_engine, objectConstructor));
+ JSValueRef propertyDescriptorGetter = JSObjectGetProperty(*m_engine, const_cast<JSObjectRef>(objectConstructor), propertyDescriptorName, &exception);
+ Q_ASSERT(JSValueIsObject(*m_engine, propertyDescriptorGetter));
+
+ JSValueRef arguments[] = { *this, JSValueMakeString(*m_engine, name) };
+ JSObjectRef propertyDescriptor
+ = const_cast<JSObjectRef>(JSObjectCallAsFunction(*m_engine,
+ const_cast<JSObjectRef>(propertyDescriptorGetter),
+ /* thisObject */ 0,
+ /* argumentCount */ 2,
+ arguments,
+ &exception));
+ if (exception) {
+ // Invalid property.
+ return QScriptValue::PropertyFlags(flags);
+ }
+
+ if (!JSValueIsObject(*m_engine, propertyDescriptor)) {
+ // Property isn't owned by this object.
+ JSObjectRef proto;
+ if (mode == QScriptValue::ResolveLocal
+ || ((proto = const_cast<JSObjectRef>(JSObjectGetPrototype(*m_engine, *this))) && JSValueIsNull(*m_engine, proto))) {
+ return QScriptValue::PropertyFlags(flags);
+ }
+ QScriptValuePrivate p(engine(), proto);
+ return p.propertyFlags(name, QScriptValue::ResolvePrototype);
}
- return new QScriptValuePrivate(m_engine.constData(), JSObjectGetPropertyAtIndex(*m_engine, *this, arrayIndex, /* exception */ 0));
+ static JSStringRef writableName = QScriptConverter::toString("writable");
+ static JSStringRef configurableName = QScriptConverter::toString("configurable");
+ static JSStringRef enumerableName = QScriptConverter::toString("enumerable");
+
+ bool readOnly = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, writableName, &exception));
+ if (!exception && readOnly)
+ flags |= QScriptValue::ReadOnly;
+ bool undeletable = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, configurableName, &exception));
+ if (!exception && undeletable)
+ flags |= QScriptValue::Undeletable;
+ bool skipInEnum = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, enumerableName, &exception));
+ if (!exception && skipInEnum)
+ flags |= QScriptValue::SkipInEnumeration;
+
+ return QScriptValue::PropertyFlags(flags);
}
QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
diff --git a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp
index 753fcd0..72ca9b1 100644
--- a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp
+++ b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp
@@ -416,21 +416,48 @@ void tst_QScriptEngine::newArray()
QScriptEngine eng;
QScriptValue array = eng.newArray();
QCOMPARE(array.isValid(), true);
- // QCOMPARE(array.isArray(), true);
+ QCOMPARE(array.isArray(), true);
QCOMPARE(array.isObject(), true);
QVERIFY(!array.isFunction());
// QCOMPARE(array.scriptClass(), (QScriptClass*)0);
// Prototype should be Array.prototype.
QCOMPARE(array.prototype().isValid(), true);
- // QCOMPARE(array.prototype().isArray(), true);
+ QCOMPARE(array.prototype().isArray(), true);
QCOMPARE(array.prototype().strictlyEquals(eng.evaluate("Array.prototype")), true);
QScriptValue arrayWithSize = eng.newArray(42);
QCOMPARE(arrayWithSize.isValid(), true);
- // QCOMPARE(arrayWithSize.isArray(), true);
+ QCOMPARE(arrayWithSize.isArray(), true);
QCOMPARE(arrayWithSize.isObject(), true);
QCOMPARE(arrayWithSize.property("length").toInt32(), 42);
+
+ // task 218092
+ {
+ QScriptValue ret = eng.evaluate("[].splice(0, 0, 'a')");
+ QVERIFY(ret.isArray());
+ QCOMPARE(ret.property("length").toInt32(), 0);
+ }
+ {
+ QScriptValue ret = eng.evaluate("['a'].splice(0, 1, 'b')");
+ QVERIFY(ret.isArray());
+ QCOMPARE(ret.property("length").toInt32(), 1);
+ }
+ {
+ QScriptValue ret = eng.evaluate("['a', 'b'].splice(0, 1, 'c')");
+ QVERIFY(ret.isArray());
+ QCOMPARE(ret.property("length").toInt32(), 1);
+ }
+ {
+ QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(0, 2, 'd')");
+ QVERIFY(ret.isArray());
+ QCOMPARE(ret.property("length").toInt32(), 2);
+ }
+ {
+ QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(1, 2, 'd', 'e', 'f')");
+ QVERIFY(ret.isArray());
+ QCOMPARE(ret.property("length").toInt32(), 2);
+ }
}
void tst_QScriptEngine::uncaughtException()
diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
index 2a2a6b1..73b57dc 100644
--- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
+++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp
@@ -274,6 +274,392 @@ void tst_QScriptValue::ctor()
QVERIFY(QScriptValue(0, QString("ciao")).isString());
}
+void tst_QScriptValue::getPropertySimple_data()
+{
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QString>("desc");
+ QTest::addColumn<bool>("isArrayIndex");
+
+ QTest::newRow("new Array()")
+ << QString::fromAscii("new Array()")
+ << QString::fromAscii("length")
+ << QString::fromAscii("0")
+ << false;
+ QTest::newRow("new Object().length")
+ << QString::fromAscii("new Object()")
+ << QString::fromAscii("length")
+ << QString::fromAscii("") // Undefined is an invalid property.
+ << false;
+ QTest::newRow("new Object().toString")
+ << QString::fromAscii("new Object()")
+ << QString::fromAscii("toString")
+ << QString::fromAscii("function toString() {\n [native code]\n}")
+ << false;
+ QTest::newRow("[1,2,3,4]")
+ << QString::fromAscii("[1,2,3,'s',4]")
+ << QString::fromAscii("2")
+ << QString::fromAscii("3")
+ << true;
+ QTest::newRow("[1,3,'a','b']")
+ << QString::fromAscii("[1,3,'a','b']")
+ << QString::fromAscii("3")
+ << QString::fromAscii("b")
+ << true;
+ QTest::newRow("[4,5]")
+ << QString::fromAscii("[4,5]")
+ << QString::fromAscii("123")
+ << QString::fromAscii("") // Undefined is an invalid property.
+ << true;
+ QTest::newRow("[1,3,4]")
+ << QString::fromAscii("[1,3,4]")
+ << QString::fromAscii("abc")
+ << QString::fromAscii("") // Undefined is an invalid property.
+ << true;
+}
+
+void tst_QScriptValue::getPropertySimple()
+{
+ QFETCH(QString, code);
+ QFETCH(QString, propertyName);
+ QFETCH(QString, desc);
+
+ QScriptEngine engine;
+ QScriptValue object = engine.evaluate(code);
+ QVERIFY(object.isValid());
+ {
+ QScriptValue property = object.property(propertyName);
+ QCOMPARE(property.toString(), desc);
+ }
+ {
+ QScriptString name = engine.toStringHandle(propertyName);
+ QScriptValue property = object.property(name);
+ QCOMPARE(property.toString(), desc);
+ }
+ {
+ bool ok;
+ quint32 idx = engine.toStringHandle(propertyName).toArrayIndex(&ok);
+ if (ok) {
+ QScriptValue property = object.property(idx);
+ QCOMPARE(property.toString(), desc);
+ }
+ }
+}
+
+void tst_QScriptValue::setPropertySimple()
+{
+ QScriptEngine engine;
+ {
+ QScriptValue invalid;
+ QScriptValue property(1234);
+
+ invalid.setProperty("aaa", property);
+ invalid.setProperty(13, property);
+ invalid.setProperty(engine.toStringHandle("aaa"), property);
+
+ QVERIFY(!invalid.property("aaa").isValid());
+ QVERIFY(!invalid.property(13).isValid());
+ QVERIFY(!invalid.property(engine.toStringHandle("aaa")).isValid());
+ }
+ {
+ QScriptValue object = engine.newObject();
+ QScriptValue property;
+
+ object.setProperty(13, property);
+ object.setProperty("aaa", property);
+ object.setProperty(engine.toStringHandle("aaa"), property);
+
+ QVERIFY(!object.property(13).isValid());
+ QVERIFY(!object.property("aaa").isValid());
+ QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
+ }
+ {
+ // Check if setting an invalid property works as deleteProperty.
+ QScriptValue object = engine.evaluate("o = {13: 0, 'aaa': 3, 'bbb': 1}");
+ QScriptValue property;
+
+ QVERIFY(object.property(13).isValid());
+ QVERIFY(object.property("aaa").isValid());
+ QVERIFY(object.property(engine.toStringHandle("aaa")).isValid());
+
+ object.setProperty(13, property);
+ object.setProperty("aaa", property);
+ object.setProperty(engine.toStringHandle("bbb"), property);
+
+ QVERIFY(!object.property(13).isValid());
+ QVERIFY(!object.property("aaa").isValid());
+ QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
+ }
+ {
+ QScriptValue object = engine.evaluate("new Object");
+ QVERIFY(object.isObject());
+ QScriptValue property = object.property("foo");
+ QVERIFY(!property.isValid());
+ property = QScriptValue(2);
+ object.setProperty("foo", property);
+ QVERIFY(object.property("foo").isNumber());
+ QVERIFY(object.property("foo").toNumber() == 2);
+ }
+ {
+ QScriptValue o1 = engine.evaluate("o1 = new Object; o1");
+ QScriptValue o2 = engine.evaluate("o2 = new Object; o2");
+ QVERIFY(engine.evaluate("o1.__proto__ = o2; o1.__proto__ === o2").toBool());
+ QVERIFY(engine.evaluate("o2.foo = 22; o1.foo == 22").toBool());
+ QVERIFY(o1.property("foo").toString() == "22");
+ o2.setProperty("foo", QScriptValue(&engine, 456.0));
+ QVERIFY(engine.evaluate("o1.foo == 456").toBool());
+ QVERIFY(o1.property("foo").isNumber());
+ }
+}
+
+void tst_QScriptValue::getPropertyResolveFlag()
+{
+ QScriptEngine engine;
+ QScriptValue object1 = engine.evaluate("o1 = new Object();");
+ QScriptValue object2 = engine.evaluate("o2 = new Object(); o1.__proto__ = o2; o2");
+ QScriptValue number(&engine, 456.0);
+ QVERIFY(object1.isObject());
+ QVERIFY(object2.isObject());
+ QVERIFY(number.isNumber());
+
+ object2.setProperty("propertyInPrototype", number);
+ QVERIFY(object2.property("propertyInPrototype").isNumber());
+ // default is ResolvePrototype
+ QCOMPARE(object1.property("propertyInPrototype").strictlyEquals(number), true);
+ QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolvePrototype)
+ .strictlyEquals(number), true);
+ QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolveLocal).isValid(), false);
+}
+
+void tst_QScriptValue::getSetProperty()
+{
+ QScriptEngine eng;
+
+ QScriptValue object = eng.newObject();
+
+ QScriptValue str = QScriptValue(&eng, "bar");
+ object.setProperty("foo", str);
+ QCOMPARE(object.property("foo").toString(), str.toString());
+
+ QScriptValue num = QScriptValue(&eng, 123.0);
+ object.setProperty("baz", num);
+ QCOMPARE(object.property("baz").toNumber(), num.toNumber());
+
+ QScriptValue strstr = QScriptValue("bar");
+ QCOMPARE(strstr.engine(), (QScriptEngine *)0);
+ object.setProperty("foo", strstr);
+ QCOMPARE(object.property("foo").toString(), strstr.toString());
+ QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine
+
+ QScriptValue numnum = QScriptValue(123.0);
+ object.setProperty("baz", numnum);
+ QCOMPARE(object.property("baz").toNumber(), numnum.toNumber());
+
+ QScriptValue inv;
+ inv.setProperty("foo", num);
+ QCOMPARE(inv.property("foo").isValid(), false);
+
+ QScriptValue array = eng.newArray();
+ array.setProperty(0, num);
+ QCOMPARE(array.property(0).toNumber(), num.toNumber());
+ QCOMPARE(array.property("0").toNumber(), num.toNumber());
+ QCOMPARE(array.property("length").toUInt32(), quint32(1));
+ array.setProperty(1, str);
+ QCOMPARE(array.property(1).toString(), str.toString());
+ QCOMPARE(array.property("1").toString(), str.toString());
+ QCOMPARE(array.property("length").toUInt32(), quint32(2));
+ array.setProperty("length", QScriptValue(&eng, 1));
+ QCOMPARE(array.property("length").toUInt32(), quint32(1));
+ QCOMPARE(array.property(1).isValid(), false);
+
+ // task 162051 -- detecting whether the property is an array index or not
+ QVERIFY(eng.evaluate("a = []; a['00'] = 123; a['00']").strictlyEquals(QScriptValue(&eng, 123)));
+ QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+ QVERIFY(eng.evaluate("a.hasOwnProperty('00')").strictlyEquals(QScriptValue(&eng, true)));
+ QVERIFY(eng.evaluate("a.hasOwnProperty('0')").strictlyEquals(QScriptValue(&eng, false)));
+ QVERIFY(eng.evaluate("a[0]").isUndefined());
+ QVERIFY(eng.evaluate("a[0.5] = 456; a[0.5]").strictlyEquals(QScriptValue(&eng, 456)));
+ QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+ QVERIFY(eng.evaluate("a.hasOwnProperty('0.5')").strictlyEquals(QScriptValue(&eng, true)));
+ QVERIFY(eng.evaluate("a[0]").isUndefined());
+ QVERIFY(eng.evaluate("a[0] = 789; a[0]").strictlyEquals(QScriptValue(&eng, 789)));
+ QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 1)));
+
+ // task 183072 -- 0x800000000 is not an array index
+ eng.evaluate("a = []; a[0x800000000] = 123");
+ QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+ QVERIFY(eng.evaluate("a[0]").isUndefined());
+ QVERIFY(eng.evaluate("a[0x800000000]").strictlyEquals(QScriptValue(&eng, 123)));
+
+ QScriptEngine otherEngine;
+ QScriptValue otherNum = QScriptValue(&otherEngine, 123);
+ QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setProperty() failed: cannot set value created in a different engine");
+ object.setProperty("oof", otherNum);
+ QCOMPARE(object.property("oof").isValid(), false);
+
+ // test ResolveMode
+ QScriptValue object2 = eng.newObject();
+ object.setPrototype(object2);
+ QScriptValue num2 = QScriptValue(&eng, 456.0);
+ object2.setProperty("propertyInPrototype", num2);
+ // default is ResolvePrototype
+ QCOMPARE(object.property("propertyInPrototype")
+ .strictlyEquals(num2), true);
+ QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolvePrototype)
+ .strictlyEquals(num2), true);
+ QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveLocal)
+ .isValid(), false);
+ QEXPECT_FAIL("", "QScriptValue::ResolveScope is not implemented", Continue);
+ QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveScope)
+ .strictlyEquals(num2), false);
+ QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveFull)
+ .strictlyEquals(num2), true);
+
+ // test property removal (setProperty(QScriptValue()))
+ QScriptValue object3 = eng.newObject();
+ object3.setProperty("foo", num);
+ QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+ object3.setProperty("bar", str);
+ QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+ object3.setProperty("foo", QScriptValue());
+ QCOMPARE(object3.property("foo").isValid(), false);
+ QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+ object3.setProperty("foo", num);
+ QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+ QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+ object3.setProperty("bar", QScriptValue());
+ QCOMPARE(object3.property("bar").isValid(), false);
+ QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+ object3.setProperty("foo", QScriptValue());
+ object3.setProperty("foo", QScriptValue());
+
+ eng.globalObject().setProperty("object3", object3);
+ QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
+ .strictlyEquals(QScriptValue(&eng, false)), true);
+ object3.setProperty("foo", num);
+ QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
+ .strictlyEquals(QScriptValue(&eng, true)), true);
+ eng.globalObject().setProperty("object3", QScriptValue());
+ QCOMPARE(eng.evaluate("this.hasOwnProperty('object3')")
+ .strictlyEquals(QScriptValue(&eng, false)), true);
+
+ eng.globalObject().setProperty("object", object);
+
+ // ReadOnly
+ object.setProperty("readOnlyProperty", num, QScriptValue::ReadOnly);
+ // QCOMPARE(object.propertyFlags("readOnlyProperty"), QScriptValue::ReadOnly);
+ QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
+ eng.evaluate("object.readOnlyProperty = !object.readOnlyProperty");
+ QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
+ // Should still be part of enumeration.
+ {
+ QScriptValue ret = eng.evaluate(
+ "found = false;"
+ "for (var p in object) {"
+ " if (p == 'readOnlyProperty') {"
+ " found = true; break;"
+ " }"
+ "} found");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+ }
+ // should still be deletable
+ {
+ QScriptValue ret = eng.evaluate("delete object.readOnlyProperty");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+ QCOMPARE(object.property("readOnlyProperty").isValid(), false);
+ }
+
+ // Undeletable
+ object.setProperty("undeletableProperty", num, QScriptValue::Undeletable);
+ // QCOMPARE(object.propertyFlags("undeletableProperty"), QScriptValue::Undeletable);
+ QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
+ {
+ QScriptValue ret = eng.evaluate("delete object.undeletableProperty");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), false);
+ QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
+ }
+ // should still be writable
+ eng.evaluate("object.undeletableProperty = object.undeletableProperty + 1");
+ QCOMPARE(object.property("undeletableProperty").toNumber(), num.toNumber() + 1);
+ // should still be part of enumeration
+ {
+ QScriptValue ret = eng.evaluate(
+ "found = false;"
+ "for (var p in object) {"
+ " if (p == 'undeletableProperty') {"
+ " found = true; break;"
+ " }"
+ "} found");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+ }
+ // should still be deletable from C++
+ object.setProperty("undeletableProperty", QScriptValue());
+ QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
+ QVERIFY(!object.property("undeletableProperty").isValid());
+ // QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
+ // QCOMPARE(object.propertyFlags("undeletableProperty"), 0);
+
+ // SkipInEnumeration
+ object.setProperty("dontEnumProperty", num, QScriptValue::SkipInEnumeration);
+ // QCOMPARE(object.propertyFlags("dontEnumProperty"), QScriptValue::SkipInEnumeration);
+ QCOMPARE(object.property("dontEnumProperty").strictlyEquals(num), true);
+ // should not be part of enumeration
+ {
+ QScriptValue ret = eng.evaluate(
+ "found = false;"
+ "for (var p in object) {"
+ " if (p == 'dontEnumProperty') {"
+ " found = true; break;"
+ " }"
+ "} found");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, false)), true);
+ }
+ // should still be writable
+ eng.evaluate("object.dontEnumProperty = object.dontEnumProperty + 1");
+ QCOMPARE(object.property("dontEnumProperty").toNumber(), num.toNumber() + 1);
+ // should still be deletable
+ {
+ QScriptValue ret = eng.evaluate("delete object.dontEnumProperty");
+ QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+ QCOMPARE(object.property("dontEnumProperty").isValid(), false);
+ }
+
+ // change flags
+ object.setProperty("flagProperty", str);
+ // QCOMPARE(object.propertyFlags("flagProperty"), static_cast<QScriptValue::PropertyFlags>(0));
+
+ object.setProperty("flagProperty", str, QScriptValue::ReadOnly);
+ // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly);
+
+ // object.setProperty("flagProperty", str, object.propertyFlags("flagProperty") | QScriptValue::SkipInEnumeration);
+ // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+
+ object.setProperty("flagProperty", str, QScriptValue::KeepExistingFlags);
+ // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+
+ object.setProperty("flagProperty", str, QScriptValue::UserRange);
+ // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::UserRange);
+
+ // flags of property in the prototype
+ {
+ QScriptValue object2 = eng.newObject();
+ object2.setPrototype(object);
+ // QCOMPARE(object2.propertyFlags("flagProperty", QScriptValue::ResolveLocal), 0);
+ // QCOMPARE(object2.propertyFlags("flagProperty"), QScriptValue::UserRange);
+ }
+
+ // using interned strings
+ QScriptString foo = eng.toStringHandle("foo");
+
+ object.setProperty(foo, QScriptValue());
+ QVERIFY(!object.property(foo).isValid());
+
+ object.setProperty(foo, num);
+ QVERIFY(object.property(foo).strictlyEquals(num));
+ QVERIFY(object.property("foo").strictlyEquals(num));
+ // QVERIFY(object.propertyFlags(foo) == 0);
+}
+
void tst_QScriptValue::toStringSimple_data()
{
QTest::addColumn<QString>("code");
@@ -580,17 +966,299 @@ void tst_QScriptValue::toObjectSimple()
}
}
-void tst_QScriptValue::propertySimple()
+void tst_QScriptValue::setProperty_data()
{
- QScriptEngine eng;
+ QTest::addColumn<QScriptValue>("property");
+ QTest::addColumn<int>("flag");
+
+ QTest::newRow("int + keepExistingFlags") << QScriptValue(123456) << static_cast<int>(QScriptValue::KeepExistingFlags);
+ QTest::newRow("int + undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::Undeletable);
+ QTest::newRow("int + readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly);
+ QTest::newRow("int + readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
+ QTest::newRow("int + skipInEnumeration") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration);
+ QTest::newRow("int + skipInEnumeration|readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly);
+ QTest::newRow("int + skipInEnumeration|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
+ QTest::newRow("int + skipInEnumeration|readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly | QScriptValue::Undeletable);
+}
+
+void tst_QScriptValue::setProperty()
+{
+ QFETCH(QScriptValue, property);
+ QFETCH(int, flag);
+ QScriptValue::PropertyFlags flags = static_cast<QScriptValue::PropertyFlag>(flag);
- QScriptValue simpleObject(eng.evaluate("new Object({ test: 1, other: 2 })"));
- QCOMPARE(simpleObject.property("test").toUInt32(), quint32(1));
- QCOMPARE(simpleObject.property("other").toUInt32(), quint32(2));
+ QScriptEngine engine;
+ QScriptValue object = engine.evaluate("o = new Object; o");
+ QScriptValue proto = engine.evaluate("p = new Object; o.__proto__ = p; p");
+ engine.evaluate("o.defined1 = 1");
+ engine.evaluate("o.defined2 = 1");
+ engine.evaluate("o[5] = 1");
+ engine.evaluate("p.overloaded1 = 1");
+ engine.evaluate("o.overloaded1 = 2");
+ engine.evaluate("p[6] = 1");
+ engine.evaluate("o[6] = 2");
+ engine.evaluate("p.overloaded2 = 1");
+ engine.evaluate("o.overloaded2 = 2");
+ engine.evaluate("p.overloaded3 = 1");
+ engine.evaluate("o.overloaded3 = 2");
+ engine.evaluate("p[7] = 1");
+ engine.evaluate("o[7] = 2");
+ engine.evaluate("p.overloaded4 = 1");
+ engine.evaluate("o.overloaded4 = 2");
+
+ // tries to set undefined property directly on object.
+ object.setProperty(QString::fromAscii("undefined1"), property, flags);
+ QVERIFY(engine.evaluate("o.undefined1").strictlyEquals(property));
+ object.setProperty(engine.toStringHandle("undefined2"), property, flags);
+ QVERIFY(object.property("undefined2").strictlyEquals(property));
+ object.setProperty(4, property, flags);
+ QVERIFY(object.property(4).strictlyEquals(property));
+
+ // tries to set defined property directly on object
+ object.setProperty("defined1", property, flags);
+ QVERIFY(engine.evaluate("o.defined1").strictlyEquals(property));
+ object.setProperty(engine.toStringHandle("defined2"), property, flags);
+ QVERIFY(object.property("defined2").strictlyEquals(property));
+ object.setProperty(5, property, flags);
+ QVERIFY(object.property(5).strictlyEquals(property));
+
+ // tries to set overloaded property directly on object
+ object.setProperty("overloaded1", property, flags);
+ QVERIFY(engine.evaluate("o.overloaded1").strictlyEquals(property));
+ object.setProperty(engine.toStringHandle("overloaded2"), property, flags);
+ QVERIFY(object.property("overloaded2").strictlyEquals(property));
+ object.setProperty(6, property, flags);
+ QVERIFY(object.property(6).strictlyEquals(property));
+
+ // tries to set overloaded property directly on prototype
+ proto.setProperty("overloaded3", property, flags);
+ QVERIFY(!engine.evaluate("o.overloaded3").strictlyEquals(property));
+ proto.setProperty(engine.toStringHandle("overloaded4"), property, flags);
+ QVERIFY(!object.property("overloaded4").strictlyEquals(property));
+ proto.setProperty(7, property, flags);
+ QVERIFY(!object.property(7).strictlyEquals(property));
+
+ // tries to set undefined property directly on prototype
+ proto.setProperty("undefined3", property, flags);
+ QVERIFY(engine.evaluate("o.undefined3").strictlyEquals(property));
+ proto.setProperty(engine.toStringHandle("undefined4"), property, flags);
+ QVERIFY(object.property("undefined4").strictlyEquals(property));
+ proto.setProperty(8, property, flags);
+ QVERIFY(object.property(8).strictlyEquals(property));
+
+ bool readOnly = flags & QScriptValue::ReadOnly;
+ bool skipInEnumeration = flags & QScriptValue::SkipInEnumeration;
+ bool undeletable = flags & QScriptValue::Undeletable;
+
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').writable").toBool());
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').writable").toBool());
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').writable").toBool());
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').writable").toBool());
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').writable").toBool());
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').writable").toBool());
+ QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
+ QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').writable").toBool());
+ QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').writable").toBool());
+ QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded3').writable").toBool());
+ QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded4').writable").toBool());
+
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').configurable").toBool());
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').configurable").toBool());
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').configurable").toBool());
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').configurable").toBool());
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').configurable").toBool());
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').configurable").toBool());
+ QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded1').configurable").toBool());
+ QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded2').configurable").toBool());
+ QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded3').configurable").toBool());
+ QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded4').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').configurable").toBool());
+ QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').configurable").toBool());
+
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '4').enumerable").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '5').enumerable").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '6').enumerable").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '7').enumerable").toBool());
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '8').enumerable").toBool());
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined1').enumerable").toBool());
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined2').enumerable").toBool());
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined3').enumerable").toBool());
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined4').enumerable").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded1').enumerable").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded2').enumerable").toBool());
+ QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded1')").toBool());
+ QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded2')").toBool());
+ QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded3')").toBool());
+ QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded4')").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded3')").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded4')").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined1')").toBool());
+ QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+ QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined2')").toBool());
+}
- QScriptValue simpleArray(eng.evaluate("new Array(7, 8, 9)"));
- QCOMPARE(simpleArray.property("length").toUInt32(), quint32(3));
- QCOMPARE(simpleArray.property(2).toUInt32(), quint32(9));
+void tst_QScriptValue::propertyFlag_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<int>("flag");
+
+ QTest::newRow("?Cr@jzi!%$") << "?Cr@jzi!%$" << static_cast<int>(0);
+ QTest::newRow("ReadOnly") << "ReadOnly" << static_cast<int>(QScriptValue::ReadOnly);
+ QTest::newRow("Undeletable") << "Undeletable" << static_cast<int>(QScriptValue::Undeletable);
+ QTest::newRow("SkipInEnumeration") << "SkipInEnumeration" << static_cast<int>(QScriptValue::SkipInEnumeration);
+ QTest::newRow("ReadOnly | Undeletable") << "ReadOnly_Undeletable" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
+ QTest::newRow("ReadOnly | SkipInEnumeration") << "ReadOnly_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+ QTest::newRow("Undeletable | SkipInEnumeration") << "Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ QTest::newRow("ReadOnly | Undeletable | SkipInEnumeration") << "ReadOnly_Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+}
+
+void tst_QScriptValue::propertyFlag()
+{
+ QScriptEngine engine;
+ QFETCH(QString, name);
+ QFETCH(int, flag);
+ const QScriptString nameHandle = engine.toStringHandle(name);
+ const QString protoName = "proto" + name;
+ const QScriptString protoNameHandle = engine.toStringHandle(protoName);
+
+ QScriptValue proto = engine.newObject();
+ QScriptValue object = engine.newObject();
+ object.setPrototype(proto);
+
+ proto.setProperty(protoName, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
+ object.setProperty(name, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
+
+ // Check using QString name
+ QCOMPARE(object.propertyFlags(name), QScriptValue::PropertyFlag(flag));
+ QCOMPARE(object.propertyFlags(protoName, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
+ QVERIFY(!object.propertyFlags(protoName, QScriptValue::ResolveLocal));
+
+ // Check using QScriptString name
+ QCOMPARE(object.propertyFlags(nameHandle), QScriptValue::PropertyFlag(flag));
+ QCOMPARE(object.propertyFlags(protoNameHandle, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
+ QVERIFY(!object.propertyFlags(protoNameHandle, QScriptValue::ResolveLocal));
}
QTEST_MAIN(tst_QScriptValue)
diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
index af600a6..6108423 100644
--- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
+++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h
@@ -51,7 +51,15 @@ private slots:
void call();
void ctor();
void toObjectSimple();
- void propertySimple();
+ void getPropertySimple_data();
+ void getPropertySimple();
+ void setPropertySimple();
+ void setProperty_data();
+ void setProperty();
+ void getSetProperty();
+ void getPropertyResolveFlag();
+ void propertyFlag_data();
+ void propertyFlag();
// Generated test functions.
void isBool_data();
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
diff --git a/JavaScriptCore/wtf/CrossThreadRefCounted.h b/JavaScriptCore/wtf/CrossThreadRefCounted.h
index f682f0d..0c0e997 100644
--- a/JavaScriptCore/wtf/CrossThreadRefCounted.h
+++ b/JavaScriptCore/wtf/CrossThreadRefCounted.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 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 are
@@ -31,10 +32,9 @@
#ifndef CrossThreadRefCounted_h
#define CrossThreadRefCounted_h
-#include <wtf/Noncopyable.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/Threading.h>
+#include "PassRefPtr.h"
+#include "RefCounted.h"
+#include "Threading.h"
namespace WTF {
@@ -78,6 +78,9 @@ namespace WTF {
, m_threadId(0)
#endif
{
+ // We use RefCountedBase in an unusual way here, so get rid of the requirement
+ // that adoptRef be called on it.
+ m_refCounter.relaxAdoptionRequirement();
}
~CrossThreadRefCounted()
diff --git a/JavaScriptCore/wtf/MessageQueue.h b/JavaScriptCore/wtf/MessageQueue.h
index 13ce1e8..14100c9 100644
--- a/JavaScriptCore/wtf/MessageQueue.h
+++ b/JavaScriptCore/wtf/MessageQueue.h
@@ -92,7 +92,7 @@ namespace WTF {
inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
{
MutexLocker lock(m_mutex);
- m_queue.append(message.release());
+ m_queue.append(message.leakPtr());
m_condition.signal();
}
@@ -102,7 +102,7 @@ namespace WTF {
{
MutexLocker lock(m_mutex);
bool wasEmpty = m_queue.isEmpty();
- m_queue.append(message.release());
+ m_queue.append(message.leakPtr());
m_condition.signal();
return wasEmpty;
}
@@ -111,7 +111,7 @@ namespace WTF {
inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
{
MutexLocker lock(m_mutex);
- m_queue.prepend(message.release());
+ m_queue.prepend(message.leakPtr());
m_condition.signal();
}
diff --git a/JavaScriptCore/wtf/OwnArrayPtr.h b/JavaScriptCore/wtf/OwnArrayPtr.h
index b06e640..d40ea17 100644
--- a/JavaScriptCore/wtf/OwnArrayPtr.h
+++ b/JavaScriptCore/wtf/OwnArrayPtr.h
@@ -30,20 +30,21 @@ namespace WTF {
template <typename T> class OwnArrayPtr : public Noncopyable {
public:
explicit OwnArrayPtr(T* ptr = 0) : m_ptr(ptr) { }
- ~OwnArrayPtr() { safeDelete(); }
+ ~OwnArrayPtr() { safeDelete(m_ptr); }
T* get() const { return m_ptr; }
T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
- // FIXME: This should be renamed to adopt.
+ // FIXME: This should be removed and replaced with PassOwnArrayPtr.
void set(T* ptr)
{
ASSERT(!ptr || m_ptr != ptr);
- safeDelete();
+ T* oldPtr = m_ptr;
m_ptr = ptr;
+ safeDelete(oldPtr);
}
- void clear() { safeDelete(); m_ptr = 0; }
+ void clear();
T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
T* operator->() const { ASSERT(m_ptr); return m_ptr; }
@@ -63,11 +64,25 @@ namespace WTF {
void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); }
private:
- void safeDelete() { typedef char known[sizeof(T) ? 1 : -1]; if (sizeof(known)) delete [] m_ptr; }
+ static void safeDelete(T*);
T* m_ptr;
};
+ template<typename T> inline void OwnArrayPtr<T>::clear()
+ {
+ T* ptr = m_ptr;
+ m_ptr = 0;
+ safeDelete(ptr);
+ }
+
+ template<typename T> inline void OwnArrayPtr<T>::safeDelete(T* ptr)
+ {
+ typedef char known[sizeof(T) ? 1 : -1];
+ if (sizeof(known))
+ delete [] ptr;
+ }
+
template <typename T> inline void swap(OwnArrayPtr<T>& a, OwnArrayPtr<T>& b) { a.swap(b); }
template <typename T> inline T* getPtr(const OwnArrayPtr<T>& p)
diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h
index af1684b..cadfad2 100644
--- a/JavaScriptCore/wtf/OwnPtr.h
+++ b/JavaScriptCore/wtf/OwnPtr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -28,36 +28,39 @@
#include <algorithm>
#include <memory>
+// Remove this once we make all WebKit code compatible with stricter rules about OwnPtr.
+#define LOOSE_OWN_PTR
+
namespace WTF {
// Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type.
- template <typename T> class PassOwnPtr;
+ template<typename T> class PassOwnPtr;
+ template<typename T> PassOwnPtr<T> adoptPtr(T*);
- template <typename T> class OwnPtr : public Noncopyable {
+ template<typename T> class OwnPtr : public Noncopyable {
public:
typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
- explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+ OwnPtr() : m_ptr(0) { }
+
// See comment in PassOwnPtr.h for why this takes a const reference.
- template <typename U> OwnPtr(const PassOwnPtr<U>& o);
+ template<typename U> OwnPtr(const PassOwnPtr<U>& o);
// This copy constructor is used implicitly by gcc when it generates
// transients for assigning a PassOwnPtr<T> object to a stack-allocated
- // OwnPtr<T> object. It should never be called explicitly and gcc
+ // OwnPtr<T> object. It should never be called explicitly and gcc
// should optimize away the constructor when generating code.
- OwnPtr(const OwnPtr<ValueType>& o);
+ OwnPtr(const OwnPtr<ValueType>&);
~OwnPtr() { deleteOwnedPtr(m_ptr); }
PtrType get() const { return m_ptr; }
- PtrType release() { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
-
- // FIXME: This should be renamed to adopt.
- void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; }
- void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; }
+ void clear();
+ PassOwnPtr<T> release();
+ PtrType leakPtr() WARN_UNUSED_RETURN;
ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
@@ -69,65 +72,99 @@ namespace WTF {
operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
OwnPtr& operator=(const PassOwnPtr<T>&);
- template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
+ template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
+#ifdef LOOSE_OWN_PTR
+ explicit OwnPtr(PtrType ptr) : m_ptr(ptr) { }
+ void set(PtrType);
+#endif
+
private:
PtrType m_ptr;
};
- template <typename T> template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
- : m_ptr(o.release())
+ template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
+ : m_ptr(o.leakPtr())
{
}
- template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
+ template<typename T> inline void OwnPtr<T>::clear()
+ {
+ PtrType ptr = m_ptr;
+ m_ptr = 0;
+ deleteOwnedPtr(ptr);
+ }
+
+ template<typename T> inline PassOwnPtr<T> OwnPtr<T>::release()
+ {
+ PtrType ptr = m_ptr;
+ m_ptr = 0;
+ return adoptPtr(ptr);
+ }
+
+ template<typename T> inline typename OwnPtr<T>::PtrType OwnPtr<T>::leakPtr()
+ {
+ PtrType ptr = m_ptr;
+ m_ptr = 0;
+ return ptr;
+ }
+
+#ifdef LOOSE_OWN_PTR
+ template<typename T> inline void OwnPtr<T>::set(PtrType ptr)
+ {
+ ASSERT(!ptr || m_ptr != ptr);
+ PtrType oldPtr = m_ptr;
+ m_ptr = ptr;
+ deleteOwnedPtr(oldPtr);
+ }
+#endif
+
+ template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
{
- T* ptr = m_ptr;
- m_ptr = o.release();
+ PtrType ptr = m_ptr;
+ m_ptr = o.leakPtr();
ASSERT(!ptr || m_ptr != ptr);
- if (ptr)
- deleteOwnedPtr(ptr);
+ deleteOwnedPtr(ptr);
return *this;
}
- template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
+ template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
{
- T* ptr = m_ptr;
- m_ptr = o.release();
+ PtrType ptr = m_ptr;
+ m_ptr = o.leakPtr();
ASSERT(!ptr || m_ptr != ptr);
- if (ptr)
- deleteOwnedPtr(ptr);
+ deleteOwnedPtr(ptr);
return *this;
}
- template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
+ template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
{
a.swap(b);
}
- template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
+ template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
{
return a.get() == b;
}
- template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b)
{
return a == b.get();
}
- template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
+ template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
{
return a.get() != b;
}
- template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
{
return a != b.get();
}
- template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
+ template<typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
{
return p.get();
}
diff --git a/JavaScriptCore/wtf/PassOwnPtr.h b/JavaScriptCore/wtf/PassOwnPtr.h
index ae70457..a223fa9 100644
--- a/JavaScriptCore/wtf/PassOwnPtr.h
+++ b/JavaScriptCore/wtf/PassOwnPtr.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
@@ -30,31 +30,36 @@
#include "OwnPtrCommon.h"
#include "TypeTraits.h"
+// Remove this once we make all WebKit code compatible with stricter rules about PassOwnPtr.
+#define LOOSE_PASS_OWN_PTR
+
namespace WTF {
// Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type.
- template <typename T> class OwnPtr;
+ template<typename T> class OwnPtr;
+ template<typename T> class PassOwnPtr;
+ template<typename T> PassOwnPtr<T> adoptPtr(T*);
- template <typename T> class PassOwnPtr {
+ template<typename T> class PassOwnPtr {
public:
typedef typename RemovePointer<T>::Type ValueType;
typedef ValueType* PtrType;
- PassOwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+ PassOwnPtr() : m_ptr(0) { }
+
// It somewhat breaks the type system to allow transfer of ownership out of
// a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
- // temporaries, and we don't really have a need to use real const PassOwnPtrs
- // anyway.
- PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.release()) { }
- template <typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.release()) { }
+ // temporaries, and we don't have a need to use real const PassOwnPtrs anyway.
+ PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { }
+ template<typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.leakPtr()) { }
~PassOwnPtr() { deleteOwnedPtr(m_ptr); }
PtrType get() const { return m_ptr; }
- void clear() { m_ptr = 0; }
- PtrType release() const { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
+ void clear();
+ PtrType leakPtr() const WARN_UNUSED_RETURN;
ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
@@ -65,105 +70,136 @@ namespace WTF {
typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
- PassOwnPtr& operator=(T*);
PassOwnPtr& operator=(const PassOwnPtr<T>&);
- template <typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
+ template<typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
+
+ template<typename U> friend PassOwnPtr<U> adoptPtr(U*);
+
+#ifdef LOOSE_PASS_OWN_PTR
+ PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
+ PassOwnPtr& operator=(PtrType);
+#endif
private:
+#ifndef LOOSE_PASS_OWN_PTR
+ explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
+#endif
+
mutable PtrType m_ptr;
};
- template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(T* optr)
+ template<typename T> inline void PassOwnPtr<T>::clear()
+ {
+ PtrType ptr = m_ptr;
+ m_ptr = 0;
+ deleteOwnedPtr(ptr);
+ }
+
+ template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
+ {
+ PtrType ptr = m_ptr;
+ m_ptr = 0;
+ return ptr;
+ }
+
+#ifdef LOOSE_PASS_OWN_PTR
+ template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(PtrType optr)
{
- T* ptr = m_ptr;
+ PtrType ptr = m_ptr;
m_ptr = optr;
ASSERT(!ptr || m_ptr != ptr);
if (ptr)
deleteOwnedPtr(ptr);
return *this;
}
+#endif
- template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
+ template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
{
- T* ptr = m_ptr;
- m_ptr = optr.release();
+ PtrType ptr = m_ptr;
+ m_ptr = optr.leakPtr();
ASSERT(!ptr || m_ptr != ptr);
if (ptr)
deleteOwnedPtr(ptr);
return *this;
}
- template <typename T> template <typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
+ template<typename T> template<typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
{
- T* ptr = m_ptr;
- m_ptr = optr.release();
+ PtrType ptr = m_ptr;
+ m_ptr = optr.leakPtr();
ASSERT(!ptr || m_ptr != ptr);
if (ptr)
deleteOwnedPtr(ptr);
return *this;
}
- template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
{
return a.get() == b.get();
}
- template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
{
return a.get() == b.get();
}
- template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
{
return a.get() == b.get();
}
- template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
+ template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
{
return a.get() == b;
}
- template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
{
return a == b.get();
}
- template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
{
return a.get() != b.get();
}
- template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
{
return a.get() != b.get();
}
- template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
{
return a.get() != b.get();
}
- template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
+ template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
{
return a.get() != b;
}
- template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
+ template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
{
return a != b.get();
}
- template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
+ template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr)
+ {
+ return PassOwnPtr<T>(ptr);
+ }
+
+ template<typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
{
- return PassOwnPtr<T>(static_cast<T*>(p.release()));
+ return adoptPtr(static_cast<T*>(p.leakPtr()));
}
- template <typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p)
+ template<typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p)
{
- return PassOwnPtr<T>(const_cast<T*>(p.release()));
+ return adoptPtr(const_cast<T*>(p.leakPtr()));
}
- template <typename T> inline T* getPtr(const PassOwnPtr<T>& p)
+ template<typename T> inline T* getPtr(const PassOwnPtr<T>& p)
{
return p.get();
}
@@ -171,6 +207,7 @@ namespace WTF {
} // namespace WTF
using WTF::PassOwnPtr;
+using WTF::adoptPtr;
using WTF::const_pointer_cast;
using WTF::static_pointer_cast;
diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h
index 7c5d868..230637a 100644
--- a/JavaScriptCore/wtf/PassRefPtr.h
+++ b/JavaScriptCore/wtf/PassRefPtr.h
@@ -76,8 +76,8 @@ namespace WTF {
T* get() const { return m_ptr; }
- void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; }
- T* leakRef() const;
+ void clear();
+ T* leakRef() const WARN_UNUSED_RETURN;
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
@@ -96,7 +96,7 @@ namespace WTF {
friend PassRefPtr adoptRef<T>(T*);
// FIXME: Remove releaseRef once we change all callers to call leakRef instead.
- T* releaseRef() const { return leakRef(); }
+ T* releaseRef() const { return leakRef(); } WARN_UNUSED_RETURN;
private:
// adopting constructor
@@ -151,12 +151,15 @@ namespace WTF {
T* get() const { return m_ptr; }
- void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
- T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
+ void clear();
+ T* leakRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } WARN_UNUSED_RETURN;
T& operator*() const { return *m_ptr; }
T* operator->() const { return m_ptr; }
+ // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
+ T* releaseRef() const { return leakRef(); } WARN_UNUSED_RETURN;
+
private:
mutable T* m_ptr;
};
@@ -168,6 +171,13 @@ namespace WTF {
refIfNotNull(ptr);
}
+ template<typename T> inline void PassRefPtr<T>::clear()
+ {
+ T* ptr = m_ptr;
+ m_ptr = 0;
+ derefIfNotNull(ptr);
+ }
+
template<typename T> inline T* PassRefPtr<T>::leakRef() const
{
T* ptr = m_ptr;
@@ -281,6 +291,13 @@ namespace WTF {
return p.get();
}
+ template<typename T> inline void NonNullPassRefPtr<T>::clear()
+ {
+ T* ptr = m_ptr;
+ m_ptr = 0;
+ derefIfNotNull(ptr);
+ }
+
} // namespace WTF
using WTF::PassRefPtr;
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index feb3a4d..2500c56 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -921,7 +921,7 @@
|| CPU(ALPHA) \
|| CPU(SPARC64)
#define WTF_USE_JSVALUE64 1
-#elif CPU(ARM) || CPU(PPC64) || CPU(MIPS)
+#elif CPU(ARM_TRADITIONAL) || CPU(PPC64) || CPU(MIPS)
#define WTF_USE_JSVALUE32 1
#elif OS(WINDOWS) && COMPILER(MINGW)
/* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg
@@ -984,6 +984,14 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#endif /* !defined(ENABLE_JIT) */
+#if !ENABLE(JIT)
+#define ENABLE_INTERPRETER 1
+#endif
+
+#if !(ENABLE(JIT) || ENABLE(INTERPRETER))
+#error You have to have at least one execution model enabled to build JSC
+#endif
+
/* CPU architecture specific optimizations */
#if CPU(ARM_TRADITIONAL)
#if ENABLE(JIT) && !defined(ENABLE_JIT_OPTIMIZE_MOD) && WTF_ARM_ARCH_AT_LEAST(5)
@@ -1024,10 +1032,14 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#define JSC_HOST_CALL
#endif
-#if COMPILER(GCC) && !ENABLE(JIT)
+#if COMPILER(GCC)
#define HAVE_COMPUTED_GOTO 1
#endif
+#if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER)
+#define ENABLE_COMPUTED_GOTO_INTERPRETER 1
+#endif
+
/* Yet Another Regex Runtime. */
#if !defined(ENABLE_YARR_JIT)
@@ -1055,6 +1067,16 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0
#endif
+/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in.
+ On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */
+#if ENABLE(ASSEMBLER)
+#if CPU(X86_64)
+#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1
+#else
+#define ENABLE_EXECUTABLE_ALLOCATOR_DEMAND 1
+#endif
+#endif
+
#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS)
#define ENABLE_PAN_SCROLLING 1
#endif
diff --git a/JavaScriptCore/wtf/RefCounted.h b/JavaScriptCore/wtf/RefCounted.h
index 5aedac3..d85c47e 100644
--- a/JavaScriptCore/wtf/RefCounted.h
+++ b/JavaScriptCore/wtf/RefCounted.h
@@ -21,11 +21,8 @@
#ifndef RefCounted_h
#define RefCounted_h
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
-
-// Remove this once we make all WebKit code compatible with stricter rules about RefCounted.
-#define LOOSE_REF_COUNTED
+#include "Assertions.h"
+#include "Noncopyable.h"
namespace WTF {
@@ -37,9 +34,7 @@ public:
void ref()
{
ASSERT(!m_deletionHasBegun);
-#ifndef LOOSE_REF_COUNTED
ASSERT(!m_adoptionIsRequired);
-#endif
++m_refCount;
}
@@ -54,6 +49,15 @@ public:
return m_refCount;
}
+ void relaxAdoptionRequirement()
+ {
+#ifndef NDEBUG
+ ASSERT(!m_deletionHasBegun);
+ ASSERT(m_adoptionIsRequired);
+ m_adoptionIsRequired = false;
+#endif
+ }
+
protected:
RefCountedBase()
: m_refCount(1)
@@ -66,19 +70,15 @@ protected:
~RefCountedBase()
{
-#ifndef LOOSE_REF_COUNTED
ASSERT(m_deletionHasBegun);
ASSERT(!m_adoptionIsRequired);
-#endif
}
// Returns whether the pointer should be freed or not.
bool derefBase()
{
ASSERT(!m_deletionHasBegun);
-#ifndef LOOSE_REF_COUNTED
ASSERT(!m_adoptionIsRequired);
-#endif
ASSERT(m_refCount > 0);
if (m_refCount == 1) {
diff --git a/JavaScriptCore/wtf/RefPtr.h b/JavaScriptCore/wtf/RefPtr.h
index 86e4323..f0c3091 100644
--- a/JavaScriptCore/wtf/RefPtr.h
+++ b/JavaScriptCore/wtf/RefPtr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -59,7 +59,7 @@ namespace WTF {
T* get() const { return m_ptr; }
- void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
+ void clear();
PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
T& operator*() const { return *m_ptr; }
@@ -97,6 +97,13 @@ namespace WTF {
{
}
+ template <typename T> inline void RefPtr<T>::clear()
+ {
+ T* ptr = m_ptr;
+ m_ptr = 0;
+ derefIfNotNull(ptr);
+ }
+
template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
{
T* optr = o.get();
diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h
index f5a027e..2768be7 100644
--- a/JavaScriptCore/wtf/RetainPtr.h
+++ b/JavaScriptCore/wtf/RetainPtr.h
@@ -71,7 +71,7 @@ namespace WTF {
PtrType get() const { return m_ptr; }
- PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; }
+ PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; } WARN_UNUSED_RETURN;
PtrType operator->() const { return m_ptr; }
diff --git a/JavaScriptCore/wtf/SizeLimits.cpp b/JavaScriptCore/wtf/SizeLimits.cpp
index 090c1ed..4e481bb 100644
--- a/JavaScriptCore/wtf/SizeLimits.cpp
+++ b/JavaScriptCore/wtf/SizeLimits.cpp
@@ -41,7 +41,8 @@
namespace WTF {
#ifndef NDEBUG
-static const size_t refCountedExtraDebugSize = sizeof(int);
+struct StructWithIntAndTwoBools { int a; bool b; bool c; };
+static const size_t refCountedExtraDebugSize = sizeof(StructWithIntAndTwoBools) - sizeof(int);
#else
static const size_t refCountedExtraDebugSize = 0;
#endif
diff --git a/JavaScriptCore/wtf/StringExtras.h b/JavaScriptCore/wtf/StringExtras.h
index 342261b..473bb22 100644
--- a/JavaScriptCore/wtf/StringExtras.h
+++ b/JavaScriptCore/wtf/StringExtras.h
@@ -65,8 +65,8 @@ inline double wtf_vsnprintf(char* buffer, size_t count, const char* format, va_l
return result;
}
-// Work around a bug in Microsoft's implementation of vsnprintf, where
-// vsnprintf does not null terminate the buffer
+// Work around a difference in Microsoft's implementation of vsnprintf, where
+// vsnprintf does not null terminate the buffer. WebKit can rely on the null termination.
#define vsnprintf(buffer, count, format, args) wtf_vsnprintf(buffer, count, format, args)
#if OS(WINCE)
diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp
index c46ff31..0b7ecc9 100644
--- a/JavaScriptCore/wtf/TCSystemAlloc.cpp
+++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp
@@ -34,7 +34,6 @@
#include "TCSystemAlloc.h"
#include <algorithm>
-#include <fcntl.h>
#include "Assertions.h"
#include "TCSpinLock.h"
#include "UnusedParam.h"
diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h
index c833eeb..c60de15 100644
--- a/JavaScriptCore/wtf/Vector.h
+++ b/JavaScriptCore/wtf/Vector.h
@@ -557,6 +557,7 @@ namespace WTF {
const T& last() const { return at(size() - 1); }
template<typename U> size_t find(const U&) const;
+ template<typename U> size_t reverseFind(const U&) const;
void shrink(size_t size);
void grow(size_t size);
@@ -744,6 +745,18 @@ namespace WTF {
}
template<typename T, size_t inlineCapacity>
+ template<typename U>
+ size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const
+ {
+ for (size_t i = 1; i <= size(); ++i) {
+ const size_t index = size() - i;
+ if (at(index) == value)
+ return index;
+ }
+ return notFound;
+ }
+
+ template<typename T, size_t inlineCapacity>
void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
{
if (size() > newSize)
diff --git a/JavaScriptCore/wtf/gobject/GOwnPtr.h b/JavaScriptCore/wtf/gobject/GOwnPtr.h
index 1fc594c..40c0bf4 100644
--- a/JavaScriptCore/wtf/gobject/GOwnPtr.h
+++ b/JavaScriptCore/wtf/gobject/GOwnPtr.h
@@ -78,8 +78,9 @@ public:
void clear()
{
- freeOwnedGPtr(m_ptr);
+ T* ptr = m_ptr;
m_ptr = 0;
+ freeOwnedGPtr(ptr);
}
T& operator*() const
diff --git a/JavaScriptCore/wtf/gobject/GRefPtr.h b/JavaScriptCore/wtf/gobject/GRefPtr.h
index 3a33605..c4d4107 100644
--- a/JavaScriptCore/wtf/gobject/GRefPtr.h
+++ b/JavaScriptCore/wtf/gobject/GRefPtr.h
@@ -52,9 +52,10 @@ public:
void clear()
{
- if (T* ptr = m_ptr)
- derefGPtr(ptr);
+ T* ptr = m_ptr;
m_ptr = 0;
+ if (ptr)
+ derefGPtr(ptr);
}
T* get() const { return m_ptr; }
diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp
index d744b15..2d4417f 100644
--- a/JavaScriptCore/wtf/text/WTFString.cpp
+++ b/JavaScriptCore/wtf/text/WTFString.cpp
@@ -663,7 +663,7 @@ CString String::utf8() const
// simply encode it to UTF-8.
if (result == sourceExhausted) {
// This should be one unpaired high surrogate.
- ASSERT((characters + 1) == (characters + length));
+ ASSERT((characters + 1) == (this->characters() + length));
ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
// There should be room left, since one UChar hasn't been converted.
ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
index ecab5bd..5112de5 100644
--- a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
+++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp
@@ -69,13 +69,12 @@ PassOwnPtr<Collator> Collator::userDefault()
CFStringRef collationOrder = collationOrderRetainer.get();
#endif
char buf[256];
- if (collationOrder) {
- CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
- return new Collator(buf);
- } else
- return new Collator("");
+ if (!collationOrder)
+ return adoptPtr(new Collator(""));
+ CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
+ return adoptPtr(new Collator(buf));
#else
- return new Collator(0);
+ return adoptPtr(new Collator(0));
#endif
}
diff --git a/JavaScriptCore/yarr/RegexInterpreter.cpp b/JavaScriptCore/yarr/RegexInterpreter.cpp
index 09c82d1..4fb5f92 100644
--- a/JavaScriptCore/yarr/RegexInterpreter.cpp
+++ b/JavaScriptCore/yarr/RegexInterpreter.cpp
@@ -1235,17 +1235,16 @@ public:
ByteCompiler(RegexPattern& pattern)
: m_pattern(pattern)
{
- m_bodyDisjunction = 0;
m_currentAlternativeIndex = 0;
}
- BytecodePattern* compile()
+ PassOwnPtr<BytecodePattern> compile()
{
regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize);
emitDisjunction(m_pattern.m_body);
regexEnd();
- return new BytecodePattern(m_bodyDisjunction, m_allParenthesesInfo, m_pattern);
+ return adoptPtr(new BytecodePattern(m_bodyDisjunction.release(), m_allParenthesesInfo, m_pattern));
}
void checkInput(unsigned count)
@@ -1448,7 +1447,7 @@ public:
void regexBegin(unsigned numSubpatterns, unsigned callFrameSize)
{
- m_bodyDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
+ m_bodyDisjunction = adoptPtr(new ByteDisjunction(numSubpatterns, callFrameSize));
m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin());
m_bodyDisjunction->terms[0].frameLocation = 0;
m_currentAlternativeIndex = 0;
@@ -1568,19 +1567,19 @@ public:
private:
RegexPattern& m_pattern;
- ByteDisjunction* m_bodyDisjunction;
+ OwnPtr<ByteDisjunction> m_bodyDisjunction;
unsigned m_currentAlternativeIndex;
Vector<ParenthesesStackEntry> m_parenthesesStack;
Vector<ByteDisjunction*> m_allParenthesesInfo;
};
-BytecodePattern* byteCompileRegex(const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
+PassOwnPtr<BytecodePattern> byteCompileRegex(const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
{
RegexPattern pattern(ignoreCase, multiline);
if ((error = compileRegex(patternString, pattern)))
- return 0;
+ return PassOwnPtr<BytecodePattern>();
numSubpatterns = pattern.m_numSubpatterns;
diff --git a/JavaScriptCore/yarr/RegexInterpreter.h b/JavaScriptCore/yarr/RegexInterpreter.h
index e3c3122..af63a7b 100644
--- a/JavaScriptCore/yarr/RegexInterpreter.h
+++ b/JavaScriptCore/yarr/RegexInterpreter.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
@@ -30,6 +30,7 @@
#include "RegexParser.h"
#include "RegexPattern.h"
+#include <wtf/PassOwnPtr.h>
#include <wtf/unicode/Unicode.h>
namespace JSC { namespace Yarr {
@@ -292,7 +293,7 @@ public:
};
struct BytecodePattern : FastAllocBase {
- BytecodePattern(ByteDisjunction* body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
+ BytecodePattern(PassOwnPtr<ByteDisjunction> body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
: m_body(body)
, m_ignoreCase(pattern.m_ignoreCase)
, m_multiline(pattern.m_multiline)
@@ -325,7 +326,7 @@ private:
Vector<CharacterClass*> m_userCharacterClasses;
};
-BytecodePattern* byteCompileRegex(const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
+PassOwnPtr<BytecodePattern> byteCompileRegex(const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
int interpretRegex(BytecodePattern* v_regex, const UChar* input, unsigned start, unsigned length, int* output);
} } // namespace JSC::Yarr