Change behavior of MasqueradesAsUndefined to better accommodate DFG changes
https://bugs.webkit.org/show_bug.cgi?id=93884

Reviewed by Geoffrey Garen.

Source/JavaScriptCore: 

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):

Source/WebCore: 

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.

Test: fast/js/document-all-between-frames.html

All of the changes in WebCore are simply passing the additional ExecState argument to JSValue::toBoolean.

* bindings/js/JSCustomSQLStatementErrorCallback.cpp:
(WebCore::JSSQLStatementErrorCallback::handleEvent):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::addEventListener):
(WebCore::JSDOMWindow::removeEventListener):
* bindings/js/JSDataViewCustom.cpp:
(WebCore::getDataViewMember):
* bindings/js/JSDeviceMotionEventCustom.cpp:
(WebCore::JSDeviceMotionEvent::initDeviceMotionEvent):
* bindings/js/JSDeviceOrientationEventCustom.cpp:
(WebCore::JSDeviceOrientationEvent::initDeviceOrientationEvent):
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue):
* bindings/js/JSDirectoryEntryCustom.cpp:
(WebCore::JSDirectoryEntry::getFile):
(WebCore::JSDirectoryEntry::getDirectory):
* bindings/js/JSDirectoryEntrySyncCustom.cpp:
(WebCore::getFlags):
* bindings/js/JSHTMLCanvasElementCustom.cpp:
(WebCore::JSHTMLCanvasElement::getContext):
* bindings/js/JSInspectorFrontendHostCustom.cpp:
(WebCore::populateContextMenuItems):
* bindings/js/JSMessageEventCustom.cpp:
(WebCore::handleInitMessageEvent):
* bindings/js/JSWebGLRenderingContextCustom.cpp:
(WebCore::dataFunctionMatrix):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::open):
* bindings/js/JavaScriptCallFrame.cpp:
(WebCore::JavaScriptCallFrame::exec):
(WebCore):
* bindings/js/JavaScriptCallFrame.h:
(JavaScriptCallFrame):
* bindings/js/ScriptDebugServer.cpp:
(WebCore::ScriptDebugServer::hasBreakpoint):
* bindings/scripts/CodeGeneratorJS.pm: Also add the custom create function for MasqueradesAsUndefined JS DOM wrappers.
(GenerateEventListenerCall):
(GenerateHeader):
(JSValueToNative):
* bindings/scripts/test/JS/JSTestEventTarget.cpp:
(WebCore::jsTestEventTargetPrototypeFunctionAddEventListener):
(WebCore::jsTestEventTargetPrototypeFunctionRemoveEventListener):
* bindings/scripts/test/JS/JSTestEventTarget.h:
(WebCore::JSTestEventTarget::create):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::setJSTestObjCreate):
(WebCore::setJSTestObjReflectedBooleanAttr):
(WebCore::setJSTestObjReflectedCustomBooleanAttr):
(WebCore::jsTestObjPrototypeFunctionAddEventListener):
(WebCore::jsTestObjPrototypeFunctionRemoveEventListener):
* bridge/c/c_utility.cpp:
(JSC::Bindings::convertValueToNPVariant):
* bridge/jni/jni_jsobject.mm:
(JavaJSObject::convertValueToJObject):
* bridge/qt/qt_runtime.cpp:
(JSC::Bindings::convertValueToQVariant):

Source/WebKit/mac: 

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.

* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::addValueToArray): Passing ExecState to toBoolean call.

Source/WebKit2: 

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.

* WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:
(WebKit::NPRuntimeObjectMap::convertJSValueToNPVariant): Passing ExecState to toBoolean call.

LayoutTests: 

Added a test that uses a variety of ways of checking whether something is correctly 
masquerading as undefined (or not) in a subframe.

