summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore')
-rw-r--r--Source/JavaScriptCore/API/JSClassRef.cpp19
-rw-r--r--Source/JavaScriptCore/ChangeLog374
-rw-r--r--Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig3
-rw-r--r--Source/JavaScriptCore/Configurations/Version.xcconfig4
-rw-r--r--Source/JavaScriptCore/GNUmakefile.am2
-rw-r--r--Source/JavaScriptCore/GNUmakefile.list.am5
-rwxr-xr-xSource/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def3
-rw-r--r--Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj8
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp8
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h3
-rw-r--r--Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp9
-rw-r--r--Source/JavaScriptCore/dfg/DFGAbstractState.cpp9
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp14
-rw-r--r--Source/JavaScriptCore/dfg/DFGCapabilities.h1
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.cpp34
-rw-r--r--Source/JavaScriptCore/dfg/DFGOperations.h3
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp30
-rw-r--r--Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp30
-rw-r--r--Source/JavaScriptCore/heap/CopiedSpace.cpp11
-rw-r--r--Source/JavaScriptCore/heap/Heap.cpp3
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.cpp56
-rw-r--r--Source/JavaScriptCore/heap/MarkStack.h19
-rw-r--r--Source/JavaScriptCore/heap/MarkedAllocator.cpp38
-rw-r--r--Source/JavaScriptCore/heap/MarkedAllocator.h2
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp21
-rw-r--r--Source/JavaScriptCore/jit/ExecutableAllocator.h1
-rw-r--r--Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp14
-rw-r--r--Source/JavaScriptCore/jit/JIT.cpp1
-rw-r--r--Source/JavaScriptCore/jit/JIT.h1
-rw-r--r--Source/JavaScriptCore/jit/JITInlineMethods.h3
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes.cpp22
-rw-r--r--Source/JavaScriptCore/jit/JITOpcodes32_64.cpp24
-rw-r--r--Source/JavaScriptCore/jit/JITStubs.cpp11
-rw-r--r--Source/JavaScriptCore/llint/LLIntSlowPaths.cpp22
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm27
-rw-r--r--Source/JavaScriptCore/llint/LowLevelInterpreter64.asm26
-rw-r--r--Source/JavaScriptCore/parser/ASTBuilder.h44
-rw-r--r--Source/JavaScriptCore/parser/NodeInfo.h4
-rw-r--r--Source/JavaScriptCore/parser/Nodes.cpp40
-rw-r--r--Source/JavaScriptCore/parser/Nodes.h88
-rw-r--r--Source/JavaScriptCore/parser/Parser.cpp54
-rw-r--r--Source/JavaScriptCore/parser/Parser.h118
-rw-r--r--Source/JavaScriptCore/parser/SourceProviderCacheItem.h4
-rw-r--r--Source/JavaScriptCore/parser/SyntaxChecker.h1
-rw-r--r--Source/JavaScriptCore/runtime/Executable.cpp6
-rw-r--r--Source/JavaScriptCore/runtime/Executable.h18
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.cpp12
-rw-r--r--Source/JavaScriptCore/runtime/JSFunction.h15
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.cpp4
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h46
-rw-r--r--Source/JavaScriptCore/runtime/JSString.h10
-rw-r--r--Source/JavaScriptCore/runtime/Structure.cpp7
-rw-r--r--Source/JavaScriptCore/runtime/Structure.h2
53 files changed, 837 insertions, 497 deletions
diff --git a/Source/JavaScriptCore/API/JSClassRef.cpp b/Source/JavaScriptCore/API/JSClassRef.cpp
index 08fa5c5e0..5f67fc37e 100644
--- a/Source/JavaScriptCore/API/JSClassRef.cpp
+++ b/Source/JavaScriptCore/API/JSClassRef.cpp
@@ -209,13 +209,16 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec)
OpaqueJSClassContextData& jsClassData = contextData(exec);
- if (!jsClassData.cachedPrototype) {
- // Recursive, but should be good enough for our purposes
- jsClassData.cachedPrototype = PassWeak<JSObject>(JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction
- if (parentClass) {
- if (JSObject* prototype = parentClass->prototype(exec))
- jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
- }
+ if (JSObject* prototype = jsClassData.cachedPrototype.get())
+ return prototype;
+
+ // Recursive, but should be good enough for our purposes
+ JSObject* prototype = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
+ if (parentClass) {
+ if (JSObject* parentPrototype = parentClass->prototype(exec))
+ prototype->setPrototype(exec->globalData(), parentPrototype);
}
- return jsClassData.cachedPrototype.get();
+
+ jsClassData.cachedPrototype = PassWeak<JSObject>(prototype, 0);
+ return prototype;
}
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index 0774438d1..38f229734 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,377 @@
+2012-05-10 Gavin Barraclough <barraclough@apple.com>
+
+ Remove op_get_callee
+
+ Rubber stamped by Geoff Garen.
+
+ This is now redundant.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.h:
+ (JSC::DFG::canCompileOpcode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+
+2012-05-10 Gavin Barraclough <barraclough@apple.com>
+
+ Cache inheritorID on JSFunction
+ https://bugs.webkit.org/show_bug.cgi?id=85853
+
+ Reviewed by Geoff Garen & Filip Pizlo.
+
+ An object's prototype is indicated via its structure. To create an otherwise
+ empty object with object A as its prototype, we require a structure with its
+ prototype set to point to A. We wish to use this same structure for all empty
+ objects created with a prototype of A, so we presently store this structure as
+ a property of A, known as the inheritorID.
+
+ When a function F is invoked as a constructor, where F has a property 'prototype'
+ set to point to A, in order to create the 'this' value for the constructor to
+ use the following steps are taken:
+ - the 'prototype' proptery of F is read, via a regular [[Get]] access.
+ - the inheritorID internal property of the prototype is read.
+ - a new, empty object is constructed with its structure set to point to inheritorID.
+
+ There are two drawbacks to the current approach:
+ - it requires that every object has an inheritorID field.
+ - it requires a [[Get]] access on every constructor call to access the 'prototype' property.
+
+ Instead, switch to caching a copy of the inheritorID on the function. Constructor
+ calls now only need read the internal property from the callee, saving a [[Get]].
+ This also means that JSObject::m_inheritorID is no longer commonly read, and in a
+ future patch we can move to storing this in a more memory efficient fashion.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::BytecodeGenerator):
+ * dfg/DFGAbstractState.cpp:
+ (JSC::DFG::AbstractState::execute):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGNodeType.h:
+ (DFG):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JITInlineMethods.h:
+ (JSC::JIT::emitAllocateJSFunction):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_create_this):
+ (JSC::JIT::emitSlow_op_create_this):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_create_this):
+ (JSC::JIT::emitSlow_op_create_this):
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::JSFunction):
+ (JSC::JSFunction::cacheInheritorID):
+ (JSC):
+ (JSC::JSFunction::put):
+ (JSC::JSFunction::defineOwnProperty):
+ * runtime/JSFunction.h:
+ (JSC::JSFunction::cachedInheritorID):
+ (JSFunction):
+ (JSC::JSFunction::offsetOfCachedInheritorID):
+
+2012-05-10 Michael Saboff <msaboff@apple.com>
+
+ Enh: Hash Const JSString in Backing Stores to Save Memory
+ https://bugs.webkit.org/show_bug.cgi?id=86024
+
+ Reviewed by Filip Pizlo.
+
+ During garbage collection, each marking thread keeps a HashMap of
+ strings. While visiting via MarkStack::copyAndAppend(), we check to
+ see if the string we are visiting is already in the HashMap. If not
+ we add it. If so, we change the reference to the current string we're
+ visiting to the prior string.
+
+ To somewhat reduce the performance impact of this change, if a string
+ is unique at the end of a marking it will not be checked during further
+ GC phases. In some cases this won't catch all duplicates, but we are
+ trying to catch the growth of duplicate strings.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::markRoots):
+ * heap/MarkStack.cpp:
+ (JSC::MarkStackThreadSharedData::resetChildren): New method called by the
+ main thread to reset the slave threads. This is primarily done to
+ clear the m_uniqueStrings HashMap.
+ (JSC):
+ (JSC::MarkStackThreadSharedData::markingThreadMain):
+ (JSC::MarkStackThreadSharedData::markingThreadStartFunc):
+ (JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
+ (JSC::MarkStackThreadSharedData::reset):
+ (JSC::MarkStack::reset): Added call to clear m_uniqueStrings.
+ (JSC::MarkStack::internalAppend): New method that performs the hash consting.
+ (JSC::SlotVisitor::copyAndAppend): Changed to call the new hash consting
+ internalAppend()
+ * heap/MarkStack.h:
+ (MarkStackThreadSharedData):
+ (MarkStack):
+ (JSC::MarkStack::sharedData):
+ * runtime/JSString.h:
+ (JSString): Added m_isHashConstSingleton flag, accessors for the flag and
+ code to initialize the flag.
+ (JSC::JSString::finishCreation):
+ (JSC::JSString::isHashConstSingleton):
+ (JSC::JSString::clearHashConstSingleton):
+ (JSC::JSString::setHashConstSingleton):
+ (JSC::JSRopeString::finishCreation):
+
+2012-05-09 Filip Pizlo <fpizlo@apple.com>
+
+ JIT memory allocator is not returning memory to the OS on Darwin
+ https://bugs.webkit.org/show_bug.cgi?id=86047
+ <rdar://problem/11414948>
+
+ Reviewed by Geoff Garen.
+
+ Work around the problem by using a different madvise() flag, but only for the JIT memory
+ allocator. Also put in ASSERTs that the call is actually working.
+
+ * jit/ExecutableAllocatorFixedVMPool.cpp:
+ (JSC::FixedVMPoolExecutableAllocator::notifyNeedPage):
+ (JSC::FixedVMPoolExecutableAllocator::notifyPageIsFree):
+
+2012-05-09 Filip Pizlo <fpizlo@apple.com>
+
+ It should be possible to get useful debug logging from the JIT memory allocator
+ https://bugs.webkit.org/show_bug.cgi?id=86042
+
+ Reviewed by Geoff Garen.
+
+ * jit/ExecutableAllocator.h:
+
+2012-05-09 Gavin Barraclough <barraclough@apple.com>
+
+ GC race condition in OpaqueJSClass::prototype
+ https://bugs.webkit.org/show_bug.cgi?id=86034
+
+ Build fix.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+ - Eeeep, landed bad version of patch!
+
+2012-05-09 Gavin Barraclough <barraclough@apple.com>
+
+ GC race condition in OpaqueJSClass::prototype
+ https://bugs.webkit.org/show_bug.cgi?id=86034
+
+ Reviewed by Filip Pizlo.
+
+ The bug here is basically:
+ if (weakref) weakref->method()
+ where a GC may occur between the if & the method call.
+
+ * API/JSClassRef.cpp:
+ (OpaqueJSClass::prototype):
+
+2012-05-09 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ CopiedSpace does not add pinned blocks back to the to-space filter
+ https://bugs.webkit.org/show_bug.cgi?id=86011
+
+ Reviewed by Geoffrey Garen.
+
+ After a collection has finished, we go through the blocks in from-space
+ and move any of them that are pinned into to-space. At the beginning of
+ collection, we reset the to-space block filter that is used during
+ conservative scanning and add back the blocks that are filled during the
+ collection. However, we neglect to add back those blocks that are moved
+ from from-space to to-space, which can cause the conservative scan to
+ think that some pinned items are not actually in CopiedSpace.
+
+ * heap/CopiedSpace.cpp:
+ (JSC::CopiedSpace::doneCopying): Add the pinned blocks back to the
+ to-space filter. Also added a comment and assert for future readers that
+ indicates that it's okay that we don't also add the block to the
+ to-space block set since it was never removed.
+
+
+2012-05-09 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Use independent version numbers for public libraries
+ https://bugs.webkit.org/show_bug.cgi?id=85984
+
+ Reviewed by Gustavo Noronha Silva.
+
+ * GNUmakefile.am: Use LIBJAVASCRIPTCOREGTK_VERSION for library
+ version.
+
+2012-05-09 Carlos Garcia Campos <cgarcia@igalia.com>
+
+ [GTK] Do not install JavaScriptCore platform-specific headers
+ https://bugs.webkit.org/show_bug.cgi?id=85983
+
+ Reviewed by Gustavo Noronha Silva.
+
+ JavaScriptCore.h includes JSStringRefCF.h unconditionally. It was
+ renamed to JavaScript.h in r29234 and it still exists for
+ compatibility with mac and windows users.
+
+ * GNUmakefile.list.am: Remove JavaScriptCore.h, JSStringRefCF.h
+ and JSStringRefBSTR.h from the sources and headers list.
+
+2012-05-08 Gavin Barraclough <barraclough@apple.com>
+
+ ROLLING OUT r114255
+
+ GC in the middle of JSObject::allocatePropertyStorage can cause badness
+ https://bugs.webkit.org/show_bug.cgi?id=83839
+
+ Reviewed by nobody.
+
+ This breaks the world, with COLLECT_ON_EVERY_ALLOCATION enabled.
+
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+ * jit/JITStubs.cpp:
+ (JSC::DEFINE_STUB_FUNCTION):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::allocatePropertyStorage):
+ * runtime/JSObject.h:
+ (JSObject):
+ (JSC::JSObject::isUsingInlineStorage):
+ (JSC):
+ (JSC::JSObject::putDirectInternal):
+ (JSC::JSObject::putDirectWithoutTransition):
+ (JSC::JSObject::transitionTo):
+ * runtime/Structure.cpp:
+ (JSC):
+ * runtime/Structure.h:
+ (JSC::Structure::didTransition):
+
+2012-05-08 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Heap should not continually allocate new pages in steady state
+ https://bugs.webkit.org/show_bug.cgi?id=85936
+
+ Reviewed by Geoff Garen.
+
+ Currently, in steady state (i.e. a constant amount of live GC
+ memory with a constant rate of allocation) assuming we've just
+ finished a collection with X live blocks in CopiedSpace, we
+ increase our working set by X blocks in CopiedSpace with each
+ collection we perform. This is due to the fact that we allocate
+ until we run out of free blocks to use in the Heap before we
+ consider whether we should run a collection.
+
+ In the longer term, this issue will be mostly resolved by
+ implementing quick release for the CopiedSpace. In the shorter
+ term, we should change our policy to check whether we should
+ allocate before trying to use a free block from the Heap. We
+ can change our policy to something more appropriate once we
+ have implemented quick release.
+
+ This change should also have the convenient side effect of
+ reducing the variance in GC-heavy tests (e.g. v8-splay) due
+ to fact that we are doing less VM allocation during copying
+ collection. Overall, this patch is performance neutral across
+ the benchmarks we track.
+
+ * heap/CopiedSpace.cpp:
+ (JSC::CopiedSpace::getFreshBlock): Shuffle the request from the BlockAllocator
+ around so that we only do it if the block request must succeed
+ i.e. after we've already checked whether we should do a collection.
+ * heap/MarkedAllocator.cpp:
+ (JSC::MarkedAllocator::allocateSlowCase): Ditto.
+ (JSC::MarkedAllocator::allocateBlock): We no longer have a failure mode in this
+ function because by the time we've called it, we've already checked whether we
+ should run a collection so there's no point in returning null.
+ * heap/MarkedAllocator.h: Removing old arguments from function declaration.
+ (MarkedAllocator):
+
+2012-05-08 Gavin Barraclough <barraclough@apple.com>
+
+ SIGFPE on divide in classic interpreter
+ https://bugs.webkit.org/show_bug.cgi?id=85917
+
+ Rubber stamped by Oliver Hunt.
+
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ - check for divisor of -1.
+
+2012-05-07 Oliver Hunt <oliver@apple.com>
+
+ Rolling out r110287
+
+ RS=Filip Pizlo
+
+ r110287 was meant to be refactoring only, but changed behavior
+ enough to break some websites, including qq.com.
+
+2012-05-07 Andy Estes <aestes@apple.com>
+
+ ENABLE_IFRAME_SEAMLESS should be part of FEATURE_DEFINES.
+
+ * Configurations/FeatureDefines.xcconfig:
+
+2012-05-07 Oliver Hunt <oliver@apple.com>
+
+ Fix release build.
+
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+
+2012-05-07 Oliver Hunt <oliver@apple.com>
+
+ LLInt doesn't check for Ropes when performing a character switch
+ https://bugs.webkit.org/show_bug.cgi?id=85837
+
+ Reviewed by Filip Pizlo.
+
+ Make LLint check if the scrutinee of a char switch is a rope, and if
+ so fall back to a slow case.
+
+ * llint/LLIntSlowPaths.cpp:
+ (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+ (LLInt):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+
+2012-05-07 Eric Seidel <eric@webkit.org>
+
+ Add ENABLE_IFRAME_SEAMLESS so Apple can turn off SEAMLESS if needed
+ https://bugs.webkit.org/show_bug.cgi?id=85822
+
+ Reviewed by Adam Barth.
+
+ * Configurations/FeatureDefines.xcconfig:
+
2012-05-05 Gavin Barraclough <barraclough@apple.com>
Remove TrustedImm32::m_isPointer
diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
index 2dc145f36..91d688b53 100644
--- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
+++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig
@@ -54,6 +54,7 @@ ENABLE_GEOLOCATION = ENABLE_GEOLOCATION;
ENABLE_HIGH_DPI_CANVAS = ENABLE_HIGH_DPI_CANVAS;
ENABLE_ICONDATABASE = $(ENABLE_ICONDATABASE_$(REAL_PLATFORM_NAME));
ENABLE_ICONDATABASE_macosx = ENABLE_ICONDATABASE;
+ENABLE_IFRAME_SEAMLESS = ENABLE_IFRAME_SEAMLESS;
ENABLE_INDEXED_DATABASE = ;
ENABLE_INPUT_SPEECH = ;
ENABLE_INPUT_TYPE_COLOR = ;
@@ -121,4 +122,4 @@ ENABLE_WEB_TIMING = ;
ENABLE_WORKERS = ENABLE_WORKERS;
ENABLE_XSLT = ENABLE_XSLT;
-FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT);
+FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_IFRAME_SEAMLESS) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT);
diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig
index d7e12df22..9760c9ada 100644
--- a/Source/JavaScriptCore/Configurations/Version.xcconfig
+++ b/Source/JavaScriptCore/Configurations/Version.xcconfig
@@ -21,8 +21,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-MAJOR_VERSION = 536;
-MINOR_VERSION = 11;
+MAJOR_VERSION = 537;
+MINOR_VERSION = 1;
TINY_VERSION = 0;
FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION);
diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am
index e84528763..1ad42fd1c 100644
--- a/Source/JavaScriptCore/GNUmakefile.am
+++ b/Source/JavaScriptCore/GNUmakefile.am
@@ -7,7 +7,7 @@ lib_LTLIBRARIES += \
# https://bugs.webkit.org/show_bug.cgi?id=27551 is fixed we'll able to
# simply rely on the usual symbol visibility flags.
libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LDFLAGS = \
- -version-info @LIBWEBKITGTK_VERSION@ \
+ -version-info @LIBJAVASCRIPTCOREGTK_VERSION@ \
$(no_undefined)
nodist_EXTRA_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am
index 1b59db10c..7b3167aa1 100644
--- a/Source/JavaScriptCore/GNUmakefile.list.am
+++ b/Source/JavaScriptCore/GNUmakefile.list.am
@@ -3,11 +3,8 @@ javascriptcore_h_api += \
Source/JavaScriptCore/API/JSContextRef.h \
Source/JavaScriptCore/API/JSObjectRef.h \
Source/JavaScriptCore/API/JSStringRef.h \
- Source/JavaScriptCore/API/JSStringRefBSTR.h \
- Source/JavaScriptCore/API/JSStringRefCF.h \
Source/JavaScriptCore/API/JSValueRef.h \
Source/JavaScriptCore/API/JavaScript.h \
- Source/JavaScriptCore/API/JavaScriptCore.h \
Source/JavaScriptCore/API/WebKitAvailability.h
javascriptcore_built_nosources += \
@@ -273,13 +270,11 @@ javascriptcore_sources += \
Source/JavaScriptCore/debugger/Debugger.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APIShims.h \
- Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScriptCore.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScript.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSBase.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSContextRef.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRef.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSRetainPtr.h \
- Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRefCF.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRef.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSValueRef.h \
Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/OpaqueJSString.h \
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index bae50e204..951f85186 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -62,6 +62,7 @@ EXPORTS
?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PAVStringImpl@4@@Z
?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVJSGlobalData@2@PAVStringImpl@4@@Z
?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z
+ ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z
?allocateSlowCase@MarkedAllocator@JSC@@AAEPAXXZ
?append@StringBuilder@WTF@@QAEXPBEI@Z
?append@StringBuilder@WTF@@QAEXPB_WI@Z
@@ -209,7 +210,6 @@ EXPORTS
?globalExec@JSGlobalObject@JSC@@QAEPAVExecState@2@XZ
?globalObjectCount@Heap@JSC@@QAEIXZ
?grow@HandleSet@JSC@@AAEXXZ
- ?growPropertyStorage@JSObject@JSC@@QAEPAV?$WriteBarrierBase@W4Unknown@JSC@@@2@AAVJSGlobalData@2@II@Z
?hasInstance@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VJSValue@2@2@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@ABVIdentifier@2@@Z
?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z
@@ -320,7 +320,6 @@ EXPORTS
?stopProfiling@Profiler@JSC@@QAE?AV?$PassRefPtr@VProfile@JSC@@@WTF@@PAVExecState@2@ABVUString@2@@Z
?stopSampling@JSGlobalData@JSC@@QAEXXZ
?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z
- ?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ
?symbolTableGet@JSVariableObject@JSC@@IAE_NABVIdentifier@2@AAVPropertyDescriptor@2@@Z
?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z
?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ
diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index d5cf8dedc..c5a5b63be 100644
--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -1041,6 +1041,9 @@
86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT64.cpp; path = dfg/DFGSpeculativeJIT64.cpp; sourceTree = "<group>"; };
869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; sourceTree = "<group>"; };
869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; };
+ 86A054461556451B00445157 /* LowLevelInterpreter.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter.asm; path = llint/LowLevelInterpreter.asm; sourceTree = "<group>"; };
+ 86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter32_64.asm; path = llint/LowLevelInterpreter32_64.asm; sourceTree = "<group>"; };
+ 86A054481556451B00445157 /* LowLevelInterpreter64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = LowLevelInterpreter64.asm; path = llint/LowLevelInterpreter64.asm; sourceTree = "<group>"; };
86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; };
86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
@@ -1430,7 +1433,6 @@
45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
A767FF9F14F4502900789059 /* JSCTypedArrayStubs.h */,
F68EBB8C0255D4C601FF60F7 /* config.h */,
- 0F46809C14BA7F4D00BFE272 /* llint */,
1432EBD70A34CAD400717B9F /* API */,
9688CB120ED12B4E001D649F /* assembler */,
969A078F0ED1D3AE00F1F681 /* bytecode */,
@@ -1440,6 +1442,7 @@
142E312A134FF0A600AFADB5 /* heap */,
1429D77A0ED20D7300B89619 /* interpreter */,
1429D92C0ED22D7000B89619 /* jit */,
+ 0F46809C14BA7F4D00BFE272 /* llint */,
7E39D8370EC3A388003AF11A /* parser */,
95AB831A0DA42C6900BC83F3 /* profiler */,
7EF6E0BB0EB7A1EC0079AFAF /* runtime */,
@@ -1489,6 +1492,9 @@
0F46809F14BA7F8200BFE272 /* LLIntSlowPaths.cpp */,
0F4680A014BA7F8200BFE272 /* LLIntSlowPaths.h */,
0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */,
+ 86A054461556451B00445157 /* LowLevelInterpreter.asm */,
+ 86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */,
+ 86A054481556451B00445157 /* LowLevelInterpreter64.asm */,
);
name = llint;
sourceTree = "<group>";
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 7b828acab..6a4d073bf 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -512,15 +512,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
dataLog("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data());
break;
}
- case op_get_callee: {
- int r0 = (++it)->u.operand;
- dataLog("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
- break;
- }
case op_create_this: {
int r0 = (++it)->u.operand;
- int r1 = (++it)->u.operand;
- dataLog("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+ dataLog("[%4d] create_this %s\n", location, registerName(exec, r0).data());
break;
}
case op_convert_this: {
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index a564de2da..ebf15bbd4 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -42,8 +42,7 @@ namespace JSC {
macro(op_create_activation, 2) \
macro(op_init_lazy_reg, 2) \
macro(op_create_arguments, 2) \
- macro(op_create_this, 3) \
- macro(op_get_callee, 2) \
+ macro(op_create_this, 2) \
macro(op_convert_this, 2) \
\
macro(op_new_object, 2) \
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index a520a4c78..b12bf40dc 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -442,17 +442,8 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN
preserveLastVar();
if (isConstructor()) {
- RefPtr<RegisterID> func = newTemporary();
- RefPtr<RegisterID> funcProto = newTemporary();
-
- emitOpcode(op_get_callee);
- instructions().append(func->index());
- // Load prototype.
- emitGetById(funcProto.get(), func.get(), globalData()->propertyNames->prototype);
-
emitOpcode(op_create_this);
instructions().append(m_thisRegister.index());
- instructions().append(funcProto->index());
} else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
emitOpcode(op_convert_this);
instructions().append(m_thisRegister.index());
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 6df40ca6f..3eb5463a7 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -774,19 +774,16 @@ bool AbstractState::execute(unsigned indexInBlock)
destination.merge(PredictObjectOther);
break;
}
-
+
case CreateThis: {
- Node& child = m_graph[node.child1()];
AbstractValue& source = forNode(node.child1());
AbstractValue& destination = forNode(nodeIndex);
- if (child.shouldSpeculateFinalObject())
- source.filter(PredictFinalObject);
-
+ source.filter(PredictFunction);
destination.set(PredictFinalObject);
break;
}
-
+
case NewObject:
forNode(nodeIndex).set(m_codeBlock->globalObjectFor(node.codeOrigin)->emptyObjectStructure());
m_haveStructures = true;
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 7a2d7bdee..cc756c61e 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -1534,8 +1534,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_create_this: {
- NodeIndex op1 = get(currentInstruction[2].u.operand);
- set(currentInstruction[1].u.operand, addToGraph(CreateThis, op1));
+ if (m_inlineStackTop->m_inlineCallFrame)
+ set(currentInstruction[1].u.operand, addToGraph(CreateThis, getDirect(m_inlineStackTop->m_calleeVR)));
+ else
+ set(currentInstruction[1].u.operand, addToGraph(CreateThis, addToGraph(GetCallee)));
NEXT_OPCODE(op_create_this);
}
@@ -1565,14 +1567,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_new_regexp);
}
- case op_get_callee: {
- if (m_inlineStackTop->m_inlineCallFrame)
- set(currentInstruction[1].u.operand, getDirect(m_inlineStackTop->m_calleeVR));
- else
- set(currentInstruction[1].u.operand, addToGraph(GetCallee));
- NEXT_OPCODE(op_get_callee);
- }
-
// === Bitwise operations ===
case op_bitand: {
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h
index b807979ba..8aae85ef7 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.h
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h
@@ -73,7 +73,6 @@ inline bool canCompileOpcode(OpcodeID opcodeID)
case op_enter:
case op_convert_this:
case op_create_this:
- case op_get_callee:
case op_bitand:
case op_bitor:
case op_bitxor:
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp
index 0e6e2f972..dfaf5dfe8 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -209,39 +209,17 @@ EncodedJSValue DFG_OPERATION operationConvertThis(ExecState* exec, EncodedJSValu
return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
}
-inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constructor)
-{
-#if !ASSERT_DISABLED
- ConstructData constructData;
- ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
-#endif
-
- JSGlobalData& globalData = exec->globalData();
- NativeCallFrameTracer tracer(&globalData, exec);
-
- Structure* structure;
- if (prototype->isObject())
- structure = asObject(prototype)->inheritorID(globalData);
- else
- structure = constructor->scope()->globalObject->emptyObjectStructure();
-
- return constructEmptyObject(exec, structure);
-}
-
-JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype)
+JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* constructor)
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
- return createThis(exec, prototype, jsCast<JSFunction*>(exec->callee()));
-}
-
-JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor)
-{
- JSGlobalData* globalData = &exec->globalData();
- NativeCallFrameTracer tracer(globalData, exec);
+#if !ASSERT_DISABLED
+ ConstructData constructData;
+ ASSERT(jsCast<JSFunction*>(constructor)->methodTable()->getConstructData(jsCast<JSFunction*>(constructor), constructData) == ConstructTypeJS);
+#endif
- return createThis(exec, prototype, jsCast<JSFunction*>(constructor));
+ return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->cachedInheritorID(exec));
}
JSCell* DFG_OPERATION operationNewObject(ExecState* exec)
diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h
index 52e99cb95..601ed7665 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -97,8 +97,7 @@ typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*);
// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
JSCell* DFG_OPERATION operationNewObject(ExecState*);
-JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* encodedOp1);
-JSCell* DFG_OPERATION operationCreateThisInlined(ExecState*, JSCell* encodedOp1, JSCell* constructor);
+JSCell* DFG_OPERATION operationCreateThis(ExecState*, JSCell* constructor);
EncodedJSValue DFG_OPERATION operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
EncodedJSValue DFG_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index c156e81d0..05c418d1e 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -3029,32 +3029,17 @@ void SpeculativeJIT::compile(Node& node)
// then we speculate because we want to get recompiled if it isn't (since
// otherwise we'd start taking slow path a lot).
- SpeculateCellOperand proto(this, node.child1());
+ SpeculateCellOperand callee(this, node.child1());
GPRTemporary result(this);
GPRTemporary scratch(this);
- GPRReg protoGPR = proto.gpr();
+ GPRReg calleeGPR = callee.gpr();
GPRReg resultGPR = result.gpr();
GPRReg scratchGPR = scratch.gpr();
- proto.use();
-
+ // Load the inheritorID. If the inheritorID is not set, go to slow path.
+ m_jit.loadPtr(MacroAssembler::Address(calleeGPR, JSFunction::offsetOfCachedInheritorID()), scratchGPR);
MacroAssembler::JumpList slowPath;
-
- // Need to verify that the prototype is an object. If we have reason to believe
- // that it's a FinalObject then we speculate on that directly. Otherwise we
- // do the slow (structure-based) check.
- if (at(node.child1()).shouldSpeculateFinalObject()) {
- if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
- } else {
- m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
- slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
- }
-
- // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
- // use to refer to that prototype). If the inheritorID is not set, go to slow path.
- m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
@@ -3064,15 +3049,12 @@ void SpeculativeJIT::compile(Node& node)
slowPath.link(&m_jit);
silentSpillAllRegisters(resultGPR);
- if (node.codeOrigin.inlineCallFrame)
- callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
- else
- callOperation(operationCreateThis, resultGPR, protoGPR);
+ callOperation(operationCreateThis, resultGPR, calleeGPR);
silentFillAllRegisters(resultGPR);
done.link(&m_jit);
- cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ cellResult(resultGPR, m_compileIndex);
break;
}
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index a46f8f262..08e7d966d 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -3053,32 +3053,17 @@ void SpeculativeJIT::compile(Node& node)
// then we speculate because we want to get recompiled if it isn't (since
// otherwise we'd start taking slow path a lot).
- SpeculateCellOperand proto(this, node.child1());
+ SpeculateCellOperand callee(this, node.child1());
GPRTemporary result(this);
GPRTemporary scratch(this);
- GPRReg protoGPR = proto.gpr();
+ GPRReg calleeGPR = callee.gpr();
GPRReg resultGPR = result.gpr();
GPRReg scratchGPR = scratch.gpr();
- proto.use();
-
+ // Load the inheritorID. If the inheritorID is not set, go to slow path.
+ m_jit.loadPtr(MacroAssembler::Address(calleeGPR, JSFunction::offsetOfCachedInheritorID()), scratchGPR);
MacroAssembler::JumpList slowPath;
-
- // Need to verify that the prototype is an object. If we have reason to believe
- // that it's a FinalObject then we speculate on that directly. Otherwise we
- // do the slow (structure-based) check.
- if (at(node.child1()).shouldSpeculateFinalObject()) {
- if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
- } else {
- m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
- slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
- }
-
- // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
- // use to refer to that prototype). If the inheritorID is not set, go to slow path.
- m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
@@ -3088,15 +3073,12 @@ void SpeculativeJIT::compile(Node& node)
slowPath.link(&m_jit);
silentSpillAllRegisters(resultGPR);
- if (node.codeOrigin.inlineCallFrame)
- callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
- else
- callOperation(operationCreateThis, resultGPR, protoGPR);
+ callOperation(operationCreateThis, resultGPR, calleeGPR);
silentFillAllRegisters(resultGPR);
done.link(&m_jit);
- cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
+ cellResult(resultGPR, m_compileIndex);
break;
}
diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp
index 063ea65a2..d52c4e756 100644
--- a/Source/JavaScriptCore/heap/CopiedSpace.cpp
+++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp
@@ -183,6 +183,9 @@ void CopiedSpace::doneCopying()
CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->removeHead());
if (block->m_isPinned) {
block->m_isPinned = false;
+ // We don't add the block to the toSpaceSet because it was never removed.
+ ASSERT(m_toSpaceSet.contains(block));
+ m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
m_toSpace->push(block);
continue;
}
@@ -212,10 +215,10 @@ void CopiedSpace::doneCopying()
CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, CopiedBlock** outBlock)
{
CopiedBlock* block = 0;
- if (HeapBlock* heapBlock = m_heap->blockAllocator().allocate())
- block = new (NotNull, heapBlock) CopiedBlock(heapBlock->m_allocation);
- else if (allocationEffort == AllocationMustSucceed) {
- if (!allocateNewBlock(&block)) {
+ if (allocationEffort == AllocationMustSucceed) {
+ if (HeapBlock* heapBlock = m_heap->blockAllocator().allocate())
+ block = new (NotNull, heapBlock) CopiedBlock(heapBlock->m_allocation);
+ else if (!allocateNewBlock(&block)) {
*outBlock = 0;
ASSERT_NOT_REACHED();
return false;
diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp
index d0dbc3172..d43ec1242 100644
--- a/Source/JavaScriptCore/heap/Heap.cpp
+++ b/Source/JavaScriptCore/heap/Heap.cpp
@@ -656,6 +656,9 @@ void Heap::markRoots(bool fullGC)
visitor.doneCopying();
visitor.reset();
m_sharedData.reset();
+#if ENABLE(PARALLEL_GC)
+ m_sharedData.resetChildren();
+#endif
m_storageSpace.doneCopying();
m_operationInProgress = NoOperation;
diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp
index cf6e3513c..785444e55 100644
--- a/Source/JavaScriptCore/heap/MarkStack.cpp
+++ b/Source/JavaScriptCore/heap/MarkStack.cpp
@@ -36,6 +36,7 @@
#include "JSObject.h"
#include "ScopeChain.h"
#include "Structure.h"
+#include "UString.h"
#include "WriteBarrier.h"
#include <wtf/MainThread.h>
@@ -218,17 +219,24 @@ void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other)
}
#if ENABLE(PARALLEL_GC)
-void MarkStackThreadSharedData::markingThreadMain()
+void MarkStackThreadSharedData::resetChildren()
+{
+ for (unsigned i = 0; i < m_slaveMarkStacks.size(); ++i)
+ m_slaveMarkStacks[i]->reset();
+}
+
+void MarkStackThreadSharedData::markingThreadMain(SlotVisitor* slotVisitor)
{
WTF::registerGCThread();
- SlotVisitor slotVisitor(*this);
- ParallelModeEnabler enabler(slotVisitor);
- slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
+ ParallelModeEnabler enabler(*slotVisitor);
+ slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
+ delete slotVisitor;
}
-void MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
+void MarkStackThreadSharedData::markingThreadStartFunc(void* myVisitor)
{
- static_cast<MarkStackThreadSharedData*>(shared)->markingThreadMain();
+ SlotVisitor* slotVisitor = static_cast<SlotVisitor*>(myVisitor);
+ slotVisitor->sharedData().markingThreadMain(slotVisitor);
}
#endif
@@ -241,7 +249,9 @@ MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData)
{
#if ENABLE(PARALLEL_GC)
for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
- m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
+ SlotVisitor* slotVisitor = new SlotVisitor(*this);
+ m_slaveMarkStacks.append(slotVisitor);
+ m_markingThreads.append(createThread(markingThreadStartFunc, slotVisitor, "JavaScriptCore::Marking"));
ASSERT(m_markingThreads.last());
}
#endif
@@ -273,7 +283,6 @@ void MarkStackThreadSharedData::reset()
#else
ASSERT(m_opaqueRoots.isEmpty());
#endif
-
m_weakReferenceHarvesters.removeAll();
}
@@ -286,6 +295,7 @@ void MarkStack::reset()
#else
m_opaqueRoots.clear();
#endif
+ m_uniqueStrings.clear();
}
void MarkStack::append(ConservativeRoots& conservativeRoots)
@@ -486,6 +496,34 @@ void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes)
return CopiedSpace::allocateFromBlock(m_copyBlock, bytes);
}
+inline void MarkStack::internalAppend(JSValue* slot)
+{
+ ASSERT(slot);
+ JSValue value = *slot;
+ ASSERT(value);
+ if (!value.isCell())
+ return;
+
+ if (value.isString()) {
+ JSString* string = jsCast<JSString*>(value.asCell());
+ if (!string->isHashConstSingleton() && string->length() > 1 && !string->isRope()) {
+ UniqueStringMap::AddResult addResult = m_uniqueStrings.add(string->string().impl(), value);
+ if (addResult.isNewEntry)
+ string->setHashConstSingleton();
+ else {
+ JSValue existingJSValue = addResult.iterator->second;
+ if (value != existingJSValue)
+ jsCast<JSString*>(existingJSValue.asCell())->clearHashConstSingleton();
+ *slot = existingJSValue;
+ return;
+ }
+ }
+ }
+
+ internalAppend(value.asCell());
+}
+
+
void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length)
{
void* oldPtr = *ptr;
@@ -499,7 +537,7 @@ void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsig
newValues[i] = value;
if (!value)
continue;
- internalAppend(value);
+ internalAppend(&newValues[i]);
}
memcpy(newPtr, oldPtr, jsValuesOffset);
diff --git a/Source/JavaScriptCore/heap/MarkStack.h b/Source/JavaScriptCore/heap/MarkStack.h
index 0695b1b32..48b65c069 100644
--- a/Source/JavaScriptCore/heap/MarkStack.h
+++ b/Source/JavaScriptCore/heap/MarkStack.h
@@ -34,12 +34,14 @@
#include "UnconditionalFinalizer.h"
#include "VTableSpectrum.h"
#include "WeakReferenceHarvester.h"
+#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
#include <wtf/Noncopyable.h>
#include <wtf/OSAllocator.h>
#include <wtf/PageBlock.h>
+#include <wtf/text/StringHash.h>
namespace JSC {
@@ -171,13 +173,17 @@ namespace JSC {
~MarkStackThreadSharedData();
void reset();
-
+
+#if ENABLE(PARALLEL_GC)
+ void resetChildren();
+#endif
+
private:
friend class MarkStack;
friend class SlotVisitor;
#if ENABLE(PARALLEL_GC)
- void markingThreadMain();
+ void markingThreadMain(SlotVisitor*);
static void markingThreadStartFunc(void* heap);
#endif
@@ -187,6 +193,7 @@ namespace JSC {
MarkStackSegmentAllocator m_segmentAllocator;
Vector<ThreadIdentifier> m_markingThreads;
+ Vector<MarkStack*> m_slaveMarkStacks;
Mutex m_markingLock;
ThreadCondition m_markingCondition;
@@ -221,13 +228,14 @@ namespace JSC {
void addOpaqueRoot(void*);
bool containsOpaqueRoot(void*);
int opaqueRootCount();
-
+
+ MarkStackThreadSharedData& sharedData() { return m_shared; }
bool isEmpty() { return m_stack.isEmpty(); }
void reset();
size_t visitCount() const { return m_visitCount; }
-
+
#if ENABLE(SIMPLE_HEAP_PROFILING)
VTableSpectrum m_visitedTypeCounts;
#endif
@@ -251,6 +259,7 @@ namespace JSC {
void internalAppend(JSCell*);
void internalAppend(JSValue);
+ void internalAppend(JSValue*);
JS_EXPORT_PRIVATE void mergeOpaqueRoots();
@@ -270,6 +279,8 @@ namespace JSC {
MarkStackArray m_stack;
HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
+ typedef HashMap<StringImpl*, JSValue> UniqueStringMap;
+ UniqueStringMap m_uniqueStrings;
#if !ASSERT_DISABLED
public:
diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
index b5e5fff77..01f00c376 100644
--- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp
+++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
@@ -68,44 +68,30 @@ void* MarkedAllocator::allocateSlowCase()
if (LIKELY(result != 0))
return result;
- AllocationEffort allocationEffort;
-
- if (m_heap->shouldCollect())
- allocationEffort = AllocationCanFail;
- else
- allocationEffort = AllocationMustSucceed;
-
- MarkedBlock* block = allocateBlock(allocationEffort);
- if (block) {
- addBlock(block);
- void* result = tryAllocate();
- ASSERT(result);
- return result;
+ if (m_heap->shouldCollect()) {
+ m_heap->collect(Heap::DoNotSweep);
+
+ result = tryAllocate();
+ if (result)
+ return result;
}
-
- m_heap->collect(Heap::DoNotSweep);
-
- result = tryAllocate();
-
- if (result)
- return result;
-
+
ASSERT(!m_heap->shouldCollect());
- addBlock(allocateBlock(AllocationMustSucceed));
-
+ MarkedBlock* block = allocateBlock();
+ ASSERT(block);
+ addBlock(block);
+
result = tryAllocate();
ASSERT(result);
return result;
}
-MarkedBlock* MarkedAllocator::allocateBlock(AllocationEffort allocationEffort)
+MarkedBlock* MarkedAllocator::allocateBlock()
{
MarkedBlock* block = static_cast<MarkedBlock*>(m_heap->blockAllocator().allocate());
if (block)
block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction);
- else if (allocationEffort == AllocationCanFail)
- return 0;
else
block = MarkedBlock::create(m_heap, m_cellSize, m_cellsNeedDestruction);
diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.h b/Source/JavaScriptCore/heap/MarkedAllocator.h
index 8ad7e925f..8b3620f08 100644
--- a/Source/JavaScriptCore/heap/MarkedAllocator.h
+++ b/Source/JavaScriptCore/heap/MarkedAllocator.h
@@ -41,7 +41,7 @@ private:
JS_EXPORT_PRIVATE void* allocateSlowCase();
void* tryAllocate();
void* tryAllocateHelper();
- MarkedBlock* allocateBlock(AllocationEffort);
+ MarkedBlock* allocateBlock();
MarkedBlock::FreeList m_freeList;
MarkedBlock* m_currentBlock;
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index 1cd5719ff..89547f40a 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -2448,7 +2448,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
- if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
+ if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0 && divisor.asInt32() != -1) {
JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32());
ASSERT(result);
callFrame->uncheckedR(dst) = result;
@@ -4788,17 +4788,6 @@ skip_id_custom_self:
vPC += OPCODE_LENGTH(op_create_activation);
NEXT_INSTRUCTION();
}
- DEFINE_OPCODE(op_get_callee) {
- /* op_get_callee callee(r)
-
- Move callee into a register.
- */
-
- callFrame->uncheckedR(vPC[1].u.operand) = JSValue(callFrame->callee());
-
- vPC += OPCODE_LENGTH(op_get_callee);
- NEXT_INSTRUCTION();
- }
DEFINE_OPCODE(op_create_this) {
/* op_create_this this(r) proto(r)
@@ -4809,7 +4798,6 @@ skip_id_custom_self:
*/
int thisRegister = vPC[1].u.operand;
- int protoRegister = vPC[2].u.operand;
JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
#if !ASSERT_DISABLED
@@ -4817,12 +4805,7 @@ skip_id_custom_self:
ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
#endif
- Structure* structure;
- JSValue proto = callFrame->r(protoRegister).jsValue();
- if (proto.isObject())
- structure = asObject(proto)->inheritorID(callFrame->globalData());
- else
- structure = constructor->scope()->globalObject->emptyObjectStructure();
+ Structure* structure = constructor->cachedInheritorID(callFrame);
callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
vPC += OPCODE_LENGTH(op_create_this);
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.h b/Source/JavaScriptCore/jit/ExecutableAllocator.h
index 1ddf011cb..c1edc9752 100644
--- a/Source/JavaScriptCore/jit/ExecutableAllocator.h
+++ b/Source/JavaScriptCore/jit/ExecutableAllocator.h
@@ -30,6 +30,7 @@
#include <limits>
#include <wtf/Assertions.h>
#include <wtf/MetaAllocatorHandle.h>
+#include <wtf/MetaAllocator.h>
#include <wtf/PageAllocation.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
index b4422c3df..884248b20 100644
--- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
+++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
@@ -78,12 +78,26 @@ protected:
virtual void notifyNeedPage(void* page)
{
+#if OS(DARWIN)
+ UNUSED_PARAM(page);
+#else
m_reservation.commit(page, pageSize());
+#endif
}
virtual void notifyPageIsFree(void* page)
{
+#if OS(DARWIN)
+ for (;;) {
+ int result = madvise(page, pageSize(), MADV_FREE);
+ if (!result)
+ return;
+ ASSERT(result == -1);
+ ASSERT(errno == EAGAIN);
+ }
+#else
m_reservation.decommit(page, pageSize());
+#endif
}
private:
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 01b1260c9..abc79d34b 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -242,7 +242,6 @@ void JIT::privateCompileMainPass()
DEFINE_OP(op_call_varargs)
DEFINE_OP(op_catch)
DEFINE_OP(op_construct)
- DEFINE_OP(op_get_callee)
DEFINE_OP(op_create_this)
DEFINE_OP(op_convert_this)
DEFINE_OP(op_init_lazy_reg)
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index af5076fb5..6dc0137d9 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -582,7 +582,6 @@ namespace JSC {
void emit_op_call_put_result(Instruction*);
void emit_op_catch(Instruction*);
void emit_op_construct(Instruction*);
- void emit_op_get_callee(Instruction*);
void emit_op_create_this(Instruction*);
void emit_op_convert_this(Instruction*);
void emit_op_create_arguments(Instruction*);
diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h
index cd33821f2..40985ac90 100644
--- a/Source/JavaScriptCore/jit/JITInlineMethods.h
+++ b/Source/JavaScriptCore/jit/JITInlineMethods.h
@@ -448,6 +448,9 @@ inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, Register
// store the function's executable member
storePtr(TrustedImmPtr(executable), Address(result, JSFunction::offsetOfExecutable()));
+ // clear the function's inheritorID
+ storePtr(TrustedImmPtr(0), Address(result, JSFunction::offsetOfCachedInheritorID()));
+
// store the function's name
ASSERT(executable->nameValue());
int functionNameOffset = sizeof(JSValue) * m_codeBlock->globalObject()->functionNameOffset();
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index d68f4109d..f43e98c45 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1263,42 +1263,24 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
}
-void JIT::emit_op_get_callee(Instruction* currentInstruction)
-{
- unsigned result = currentInstruction[1].u.operand;
- emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
- emitPutVirtualRegister(result);
-}
-
void JIT::emit_op_create_this(Instruction* currentInstruction)
{
- emitGetVirtualRegister(currentInstruction[2].u.operand, regT2);
- emitJumpSlowCaseIfNotJSCell(regT2, currentInstruction[2].u.operand);
- loadPtr(Address(regT2, JSCell::structureOffset()), regT1);
- addSlowCase(emitJumpIfNotObject(regT1));
-
- // now we know that the prototype is an object, but we don't know if it's got an
- // inheritor ID
-
- loadPtr(Address(regT2, JSObject::offsetOfInheritorID()), regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
+ loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2);
addSlowCase(branchTestPtr(Zero, regT2));
// now regT2 contains the inheritorID, which is the structure that the newly
// allocated object will have.
emitAllocateJSFinalObject(regT2, regT0, regT1);
-
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
- linkSlowCase(iter); // not an object
linkSlowCase(iter); // doesn't have an inheritor ID
linkSlowCase(iter); // allocation failed
JITStubCall stubCall(this, cti_op_create_this);
- stubCall.addArgument(currentInstruction[2].u.operand, regT1);
stubCall.call(currentInstruction[1].u.operand);
}
diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 76e11e48c..c9f8922fa 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1523,44 +1523,24 @@ void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)
emitStore(dst, JSValue());
}
-void JIT::emit_op_get_callee(Instruction* currentInstruction)
-{
- int dst = currentInstruction[1].u.operand;
- emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
- emitStoreCell(dst, regT0);
-}
-
void JIT::emit_op_create_this(Instruction* currentInstruction)
{
- emitLoad(currentInstruction[2].u.operand, regT1, regT0);
- emitJumpSlowCaseIfNotJSCell(currentInstruction[2].u.operand, regT1);
- loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
- addSlowCase(emitJumpIfNotObject(regT1));
-
- // now we know that the prototype is an object, but we don't know if it's got an
- // inheritor ID
-
- loadPtr(Address(regT0, JSObject::offsetOfInheritorID()), regT2);
+ emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
+ loadPtr(Address(regT0, JSFunction::offsetOfCachedInheritorID()), regT2);
addSlowCase(branchTestPtr(Zero, regT2));
// now regT2 contains the inheritorID, which is the structure that the newly
// allocated object will have.
emitAllocateJSFinalObject(regT2, regT0, regT1);
-
emitStoreCell(currentInstruction[1].u.operand, regT0);
}
void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
{
- linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand); // not a cell
- linkSlowCase(iter); // not an object
linkSlowCase(iter); // doesn't have an inheritor ID
linkSlowCase(iter); // allocation failed
- unsigned protoRegister = currentInstruction[2].u.operand;
- emitLoad(protoRegister, regT1, regT0);
JITStubCall stubCall(this, cti_op_create_this);
- stubCall.addArgument(regT1, regT0);
stubCall.call(currentInstruction[1].u.operand);
}
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index d81e68aae..73f4892ac 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -1286,12 +1286,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
#endif
- Structure* structure;
- JSValue proto = stackFrame.args[0].jsValue();
- if (proto.isObject())
- structure = asObject(proto)->inheritorID(*stackFrame.globalData);
- else
- structure = constructor->scope()->globalObject->emptyObjectStructure();
+ Structure* structure = constructor->cachedInheritorID(callFrame);
JSValue result = constructEmptyObject(callFrame, structure);
return JSValue::encode(result);
@@ -1497,9 +1492,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
ASSERT(baseValue.isObject());
JSObject* base = asObject(baseValue);
- JSGlobalData& globalData = *stackFrame.globalData;
- PropertyStorage newStorage = base->growPropertyStorage(globalData, oldSize, newSize);
- base->setPropertyStorage(globalData, newStorage, newStructure);
+ base->allocatePropertyStorage(*stackFrame.globalData, oldSize, newSize);
return base;
}
diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
index 2b5161f7b..d184b6e62 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -458,13 +458,7 @@ LLINT_SLOW_PATH_DECL(slow_path_create_this)
ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
#endif
- Structure* structure;
- JSValue proto = LLINT_OP(2).jsValue();
- if (proto.isObject())
- structure = asObject(proto)->inheritorID(globalData);
- else
- structure = constructor->scope()->globalObject->emptyObjectStructure();
-
+ Structure* structure = constructor->cachedInheritorID(exec);
LLINT_RETURN(constructEmptyObject(exec, structure));
}
@@ -1167,6 +1161,20 @@ LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
LLINT_END();
}
+LLINT_SLOW_PATH_DECL(slow_path_switch_char)
+{
+ LLINT_BEGIN();
+ JSValue scrutinee = LLINT_OP_C(3).jsValue();
+ ASSERT(scrutinee.isString());
+ JSString* string = asString(scrutinee);
+ ASSERT(string->length() == 1);
+ int defaultOffset = pc[2].u.operand;
+ StringImpl* impl = string->value(exec).impl();
+ CodeBlock* codeBlock = exec->codeBlock();
+ pc += codeBlock->characterSwitchJumpTable(pc[1].u.operand).offsetForValue((*impl)[0], defaultOffset);
+ LLINT_END();
+}
+
LLINT_SLOW_PATH_DECL(slow_path_switch_string)
{
LLINT_BEGIN();
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
index 42ab4c1e4..e1361315f 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -343,31 +343,17 @@ _llint_op_create_arguments:
_llint_op_create_this:
traceExecution()
- loadi 8[PC], t0
- assertNotConstant(t0)
- bineq TagOffset[cfr, t0, 8], CellTag, .opCreateThisSlow
- loadi PayloadOffset[cfr, t0, 8], t0
- loadp JSCell::m_structure[t0], t1
- bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
- loadp JSObject::m_inheritorID[t0], t2
+ loadp Callee[cfr], t0
+ loadp JSFunction::m_cachedInheritorID[t0], t2
btpz t2, .opCreateThisSlow
allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
loadi 4[PC], t1
storei CellTag, TagOffset[cfr, t1, 8]
storei t0, PayloadOffset[cfr, t1, 8]
- dispatch(3)
+ dispatch(2)
.opCreateThisSlow:
callSlowPath(_llint_slow_path_create_this)
- dispatch(3)
-
-
-_llint_op_get_callee:
- traceExecution()
- loadi 4[PC], t0
- loadp PayloadOffset + Callee[cfr], t1
- storei CellTag, TagOffset[cfr, t0, 8]
- storei t1, PayloadOffset[cfr, t0, 8]
dispatch(2)
@@ -1446,8 +1432,9 @@ _llint_op_switch_char:
bineq t1, CellTag, .opSwitchCharFallThrough
loadp JSCell::m_structure[t0], t1
bbneq Structure::m_typeInfo + TypeInfo::m_type[t1], StringType, .opSwitchCharFallThrough
+ bineq JSString::m_length[t0], 1, .opSwitchCharFallThrough
loadp JSString::m_value[t0], t0
- bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough
+ btpz t0, .opSwitchOnRope
loadp StringImpl::m_data8[t0], t1
btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
loadh [t1], t0
@@ -1465,6 +1452,10 @@ _llint_op_switch_char:
.opSwitchCharFallThrough:
dispatchBranch(8[PC])
+.opSwitchOnRope:
+ callSlowPath(_llint_slow_path_switch_char)
+ dispatch(0)
+
_llint_op_new_func:
traceExecution()
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
index b28051f33..baf246b0b 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -221,29 +221,16 @@ _llint_op_create_arguments:
_llint_op_create_this:
traceExecution()
- loadis 16[PB, PC, 8], t0
- assertNotConstant(t0)
- loadp [cfr, t0, 8], t0
- btpnz t0, tagMask, .opCreateThisSlow
- loadp JSCell::m_structure[t0], t1
- bbb Structure::m_typeInfo + TypeInfo::m_type[t1], ObjectType, .opCreateThisSlow
- loadp JSObject::m_inheritorID[t0], t2
+ loadp Callee[cfr], t0
+ loadp JSFunction::m_cachedInheritorID[t0], t2
btpz t2, .opCreateThisSlow
allocateBasicJSObject(JSFinalObjectSizeClassIndex, JSGlobalData::jsFinalObjectClassInfo, t2, t0, t1, t3, .opCreateThisSlow)
loadis 8[PB, PC, 8], t1
storep t0, [cfr, t1, 8]
- dispatch(3)
+ dispatch(2)
.opCreateThisSlow:
callSlowPath(_llint_slow_path_create_this)
- dispatch(3)
-
-
-_llint_op_get_callee:
- traceExecution()
- loadis 8[PB, PC, 8], t0
- loadp Callee[cfr], t1
- storep t1, [cfr, t0, 8]
dispatch(2)
@@ -1292,8 +1279,9 @@ _llint_op_switch_char:
btpnz t1, tagMask, .opSwitchCharFallThrough
loadp JSCell::m_structure[t1], t0
bbneq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, .opSwitchCharFallThrough
+ bineq JSString::m_length[t1], 1, .opSwitchCharFallThrough
loadp JSString::m_value[t1], t0
- bineq StringImpl::m_length[t0], 1, .opSwitchCharFallThrough
+ btpz t0, .opSwitchOnRope
loadp StringImpl::m_data8[t0], t1
btinz StringImpl::m_hashAndFlags[t0], HashFlags8BitBuffer, .opSwitchChar8Bit
loadh [t1], t0
@@ -1311,6 +1299,10 @@ _llint_op_switch_char:
.opSwitchCharFallThrough:
dispatchInt(16[PB, PC, 8])
+.opSwitchOnRope:
+ callSlowPath(_llint_slow_path_switch_char)
+ dispatch(0)
+
_llint_op_new_func:
traceExecution()
diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h
index a173cc10f..0eb60cf89 100644
--- a/Source/JavaScriptCore/parser/ASTBuilder.h
+++ b/Source/JavaScriptCore/parser/ASTBuilder.h
@@ -77,6 +77,7 @@ public:
: m_globalData(globalData)
, m_sourceCode(sourceCode)
, m_scope(globalData)
+ , m_evalCount(0)
{
}
@@ -118,6 +119,7 @@ public:
ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; }
ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; }
+ int features() const { return m_scope.m_features; }
int numConstants() const { return m_scope.m_numConstants; }
void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); }
@@ -150,8 +152,17 @@ public:
incConstants();
return new (m_globalData) VoidNode(lineNumber, expr);
}
- ExpressionNode* thisExpr(int lineNumber) { return new (m_globalData) ThisNode(lineNumber); }
- ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start) { return new (m_globalData) ResolveNode(lineNumber, *ident, start); }
+ ExpressionNode* thisExpr(int lineNumber)
+ {
+ usesThis();
+ return new (m_globalData) ThisNode(lineNumber);
+ }
+ ExpressionNode* createResolve(int lineNumber, const Identifier* ident, int start)
+ {
+ if (m_globalData->propertyNames->arguments == *ident)
+ usesArguments();
+ return new (m_globalData) ResolveNode(lineNumber, *ident, start);
+ }
ExpressionNode* createObjectLiteral(int lineNumber) { return new (m_globalData) ObjectLiteralNode(lineNumber); }
ExpressionNode* createObjectLiteral(int lineNumber, PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(lineNumber, properties); }
@@ -252,9 +263,9 @@ public:
return result;
}
- FunctionBodyNode* createFunctionBody(int lineNumber, ScopeFlags scopeFlags)
+ FunctionBodyNode* createFunctionBody(int lineNumber, bool inStrictContext)
{
- return FunctionBodyNode::create(m_globalData, lineNumber, scopeFlags);
+ return FunctionBodyNode::create(m_globalData, lineNumber, inStrictContext);
}
template <bool> PropertyNode* createGetterOrSetterProperty(int lineNumber, PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
@@ -301,6 +312,8 @@ public:
StatementNode* createFuncDeclStatement(int lineNumber, const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
{
FuncDeclNode* decl = new (m_globalData) FuncDeclNode(lineNumber, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters);
+ if (*name == m_globalData->propertyNames->arguments)
+ usesArguments();
m_scope.m_funcDeclarations->data.append(decl->body());
body->setLoc(bodyStartLine, bodyEndLine);
return decl;
@@ -413,6 +426,8 @@ public:
StatementNode* createTryStatement(int lineNumber, StatementNode* tryBlock, const Identifier* ident, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
{
TryNode* result = new (m_globalData) TryNode(lineNumber, tryBlock, *ident, catchBlock, finallyBlock);
+ if (catchBlock)
+ usesCatch();
result->setLoc(startLine, endLine);
return result;
}
@@ -448,6 +463,7 @@ public:
StatementNode* createWithStatement(int lineNumber, ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine)
{
+ usesWith();
WithNode* result = new (m_globalData) WithNode(lineNumber, expr, statement, end, end - start);
result->setLoc(startLine, endLine);
return result;
@@ -490,6 +506,8 @@ public:
void addVar(const Identifier* ident, int attrs)
{
+ if (m_globalData->propertyNames->arguments == *ident)
+ usesArguments();
m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
}
@@ -504,6 +522,8 @@ public:
return new (m_globalData) CommaNode(lineNumber, list, init);
}
+ int evalCount() const { return m_evalCount; }
+
void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments)
{
operandStackDepth++;
@@ -590,11 +610,13 @@ private:
Scope(JSGlobalData* globalData)
: m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>)
, m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>)
+ , m_features(0)
, m_numConstants(0)
{
}
ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ int m_features;
int m_numConstants;
};
@@ -604,6 +626,15 @@ private:
}
void incConstants() { m_scope.m_numConstants++; }
+ void usesThis() { m_scope.m_features |= ThisFeature; }
+ void usesCatch() { m_scope.m_features |= CatchFeature; }
+ void usesArguments() { m_scope.m_features |= ArgumentsFeature; }
+ void usesWith() { m_scope.m_features |= WithFeature; }
+ void usesEval()
+ {
+ m_evalCount++;
+ m_scope.m_features |= EvalFeature;
+ }
ExpressionNode* createNumber(int lineNumber, double d)
{
return new (m_globalData) NumberNode(lineNumber, d);
@@ -616,6 +647,7 @@ private:
Vector<AssignmentInfo, 10> m_assignmentInfoStack;
Vector<pair<int, int>, 10> m_binaryOperatorStack;
Vector<pair<int, int>, 10> m_unaryTokenStack;
+ int m_evalCount;
};
ExpressionNode* ASTBuilder::makeTypeOfNode(int lineNumber, ExpressionNode* expr)
@@ -765,8 +797,10 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(int lineNumber, ExpressionNode*
if (func->isResolveNode()) {
ResolveNode* resolve = static_cast<ResolveNode*>(func);
const Identifier& identifier = resolve->identifier();
- if (identifier == m_globalData->propertyNames->eval)
+ if (identifier == m_globalData->propertyNames->eval) {
+ usesEval();
return new (m_globalData) EvalFunctionCallNode(lineNumber, args, divot, divot - start, end - divot);
+ }
return new (m_globalData) FunctionCallResolveNode(lineNumber, identifier, args, divot, divot - start, end - divot);
}
if (func->isBracketAccessorNode()) {
diff --git a/Source/JavaScriptCore/parser/NodeInfo.h b/Source/JavaScriptCore/parser/NodeInfo.h
index e0d4ffec4..4853aec42 100644
--- a/Source/JavaScriptCore/parser/NodeInfo.h
+++ b/Source/JavaScriptCore/parser/NodeInfo.h
@@ -26,7 +26,7 @@ namespace JSC {
template <typename T> struct NodeInfo {
T m_node;
- ScopeFlags m_scopeFlags;
+ CodeFeatures m_features;
int m_numConstants;
};
@@ -44,7 +44,7 @@ namespace JSC {
T m_node;
ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
- ScopeFlags m_scopeFlags;
+ CodeFeatures m_features;
int m_numConstants;
};
diff --git a/Source/JavaScriptCore/parser/Nodes.cpp b/Source/JavaScriptCore/parser/Nodes.cpp
index 75c848bce..c32e4c73a 100644
--- a/Source/JavaScriptCore/parser/Nodes.cpp
+++ b/Source/JavaScriptCore/parser/Nodes.cpp
@@ -75,19 +75,19 @@ StatementNode* SourceElements::singleStatement() const
// ------------------------------ ScopeNode -----------------------------
-ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags)
+ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
: StatementNode(lineNumber)
, ParserArenaRefCounted(globalData)
- , m_scopeFlags(scopeFlags)
+ , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
, m_numConstants(0)
, m_statements(0)
{
}
-ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, ScopeFlags scopeFlags, int numConstants)
+ScopeNode::ScopeNode(JSGlobalData* globalData, int lineNumber, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
: StatementNode(lineNumber)
, ParserArenaRefCounted(globalData)
- , m_scopeFlags(scopeFlags)
+ , m_features(features)
, m_source(source)
, m_numConstants(numConstants)
, m_statements(children)
@@ -107,14 +107,14 @@ StatementNode* ScopeNode::singleStatement() const
// ------------------------------ ProgramNode -----------------------------
-inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants)
- : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants)
+inline ProgramNode::ProgramNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants)
{
}
-PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants)
+PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
{
- RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants);
+ RefPtr<ProgramNode> node = new ProgramNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants);
ASSERT(node->m_arena.last() == node);
node->m_arena.removeLast();
@@ -125,14 +125,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, int lineNu
// ------------------------------ EvalNode -----------------------------
-inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants)
- : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants)
+inline EvalNode::EvalNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, lineNumber, source, children, varStack, funcStack, capturedVariables, features, numConstants)
{
}
-PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, ScopeFlags scopeFlags, int numConstants)
+PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
{
- RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, scopeFlags, numConstants);
+ RefPtr<EvalNode> node = new EvalNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, source, features, numConstants);
ASSERT(node->m_arena.last() == node);
node->m_arena.removeLast();
@@ -149,13 +149,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
append(parameter->ident());
}
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags)
- : ScopeNode(globalData, lineNumber, scopeFlags)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
+ : ScopeNode(globalData, lineNumber, inStrictContext)
{
}
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants)
- : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, scopeFlags, numConstants)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+ : ScopeNode(globalData, lineNumber, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
{
}
@@ -172,14 +172,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters,
m_ident = ident;
}
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, ScopeFlags scopeFlags)
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, bool inStrictContext)
{
- return new FunctionBodyNode(globalData, lineNumber, scopeFlags);
+ return new FunctionBodyNode(globalData, lineNumber, inStrictContext);
}
-PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, ScopeFlags scopeFlags, int numConstants)
+PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, int lineNumber, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
{
- RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, scopeFlags, numConstants);
+ RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, lineNumber, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
ASSERT(node->m_arena.last() == node);
node->m_arena.removeLast();
diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h
index f752b91e9..26c829da6 100644
--- a/Source/JavaScriptCore/parser/Nodes.h
+++ b/Source/JavaScriptCore/parser/Nodes.h
@@ -47,31 +47,19 @@ namespace JSC {
class ScopeChainNode;
class ScopeNode;
- typedef unsigned short ScopeFlags;
-
- const ScopeFlags NoScopeFlags = 0;
-
- // Some scope flags propagate down the parse tree from parent scopes, like
- // strict mode. They are modal to an entire set of nested scopes.
- const ScopeFlags StrictModeFlag = 1 << 0;
- const ScopeFlags FunctionModeFlag = 1 << 1;
- const ScopeFlags AllScopeModeFlags = StrictModeFlag | FunctionModeFlag;
-
- // Some scope flags refer only to a specific scope, and don't propagate down
- // or up.
- const ScopeFlags BlockScopeFlag = 1 << 4;
- const ScopeFlags AllScopeKindFlags = BlockScopeFlag;
-
- // Other flags reflect uses within nested scopes, and so propagate up
- // from the leaves.
- const ScopeFlags UsesEvalFlag = 1 << 8;
- const ScopeFlags UsesArgumentsFlag = 1 << 9;
- const ScopeFlags UsesWithFlag = 1 << 10;
- const ScopeFlags UsesCatchFlag = 1 << 11;
- const ScopeFlags UsesThisFlag = 1 << 12;
- const ScopeFlags ShadowsArgumentsFlag = 1 << 13;
- const ScopeFlags AllScopeUsesFlags = UsesEvalFlag | UsesArgumentsFlag | UsesWithFlag | UsesCatchFlag | UsesThisFlag | ShadowsArgumentsFlag;
+ typedef unsigned CodeFeatures;
+
+ const CodeFeatures NoFeatures = 0;
+ const CodeFeatures EvalFeature = 1 << 0;
+ const CodeFeatures ArgumentsFeature = 1 << 1;
+ const CodeFeatures WithFeature = 1 << 2;
+ const CodeFeatures CatchFeature = 1 << 3;
+ const CodeFeatures ThisFeature = 1 << 4;
+ const CodeFeatures StrictModeFeature = 1 << 5;
+ const CodeFeatures ShadowsArgumentsFeature = 1 << 6;
+ const CodeFeatures AllFeatures = EvalFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
+
enum Operator {
OpEqual,
OpPlusEq,
@@ -1395,8 +1383,8 @@ namespace JSC {
typedef DeclarationStacks::VarStack VarStack;
typedef DeclarationStacks::FunctionStack FunctionStack;
- ScopeNode(JSGlobalData*, int, ScopeFlags);
- ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, ScopeFlags, int numConstants);
+ ScopeNode(JSGlobalData*, int, bool inStrictContext);
+ ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
using ParserArenaRefCounted::operator new;
@@ -1409,26 +1397,24 @@ namespace JSC {
m_capturedVariables.clear();
}
- bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
- size_t capturedVariableCount() const { return m_capturedVariables.size(); }
- bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); }
-
- void addScopeFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; }
- ScopeFlags scopeFlags() const { return m_scopeFlags; }
-
- bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; }
- bool usesEval() const { return m_scopeFlags & UsesEvalFlag; }
- bool usesArguments() const { return (m_scopeFlags & UsesArgumentsFlag) && !(m_scopeFlags & ShadowsArgumentsFlag); }
- void setUsesArguments() { m_scopeFlags |= UsesArgumentsFlag; }
- bool usesThis() const { return m_scopeFlags & UsesThisFlag; }
-
- bool needsActivationForMoreThanVariables() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); }
- bool needsActivation() const { return hasCapturedVariables() || needsActivationForMoreThanVariables(); }
-
const SourceCode& source() const { return m_source; }
const UString& sourceURL() const { return m_source.provider()->url(); }
intptr_t sourceID() const { return m_source.provider()->asID(); }
+ void setFeatures(CodeFeatures features) { m_features = features; }
+ CodeFeatures features() { return m_features; }
+
+ bool usesEval() const { return m_features & EvalFeature; }
+ bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
+ bool isStrictMode() const { return m_features & StrictModeFeature; }
+ void setUsesArguments() { m_features |= ArgumentsFeature; }
+ bool usesThis() const { return m_features & ThisFeature; }
+ bool needsActivationForMoreThanVariables() const { return m_features & (EvalFeature | WithFeature | CatchFeature); }
+ bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
+ bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
+ size_t capturedVariableCount() const { return m_capturedVariables.size(); }
+ bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); }
+
VarStack& varStack() { return m_varStack; }
FunctionStack& functionStack() { return m_functionStack; }
@@ -1448,7 +1434,7 @@ namespace JSC {
ParserArena m_arena;
private:
- ScopeFlags m_scopeFlags;
+ CodeFeatures m_features;
SourceCode m_source;
VarStack m_varStack;
FunctionStack m_functionStack;
@@ -1460,12 +1446,12 @@ namespace JSC {
class ProgramNode : public ScopeNode {
public:
static const bool isFunctionNode = false;
- static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ static PassRefPtr<ProgramNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
static const bool scopeIsFunction = false;
private:
- ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
@@ -1473,12 +1459,12 @@ namespace JSC {
class EvalNode : public ScopeNode {
public:
static const bool isFunctionNode = false;
- static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ static PassRefPtr<EvalNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
static const bool scopeIsFunction = false;
private:
- EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
};
@@ -1495,8 +1481,8 @@ namespace JSC {
class FunctionBodyNode : public ScopeNode {
public:
static const bool isFunctionNode = true;
- static FunctionBodyNode* create(JSGlobalData*, int, ScopeFlags);
- static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode);
+ static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
FunctionParameters* parameters() const { return m_parameters.get(); }
size_t parameterCount() const { return m_parameters->size(); }
@@ -1513,8 +1499,8 @@ namespace JSC {
static const bool scopeIsFunction = true;
private:
- FunctionBodyNode(JSGlobalData*, int, ScopeFlags);
- FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, ScopeFlags, int numConstants);
+ FunctionBodyNode(JSGlobalData*, int, bool inStrictContext);
+ FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
Identifier m_ident;
Identifier m_inferredName;
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index a03af24df..d88a9a8b7 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -62,12 +62,11 @@ Parser<LexerType>::Parser(JSGlobalData* globalData, const SourceCode& source, Fu
m_lexer->setCode(source, m_arena);
m_functionCache = source.provider()->cache();
- ScopeFlags scopeFlags = NoScopeFlags;
- if (strictness == JSParseStrict)
- scopeFlags |= StrictModeFlag;
+ ScopeRef scope = pushScope();
if (parserMode == JSParseFunctionCode)
- scopeFlags |= FunctionModeFlag;
- ScopeRef scope = pushScope(scopeFlags);
+ scope->setIsFunction();
+ if (strictness == JSParseStrict)
+ scope->setStrictMode();
if (parameters) {
for (unsigned i = 0; i < parameters->size(); i++)
scope->declareParameter(&parameters->at(i));
@@ -97,12 +96,16 @@ UString Parser<LexerType>::parseInner()
IdentifierSet capturedVariables;
scope->getCapturedVariables(capturedVariables);
- ScopeFlags scopeFlags = scope->modeFlags() | scope->usesFlags();
+ CodeFeatures features = context.features();
+ if (scope->strictMode())
+ features |= StrictModeFeature;
+ if (scope->shadowsArguments())
+ features |= ShadowsArgumentsFeature;
unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
if (functionCacheSize != oldFunctionCacheSize)
m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize);
- didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), scopeFlags,
+ didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
m_lastLine, context.numConstants(), capturedVariables);
return parseError;
@@ -110,13 +113,13 @@ UString Parser<LexerType>::parseInner()
template <typename LexerType>
void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack,
- ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, ScopeFlags scopeFlags, int lastLine, int numConstants, IdentifierSet& capturedVars)
+ ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars)
{
m_sourceElements = sourceElements;
m_varDeclarations = varStack;
m_funcDeclarations = funcStack;
m_capturedVariables.swap(capturedVars);
- m_scopeFlags = scopeFlags;
+ m_features = features;
m_lastLine = lastLine;
m_numConstants = numConstants;
}
@@ -144,7 +147,7 @@ template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements Parser<
if (directive) {
// "use strict" must be the exact literal without escape sequences or line continuation.
if (!hasSetStrict && directiveLiteralLength == lengthOfUseStrictLiteral && m_globalData->propertyNames->useStrictIdentifier == *directive) {
- currentScope()->setFlags(StrictModeFlag);
+ setStrictMode();
hasSetStrict = true;
failIfFalse(isValidStrictMode());
m_lexer->setOffset(startOffset);
@@ -252,8 +255,6 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseVarDeclarati
next();
bool hasInitializer = match(EQUAL);
failIfFalseIfStrictWithNameAndMessage(declareVariable(name), "Cannot declare a variable named", name->impl(), "in strict mode.");
- if (m_globalData->propertyNames->arguments == *name)
- currentScope()->setFlags(UsesArgumentsFlag);
context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
if (hasInitializer) {
int varDivot = tokenStart() + 1;
@@ -288,8 +289,6 @@ template <class TreeBuilder> TreeConstDeclList Parser<LexerType>::parseConstDecl
next();
bool hasInitializer = match(EQUAL);
declareVariable(name);
- if (m_globalData->propertyNames->arguments == *name)
- currentScope()->setFlags(UsesArgumentsFlag);
context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
TreeExpression initializer = 0;
if (hasInitializer) {
@@ -512,7 +511,7 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement
{
ASSERT(match(WITH));
failIfTrueWithMessage(strictMode(), "'with' statements are not valid in strict mode");
- currentScope()->setFlags(UsesWithFlag);
+ currentScope()->setNeedsFullActivation();
int startLine = tokenLine();
next();
consumeOrFail(OPENPAREN);
@@ -527,7 +526,6 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseWithStatement
TreeStatement statement = parseStatement(context, unused);
failIfFalse(statement);
- currentScope()->setFlags(UsesWithFlag);
return context.createWithStatement(m_lexer->lastLineNumber(), expr, statement, start, end, startLine, endLine);
}
@@ -616,15 +614,15 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseTryStatement(
int lastLine = m_lastLine;
if (match(CATCH)) {
- currentScope()->setFlags(UsesCatchFlag);
+ currentScope()->setNeedsFullActivation();
next();
consumeOrFail(OPENPAREN);
matchOrFail(IDENT);
ident = m_token.m_data.ident;
next();
- AutoPopScopeRef catchScope(this, pushScope(currentScope()->modeFlags()));
+ AutoPopScopeRef catchScope(this, pushScope());
failIfFalseIfStrictWithNameAndMessage(declareVariable(ident), "Cannot declare a variable named", ident->impl(), "in strict mode");
- currentScope()->setFlags(BlockScopeFlag | UsesCatchFlag);
+ catchScope->preventNewDecls();
consumeOrFail(CLOSEPAREN);
matchOrFail(OPENBRACE);
catchBlock = parseBlockStatement(context);
@@ -761,7 +759,7 @@ template <typename LexerType>
template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBody(TreeBuilder& context)
{
if (match(CLOSEBRACE))
- return context.createFunctionBody(m_lexer->lastLineNumber(), currentScope()->modeFlags());
+ return context.createFunctionBody(m_lexer->lastLineNumber(), strictMode());
DepthManager statementDepth(&m_statementDepth);
m_statementDepth = 0;
typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast<JSGlobalData*>(m_globalData), m_lexer.get());
@@ -772,7 +770,8 @@ template <class TreeBuilder> TreeFunctionBody Parser<LexerType>::parseFunctionBo
template <typename LexerType>
template <FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
{
- AutoPopScopeRef functionScope(this, pushScope(currentScope()->modeFlags() | FunctionModeFlag));
+ AutoPopScopeRef functionScope(this, pushScope());
+ functionScope->setIsFunction();
if (match(IDENT)) {
name = m_token.m_data.ident;
next();
@@ -794,8 +793,8 @@ template <FunctionRequirements requirements, bool nameIsInContainingScope, class
// If we know about this function already, we can use the cached info and skip the parser to the end of the function.
if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
// If we're in a strict context, the cached function info must say it was strict too.
- ASSERT(!strictMode() || (cachedInfo->scopeFlags & StrictModeFlag));
- body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->scopeFlags);
+ ASSERT(!strictMode() || cachedInfo->strictMode);
+ body = context.createFunctionBody(m_lexer->lastLineNumber(), cachedInfo->strictMode);
functionScope->restoreFunctionInfo(cachedInfo);
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
@@ -855,8 +854,6 @@ template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla
failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
failIfFalse(name);
failIfFalseIfStrict(declareVariable(name));
- if (*name == m_globalData->propertyNames->arguments)
- currentScope()->setFlags(UsesArgumentsFlag);
return context.createFuncDeclStatement(m_lexer->lastLineNumber(), name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
}
@@ -1416,18 +1413,13 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parsePrimaryExpre
}
case THISTOKEN: {
next();
- currentScope()->setFlags(UsesThisFlag);
return context.thisExpr(m_lexer->lastLineNumber());
}
case IDENT: {
int start = tokenStart();
const Identifier* ident = m_token.m_data.ident;
next();
- if (m_globalData->propertyNames->eval == *ident)
- currentScope()->setFlags(UsesEvalFlag);
- else if (m_globalData->propertyNames->arguments == *ident)
- currentScope()->setFlags(UsesArgumentsFlag);
- currentScope()->useVariable(ident);
+ currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
m_lastIdentifier = ident;
return context.createResolve(m_lexer->lastLineNumber(), ident, start);
}
diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h
index c0b13c53a..c2a11d665 100644
--- a/Source/JavaScriptCore/parser/Parser.h
+++ b/Source/JavaScriptCore/parser/Parser.h
@@ -130,19 +130,30 @@ struct ScopeLabelInfo {
};
struct Scope {
- Scope(const JSGlobalData* globalData, ScopeFlags scopeFlags)
+ Scope(const JSGlobalData* globalData, bool isFunction, bool strictMode)
: m_globalData(globalData)
- , m_scopeFlags(scopeFlags)
+ , m_shadowsArguments(false)
+ , m_usesEval(false)
+ , m_needsFullActivation(false)
+ , m_allowsNewDecls(true)
+ , m_strictMode(strictMode)
+ , m_isFunction(isFunction)
+ , m_isFunctionBoundary(false)
, m_isValidStrictMode(true)
, m_loopDepth(0)
, m_switchDepth(0)
{
- ASSERT(!(scopeFlags & ~AllScopeModeFlags));
}
Scope(const Scope& rhs)
: m_globalData(rhs.m_globalData)
- , m_scopeFlags(rhs.m_scopeFlags)
+ , m_shadowsArguments(rhs.m_shadowsArguments)
+ , m_usesEval(rhs.m_usesEval)
+ , m_needsFullActivation(rhs.m_needsFullActivation)
+ , m_allowsNewDecls(rhs.m_allowsNewDecls)
+ , m_strictMode(rhs.m_strictMode)
+ , m_isFunction(rhs.m_isFunction)
+ , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
, m_isValidStrictMode(rhs.m_isValidStrictMode)
, m_loopDepth(rhs.m_loopDepth)
, m_switchDepth(rhs.m_switchDepth)
@@ -157,22 +168,6 @@ struct Scope {
}
}
- ALWAYS_INLINE ScopeFlags scopeFlags() const { return m_scopeFlags; }
- ALWAYS_INLINE ScopeFlags modeFlags() const { return m_scopeFlags & AllScopeModeFlags; }
- ALWAYS_INLINE ScopeFlags usesFlags() const { return m_scopeFlags & AllScopeUsesFlags; }
- ALWAYS_INLINE void setFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; }
-
- ALWAYS_INLINE bool usesEval() const { return m_scopeFlags & UsesEvalFlag; }
- ALWAYS_INLINE bool strictMode() const { return m_scopeFlags & StrictModeFlag; }
- ALWAYS_INLINE bool shadowsArguments() const { return m_scopeFlags & ShadowsArgumentsFlag; }
- ALWAYS_INLINE bool isFunction() const { return m_scopeFlags & FunctionModeFlag; }
- ALWAYS_INLINE bool isBlockScope() const { return m_scopeFlags & BlockScopeFlag; }
- ALWAYS_INLINE bool isFunctionBoundary() const { return isFunction() && !isBlockScope(); }
-
- ALWAYS_INLINE bool allowsNewDecls() const { return !isBlockScope(); }
-
- ALWAYS_INLINE bool isValidStrictMode() const { return m_isValidStrictMode; }
-
void startSwitch() { m_switchDepth++; }
void endSwitch() { m_switchDepth--; }
void startLoop() { m_loopDepth++; }
@@ -206,6 +201,14 @@ struct Scope {
return 0;
}
+ void setIsFunction()
+ {
+ m_isFunction = true;
+ m_isFunctionBoundary = true;
+ }
+ bool isFunction() { return m_isFunction; }
+ bool isFunctionBoundary() { return m_isFunctionBoundary; }
+
bool declareVariable(const Identifier* ident)
{
bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
@@ -216,28 +219,35 @@ struct Scope {
void declareWrite(const Identifier* ident)
{
- ASSERT(strictMode());
+ ASSERT(m_strictMode);
m_writtenVariables.add(ident->impl());
}
+ void preventNewDecls() { m_allowsNewDecls = false; }
+ bool allowsNewDecls() const { return m_allowsNewDecls; }
+
bool declareParameter(const Identifier* ident)
{
bool isArguments = m_globalData->propertyNames->arguments == *ident;
bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).isNewEntry && m_globalData->propertyNames->eval != *ident && !isArguments;
m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
if (isArguments)
- setFlags(ShadowsArgumentsFlag);
+ m_shadowsArguments = true;
return isValidStrictMode;
}
- void useVariable(const Identifier* ident)
+ void useVariable(const Identifier* ident, bool isEval)
{
+ m_usesEval |= isEval;
m_usedVariables.add(ident->ustring().impl());
}
+ void setNeedsFullActivation() { m_needsFullActivation = true; }
+
bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
{
- setFlags(nestedScope->usesFlags());
+ if (nestedScope->m_usesEval)
+ m_usesEval = true;
IdentifierSet::iterator end = nestedScope->m_usedVariables.end();
for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) {
if (nestedScope->m_declaredVariables.contains(*ptr))
@@ -269,7 +279,7 @@ struct Scope {
void getCapturedVariables(IdentifierSet& capturedVariables)
{
- if (usesEval()) {
+ if (m_needsFullActivation || m_usesEval) {
capturedVariables.swap(m_declaredVariables);
return;
}
@@ -279,6 +289,11 @@ struct Scope {
capturedVariables.add(*ptr);
}
}
+ void setStrictMode() { m_strictMode = true; }
+ bool strictMode() const { return m_strictMode; }
+ bool isValidStrictMode() const { return m_isValidStrictMode; }
+ bool shadowsArguments() const { return m_shadowsArguments; }
+
void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector)
{
IdentifierSet::iterator end = capturedVariables.end();
@@ -292,16 +307,20 @@ struct Scope {
void saveFunctionInfo(SourceProviderCacheItem* info)
{
- ASSERT(isFunction());
- info->scopeFlags = m_scopeFlags;
+ ASSERT(m_isFunction);
+ info->usesEval = m_usesEval;
+ info->strictMode = m_strictMode;
+ info->needsFullActivation = m_needsFullActivation;
copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
}
void restoreFunctionInfo(const SourceProviderCacheItem* info)
{
- ASSERT(isFunction());
- m_scopeFlags |= info->scopeFlags;
+ ASSERT(m_isFunction);
+ m_usesEval = info->usesEval;
+ m_strictMode = info->strictMode;
+ m_needsFullActivation = info->needsFullActivation;
unsigned size = info->usedVariables.size();
for (unsigned i = 0; i < size; ++i)
m_usedVariables.add(info->usedVariables[i]);
@@ -312,7 +331,13 @@ struct Scope {
private:
const JSGlobalData* m_globalData;
- ScopeFlags m_scopeFlags;
+ bool m_shadowsArguments : 1;
+ bool m_usesEval : 1;
+ bool m_needsFullActivation : 1;
+ bool m_allowsNewDecls : 1;
+ bool m_strictMode : 1;
+ bool m_isFunction : 1;
+ bool m_isFunctionBoundary : 1;
bool m_isValidStrictMode : 1;
int m_loopDepth;
int m_switchDepth;
@@ -402,14 +427,20 @@ private:
Parser* m_parser;
};
- ALWAYS_INLINE ScopeRef currentScope()
+ ScopeRef currentScope()
{
return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
}
- ScopeRef pushScope(ScopeFlags scopeFlags)
+ ScopeRef pushScope()
{
- m_scopeStack.append(Scope(m_globalData, scopeFlags));
+ bool isFunction = false;
+ bool isStrict = false;
+ if (!m_scopeStack.isEmpty()) {
+ isStrict = m_scopeStack.last().strictMode();
+ isFunction = m_scopeStack.last().isFunction();
+ }
+ m_scopeStack.append(Scope(m_globalData, isFunction, isStrict));
return currentScope();
}
@@ -461,7 +492,7 @@ private:
UString parseInner();
void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
- ParserArenaData<DeclarationStacks::FunctionStack>*, ScopeFlags,
+ ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures,
int, int, IdentifierSet&);
// Used to determine type of error to report.
@@ -792,13 +823,14 @@ private:
m_errorMessage = UString(msg);
}
- ALWAYS_INLINE void startLoop() { currentScope()->startLoop(); }
- ALWAYS_INLINE void endLoop() { currentScope()->endLoop(); }
- ALWAYS_INLINE void startSwitch() { currentScope()->startSwitch(); }
- ALWAYS_INLINE void endSwitch() { currentScope()->endSwitch(); }
- ALWAYS_INLINE bool strictMode() { return currentScope()->strictMode(); }
- ALWAYS_INLINE bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
- ALWAYS_INLINE bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
+ void startLoop() { currentScope()->startLoop(); }
+ void endLoop() { currentScope()->endLoop(); }
+ void startSwitch() { currentScope()->startSwitch(); }
+ void endSwitch() { currentScope()->endSwitch(); }
+ void setStrictMode() { currentScope()->setStrictMode(); }
+ bool strictMode() { return currentScope()->strictMode(); }
+ bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
+ bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
bool breakIsValid()
{
ScopeRef current = currentScope();
@@ -917,7 +949,7 @@ private:
ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
IdentifierSet m_capturedVariables;
- ScopeFlags m_scopeFlags;
+ CodeFeatures m_features;
int m_numConstants;
struct DepthManager {
@@ -978,7 +1010,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj
m_funcDeclarations ? &m_funcDeclarations->data : 0,
m_capturedVariables,
*m_source,
- m_scopeFlags,
+ m_features,
m_numConstants);
result->setLoc(m_source->firstLine(), m_lastLine);
} else if (lexicalGlobalObject) {
diff --git a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h
index ad7a759ce..3662367a0 100644
--- a/Source/JavaScriptCore/parser/SourceProviderCacheItem.h
+++ b/Source/JavaScriptCore/parser/SourceProviderCacheItem.h
@@ -61,7 +61,9 @@ public:
int closeBraceLine;
int closeBracePos;
- unsigned short scopeFlags;
+ bool usesEval;
+ bool strictMode;
+ bool needsFullActivation;
Vector<RefPtr<StringImpl> > usedVariables;
Vector<RefPtr<StringImpl> > writtenVariables;
};
diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h
index 2acb5097d..c2c93756d 100644
--- a/Source/JavaScriptCore/parser/SyntaxChecker.h
+++ b/Source/JavaScriptCore/parser/SyntaxChecker.h
@@ -220,6 +220,7 @@ public:
void appendStatement(int, int) { }
void addVar(const Identifier*, bool) { }
int combineCommaNodes(int, int, int) { return 1; }
+ int evalCount() const { return 0; }
void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
{
if (!m_topBinaryExpr)
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 934533c46..3690c2c33 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -225,7 +225,7 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope
ASSERT(exception);
return exception;
}
- recordParse(evalNode->scopeFlags(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
+ recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
@@ -357,7 +357,7 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc
ASSERT(exception);
return exception;
}
- recordParse(programNode->scopeFlags(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
+ recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
@@ -512,7 +512,7 @@ PassOwnPtr<FunctionCodeBlock> FunctionExecutable::produceCodeBlockFor(ScopeChain
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
- recordParse(body->scopeFlags(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
+ recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
OwnPtr<FunctionCodeBlock> result;
ASSERT((compilationKind == FirstCompilation) == !codeBlockFor(specializationKind));
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 3b979ba82..b9d3e6ee1 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -271,14 +271,14 @@ namespace JSC {
ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext)
: ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
- , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags)
+ , m_features(isInStrictContext ? StrictModeFeature : 0)
{
}
ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
: ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
, m_source(source)
- , m_scopeFlags(isInStrictContext ? StrictModeFlag : NoScopeFlags)
+ , m_features(isInStrictContext ? StrictModeFeature : 0)
{
}
@@ -292,10 +292,10 @@ namespace JSC {
int lineNo() const { return m_firstLine; }
int lastLine() const { return m_lastLine; }
- bool usesEval() const { return m_scopeFlags & UsesEvalFlag; }
- bool usesArguments() const { return m_scopeFlags & UsesArgumentsFlag; }
- bool needsActivation() const { return m_hasCapturedVariables || m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); }
- bool isStrictMode() const { return m_scopeFlags & StrictModeFlag; }
+ bool usesEval() const { return m_features & EvalFeature; }
+ bool usesArguments() const { return m_features & ArgumentsFeature; }
+ bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
+ bool isStrictMode() const { return m_features & StrictModeFeature; }
void unlinkCalls();
@@ -311,16 +311,16 @@ namespace JSC {
#endif
}
- void recordParse(ScopeFlags scopeFlags, bool hasCapturedVariables, int firstLine, int lastLine)
+ void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
{
- m_scopeFlags = scopeFlags;
+ m_features = features;
m_hasCapturedVariables = hasCapturedVariables;
m_firstLine = firstLine;
m_lastLine = lastLine;
}
SourceCode m_source;
- ScopeFlags m_scopeFlags;
+ CodeFeatures m_features;
bool m_hasCapturedVariables;
int m_firstLine;
int m_lastLine;
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 243946ba9..563325ab0 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -112,6 +112,16 @@ void JSFunction::finishCreation(ExecState* exec, FunctionExecutable* executable,
putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
}
+Structure* JSFunction::cacheInheritorID(ExecState* exec)
+{
+ JSValue prototype = get(exec, exec->globalData().propertyNames->prototype);
+ if (prototype.isObject())
+ m_cachedInheritorID.set(exec->globalData(), this, asObject(prototype)->inheritorID(exec->globalData()));
+ else
+ m_cachedInheritorID.set(exec->globalData(), this, globalObject()->emptyObjectStructure());
+ return m_cachedInheritorID.get();
+}
+
const UString& JSFunction::name(ExecState* exec)
{
return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
@@ -332,6 +342,7 @@ void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyNa
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot;
thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ thisObject->m_cachedInheritorID.clear();
}
if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
// This will trigger the property to be reified, if this is not already the case!
@@ -372,6 +383,7 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Iden
// following the rules set out in ECMA-262 8.12.9.
PropertySlot slot;
thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ thisObject->m_cachedInheritorID.clear();
return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index 5553115bf..9de66d721 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -121,6 +121,18 @@ namespace JSC {
return OBJECT_OFFSETOF(JSFunction, m_executable);
}
+ Structure* cachedInheritorID(ExecState* exec)
+ {
+ if (UNLIKELY(!m_cachedInheritorID))
+ return cacheInheritorID(exec);
+ return m_cachedInheritorID.get();
+ }
+
+ static size_t offsetOfCachedInheritorID()
+ {
+ return OBJECT_OFFSETOF(JSFunction, m_cachedInheritorID);
+ }
+
protected:
const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
@@ -130,6 +142,8 @@ namespace JSC {
void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name);
void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*);
+ Structure* cacheInheritorID(ExecState*);
+
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties);
@@ -152,6 +166,7 @@ namespace JSC {
WriteBarrier<ExecutableBase> m_executable;
WriteBarrier<ScopeChainNode> m_scopeChain;
+ WriteBarrier<Structure> m_cachedInheritorID;
};
inline bool JSValue::isFunction() const
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 500f3891a..a8c6c3f3f 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -552,7 +552,7 @@ Structure* JSObject::createInheritorID(JSGlobalData& globalData)
return m_inheritorID.get();
}
-PropertyStorage JSObject::growPropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
+void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize)
{
ASSERT(newSize > oldSize);
@@ -580,7 +580,7 @@ PropertyStorage JSObject::growPropertyStorage(JSGlobalData& globalData, size_t o
}
ASSERT(newPropertyStorage);
- return newPropertyStorage;
+ m_propertyStorage.set(globalData, this, newPropertyStorage);
}
bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index d95860d62..7345bb700 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -212,9 +212,8 @@ namespace JSC {
bool staticFunctionsReified() { return structure()->staticFunctionsReified(); }
void reifyStaticFunctionsForDelete(ExecState* exec);
- JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
+ JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize);
bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); }
- void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*);
void* addressOfPropertyStorage()
{
@@ -453,14 +452,6 @@ inline bool JSObject::isGlobalThis() const
return structure()->typeInfo().type() == GlobalThisType;
}
-inline void JSObject::setPropertyStorage(JSGlobalData& globalData, PropertyStorage storage, Structure* structure)
-{
- ASSERT(storage);
- ASSERT(structure);
- setStructure(globalData, structure);
- m_propertyStorage.set(globalData, this, storage);
-}
-
inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
{
return JSFinalObject::create(exec, structure);
@@ -672,11 +663,10 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
if ((mode == PutModePut) && !isExtensible())
return false;
- PropertyStorage newStorage = propertyStorage();
- if (structure()->shouldGrowPropertyStorage())
- newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+ size_t currentCapacity = structure()->propertyStorageCapacity();
offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
- setPropertyStorage(globalData, newStorage, structure());
+ if (currentCapacity != structure()->propertyStorageCapacity())
+ allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity());
ASSERT(offset < structure()->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
@@ -688,13 +678,12 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
size_t offset;
size_t currentCapacity = structure()->propertyStorageCapacity();
- if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
- PropertyStorage newStorage = propertyStorage();
+ if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
if (currentCapacity != structure->propertyStorageCapacity())
- newStorage = growPropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
+ allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
ASSERT(offset < structure->propertyStorageCapacity());
- setPropertyStorage(globalData, newStorage, structure);
+ setStructure(globalData, structure);
putDirectOffset(globalData, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
@@ -738,14 +727,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
if ((mode == PutModePut) && !isExtensible())
return false;
- PropertyStorage newStorage = propertyStorage();
- if (structure()->shouldGrowPropertyStorage())
- newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
-
Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset);
+ if (currentCapacity != structure->propertyStorageCapacity())
+ allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity());
+
ASSERT(offset < structure->propertyStorageCapacity());
- setPropertyStorage(globalData, newStorage, structure);
+ setStructure(globalData, structure);
putDirectOffset(globalData, offset, value);
// This is a new property; transitions with specific values are not currently cachable,
// so leave the slot in an uncachable state.
@@ -779,20 +767,18 @@ inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& prop
inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
{
ASSERT(!value.isGetterSetter() && !(attributes & Accessor));
- PropertyStorage newStorage = propertyStorage();
- if (structure()->shouldGrowPropertyStorage())
- newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize());
+ size_t currentCapacity = structure()->propertyStorageCapacity();
size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value));
- setPropertyStorage(globalData, newStorage, structure());
+ if (currentCapacity != structure()->propertyStorageCapacity())
+ allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity());
putDirectOffset(globalData, offset, value);
}
inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
{
- PropertyStorage newStorage = propertyStorage();
if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
- newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
- setPropertyStorage(globalData, newStorage, newStructure);
+ allocatePropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
+ setStructure(globalData, newStructure);
}
inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 10ec799e5..c95233deb 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -67,6 +67,7 @@ namespace JSC {
friend class JSGlobalData;
friend class SpecializedThunkJIT;
friend class JSRopeString;
+ friend class MarkStack;
friend struct ThunkHelpers;
typedef JSCell Base;
@@ -91,6 +92,7 @@ namespace JSC {
Base::finishCreation(globalData);
m_length = length;
m_is8Bit = m_value.impl()->is8Bit();
+ m_isHashConstSingleton = false;
}
void finishCreation(JSGlobalData& globalData, size_t length, size_t cost)
@@ -99,6 +101,7 @@ namespace JSC {
Base::finishCreation(globalData);
m_length = length;
m_is8Bit = m_value.impl()->is8Bit();
+ m_isHashConstSingleton = false;
Heap::heap(this)->reportExtraMemoryCost(cost);
}
@@ -108,6 +111,7 @@ namespace JSC {
Base::finishCreation(globalData);
m_length = 0;
m_is8Bit = true;
+ m_isHashConstSingleton = false;
}
public:
@@ -161,9 +165,13 @@ namespace JSC {
protected:
bool isRope() const { return m_value.isNull(); }
bool is8Bit() const { return m_is8Bit; }
+ bool isHashConstSingleton() const { return m_isHashConstSingleton; }
+ void clearHashConstSingleton() { m_isHashConstSingleton = false; }
+ void setHashConstSingleton() { m_isHashConstSingleton = true; }
// A string is represented either by a UString or a rope of fibers.
bool m_is8Bit : 1;
+ bool m_isHashConstSingleton : 1;
unsigned m_length;
mutable UString m_value;
@@ -233,6 +241,7 @@ namespace JSC {
Base::finishCreation(globalData);
m_length = s1->length() + s2->length();
m_is8Bit = (s1->is8Bit() && s2->is8Bit());
+ m_isHashConstSingleton = false;
m_fibers[0].set(globalData, this, s1);
m_fibers[1].set(globalData, this, s2);
}
@@ -242,6 +251,7 @@ namespace JSC {
Base::finishCreation(globalData);
m_length = s1->length() + s2->length() + s3->length();
m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit());
+ m_isHashConstSingleton = false;
m_fibers[0].set(globalData, this, s1);
m_fibers[1].set(globalData, this, s2);
m_fibers[2].set(globalData, this, s3);
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index 074c8b354..ac4b4f1fe 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -267,13 +267,6 @@ void Structure::growPropertyStorageCapacity()
m_propertyStorageCapacity *= 2;
}
-size_t Structure::suggestedNewPropertyStorageSize()
-{
- if (isUsingInlineStorage())
- return JSObject::baseExternalStorageCapacity;
- return m_propertyStorageCapacity * 2;
-}
-
void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName)
{
StringImpl* rep = propertyName.impl();
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 00bc76177..ee580e245 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -102,8 +102,6 @@ namespace JSC {
bool isFrozen(JSGlobalData&);
bool isExtensible() const { return !m_preventExtensions; }
bool didTransition() const { return m_didTransition; }
- bool shouldGrowPropertyStorage() { return propertyStorageCapacity() == propertyStorageSize(); }
- JS_EXPORT_PRIVATE size_t suggestedNewPropertyStorageSize();
Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);