diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-08-24 08:29:43 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-08-24 08:29:43 +0200 |
commit | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (patch) | |
tree | 3b94a9a9fa83efa384b8dac611cf8c6495532a62 /Source/JavaScriptCore | |
parent | f53e6f8e798362ed712d4a51633b0d0b03dbc213 (diff) | |
download | qtwebkit-2e2ba8ff45915f40ed3e014101269c175f2a89a0.tar.gz |
Imported WebKit commit bf0b0213bbf3886c96610020602012ca7d11b084 (http://svn.webkit.org/repository/webkit/trunk@126545)
New snapshot with clang and python build fixes
Diffstat (limited to 'Source/JavaScriptCore')
39 files changed, 600 insertions, 128 deletions
diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp index 04d7f661d..9b7268a2d 100644 --- a/Source/JavaScriptCore/API/JSValueRef.cpp +++ b/Source/JavaScriptCore/API/JSValueRef.cpp @@ -266,7 +266,7 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); - return jsValue.toBoolean(); + return jsValue.toBoolean(exec); } double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 987ca8ecf..a8434ccc7 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,204 @@ +2011-08-23 Geoffrey Garen <ggaren@apple.com> + + Unreviewed, rolling out r126505. + http://trac.webkit.org/changeset/126505 + https://bugs.webkit.org/show_bug.cgi?id=94840 + + Caused testapi to crash on launch + + * DerivedSources.make: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecode/OpcodeDefinitions.h: Removed. + * bytecode/opcodes: Removed. + * opcode_definition_generator.py: Removed. + * opcode_generator.py: Removed. + * opcode_parser.py: Removed. + +2012-08-23 Oliver Hunt <oliver@apple.com> + + Autogenerate Opcode definitions + https://bugs.webkit.org/show_bug.cgi?id=94840 + + Reviewed by Gavin Barraclough. + + Start the process of autogenerating the code emission for the bytecode. + We'll just start with automatic generation of the list of Opcodes as that + requires the actual definition of the opcodes, and the logic for parsing + them. + + Due to some rather annoying dependency cycles, this initial version has + the OpcodeDefinitions.h file checked into the tree, although with some + work I hope to be able to fix that. + + * DerivedSources.make: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/Opcode.h: + Include OpcodeDefinitions.h as our definitive source of info + about the opcodes. + * bytecode/OpcodeDefinitions.h: Added. + Autogenerated file + * bytecode/opcodes: Added. + The new opcode definition file + * opcode_definition_generator.py: Added. + (generateOpcodeDefinition): + (generate): + Module that generates the content for OpcodeDefinitions.h + * opcode_generator.py: Added. + (printUsage): + (main): + Driver script + * opcode_parser.py: Added. + Simple parser for the opcode definitions. + +2012-08-23 Mark Hahnenberg <mhahnenberg@apple.com> + + Change behavior of MasqueradesAsUndefined to better accommodate DFG changes + https://bugs.webkit.org/show_bug.cgi?id=93884 + + Reviewed by Filip Pizlo. + + With some upcoming changes to the DFG to remove uses of ClassInfo, we will be changing the behavior of + MasqueradesAsUndefined. In order to make this change consistent across all of our execution engines, + we will make this change to MasqueradesAsUndefined as a separate patch. After this patch, MasqueradesAsUndefined + objects will only masquerade as undefined in their original context (i.e. their original JSGlobalObject). + For example, if an object that masquerades as undefined in frame A is passed to frame B, it will not + masquerade as undefined within frame B, but it will continue to masquerade in frame A. + + There are two primary changes that are taking place here. One is to thread the ExecState* through + JSValue::toBoolean and JSCell::toBoolean so that JSCell::toBoolean can check the object's + JSGlobalObject to compare it to the lexical JSGlobalObject of the currently running code. If the two + are distinct, then the object cannot MasqueradeAsUndefined. + + The other change is to perform this comparison of JSGlobalObjects everywhere where the MasqueradesAsUndefined + flag in the Structure is checked. For C++ code, this check has been factored into its own function in + Structure::masqueradesAsUndefined. We only perform this check in the DFG if the current JSGlobalObject has + had a MasqueradesAsUndefined object allocated within its context. This conditional compilation is managed + through the use of a WatchpointSet in each JSGlobalObject and alternate create() functions for JS DOM wrappers + that are MasqueradesAsUndefined. + + * API/JSValueRef.cpp: + (JSValueToBoolean): + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * bytecode/Watchpoint.h: + (WatchpointSet): + * debugger/DebuggerCallFrame.h: + (JSC::DebuggerCallFrame::callFrame): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGCFGSimplificationPhase.cpp: + (JSC::DFG::CFGSimplificationPhase::run): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull): + (JSC::DFG::SpeculativeJIT::compile): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_is_undefined): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_eq_null): + (JSC::JIT::emit_op_neq_null): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_is_undefined): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_eq_null): + (JSC::JIT::emit_op_neq_null): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncEvery): + (JSC::arrayProtoFuncSome): + * runtime/BooleanConstructor.cpp: + (JSC::constructBoolean): + (JSC::callBooleanConstructor): + * runtime/JSCell.h: + (JSCell): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::JSGlobalObject): + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::masqueradesAsUndefinedWatchpoint): + * runtime/JSString.h: + (JSC::JSCell::toBoolean): + (JSC::JSValue::toBoolean): + * runtime/JSValue.h: + * runtime/ObjectConstructor.cpp: + (JSC::toPropertyDescriptor): + * runtime/Operations.cpp: + (JSC::jsTypeStringForValue): + (JSC::jsIsObjectType): + * runtime/Operations.h: + (JSC): + (JSC::JSValue::equalSlowCaseInline): + * runtime/RegExpConstructor.cpp: + (JSC::setRegExpConstructorMultiline): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + * runtime/Structure.h: + (Structure): + (JSC::Structure::globalObjectOffset): + (JSC::Structure::masqueradesAsUndefined): + (JSC): + +2012-08-23 Mark Rowe <mrowe@apple.com> + + Make JavaScriptCore build with the latest version of clang. + + Reviewed by Dan Bernstein. + + * heap/MachineStackMarker.cpp: + (JSC::MachineThreads::MachineThreads): The m_heap member is only used within + assertions, so guard its initialization with !ASSERT_DISABLED. + * heap/MachineStackMarker.h: + (MachineThreads): Ditto for its declaration. + * jit/JITStubCall.h: + (JSC::JITStubCall::JITStubCall): The m_returnType member is only used within + assertions or if we're using JSVALUE32_64, so guard its uses with the appropriate + #if. + (JITStubCall): Ditto. + +2012-08-23 Christophe Dumez <christophe.dumez@intel.com> + + Serialization of JavaScript values does not appear to respect new HTML5 Structured Clone semantics + https://bugs.webkit.org/show_bug.cgi?id=65292 + + Reviewed by Oliver Hunt. + + Add function to construct a StringObject from a JSValue. + Similar functions already exist for NumberObject and + BooleanObject for example. + + Export several symbols so address linking errors in + WebCore. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/BooleanObject.h: + (BooleanObject): + * runtime/NumberObject.h: + (NumberObject): + (JSC): + * runtime/StringObject.cpp: + (JSC::constructString): + (JSC): + * runtime/StringObject.h: + (JSC): + 2012-08-22 Filip Pizlo <fpizlo@apple.com> Array accesses should remember what kind of array they are predicted to access diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index b619d3602..cff1fe049 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 537; -MINOR_VERSION = 6; +MINOR_VERSION = 8; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 8032ed178..e3453201b 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -1,6 +1,7 @@ EXPORTS ??0ArrayBufferView@WTF@@IAE@V?$PassRefPtr@VArrayBuffer@WTF@@@1@I@Z + ??0BooleanObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@@Z ??0CString@WTF@@QAE@PBD@Z ??0CString@WTF@@QAE@PBDI@Z ??0Collator@WTF@@QAE@PBD@Z @@ -107,6 +108,8 @@ EXPORTS ?constructArray@JSC@@YAPAVJSArray@1@PAVExecState@1@ABVArgList@1@@Z ?constructEmptyObject@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z ?constructFunctionSkippingEvalEnabledCheck@JSC@@YAPAVJSObject@1@PAVExecState@1@PAVJSGlobalObject@1@ABVArgList@1@ABVIdentifier@1@ABVUString@1@ABVTextPosition@WTF@@@Z + ?constructNumber@JSC@@YAPAVNumberObject@1@PAVExecState@1@PAVJSGlobalObject@1@VJSValue@1@@Z + ?constructString@JSC@@YAPAVStringObject@1@PAVExecState@1@PAVJSGlobalObject@1@VJSValue@1@@Z ?convertLatin1ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBEPBEPAPADPAD@Z ?convertUTF16ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPB_WPB_WPAPADPAD_N@Z ?convertUTF8ToUTF16@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBDPBDPAPA_WPA_W_N@Z @@ -186,6 +189,7 @@ EXPORTS ?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@PAV?$WriteBarrierBase@W4Unknown@JSC@@@2@@Z ?finalize@WeakHandleOwner@JSC@@UAEXV?$Handle@W4Unknown@JSC@@@2@PAX@Z ?findAllocator@WeakSet@JSC@@AAEPAUFreeCell@WeakBlock@2@XZ + ?finishCreation@BooleanObject@JSC@@IAEXAAVJSGlobalData@2@@Z ?finishCreation@DateInstance@JSC@@IAEXAAVJSGlobalData@2@N@Z ?finishCreation@InternalFunction@JSC@@IAEXAAVJSGlobalData@2@ABVUString@2@@Z ?finishCreation@JSArray@JSC@@IAEXAAVJSGlobalData@2@I@Z @@ -258,6 +262,7 @@ EXPORTS ?neuter@ArrayBufferView@WTF@@MAEXXZ ?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z ?notifyWriteSlow@SymbolTableEntry@JSC@@AAEXXZ + ?notifyWriteSlow@WatchpointSet@JSC@@QAEXXZ ?nullptr@@3Vnullptr_t@std@@A ?number@String@WTF@@SA?AV12@NII@Z ?number@UString@JSC@@SA?AV12@H@Z diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h index 8e0526c0f..e6fba93a9 100644 --- a/Source/JavaScriptCore/bytecode/Watchpoint.h +++ b/Source/JavaScriptCore/bytecode/Watchpoint.h @@ -78,7 +78,7 @@ public: bool* addressOfIsWatched() { return &m_isWatched; } - void notifyWriteSlow(); // Call only if you've checked isWatched. + JS_EXPORT_PRIVATE void notifyWriteSlow(); // Call only if you've checked isWatched. private: void fireAllWatchpoints(); diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h index 8605af54d..dca7487c0 100644 --- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h @@ -48,6 +48,7 @@ namespace JSC { { } + CallFrame* callFrame() const { return m_callFrame; } JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); } ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); } JS_EXPORT_PRIVATE const UString* functionName() const; diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index cfe915947..43b5a03f3 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -618,7 +618,7 @@ bool AbstractState::execute(unsigned indexInBlock) case LogicalNot: { JSValue childConst = forNode(node.child1()).value(); - if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean()))) { + if (childConst && trySetConstant(nodeIndex, jsBoolean(!childConst.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec())))) { m_foundConstants = true; node.setCanExit(false); break; @@ -650,16 +650,23 @@ bool AbstractState::execute(unsigned indexInBlock) case IsString: case IsObject: case IsFunction: { - node.setCanExit(false); + node.setCanExit(node.op() == IsUndefined && m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()); JSValue child = forNode(node.child1()).value(); if (child) { bool constantWasSet; switch (node.op()) { case IsUndefined: - constantWasSet = trySetConstant(nodeIndex, jsBoolean( - child.isCell() - ? child.asCell()->structure()->typeInfo().masqueradesAsUndefined() - : child.isUndefined())); + if (m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + constantWasSet = trySetConstant(nodeIndex, jsBoolean( + child.isCell() + ? false + : child.isUndefined())); + } else { + constantWasSet = trySetConstant(nodeIndex, jsBoolean( + child.isCell() + ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node.codeOrigin)) + : child.isUndefined())); + } break; case IsBoolean: constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isBoolean())); @@ -739,8 +746,8 @@ bool AbstractState::execute(unsigned indexInBlock) && m_graph.valueOfJSConstant(node.child1().index()).isNull()) || (m_graph.isConstant(node.child2().index()) && m_graph.valueOfJSConstant(node.child2().index()).isNull())) { - // We know that this won't clobber the world. But that's all we know. - node.setCanExit(false); + // We can exit if we haven't fired the MasqueradesAsUndefind watchpoint yet. + node.setCanExit(m_codeBlock->globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()); break; } @@ -1077,7 +1084,7 @@ bool AbstractState::execute(unsigned indexInBlock) case Branch: { JSValue value = forNode(node.child1()).value(); if (value) { - bool booleanValue = value.toBoolean(); + bool booleanValue = value.toBoolean(m_codeBlock->globalObjectFor(node.codeOrigin)->globalExec()); if (booleanValue) m_branchDirection = TakeTrue; else diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp index f054707e2..aecce83ed 100644 --- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp @@ -101,7 +101,7 @@ public: // Branch on constant -> jettison the not-taken block and merge. if (m_graph[m_graph[block->last()].child1()].hasConstant()) { bool condition = - m_graph.valueOfJSConstant(m_graph[block->last()].child1().index()).toBoolean(); + m_graph.valueOfJSConstant(m_graph[block->last()].child1().index()).toBoolean(m_graph.globalObjectFor(m_graph[block->last()].codeOrigin)->globalExec()); BasicBlock* targetBlock = m_graph.m_blocks[ m_graph.successorForCondition(block, condition)].get(); if (targetBlock->m_predecessors.size() == 1) { diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 882e1cd02..b5c3b961b 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -1273,9 +1273,9 @@ JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* fu return function; } -size_t DFG_OPERATION operationIsObject(EncodedJSValue value) +size_t DFG_OPERATION operationIsObject(ExecState* exec, EncodedJSValue value) { - return jsIsObjectType(JSValue::decode(value)); + return jsIsObjectType(exec, JSValue::decode(value)); } size_t DFG_OPERATION operationIsFunction(EncodedJSValue value) @@ -1368,7 +1368,7 @@ size_t DFG_OPERATION dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); - return JSValue::decode(encodedOp).toBoolean(); + return JSValue::decode(encodedOp).toBoolean(exec); } #if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE) diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index 0ff721216..455c2bcc3 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -180,7 +180,7 @@ EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t, int3 JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*) WTF_INTERNAL; JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*) WTF_INTERNAL; double DFG_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL; -size_t DFG_OPERATION operationIsObject(EncodedJSValue) WTF_INTERNAL; +size_t DFG_OPERATION operationIsObject(ExecState*, EncodedJSValue) WTF_INTERNAL; size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL; void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL; char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState*) WTF_INTERNAL; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index 26a48dcec..846d078ba 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -623,10 +623,29 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool inv JITCompiler::Jump notCell; if (!isKnownCell(operand.index())) notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag)); - - m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultPayloadGPR); - m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultPayloadGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultPayloadGPR); - + + JITCompiler::Jump notMasqueradesAsUndefined; + if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR); + notMasqueradesAsUndefined = m_jit.jump(); + } else { + m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultPayloadGPR); + JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(resultPayloadGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)); + + m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR); + notMasqueradesAsUndefined = m_jit.jump(); + + isMasqueradesAsUndefined.link(&m_jit); + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); + m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR); + } + if (!isKnownCell(operand.index())) { JITCompiler::Jump done = m_jit.jump(); @@ -640,6 +659,8 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool inv done.link(&m_jit); } + notMasqueradesAsUndefined.link(&m_jit); + booleanResult(resultPayloadGPR, m_compileIndex); } @@ -668,9 +689,22 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex br if (!isKnownCell(operand.index())) notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag)); - m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultGPR); - branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), taken); - + if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + jump(invert ? taken : notTaken, ForceJump); + } else { + m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureOffset()), resultGPR); + branchTest8(JITCompiler::Zero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), invert ? taken : notTaken); + + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); + branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken); + } + if (!isKnownCell(operand.index())) { jump(notTaken, ForceJump); @@ -3580,9 +3614,28 @@ void SpeculativeJIT::compile(Node& node) JITCompiler::Jump done = m_jit.jump(); isCell.link(&m_jit); - m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr()); - m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr()); - + JITCompiler::Jump notMasqueradesAsUndefined; + if (m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + m_jit.move(TrustedImm32(0), result.gpr()); + notMasqueradesAsUndefined = m_jit.jump(); + } else { + m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr()); + JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + m_jit.move(TrustedImm32(0), result.gpr()); + notMasqueradesAsUndefined = m_jit.jump(); + + isMasqueradesAsUndefined.link(&m_jit); + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); + m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr()); + } + + notMasqueradesAsUndefined.link(&m_jit); done.link(&m_jit); booleanResult(result.gpr(), m_compileIndex); break; diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index c2e207264..b69d53600 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -588,10 +588,29 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool inv if (!isKnownCell(operand.index())) notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister); - - m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); - m_jit.test8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), resultGPR); - + + JITCompiler::Jump notMasqueradesAsUndefined; + if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR); + notMasqueradesAsUndefined = m_jit.jump(); + } else { + m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); + JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined)); + + m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR); + notMasqueradesAsUndefined = m_jit.jump(); + + isMasqueradesAsUndefined.link(&m_jit); + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); + m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR); + } + if (!isKnownCell(operand.index())) { JITCompiler::Jump done = m_jit.jump(); @@ -603,7 +622,9 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool inv done.link(&m_jit); } - + + notMasqueradesAsUndefined.link(&m_jit); + m_jit.or32(TrustedImm32(ValueFalse), resultGPR); jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } @@ -632,9 +653,22 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex br if (!isKnownCell(operand.index())) notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister); - m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); - branchTest8(invert ? JITCompiler::Zero : JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), taken); - + if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + jump(invert ? taken : notTaken, ForceJump); + } else { + m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR); + branchTest8(JITCompiler::Zero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), invert ? taken : notTaken); + + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); + branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken); + } + if (!isKnownCell(operand.index())) { jump(notTaken, ForceJump); @@ -3553,9 +3587,28 @@ void SpeculativeJIT::compile(Node& node) JITCompiler::Jump done = m_jit.jump(); isCell.link(&m_jit); - m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr()); - m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr()); - + JITCompiler::Jump notMasqueradesAsUndefined; + if (m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { + m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); + m_jit.move(TrustedImm32(0), result.gpr()); + notMasqueradesAsUndefined = m_jit.jump(); + } else { + m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr()); + JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + m_jit.move(TrustedImm32(0), result.gpr()); + notMasqueradesAsUndefined = m_jit.jump(); + + isMasqueradesAsUndefined.link(&m_jit); + GPRTemporary localGlobalObject(this); + GPRTemporary remoteGlobalObject(this); + GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); + GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); + m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), localGlobalObjectGPR); + m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); + m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr()); + } + + notMasqueradesAsUndefined.link(&m_jit); done.link(&m_jit); m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp index 537a34e48..3c7ff9c3e 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp @@ -133,10 +133,13 @@ public: }; MachineThreads::MachineThreads(Heap* heap) - : m_heap(heap) - , m_registeredThreads(0) + : m_registeredThreads(0) , m_threadSpecific(0) +#if !ASSERT_DISABLED + , m_heap(heap) +#endif { + UNUSED_PARAM(heap); } MachineThreads::~MachineThreads() diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h index 3d4aa22d4..cece29cd3 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.h +++ b/Source/JavaScriptCore/heap/MachineStackMarker.h @@ -52,10 +52,12 @@ namespace JSC { void gatherFromOtherThread(ConservativeRoots&, Thread*); - Heap* m_heap; Mutex m_registeredThreadsMutex; Thread* m_registeredThreads; WTF::ThreadSpecificKey m_threadSpecific; +#if !ASSERT_DISABLED + Heap* m_heap; +#endif }; } // namespace JSC diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index a9118f43b..f6a197ef0 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -2118,7 +2118,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined()); + callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())); vPC += OPCODE_LENGTH(op_eq_null); NEXT_INSTRUCTION(); } @@ -2158,7 +2158,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->typeInfo().masqueradesAsUndefined()); + callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())); vPC += OPCODE_LENGTH(op_neq_null); NEXT_INSTRUCTION(); } @@ -2632,7 +2632,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = vPC[1].u.operand; int src = vPC[2].u.operand; - JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean()); + JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->uncheckedR(dst) = result; @@ -2708,7 +2708,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = vPC[1].u.operand; int src = vPC[2].u.operand; JSValue v = callFrame->r(src).jsValue(); - callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()); + callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()) : v.isUndefined()); vPC += OPCODE_LENGTH(op_is_undefined); NEXT_INSTRUCTION(); @@ -2764,7 +2764,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = vPC[1].u.operand; int src = vPC[2].u.operand; - callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue())); + callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame, callFrame->r(src).jsValue())); vPC += OPCODE_LENGTH(op_is_object); NEXT_INSTRUCTION(); @@ -3980,7 +3980,7 @@ skip_id_custom_self: */ int cond = vPC[1].u.operand; int target = vPC[2].u.operand; - if (callFrame->r(cond).jsValue().toBoolean()) { + if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; CHECK_FOR_TIMEOUT(); NEXT_INSTRUCTION(); @@ -4000,7 +4000,7 @@ skip_id_custom_self: */ int cond = vPC[1].u.operand; int target = vPC[2].u.operand; - if (!callFrame->r(cond).jsValue().toBoolean()) { + if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; CHECK_FOR_TIMEOUT(); NEXT_INSTRUCTION(); @@ -4017,7 +4017,7 @@ skip_id_custom_self: */ int cond = vPC[1].u.operand; int target = vPC[2].u.operand; - if (callFrame->r(cond).jsValue().toBoolean()) { + if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } @@ -4033,7 +4033,7 @@ skip_id_custom_self: */ int cond = vPC[1].u.operand; int target = vPC[2].u.operand; - if (!callFrame->r(cond).jsValue().toBoolean()) { + if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } @@ -4051,7 +4051,7 @@ skip_id_custom_self: int target = vPC[2].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); - if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { + if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject()))) { vPC += target; NEXT_INSTRUCTION(); } @@ -4069,7 +4069,7 @@ skip_id_custom_self: int target = vPC[2].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); - if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { + if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !(srcValue.asCell()->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())))) { vPC += target; NEXT_INSTRUCTION(); } diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 0d24961b8..8ebad61ff 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -479,8 +479,16 @@ void JIT::emit_op_is_undefined(Instruction* currentInstruction) isCell.link(this); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); - + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(0), regT0); + Jump notMasqueradesAsUndefined = jump(); + + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT1, Structure::globalObjectOffset()), regT1); + comparePtr(Equal, regT0, regT1, regT0); + + notMasqueradesAsUndefined.link(this); done.link(this); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); @@ -760,15 +768,18 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); - Jump wasNotImmediate = jump(); + Jump isNotMasqueradesAsUndefined = branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + addJump(branchPtr(Equal, Address(regT2, Structure::globalObjectOffset()), regT0), target); + Jump masqueradesGlobalObjectIsForeign = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); andPtr(TrustedImm32(~TagBitUndefined), regT0); addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target); - wasNotImmediate.link(this); + isNotMasqueradesAsUndefined.link(this); + masqueradesGlobalObjectIsForeign.link(this); }; void JIT::emit_op_jneq_null(Instruction* currentInstruction) { @@ -781,6 +792,8 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, JSCell::structureOffset()), regT2); addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + addJump(branchPtr(NotEqual, Address(regT2, Structure::globalObjectOffset()), regT0), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null @@ -1172,8 +1185,14 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - test8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); - + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(0), regT0); + Jump wasNotMasqueradesAsUndefined = jump(); + + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2); + comparePtr(Equal, regT0, regT2, regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); @@ -1182,6 +1201,7 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) comparePtr(Equal, regT0, TrustedImm32(ValueNull), regT0); wasNotImmediate.link(this); + wasNotMasqueradesAsUndefined.link(this); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); @@ -1197,8 +1217,14 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - test8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); - + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(1), regT0); + Jump wasNotMasqueradesAsUndefined = jump(); + + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2); + comparePtr(NotEqual, regT0, regT2, regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); @@ -1207,6 +1233,7 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) comparePtr(NotEqual, regT0, TrustedImm32(ValueNull), regT0); wasNotImmediate.link(this); + wasNotMasqueradesAsUndefined.link(this); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst); diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index eec9df36f..00c886eb7 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -646,8 +646,16 @@ void JIT::emit_op_is_undefined(Instruction* currentInstruction) isCell.link(this); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(0), regT0); + Jump notMasqueradesAsUndefined = jump(); + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT1, Structure::globalObjectOffset()), regT1); + compare32(Equal, regT0, regT1, regT0); + + notMasqueradesAsUndefined.link(this); done.link(this); emitStoreBool(dst, regT0); } @@ -930,18 +938,19 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, JSCell::structureOffset()), regT2); - addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); - - Jump wasNotImmediate = jump(); + Jump isNotMasqueradesAsUndefined = branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + addJump(branchPtr(Equal, Address(regT2, Structure::globalObjectOffset()), regT0), target); + Jump masqueradesGlobalObjectIsForeign = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); - ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1)); or32(TrustedImm32(1), regT1); addJump(branch32(Equal, regT1, TrustedImm32(JSValue::NullTag)), target); - wasNotImmediate.link(this); + isNotMasqueradesAsUndefined.link(this); + masqueradesGlobalObjectIsForeign.link(this); } void JIT::emit_op_jneq_null(Instruction* currentInstruction) @@ -956,7 +965,8 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, JSCell::structureOffset()), regT2); addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); - + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + addJump(branchPtr(NotEqual, Address(regT2, Structure::globalObjectOffset()), regT0), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null @@ -1158,8 +1168,14 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1); - + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(0), regT1); + Jump wasNotMasqueradesAsUndefined = jump(); + + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2); + compare32(Equal, regT0, regT2, regT1); Jump wasNotImmediate = jump(); isImmediate.link(this); @@ -1169,6 +1185,7 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) or32(regT2, regT1); wasNotImmediate.link(this); + wasNotMasqueradesAsUndefined.link(this); emitStoreBool(dst, regT1); } @@ -1182,8 +1199,14 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); loadPtr(Address(regT0, JSCell::structureOffset()), regT1); - test8(Zero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1); - + Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)); + move(TrustedImm32(1), regT1); + Jump wasNotMasqueradesAsUndefined = jump(); + + isMasqueradesAsUndefined.link(this); + move(TrustedImmPtr(m_codeBlock->globalObject()), regT0); + loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2); + compare32(NotEqual, regT0, regT2, regT1); Jump wasNotImmediate = jump(); isImmediate.link(this); @@ -1193,6 +1216,7 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) and32(regT2, regT1); wasNotImmediate.link(this); + wasNotMasqueradesAsUndefined.link(this); emitStoreBool(dst, regT1); } diff --git a/Source/JavaScriptCore/jit/JITStubCall.h b/Source/JavaScriptCore/jit/JITStubCall.h index a525ff227..352956559 100644 --- a/Source/JavaScriptCore/jit/JITStubCall.h +++ b/Source/JavaScriptCore/jit/JITStubCall.h @@ -37,7 +37,9 @@ namespace JSC { JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(Cell) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -45,7 +47,9 @@ namespace JSC { JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(Cell) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -53,7 +57,9 @@ namespace JSC { JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(VoidPtr) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -61,7 +67,9 @@ namespace JSC { JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(Int) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -69,7 +77,9 @@ namespace JSC { JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(Int) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -77,7 +87,9 @@ namespace JSC { JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) , m_stub(stub) +#if USE(JSVALUE32_64) || !ASSERT_DISABLED , m_returnType(Void) +#endif , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } @@ -265,7 +277,9 @@ namespace JSC { JIT* m_jit; FunctionPtr m_stub; +#if USE(JSVALUE32_64) || !ASSERT_DISABLED enum { Void, VoidPtr, Int, Value, Cell } m_returnType; +#endif size_t m_stackIndex; }; } diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index cb5adc2fa..cc899587f 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -2777,7 +2777,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_not) JSValue src = stackFrame.args[0].jsValue(); - JSValue result = jsBoolean(!src.toBoolean()); + JSValue result = jsBoolean(!src.toBoolean(stackFrame.callFrame)); CHECK_FOR_EXCEPTION_AT_END(); return JSValue::encode(result); } @@ -2788,7 +2788,7 @@ DEFINE_STUB_FUNCTION(int, op_jtrue) JSValue src1 = stackFrame.args[0].jsValue(); - bool result = src1.toBoolean(); + bool result = src1.toBoolean(stackFrame.callFrame); CHECK_FOR_EXCEPTION_AT_END(); return result; } @@ -2819,13 +2819,13 @@ DEFINE_STUB_FUNCTION(int, op_eq) start: if (src2.isUndefined()) { return src1.isNull() || - (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined()) + (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject())) || src1.isUndefined(); } if (src2.isNull()) { return src1.isUndefined() || - (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined()) + (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject())) || src1.isNull(); } @@ -2862,10 +2862,10 @@ DEFINE_STUB_FUNCTION(int, op_eq) } if (src1.isUndefined()) - return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()); if (src1.isNull()) - return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()); JSCell* cell1 = src1.asCell(); @@ -3178,7 +3178,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object) { STUB_INIT_STACK_FRAME(stackFrame); - return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue()))); + return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.callFrame, stackFrame.args[0].jsValue()))); } DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function) diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index 58bf1bdeb..eef54ac7b 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -517,7 +517,7 @@ LLINT_SLOW_PATH_DECL(slow_path_new_regexp) LLINT_SLOW_PATH_DECL(slow_path_not) { LLINT_BEGIN(); - LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean())); + LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec))); } LLINT_SLOW_PATH_DECL(slow_path_eq) @@ -739,7 +739,7 @@ LLINT_SLOW_PATH_DECL(slow_path_typeof) LLINT_SLOW_PATH_DECL(slow_path_is_object) { LLINT_BEGIN(); - LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue()))); + LLINT_RETURN(jsBoolean(jsIsObjectType(exec, LLINT_OP_C(2).jsValue()))); } LLINT_SLOW_PATH_DECL(slow_path_is_function) @@ -1173,13 +1173,13 @@ LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes) LLINT_SLOW_PATH_DECL(slow_path_jtrue) { LLINT_BEGIN(); - LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean()); + LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec)); } LLINT_SLOW_PATH_DECL(slow_path_jfalse) { LLINT_BEGIN(); - LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean()); + LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec)); } LLINT_SLOW_PATH_DECL(slow_path_jless) diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 5f280ce1b..c0f136889 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -444,7 +444,13 @@ _llint_op_eq_null: loadi PayloadOffset[cfr, t0, 8], t0 bineq t1, CellTag, .opEqNullImmediate loadp JSCell::m_structure[t0], t1 - tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + btbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, .opEqNullMasqueradesAsUndefined + move 0, t1 + jmp .opEqNullNotImmediate +.opEqNullMasqueradesAsUndefined: + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + cpeq Structure::m_globalObject[t1], t0, t1 jmp .opEqNullNotImmediate .opEqNullImmediate: cieq t1, NullTag, t2 @@ -485,7 +491,13 @@ _llint_op_neq_null: loadi PayloadOffset[cfr, t0, 8], t0 bineq t1, CellTag, .opNeqNullImmediate loadp JSCell::m_structure[t0], t1 - tbz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + btbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, .opNeqNullMasqueradesAsUndefined + move 1, t1 + jmp .opNeqNullNotImmediate +.opNeqNullMasqueradesAsUndefined: + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + cpneq Structure::m_globalObject[t1], t0, t1 jmp .opNeqNullNotImmediate .opNeqNullImmediate: cineq t1, NullTag, t2 @@ -875,7 +887,14 @@ _llint_op_is_undefined: dispatch(3) .opIsUndefinedCell: loadp JSCell::m_structure[t3], t1 - tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + btbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, .opIsUndefinedMasqueradesAsUndefined + move 0, t1 + storei t1, PayloadOffset[cfr, t0, 8] + dispatch(3) +.opIsUndefinedMasqueradesAsUndefined: + loadp CodeBlock[cfr], t3 + loadp CodeBlock::m_globalObject[t3], t3 + cpeq Structure::m_globalObject[t1], t3, t1 storei t1, PayloadOffset[cfr, t0, 8] dispatch(3) @@ -1406,7 +1425,7 @@ macro equalNull(cellHandler, immediateHandler) loadi PayloadOffset[cfr, t0, 8], t0 bineq t1, CellTag, .immediate loadp JSCell::m_structure[t0], t2 - cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) + cellHandler(t2, Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) dispatch(3) .target: @@ -1421,14 +1440,25 @@ end _llint_op_jeq_null: traceExecution() equalNull( - macro (value, target) btbnz value, MasqueradesAsUndefined, target end, + macro (structure, value, target) + btbz value, MasqueradesAsUndefined, .opJeqNullNotMasqueradesAsUndefined + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + bpeq Structure::m_globalObject[structure], t0, target +.opJeqNullNotMasqueradesAsUndefined: + end, macro (value, target) bieq value, NullTag, target end) _llint_op_jneq_null: traceExecution() equalNull( - macro (value, target) btbz value, MasqueradesAsUndefined, target end, + macro (structure, value, target) + btbz value, MasqueradesAsUndefined, target + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + bpneq Structure::m_globalObject[structure], t0, target + end, macro (value, target) bineq value, NullTag, target end) diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm index f1a7e2998..73e8613de 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -324,7 +324,13 @@ macro equalNullComparison() loadp [cfr, t0, 8], t0 btpnz t0, tagMask, .immediate loadp JSCell::m_structure[t0], t2 - tbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, t0 + btbnz Structure::m_typeInfo + TypeInfo::m_flags[t2], MasqueradesAsUndefined, .masqueradesAsUndefined + move 0, t0 + jmp .done +.masqueradesAsUndefined: + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + cpeq Structure::m_globalObject[t2], t0, t0 jmp .done .immediate: andp ~TagBitUndefined, t0 @@ -733,10 +739,17 @@ _llint_op_is_undefined: dispatch(3) .opIsUndefinedCell: loadp JSCell::m_structure[t0], t0 - tbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, t1 - orp ValueFalse, t1 + btbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, .masqueradesAsUndefined + move ValueFalse, t1 storep t1, [cfr, t2, 8] dispatch(3) +.masqueradesAsUndefined: + loadp CodeBlock[cfr], t1 + loadp CodeBlock::m_globalObject[t1], t1 + cpeq Structure::m_globalObject[t0], t1, t3 + orp ValueFalse, t3 + storep t3, [cfr, t2, 8] + dispatch(3) _llint_op_is_boolean: @@ -1250,7 +1263,7 @@ macro equalNull(cellHandler, immediateHandler) loadp [cfr, t0, 8], t0 btpnz t0, tagMask, .immediate loadp JSCell::m_structure[t0], t2 - cellHandler(Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) + cellHandler(t2, Structure::m_typeInfo + TypeInfo::m_flags[t2], .target) dispatch(3) .target: @@ -1265,14 +1278,25 @@ end _llint_op_jeq_null: traceExecution() equalNull( - macro (value, target) btbnz value, MasqueradesAsUndefined, target end, + macro (structure, value, target) + btbz value, MasqueradesAsUndefined, .notMasqueradesAsUndefined + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + bpeq Structure::m_globalObject[structure], t0, target +.notMasqueradesAsUndefined: + end, macro (value, target) bpeq value, ValueNull, target end) _llint_op_jneq_null: traceExecution() equalNull( - macro (value, target) btbz value, MasqueradesAsUndefined, target end, + macro (structure, value, target) + btbz value, MasqueradesAsUndefined, target + loadp CodeBlock[cfr], t0 + loadp CodeBlock::m_globalObject[t0], t0 + bpneq Structure::m_globalObject[structure], t0, target + end, macro (value, target) bpneq value, ValueNull, target end) diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index b0adb7f0f..a97cf82de 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -797,7 +797,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (result.toBoolean()) + if (result.toBoolean(exec)) resultArray->putDirectIndex(exec, filterIndex++, v); } if (k == length) @@ -818,7 +818,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) eachArguments.append(thisObj); JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result.toBoolean()) + if (result.toBoolean(exec)) resultArray->putDirectIndex(exec, filterIndex++, v); } return JSValue::encode(resultArray); @@ -917,7 +917,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) cachedCall.setArgument(1, jsNumber(k)); cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (!result.toBoolean()) + if (!result.toBoolean(exec)) return JSValue::encode(jsBoolean(false)); } } @@ -934,7 +934,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (!predicateResult) { result = jsBoolean(false); break; @@ -1025,7 +1025,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) cachedCall.setArgument(1, jsNumber(k)); cachedCall.setArgument(2, thisObj); JSValue result = cachedCall.call(); - if (result.toBoolean()) + if (result.toBoolean(exec)) return JSValue::encode(jsBoolean(true)); } } @@ -1042,7 +1042,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) if (exec->hadException()) return JSValue::encode(jsUndefined()); - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(); + bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); if (predicateResult) { result = jsBoolean(true); break; diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 090be0aaa..9b666292c 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -49,7 +49,7 @@ void BooleanConstructor::finishCreation(ExecState* exec, BooleanPrototype* boole JSObject* constructBoolean(ExecState* exec, const ArgList& args) { BooleanObject* obj = BooleanObject::create(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); - obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean())); + obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -68,7 +68,7 @@ ConstructType BooleanConstructor::getConstructData(JSCell*, ConstructData& const // ECMA 15.6.1 static EncodedJSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec) { - return JSValue::encode(jsBoolean(exec->argument(0).toBoolean())); + return JSValue::encode(jsBoolean(exec->argument(0).toBoolean(exec))); } CallType BooleanConstructor::getCallData(JSCell*, CallData& callData) diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index 2704ff3cd..bd0f66944 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -27,8 +27,8 @@ namespace JSC { class BooleanObject : public JSWrapperObject { protected: - BooleanObject(JSGlobalData&, Structure*); - void finishCreation(JSGlobalData&); + JS_EXPORT_PRIVATE BooleanObject(JSGlobalData&, Structure*); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&); public: typedef JSWrapperObject Base; @@ -40,7 +40,7 @@ namespace JSC { return boolean; } - static const ClassInfo s_info; + static JS_EXPORTDATA const ClassInfo s_info; static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 90e531cec..39f98356f 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -98,7 +98,7 @@ namespace JSC { // Basic conversions. JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; - bool toBoolean() const; + bool toBoolean(ExecState*) const; JS_EXPORT_PRIVATE double toNumber(ExecState*) const; JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 0edc0a8a9..ff7b1486f 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -115,6 +115,7 @@ template <typename T> static inline void visitIfNeeded(SlotVisitor& visitor, Wri JSGlobalObject::JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable) : JSSegmentedVariableObject(globalData, structure, &m_symbolTable) , m_globalScopeChain() + , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(InitializedWatching))) , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) , m_evalEnabled(true) , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index af03f32e6..248004bd5 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -30,6 +30,7 @@ #include "NumberPrototype.h" #include "StringPrototype.h" #include "StructureChain.h" +#include "Watchpoint.h" #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/RandomNumber.h> @@ -142,6 +143,8 @@ namespace JSC { Debugger* m_debugger; + RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint; + OwnPtr<JSGlobalObjectRareData> m_rareData; WeakRandom m_weakRandom; @@ -270,6 +273,8 @@ namespace JSC { Structure* regExpStructure() const { return m_regExpStructure.get(); } Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } + WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); } + void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; } unsigned profileGroup() const { diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index d6fc4c2a1..e91553aeb 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -500,23 +500,23 @@ namespace JSC { inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; } - inline bool JSCell::toBoolean() const + inline bool JSCell::toBoolean(ExecState* exec) const { if (isString()) return static_cast<const JSString*>(this)->toBoolean(); - return !structure()->typeInfo().masqueradesAsUndefined(); + return !structure()->masqueradesAsUndefined(exec->lexicalGlobalObject()); } // --- JSValue inlines ---------------------------- - inline bool JSValue::toBoolean() const + inline bool JSValue::toBoolean(ExecState* exec) const { if (isInt32()) return asInt32(); if (isDouble()) return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN if (isCell()) - return asCell()->toBoolean(); + return asCell()->toBoolean(exec); return isTrue(); // false, null, and undefined all convert to false. } diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index 19a8c4759..7aa5453e4 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -209,7 +209,7 @@ namespace JSC { JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&); - bool toBoolean() const; + bool toBoolean(ExecState*) const; // toNumber conversion is expected to be side effect free if an exception has // been set in the ExecState already. diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h index 07334722b..ed84207d9 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.h +++ b/Source/JavaScriptCore/runtime/NumberObject.h @@ -40,7 +40,7 @@ namespace JSC { return number; } - static const ClassInfo s_info; + static JS_EXPORTDATA const ClassInfo s_info; static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { @@ -48,7 +48,7 @@ namespace JSC { } }; - NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue); + JS_EXPORT_PRIVATE NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 7b6a5f669..5a6fcddf0 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -214,14 +214,14 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor PropertySlot enumerableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { - desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean()); + desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); if (exec->hadException()) return false; } PropertySlot configurableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { - desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean()); + desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); if (exec->hadException()) return false; } @@ -236,7 +236,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor PropertySlot writableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { - desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean()); + desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); if (exec->hadException()) return false; } diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp index 4cb9de505..d96bae575 100644 --- a/Source/JavaScriptCore/runtime/Operations.cpp +++ b/Source/JavaScriptCore/runtime/Operations.cpp @@ -70,7 +70,7 @@ JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v) if (v.isObject()) { // Return "undefined" for objects that should be treated // as null when doing comparisons. - if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) + if (asObject(v)->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())) return globalData.smallStrings.undefinedString(&globalData); CallData callData; JSObject* object = asObject(v); @@ -80,7 +80,7 @@ JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v) return globalData.smallStrings.objectString(&globalData); } -bool jsIsObjectType(JSValue v) +bool jsIsObjectType(CallFrame* callFrame, JSValue v) { if (!v.isCell()) return v.isNull(); @@ -89,7 +89,7 @@ bool jsIsObjectType(JSValue v) if (type == NumberType || type == StringType) return false; if (type >= ObjectType) { - if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) + if (asObject(v)->structure()->masqueradesAsUndefined(callFrame->lexicalGlobalObject())) return false; CallData callData; JSObject* object = asObject(v); diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index 497b19d82..88fffdac4 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -31,7 +31,7 @@ namespace JSC { NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); JSValue jsTypeStringForValue(CallFrame*, JSValue); - bool jsIsObjectType(JSValue); + bool jsIsObjectType(CallFrame*, JSValue); bool jsIsFunctionType(JSValue); ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2) @@ -134,13 +134,13 @@ namespace JSC { return true; if (!v2.isCell()) return false; - return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + return v2.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject()); } if (v2.isUndefinedOrNull()) { if (!v1.isCell()) return false; - return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + return v1.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject()); } if (v1.isObject()) { diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 0f2091c27..0b463474f 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -249,9 +249,9 @@ void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue va asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec)); } -void setRegExpConstructorMultiline(ExecState*, JSObject* baseObject, JSValue value) +void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setMultiline(value.toBoolean()); + asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); } // ECMA 15.10.4 diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 6080a1c99..24c7c8027 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -147,11 +147,11 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec) char postfix[5] = { '/', 0, 0, 0, 0 }; int index = 1; - if (thisObject->get(exec, exec->propertyNames().global).toBoolean()) + if (thisObject->get(exec, exec->propertyNames().global).toBoolean(exec)) postfix[index++] = 'g'; - if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean()) + if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) postfix[index++] = 'i'; - if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean()) + if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec)) postfix[index] = 'm'; UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec)->value(exec); // If source is empty, use "/(?:)/" to avoid colliding with comment syntax diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index 1dac06b46..3c037bcd1 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -22,6 +22,7 @@ #include "StringObject.h" #include "Error.h" +#include "JSGlobalObject.h" #include "PropertyNameArray.h" namespace JSC { @@ -143,4 +144,11 @@ void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, Proper return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); } +StringObject* constructString(ExecState* exec, JSGlobalObject* globalObject, JSValue string) +{ + StringObject* object = StringObject::create(exec, globalObject->stringObjectStructure()); + object->setInternalValue(exec->globalData(), string); + return object; +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index 7089e8983..f0c445e91 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -78,6 +78,8 @@ namespace JSC { return static_cast<StringObject*>(asObject(value)); } + JS_EXPORT_PRIVATE StringObject* constructString(ExecState*, JSGlobalObject*, JSValue); + } // namespace JSC #endif // StringObject_h diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 0b9c92210..2bb0107b7 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -256,6 +256,8 @@ namespace JSC { && offset <= lastValidOffset(); } + bool masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject); + PropertyOffset get(JSGlobalData&, PropertyName); PropertyOffset get(JSGlobalData&, const UString& name); JS_EXPORT_PRIVATE PropertyOffset get(JSGlobalData&, PropertyName, unsigned& attributes, JSCell*& specificValue); @@ -313,6 +315,11 @@ namespace JSC { return OBJECT_OFFSETOF(Structure, m_prototype); } + static ptrdiff_t globalObjectOffset() + { + return OBJECT_OFFSETOF(Structure, m_globalObject); + } + static ptrdiff_t typeInfoFlagsOffset() { return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset(); @@ -505,6 +512,11 @@ namespace JSC { return entry ? entry->offset : invalidOffset; } + inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject) + { + return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject; + } + inline JSValue JSValue::structureOrUndefined() const { if (isCell()) |