* fast/js/document-all-between-frames-expected.txt: Added.
* fast/js/document-all-between-frames.html: Added.
* fast/js/resources/document-all-between-frames-subframe.html: Added.
* platform/chromium/TestExpectations: Chromium treats document.all differently, so skip our new test.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@125687 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp
index 04d7f66..9b7268a 100644
--- a/Source/JavaScriptCore/API/JSValueRef.cpp
+++ b/Source/JavaScriptCore/API/JSValueRef.cpp
@@ -266,7 +266,7 @@
     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 d69e576..b8d9460 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,106 @@
+2012-08-14  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 Geoffrey Garen.
+
+        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-14  Filip Pizlo  <fpizlo@apple.com>
 
         Unreviewed, build fix for !ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
index 8032ed1..48c79e0 100755
--- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
+++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
@@ -258,6 +258,7 @@
     ?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 8e0526c..e6fba93 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.h
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h
@@ -78,7 +78,7 @@
     
     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 8605af5..dca7487 100644
--- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
+++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.h
@@ -48,6 +48,7 @@
         {
         }
 
+        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 e09b940..73510d2 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -608,7 +608,7 @@
             
     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;
@@ -646,10 +646,18 @@
             bool constantWasSet;
             switch (node.op()) {
             case IsUndefined:
-                constantWasSet = trySetConstant(nodeIndex, jsBoolean(
-                    child.isCell()
-                    ? child.asCell()->structure()->typeInfo().masqueradesAsUndefined()
-                    : child.isUndefined()));
+                node.setCanExit(true);
+                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()));
@@ -729,8 +737,8 @@
                  && 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;
             }
             
@@ -1083,7 +1091,7 @@
     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 f054707..aecce83 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -101,7 +101,7 @@
                     // 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 882e1cd..b5c3b96 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp
+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp
@@ -1273,9 +1273,9 @@
     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 @@
     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 0ff7212..455c2bc 100644
--- a/Source/JavaScriptCore/dfg/DFGOperations.h
+++ b/Source/JavaScriptCore/dfg/DFGOperations.h
@@ -180,7 +180,7 @@
 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 92bb8b1..a22f886 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -623,10 +623,29 @@
     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(0) : TrustedImm32(1), 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(0) : TrustedImm32(1), 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 @@
         done.link(&m_jit);
     }
     
+    notMasqueradesAsUndefined.link(&m_jit);
+ 
     booleanResult(resultPayloadGPR, m_compileIndex);
 }
 
@@ -668,9 +689,22 @@
     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(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
+    }
+ 
     if (!isKnownCell(operand.index())) {
         jump(notTaken, ForceJump);
         
@@ -3768,9 +3802,28 @@
         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 4f3dabb..658c55b 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -588,10 +588,29 @@
     
     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(0) : TrustedImm32(1), 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(0) : TrustedImm32(1), 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 @@
         
         done.link(&m_jit);
     }
-    
+   
+    notMasqueradesAsUndefined.link(&m_jit);
+ 
     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
 }
@@ -632,9 +653,22 @@
     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(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
+    }
+ 
     if (!isKnownCell(operand.index())) {
         jump(notTaken, ForceJump);
         
@@ -3755,9 +3789,28 @@
         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(ValueFalse), 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(ValueFalse), 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/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index a9118f4..f6a197e 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -2118,7 +2118,7 @@
             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 @@
             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 @@
         */
         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 @@
         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 @@
         */
         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 @@
          */
         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 @@
          */
         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 @@
         */
         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 @@
         */
         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 @@
         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 @@
         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 0d24961..9eaff2d 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -479,8 +479,16 @@
     
     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(ValueFalse), 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,19 @@
 
     // 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));
+    loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2);
+    move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
+    addJump(branchPtr(Equal, regT0, regT2), 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 +793,8 @@
     // 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 +1186,14 @@
     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 +1202,7 @@
     comparePtr(Equal, regT0, TrustedImm32(ValueNull), regT0);
 
     wasNotImmediate.link(this);
+    wasNotMasqueradesAsUndefined.link(this);
 
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(dst);
@@ -1197,8 +1218,14 @@
     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 +1234,7 @@
     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 eec9df3..ba8ca00 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -646,8 +646,16 @@
     
     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,20 @@
 
     // 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));
+    loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2);
+    move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
+    addJump(branchPtr(Equal, regT0, regT2), 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 +966,8 @@
     // 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 +1169,14 @@
     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), regT0);
