diff options
author | Ben Murdoch <benm@google.com> | 2010-07-22 15:37:06 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-07-27 10:20:25 +0100 |
commit | 967717af5423377c967781471ee106e2bb4e11c8 (patch) | |
tree | 1e701dc0a12f7f07cce1df4a7681717de77a211b /JavaScriptCore | |
parent | dcc30a9fca45f634b1d3a12b276d3a0ccce99fc3 (diff) | |
download | external_webkit-967717af5423377c967781471ee106e2bb4e11c8.zip external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.gz external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.bz2 |
Merge WebKit at r63859 : Initial merge by git.
Change-Id: Ie8096c63ec7c991c9a9cba8bdd9c3b74a3b8ed62
Diffstat (limited to 'JavaScriptCore')
79 files changed, 3193 insertions, 1148 deletions
diff --git a/JavaScriptCore/CMakeLists.txt b/JavaScriptCore/CMakeLists.txt index bdb1467..efcc05d 100644 --- a/JavaScriptCore/CMakeLists.txt +++ b/JavaScriptCore/CMakeLists.txt @@ -50,10 +50,6 @@ SET(JavaScriptCore_SOURCES interpreter/RegisterFile.cpp jit/ExecutableAllocator.cpp - jit/ExecutableAllocatorFixedVMPool.cpp - jit/ExecutableAllocatorPosix.cpp - jit/ExecutableAllocatorSymbian.cpp - jit/ExecutableAllocatorWin.cpp jit/JITArithmetic32_64.cpp jit/JITArithmetic.cpp jit/JITCall32_64.cpp diff --git a/JavaScriptCore/CMakeListsEfl.txt b/JavaScriptCore/CMakeListsEfl.txt index aca73a8..945ad52 100644 --- a/JavaScriptCore/CMakeListsEfl.txt +++ b/JavaScriptCore/CMakeListsEfl.txt @@ -1,4 +1,6 @@ LIST(APPEND JavaScriptCore_SOURCES + jit/ExecutableAllocatorFixedVMPool.cpp + jit/ExecutableAllocatorPosix.cpp runtime/MarkStackPosix.cpp ) @@ -8,4 +10,4 @@ LIST(APPEND JavaScriptCore_LIBRARIES LIST(APPEND JavaScriptCore_LINK_FLAGS ${ECORE_LDFLAGS} -)
\ No newline at end of file +) diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 0acccc8..5e01de2 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,653 @@ +2010-07-20 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Adam Roben. + + WebKit on Windows should build optionally with an unversioned ICU DLL + https://bugs.webkit.org/show_bug.cgi?id=42722 + <rdar://problem/8211743> JavaScriptCore needs to link against unversioned ICU + + Dynamically create a new header, ICUVersion.h, as part of build-generated-files.sh. + Header contains a preprocessor define (U_DISABLE_RENAMING) indicating to ICU whether the ICU API + should be namespaced with the current ICU version number. Proper value is determined + by checking for the presence of libicuuc.lib, the unversioned copy of ICU. + + To get the proper value for U_DISABLE_RENAMING into all source files, we force + the include of ICUVersion.h (our generated header) via the compiler options. + + Since the versioned and unversioned ICU have different filenames (libicuuc.lib vs icuuc.lib) + we copy the ICU lib to an intermediate location under obj with a common name. This + allows us to link properly with either without adding a new build configuration. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + Copy ICU libs into a common location with a common name. + Add additional library search path to pick up icu lib. + Change ICU library filename specified to linker. + Add forced include of ICUVersion.h. + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Generate ICUVersion.h + * JavaScriptCore.vcproj/WTF/WTFCommon.vsprops: Add forced include of ICUVersion.h. + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: + Copy ICU libs into a common location with a common name. + Add additional library search path to pick up icu lib. + Change ICU library filename specified to linker. + Add forced include of ICUVersion.h. + * JavaScriptCore.vcproj/testapi/testapiCommon.vsprops: + Copy ICU libs into a common location with a common name. + Add additional library search path to pick up icu lib. + Change ICU library filename specified to linker. + Add forced include of ICUVersion.h. + +2010-07-20 Steve Falkenburg <sfalken@apple.com> + + Re-save vsprops files after no-op edits in Visual Studio + to fix manual edit issues. + +2010-07-20 Mahesh Kulkarni <mahesh.kulkarni@nokia.com> + + Reviewed by Steve Block. + + Need to be able to configure Geolocation policy regarding user permissions + https://bugs.webkit.org/show_bug.cgi?id=42068 + + If CLIENT_BASED_GEOLOCATION is enabled, enable preemtive permission policy + by default + + * wtf/Platform.h: + +2010-07-20 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r63742. + http://trac.webkit.org/changeset/63742 + https://bugs.webkit.org/show_bug.cgi?id=42641 + + Broke Leopard Intel build. (Requested by bbandix on #webkit). + + * wtf/Platform.h: + +2010-07-20 Mahesh Kulkarni <mahesh.kulkarni@nokia.com> + + Reviewed by Steve Block. + + Need to be able to configure Geolocation policy regarding user permissions + https://bugs.webkit.org/show_bug.cgi?id=42068 + + If CLIENT_BASED_GEOLOCATION is enabled, enable preemtive permission policy + by default + + * wtf/Platform.h: + +2010-07-19 Dirk Schulze <krit@webkit.org> + + Reviewed by Nikolas Zimmermann. + + SVG CleanUp of SVGPathData parsing + https://bugs.webkit.org/show_bug.cgi?id=41410 + + Added piOverTwo to MathExtras. + + * wtf/MathExtras.h: + +2010-07-19 Mike Moretti <mike.moretti@nokia.com> + + Reviewed by Laszlo Gombos. + + [Symbian] Build fix after r63404. + + Implement isValid() function for the Symbian executable allocator. + + * jit/ExecutableAllocatorSymbian.cpp: + (JSC::ExecutableAllocator::isValid): + +2010-07-19 Chris Marrin <cmarrin@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=42118 + Disable WebGL on Leopard for now. + + LayoutTests fail on some graphics hardware on Leopard because one of the features we use, + GL_ARB_framebuffer_object, is not universally available in Leopard like it is in + SnowLeopard. This will allow LayoutTests to pass on Leopard until we add logic to use a + software OpenGL driver on machines without this support. + + * Configurations/FeatureDefines.xcconfig: + +2010-07-16 Darin Adler <darin@apple.com> + + Reviewed by Sam Weinig. + + Use OwnPtr for CodeBlock objects + https://bugs.webkit.org/show_bug.cgi?id=42490 + + * runtime/Executable.cpp: + (JSC::EvalExecutable::EvalExecutable): Moved this here and made it non-inline. + Eliminated the code that used to initialize the raw pointer since it's now + an OwnPtr. + (JSC::EvalExecutable::~EvalExecutable): Removed the explicit delete here. + (JSC::ProgramExecutable::ProgramExecutable): Ditto. + (JSC::ProgramExecutable::~ProgramExecutable): Ditto. + (JSC::FunctionExecutable::FunctionExecutable): Ditto. + (JSC::FunctionExecutable::~FunctionExecutable): Ditto. + (JSC::EvalExecutable::compileInternal): Added use of adoptPtr and get. + (JSC::ProgramExecutable::compileInternal): Ditto. + (JSC::FunctionExecutable::compileForCallInternal): Ditto. + (JSC::FunctionExecutable::compileForConstructInternal): Ditto. + (JSC::FunctionExecutable::recompile): Use clear instead of delete followed + by assignment of 0. + + * runtime/Executable.h: Moved constructors to the cpp file and changed + raw pointers to OwnPtr. + +2010-07-19 Lucas De Marchi <lucas.demarchi@profusion.mobi> + + Reviewed by Kenneth Rohde Christiansen. + + [EFL] Fix build on 64-bit systems. According to + JavaScriptCore/wtf/Platform.h, x86_64 uses fixed allocator, which + needs jit/ExecutableAllocatorFixedVMPool.cpp to be included in build + system. + https://bugs.webkit.org/show_bug.cgi?id=42559 + + * CMakeListsEfl.txt: add missing file for x86_64. + +2010-07-16 Leandro Pereira <leandro@profusion.mobi> + + [EFL] Unreviewed build system cleanup. + + Move ExecutableAllocator{FixedVMPool,Posix,Symbian,Win}.cpp from + root CMakeLists.txt to the platform CMakeLists.txt. + + * CMakeLists.txt: + * CMakeListsEfl.txt: Add ExecutableAllocatorPosix.cpp. + +2010-07-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + ES5 allows use of reserved words as IdentifierName + https://bugs.webkit.org/show_bug.cgi?id=42471 + + Modify the lexer to allow us to avoid identifying reserved + words in those contexts where they are valid identifiers, and + we know it's safe. Additionally tag the reserved word tokens + so we can easily identify them in those cases where we can't + guarantee that we've skipped reserved word identification. + + * parser/JSParser.cpp: + (JSC::JSParser::next): + (JSC::JSParser::parseProperty): + (JSC::JSParser::parseMemberExpression): + * parser/JSParser.h: + (JSC::): + * parser/Lexer.cpp: + (JSC::Lexer::lex): + * parser/Lexer.h: + (JSC::Lexer::): + +2010-07-16 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + clang++ build fixes for JavaScriptCore and WebCore + https://bugs.webkit.org/show_bug.cgi?id=42478 + + * runtime/RegExpKey.h: + (JSC::operator==): + Move the RegExpKey equals operator into the JSC namespace so it can be found by ADL. + +2010-07-16 Anders Carlsson <andersca@apple.com> + + Reviewed by David Levin. + + Really add WARN_UNUSED_RESULT to leakRef + https://bugs.webkit.org/show_bug.cgi?id=42464 + + * wtf/PassRefPtr.h: + (WTF::PassRefPtr::): + (WTF::NonNullPassRefPtr::): + Put the WARN_UNUSED_RESULT attribute at the right place. + + * wtf/RetainPtr.h: + (WTF::RetainPtr::releaseRef): + Remove WARN_UNUSED_RESULT here for now, it leads to two warnings that need + to be fixed first. + +2010-07-15 Victor Wang <victorw@chromium.org> + + Reviewed by David Levin. + + [Chromium] Disable c4291 for chromium windows multi dll build. + + https://bugs.webkit.org/show_bug.cgi?id=42177 + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2010-07-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Maciej Stachowiak. + + Crash entering mail.yahoo.com + https://bugs.webkit.org/show_bug.cgi?id=42394 + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::argumentNumberFor): Added a NULL check. If the + identifier we're resolving is not a local variable, registerFor returns + NULL. + + * bytecompiler/NodesCodegen.cpp: + (JSC::FunctionBodyNode::emitBytecode): Unrelated to the crash, but I + noticed this while working on it: No need to NULL-check returnNode, + since an early return has already done so. + +2010-07-15 Martin Robinson <mrobinson@igalia.com> + + Reviewed by Oliver Hunt. + + [GTK] Simplify the distribution step + https://bugs.webkit.org/show_bug.cgi?id=42414 + + * GNUmakefile.am: Add extra dist files directly to EXTRA_DIST instead + of adding them by proxy via javascriptcore_dist. Sort the EXTRA_DIST list. + Refer to create_hash_table and create_regexp_tables directly, as is the + behavior with other code generation scripts. + +2010-07-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Fix dumping of op_put_by_id. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::printPutByIdOp): + +2010-07-15 Zoltan Herczeg <zherczeg@webkit.org> + + Reviewed by Darin Adler. + + Refactoring some parts of the lexer + https://bugs.webkit.org/show_bug.cgi?id=41845 + + This patch is a precursor of refactoring the identifier + parsing, which currently slows down the lexer, and not + ready for landing. This patch contains those sources, + which does not slow down the lexer (mainly style changes). + + SunSpider: no change (529.4ms to 528.7ms) + --parse-only: no change (31.0ms to 31.2ms) + + * parser/Lexer.cpp: + (JSC::isIdentStart): using typesOfASCIICharacters to determine + whether the current character is in identifier start + (JSC::isIdentPart): using typesOfASCIICharacters to determine + whether the current character is in identifier part + (JSC::Lexer::parseString): style fix + (JSC::Lexer::lex): removing the else after the main which + which reduces code duplication + +2010-07-15 Mark Rowe <mrowe@apple.com> + + Update the sorting in the Xcode project files. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-07-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Make sure that mixed interpreter/jit builds don't try to use the jit if the allocator fails + https://bugs.webkit.org/show_bug.cgi?id=42310 + + Add some null checks to deal with the Fixed VM allocator failing + to get the requested executable region, delay the creation of the + JITStubs in JSGlobalData until after we know whether we're using + the JIT. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::ExecutableAllocator): + (JSC::ExecutableAllocator::poolForSize): + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator): + (JSC::FixedVMPoolAllocator::alloc): + (JSC::FixedVMPoolAllocator::free): + (JSC::FixedVMPoolAllocator::isValid): + (JSC::ExecutableAllocator::isValid): + (JSC::ExecutablePool::systemAlloc): + (JSC::ExecutablePool::systemRelease): + * jit/ExecutableAllocatorPosix.cpp: + (JSC::ExecutableAllocator::isValid): + * jit/ExecutableAllocatorWin.cpp: + (JSC::ExecutableAllocator::isValid): + * jit/JIT.cpp: + (JSC::JIT::linkCall): + (JSC::JIT::linkConstruct): + * jit/JIT.h: + (JSC::JIT::compileCTIMachineTrampolines): + (JSC::JIT::compileCTINativeCall): + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_mod): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_mod): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTINativeCall): + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + (JSC::JITThunks::tryCacheGetByID): + (JSC::JITThunks::hostFunctionStub): + * jit/ThunkGenerators.cpp: + (JSC::charCodeAtThunkGenerator): + (JSC::charAtThunkGenerator): + (JSC::fromCharCodeThunkGenerator): + (JSC::sqrtThunkGenerator): + (JSC::powThunkGenerator): + * runtime/Executable.h: + (JSC::NativeExecutable::create): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::getHostFunction): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::getCTIStub): + * yarr/RegexJIT.cpp: + (JSC::Yarr::jitCompileRegex): + +2010-07-14 Gavin Barraclough <barraclough@apple.com> + + Speculative Qt/Windows build fix. + + * jit/JITStubs.h: + +2010-07-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=42280 + JIT_STUB_ARGUMENT_VA_LIST is only slowing us down! Remove it! + + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::restoreArgumentReferenceForTrampoline): + * jit/JITStubs.cpp: + * jit/JITStubs.h: + * wtf/Platform.h: + +2010-07-14 Oliver Hunt <oliver@apple.com> + + RS=Geoff Garen. + + Guard the CF path of interpreter vs. jit selection with PLATFORM(CF) + + This allows the code to work on windows as well. Also unifies the + environment variable with the preference name. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + +2010-07-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Don Melton. + + Crash when trying to enable JIT and Interpreter in a single build. + + CFPreferences code added at the last minute failed to account for + the preference not being present and then attempted to CFRelease + a null value. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + +2010-07-14 Zoltan Herczeg <zherczeg@webkit.org> + + Reviewed by Darin Adler. + + Change indentations in the lexer + https://bugs.webkit.org/show_bug.cgi?id=41845 + + This patch fixes an old, indentation error comes from kjs, + as webkit has a different style rule for switches, and change + the indentation of the main switch, which is a temporary + style error. This change makes easier to see the behavioural + changes in the follow-up patch. + + No behavioural changes. + + * parser/Lexer.cpp: + (JSC::singleEscape): + (JSC::Lexer::lex): + +2010-07-13 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r63262. + http://trac.webkit.org/changeset/63262 + https://bugs.webkit.org/show_bug.cgi?id=42229 + + broke Windows compile (Requested by bweinstein on #webkit). + + * API/tests/testapi.c: + (assertEqualsAsCharactersPtr): + (main): + * testapi.pro: Removed. + +2010-07-13 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + ES5 requires BOMs to be treated as whitespace + https://bugs.webkit.org/show_bug.cgi?id=42218 + + Add BOM character to the Lexer's definition of whitespace, + and remove the logic that dealt with stripping BOMs and + caching the cleaned string. + + * parser/Lexer.h: + (JSC::Lexer::isWhiteSpace): + * parser/SourceProvider.h: + (JSC::UStringSourceProvider::create): + (JSC::UStringSourceProvider::UStringSourceProvider): + * wtf/text/StringImpl.h: + +2010-07-13 Andreas Kling <andreas.kling@nokia.com> + + Reviewed by Darin Adler. + + Avoid slow-path for put() in Array.splice() + https://bugs.webkit.org/show_bug.cgi?id=41920 + + Defer creation of the returned array until its final size is known + to avoid growing it while adding elements. + + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): Add two modes of creation, CreateInitialized (old) + and CreateCompact (which should only be used when constructing arrays whose + size and contents are known at the time of creation.) + (JSC::JSArray::setLength): Skip first consistency check if in CreateCompact + initialization mode. (Only applies to non-empty arrays.) + (JSC::JSArray::checkConsistency): Build fix (JSValue::type() is gone) + * runtime/JSArray.h: + (JSC::JSArray::uncheckedSetIndex): Added for fast initialization of compact + arrays. Does no bounds or other sanity checking. + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncSplice): Optimized creation of the returned JSArray. + * runtime/ArrayConstructor.cpp: + (JSC::constructArrayWithSizeQuirk): Pass CreateInitialized to ctor. + * runtime/JSGlobalObject.h: + (JSC::constructEmptyArray): Pass CreateInitialized to ctor. + * runtime/RegExpConstructor.cpp: + (JSC::RegExpMatchesArray::RegExpMatchesArray): Pass CreateInitialized to ctor. + +2010-07-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 42207 - Clean up interface to compile executables, always check for exceptions + + Presently interface to compile executable is inconsistent between eval/program and + function code, and is error prone in allowing a caller to byte compile without JIT + compiling an executable (we rely on all executables with codeblocks having JIT code). + Unify on an interface where all compilation is performed by a single compile (with + ForCall|ForConstruct variants) method, and make all clients check for errors. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::unwindCallFrame): + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): + (JSC::Interpreter::prepareForRepeatCall): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * parser/Parser.h: + (JSC::Parser::isFunctionBodyNode): + (JSC::Parser::parse): + * runtime/ArrayPrototype.cpp: + (JSC::isNumericCompareFunction): + * runtime/ExceptionHelpers.cpp: + (JSC::createStackOverflowError): + * runtime/ExceptionHelpers.h: + * runtime/Executable.cpp: + (JSC::EvalExecutable::compileInternal): + (JSC::ProgramExecutable::checkSyntax): + (JSC::ProgramExecutable::compileInternal): + (JSC::FunctionExecutable::compileForCallInternal): + (JSC::FunctionExecutable::compileForConstructInternal): + (JSC::FunctionExecutable::reparseExceptionInfo): + (JSC::EvalExecutable::reparseExceptionInfo): + (JSC::FunctionExecutable::fromGlobalCode): + * runtime/Executable.h: + (JSC::EvalExecutable::compile): + (JSC::EvalExecutable::generatedBytecode): + (JSC::EvalExecutable::generatedJITCode): + (JSC::ProgramExecutable::compile): + (JSC::ProgramExecutable::generatedBytecode): + (JSC::ProgramExecutable::generatedJITCode): + (JSC::FunctionExecutable::generatedBytecode): + (JSC::FunctionExecutable::compileForCall): + (JSC::FunctionExecutable::compileForConstruct): + (JSC::FunctionExecutable::generatedJITCodeForConstructWithArityCheck): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/JSActivation.cpp: + (JSC::JSActivation::argumentsGetter): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::canUseJIT): + +2010-07-13 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> + + Reviewed by Oliver Hunt. + + testapi.c depends on the Core Foundation. + https://bugs.webkit.org/show_bug.cgi?id=40058 + + Separate CoreFoundation specific tests in JSC's testapi.c. Enabling it + to compile in Qt environments. + + All tests should work except for the JSStringCreateWithCharacters() function, + because its tests depend on Core Foundation specific functions. + + * API/tests/testapi.c: + (testJSStringRefCF): moved CoreFoundation specific tests to this function. + (main): The moves plus some minor tweaks. + * testapi.pro: Added. + +2010-07-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 42182 - Change how numeric compare functions are detected + + There are three problems with the current mechanism: + * It requires that a function executable be bytecode compiled without + being JIT generated (in order to copy the bytecode from the numeric + compare function). This is a problem since we have an invariant when + running with the JIT that functions are never bytecode compiled without + also being JIT generated (after checking the codeblock we assume the + function has JIT code). To help maintain this invariant + * This implementation will prevent us from experimenting with alternate + compilation paths which do not compile via bytecode. + * It doesn't work. Functions passing more than two arguments will match + if they are comparing their last two arguments, not the first two. + Generally the mapping back from bytecode to semantics may be more + complex then initially expected. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::generate): + (JSC::BytecodeGenerator::setIsNumericCompareFunction): + (JSC::BytecodeGenerator::argumentNumberFor): + * bytecompiler/BytecodeGenerator.h: + * bytecompiler/NodesCodegen.cpp: + (JSC::BlockNode::singleStatement): + (JSC::FunctionBodyNode::emitBytecode): + * parser/Nodes.h: + (JSC::ExpressionNode::isSubtract): + (JSC::BinaryOpNode::lhs): + (JSC::BinaryOpNode::rhs): + (JSC::SubNode::isSubtract): + (JSC::ReturnNode::value): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + +2010-07-12 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + REGRESSION: Crash at JSC::JIT::privateCompile(JSC::MacroAssemblerCodePtr*) + https://bugs.webkit.org/show_bug.cgi?id=41763 + + There are two parts to this patch, the first is to fix the actual + problem. When calling copyStringWithoutBOMs on a string we know + to contain BOMs we return a value indicating that there are no + BOMs. + + The second part of this fix is simply to harden the path that + led to a crash when parsing failed. + + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + Harden compilation stubs against parser failure. + * parser/Lexer.cpp: + (JSC::Lexer::sourceCode): + Add assertions to ensure that subranges into a source provider + are always actually braces. Hopefully this should catch similar + failures in future. These assertions fire on existing tests + without this fix. + * runtime/Executable.h: + (JSC::FunctionExecutable::tryJitCodeForCall): + (JSC::FunctionExecutable::tryJitCodeForConstruct): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::copyStringWithoutBOMs): + Make copyStringWithBOMs do the right thing. + +2010-07-13 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Fix the constant encoding in data transfer instructions on ARM + https://bugs.webkit.org/show_bug.cgi?id=42166 + + The getImm function is designed to produce modified immediate constant + for data processing instructions. It should not be used to encode + any constant for data transfer. In the current situation there is no + way to use any immediate constant for data transfer. So, the moveImm + function is the desired method to pass the offset value to the data + transfer instructions. + + Reported by Jacob Bramley. + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::dataTransfer32): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::call32): + 2010-07-09 Darin Adler <darin@apple.com> Reviewed by Geoffrey Garen. diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 9a3ec0b..4b363aa 100644 --- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -34,7 +34,6 @@ 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; ENABLE_3D_CANVAS_1070 = ENABLE_3D_CANVAS; diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 28cff47..9a2886f 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -554,14 +554,14 @@ javascriptcore_sources += \ JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h endif -JavaScriptCore/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser/Keywords.table +JavaScriptCore/Lexer.lut.h: $(srcdir)/JavaScriptCore/create_hash_table $(srcdir)/JavaScriptCore/parser/Keywords.table $(AM_V_GEN)$(PERL) $^ > $@ -JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp +JavaScriptCore/%.lut.h: $(srcdir)/JavaScriptCore/create_hash_table $(srcdir)/JavaScriptCore/%.cpp $(AM_V_GEN)$(PERL) $^ -i > $@ JavaScriptCore/RegExpJitTables.h: $(srcdir)/JavaScriptCore/create_regex_tables - $(AM_V_GEN)$(PYTHON) $(CREATE_REGEXP_TABLES) > $@ + $(AM_V_GEN)$(PYTHON) $^ > $@ JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables $(AM_V_GEN)$(PERL) $^ $@ @@ -627,20 +627,20 @@ Programs_jsc_CXXFLAGS = \ Programs_jsc_LDADD = \ libJavaScriptCore.la -javascriptcore_dist += \ - $(CREATE_HASH_TABLE) \ - $(CREATE_REGEXP_TABLES) \ +EXTRA_DIST += \ JavaScriptCore/AUTHORS \ - JavaScriptCore/COPYING.LIB \ JavaScriptCore/ChangeLog \ - JavaScriptCore/THANKS \ + JavaScriptCore/COPYING.LIB \ + JavaScriptCore/create_hash_table \ + JavaScriptCore/create_regex_tables \ JavaScriptCore/icu/LICENSE \ JavaScriptCore/icu/README \ - JavaScriptCore/pcre/COPYING \ + JavaScriptCore/parser/Keywords.table \ JavaScriptCore/pcre/AUTHORS \ + JavaScriptCore/pcre/COPYING \ JavaScriptCore/pcre/dftables \ JavaScriptCore/pcre/ucptable.cpp \ - JavaScriptCore/parser/Keywords.table + JavaScriptCore/THANKS # Clean rules for JavaScriptCore CLEANFILES += \ diff --git a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index 9e014dd..32270e8 100644 --- a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -142,6 +142,18 @@ 'include_dirs!': [ '<(SHARED_INTERMEDIATE_DIR)/webkit', ], + 'conditions': [ + ['inside_chromium_build==1 and component=="shared_library"', { + # Chromium windows multi-dll build enables c++ exception and this + # causes wtf generates 4291 warning due to operator new/delete + # implementations. Disable the warning for chromium windows + # multi-dll build. + 'msvs_disabled_warnings': [4291], + 'direct_dependent_settings': { + 'msvs_disabled_warnings': [4291], + }, + }], + ], }], ], }, diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops index ad81c36..c92196e 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops @@ -1,26 +1,32 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="JavaScriptCoreCommon" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads"" - PreprocessorDefinitions="__STD_C" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="gdi32.lib oleaut32.lib winmm.lib icuin$(LibraryConfigSuffix).lib icuuc$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib WTF$(WebKitConfigSuffix).lib" - OutputFile="$(OutDir)\$(ProjectName)$(WebKitDLLConfigSuffix).dll" - ModuleDefinitionFile="JavaScriptCore.def" - /> - <Tool - Name="VCPostBuildEventTool" - CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\AtomicString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\StringImpl.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\WTFString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"


mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
" - /> - <Tool - Name="VCPreBuildEventTool" - CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
" - /> -</VisualStudioPropertySheet> +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="JavaScriptCoreCommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads""
+ PreprocessorDefinitions="__STD_C"
+ ForcedIncludeFiles="ICUVersion.h"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="gdi32.lib oleaut32.lib winmm.lib libicuin$(LibraryConfigSuffix).lib libicuuc$(LibraryConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib WTF$(WebKitConfigSuffix).lib"
+ OutputFile="$(OutDir)\$(ProjectName)$(WebKitDLLConfigSuffix).dll"
+ AdditionalLibraryDirectories=""$(IntDir)\lib""
+ ModuleDefinitionFile="JavaScriptCore.def"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\AtomicString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\StringImpl.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\WTFString.cpp" "$(WebKitOutputDir)\include\private\JavaScriptCore"


mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ />
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"

bash "$(WebKitLibrariesDir)\tools\scripts\auto-version.sh" "$(IntDir)"
"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="mkdir 2>NUL "$(IntDir)\lib"

if exist "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuuc$(LibraryConfigSuffix).lib"
if exist "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuin$(LibraryConfigSuffix).lib"

if exist "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib"
if exist "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib"

cmd /c
"
+ />
+</VisualStudioPropertySheet>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh index 5955365..85c3152 100755 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh @@ -10,6 +10,16 @@ then echo "#define QUARTZCORE_PRESENT $?" > "${QUARTZCOREPRESENT_H_PATH}" fi +# Determine whether we have the versioned ICU 4.0 or the unversioned ICU 4.4 +UNVERSIONED_ICU_LIB_PATH=$(cygpath -u "${WEBKITLIBRARIESDIR}/lib/libicuuc.lib") +ICUVERSION_H_PATH=$(cygpath -u "${WEBKITOUTPUTDIR}/include/private/ICUVersion.h") +if test \( ! -f "${ICUVERSION_H_PATH}" \) -o \( -f "${UNVERSIONED_ICU_LIB_PATH}" -a \( "${UNVERSIONED_ICU_LIB_PATH}" -nt "${ICUVERSION_H_PATH}" \) \) +then + mkdir -p "$(dirname "${ICUVERSION_H_PATH}")" + test ! -f "${UNVERSIONED_ICU_LIB_PATH}" + echo "#define U_DISABLE_RENAMING $?" > "${ICUVERSION_H_PATH}" +fi + NUMCPUS=`../../../WebKitTools/Scripts/num-cpus` XSRCROOT="`pwd`/../.." diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops index b41682f..c2569ba 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops @@ -9,6 +9,7 @@ Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../parser/;../../wtf/;../../wtf/unicode/;"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
+ ForcedIncludeFiles="ICUVersion.h"
/>
<Tool
Name="VCLibrarianTool"
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops index a8102c9..e5cc866 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops @@ -1,25 +1,32 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="jscCommon" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../API/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;../../profiler;../../jit/;"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\include"" - PreprocessorDefinitions="__STD_C" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib icuin$(LibraryConfigSuffix).lib icuuc$(LibraryConfigSuffix).lib winmm.lib pthreadVC2$(LibraryConfigSuffix).lib user32.lib" - SubSystem="1" - /> - <Tool - Name="VCPostBuildEventTool" - CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
if exist "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"

cmd /c
" - /> - <Tool - Name="VCPreBuildEventTool" - CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"
" - /> -</VisualStudioPropertySheet> +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="jscCommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../API/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;../../profiler;../../jit/;"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\include""
+ PreprocessorDefinitions="__STD_C"
+ ForcedIncludeFiles="ICUVersion.h"
+ ForcedUsingFiles=""
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib libicuin$(LibraryConfigSuffix).lib libicuuc$(LibraryConfigSuffix).lib winmm.lib pthreadVC2$(LibraryConfigSuffix).lib user32.lib"
+ AdditionalLibraryDirectories=""$(IntDir)\lib""
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
if exist "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"

cmd /c
"
+ />
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"
"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="mkdir 2>NUL "$(IntDir)\lib"

if exist "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuuc$(LibraryConfigSuffix).lib"
if exist "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuin$(LibraryConfigSuffix).lib"

if exist "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib"
if exist "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib"

cmd /c
"
+ />
+</VisualStudioPropertySheet>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiCommon.vsprops index 161f571..a1a7267 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiCommon.vsprops @@ -1,26 +1,32 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="testapiCommon" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(ProjectDir)\..\..\API";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private\JavaScriptCore";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private"" - WarningLevel="4" - Detect64BitPortabilityProblems="true" - /> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WTF$(WebKitConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib icuin$(LibraryConfigSuffix).lib icuuc$(LibraryConfigSuffix).lib" - SubSystem="1" - /> - <Tool - Name="VCPostBuildEventTool" - CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

xcopy /y /d "$(ProjectDir)\..\..\API\tests\testapi.js" "$(OutDir)"
" - /> - <Tool - Name="VCPreBuildEventTool" - CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"
" - /> -</VisualStudioPropertySheet> +<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="testapiCommon"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""$(ProjectDir)\..\..\API";"$(WebKitOutputDir)\include\WebCore\ForwardingHeaders";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private\JavaScriptCore";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private""
+ WarningLevel="4"
+ Detect64BitPortabilityProblems="true"
+ ForcedIncludeFiles="ICUVersion.h"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="JavaScriptCore$(WebKitDLLConfigSuffix).lib WTF$(WebKitConfigSuffix).lib pthreadVC2$(LibraryConfigSuffix).lib libicuin$(LibraryConfigSuffix).lib libicuuc$(LibraryConfigSuffix).lib"
+ AdditionalLibraryDirectories=""$(IntDir)\lib""
+ SubSystem="1"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

xcopy /y /d "$(ProjectDir)\..\..\API\tests\testapi.js" "$(OutDir)"
"
+ />
+ <Tool
+ Name="VCPreBuildEventTool"
+ CommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c
if exist "$(WebKitOutputDir)\buildfailed" grep XX$(ProjectName)XX "$(WebKitOutputDir)\buildfailed"
if errorlevel 1 exit 1
echo XX$(ProjectName)XX > "$(WebKitOutputDir)\buildfailed"
"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="mkdir 2>NUL "$(IntDir)\lib"

if exist "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuuc$(LibraryConfigSuffix).lib"
if exist "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\icuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib\libicuin$(LibraryConfigSuffix).lib"

if exist "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuuc$(LibraryConfigSuffix).lib" "$(IntDir)\lib"
if exist "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" copy /y "$(WebKitLibrariesDir)\lib\libicuin$(LibraryConfigSuffix).lib" "$(IntDir)\lib"

cmd /c
"
+ />
+</VisualStudioPropertySheet>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 2dd4abd..562b4a1 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -1250,9 +1250,6 @@ 1429D92C0ED22D7000B89619 /* jit */ = { isa = PBXGroup; children = ( - A7386551118697B400540279 /* SpecializedThunkJIT.h */, - A7386552118697B400540279 /* ThunkGenerators.cpp */, - A7386553118697B400540279 /* ThunkGenerators.h */, A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */, A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */, 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */, @@ -1274,6 +1271,9 @@ 14A23D6C0F4E19CE0023CDAD /* JITStubs.cpp */, 14A6581A0F4E36F4000150FD /* JITStubs.h */, A76C51741182748D00715B05 /* JSInterfaceJIT.h */, + A7386551118697B400540279 /* SpecializedThunkJIT.h */, + A7386552118697B400540279 /* ThunkGenerators.cpp */, + A7386553118697B400540279 /* ThunkGenerators.h */, ); path = jit; sourceTree = "<group>"; @@ -1314,12 +1314,12 @@ 146AAB2A0B66A84900E55F16 /* JSStringRefCF.h */, 14BD5A2B0A3E91F600BAF59C /* JSValueRef.cpp */, 1482B6EA0A4300B300517CFC /* JSValueRef.h */, + A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */, + A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */, + A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */, E124A8F60E555775003091F1 /* OpaqueJSString.cpp */, E124A8F50E555775003091F1 /* OpaqueJSString.h */, 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */, - A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */, - A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */, - A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */, ); path = API; sourceTree = "<group>"; @@ -1374,7 +1374,6 @@ 650FDF8D09D0FCA700769E54 /* Derived Sources */ = { isa = PBXGroup; children = ( - A718F61A11754A21002465A7 /* RegExpJitTables.h */, BC18C5230E16FC8A00B34460 /* ArrayPrototype.lut.h */, 65B174BE09D1000200820339 /* chartables.c */, BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */, @@ -1383,6 +1382,7 @@ BC18C5290E16FCC200B34460 /* MathObject.lut.h */, BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */, BCD202D50E170708002C7E82 /* RegExpConstructor.lut.h */, + A718F61A11754A21002465A7 /* RegExpJitTables.h */, BC18C52B0E16FCD200B34460 /* RegExpObject.lut.h */, BC18C5250E16FCA700B34460 /* StringPrototype.lut.h */, 5D53727D0E1C55EC0021E549 /* TracingDtrace.h */, @@ -1419,6 +1419,7 @@ E48E0F2C0F82151700A8CA37 /* FastAllocBase.h */, 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */, 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */, + A7F19ECD11DD490900931E70 /* FixedArray.h */, 935AF46909E9D9DB00ACD1D8 /* Forward.h */, 93B6A0DE0AA64DA40076DE27 /* GetPtr.h */, 657EEBBF094E445E008C9C7B /* HashCountedSet.h */, @@ -1458,8 +1459,8 @@ 65C647B3093EF8D60022C380 /* RefPtr.h */, 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */, 51F648D60BB4E2CA0033D760 /* RetainPtr.h */, - 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */, 969A07290ED1CE6900F1F681 /* SegmentedVector.h */, + 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */, 868BFA5F117D048200B908B1 /* StaticConstructors.h */, FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, E11D51750B2E798D0056C188 /* StringExtras.h */, @@ -1486,7 +1487,6 @@ 96DD73780F9DA3100027FBCC /* VMTags.h */, 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */, 86D08D5211793613006E5ED0 /* WTFThreadData.h */, - A7F19ECD11DD490900931E70 /* FixedArray.h */, ); path = wtf; sourceTree = "<group>"; @@ -1551,9 +1551,6 @@ 7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = { isa = PBXGroup; children = ( - A1712B4011C7B235007A5315 /* RegExpKey.h */, - A1712B3E11C7B228007A5315 /* RegExpCache.h */, - A1712B3A11C7B212007A5315 /* RegExpCache.cpp */, BCF605110E203EF800B9A64D /* ArgList.cpp */, BCF605120E203EF800B9A64D /* ArgList.h */, BC257DE50E1F51C50016B6C9 /* Arguments.cpp */, @@ -1704,8 +1701,11 @@ 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */, F692A87D0255597D01FF60F7 /* RegExp.cpp */, F692A87E0255597D01FF60F7 /* RegExp.h */, + A1712B3A11C7B212007A5315 /* RegExpCache.cpp */, + A1712B3E11C7B228007A5315 /* RegExpCache.h */, BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */, BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */, + A1712B4011C7B235007A5315 /* RegExpKey.h */, 93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */, F692A87B0255597D01FF60F7 /* RegExpObject.cpp */, F692A87C0255597D01FF60F7 /* RegExpObject.h */, @@ -1913,11 +1913,16 @@ 9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */, 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */, BC18C3EA0E16F5CD00B34460 /* Assertions.h in Headers */, + A784A26111D16622005776AC /* ASTBuilder.h in Headers */, + BC5F7BBE11823B590052C02C /* Atomics.h in Headers */, + 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */, + 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */, BC18C3EB0E16F5CD00B34460 /* AVLTree.h in Headers */, 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */, A7A1F7AD0F252B3C00E184E2 /* ByteArray.h in Headers */, 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */, + 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */, BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */, 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, 95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */, @@ -1933,6 +1938,7 @@ BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */, 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */, 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */, + 86565743115BE3DA00291F40 /* CString.h in Headers */, 180B9B080F16D94F009BDBC5 /* CurrentTime.h in Headers */, BCD2034A0E17135E002C7E82 /* DateConstructor.h in Headers */, 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */, @@ -1957,6 +1963,7 @@ A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */, E48E0F2D0F82151700A8CA37 /* FastAllocBase.h in Headers */, BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */, + A7F19ECE11DD490900931E70 /* FixedArray.h in Headers */, BC18C4030E16F5CD00B34460 /* Forward.h in Headers */, BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */, BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */, @@ -2001,12 +2008,16 @@ BC18C4210E16F5CD00B34460 /* JSGlobalObject.h in Headers */, BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */, BC18C4220E16F5CD00B34460 /* JSImmediate.h in Headers */, + A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */, BC18C4230E16F5CD00B34460 /* JSLock.h in Headers */, BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */, BC18C4240E16F5CD00B34460 /* JSObject.h in Headers */, BC18C4250E16F5CD00B34460 /* JSObjectRef.h in Headers */, + A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */, + A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */, A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */, BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */, + A784A26311D16622005776AC /* JSParser.h in Headers */, 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */, BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */, BC18C4270E16F5CD00B34460 /* JSString.h in Headers */, @@ -2018,7 +2029,10 @@ BC18C42B0E16F5CD00B34460 /* JSValue.h in Headers */, BC18C42C0E16F5CD00B34460 /* JSValueRef.h in Headers */, BC18C42D0E16F5CD00B34460 /* JSVariableObject.h in Headers */, + A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */, + A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */, BC18C42E0E16F5CD00B34460 /* JSWrapperObject.h in Headers */, + BC01D4F211A8F1FF00A54B2A /* JSZombie.h in Headers */, BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */, 969A072A0ED1CE6900F1F681 /* Label.h in Headers */, 960097A60EBABB58007A7297 /* LabelScope.h in Headers */, @@ -2034,6 +2048,7 @@ 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */, 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */, 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */, + 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */, 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */, 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */, 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */, @@ -2043,7 +2058,9 @@ BC18C43B0E16F5CD00B34460 /* MathExtras.h in Headers */, BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */, BC18C52A0E16FCC200B34460 /* MathObject.lut.h in Headers */, + 511FC4CB117EE2A800425272 /* MD5.h in Headers */, BC18C43E0E16F5CD00B34460 /* MessageQueue.h in Headers */, + 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */, BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */, BC02E9130E1839DB000F9297 /* NativeErrorPrototype.h in Headers */, A76EE6590FAE59D5003F069A /* NativeFunctionWrapper.h in Headers */, @@ -2097,8 +2114,10 @@ BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, 86EAC49B0F93E8D1008EC948 /* RegexParser.h in Headers */, 86EAC49C0F93E8D1008EC948 /* RegexPattern.h in Headers */, + A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */, BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */, + A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */, BC18C45B0E16F5CD00B34460 /* RegExpObject.h in Headers */, BC18C52C0E16FCD200B34460 /* RegExpObject.lut.h in Headers */, BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */, @@ -2108,17 +2127,24 @@ 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */, 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */, BC18C4600E16F5CD00B34460 /* RetainPtr.h in Headers */, + 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */, 1429D8860ED21C3D00B89619 /* SamplingTool.h in Headers */, BC18C4610E16F5CD00B34460 /* ScopeChain.h in Headers */, 969A072C0ED1CE6900F1F681 /* SegmentedVector.h in Headers */, 933040040E6A749400786E6A /* SmallStrings.h in Headers */, BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */, BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */, + A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */, + 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */, + 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, 8698B86910D44D9400D8D01B /* StringBuilder.h in Headers */, BC18C4660E16F5CD00B34460 /* StringConstructor.h in Headers */, BC18C4670E16F5CD00B34460 /* StringExtras.h in Headers */, + 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */, 5D63E9AD10F2BD6E00FC8AE9 /* StringHashFunctions.h in Headers */, + 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */, + 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */, BC18C4680E16F5CD00B34460 /* StringObject.h in Headers */, BC18C4690E16F5CD00B34460 /* StringObjectThatMasqueradesAsUndefined.h in Headers */, BC18C46A0E16F5CD00B34460 /* StringPrototype.h in Headers */, @@ -2128,14 +2154,18 @@ BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */, BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */, BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */, + A784A26411D16622005776AC /* SyntaxChecker.h in Headers */, BC18C46C0E16F5CD00B34460 /* TCPackedCache.h in Headers */, BC18C46D0E16F5CD00B34460 /* TCPageMap.h in Headers */, BC18C46E0E16F5CD00B34460 /* TCSpinLock.h in Headers */, BC18C46F0E16F5CD00B34460 /* TCSystemAlloc.h in Headers */, + 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */, 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */, BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, + BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, + BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */, BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */, - 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */, + A7386556118697B400540279 /* ThunkGenerators.h in Headers */, 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */, 5D53726F0E1C54880021E549 /* Tracing.h in Headers */, 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */, @@ -2154,39 +2184,9 @@ 14035DB110DBFB2A00FFFFE7 /* WeakGCPtr.h in Headers */, 1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */, BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */, - 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, - A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */, - 86565743115BE3DA00291F40 /* CString.h in Headers */, - A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */, - A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */, - 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */, - 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */, - 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */, - 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */, - 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */, 868BFA18117CF19900B908B1 /* WTFString.h in Headers */, - 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, - 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */, - 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, - 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */, - 511FC4CB117EE2A800425272 /* MD5.h in Headers */, - BC5F7BBE11823B590052C02C /* Atomics.h in Headers */, - BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, - BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */, - A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */, - A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */, - A7386556118697B400540279 /* ThunkGenerators.h in Headers */, - 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */, - 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */, - 86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */, - A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */, - BC01D4F211A8F1FF00A54B2A /* JSZombie.h in Headers */, - A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */, - A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */, - A784A26111D16622005776AC /* ASTBuilder.h in Headers */, - A784A26311D16622005776AC /* JSParser.h in Headers */, - A784A26411D16622005776AC /* SyntaxChecker.h in Headers */, - A7F19ECE11DD490900931E70 /* FixedArray.h in Headers */, + 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */, + 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2462,6 +2462,7 @@ 147F39BF107EC37600427A48 /* ArrayConstructor.cpp in Sources */, 147F39C0107EC37600427A48 /* ArrayPrototype.cpp in Sources */, 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */, + 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */, 14280863107EC11A0013E7B2 /* BooleanConstructor.cpp in Sources */, 14280864107EC11A0013E7B2 /* BooleanObject.cpp in Sources */, 14280865107EC11A0013E7B2 /* BooleanPrototype.cpp in Sources */, @@ -2476,6 +2477,7 @@ 147F39C1107EC37600427A48 /* CommonIdentifiers.cpp in Sources */, 147F39C2107EC37600427A48 /* Completion.cpp in Sources */, 1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */, + 86565742115BE3DA00291F40 /* CString.cpp in Sources */, 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */, 147F39C3107EC37600427A48 /* DateConstructor.cpp in Sources */, 147F39C4107EC37600427A48 /* DateConversion.cpp in Sources */, @@ -2507,8 +2509,11 @@ 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */, 1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */, 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */, + A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */, 86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */, + 146FE51211A710430087AE66 /* JITCall32_64.cpp in Sources */, BCDD51EB0FB8DF74004A8BDC /* JITOpcodes.cpp in Sources */, + A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */, 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */, A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */, 14A23D750F4E1ABB0023CDAD /* JITStubs.cpp in Sources */, @@ -2533,7 +2538,9 @@ 1428085D107EC0F80013E7B2 /* JSNumberCell.cpp in Sources */, 147F39D4107EC37600427A48 /* JSObject.cpp in Sources */, 1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */, + A783A2AB11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp in Sources */, A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */, + A784A26211D16622005776AC /* JSParser.cpp in Sources */, 95F6E6950E5B5F970091E860 /* JSProfilerPrivate.cpp in Sources */, A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */, 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */, @@ -2543,16 +2550,20 @@ 147F39D6107EC37600427A48 /* JSValue.cpp in Sources */, 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */, 147F39D7107EC37600427A48 /* JSVariableObject.cpp in Sources */, + A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */, 14280870107EC1340013E7B2 /* JSWrapperObject.cpp in Sources */, + BC01D4F111A8F1FF00A54B2A /* JSZombie.cpp in Sources */, BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */, 148F21B0107EC5410042EC2C /* Lexer.cpp in Sources */, A7E2EA6C0FB460CF00601F06 /* LiteralParser.cpp in Sources */, 14469DDE107EC7E700650446 /* Lookup.cpp in Sources */, + 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */, 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */, 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */, A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */, A7C530E4102A3813005BC741 /* MarkStackPosix.cpp in Sources */, 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */, + 511FC4C9117EE28700425272 /* MD5.cpp in Sources */, 14469DE0107EC7E700650446 /* NativeErrorConstructor.cpp in Sources */, 14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */, 148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */, @@ -2587,16 +2598,21 @@ 86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */, 86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in Sources */, 14280841107EC0930013E7B2 /* RegExp.cpp in Sources */, + A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */, 14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */, 14280843107EC0930013E7B2 /* RegExpObject.cpp in Sources */, 14280844107EC0930013E7B2 /* RegExpPrototype.cpp in Sources */, 1428083A107EC0750013E7B2 /* RegisterFile.cpp in Sources */, + 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */, 1429D8850ED21C3D00B89619 /* SamplingTool.cpp in Sources */, 14469DEA107EC7E700650446 /* ScopeChain.cpp in Sources */, + 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */, 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */, + 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */, 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */, + 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */, BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */, 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */, BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */, @@ -2604,29 +2620,13 @@ 18BAB55310DAE054000D945B /* ThreadIdentifierDataPthreads.cpp in Sources */, 5D6A566B0F05995500266145 /* Threading.cpp in Sources */, E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, + A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */, 14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */, 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */, 14469DEE107EC7E700650446 /* UString.cpp in Sources */, E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, - 86565742115BE3DA00291F40 /* CString.cpp in Sources */, - A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */, - 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */, - 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */, - 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */, - 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */, - 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */, - 511FC4C9117EE28700425272 /* MD5.cpp in Sources */, - A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */, - A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */, - 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */, - A71236E51195F33C00BD2174 /* JITOpcodes32_64.cpp in Sources */, - 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */, - 146FE51211A710430087AE66 /* JITCall32_64.cpp in Sources */, - A783A2AB11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp in Sources */, - BC01D4F111A8F1FF00A54B2A /* JSZombie.cpp in Sources */, - A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */, - A784A26211D16622005776AC /* JSParser.cpp in Sources */, + 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/assembler/ARMAssembler.cpp b/JavaScriptCore/assembler/ARMAssembler.cpp index a181b7e..0016540 100644 --- a/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/JavaScriptCore/assembler/ARMAssembler.cpp @@ -272,8 +272,8 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8)); dtr_u(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag); } else { - ARMWord reg = getImm(offset, ARMRegisters::S0); - dtr_ur(isLoad, srcDst, base, reg | transferFlag); + moveImm(offset, ARMRegisters::S0); + dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag); } } else { offset = -offset; @@ -283,8 +283,8 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8)); dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag); } else { - ARMWord reg = getImm(offset, ARMRegisters::S0); - dtr_dr(isLoad, srcDst, base, reg | transferFlag); + moveImm(offset, ARMRegisters::S0); + dtr_dr(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag); } } } diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h index 1c64071..bb1a6da 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -956,9 +956,9 @@ protected: prepareCall(); m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff); } else { - ARMWord reg = m_assembler.getImm(offset, tmpReg); + m_assembler.moveImm(offset, tmpReg); prepareCall(); - m_assembler.dtr_ur(true, targetReg, base, reg); + m_assembler.dtr_ur(true, targetReg, base, tmpReg); } } else { offset = -offset; @@ -970,9 +970,9 @@ protected: prepareCall(); m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff); } else { - ARMWord reg = m_assembler.getImm(offset, tmpReg); + m_assembler.moveImm(offset, tmpReg); prepareCall(); - m_assembler.dtr_dr(true, targetReg, base, reg); + m_assembler.dtr_dr(true, targetReg, base, tmpReg); } } #if WTF_ARM_ARCH_AT_LEAST(5) diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index a664719..0e55d6a 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -174,7 +174,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); - it += 4; + it += 5; } #if ENABLE(JIT) diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 8ff1b5d..a3fa937 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -152,8 +152,6 @@ void BytecodeGenerator::generate() if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode) symbolTable().clear(); - - m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec())); #if !ENABLE(OPCODE_SAMPLING) if (!m_regeneratingForExceptionInfo && !m_usesExceptions && (m_codeType == FunctionCode || m_codeType == EvalCode)) @@ -2045,4 +2043,19 @@ RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException() return exception; } +void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunction) +{ + m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction); +} + +int BytecodeGenerator::argumentNumberFor(const Identifier& ident) +{ + int parameterCount = m_parameters.size(); // includes 'this' + RegisterID* registerID = registerFor(ident); + if (!registerID) + return 0; + int index = registerID->index() + RegisterFile::CallFrameHeaderSize + parameterCount; + return (index > 0 && index < parameterCount) ? index : 0; +} + } // namespace JSC diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 2b231a7..ad0ae4e 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -108,7 +108,12 @@ namespace JSC { // such register exists. Registers returned by registerFor do not // require explicit reference counting. RegisterID* registerFor(const Identifier&); - + + // Returns the agument number if this is an argument, or 0 if not. + int argumentNumberFor(const Identifier&); + + void setIsNumericCompareFunction(bool isNumericCompareFunction); + bool willResolveToArguments(const Identifier&); RegisterID* uncheckedRegisterForArguments(); diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp index e50ce2d..277562d 100644 --- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -1359,6 +1359,11 @@ inline StatementNode* BlockNode::lastStatement() const return m_statements ? m_statements->lastStatement() : 0; } +inline StatementNode* BlockNode::singleStatement() const +{ + return m_statements ? m_statements->singleStatement() : 0; +} + RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { if (m_statements) @@ -2011,16 +2016,38 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe { generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); emitStatementsBytecode(generator, generator.ignoredResult()); + StatementNode* singleStatement = this->singleStatement(); + ReturnNode* returnNode = 0; + + // Check for a return statement at the end of a function composed of a single block. if (singleStatement && singleStatement->isBlock()) { StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement(); if (lastStatementInBlock && lastStatementInBlock->isReturnNode()) - return 0; + returnNode = static_cast<ReturnNode*>(lastStatementInBlock); + } + + // If there is no return we must automatically insert one. + if (!returnNode) { + RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitReturn(r0); + return 0; + } + + // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare. + if (static_cast<BlockNode*>(singleStatement)->singleStatement()) { + ExpressionNode* returnValueExpression = returnNode->value(); + if (returnValueExpression && returnValueExpression->isSubtract()) { + ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs(); + ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs(); + if (lhsExpression->isResolveNode() && rhsExpression->isResolveNode()) { + generator.setIsNumericCompareFunction(generator.argumentNumberFor(static_cast<ResolveNode*>(lhsExpression)->identifier()) == 1 + && generator.argumentNumberFor(static_cast<ResolveNode*>(rhsExpression)->identifier()) == 2); + } + } } - RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); - generator.emitReturn(r0); return 0; } diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 26f7a6b..2342ed6 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -547,18 +547,17 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex return false; codeBlock = callerFrame->codeBlock(); -#if ENABLE(JIT) -#if ENABLE(INTERPRETER) +#if ENABLE(JIT) && ENABLE(INTERPRETER) if (callerFrame->globalData().canUseJIT()) -#endif bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); -#if ENABLE(INTERPRETER) else bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC()); -#endif +#elif ENABLE(JIT) + bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC()); #else bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC()); #endif + callFrame = callerFrame; return true; } @@ -660,11 +659,12 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S } } - CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain); - if (!codeBlock) { - *exception = createStackOverflowError(callFrame); + JSObject* error = program->compile(callFrame, scopeChain); + if (error) { + *exception = error; return jsNull(); } + CodeBlock* codeBlock = &program->generatedBytecode(); Register* oldEnd = m_registerFile.end(); Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; @@ -697,17 +697,11 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S m_reentryDepth++; #if ENABLE(JIT) -#if ENABLE(INTERPRETER) if (callFrame->globalData().canUseJIT()) -#endif - result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); -#if ENABLE(INTERPRETER) + result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); else #endif -#endif -#if ENABLE(INTERPRETER) result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); -#endif m_reentryDepth--; } @@ -752,12 +746,16 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); - if (newCodeBlock) - newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); - else - newCallFrame = 0; + JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain); + if (UNLIKELY(!!compileError)) { + *exception = compileError; + m_registerFile.shrink(oldEnd); + return jsNull(); + } + + CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); + newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); m_registerFile.shrink(oldEnd); @@ -778,17 +776,11 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT 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) + result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception); else #endif -#endif -#if ENABLE(INTERPRETER) result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); -#endif m_reentryDepth--; } @@ -851,12 +843,16 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (constructType == ConstructTypeJS) { ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain; - CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain); - if (newCodeBlock) - newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); - else - newCallFrame = 0; + JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain); + if (UNLIKELY(!!compileError)) { + *exception = compileError; + m_registerFile.shrink(oldEnd); + return 0; + } + + CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct(); + newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); m_registerFile.shrink(oldEnd); @@ -877,17 +873,11 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc 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) + result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception); else #endif -#endif -#if ENABLE(INTERPRETER) result = privateExecute(Normal, &m_registerFile, newCallFrame, exception); -#endif m_reentryDepth--; } @@ -952,11 +942,15 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE for (int i = 0; i < argc; ++i) newCallFrame->r(++dst) = jsUndefined(); - CodeBlock* codeBlock = FunctionExecutable->bytecodeForCall(callFrame, scopeChain); - if (codeBlock) - newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); - else - newCallFrame = 0; + JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain); + if (error) { + *exception = error; + m_registerFile.shrink(oldEnd); + return CallFrameClosure(); + } + CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall(); + + newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc); if (UNLIKELY(!newCallFrame)) { *exception = createStackOverflowError(callFrame); m_registerFile.shrink(oldEnd); @@ -964,12 +958,6 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE } // a 0 codeBlock indicates a built-in caller newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function); -#if ENABLE(JIT) -#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; } @@ -1013,7 +1001,12 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure) JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception) { - return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); + JSObject* compileError = eval->compile(callFrame, scopeChain); + if (UNLIKELY(!!compileError)) { + *exception = compileError; + return jsNull(); + } + return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception); } JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception) @@ -1029,11 +1022,12 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); - EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain); - if (!codeBlock) { - *exception = createStackOverflowError(callFrame); + JSObject* compileError = eval->compile(callFrame, scopeChain); + if (UNLIKELY(!!compileError)) { + *exception = compileError; return jsNull(); } + EvalCodeBlock* codeBlock = &eval->generatedBytecode(); JSVariableObject* variableObject; for (ScopeChainNode* node = scopeChain; ; node = node->next) { @@ -1096,7 +1090,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec #if ENABLE(INTERPRETER) if (callFrame->globalData().canUseJIT()) #endif - result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); + result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception); #if ENABLE(INTERPRETER) else #endif @@ -3712,13 +3706,16 @@ skip_id_custom_self: if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); + + JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain); + if (UNLIKELY(!!error)) { + exceptionValue = error; + goto vm_throw; + } CallFrame* previousCallFrame = callFrame; - if (newCodeBlock) - callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); - else - callFrame = 0; + CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); + callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); if (UNLIKELY(!callFrame)) { callFrame = previousCallFrame; exceptionValue = createStackOverflowError(callFrame); @@ -3870,19 +3867,22 @@ skip_id_custom_self: if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; - CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain); - + + JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain); + if (UNLIKELY(!!error)) { + exceptionValue = error; + goto vm_throw; + } + CallFrame* previousCallFrame = callFrame; - if (newCodeBlock) - callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); - else - callFrame = 0; + CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall(); + callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); if (UNLIKELY(!callFrame)) { callFrame = previousCallFrame; exceptionValue = createStackOverflowError(callFrame); goto vm_throw; } - + callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v)); codeBlock = newCodeBlock; ASSERT(codeBlock == callFrame->codeBlock()); @@ -4195,15 +4195,16 @@ skip_id_custom_self: if (constructType == ConstructTypeJS) { ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; - CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain); - - CallFrame* previousCallFrame = callFrame; - if (newCodeBlock) - callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); - else - callFrame = 0; + JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScopeChain); + if (UNLIKELY(!!error)) { + exceptionValue = error; + goto vm_throw; + } + CallFrame* previousCallFrame = callFrame; + CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct(); + callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount); if (UNLIKELY(!callFrame)) { callFrame = previousCallFrame; exceptionValue = createStackOverflowError(callFrame); diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h index 703f63f..8fd6b71 100644 --- a/JavaScriptCore/jit/ExecutableAllocator.h +++ b/JavaScriptCore/jit/ExecutableAllocator.h @@ -150,12 +150,20 @@ public: { if (!pageSize) intializePageSize(); - m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE); + if (isValid()) + m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE); +#if !ENABLE(INTERPRETER) + else + CRASH(); +#endif } + bool isValid() const; + PassRefPtr<ExecutablePool> poolForSize(size_t n) { // Try to fit in the existing small allocator + ASSERT(m_smallAllocationPool); if (n < m_smallAllocationPool->available()) return m_smallAllocationPool; diff --git a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 7846a25..65c9c13 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -306,20 +306,30 @@ public: 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(); - // For simplicity, we keep all memory in m_freeList in a 'released' state. - // This means that we can simply reuse all memory when allocating, without - // worrying about it's previous state, and also makes coalescing m_freeList - // simpler since we need not worry about the possibility of coalescing released - // chunks with non-released ones. - release(m_base, m_totalHeapSize); - m_freeList.insert(new FreeListEntry(m_base, m_totalHeapSize)); + if (m_base) { + // For simplicity, we keep all memory in m_freeList in a 'released' state. + // This means that we can simply reuse all memory when allocating, without + // worrying about it's previous state, and also makes coalescing m_freeList + // simpler since we need not worry about the possibility of coalescing released + // chunks with non-released ones. + release(m_base, m_totalHeapSize); + m_freeList.insert(new FreeListEntry(m_base, m_totalHeapSize)); + } +#if !ENABLE(INTERPRETER) + else + CRASH(); +#endif } void* alloc(size_t size) { +#if ENABLE(INTERPRETER) + if (!m_base) + return 0; +#else + ASSERT(m_base); +#endif void* result; // Freed allocations of the common size are not stored back into the main @@ -382,6 +392,7 @@ public: void free(void* pointer, size_t size) { + ASSERT(m_base); // Call release to report to the operating system that this // memory is no longer in use, and need not be paged out. ASSERT(isWithinVMPool(pointer, size)); @@ -404,6 +415,8 @@ public: } } + bool isValid() const { return !!m_base; } + private: #ifndef NDEBUG @@ -435,19 +448,26 @@ void ExecutableAllocator::intializePageSize() static FixedVMPoolAllocator* allocator = 0; static SpinLock spinlock = SPINLOCK_INITIALIZER; -ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size) +bool ExecutableAllocator::isValid() const { - SpinLockHolder lock_holder(&spinlock); - + SpinLockHolder lock_holder(&spinlock); if (!allocator) allocator = new FixedVMPoolAllocator(JIT_ALLOCATOR_LARGE_ALLOC_SIZE, VM_POOL_SIZE); + return allocator->isValid(); +} + +ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size) +{ + SpinLockHolder lock_holder(&spinlock); + + ASSERT(allocator); ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocator->alloc(size)), size}; return alloc; } void ExecutablePool::systemRelease(const ExecutablePool::Allocation& allocation) { - SpinLockHolder lock_holder(&spinlock); + SpinLockHolder lock_holder(&spinlock); ASSERT(allocator); allocator->free(allocation.pages, allocation.size); diff --git a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp index b04049c..a841d32 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp @@ -55,6 +55,11 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) ASSERT_UNUSED(result, !result); } +bool ExecutableAllocator::isValid() const +{ + return true; +} + } #endif diff --git a/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp b/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp index 9028f50..8b0553d 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp @@ -66,6 +66,11 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) delete alloc.chunk; } +bool ExecutableAllocator::isValid() const +{ + return true; +} + #if ENABLE(ASSEMBLER_WX_EXCLUSIVE) #error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform." #endif diff --git a/JavaScriptCore/jit/ExecutableAllocatorWin.cpp b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp index 72a1d5f..2b13529 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorWin.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorWin.cpp @@ -54,6 +54,11 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) VirtualFree(alloc.pages, 0, MEM_RELEASE); } +bool ExecutableAllocator::isValid() const +{ + return true; +} + #if ENABLE(ASSEMBLER_WX_EXCLUSIVE) #error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform." #endif diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp index 5d96847..f5df5f7 100644 --- a/JavaScriptCore/jit/JIT.cpp +++ b/JavaScriptCore/jit/JIT.cpp @@ -637,7 +637,7 @@ void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* ca } // patch the call so we do not continue to try to link. - repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs.ctiVirtualCall()); + repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualCall()); } void JIT::linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData) @@ -657,7 +657,7 @@ void JIT::linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBloc } // patch the call so we do not continue to try to link. - repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs.ctiVirtualConstruct()); + repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualConstruct()); } #endif // ENABLE(JIT_OPTIMIZE_CALL) diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h index 0980be2..f9be930 100644 --- a/JavaScriptCore/jit/JIT.h +++ b/JavaScriptCore/jit/JIT.h @@ -219,12 +219,16 @@ namespace JSC { static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, TrampolineStructure *trampolines) { + if (!globalData->canUseJIT()) + return; JIT jit(globalData); jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines); } static CodePtr compileCTINativeCall(JSGlobalData* globalData, PassRefPtr<ExecutablePool> executablePool, NativeFunction func) { + if (!globalData->canUseJIT()) + return CodePtr(); JIT jit(globalData); return jit.privateCompileCTINativeCall(executablePool, globalData, func); } @@ -352,12 +356,8 @@ namespace JSC { static const int patchOffsetGetByIdPropertyMapOffset1 = 22; static const int patchOffsetGetByIdPropertyMapOffset2 = 28; static const int patchOffsetGetByIdPutResult = 28; -#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST) - static const int patchOffsetGetByIdSlowCaseCall = 35; -#elif ENABLE(OPCODE_SAMPLING) +#if ENABLE(OPCODE_SAMPLING) static const int patchOffsetGetByIdSlowCaseCall = 37; -#elif USE(JIT_STUB_ARGUMENT_VA_LIST) - static const int patchOffsetGetByIdSlowCaseCall = 25; #else static const int patchOffsetGetByIdSlowCaseCall = 27; #endif @@ -549,12 +549,8 @@ namespace JSC { static const int patchLengthGetByIdExternalLoad = 3; static const int patchOffsetGetByIdPropertyMapOffset = 22; static const int patchOffsetGetByIdPutResult = 22; -#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST) - static const int patchOffsetGetByIdSlowCaseCall = 31; -#elif ENABLE(OPCODE_SAMPLING) +#if ENABLE(OPCODE_SAMPLING) static const int patchOffsetGetByIdSlowCaseCall = 33; -#elif USE(JIT_STUB_ARGUMENT_VA_LIST) - static const int patchOffsetGetByIdSlowCaseCall = 21; #else static const int patchOffsetGetByIdSlowCaseCall = 23; #endif diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp index 0e5bb45..0f6d290 100644 --- a/JavaScriptCore/jit/JITArithmetic.cpp +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -1203,7 +1203,7 @@ void JIT::emit_op_mod(Instruction* currentInstruction) addSlowCase(branch32(Equal, regT2, Imm32(1))); - emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); + emitNakedCall(m_globalData->jitStubs->ctiSoftModulo()); emitPutVirtualRegister(result, regT0); #else diff --git a/JavaScriptCore/jit/JITArithmetic32_64.cpp b/JavaScriptCore/jit/JITArithmetic32_64.cpp index 4f36d66..232e287 100644 --- a/JavaScriptCore/jit/JITArithmetic32_64.cpp +++ b/JavaScriptCore/jit/JITArithmetic32_64.cpp @@ -1370,7 +1370,7 @@ void JIT::emit_op_mod(Instruction* currentInstruction) addSlowCase(branch32(Equal, regT2, Imm32(0))); - emitNakedCall(m_globalData->jitStubs.ctiSoftModulo()); + emitNakedCall(m_globalData->jitStubs->ctiSoftModulo()); emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); #else diff --git a/JavaScriptCore/jit/JITCall.cpp b/JavaScriptCore/jit/JITCall.cpp index 5c2b308..368eab9 100644 --- a/JavaScriptCore/jit/JITCall.cpp +++ b/JavaScriptCore/jit/JITCall.cpp @@ -81,7 +81,7 @@ void JIT::compileOpCallVarargs(Instruction* instruction) addPtr(callFrameRegister, regT3); storePtr(callFrameRegister, regT3); addPtr(regT2, callFrameRegister); - emitNakedCall(m_globalData->jitStubs.ctiVirtualCall()); + emitNakedCall(m_globalData->jitStubs->ctiVirtualCall()); sampleCodeBlock(m_codeBlock); } @@ -132,7 +132,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); move(Imm32(argCount), regT1); - emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs.ctiVirtualConstruct() : m_globalData->jitStubs.ctiVirtualCall()); + emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall()); if (opcodeID == op_call_eval) wasEval.link(this); @@ -231,7 +231,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); move(Imm32(argCount), regT1); - m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs.ctiVirtualConstructLink() : m_globalData->jitStubs.ctiVirtualCallLink()); + m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink()); // Done! - return back to the hot path. ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval)); diff --git a/JavaScriptCore/jit/JITCall32_64.cpp b/JavaScriptCore/jit/JITCall32_64.cpp index 5f551cc..aa8e987 100644 --- a/JavaScriptCore/jit/JITCall32_64.cpp +++ b/JavaScriptCore/jit/JITCall32_64.cpp @@ -82,7 +82,7 @@ void JIT::compileOpCallVarargs(Instruction* instruction) move(regT2, regT1); // argCount - emitNakedCall(m_globalData->jitStubs.ctiVirtualCall()); + emitNakedCall(m_globalData->jitStubs->ctiVirtualCall()); sampleCodeBlock(m_codeBlock); } @@ -232,7 +232,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); move(Imm32(argCount), regT1); - emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs.ctiVirtualConstruct() : m_globalData->jitStubs.ctiVirtualCall()); + emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall()); if (opcodeID == op_call_eval) wasEval.link(this); @@ -333,7 +333,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); move(Imm32(argCount), regT1); - m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs.ctiVirtualConstructLink() : m_globalData->jitStubs.ctiVirtualCallLink()); + m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink()); // Done! - return back to the hot path. ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval)); diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h index 04f7158..3b28f34 100644 --- a/JavaScriptCore/jit/JITInlineMethods.h +++ b/JavaScriptCore/jit/JITInlineMethods.h @@ -181,18 +181,12 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address) #endif -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -ALWAYS_INLINE void JIT::restoreArgumentReference() -{ - poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*)); -} -ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {} -#else ALWAYS_INLINE void JIT::restoreArgumentReference() { move(stackPointerRegister, firstArgumentRegister); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*)); } + ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() { #if CPU(X86) @@ -203,7 +197,6 @@ ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() #endif // In the trampoline on x86-64, the first argument register is not overwritten. } -#endif ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure) { diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp index 8e86d40..949dee3 100644 --- a/JavaScriptCore/jit/JITOpcodes.cpp +++ b/JavaScriptCore/jit/JITOpcodes.cpp @@ -73,14 +73,14 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // VirtualCallLink Trampoline // regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable. - JumpList callLazyLinkFailures; + JumpList callLinkFailures; Label virtualCallLinkBegin = align(); compileOpCallInitializeCallFrame(); preserveReturnAddressAfterCall(regT3); emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); restoreArgumentReference(); Call callLazyLinkCall = call(); - callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); + callLinkFailures.append(branchTestPtr(Zero, regT0)); restoreReturnAddressBeforeReturn(regT3); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); jump(regT0); @@ -93,24 +93,11 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); restoreArgumentReference(); Call callLazyLinkConstruct = call(); - callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); + callLinkFailures.append(branchTestPtr(Zero, regT0)); restoreReturnAddressBeforeReturn(regT3); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); jump(regT0); - // If the parser fails we want to be able to be able to keep going, - // So we handle this as a parse failure. - callLazyLinkFailures.link(this); - emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); - emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); - restoreReturnAddressBeforeReturn(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); - storePtr(regT1, regT2); - poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); - poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); - ret(); - - // VirtualCall Trampoline // regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable. Label virtualCallBegin = align(); @@ -122,6 +109,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCall = call(); + callLinkFailures.append(branchTestPtr(Zero, regT0)); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); restoreReturnAddressBeforeReturn(regT3); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -141,6 +129,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileConstruct = call(); + callLinkFailures.append(branchTestPtr(Zero, regT0)); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); restoreReturnAddressBeforeReturn(regT3); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -148,6 +137,18 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0); jump(regT0); + + // If the parser fails we want to be able to be able to keep going, + // So we handle this as a parse failure. + callLinkFailures.link(this); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); + restoreReturnAddressBeforeReturn(regT1); + move(ImmPtr(&globalData->exceptionLocation), regT2); + storePtr(regT1, regT2); + poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); + poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); + ret(); // NativeCall Trampoline Label nativeCallThunk = privateCompileCTINativeCall(globalData); @@ -307,7 +308,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool>, JSGlobalData* globalData, NativeFunction) { - return globalData->jitStubs.ctiNativeCall(); + return globalData->jitStubs->ctiNativeCall(); } void JIT::emit_op_mov(Instruction* currentInstruction) diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp index a44a8a1..658ebc5 100644 --- a/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -64,10 +64,10 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable ret(); #endif - + + JumpList callLinkFailures; // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct. #if ENABLE(JIT_OPTIMIZE_CALL) - JumpList callLazyLinkFailures; // VirtualCallLink Trampoline // regT0 holds callee, regT1 holds argCount. regT2 will hold the FunctionExecutable. Label virtualCallLinkBegin = align(); @@ -76,7 +76,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); restoreArgumentReference(); Call callLazyLinkCall = call(); - callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); + callLinkFailures.append(branchTestPtr(Zero, regT0)); restoreReturnAddressBeforeReturn(regT3); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); jump(regT0); @@ -90,22 +90,10 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable restoreArgumentReference(); Call callLazyLinkConstruct = call(); restoreReturnAddressBeforeReturn(regT3); - callLazyLinkFailures.append(branchTestPtr(Zero, regT0)); + callLinkFailures.append(branchTestPtr(Zero, regT0)); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); jump(regT0); - // If the parser fails we want to be able to be able to keep going, - // So we handle this as a parse failure. - callLazyLinkFailures.link(this); - emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); - emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); - restoreReturnAddressBeforeReturn(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); - storePtr(regT1, regT2); - poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); - poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); - ret(); - #endif // ENABLE(JIT_OPTIMIZE_CALL) // VirtualCall Trampoline @@ -119,6 +107,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCall = call(); + callLinkFailures.append(branchTestPtr(Zero, regT0)); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); restoreReturnAddressBeforeReturn(regT3); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -138,6 +127,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCconstruct = call(); + callLinkFailures.append(branchTestPtr(Zero, regT0)); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1); restoreReturnAddressBeforeReturn(regT3); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); @@ -145,6 +135,18 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0); jump(regT0); + + // If the parser fails we want to be able to be able to keep going, + // So we handle this as a parse failure. + callLinkFailures.link(this); + emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); + emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); + restoreReturnAddressBeforeReturn(regT1); + move(ImmPtr(&globalData->exceptionLocation), regT2); + storePtr(regT1, regT2); + poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); + poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); + ret(); // NativeCall Trampoline Label nativeCallThunk = privateCompileCTINativeCall(globalData); diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp index 85bd54f..f088b6e 100644 --- a/JavaScriptCore/jit/JITStubs.cpp +++ b/JavaScriptCore/jit/JITStubs.cpp @@ -139,9 +139,7 @@ asm ( ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" -#if !USE(JIT_STUB_ARGUMENT_VA_LIST) "movl %esp, %ecx" "\n" -#endif "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addl $0x3c, %esp" "\n" "popl %ebx" "\n" @@ -165,10 +163,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(GCC) && CPU(X86_64) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." -#endif - // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment); @@ -235,10 +229,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(GCC) && CPU(ARM_THUMB2) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." -#endif - #define THUNK_RETURN_ADDRESS_OFFSET 0x3C #define PRESERVED_RETURN_ADDRESS_OFFSET 0x40 #define PRESERVED_R4_OFFSET 0x44 @@ -256,10 +246,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(MSVC) && CPU(X86) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." -#endif - // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); @@ -358,9 +344,7 @@ asm ( ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" -#if !USE(JIT_STUB_ARGUMENT_VA_LIST) "movl %esp, %ecx" "\n" -#endif "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addl $0x1c, %esp" "\n" "popl %ebx" "\n" @@ -384,10 +368,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(GCC) && CPU(X86_64) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." -#endif - // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); @@ -461,10 +441,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif COMPILER(GCC) && CPU(ARM_THUMB2) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." -#endif - #define THUNK_RETURN_ADDRESS_OFFSET 0x1C #define PRESERVED_RETURN_ADDRESS_OFFSET 0x20 #define PRESERVED_R4_OFFSET 0x24 @@ -482,10 +458,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #elif CPU(MIPS) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST not supported on MIPS." -#endif - asm volatile( ".text" "\n" ".align 2" "\n" @@ -620,10 +592,6 @@ __asm void ctiOpThrowNotCaught() #elif COMPILER(MSVC) && CPU(X86) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." -#endif - // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline); @@ -797,8 +765,11 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" JITThunks::JITThunks(JSGlobalData* globalData) { - JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure); + if (!globalData->executableAllocator.isValid()) + return; + JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure); + ASSERT(m_executablePool); #if CPU(ARM_THUMB2) // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types), // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT @@ -915,7 +886,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) { // The tradeoff of compiling an patched inline string length access routine does not seem // to pay off, so we currently only do this for arrays. - ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline()); + ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline()); return; } @@ -985,12 +956,6 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) -#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args) -#else -#define SETUP_VA_LISTL_ARGS -#endif - #ifndef NDEBUG extern "C" { @@ -1021,13 +986,13 @@ struct StackHack { ReturnAddressPtr savedReturnAddress; }; -#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame) +#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame) #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress) #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress #else -#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS) +#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS) #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress) #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot() @@ -1858,8 +1823,11 @@ DEFINE_STUB_FUNCTION(void*, op_call_jitCompile) ASSERT(!function->isHostFunction()); FunctionExecutable* executable = function->jsExecutable(); ScopeChainNode* callDataScopeChain = function->scope().node(); - executable->jitCodeForCall(stackFrame.callFrame, callDataScopeChain); - + JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain); + if (error) { + stackFrame.callFrame->globalData().exception = error; + return 0; + } return function; } @@ -1876,8 +1844,11 @@ DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile) ASSERT(!function->isHostFunction()); FunctionExecutable* executable = function->jsExecutable(); ScopeChainNode* callDataScopeChain = function->scope().node(); - executable->jitCodeForConstruct(stackFrame.callFrame, callDataScopeChain); - + JSObject* error = executable->compileForConstruct(stackFrame.callFrame, callDataScopeChain); + if (error) { + stackFrame.callFrame->globalData().exception = error; + return 0; + } return function; } @@ -2013,12 +1984,12 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall) codePtr = executable->generatedJITCodeForCall().addressForCall(); else { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); - codeBlock = functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node()); - if (!codeBlock) { - stackFrame.callFrame->globalData().exception = createStackOverflowError(callFrame); + JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope().node()); + if (error) { + callFrame->globalData().exception = createStackOverflowError(callFrame); return 0; } - functionExecutable->jitCodeForCall(callFrame, callee->scope().node()); + codeBlock = &functionExecutable->generatedBytecodeForCall(); if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters)) codePtr = functionExecutable->generatedJITCodeForCall().addressForCall(); else @@ -2047,12 +2018,12 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct) codePtr = executable->generatedJITCodeForConstruct().addressForCall(); else { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); - codeBlock = functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node()); - if (!codeBlock) { + JSObject* error = functionExecutable->compileForConstruct(callFrame, callee->scope().node()); + if (error) { throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS); - VM_THROW_EXCEPTION(); + return 0; } - functionExecutable->jitCodeForConstruct(callFrame, callee->scope().node()); + codeBlock = &functionExecutable->generatedBytecodeForConstruct(); if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters)) codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall(); else @@ -3536,8 +3507,10 @@ PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalDat PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator) { std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0); - if (entry.second) - entry.first->second = NativeExecutable::create(generator(globalData, m_executablePool.get()), function, ctiNativeConstruct(), callHostFunctionAsConstructor); + if (entry.second) { + MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr(); + entry.first->second = NativeExecutable::create(code, function, ctiNativeConstruct(), callHostFunctionAsConstructor); + } return entry.first->second; } diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h index a5b21e5..ba9e15f 100644 --- a/JavaScriptCore/jit/JITStubs.h +++ b/JavaScriptCore/jit/JITStubs.h @@ -225,26 +225,15 @@ namespace JSC { #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*)) -#if USE(JIT_STUB_ARGUMENT_VA_LIST) - #define STUB_ARGS_DECLARATION void* args, ... - #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1) - - #if COMPILER(MSVC) - #define JIT_STUB __cdecl - #else - #define JIT_STUB - #endif +#define STUB_ARGS_DECLARATION void** args +#define STUB_ARGS (args) + +#if CPU(X86) && COMPILER(MSVC) +#define JIT_STUB __fastcall +#elif CPU(X86) && COMPILER(GCC) && !OS(WINDOWS) +#define JIT_STUB __attribute__ ((fastcall)) #else - #define STUB_ARGS_DECLARATION void** args - #define STUB_ARGS (args) - - #if CPU(X86) && COMPILER(MSVC) - #define JIT_STUB __fastcall - #elif CPU(X86) && COMPILER(GCC) - #define JIT_STUB __attribute__ ((fastcall)) - #else - #define JIT_STUB - #endif +#define JIT_STUB #endif extern "C" void ctiVMThrowTrampoline(); diff --git a/JavaScriptCore/jit/ThunkGenerators.cpp b/JavaScriptCore/jit/ThunkGenerators.cpp index 271c7c1..20857cb 100644 --- a/JavaScriptCore/jit/ThunkGenerators.cpp +++ b/JavaScriptCore/jit/ThunkGenerators.cpp @@ -68,7 +68,7 @@ MacroAssemblerCodePtr charCodeAtThunkGenerator(JSGlobalData* globalData, Executa SpecializedThunkJIT jit(1, globalData, pool); stringCharLoad(jit); jit.returnInt32(SpecializedThunkJIT::regT0); - return jit.finalize(globalData->jitStubs.ctiNativeCall()); + return jit.finalize(globalData->jitStubs->ctiNativeCall()); } MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) @@ -77,7 +77,7 @@ MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData* globalData, ExecutableP stringCharLoad(jit); charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); jit.returnJSCell(SpecializedThunkJIT::regT0); - return jit.finalize(globalData->jitStubs.ctiNativeCall()); + return jit.finalize(globalData->jitStubs->ctiNativeCall()); } MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) @@ -87,7 +87,7 @@ MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, Execu jit.loadInt32Argument(0, SpecializedThunkJIT::regT0); charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1); jit.returnJSCell(SpecializedThunkJIT::regT0); - return jit.finalize(globalData->jitStubs.ctiNativeCall()); + return jit.finalize(globalData->jitStubs->ctiNativeCall()); } MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool) @@ -95,15 +95,15 @@ MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePoo #if USE(JSVALUE64) || USE(JSVALUE32_64) SpecializedThunkJIT jit(1, globalData, pool); if (!jit.supportsFloatingPointSqrt()) - return globalData->jitStubs.ctiNativeCall(); + return globalData->jitStubs->ctiNativeCall(); jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); jit.returnDouble(SpecializedThunkJIT::fpRegT0); - return jit.finalize(globalData->jitStubs.ctiNativeCall()); + return jit.finalize(globalData->jitStubs->ctiNativeCall()); #else UNUSED_PARAM(pool); - return globalData->jitStubs.ctiNativeCall(); + return globalData->jitStubs->ctiNativeCall(); #endif } @@ -115,7 +115,7 @@ MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool #if USE(JSVALUE64) || USE(JSVALUE32_64) SpecializedThunkJIT jit(2, globalData, pool); if (!jit.supportsFloatingPoint()) - return globalData->jitStubs.ctiNativeCall(); + return globalData->jitStubs->ctiNativeCall(); jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1); jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); @@ -148,10 +148,10 @@ MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool } else jit.appendFailure(nonIntExponent); - return jit.finalize(globalData->jitStubs.ctiNativeCall()); + return jit.finalize(globalData->jitStubs->ctiNativeCall()); #else UNUSED_PARAM(pool); - return globalData->jitStubs.ctiNativeCall(); + return globalData->jitStubs->ctiNativeCall(); #endif } diff --git a/JavaScriptCore/parser/JSParser.cpp b/JavaScriptCore/parser/JSParser.cpp index 1fb1a9187..13013c7 100644 --- a/JavaScriptCore/parser/JSParser.cpp +++ b/JavaScriptCore/parser/JSParser.cpp @@ -85,12 +85,12 @@ private: }; const JSToken& token() { return m_token; } - void next() + void next(Lexer::LexType lexType = Lexer::IdentifyReservedWords) { 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_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType); m_tokenCount++; } @@ -1091,11 +1091,12 @@ template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty { bool wasIdent = false; switch (token().m_type) { + namedProperty: case IDENT: wasIdent = true; case STRING: { const Identifier* ident = token().m_data.ident; - next(); + next(Lexer::IgnoreReservedWords); if (match(COLON)) { next(); TreeExpression node = parseAssignmentExpression(context); @@ -1129,7 +1130,8 @@ template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant); } default: - fail(); + failIfFalse(token().m_type & KeywordTokenFlag); + goto namedProperty; } } @@ -1410,7 +1412,7 @@ template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(Tree } case DOT: { int expressionEnd = lastTokenEnd(); - next(); + next(Lexer::IgnoreReservedWords); matchOrFail(IDENT); base = context.createDotAccess(base, *token().m_data.ident, expressionStart, expressionEnd, tokenEnd()); next(); diff --git a/JavaScriptCore/parser/JSParser.h b/JavaScriptCore/parser/JSParser.h index 60f284c..b5a21d9 100644 --- a/JavaScriptCore/parser/JSParser.h +++ b/JavaScriptCore/parser/JSParser.h @@ -34,16 +34,17 @@ class SourceCode; enum { UnaryOpTokenFlag = 64, - BinaryOpTokenPrecedenceShift = 7, + KeywordTokenFlag = 128, + BinaryOpTokenPrecedenceShift = 8, BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4, - BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift + BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift, }; #define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))) #define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)) enum JSTokenType { - NULLTOKEN, + NULLTOKEN = KeywordTokenFlag, TRUETOKEN, FALSETOKEN, BREAK, @@ -69,7 +70,7 @@ enum JSTokenType { FINALLY, DEBUGGER, ELSE, - OPENBRACE, + OPENBRACE = 0, CLOSEBRACE, OPENPAREN, CLOSEPAREN, @@ -106,9 +107,9 @@ enum JSTokenType { TILDE = 3 | UnaryOpTokenFlag, AUTOPLUSPLUS = 4 | UnaryOpTokenFlag, AUTOMINUSMINUS = 5 | UnaryOpTokenFlag, - TYPEOF = 6 | UnaryOpTokenFlag, - VOIDTOKEN = 7 | UnaryOpTokenFlag, - DELETETOKEN = 8 | UnaryOpTokenFlag, + TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag, + VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag, + DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag, OR = 0 | BINARY_OP_PRECEDENCE(1), AND = 1 | BINARY_OP_PRECEDENCE(2), BITOR = 2 | BINARY_OP_PRECEDENCE(3), @@ -122,8 +123,8 @@ enum JSTokenType { 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), + INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7) | KeywordTokenFlag, + INTOKEN = 14 | IN_OP_PRECEDENCE(7) | KeywordTokenFlag, LSHIFT = 15 | BINARY_OP_PRECEDENCE(8), RSHIFT = 16 | BINARY_OP_PRECEDENCE(8), URSHIFT = 17 | BINARY_OP_PRECEDENCE(8), diff --git a/JavaScriptCore/parser/Lexer.cpp b/JavaScriptCore/parser/Lexer.cpp index 45fe007..d7a122e 100644 --- a/JavaScriptCore/parser/Lexer.cpp +++ b/JavaScriptCore/parser/Lexer.cpp @@ -46,14 +46,16 @@ using namespace Unicode; namespace JSC { -enum CharacterTypes { +enum CharacterType { // Types for the main switch - CharacterInvalid, - CharacterAlpha, + // The first three types are fixed, and also used for identifying + // ASCII alpha and alphanumeric characters (see isIdentStart and isIdentPart). + CharacterIdentifierStart, CharacterZero, CharacterNumber, + CharacterInvalid, CharacterLineTerminator, CharacterExclamationMark, CharacterOpenParen, @@ -87,8 +89,8 @@ enum CharacterTypes { CharacterWhiteSpace, }; -// 128 ascii codes -static unsigned short AsciiCharacters[128] = { +// 128 ASCII codes +static const unsigned short typesOfASCIICharacters[128] = { /* 0 - Null */ CharacterInvalid, /* 1 - Start of Heading */ CharacterInvalid, /* 2 - Start of Text */ CharacterInvalid, @@ -125,7 +127,7 @@ static unsigned short AsciiCharacters[128] = { /* 33 - ! */ CharacterExclamationMark, /* 34 - " */ CharacterQuote, /* 35 - # */ CharacterInvalid, -/* 36 - $ */ CharacterAlpha, +/* 36 - $ */ CharacterIdentifierStart, /* 37 - % */ CharacterModulo, /* 38 - & */ CharacterAnd, /* 39 - ' */ CharacterQuote, @@ -154,64 +156,64 @@ static unsigned short AsciiCharacters[128] = { /* 62 - > */ CharacterGreater, /* 63 - ? */ CharacterQuestion, /* 64 - @ */ CharacterInvalid, -/* 65 - A */ CharacterAlpha, -/* 66 - B */ CharacterAlpha, -/* 67 - C */ CharacterAlpha, -/* 68 - D */ CharacterAlpha, -/* 69 - E */ CharacterAlpha, -/* 70 - F */ CharacterAlpha, -/* 71 - G */ CharacterAlpha, -/* 72 - H */ CharacterAlpha, -/* 73 - I */ CharacterAlpha, -/* 74 - J */ CharacterAlpha, -/* 75 - K */ CharacterAlpha, -/* 76 - L */ CharacterAlpha, -/* 77 - M */ CharacterAlpha, -/* 78 - N */ CharacterAlpha, -/* 79 - O */ CharacterAlpha, -/* 80 - P */ CharacterAlpha, -/* 81 - Q */ CharacterAlpha, -/* 82 - R */ CharacterAlpha, -/* 83 - S */ CharacterAlpha, -/* 84 - T */ CharacterAlpha, -/* 85 - U */ CharacterAlpha, -/* 86 - V */ CharacterAlpha, -/* 87 - W */ CharacterAlpha, -/* 88 - X */ CharacterAlpha, -/* 89 - Y */ CharacterAlpha, -/* 90 - Z */ CharacterAlpha, +/* 65 - A */ CharacterIdentifierStart, +/* 66 - B */ CharacterIdentifierStart, +/* 67 - C */ CharacterIdentifierStart, +/* 68 - D */ CharacterIdentifierStart, +/* 69 - E */ CharacterIdentifierStart, +/* 70 - F */ CharacterIdentifierStart, +/* 71 - G */ CharacterIdentifierStart, +/* 72 - H */ CharacterIdentifierStart, +/* 73 - I */ CharacterIdentifierStart, +/* 74 - J */ CharacterIdentifierStart, +/* 75 - K */ CharacterIdentifierStart, +/* 76 - L */ CharacterIdentifierStart, +/* 77 - M */ CharacterIdentifierStart, +/* 78 - N */ CharacterIdentifierStart, +/* 79 - O */ CharacterIdentifierStart, +/* 80 - P */ CharacterIdentifierStart, +/* 81 - Q */ CharacterIdentifierStart, +/* 82 - R */ CharacterIdentifierStart, +/* 83 - S */ CharacterIdentifierStart, +/* 84 - T */ CharacterIdentifierStart, +/* 85 - U */ CharacterIdentifierStart, +/* 86 - V */ CharacterIdentifierStart, +/* 87 - W */ CharacterIdentifierStart, +/* 88 - X */ CharacterIdentifierStart, +/* 89 - Y */ CharacterIdentifierStart, +/* 90 - Z */ CharacterIdentifierStart, /* 91 - [ */ CharacterOpenBracket, /* 92 - \ */ CharacterBackSlash, /* 93 - ] */ CharacterCloseBracket, /* 94 - ^ */ CharacterXor, -/* 95 - _ */ CharacterAlpha, +/* 95 - _ */ CharacterIdentifierStart, /* 96 - ` */ CharacterInvalid, -/* 97 - a */ CharacterAlpha, -/* 98 - b */ CharacterAlpha, -/* 99 - c */ CharacterAlpha, -/* 100 - d */ CharacterAlpha, -/* 101 - e */ CharacterAlpha, -/* 102 - f */ CharacterAlpha, -/* 103 - g */ CharacterAlpha, -/* 104 - h */ CharacterAlpha, -/* 105 - i */ CharacterAlpha, -/* 106 - j */ CharacterAlpha, -/* 107 - k */ CharacterAlpha, -/* 108 - l */ CharacterAlpha, -/* 109 - m */ CharacterAlpha, -/* 110 - n */ CharacterAlpha, -/* 111 - o */ CharacterAlpha, -/* 112 - p */ CharacterAlpha, -/* 113 - q */ CharacterAlpha, -/* 114 - r */ CharacterAlpha, -/* 115 - s */ CharacterAlpha, -/* 116 - t */ CharacterAlpha, -/* 117 - u */ CharacterAlpha, -/* 118 - v */ CharacterAlpha, -/* 119 - w */ CharacterAlpha, -/* 120 - x */ CharacterAlpha, -/* 121 - y */ CharacterAlpha, -/* 122 - z */ CharacterAlpha, +/* 97 - a */ CharacterIdentifierStart, +/* 98 - b */ CharacterIdentifierStart, +/* 99 - c */ CharacterIdentifierStart, +/* 100 - d */ CharacterIdentifierStart, +/* 101 - e */ CharacterIdentifierStart, +/* 102 - f */ CharacterIdentifierStart, +/* 103 - g */ CharacterIdentifierStart, +/* 104 - h */ CharacterIdentifierStart, +/* 105 - i */ CharacterIdentifierStart, +/* 106 - j */ CharacterIdentifierStart, +/* 107 - k */ CharacterIdentifierStart, +/* 108 - l */ CharacterIdentifierStart, +/* 109 - m */ CharacterIdentifierStart, +/* 110 - n */ CharacterIdentifierStart, +/* 111 - o */ CharacterIdentifierStart, +/* 112 - p */ CharacterIdentifierStart, +/* 113 - q */ CharacterIdentifierStart, +/* 114 - r */ CharacterIdentifierStart, +/* 115 - s */ CharacterIdentifierStart, +/* 116 - t */ CharacterIdentifierStart, +/* 117 - u */ CharacterIdentifierStart, +/* 118 - v */ CharacterIdentifierStart, +/* 119 - w */ CharacterIdentifierStart, +/* 120 - x */ CharacterIdentifierStart, +/* 121 - y */ CharacterIdentifierStart, +/* 122 - z */ CharacterIdentifierStart, /* 123 - { */ CharacterOpenBrace, /* 124 - | */ CharacterOr, /* 125 - } */ CharacterCloseBrace, @@ -335,7 +337,7 @@ static NEVER_INLINE bool isNonASCIIIdentStart(int c) static inline bool isIdentStart(int c) { - return isASCII(c) ? isASCIIAlpha(c) || c == '$' || c == '_' : isNonASCIIIdentStart(c); + return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c); } static NEVER_INLINE bool isNonASCIIIdentPart(int c) @@ -346,32 +348,35 @@ static NEVER_INLINE bool isNonASCIIIdentPart(int c) static inline bool isIdentPart(int c) { - return isASCII(c) ? isASCIIAlphanumeric(c) || c == '$' || c == '_' : isNonASCIIIdentPart(c); + // Character types are divided into two groups depending on whether they can be part of an + // identifier or not. Those whose type value is less or equal than CharacterNumber can be + // part of an identifier. (See the CharacterType definition for more details.) + return isASCII(c) ? typesOfASCIICharacters[c] <= CharacterNumber : isNonASCIIIdentPart(c); } static inline int singleEscape(int c) { switch (c) { - case 'b': - return 0x08; - case 't': - return 0x09; - case 'n': - return 0x0A; - case 'v': - return 0x0B; - case 'f': - return 0x0C; - case 'r': - return 0x0D; - case '\\': - return '\\'; - case '\'': - return '\''; - case '"': - return '"'; - default: - return 0; + case 'b': + return 0x08; + case 't': + return 0x09; + case 'n': + return 0x0A; + case 'v': + return 0x0B; + case 'f': + return 0x0C; + case 'r': + return 0x0D; + case '\\': + return '\\'; + case '\'': + return '\''; + case '"': + return '"'; + default: + return 0; } } @@ -456,7 +461,11 @@ ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp) stringStart = currentCharacter(); continue; - } else if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) { + } + // 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(((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; @@ -472,7 +481,7 @@ ALWAYS_INLINE bool Lexer::parseString(JSTokenData* lvalp) return true; } -JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp) +JSTokenType Lexer::lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType lexType) { ASSERT(!m_error); ASSERT(m_buffer8.isEmpty()); @@ -493,295 +502,287 @@ start: m_delimited = false; - if (isASCII(m_current)) { - ASSERT(m_current >= 0 && m_current < 128); + CharacterType type; + if (LIKELY(isASCII(m_current))) + type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]); + else if (isNonASCIIIdentStart(m_current)) + type = CharacterIdentifierStart; + else if (isLineTerminator(m_current)) + type = CharacterLineTerminator; + else + type = CharacterInvalid; - switch (AsciiCharacters[m_current]) { - case CharacterGreater: + switch (type) { + case CharacterGreater: + shift(); + if (m_current == '>') { shift(); if (m_current == '>') { shift(); - if (m_current == '>') { - shift(); - if (m_current == '=') { - shift(); - token = URSHIFTEQUAL; - break; - } - token = URSHIFT; - break; - } if (m_current == '=') { shift(); - token = RSHIFTEQUAL; + token = URSHIFTEQUAL; break; } - token = RSHIFT; - break; - } - if (m_current == '=') { - shift(); - token = GE; - break; - } - token = GT; - break; - case CharacterEqual: - shift(); - if (m_current == '=') { - shift(); - if (m_current == '=') { - shift(); - token = STREQ; - break; - } - token = EQEQ; - break; - } - token = EQUAL; - break; - case CharacterLess: - shift(); - if (m_current == '!' && peek(1) == '-' && peek(2) == '-') { - // <!-- marks the beginning of a line comment (for www usage) - goto inSingleLineComment; - } - if (m_current == '<') { - shift(); - if (m_current == '=') { - shift(); - token = LSHIFTEQUAL; - break; - } - token = LSHIFT; - break; - } - if (m_current == '=') { - shift(); - token = LE; + token = URSHIFT; break; } - token = LT; - break; - case CharacterExclamationMark: - shift(); if (m_current == '=') { shift(); - if (m_current == '=') { - shift(); - token = STRNEQ; - break; - } - token = NE; + token = RSHIFTEQUAL; break; } - token = EXCLAMATION; + token = RSHIFT; break; - case CharacterAdd: + } + if (m_current == '=') { shift(); - if (m_current == '+') { - shift(); - token = (!m_terminator) ? PLUSPLUS : AUTOPLUSPLUS; - break; - } - if (m_current == '=') { - shift(); - token = PLUSEQUAL; - break; - } - token = PLUS; + token = GE; break; - case CharacterSub: + } + token = GT; + break; + case CharacterEqual: + shift(); + if (m_current == '=') { shift(); - if (m_current == '-') { - shift(); - if (m_atLineStart && m_current == '>') { - shift(); - goto inSingleLineComment; - } - token = (!m_terminator) ? MINUSMINUS : AUTOMINUSMINUS; - break; - } if (m_current == '=') { shift(); - token = MINUSEQUAL; + token = STREQ; break; } - token = MINUS; + token = EQEQ; break; - case CharacterMultiply: + } + token = EQUAL; + break; + case CharacterLess: + shift(); + if (m_current == '!' && peek(1) == '-' && peek(2) == '-') { + // <!-- marks the beginning of a line comment (for www usage) + goto inSingleLineComment; + } + if (m_current == '<') { shift(); if (m_current == '=') { shift(); - token = MULTEQUAL; + token = LSHIFTEQUAL; break; } - token = TIMES; + token = LSHIFT; break; - case CharacterSlash: + } + if (m_current == '=') { shift(); - if (m_current == '/') { - shift(); - goto inSingleLineComment; - } - if (m_current == '*') { - shift(); - goto inMultiLineComment; - } - if (m_current == '=') { - shift(); - token = DIVEQUAL; - break; - } - token = DIVIDE; + token = LE; break; - case CharacterAnd: + } + token = LT; + break; + case CharacterExclamationMark: + shift(); + if (m_current == '=') { shift(); - if (m_current == '&') { - shift(); - token = AND; - break; - } if (m_current == '=') { shift(); - token = ANDEQUAL; + token = STRNEQ; break; } - token = BITAND; + token = NE; break; - case CharacterXor: + } + token = EXCLAMATION; + break; + case CharacterAdd: + shift(); + if (m_current == '+') { shift(); - if (m_current == '=') { - shift(); - token = XOREQUAL; - break; - } - token = BITXOR; + token = (!m_terminator) ? PLUSPLUS : AUTOPLUSPLUS; break; - case CharacterModulo: + } + if (m_current == '=') { shift(); - if (m_current == '=') { - shift(); - token = MODEQUAL; - break; - } - token = MOD; + token = PLUSEQUAL; break; - case CharacterOr: + } + token = PLUS; + break; + case CharacterSub: + shift(); + if (m_current == '-') { shift(); - if (m_current == '=') { + if (m_atLineStart && m_current == '>') { shift(); - token = OREQUAL; - break; - } - if (m_current == '|') { - shift(); - token = OR; - break; - } - token = BITOR; - break; - case CharacterDot: - shift(); - if (isASCIIDigit(m_current)) { - record8('.'); - goto inNumberAfterDecimalPoint; + goto inSingleLineComment; } - token = DOT; - break; - case CharacterOpenParen: - token = OPENPAREN; - shift(); + token = (!m_terminator) ? MINUSMINUS : AUTOMINUSMINUS; break; - case CharacterCloseParen: - token = CLOSEPAREN; + } + if (m_current == '=') { shift(); + token = MINUSEQUAL; break; - case CharacterOpenBracket: - token = OPENBRACKET; + } + token = MINUS; + break; + case CharacterMultiply: + shift(); + if (m_current == '=') { shift(); + token = MULTEQUAL; break; - case CharacterCloseBracket: - token = CLOSEBRACKET; + } + token = TIMES; + break; + case CharacterSlash: + shift(); + if (m_current == '/') { shift(); - break; - case CharacterComma: - token = COMMA; + goto inSingleLineComment; + } + if (m_current == '*') { shift(); - break; - case CharacterColon: - token = COLON; + goto inMultiLineComment; + } + if (m_current == '=') { shift(); + token = DIVEQUAL; break; - case CharacterQuestion: - token = QUESTION; + } + token = DIVIDE; + break; + case CharacterAnd: + shift(); + if (m_current == '&') { shift(); + token = AND; break; - case CharacterTilde: - token = TILDE; + } + if (m_current == '=') { shift(); + token = ANDEQUAL; break; - case CharacterSemicolon: - m_delimited = true; + } + token = BITAND; + break; + case CharacterXor: + shift(); + if (m_current == '=') { shift(); - token = SEMICOLON; + token = XOREQUAL; break; - case CharacterOpenBrace: - lvalp->intValue = currentOffset(); + } + token = BITXOR; + break; + case CharacterModulo: + shift(); + if (m_current == '=') { shift(); - token = OPENBRACE; + token = MODEQUAL; break; - case CharacterCloseBrace: - lvalp->intValue = currentOffset(); - m_delimited = true; + } + token = MOD; + break; + case CharacterOr: + shift(); + if (m_current == '=') { shift(); - token = CLOSEBRACE; + token = OREQUAL; break; - case CharacterBackSlash: - goto startIdentifierWithBackslash; - case CharacterZero: - goto startNumberWithZeroDigit; - case CharacterNumber: - goto startNumber; - case CharacterQuote: - if (UNLIKELY(!parseString(lvalp))) - goto returnError; + } + if (m_current == '|') { shift(); - m_delimited = false; - token = STRING; + token = OR; break; - case CharacterAlpha: - ASSERT(isIdentStart(m_current)); - goto startIdentifierOrKeyword; - case CharacterLineTerminator: - ASSERT(isLineTerminator(m_current)); - shiftLineTerminator(); - m_atLineStart = true; - m_terminator = true; - if (lastTokenWasRestrKeyword()) { - token = SEMICOLON; - goto doneSemicolon; - } - goto start; - case CharacterInvalid: - goto returnError; - default: - ASSERT_NOT_REACHED(); - goto returnError; } - } else { - // Rare characters - - if (isNonASCIIIdentStart(m_current)) - goto startIdentifierOrKeyword; - if (isLineTerminator(m_current)) { - shiftLineTerminator(); - m_atLineStart = true; - m_terminator = true; - if (lastTokenWasRestrKeyword()) - goto doneSemicolon; - goto start; + token = BITOR; + break; + case CharacterDot: + shift(); + if (isASCIIDigit(m_current)) { + record8('.'); + goto inNumberAfterDecimalPoint; } + token = DOT; + break; + case CharacterOpenParen: + token = OPENPAREN; + shift(); + break; + case CharacterCloseParen: + token = CLOSEPAREN; + shift(); + break; + case CharacterOpenBracket: + token = OPENBRACKET; + shift(); + break; + 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 = SEMICOLON; + break; + case CharacterOpenBrace: + lvalp->intValue = currentOffset(); + shift(); + token = OPENBRACE; + break; + case CharacterCloseBrace: + lvalp->intValue = currentOffset(); + m_delimited = true; + shift(); + token = CLOSEBRACE; + break; + case CharacterBackSlash: + goto startIdentifierWithBackslash; + case CharacterZero: + goto startNumberWithZeroDigit; + case CharacterNumber: + goto startNumber; + case CharacterQuote: + if (UNLIKELY(!parseString(lvalp))) + goto returnError; + shift(); + m_delimited = false; + token = STRING; + break; + case CharacterIdentifierStart: + ASSERT(isIdentStart(m_current)); + goto startIdentifierOrKeyword; + case CharacterLineTerminator: + ASSERT(isLineTerminator(m_current)); + shiftLineTerminator(); + m_atLineStart = true; + m_terminator = true; + if (lastTokenWasRestrKeyword()) { + token = SEMICOLON; + goto doneSemicolon; + } + goto start; + case CharacterInvalid: + goto returnError; + default: + ASSERT_NOT_REACHED(); goto returnError; } @@ -1021,9 +1022,11 @@ doneIdentifierOrKeyword: { m_atLineStart = false; m_delimited = false; m_buffer16.resize(0); - const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident); - token = entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT; - + if (lexType == IdentifyReservedWords) { + const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident); + token = entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT; + } else + token = IDENT; // Fall through into returnToken. } @@ -1157,6 +1160,8 @@ void Lexer::clear() SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine) { + ASSERT(m_source->provider()->data()[openBrace] == '{'); + ASSERT(m_source->provider()->data()[closeBrace] == '}'); return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine); } diff --git a/JavaScriptCore/parser/Lexer.h b/JavaScriptCore/parser/Lexer.h index 5ab7ad7..4f7af44 100644 --- a/JavaScriptCore/parser/Lexer.h +++ b/JavaScriptCore/parser/Lexer.h @@ -50,7 +50,8 @@ namespace JSC { void setIsReparsing() { m_isReparsing = true; } // Functions for the parser itself. - JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp); + enum LexType { IdentifyReservedWords, IgnoreReservedWords }; + JSTokenType lex(JSTokenData* lvalp, JSTokenInfo* llocp, LexType); int lineNumber() const { return m_lineNumber; } void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; } int lastLineNumber() const { return m_lastLineNumber; } @@ -126,7 +127,7 @@ namespace JSC { inline bool Lexer::isWhiteSpace(int ch) { - return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : WTF::Unicode::isSeparatorSpace(ch); + return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF); } inline bool Lexer::isLineTerminator(int ch) diff --git a/JavaScriptCore/parser/Nodes.cpp b/JavaScriptCore/parser/Nodes.cpp index ffea524..c41d735 100644 --- a/JavaScriptCore/parser/Nodes.cpp +++ b/JavaScriptCore/parser/Nodes.cpp @@ -67,7 +67,7 @@ void SourceElements::append(StatementNode* statement) m_statements.append(statement); } -inline StatementNode* SourceElements::singleStatement() const +StatementNode* SourceElements::singleStatement() const { size_t size = m_statements.size(); return size == 1 ? m_statements[0] : 0; diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index 6206384..d25079b 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -152,6 +152,7 @@ namespace JSC { virtual bool isCommaNode() const { return false; } virtual bool isSimpleArray() const { return false; } virtual bool isAdd() const { return false; } + virtual bool isSubtract() const { return false; } virtual bool hasConditionContextCodegen() const { return false; } virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } @@ -806,6 +807,9 @@ namespace JSC { RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + ExpressionNode* lhs() { return m_expr1; }; + ExpressionNode* rhs() { return m_expr2; }; + private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -854,6 +858,8 @@ namespace JSC { class SubNode : public BinaryOpNode { public: SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isSubtract() const { return true; } }; class LeftShiftNode : public BinaryOpNode { @@ -1143,6 +1149,7 @@ namespace JSC { public: BlockNode(JSGlobalData*, SourceElements* = 0); + StatementNode* singleStatement() const; StatementNode* lastStatement() const; private: @@ -1294,6 +1301,8 @@ namespace JSC { public: ReturnNode(JSGlobalData*, ExpressionNode* value); + ExpressionNode* value() { return m_value; } + private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); diff --git a/JavaScriptCore/parser/Parser.h b/JavaScriptCore/parser/Parser.h index 894f709..c167980 100644 --- a/JavaScriptCore/parser/Parser.h +++ b/JavaScriptCore/parser/Parser.h @@ -24,6 +24,7 @@ #define Parser_h #include "Debugger.h" +#include "ExceptionHelpers.h" #include "Executable.h" #include "JSGlobalObject.h" #include "Lexer.h" @@ -38,6 +39,7 @@ namespace JSC { class FunctionBodyNode; + class ProgramNode; class UString; @@ -46,7 +48,7 @@ namespace JSC { class Parser : public Noncopyable { public: template <class ParsedNode> - PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, Debugger*, ExecState*, const SourceCode& source, int* errLine = 0, UString* errMsg = 0); + PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, JSObject** exception); void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants); @@ -56,6 +58,10 @@ namespace JSC { private: void parse(JSGlobalData*, int* errLine, UString* errMsg); + // Used to determine type of error to report. + bool isFunctionBodyNode(ScopeNode*) { return false; } + bool isFunctionBodyNode(FunctionBodyNode*) { return true; } + ParserArena m_arena; const SourceCode* m_source; SourceElements* m_sourceElements; @@ -67,12 +73,16 @@ namespace JSC { }; template <class ParsedNode> - PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, int* errLine, UString* errMsg) + PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, JSObject** exception) { + ASSERT(exception && !*exception); + int errLine; + UString errMsg; + m_source = &source; if (ParsedNode::scopeIsFunction) globalData->lexer->setIsReparsing(); - parse(globalData, errLine, errMsg); + parse(globalData, &errLine, &errMsg); RefPtr<ParsedNode> result; if (m_sourceElements) { @@ -84,6 +94,17 @@ namespace JSC { m_features, m_numConstants); result->setLoc(m_source->firstLine(), m_lastLine); + } else if (lexicalGlobalObject) { + // We can never see a syntax error when reparsing a function, since we should have + // reported the error when parsing the containing program or eval code. So if we're + // parsing a function body node, we assume that what actually happened here is that + // we ran out of stack while parsing. If we see an error while parsing eval or program + // code we assume that it was a syntax error since running out of stack is much less + // likely, and we are currently unable to distinguish between the two cases. + if (isFunctionBodyNode(static_cast<ParsedNode*>(0))) + *exception = createStackOverflowError(lexicalGlobalObject); + else + *exception = addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, source); } m_arena.reset(); @@ -94,7 +115,7 @@ namespace JSC { m_funcDeclarations = 0; if (debugger && !ParsedNode::scopeIsFunction) - debugger->sourceParsed(debuggerExecState, source, *errLine, *errMsg); + debugger->sourceParsed(debuggerExecState, source, errLine, errMsg); return result.release(); } diff --git a/JavaScriptCore/parser/SourceProvider.h b/JavaScriptCore/parser/SourceProvider.h index 6b9c028..5a57542 100644 --- a/JavaScriptCore/parser/SourceProvider.h +++ b/JavaScriptCore/parser/SourceProvider.h @@ -60,9 +60,9 @@ namespace JSC { class UStringSourceProvider : public SourceProvider { public: - static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url, bool hasBOMs = true) + static PassRefPtr<UStringSourceProvider> create(const UString& source, const UString& url) { - return adoptRef(new UStringSourceProvider(source, url, hasBOMs)); + return adoptRef(new UStringSourceProvider(source, url)); } UString getRange(int start, int end) const @@ -73,14 +73,10 @@ namespace JSC { int length() const { return m_source.size(); } private: - UStringSourceProvider(const UString& source, const UString& url, bool hasBOMs) + UStringSourceProvider(const UString& source, const UString& url) : SourceProvider(url) , m_source(source) { - if (hasBOMs && m_source.size()) { - bool scratch = false; - m_source = UString(m_source.rep()->copyStringWithoutBOMs(false, scratch)); - } } UString m_source; diff --git a/JavaScriptCore/qt/ChangeLog b/JavaScriptCore/qt/ChangeLog index 71b4a21..448a59e 100644 --- a/JavaScriptCore/qt/ChangeLog +++ b/JavaScriptCore/qt/ChangeLog @@ -1,3 +1,115 @@ +2010-07-14 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Introduce QScriptOriginalGlobalObject. + + QtScript exposes more functionality than JSC C API. Sometimes it is + necessary to take a shortcut in implementation. Really often we have + to use a standard JS function. These function could be changed or + even deleted by a script, so a backup of a reference to an object is needed. + + In them same time this is rather a workaround then real fix, so the code + should be separated and changed easily in future. It is why we need + the new internal class. + + The patch fixes a few crashes. + + [Qt] QScriptEngine should work correctly even after global object changes + https://bugs.webkit.org/show_bug.cgi?id=41839 + + * api/QtScript.pro: + * api/qscriptengine_p.cpp: + (QScriptEnginePrivate::QScriptEnginePrivate): + (QScriptEnginePrivate::~QScriptEnginePrivate): + * api/qscriptengine_p.h: + (QScriptEnginePrivate::isArray): + (QScriptEnginePrivate::isError): + (QScriptEnginePrivate::objectHasOwnProperty): + (QScriptEnginePrivate::objectGetOwnPropertyNames): + * api/qscriptoriginalglobalobject_p.h: Added. + (QScriptOriginalGlobalObject::QScriptOriginalGlobalObject): + (QScriptOriginalGlobalObject::initializeMember): + (QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject): + (QScriptOriginalGlobalObject::objectHasOwnProperty): + (QScriptOriginalGlobalObject::objectGetOwnPropertyNames): + (QScriptOriginalGlobalObject::isArray): + (QScriptOriginalGlobalObject::isError): + (QScriptOriginalGlobalObject::isType): + * api/qscriptvalue_p.h: + (QScriptValuePrivate::isError): + (QScriptValuePrivate::hasOwnProperty): + * api/qscriptvalueiterator_p.h: + (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate): + * tests/qscriptvalue/tst_qscriptvalue.cpp: + (tst_QScriptValue::globalObjectChanges): + * tests/qscriptvalue/tst_qscriptvalue.h: + +2010-07-13 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Introduce QScriptValueIterator. + + The QScriptValueIterator class permits to iterate over a QScriptValue's properties. + + [Qt] QtScript should provide an API for enumerating a JS object's properties + https://bugs.webkit.org/show_bug.cgi?id=41680 + + * api/QtScript.pro: + * api/qscriptvalueiterator.cpp: Added. + (QScriptValueIterator::QScriptValueIterator): + (QScriptValueIterator::~QScriptValueIterator): + (QScriptValueIterator::hasNext): + (QScriptValueIterator::next): + (QScriptValueIterator::hasPrevious): + (QScriptValueIterator::previous): + (QScriptValueIterator::toFront): + (QScriptValueIterator::toBack): + (QScriptValueIterator::name): + (QScriptValueIterator::scriptName): + (QScriptValueIterator::value): + (QScriptValueIterator::setValue): + (QScriptValueIterator::remove): + (QScriptValueIterator::flags): + (QScriptValueIterator::operator=): + * api/qscriptvalueiterator.h: Added. + * api/qscriptvalueiterator_p.h: Added. + (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate): + (QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate): + (QScriptValueIteratorPrivate::hasNext): + (QScriptValueIteratorPrivate::next): + (QScriptValueIteratorPrivate::hasPrevious): + (QScriptValueIteratorPrivate::previous): + (QScriptValueIteratorPrivate::name): + (QScriptValueIteratorPrivate::scriptName): + (QScriptValueIteratorPrivate::value): + (QScriptValueIteratorPrivate::setValue): + (QScriptValueIteratorPrivate::remove): + (QScriptValueIteratorPrivate::toFront): + (QScriptValueIteratorPrivate::toBack): + (QScriptValueIteratorPrivate::flags): + (QScriptValueIteratorPrivate::isValid): + (QScriptValueIteratorPrivate::engine): + * tests/qscriptvalueiterator/qscriptvalueiterator.pro: Added. + * tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp: Added. + (tst_QScriptValueIterator::tst_QScriptValueIterator): + (tst_QScriptValueIterator::~tst_QScriptValueIterator): + (tst_QScriptValueIterator::iterateForward_data): + (tst_QScriptValueIterator::iterateForward): + (tst_QScriptValueIterator::iterateBackward_data): + (tst_QScriptValueIterator::iterateBackward): + (tst_QScriptValueIterator::iterateArray_data): + (tst_QScriptValueIterator::iterateArray): + (tst_QScriptValueIterator::iterateBackAndForth): + (tst_QScriptValueIterator::setValue): + (tst_QScriptValueIterator::remove): + (tst_QScriptValueIterator::removeMixed): + (tst_QScriptValueIterator::removeUndeletable): + (tst_QScriptValueIterator::iterateString): + (tst_QScriptValueIterator::assignObjectToIterator): + * tests/tests.pro: + 2010-07-09 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> Reviewed by Simon Hausmann. diff --git a/JavaScriptCore/qt/api/QtScript.pro b/JavaScriptCore/qt/api/QtScript.pro index 3c2691e..c2c6f83 100644 --- a/JavaScriptCore/qt/api/QtScript.pro +++ b/JavaScriptCore/qt/api/QtScript.pro @@ -24,6 +24,7 @@ INCLUDEPATH += $$PWD/../../API SOURCES += $$PWD/qscriptengine.cpp \ $$PWD/qscriptengine_p.cpp \ $$PWD/qscriptvalue.cpp \ + $$PWD/qscriptvalueiterator.cpp \ $$PWD/qscriptstring.cpp \ $$PWD/qscriptprogram.cpp \ $$PWD/qscriptsyntaxcheckresult.cpp \ @@ -33,12 +34,15 @@ HEADERS += $$PWD/qtscriptglobal.h \ $$PWD/qscriptengine_p.h \ $$PWD/qscriptvalue.h \ $$PWD/qscriptvalue_p.h \ + $$PWD/qscriptvalueiterator.h \ + $$PWD/qscriptvalueiterator_p.h \ $$PWD/qscriptconverter_p.h \ $$PWD/qscriptstring.h \ $$PWD/qscriptstring_p.h \ $$PWD/qscriptprogram.h \ $$PWD/qscriptprogram_p.h \ $$PWD/qscriptsyntaxcheckresult.h \ + $$PWD/qscriptoriginalglobalobject_p.h \ !static: DEFINES += QT_MAKEDLL diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp index 360de29..e3311ed 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.cpp +++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp @@ -32,32 +32,12 @@ QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine) : q_ptr(const_cast<QScriptEngine*>(engine)) , m_context(JSGlobalContextCreate(0)) , m_exception(0) - , m_arrayConstructor(0) - , m_arrayPrototype(0) + , m_originalGlobalObject(m_context) { - 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 401c051..d54cdcc 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.h +++ b/JavaScriptCore/qt/api/qscriptengine_p.h @@ -22,6 +22,7 @@ #include "qscriptconverter_p.h" #include "qscriptengine.h" +#include "qscriptoriginalglobalobject_p.h" #include "qscriptstring_p.h" #include "qscriptsyntaxcheckresult_p.h" #include "qscriptvalue.h" @@ -79,13 +80,15 @@ public: inline operator JSGlobalContextRef() const; inline bool isArray(JSValueRef value) const; + inline bool isError(JSValueRef value) const; + inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const; + inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const; private: QScriptEngine* q_ptr; JSGlobalContextRef m_context; JSValueRef m_exception; - JSObjectRef m_arrayConstructor; - JSValueRef m_arrayPrototype; + QScriptOriginalGlobalObject m_originalGlobalObject; }; @@ -218,9 +221,24 @@ QScriptEnginePrivate::operator JSGlobalContextRef() const 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); + return m_originalGlobalObject.isArray(value); +} + +bool QScriptEnginePrivate::isError(JSValueRef value) const +{ + return m_originalGlobalObject.isError(value); +} + +inline bool QScriptEnginePrivate::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const +{ + // FIXME We need a JSC C API function for this. + return m_originalGlobalObject.objectHasOwnProperty(object, property); +} + +inline QVector<JSStringRef> QScriptEnginePrivate::objectGetOwnPropertyNames(JSObjectRef object) const +{ + // FIXME We can't use C API function JSObjectGetPropertyNames as it returns only enumerable properties. + return m_originalGlobalObject.objectGetOwnPropertyNames(object); } #endif diff --git a/JavaScriptCore/qt/api/qscriptoriginalglobalobject_p.h b/JavaScriptCore/qt/api/qscriptoriginalglobalobject_p.h new file mode 100644 index 0000000..8d080fb --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptoriginalglobalobject_p.h @@ -0,0 +1,186 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptoriginalglobalobject_p_h +#define qscriptoriginalglobalobject_p_h + +#include <JavaScriptCore/JavaScript.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <QtCore/qvector.h> + +/*! + \internal + This class is a workaround for missing JSC C API functionality. This class keeps all important + properties of an original (default) global object, so we can use it even if the global object was + changed. + + FIXME this class is a container for workarounds :-) it should be replaced by proper JSC C API calls. + + The class have to be created on the QScriptEnginePrivate creation time (before any change got applied to + global object). +*/ +class QScriptOriginalGlobalObject { +public: + inline QScriptOriginalGlobalObject(JSGlobalContextRef context); + inline ~QScriptOriginalGlobalObject(); + + inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const; + inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const; + + inline bool isArray(JSValueRef value) const; + inline bool isError(JSValueRef value) const; +private: + inline bool isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const; + inline void initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype); + + // Copy of the global context reference (the same as in QScriptEnginePrivate). + JSGlobalContextRef m_context; + + // Copy of constructors and prototypes used in isType functions. + JSObjectRef m_arrayConstructor; + JSValueRef m_arrayPrototype; + JSObjectRef m_errorConstructor; + JSValueRef m_errorPrototype; + + // Reference to standard JS functions that are not exposed by JSC C API. + JSObjectRef m_hasOwnPropertyFunction; + JSObjectRef m_getOwnPropertyNamesFunction; +}; + +QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(JSGlobalContextRef context) + : m_context(JSGlobalContextRetain(context)) +{ + JSObjectRef globalObject = JSContextGetGlobalObject(m_context); + JSValueRef exception = 0; + JSRetainPtr<JSStringRef> propertyName; + + propertyName.adopt(JSStringCreateWithUTF8CString("prototype")); + initializeMember(globalObject, propertyName.get(), "Array", m_arrayConstructor, m_arrayPrototype); + initializeMember(globalObject, propertyName.get(), "Error", m_errorConstructor, m_errorPrototype); + + propertyName.adopt(JSStringCreateWithUTF8CString("hasOwnProperty")); + m_hasOwnPropertyFunction = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception)); + JSValueProtect(m_context, m_hasOwnPropertyFunction); + Q_ASSERT(JSValueIsObject(m_context, m_hasOwnPropertyFunction)); + Q_ASSERT(JSObjectIsFunction(m_context, m_hasOwnPropertyFunction)); + Q_ASSERT(!exception); + + propertyName.adopt(JSStringCreateWithUTF8CString("Object")); + JSObjectRef objectConstructor + = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception)); + propertyName.adopt(JSStringCreateWithUTF8CString("getOwnPropertyNames")); + m_getOwnPropertyNamesFunction + = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, objectConstructor, propertyName.get(), &exception)); + JSValueProtect(m_context, m_getOwnPropertyNamesFunction); + Q_ASSERT(JSValueIsObject(m_context, m_getOwnPropertyNamesFunction)); + Q_ASSERT(JSObjectIsFunction(m_context, m_getOwnPropertyNamesFunction)); + Q_ASSERT(!exception); +} + +inline void QScriptOriginalGlobalObject::initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype) +{ + JSRetainPtr<JSStringRef> typeName(Adopt, JSStringCreateWithUTF8CString(type)); + JSValueRef exception = 0; + + // Save references to the Type constructor and prototype. + JSValueRef typeConstructor = JSObjectGetProperty(m_context, globalObject, typeName.get(), &exception); + Q_ASSERT(JSValueIsObject(m_context, typeConstructor)); + constructor = JSValueToObject(m_context, typeConstructor, &exception); + JSValueProtect(m_context, constructor); + + // Note that this is not the [[Prototype]] internal property (which we could + // get via JSObjectGetPrototype), but the Type.prototype, that will be set + // as [[Prototype]] of Type instances. + prototype = JSObjectGetProperty(m_context, constructor, prototypeName, &exception); + Q_ASSERT(JSValueIsObject(m_context, prototype)); + JSValueProtect(m_context, prototype); + Q_ASSERT(!exception); +} + +QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject() +{ + JSValueUnprotect(m_context, m_arrayConstructor); + JSValueUnprotect(m_context, m_arrayPrototype); + JSValueUnprotect(m_context, m_errorConstructor); + JSValueUnprotect(m_context, m_errorPrototype); + JSValueUnprotect(m_context, m_hasOwnPropertyFunction); + JSValueUnprotect(m_context, m_getOwnPropertyNamesFunction); + JSGlobalContextRelease(m_context); +} + +inline bool QScriptOriginalGlobalObject::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const +{ + // FIXME This function should be replaced by JSC C API. + JSValueRef exception = 0; + JSValueRef propertyName[] = { JSValueMakeString(m_context, property) }; + JSValueRef result = JSObjectCallAsFunction(m_context, m_hasOwnPropertyFunction, object, 1, propertyName, &exception); + return exception ? false : JSValueToBoolean(m_context, result); +} + +/*! + \internal + This method gives ownership of all JSStringRefs. +*/ +inline QVector<JSStringRef> QScriptOriginalGlobalObject::objectGetOwnPropertyNames(JSObjectRef object) const +{ + JSValueRef exception = 0; + JSObjectRef propertyNames + = const_cast<JSObjectRef>(JSObjectCallAsFunction(m_context, + m_getOwnPropertyNamesFunction, + /* thisObject */ 0, + /* argumentCount */ 1, + &object, + &exception)); + Q_ASSERT(JSValueIsObject(m_context, propertyNames)); + Q_ASSERT(!exception); + JSStringRef lengthName = QScriptConverter::toString("length"); + int count = JSValueToNumber(m_context, JSObjectGetProperty(m_context, propertyNames, lengthName, &exception), &exception); + + Q_ASSERT(!exception); + QVector<JSStringRef> names; + names.reserve(count); + for (int i = 0; i < count; ++i) { + JSValueRef tmp = JSObjectGetPropertyAtIndex(m_context, propertyNames, i, &exception); + names.append(JSValueToStringCopy(m_context, tmp, &exception)); + Q_ASSERT(!exception); + } + return names; +} + +inline bool QScriptOriginalGlobalObject::isArray(JSValueRef value) const +{ + return isType(value, m_arrayConstructor, m_arrayPrototype); +} + +inline bool QScriptOriginalGlobalObject::isError(JSValueRef value) const +{ + return isType(value, m_errorConstructor, m_errorPrototype); +} + +inline bool QScriptOriginalGlobalObject::isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const +{ + // JSC API doesn't export the [[Class]] information for the builtins. But we know that a value + // is an object of the Type if it was created with the Type constructor or if it is the Type.prototype. + JSValueRef exception = 0; + bool result = JSValueIsInstanceOfConstructor(m_context, value, constructor, &exception) || JSValueIsStrictEqual(m_context, value, prototype); + Q_ASSERT(!exception); + return result; +} + +#endif // qscriptoriginalglobalobject_p_h diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h index 1d319ba..6e93a07 100644 --- a/JavaScriptCore/qt/api/qscriptvalue_p.h +++ b/JavaScriptCore/qt/api/qscriptvalue_p.h @@ -184,7 +184,6 @@ private: Value(QString* string) : m_string(string) {} } u; - inline bool inherits(const char*); inline State refinedJSValue(); inline bool isJSBased() const; @@ -416,7 +415,7 @@ bool QScriptValuePrivate::isError() return false; // Fall-through. case JSObject: - return inherits("Error"); + return m_engine->isError(*this); default: return false; } @@ -868,13 +867,7 @@ inline bool QScriptValuePrivate::hasOwnProperty(quint32 property) 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); + return m_engine->objectHasOwnProperty(*this, property); } /*! @@ -1124,24 +1117,6 @@ QScriptValuePrivate::operator JSObjectRef() const /*! \internal - Returns true if QSV is created from constructor with the given \a name, it has to be a - built-in type. -*/ -bool QScriptValuePrivate::inherits(const char* name) -{ - Q_ASSERT(isJSBased()); - JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine); - JSStringRef errorAttrName = QScriptConverter::toString(name); - JSValueRef exception = 0; - JSValueRef error = JSObjectGetProperty(*m_engine, globalObject, errorAttrName, &exception); - JSStringRelease(errorAttrName); - bool result = JSValueIsInstanceOfConstructor(*m_engine, *this, JSValueToObject(*m_engine, error, &exception), &exception); - m_engine->setException(exception); - return result; -} - -/*! - \internal Refines the state of this QScriptValuePrivate. Returns the new state. */ QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue() diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator.cpp b/JavaScriptCore/qt/api/qscriptvalueiterator.cpp new file mode 100644 index 0000000..f1caa61 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptvalueiterator.cpp @@ -0,0 +1,226 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" + +#include "qscriptvalueiterator.h" + +#include "qscriptvalue_p.h" +#include "qscriptvalueiterator_p.h" + +/*! + \class QScriptValueIterator + + \brief The QScriptValueIterator class provides a Java-style iterator for QScriptValue. + + \ingroup script + + + The QScriptValueIterator constructor takes a QScriptValue as + argument. After construction, the iterator is located at the very + beginning of the sequence of properties. Here's how to iterate over + all the properties of a QScriptValue: + + \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0 + + The next() advances the iterator. The name(), value() and flags() + functions return the name, value and flags of the last item that was + jumped over. + + If you want to remove properties as you iterate over the + QScriptValue, use remove(). If you want to modify the value of a + property, use setValue(). + + Note that QScriptValueIterator only iterates over the QScriptValue's + own properties; i.e. it does not follow the prototype chain. You can + use a loop like this to follow the prototype chain: + + \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1 + + Note that QScriptValueIterator will not automatically skip over + properties that have the QScriptValue::SkipInEnumeration flag set; + that flag only affects iteration in script code. If you want, you + can skip over such properties with code like the following: + + \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2 + + \sa QScriptValue::property() +*/ + +/*! + Constructs an iterator for traversing \a object. The iterator is + set to be at the front of the sequence of properties (before the + first property). +*/ +QScriptValueIterator::QScriptValueIterator(const QScriptValue& object) + : d_ptr(new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object))) +{} + +/*! + Destroys the iterator. +*/ +QScriptValueIterator::~QScriptValueIterator() +{} + +/*! + Returns true if there is at least one item ahead of the iterator + (i.e. the iterator is \e not at the back of the property sequence); + otherwise returns false. + + \sa next(), hasPrevious() +*/ +bool QScriptValueIterator::hasNext() const +{ + return d_ptr->hasNext(); +} + +/*! + Advances the iterator by one position. + + Calling this function on an iterator located at the back of the + container leads to undefined results. + + \sa hasNext(), previous(), name() +*/ +void QScriptValueIterator::next() +{ + d_ptr->next(); +} + +/*! + Returns true if there is at least one item behind the iterator + (i.e. the iterator is \e not at the front of the property sequence); + otherwise returns false. + + \sa previous(), hasNext() +*/ +bool QScriptValueIterator::hasPrevious() const +{ + return d_ptr->hasPrevious(); +} + +/*! + Moves the iterator back by one position. + + Calling this function on an iterator located at the front of the + container leads to undefined results. + + \sa hasPrevious(), next(), name() +*/ +void QScriptValueIterator::previous() +{ + d_ptr->previous(); +} + +/*! + Moves the iterator to the front of the QScriptValue (before the + first property). + + \sa toBack(), next() +*/ +void QScriptValueIterator::toFront() +{ + d_ptr->toFront(); +} + +/*! + Moves the iterator to the back of the QScriptValue (after the + last property). + + \sa toFront(), previous() +*/ +void QScriptValueIterator::toBack() +{ + d_ptr->toBack(); +} + +/*! + Returns the name of the last property that was jumped over using + next() or previous(). + + \sa value(), flags() +*/ +QString QScriptValueIterator::name() const +{ + return d_ptr->name(); +} + +/*! + Returns the name of the last property that was jumped over using + next() or previous(). +*/ +QScriptString QScriptValueIterator::scriptName() const +{ + return QScriptStringPrivate::get(d_ptr->scriptName()); +} + +/*! + Returns the value of the last property that was jumped over using + next() or previous(). + + \sa setValue(), name() +*/ +QScriptValue QScriptValueIterator::value() const +{ + return QScriptValuePrivate::get(d_ptr->value()); +} + +/*! + Sets the \a value of the last property that was jumped over using + next() or previous(). + + \sa value(), name() +*/ +void QScriptValueIterator::setValue(const QScriptValue& value) +{ + d_ptr->setValue(QScriptValuePrivate::get(value)); +} + +/*! + Removes the last property that was jumped over using next() + or previous(). + + \sa setValue() +*/ +void QScriptValueIterator::remove() +{ + d_ptr->remove(); +} + +/*! + Returns the flags of the last property that was jumped over using + next() or previous(). + + \sa value() +*/ +QScriptValue::PropertyFlags QScriptValueIterator::flags() const +{ + return d_ptr->flags(); +} + +/*! + Makes the iterator operate on \a object. The iterator is set to be + at the front of the sequence of properties (before the first + property). +*/ +QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue& object) +{ + d_ptr = new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object)); + return *this; +} diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator.h b/JavaScriptCore/qt/api/qscriptvalueiterator.h new file mode 100644 index 0000000..0c90661 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptvalueiterator.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptvalueiterator_h +#define qscriptvalueiterator_h + +#include "qtscriptglobal.h" +#include "qscriptstring.h" +#include <QtCore/qshareddata.h> +#include "qscriptvalue.h" + +class QScriptValue; +class QScriptValueIteratorPrivate; + + +class Q_JAVASCRIPT_EXPORT QScriptValueIterator { +public: + QScriptValueIterator(const QScriptValue& value); + ~QScriptValueIterator(); + + bool hasNext() const; + void next(); + + bool hasPrevious() const; + void previous(); + + QString name() const; + QScriptString scriptName() const; + + QScriptValue value() const; + void setValue(const QScriptValue& value); + + void remove(); + QScriptValue::PropertyFlags flags() const; + + void toFront(); + void toBack(); + + QScriptValueIterator& operator=(QScriptValue& value); +private: + QExplicitlySharedDataPointer<QScriptValueIteratorPrivate> d_ptr; + + Q_DECLARE_PRIVATE(QScriptValueIterator) + Q_DISABLE_COPY(QScriptValueIterator) +}; + +#endif // qscriptvalueiterator_h diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator_p.h b/JavaScriptCore/qt/api/qscriptvalueiterator_p.h new file mode 100644 index 0000000..b93b518 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptvalueiterator_p.h @@ -0,0 +1,172 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef qscriptvalueiterator_p_h +#define qscriptvalueiterator_p_h + +#include "qscriptvalue_p.h" +#include <JavaScriptCore/JavaScript.h> +#include <JavaScriptCore/JSRetainPtr.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qvector.h> + +class QScriptValueIteratorPrivate: public QSharedData { +public: + inline QScriptValueIteratorPrivate(const QScriptValuePrivate* value); + inline ~QScriptValueIteratorPrivate(); + + inline bool hasNext(); + inline void next(); + + inline bool hasPrevious(); + inline void previous(); + + inline QString name() const; + inline QScriptStringPrivate* scriptName() const; + + inline QScriptValuePrivate* value() const; + inline void setValue(const QScriptValuePrivate* value); + + inline void remove(); + + inline void toFront(); + inline void toBack(); + + QScriptValue::PropertyFlags flags() const; + + inline bool isValid() const; +private: + inline QScriptEnginePrivate* engine() const; + + QExplicitlySharedDataPointer<QScriptValuePrivate> m_object; + QVector<JSStringRef> m_names; + QMutableVectorIterator<JSStringRef> m_idx; +}; + +inline QScriptValueIteratorPrivate::QScriptValueIteratorPrivate(const QScriptValuePrivate* value) + : m_object(const_cast<QScriptValuePrivate*>(value)) + , m_idx(m_names) +{ + if (m_object->isObject()) { + m_names = engine()->objectGetOwnPropertyNames(*m_object); + m_idx = m_names; + } else + m_object = 0; +} + +inline QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate() +{ + QVector<JSStringRef>::const_iterator i = m_names.constBegin(); + for (; i != m_names.constEnd(); ++i) + JSStringRelease(*i); +} + +inline bool QScriptValueIteratorPrivate::hasNext() +{ + return m_idx.hasNext(); +} + +inline void QScriptValueIteratorPrivate::next() +{ + // FIXME (Qt5) This method should return a value (QTBUG-11226). + m_idx.next(); +} + +inline bool QScriptValueIteratorPrivate::hasPrevious() +{ + return m_idx.hasPrevious(); +} + +inline void QScriptValueIteratorPrivate::previous() +{ + m_idx.previous(); +} + +inline QString QScriptValueIteratorPrivate::name() const +{ + if (!isValid()) + return QString(); + return QScriptConverter::toString(m_idx.value()); +} + +inline QScriptStringPrivate* QScriptValueIteratorPrivate::scriptName() const +{ + if (!isValid()) + return new QScriptStringPrivate(); + return new QScriptStringPrivate(QScriptConverter::toString(m_idx.value())); +} + +inline QScriptValuePrivate* QScriptValueIteratorPrivate::value() const +{ + if (!isValid()) + return new QScriptValuePrivate(); + JSValueRef exception = 0; + JSValueRef value = m_object->property(m_idx.value(), &exception); + engine()->setException(exception); + return new QScriptValuePrivate(engine(), value); +} + +inline void QScriptValueIteratorPrivate::setValue(const QScriptValuePrivate* value) +{ + if (!isValid()) + return; + JSValueRef exception = 0; + m_object->setProperty(m_idx.value(), *value, /* flags */ 0, &exception); + engine()->setException(exception); +} + +inline void QScriptValueIteratorPrivate::remove() +{ + if (!isValid()) + return; + JSValueRef exception = 0; + m_object->deleteProperty(m_idx.value(), &exception); + engine()->setException(exception); + m_idx.remove(); +} + +inline void QScriptValueIteratorPrivate::toFront() +{ + m_idx.toFront(); +} + +inline void QScriptValueIteratorPrivate::toBack() +{ + m_idx.toBack(); +} + +QScriptValue::PropertyFlags QScriptValueIteratorPrivate::flags() const +{ + if (!isValid()) + return QScriptValue::PropertyFlags(0); + return m_object->propertyFlags(m_idx.value(), QScriptValue::ResolveLocal); +} + +inline bool QScriptValueIteratorPrivate::isValid() const +{ + return m_object; +} + +inline QScriptEnginePrivate* QScriptValueIteratorPrivate::engine() const +{ + Q_ASSERT(isValid()); + return m_object->engine(); +} + +#endif // qscriptvalueiterator_p_h diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp index 73b57dc..a82347e 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp @@ -1261,4 +1261,28 @@ void tst_QScriptValue::propertyFlag() QVERIFY(!object.propertyFlags(protoNameHandle, QScriptValue::ResolveLocal)); } +void tst_QScriptValue::globalObjectChanges() +{ + // API functionality shouldn't depend on Global Object. + QScriptEngine engine; + QScriptValue array = engine.newArray(); + QScriptValue error = engine.evaluate("new Error"); + QScriptValue object = engine.newObject(); + + object.setProperty("foo", 512); + + // Remove properties form global object. + engine.evaluate("delete Object; delete Error; delete Array;"); + + QVERIFY(array.isArray()); + QVERIFY(error.isError()); + QVERIFY(object.isObject()); + + QVERIFY(object.property("foo").isValid()); + QVERIFY(object.property("foo", QScriptValue::ResolveLocal).isValid()); + object.setProperty("foo", QScriptValue()); + QVERIFY(!object.property("foo").isValid()); + QVERIFY(!object.property("foo", QScriptValue::ResolveLocal).isValid()); +} + QTEST_MAIN(tst_QScriptValue) diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h index 6108423..41b99cd 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h @@ -60,6 +60,7 @@ private slots: void getPropertyResolveFlag(); void propertyFlag_data(); void propertyFlag(); + void globalObjectChanges(); // Generated test functions. void isBool_data(); diff --git a/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro b/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro new file mode 100644 index 0000000..5314ec9 --- /dev/null +++ b/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_qscriptvalueiterator +QT += testlib +include(../tests.pri) + +SOURCES += tst_qscriptvalueiterator.cpp + diff --git a/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp b/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp new file mode 100644 index 0000000..43d0042 --- /dev/null +++ b/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp @@ -0,0 +1,531 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef tst_qscriptvalueiterator_h +#define tst_qscriptvalueiterator_h + +#include "qscriptengine.h" +#include "qscriptvalue.h" +#include "qscriptvalueiterator.h" +#include <QtCore/qhash.h> +#include <QtTest/QtTest> + +class tst_QScriptValueIterator : public QObject { + Q_OBJECT + +public: + tst_QScriptValueIterator(); + virtual ~tst_QScriptValueIterator(); + +private slots: + void iterateForward_data(); + void iterateForward(); + void iterateBackward_data(); + void iterateBackward(); + void iterateArray_data(); + void iterateArray(); + void iterateBackAndForth(); + void setValue(); + void remove(); + void removeMixed(); + void removeUndeletable(); + void iterateString(); + void assignObjectToIterator(); +}; + +tst_QScriptValueIterator::tst_QScriptValueIterator() +{ +} + +tst_QScriptValueIterator::~tst_QScriptValueIterator() +{ +} + +void tst_QScriptValueIterator::iterateForward_data() +{ + QTest::addColumn<QStringList>("propertyNames"); + QTest::addColumn<QStringList>("propertyValues"); + + QTest::newRow("no properties") + << QStringList() << QStringList(); + QTest::newRow("foo=bar") + << (QStringList() << "foo") + << (QStringList() << "bar"); + QTest::newRow("foo=bar, baz=123") + << (QStringList() << "foo" << "baz") + << (QStringList() << "bar" << "123"); + QTest::newRow("foo=bar, baz=123, rab=oof") + << (QStringList() << "foo" << "baz" << "rab") + << (QStringList() << "bar" << "123" << "oof"); +} + +void tst_QScriptValueIterator::iterateForward() +{ + QFETCH(QStringList, propertyNames); + QFETCH(QStringList, propertyValues); + QMap<QString, QString> pmap; + Q_ASSERT(propertyNames.size() == propertyValues.size()); + + QScriptEngine engine; + QScriptValue object = engine.newObject(); + for (int i = 0; i < propertyNames.size(); ++i) { + QString name = propertyNames.at(i); + QString value = propertyValues.at(i); + pmap.insert(name, value); + object.setProperty(name, QScriptValue(&engine, value)); + } + QScriptValue otherObject = engine.newObject(); + otherObject.setProperty("foo", QScriptValue(&engine, 123456)); + otherObject.setProperty("protoProperty", QScriptValue(&engine, 654321)); + object.setPrototype(otherObject); // should not affect iterator + + QStringList lst; + QScriptValueIterator it(object); + while (!pmap.isEmpty()) { + QCOMPARE(it.hasNext(), true); + QCOMPARE(it.hasNext(), true); + it.next(); + QString name = it.name(); + QCOMPARE(pmap.contains(name), true); + QCOMPARE(it.name(), name); + QCOMPARE(it.flags(), object.propertyFlags(name)); + QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true); + QCOMPARE(it.scriptName(), engine.toStringHandle(name)); + pmap.remove(name); + lst.append(name); + } + + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.hasNext(), false); + + it.toFront(); + for (int i = 0; i < lst.count(); ++i) { + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), lst.at(i)); + } + + for (int i = 0; i < lst.count(); ++i) { + QCOMPARE(it.hasPrevious(), true); + it.previous(); + QCOMPARE(it.name(), lst.at(lst.count()-1-i)); + } + QCOMPARE(it.hasPrevious(), false); +} + +void tst_QScriptValueIterator::iterateBackward_data() +{ + iterateForward_data(); +} + +void tst_QScriptValueIterator::iterateBackward() +{ + QFETCH(QStringList, propertyNames); + QFETCH(QStringList, propertyValues); + QMap<QString, QString> pmap; + Q_ASSERT(propertyNames.size() == propertyValues.size()); + + QScriptEngine engine; + QScriptValue object = engine.newObject(); + for (int i = 0; i < propertyNames.size(); ++i) { + QString name = propertyNames.at(i); + QString value = propertyValues.at(i); + pmap.insert(name, value); + object.setProperty(name, QScriptValue(&engine, value)); + } + + QStringList lst; + QScriptValueIterator it(object); + it.toBack(); + while (!pmap.isEmpty()) { + QCOMPARE(it.hasPrevious(), true); + QCOMPARE(it.hasPrevious(), true); + it.previous(); + QString name = it.name(); + QCOMPARE(pmap.contains(name), true); + QCOMPARE(it.name(), name); + QCOMPARE(it.flags(), object.propertyFlags(name)); + QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true); + pmap.remove(name); + lst.append(name); + } + + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasPrevious(), false); + + it.toBack(); + for (int i = 0; i < lst.count(); ++i) { + QCOMPARE(it.hasPrevious(), true); + it.previous(); + QCOMPARE(it.name(), lst.at(i)); + } + + for (int i = 0; i < lst.count(); ++i) { + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), lst.at(lst.count()-1-i)); + } + QCOMPARE(it.hasNext(), false); +} + +void tst_QScriptValueIterator::iterateArray_data() +{ + QTest::addColumn<QStringList>("inputPropertyNames"); + QTest::addColumn<QStringList>("inputPropertyValues"); + QTest::addColumn<QStringList>("propertyNames"); + QTest::addColumn<QStringList>("propertyValues"); + QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList(); + + QTest::newRow("0=foo, 1=barr") + << (QStringList() << "0" << "1") + << (QStringList() << "foo" << "bar") + << (QStringList() << "0" << "1") + << (QStringList() << "foo" << "bar"); + + QTest::newRow("0=foo, 3=barr") + << (QStringList() << "0" << "1" << "2" << "3") + << (QStringList() << "foo" << "" << "" << "bar") + << (QStringList() << "0" << "1" << "2" << "3") + << (QStringList() << "foo" << "" << "" << "bar"); +} + +void tst_QScriptValueIterator::iterateArray() +{ + QFETCH(QStringList, inputPropertyNames); + QFETCH(QStringList, inputPropertyValues); + QFETCH(QStringList, propertyNames); + QFETCH(QStringList, propertyValues); + + QScriptEngine engine; + QScriptValue array = engine.newArray(); + for (int i = 0; i < inputPropertyNames.size(); ++i) + array.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i)); + + int length = array.property("length").toInt32(); + QCOMPARE(length, propertyNames.size()); + QScriptValueIterator it(array); + for (int i = 0; i < length; ++i) { + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), propertyNames.at(i)); + QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); + QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); + QCOMPARE(it.value().toString(), propertyValues.at(i)); + } + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("length")); + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable)); + + it.previous(); + QCOMPARE(it.hasPrevious(), length > 0); + for (int i = length - 1; i >= 0; --i) { + it.previous(); + QCOMPARE(it.name(), propertyNames.at(i)); + QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); + QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); + QCOMPARE(it.value().toString(), propertyValues.at(i)); + QCOMPARE(it.hasPrevious(), i > 0); + } + QCOMPARE(it.hasPrevious(), false); + + // hasNext() and hasPrevious() cache their result; verify that the result is in sync + if (length > 1) { + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("0")); + QVERIFY(it.hasNext()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("0")); + QVERIFY(!it.hasPrevious()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("0")); + QVERIFY(it.hasPrevious()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("1")); + } + { + // same test as object: + QScriptValue originalArray = engine.newArray(); + for (int i = 0; i < inputPropertyNames.size(); ++i) + originalArray.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i)); + + QScriptValue array = originalArray.toObject(); + int length = array.property("length").toInt32(); + QCOMPARE(length, propertyNames.size()); + QScriptValueIterator it(array); + for (int i = 0; i < length; ++i) { + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), propertyNames.at(i)); + QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i))); + QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i)))); + QCOMPARE(it.value().toString(), propertyValues.at(i)); + } + QCOMPARE(it.hasNext(), true); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("length")); + } +} + +void tst_QScriptValueIterator::iterateBackAndForth() +{ + QScriptEngine engine; + { + QScriptValue object = engine.newObject(); + object.setProperty("foo", QScriptValue(&engine, "bar")); + object.setProperty("rab", QScriptValue(&engine, "oof"), + QScriptValue::SkipInEnumeration); // should not affect iterator + QScriptValueIterator it(object); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QLatin1String("foo")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QLatin1String("foo")); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QLatin1String("foo")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QLatin1String("foo")); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QLatin1String("foo")); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QLatin1String("rab")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QLatin1String("rab")); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QLatin1String("rab")); + QVERIFY(it.hasPrevious()); + it.previous(); + QCOMPARE(it.name(), QLatin1String("rab")); + } + { + // hasNext() and hasPrevious() cache their result; verify that the result is in sync + QScriptValue object = engine.newObject(); + object.setProperty("foo", QScriptValue(&engine, "bar")); + object.setProperty("rab", QScriptValue(&engine, "oof")); + QScriptValueIterator it(object); + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QVERIFY(it.hasNext()); + it.previous(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QVERIFY(!it.hasPrevious()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + QVERIFY(it.hasPrevious()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("rab")); + } +} + +void tst_QScriptValueIterator::setValue() +{ + QScriptEngine engine; + QScriptValue object = engine.newObject(); + object.setProperty("foo", QScriptValue(&engine, "bar")); + QScriptValueIterator it(object); + it.next(); + QCOMPARE(it.name(), QLatin1String("foo")); + it.setValue(QScriptValue(&engine, "baz")); + QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("baz"))), true); + QCOMPARE(object.property("foo").toString(), QLatin1String("baz")); + it.setValue(QScriptValue(&engine, "zab")); + QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("zab"))), true); + QCOMPARE(object.property("foo").toString(), QLatin1String("zab")); +} + +void tst_QScriptValueIterator::remove() +{ + QScriptEngine engine; + QScriptValue object = engine.newObject(); + object.setProperty("foo", QScriptValue(&engine, "bar"), + QScriptValue::SkipInEnumeration); // should not affect iterator + object.setProperty("rab", QScriptValue(&engine, "oof")); + QScriptValueIterator it(object); + it.next(); + QCOMPARE(it.name(), QLatin1String("foo")); + it.remove(); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(object.property("foo").isValid(), false); + QCOMPARE(object.property("rab").toString(), QLatin1String("oof")); + it.next(); + QCOMPARE(it.name(), QLatin1String("rab")); + QCOMPARE(it.value().toString(), QLatin1String("oof")); + QCOMPARE(it.hasNext(), false); + it.remove(); + QCOMPARE(object.property("rab").isValid(), false); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); +} + +void tst_QScriptValueIterator::removeMixed() +{ + // This test checks if QScriptValueIterator behaives correctly if an object's property got deleted + // in different way. + QScriptEngine engine; + QScriptValue object = engine.evaluate("o = new Object; o"); + object.setProperty("a", QScriptValue(124), QScriptValue::SkipInEnumeration); + object.setProperty("b", QScriptValue(816)); + object.setProperty("c", QScriptValue(3264)); + QScriptValueIterator it(object); + it.next(); + it.next(); + QCOMPARE(it.name(), QLatin1String("b")); + QCOMPARE(it.hasPrevious(), true); + QCOMPARE(it.hasNext(), true); + // Remove 'a' + object.setProperty("a", QScriptValue()); + QEXPECT_FAIL("", "That would be a significant behavioral and performance change, new QtScript API should be developed (QTBUG-12087)", Abort); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), true); + // Remove 'c' + engine.evaluate("delete o.c"); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); + // Remove 'b' + object.setProperty("b", QScriptValue()); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.name(), QString()); + QCOMPARE(it.value().toString(), QString()); + + // Try to remove a removed property. + it.remove(); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.name(), QString()); + QCOMPARE(it.value().toString(), QString()); + + for (int i = 0; i < 2; ++i) { + it.next(); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.name(), QString()); + QCOMPARE(it.value().toString(), QString()); + } + + for (int i = 0; i < 2; ++i) { + it.previous(); + QCOMPARE(it.hasPrevious(), false); + QCOMPARE(it.hasNext(), false); + QCOMPARE(it.name(), QString()); + QCOMPARE(it.value().toString(), QString()); + } +} + +void tst_QScriptValueIterator::removeUndeletable() +{ + // Undeletable property can't be deleted via iterator. + QScriptEngine engine; + QScriptValue object = engine.evaluate("o = new Object; o"); + object.setProperty("a", QScriptValue(&engine, 124)); + object.setProperty("b", QScriptValue(&engine, 816), QScriptValue::Undeletable); + QVERIFY(object.property("b").isValid()); + QScriptValueIterator it(object); + it.next(); + it.next(); + it.remove(); + it.toFront(); + QVERIFY(it.hasNext()); + QVERIFY(object.property("b").isValid()); +} + +void tst_QScriptValueIterator::iterateString() +{ + QScriptEngine engine; + QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao")); + QVERIFY(str.isString()); + QScriptValue obj = str.toObject(); + int length = obj.property("length").toInt32(); + QCOMPARE(length, 4); + QScriptValueIterator it(obj); + for (int i = 0; i < length; ++i) { + QCOMPARE(it.hasNext(), true); + QString indexStr = QScriptValue(&engine, i).toString(); + it.next(); + QCOMPARE(it.name(), indexStr); + QCOMPARE(it.flags(), obj.propertyFlags(indexStr)); + QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true); + } + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("length")); + QVERIFY(it.value().isNumber()); + QCOMPARE(it.value().toInt32(), length); + QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable)); + + it.previous(); + QCOMPARE(it.hasPrevious(), length > 0); + for (int i = length - 1; i >= 0; --i) { + it.previous(); + QString indexStr = QScriptValue(&engine, i).toString(); + QCOMPARE(it.name(), indexStr); + QCOMPARE(it.flags(), obj.propertyFlags(indexStr)); + QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true); + QCOMPARE(it.hasPrevious(), i > 0); + } + QCOMPARE(it.hasPrevious(), false); +} + +void tst_QScriptValueIterator::assignObjectToIterator() +{ + QScriptEngine eng; + QScriptValue obj1 = eng.newObject(); + obj1.setProperty("foo", 123); + QScriptValue obj2 = eng.newObject(); + obj2.setProperty("bar", 456); + + QScriptValueIterator it(obj1); + QVERIFY(it.hasNext()); + it.next(); + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + + it = obj1; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("foo")); + + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); + + it = obj2; + QVERIFY(it.hasNext()); + it.next(); + QCOMPARE(it.name(), QString::fromLatin1("bar")); +} + +QTEST_MAIN(tst_QScriptValueIterator) +#include "tst_qscriptvalueiterator.moc" + +#endif // tst_qscriptvalueiterator_h diff --git a/JavaScriptCore/qt/tests/tests.pro b/JavaScriptCore/qt/tests/tests.pro index 7c3f590..6d5559b 100644 --- a/JavaScriptCore/qt/tests/tests.pro +++ b/JavaScriptCore/qt/tests/tests.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS = qscriptengine \ qscriptvalue \ + qscriptvalueiterator \ qscriptstring diff --git a/JavaScriptCore/runtime/ArrayConstructor.cpp b/JavaScriptCore/runtime/ArrayConstructor.cpp index 589739a..e5d0dac 100644 --- a/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -58,7 +58,7 @@ static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgLi uint32_t n = args.at(0).toUInt32(exec); if (n != args.at(0).toNumber(exec)) return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer.")); - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n, CreateInitialized); } // otherwise the array is constructed with the arguments in it diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 2cb04ff..e79c46d 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -73,26 +73,13 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, if (callType != CallTypeJS) return false; -#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. - 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 - if (!codeBlock) + FunctionExecutable* executable = callData.js.functionExecutable; + + JSObject* error = executable->compileForCall(exec, callData.js.scopeChain); + if (error) return false; - return codeBlock->isNumericCompareFunction(); + return executable->generatedBytecodeForCall().isNumericCompareFunction(); } // ------------------------------ ArrayPrototype ---------------------------- @@ -560,8 +547,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) JSObject* thisObj = thisValue.toThisObject(exec); // 15.4.4.12 - JSArray* resObj = constructEmptyArray(exec); - JSValue result = resObj; // FIXME: Firefox returns an empty array. if (!exec->argumentCount()) @@ -582,10 +567,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) else deleteCount = length - begin; - for (unsigned k = 0; k < deleteCount; k++) { - if (JSValue v = getProperty(exec, thisObj, k + begin)) - resObj->put(exec, k, v); - } + JSArray* resObj = new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact); + JSValue result = resObj; + + for (unsigned k = 0; k < deleteCount; k++) + resObj->uncheckedSetIndex(k, getProperty(exec, thisObj, k + begin)); + resObj->setLength(deleteCount); unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0); diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index 0647e81..ebde320 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -78,6 +78,11 @@ JSObject* createStackOverflowError(ExecState* exec) return createRangeError(exec, "Maximum call stack size exceeded."); } +JSObject* createStackOverflowError(JSGlobalObject* globalObject) +{ + return createRangeError(globalObject, "Maximum call stack size exceeded."); +} + JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index 906465f..3e6de86 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -37,6 +37,7 @@ namespace JSC { class ExecState; class Identifier; class JSGlobalData; + class JSGlobalObject; class JSNotAnObjectErrorStub; class JSObject; class Node; @@ -45,6 +46,7 @@ namespace JSC { JSValue createInterruptedExecutionException(JSGlobalData*); JSValue createTerminatedExecutionException(JSGlobalData*); JSObject* createStackOverflowError(ExecState*); + JSObject* createStackOverflowError(JSGlobalObject*); JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull); JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*); diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp index 355ee86..229588b 100644 --- a/JavaScriptCore/runtime/Executable.cpp +++ b/JavaScriptCore/runtime/Executable.cpp @@ -45,86 +45,144 @@ VPtrHackExecutable::~VPtrHackExecutable() { } +EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source) + : ScriptExecutable(exec, source) +{ +} + EvalExecutable::~EvalExecutable() { - delete m_evalCodeBlock; +} + +ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) + : ScriptExecutable(exec, source) +{ } ProgramExecutable::~ProgramExecutable() { - delete m_programCodeBlock; +} + +FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + : ScriptExecutable(globalData, source) + , m_numVariables(0) + , m_forceUsesArguments(forceUsesArguments) + , m_parameters(parameters) + , m_name(name) + , m_symbolTable(0) +{ + m_firstLine = firstLine; + m_lastLine = lastLine; +} + +FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) + : ScriptExecutable(exec, source) + , m_numVariables(0) + , m_forceUsesArguments(forceUsesArguments) + , m_parameters(parameters) + , m_name(name) + , m_symbolTable(0) +{ + m_firstLine = firstLine; + m_lastLine = lastLine; } FunctionExecutable::~FunctionExecutable() { - delete m_codeBlockForCall; - delete m_codeBlockForConstruct; } -JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { - int errLine; - UString errMsg; + JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg); - if (!evalNode) - return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source); + RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + if (!evalNode) { + ASSERT(exception); + return exception; + } recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); ASSERT(!m_evalCodeBlock); - m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock))); + m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())); + OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get()))); generator->generate(); evalNode->destroyData(); + +#if ENABLE(JIT) + if (exec->globalData().canUseJIT()) { + m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get()); +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_evalCodeBlock->discardBytecode(); +#endif + } +#endif + return 0; } JSObject* ProgramExecutable::checkSyntax(ExecState* exec) { - int errLine; - UString errMsg; + JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg); - if (!programNode) - return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source); - return 0; + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + if (programNode) + return 0; + ASSERT(exception); + return exception; } -JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode) +JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { - int errLine; - UString errMsg; + ASSERT(!m_programCodeBlock); + + JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); - RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg); - if (!programNode) - return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source); + RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception); + if (!programNode) { + ASSERT(exception); + return exception; + } recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine()); ScopeChain scopeChain(scopeChainNode); JSGlobalObject* globalObject = scopeChain.globalObject(); - ASSERT(!m_programCodeBlock); - m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock))); + m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider())); + OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock.get()))); generator->generate(); programNode->destroyData(); - return 0; + +#if ENABLE(JIT) + if (exec->globalData().canUseJIT()) { + m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get()); +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_programCodeBlock->discardBytecode(); +#endif + } +#endif + + return 0; } -bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode) +JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { + JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); - if (!body) - return false; + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception); + if (!body) { + ASSERT(exception); + return exception; + } if (m_forceUsesArguments) body->setUsesArguments(); body->finishParsing(m_parameters, m_name); @@ -134,8 +192,8 @@ bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNo JSGlobalObject* globalObject = scopeChain.globalObject(); ASSERT(!m_codeBlockForCall); - m_codeBlockForCall = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), false); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall))); + m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), false)); + OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get()))); generator->generate(); m_numParametersForCall = m_codeBlockForCall->m_numParameters; ASSERT(m_numParametersForCall); @@ -143,15 +201,29 @@ bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNo m_symbolTable = m_codeBlockForCall->sharedSymbolTable(); body->destroyData(); - return true; + +#if ENABLE(JIT) + if (exec->globalData().canUseJIT()) { + m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_codeBlockForCall->discardBytecode(); +#endif + } +#endif + + return 0; } -bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode) +JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { + JSObject* exception = 0; JSGlobalData* globalData = scopeChainNode->globalData; - RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); - if (!body) - return false; + RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception); + if (!body) { + ASSERT(exception); + return exception; + } if (m_forceUsesArguments) body->setUsesArguments(); body->finishParsing(m_parameters, m_name); @@ -161,8 +233,8 @@ bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh JSGlobalObject* globalObject = scopeChain.globalObject(); ASSERT(!m_codeBlockForConstruct); - m_codeBlockForConstruct = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), true); - OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct))); + m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), true)); + OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get()))); generator->generate(); m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters; ASSERT(m_numParametersForConstruct); @@ -170,69 +242,20 @@ bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable(); body->destroyData(); - return true; -} #if ENABLE(JIT) - -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); - -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - codeBlock->discardBytecode(); -#endif -} - -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); - -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - codeBlock->discardBytecode(); -#endif -} - -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); - + if (exec->globalData().canUseJIT()) { + m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, m_codeBlockForConstruct.get(), &m_jitCodeForConstructWithArityCheck); #if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - codeBlock->discardBytecode(); + if (!BytecodeGenerator::dumpsGeneratedCode()) + m_codeBlockForConstruct->discardBytecode(); #endif -} - -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); -#if !ENABLE(OPCODE_SAMPLING) - if (!BytecodeGenerator::dumpsGeneratedCode()) - codeBlock->discardBytecode(); -#endif + return 0; } -#endif - void FunctionExecutable::markAggregate(MarkStack& markStack) { if (m_codeBlockForCall) @@ -243,7 +266,8 @@ void FunctionExecutable::markAggregate(MarkStack& markStack) PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { - RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source); + JSObject* exception = 0; + RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, &exception); if (!newFunctionBody) return PassOwnPtr<ExceptionInfo>(); if (m_forceUsesArguments) @@ -263,10 +287,7 @@ PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount()); #if ENABLE(JIT) -#if ENABLE(INTERPRETER) - if (globalData->canUseJIT()) -#endif - { + if (globalData->canUseJIT()) { JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get()); ASSERT(codeBlock->m_isConstructor ? newJITCode.size() == generatedJITCodeForConstruct().size() : newJITCode.size() == generatedJITCodeForCall().size()); } @@ -279,7 +300,8 @@ PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock) { - RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source); + JSObject* exception = 0; + RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, &exception); if (!newEvalBody) return PassOwnPtr<ExceptionInfo>(); @@ -295,10 +317,7 @@ PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* glo ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount()); #if ENABLE(JIT) -#if ENABLE(INTERPRETER) - if (globalData->canUseJIT()) -#endif - { + if (globalData->canUseJIT()) { JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get()); ASSERT(newJITCode.size() == generatedJITCodeForCall().size()); } @@ -309,10 +328,8 @@ PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* glo void FunctionExecutable::recompile(ExecState*) { - delete m_codeBlockForCall; - m_codeBlockForCall = 0; - delete m_codeBlockForConstruct; - m_codeBlockForConstruct = 0; + m_codeBlockForCall.clear(); + m_codeBlockForConstruct.clear(); m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED; m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED; #if ENABLE(JIT) @@ -321,26 +338,25 @@ void FunctionExecutable::recompile(ExecState*) #endif } -PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg) +PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { - RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg); - if (!program) + JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); + RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, exception); + if (!program) { + ASSERT(*exception); return 0; + } + // Uses of this function that would not result in a single function expression are invalid. StatementNode* exprStatement = program->singleStatement(); ASSERT(exprStatement); ASSERT(exprStatement->isExprStatement()); - if (!exprStatement || !exprStatement->isExprStatement()) - return 0; - ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr(); ASSERT(funcExpr); ASSERT(funcExpr->isFuncExprNode()); - if (!funcExpr || !funcExpr->isFuncExprNode()) - return 0; - FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body(); ASSERT(body); + return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine()); } diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index 516d6ce..10dfb34 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -98,6 +98,8 @@ namespace JSC { public: static PassRefPtr<NativeExecutable> create(MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor) { + if (!callThunk) + return adoptRef(new NativeExecutable(JITCode(), function, JITCode(), constructor)); return adoptRef(new NativeExecutable(JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor)); } @@ -193,42 +195,38 @@ namespace JSC { ~EvalExecutable(); - EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) + JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { - if (!m_evalCodeBlock) { - JSObject* error = compile(exec, scopeChainNode); - ASSERT_UNUSED(!error, error); - } - return *m_evalCodeBlock; + JSObject* error = 0; + if (!m_evalCodeBlock) + error = compileInternal(exec, scopeChainNode); + ASSERT(!error == !!m_evalCodeBlock); + return error; } - JSObject* compile(ExecState*, ScopeChainNode*); - - static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); } - - private: - EvalExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) - , m_evalCodeBlock(0) + EvalCodeBlock& generatedBytecode() { + ASSERT(m_evalCodeBlock); + return *m_evalCodeBlock; } - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); - - EvalCodeBlock* m_evalCodeBlock; + static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); } #if ENABLE(JIT) - public: - JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode) + JITCode& generatedJITCode() { - if (!m_jitCodeForCall) - generateJITCode(exec, scopeChainNode); - return m_jitCodeForCall; + return generatedJITCodeForCall(); } +#endif private: - void generateJITCode(ExecState*, ScopeChainNode*); -#endif + EvalExecutable(ExecState*, const SourceCode&); + + JSObject* compileInternal(ExecState*, ScopeChainNode*); + + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + + OwnPtr<EvalCodeBlock> m_evalCodeBlock; }; class ProgramExecutable : public ScriptExecutable { @@ -240,41 +238,38 @@ namespace JSC { ~ProgramExecutable(); - ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) + JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { - if (!m_programCodeBlock) { - JSObject* error = compile(exec, scopeChainNode); - ASSERT_UNUSED(!error, error); - } - return *m_programCodeBlock; + JSObject* error = 0; + if (!m_programCodeBlock) + error = compileInternal(exec, scopeChainNode); + ASSERT(!error == !!m_programCodeBlock); + return error; } - JSObject* checkSyntax(ExecState*); - JSObject* compile(ExecState*, ScopeChainNode*); - - private: - ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) - , m_programCodeBlock(0) + ProgramCodeBlock& generatedBytecode() { + ASSERT(m_programCodeBlock); + return *m_programCodeBlock; } - virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); - - ProgramCodeBlock* m_programCodeBlock; + JSObject* checkSyntax(ExecState*); #if ENABLE(JIT) - public: - JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode) + JITCode& generatedJITCode() { - if (!m_jitCodeForCall) - generateJITCode(exec, scopeChainNode); - return m_jitCodeForCall; + return generatedJITCodeForCall(); } +#endif private: - void generateJITCode(ExecState*, ScopeChainNode*); -#endif + ProgramExecutable(ExecState*, const SourceCode&); + + JSObject* compileInternal(ExecState*, ScopeChainNode*); + + virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); + + OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; class FunctionExecutable : public ScriptExecutable { @@ -300,7 +295,7 @@ namespace JSC { // Returns either call or construct bytecode. This can be appropriate // for answering questions that that don't vary between call and construct -- // for example, argumentsRegister(). - FunctionCodeBlock& generatedByteCode() + FunctionCodeBlock& generatedBytecode() { if (m_codeBlockForCall) return *m_codeBlockForCall; @@ -308,12 +303,13 @@ namespace JSC { return *m_codeBlockForConstruct; } - FunctionCodeBlock* bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode) + JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode) { - ASSERT(scopeChainNode); + JSObject* error = 0; if (!m_codeBlockForCall) - compileForCall(exec, scopeChainNode); - return m_codeBlockForCall; + error = compileForCallInternal(exec, scopeChainNode); + ASSERT(!error == !!m_codeBlockForCall); + return error; } bool isGeneratedForCall() const @@ -327,12 +323,13 @@ namespace JSC { return *m_codeBlockForCall; } - FunctionCodeBlock* bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) + JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) { - ASSERT(scopeChainNode); + JSObject* error = 0; if (!m_codeBlockForConstruct) - compileForConstruct(exec, scopeChainNode); - return m_codeBlockForConstruct; + error = compileForConstructInternal(exec, scopeChainNode); + ASSERT(!error == !!m_codeBlockForConstruct); + return error; } bool isGeneratedForConstruct() const @@ -353,40 +350,15 @@ namespace JSC { SharedSymbolTable* symbolTable() const { return m_symbolTable; } void recompile(ExecState*); - void markAggregate(MarkStack& markStack); - static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0); + void markAggregate(MarkStack&); + static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); private: - FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(globalData, source) - , m_numVariables(0) - , m_forceUsesArguments(forceUsesArguments) - , m_parameters(parameters) - , m_codeBlockForCall(0) - , m_codeBlockForConstruct(0) - , m_name(name) - , m_symbolTable(0) - { - m_firstLine = firstLine; - m_lastLine = lastLine; - } + FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); + FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, int firstLine, int lastLine); - FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine) - : ScriptExecutable(exec, source) - , m_numVariables(0) - , m_forceUsesArguments(forceUsesArguments) - , m_parameters(parameters) - , m_codeBlockForCall(0) - , m_codeBlockForConstruct(0) - , m_name(name) - , m_symbolTable(0) - { - m_firstLine = firstLine; - m_lastLine = lastLine; - } - - bool compileForCall(ExecState*, ScopeChainNode*); - bool compileForConstruct(ExecState*, ScopeChainNode*); + JSObject* compileForCallInternal(ExecState*, ScopeChainNode*); + JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); @@ -394,27 +366,13 @@ namespace JSC { bool m_forceUsesArguments : 1; RefPtr<FunctionParameters> m_parameters; - FunctionCodeBlock* m_codeBlockForCall; - FunctionCodeBlock* m_codeBlockForConstruct; + OwnPtr<FunctionCodeBlock> m_codeBlockForCall; + OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct; Identifier m_name; SharedSymbolTable* m_symbolTable; #if ENABLE(JIT) public: - JITCode& jitCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode) - { - if (!m_jitCodeForCall) - generateJITCodeForCall(exec, scopeChainNode); - return m_jitCodeForCall; - } - - JITCode& jitCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) - { - if (!m_jitCodeForConstruct) - generateJITCodeForConstruct(exec, scopeChainNode); - return m_jitCodeForConstruct; - } - MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck() { ASSERT(m_jitCodeForCall); @@ -428,10 +386,6 @@ namespace JSC { ASSERT(m_jitCodeForConstructWithArityCheck); return m_jitCodeForConstructWithArityCheck; } - - private: - void generateJITCodeForCall(ExecState*, ScopeChainNode*); - void generateJITCodeForConstruct(ExecState*, ScopeChainNode*); #endif }; diff --git a/JavaScriptCore/runtime/FunctionConstructor.cpp b/JavaScriptCore/runtime/FunctionConstructor.cpp index a5ff28c..a036eef 100644 --- a/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -95,14 +95,15 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi program = builder.build(); } - int errLine; - UString errMsg; JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSGlobalData* globalData = globalObject->globalData(); SourceCode source = makeSource(program, sourceURL, lineNumber); - RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg); - if (!function) - return throwError(exec, addErrorInfo(globalData, createSyntaxError(globalObject, errMsg), errLine, source)); + JSObject* exception = 0; + RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); + if (!function) { + ASSERT(exception); + return throwError(exec, exception); + } ScopeChain scopeChain(globalObject, globalData, globalObject, exec->globalThisValue()); return new (exec) JSFunction(exec, function, scopeChain.node()); diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index fd415ce..8cf71d0 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -143,7 +143,7 @@ JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identi { JSActivation* activation = asActivation(slotBase); CallFrame* callFrame = CallFrame::create(activation->d()->registers); - int argumentsRegister = activation->d()->functionExecutable->generatedByteCode().argumentsRegister(); + int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister(); if (!callFrame->r(argumentsRegister).jsValue()) { JSValue arguments = JSValue(new (callFrame) Arguments(callFrame)); callFrame->r(argumentsRegister) = arguments; diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index 362f89b..56603a3 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -33,8 +33,6 @@ #include <wtf/OwnPtr.h> #include <Operations.h> -#define CHECK_ARRAY_CONSISTENCY 0 - using namespace std; using namespace WTF; @@ -141,22 +139,37 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure) checkConsistency(); } -JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength) +JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength, ArrayCreationMode creationMode) : JSObject(structure) { - unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); + unsigned initialCapacity; + if (creationMode == CreateCompact) + initialCapacity = initialLength; + else + initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity))); - m_storage->m_length = initialLength; m_vectorLength = initialCapacity; - m_storage->m_numValuesInVector = 0; m_storage->m_sparseValueMap = 0; m_storage->subclassData = 0; m_storage->reportedMapCapacity = 0; - JSValue* vector = m_storage->m_vector; - for (size_t i = 0; i < initialCapacity; ++i) - vector[i] = JSValue(); + if (creationMode == CreateCompact) { +#if CHECK_ARRAY_CONSISTENCY + m_storage->m_inCompactInitialization = !!initialCapacity; +#endif + m_storage->m_length = 0; + m_storage->m_numValuesInVector = initialCapacity; + } else { +#if CHECK_ARRAY_CONSISTENCY + m_storage->m_inCompactInitialization = false; +#endif + m_storage->m_length = initialLength; + m_storage->m_numValuesInVector = 0; + JSValue* vector = m_storage->m_vector; + for (size_t i = 0; i < initialCapacity; ++i) + vector[i] = JSValue(); + } checkConsistency(); @@ -175,6 +188,9 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list) m_storage->m_sparseValueMap = 0; m_storage->subclassData = 0; m_storage->reportedMapCapacity = 0; +#if CHECK_ARRAY_CONSISTENCY + m_storage->m_inCompactInitialization = false; +#endif size_t i = 0; ArgList::const_iterator end = list.end(); @@ -524,7 +540,12 @@ bool JSArray::increaseVectorLength(unsigned newLength) void JSArray::setLength(unsigned newLength) { - checkConsistency(); +#if CHECK_ARRAY_CONSISTENCY + if (!m_storage->m_inCompactInitialization) + checkConsistency(); + else + m_storage->m_inCompactInitialization = false; +#endif ArrayStorage* storage = m_storage; @@ -1045,7 +1066,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) if (JSValue value = m_storage->m_vector[i]) { ASSERT(i < m_storage->m_length); if (type != DestructorConsistencyCheck) - value->type(); // Likely to crash if the object was deallocated. + value.isUndefined(); // Likely to crash if the object was deallocated. ++numValuesInVector; } else { if (type == SortConsistencyCheck) @@ -1064,7 +1085,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) ASSERT(index <= MAX_ARRAY_INDEX); ASSERT(it->second); if (type != DestructorConsistencyCheck) - it->second->type(); // Likely to crash if the object was deallocated. + it->second.isUndefined(); // Likely to crash if the object was deallocated. } } } diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index f65f2bc..b6dd7cc 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -23,6 +23,8 @@ #include "JSObject.h" +#define CHECK_ARRAY_CONSISTENCY 0 + namespace JSC { typedef HashMap<unsigned, JSValue> SparseArrayValueMap; @@ -33,16 +35,29 @@ namespace JSC { SparseArrayValueMap* m_sparseValueMap; void* subclassData; // A JSArray subclass can use this to fill the vector lazily. size_t reportedMapCapacity; +#if CHECK_ARRAY_CONSISTENCY + bool m_inCompactInitialization; +#endif JSValue m_vector[1]; }; + // The CreateCompact creation mode is used for fast construction of arrays + // whose size and contents are known at time of creation. + // + // There are two obligations when using this mode: + // + // - uncheckedSetIndex() must be used when initializing the array. + // - setLength() must be called after initialization. + + enum ArrayCreationMode { CreateCompact, CreateInitialized }; + class JSArray : public JSObject { friend class JIT; friend class Walker; public: explicit JSArray(NonNullPassRefPtr<Structure>); - JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength); + JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength, ArrayCreationMode); JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); @@ -83,6 +98,15 @@ namespace JSC { x = v; } + void uncheckedSetIndex(unsigned i, JSValue v) + { + ASSERT(canSetIndex(i)); +#if CHECK_ARRAY_CONSISTENCY + ASSERT(m_storage->m_inCompactInitialization); +#endif + m_storage->m_vector[i] = v; + } + void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToRegisters(ExecState*, Register*, uint32_t); diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 1508750..065cbe1 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -136,11 +136,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , lexer(new Lexer(this)) , parser(new Parser) , interpreter(new Interpreter) -#if ENABLE(JIT) - , jitStubs(this) -#endif , heap(this) - , initializingLazyNumericCompareFunction(false) , head(0) , dynamicGlobalObject(0) , functionCodeBlockBeingReparsed(0) @@ -158,18 +154,28 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread startProfilerServerIfNeeded(); #endif #if ENABLE(JIT) && ENABLE(INTERPRETER) -#if PLATFORM(MAC) +#if PLATFORM(CF) CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); - m_canUseJIT = kCFBooleanTrue == canUseJIT; - CFRelease(canUseJIT); + if (canUseJIT) { + m_canUseJIT = kCFBooleanTrue == canUseJIT; + CFRelease(canUseJIT); + } else + m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); CFRelease(canUseJITKey); #elif OS(UNIX) - m_canUseJIT = !getenv("JSC_FORCE_INTERPRETER"); + m_canUseJIT = !getenv("JavaScriptCoreUseJIT"); #else m_canUseJIT = true; #endif #endif +#if ENABLE(JIT) +#if ENABLE(INTERPRETER) + if (m_canUseJIT) + m_canUseJIT = executableAllocator.isValid(); +#endif + jitStubs = new JITThunks(this); +#endif } JSGlobalData::~JSGlobalData() @@ -257,27 +263,14 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal() return sharedInstance; } -// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc. -const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec) -{ - if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) { - initializingLazyNumericCompareFunction = true; - RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0); - lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain())->instructions(); - initializingLazyNumericCompareFunction = false; - } - - return lazyNumericCompareFunction; -} - #if ENABLE(JIT) PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) { - return jitStubs.hostFunctionStub(this, function); + return jitStubs->hostFunctionStub(this, function); } PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) { - return jitStubs.hostFunctionStub(this, function, generator); + return jitStubs->hostFunctionStub(this, function, generator); } #endif diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index f3f6cba..23b6b21 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -167,21 +167,21 @@ namespace JSC { ExecutableAllocator executableAllocator; #endif -#if ENABLE(JIT) -#if ENABLE(INTERPRETER) - bool canUseJIT() { return m_canUseJIT; } -#endif +#if !ENABLE(JIT) + bool canUseJIT() { return false; } // interpreter only +#elif !ENABLE(INTERPRETER) + bool canUseJIT() { return true; } // jit only #else - bool canUseJIT() { return false; } + bool canUseJIT() { return m_canUseJIT; } #endif Lexer* lexer; Parser* parser; Interpreter* interpreter; #if ENABLE(JIT) - JITThunks jitStubs; + OwnPtr<JITThunks> jitStubs; MacroAssemblerCodePtr getCTIStub(ThunkGenerator generator) { - return jitStubs.ctiStub(this, generator); + return jitStubs->ctiStub(this, generator); } PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function); PassRefPtr<NativeExecutable> getHostFunction(NativeFunction function, ThunkGenerator generator); @@ -195,10 +195,6 @@ namespace JSC { ReturnAddressPtr exceptionLocation; #endif - const Vector<Instruction>& numericCompareFunction(ExecState*); - Vector<Instruction> lazyNumericCompareFunction; - bool initializingLazyNumericCompareFunction; - HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData; JSGlobalObject* head; diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index 09a92a1..115af87 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -457,7 +457,7 @@ namespace JSC { inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) { - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength, CreateInitialized); } inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue) diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index fa2a1e2..aff83e7 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -106,7 +106,7 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObje } RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) - : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1) + : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized) { RegExpConstructorPrivate* d = new RegExpConstructorPrivate; d->input = data->lastInput; diff --git a/JavaScriptCore/runtime/RegExpKey.h b/JavaScriptCore/runtime/RegExpKey.h index e5ab438..2bbdb07 100644 --- a/JavaScriptCore/runtime/RegExpKey.h +++ b/JavaScriptCore/runtime/RegExpKey.h @@ -76,13 +76,8 @@ struct RegExpKey { return flagsValue; } }; -} // namespace JSC - -namespace WTF { -template<typename T> struct DefaultHash; -template<typename T> struct RegExpHash; -inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b) +inline bool operator==(const RegExpKey& a, const RegExpKey& b) { if (a.flagsValue != b.flagsValue) return false; @@ -93,6 +88,12 @@ inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b) return equal(a.pattern.get(), b.pattern.get()); } +} // namespace JSC + +namespace WTF { +template<typename T> struct DefaultHash; +template<typename T> struct RegExpHash; + template<> struct RegExpHash<JSC::RegExpKey> { static unsigned hash(const JSC::RegExpKey& key) { return key.pattern->hash(); } static bool equal(const JSC::RegExpKey& a, const JSC::RegExpKey& b) { return a == b; } diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h index 0222a10..8a8741c 100644 --- a/JavaScriptCore/wtf/MathExtras.h +++ b/JavaScriptCore/wtf/MathExtras.h @@ -54,6 +54,14 @@ const double piDouble = M_PI; const float piFloat = static_cast<float>(M_PI); #endif +#ifndef M_PI_2 +const double piOverTwoDouble = 1.57079632679489661923; +const float piOverTwoFloat = 1.57079632679489661923f; +#else +const double piOverTwoDouble = M_PI_2; +const float piOverTwoFloat = static_cast<float>(M_PI_2); +#endif + #ifndef M_PI_4 const double piOverFourDouble = 0.785398163397448309616; const float piOverFourFloat = 0.785398163397448309616f; diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index 230637a..54fa14c 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -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(); } WARN_UNUSED_RETURN; + T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); } private: // adopting constructor @@ -152,13 +152,13 @@ namespace WTF { T* get() const { return m_ptr; } void clear(); - T* leakRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } WARN_UNUSED_RETURN; + T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; } 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; + T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); } private: mutable T* m_ptr; diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index 2500c56..4166ad9 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -944,7 +944,6 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ /* The JIT is tested & working on x86 Mac */ #elif CPU(X86) && PLATFORM(MAC) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 #elif CPU(ARM_THUMB2) && PLATFORM(IPHONE) #define ENABLE_JIT 1 /* The JIT is tested & working on Android */ @@ -960,16 +959,12 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define ENABLE_JIT 1 #elif CPU(X86) && OS(DARWIN) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 #elif CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100 #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 #elif CPU(X86) && OS(WINDOWS) && COMPILER(MSVC) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 #elif CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100 #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 #elif CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100 #define ENABLE_JIT 1 #elif CPU(ARM_TRADITIONAL) && OS(LINUX) @@ -978,7 +973,6 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define ENABLE_JIT 1 #elif CPU(MIPS) && OS(LINUX) #define ENABLE_JIT 1 - #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0 #endif #endif /* PLATFORM(QT) */ @@ -1138,4 +1132,11 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define WTF_USE_PLATFORM_STRATEGIES 1 #endif +/* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location. + Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy. + pre-emptive permission policy is enabled by default for all client-based implementations. */ +#if ENABLE(CLIENT_BASED_GEOLOCATION) +#define WTF_USE_PREEMPT_GEOLOCATION_PERMISSION 1 +#endif + #endif /* WTF_Platform_h */ diff --git a/JavaScriptCore/wtf/RetainPtr.h b/JavaScriptCore/wtf/RetainPtr.h index 2768be7..f5a027e 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; } WARN_UNUSED_RETURN; + PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; } PtrType operator->() const { return m_ptr; } diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h index a172e2c..244009f 100644 --- a/JavaScriptCore/wtf/text/StringImpl.h +++ b/JavaScriptCore/wtf/text/StringImpl.h @@ -257,37 +257,6 @@ public: memcpy(destination, source, numCharacters * sizeof(UChar)); } - PassRefPtr<StringImpl> copyStringWithoutBOMs(bool definitelyHasBOMs, bool& hasBOMs) - { - static const UChar byteOrderMark = 0xFEFF; - size_t i = 0; - if (!definitelyHasBOMs) { - hasBOMs = false; - // ECMA-262 calls for stripping all Cf characters, but we only strip BOM characters. - // See <https://bugs.webkit.org/show_bug.cgi?id=4931> for details. - for (; i < m_length; i++) { - if (UNLIKELY(m_data[i] == byteOrderMark)) { - hasBOMs = true; - break; - } - } - if (!hasBOMs) - return this; - } - Vector<UChar> result; - result.reserveInitialCapacity(m_length); - size_t firstBOM = i; - i = 0; - for (; i < firstBOM; i++) - result.append(m_data[i]); - for (; i < m_length; i++) { - UChar c = m_data[i]; - if (c != byteOrderMark) - result.append(c); - } - return StringImpl::adopt(result); - } - // Returns a StringImpl suitable for use on another thread. PassRefPtr<StringImpl> crossThreadString(); // Makes a deep copy. Helpful only if you need to use a String on another thread diff --git a/JavaScriptCore/yarr/RegexJIT.cpp b/JavaScriptCore/yarr/RegexJIT.cpp index 68d3803..609417f 100644 --- a/JavaScriptCore/yarr/RegexJIT.cpp +++ b/JavaScriptCore/yarr/RegexJIT.cpp @@ -1489,7 +1489,7 @@ void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const return; numSubpatterns = pattern.m_numSubpatterns; - if (!pattern.m_containsBackreferences) { + if (!pattern.m_containsBackreferences && globalData->canUseJIT()) { RegexGenerator generator(pattern); generator.compile(globalData, jitObject); if (!generator.shouldFallBack()) |