+    Jump wasNotMasqueradesAsUndefined = jump();
 
+    isMasqueradesAsUndefined.link(this);
+    move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
+    loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2);
+    compare32(Equal, regT0, regT2, regT0);
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
@@ -1169,6 +1186,7 @@
     or32(regT2, regT1);
 
     wasNotImmediate.link(this);
+    wasNotMasqueradesAsUndefined.link(this);
 
     emitStoreBool(dst, regT1);
 }
@@ -1182,8 +1200,14 @@
     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(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);
+    compare32(NotEqual, regT0, regT2, regT0);
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
@@ -1193,6 +1217,7 @@
     and32(regT2, regT1);
 
     wasNotImmediate.link(this);
+    wasNotMasqueradesAsUndefined.link(this);
 
     emitStoreBool(dst, regT1);
 }
diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp
index 8b85469..34f0cb5 100644
--- a/Source/JavaScriptCore/jit/JITStubs.cpp
+++ b/Source/JavaScriptCore/jit/JITStubs.cpp
@@ -2778,7 +2778,7 @@
 
     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);
 }
@@ -2789,7 +2789,7 @@
 
     JSValue src1 = stackFrame.args[0].jsValue();
 
-    bool result = src1.toBoolean();
+    bool result = src1.toBoolean(stackFrame.callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
     return result;
 }
@@ -2820,13 +2820,13 @@
     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();
     }
 
@@ -2863,10 +2863,10 @@
     }
     
     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();
 
@@ -3179,7 +3179,7 @@
 {
     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 58bf1bd..eef54ac 100644
--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
@@ -517,7 +517,7 @@
 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_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_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 5f280ce..c0f1368 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
@@ -444,7 +444,13 @@
     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 @@
     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 @@
     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 @@
     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 @@
 _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 f1a7e29..73e8613 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
@@ -324,7 +324,13 @@
     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 @@
     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 @@
     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 @@
 _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 b0adb7f..a97cf82 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -797,7 +797,7 @@
             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 @@
         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 @@
             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 @@
         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 @@
             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 @@
         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 090be0a..9b66629 100644
--- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
@@ -49,7 +49,7 @@
 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 @@
 // 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/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 90e531c..39f9835 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -98,7 +98,7 @@
         // 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 0edc0a8..ff7b148 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -115,6 +115,7 @@
 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 af03f32..248004b 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 @@
 
         Debugger* m_debugger;
 
+        RefPtr<WatchpointSet> m_masqueradesAsUndefinedWatchpoint;
+
         OwnPtr<JSGlobalObjectRareData> m_rareData;
 
         WeakRandom m_weakRandom;
@@ -270,6 +273,8 @@
         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 d6fc4c2..e91553a 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -500,23 +500,23 @@
 
     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 19a8c47..7aa5453 100644
--- a/Source/JavaScriptCore/runtime/JSValue.h
+++ b/Source/JavaScriptCore/runtime/JSValue.h
@@ -209,7 +209,7 @@
         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/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index 7b6a5f6..5a6fcdd 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -214,14 +214,14 @@
 
     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 @@
 
     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 4cb9de5..d96bae5 100644
--- a/Source/JavaScriptCore/runtime/Operations.cpp
+++ b/Source/JavaScriptCore/runtime/Operations.cpp
@@ -70,7 +70,7 @@
     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 @@
     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 @@
     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 497b19d..88fffda 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -31,7 +31,7 @@
 
     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 @@
                     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 0f2091c..0b46347 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -249,9 +249,9 @@
     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 6080a1c..24c7c80 100644
--- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -147,11 +147,11 @@
 
     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/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 0b9c922..2bb0107 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -256,6 +256,8 @@
                 && 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 @@
             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 @@
         return entry ? entry->offset : invalidOffset;
     }
     
+    inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+    {
+        return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+    }
+
     inline JSValue JSValue::structureOrUndefined() const
     {
         if (isCell())