WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
patch 2: revised.
bug-134420.patch (text/plain), 33.20 KB, created by
Mark Lam
on 2014-07-01 14:31:32 PDT
(
hide
)
Description:
patch 2: revised.
Filename:
MIME Type:
Creator:
Mark Lam
Created:
2014-07-01 14:31:32 PDT
Size:
33.20 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 170562) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,127 @@ >+2014-06-27 Mark Lam <mark.lam@apple.com> >+ >+ [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope. >+ <https://webkit.org/b/134420> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant >+ peers) which the WebInspector will use to introspect CallFrame variables. >+ Instead, we should be returning a DebuggerScope as an abstraction layer that >+ provides the introspection functionality that the WebInspector needs. This >+ is the first step towards not forcing every frame to have a JSActivation >+ object just because the debugger is enabled. >+ >+ 1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject >+ instead of the VM. This allows JSObject::globalObject() to be able to >+ return the global object for the DebuggerScope. >+ >+ 2. The DebuggerScope now takes care of instantiating the JSActivation object >+ for the scope instead of explicitly doing it in DebuggerCallFrame::scope(). >+ This allows the DebuggerScope to hide how the inspector gets introspection >+ information about scopes of CallFrames on the stack. >+ >+ 3. DebuggerScope::create() takes an optional scope parameter that defaults to >+ null. The scope parameter means one of the following: >+ 1. If unspecified (i.e. null), we'll initialize the DebuggerScope instance >+ with the scope of the DebuggerCallFrame's underlying CallFrame. This >+ is used in DebuggerCallFrame::scope() where we instantiate the top >+ DebuggerScope for that frame. >+ 2. If specified (i.e. not null), we'll initialize the DebuggerScope instance >+ with the specified scope. We need this when we are creating DebuggerScope >+ instances for "parent" scopes in the scope chain of the same DebuggerCallFrame. >+ We instantiate these in DebuggerScope::next(). >+ >+ 4. On the DebuggerScope's life-cycle management: >+ >+ The DebuggerCallFrame is designed to be "valid" only during a debugging session >+ (while the debugger is broken) through the use of a DebuggerCallFrameScope in >+ Debugger::pauseIfNeeded(). Once the debugger resumes from the break, the >+ DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated. >+ We can't guarantee (from this code alone) that the Inspector code isn't still >+ holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract, >+ the frame will be invalidated, and any attempt to query it will return null values. >+ This is pre-existing behavior. >+ >+ Now, we're adding the DebuggerScope into the picture. While a single debugger >+ pause session is in progress, the Inspector may request the scope from the >+ DebuggerCallFrame. While the DebuggerCallFrame is still valid, we want >+ DebuggerCallFrame::scope() to always return the same DebuggerScope object. >+ This is why we hold on to the DebuggerScope with a strong ref. >+ >+ If we use a weak ref instead, the following cooky behavior can manifest: >+ 1. The Inspector calls Debugger::scope() to get the top scope. >+ 2. The Inspector iterates down the scope chain and is now only holding a >+ reference to a parent scope. It is no longer referencing the top scope. >+ 3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope >+ gets cleared. >+ 4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets >+ a different DebuggerScope instance. >+ 5. The Inspector iterates down the scope chain but never sees the parent scope >+ instance that retained a ref to in step 2 above. This is because when iterating >+ this new DebuggerScope instance (which has no knowledge of the previous parent >+ DebuggerScope instance), a new DebuggerScope instance will get created for the >+ same parent scope. >+ >+ Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability. >+ However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame. >+ When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if >+ instantiated) will also get invalidated. This is why we need the >+ DebuggerScope::invalidateChain() method. The Inspector should not be using the >+ DebuggerScope instance after its owner DebuggerCallFrame is invalidated. If it does, >+ those methods will do nothing or returned a failed status. >+ >+ * debugger/Debugger.h: >+ * debugger/DebuggerCallFrame.cpp: >+ (JSC::DebuggerCallFrame::scope): >+ (JSC::DebuggerCallFrame::evaluate): >+ (JSC::DebuggerCallFrame::invalidate): >+ (JSC::DebuggerCallFrame::vm): >+ (JSC::DebuggerCallFrame::lexicalGlobalObject): >+ * debugger/DebuggerCallFrame.h: >+ * debugger/DebuggerScope.cpp: >+ (JSC::DebuggerScope::DebuggerScope): >+ (JSC::DebuggerScope::finishCreation): >+ (JSC::DebuggerScope::visitChildren): >+ (JSC::DebuggerScope::className): >+ (JSC::DebuggerScope::getOwnPropertySlot): >+ (JSC::DebuggerScope::put): >+ (JSC::DebuggerScope::deleteProperty): >+ (JSC::DebuggerScope::getOwnPropertyNames): >+ (JSC::DebuggerScope::defineOwnProperty): >+ (JSC::DebuggerScope::next): >+ (JSC::DebuggerScope::invalidateChain): >+ (JSC::DebuggerScope::isWithScope): >+ (JSC::DebuggerScope::isGlobalScope): >+ (JSC::DebuggerScope::isFunctionScope): >+ * debugger/DebuggerScope.h: >+ (JSC::DebuggerScope::create): >+ (JSC::DebuggerScope::Iterator::Iterator): >+ (JSC::DebuggerScope::Iterator::get): >+ (JSC::DebuggerScope::Iterator::operator++): >+ (JSC::DebuggerScope::Iterator::operator==): >+ (JSC::DebuggerScope::Iterator::operator!=): >+ (JSC::DebuggerScope::isValid): >+ (JSC::DebuggerScope::toJSScope): >+ (JSC::DebuggerScope::begin): >+ (JSC::DebuggerScope::end): >+ * inspector/JSJavaScriptCallFrame.cpp: >+ (Inspector::JSJavaScriptCallFrame::scopeType): >+ (Inspector::JSJavaScriptCallFrame::scopeChain): >+ * inspector/JavaScriptCallFrame.h: >+ (Inspector::JavaScriptCallFrame::scopeChain): >+ * inspector/ScriptDebugServer.cpp: >+ * runtime/JSGlobalObject.cpp: >+ (JSC::JSGlobalObject::visitChildren): >+ * runtime/JSGlobalObject.h: >+ (JSC::JSGlobalObject::debuggerScopeStructure): >+ * runtime/JSObject.h: >+ (JSC::JSObject::isWithScope): >+ * runtime/JSScope.h: >+ * runtime/VM.cpp: >+ (JSC::VM::VM): >+ * runtime/VM.h: >+ > 2014-06-27 Michael Saboff <msaboff@apple.com> > > Unreviewed build fix after r169795. >Index: Source/JavaScriptCore/debugger/Debugger.h >=================================================================== >--- Source/JavaScriptCore/debugger/Debugger.h (revision 170504) >+++ Source/JavaScriptCore/debugger/Debugger.h (working copy) >@@ -34,6 +34,7 @@ > > namespace JSC { > >+class CodeBlock; > class ExecState; > class JSGlobalObject; > class SourceProvider; >Index: Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp >=================================================================== >--- Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (revision 170504) >+++ Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp (working copy) >@@ -30,12 +30,14 @@ > #include "DebuggerCallFrame.h" > > #include "CodeBlock.h" >+#include "DebuggerScope.h" > #include "Interpreter.h" > #include "JSActivation.h" > #include "JSFunction.h" > #include "JSCInlines.h" > #include "Parser.h" > #include "StackVisitor.h" >+#include "StrongInlines.h" > > namespace JSC { > >@@ -106,20 +108,17 @@ String DebuggerCallFrame::functionName() > return getCalculatedDisplayName(m_callFrame, function); > } > >-JSScope* DebuggerCallFrame::scope() const >+DebuggerScope* DebuggerCallFrame::scope() > { > ASSERT(isValid()); > if (!isValid()) > return 0; > >- CodeBlock* codeBlock = m_callFrame->codeBlock(); >- if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) { >- JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock); >- m_callFrame->setActivation(activation); >- m_callFrame->setScope(activation); >+ if (!m_scope) { >+ VM& vm = m_callFrame->vm(); >+ m_scope.set(vm, DebuggerScope::create(vm, this)); > } >- >- return m_callFrame->scope(); >+ return m_scope.get(); > } > > DebuggerCallFrame::Type DebuggerCallFrame::type() const >@@ -162,7 +161,7 @@ JSValue DebuggerCallFrame::evaluate(cons > } > > JSValue thisValue = thisValueForCallFrame(callFrame); >- JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()); >+ JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope()); > if (vm.exception()) { > exception = vm.exception(); > vm.clearException(); >@@ -174,6 +173,10 @@ JSValue DebuggerCallFrame::evaluate(cons > void DebuggerCallFrame::invalidate() > { > m_callFrame = nullptr; >+ if (m_scope) { >+ m_scope->invalidateChain(); >+ m_scope.clear(); >+ } > RefPtr<DebuggerCallFrame> frame = m_caller.release(); > while (frame) { > frame->m_callFrame = nullptr; >@@ -213,4 +216,14 @@ JSValue DebuggerCallFrame::thisValueForC > return thisValue; > } > >+VM& DebuggerCallFrame::vm() const >+{ >+ return m_callFrame->vm(); >+} >+ >+JSGlobalObject* DebuggerCallFrame::lexicalGlobalObject() const >+{ >+ return m_callFrame->lexicalGlobalObject(); >+} >+ > } // namespace JSC >Index: Source/JavaScriptCore/debugger/DebuggerCallFrame.h >=================================================================== >--- Source/JavaScriptCore/debugger/DebuggerCallFrame.h (revision 170504) >+++ Source/JavaScriptCore/debugger/DebuggerCallFrame.h (working copy) >@@ -29,14 +29,18 @@ > #ifndef DebuggerCallFrame_h > #define DebuggerCallFrame_h > >-#include "CallFrame.h" > #include "DebuggerPrimitives.h" >+#include "Strong.h" > #include <wtf/PassRefPtr.h> > #include <wtf/RefCounted.h> > #include <wtf/text/TextPosition.h> > > namespace JSC { > >+class DebuggerScope; >+class ExecState; >+typedef ExecState CallFrame; >+ > class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> { > public: > enum Type { ProgramType, FunctionType }; >@@ -58,7 +62,7 @@ public: > JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; } > > JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const; >- JS_EXPORT_PRIVATE JSScope* scope() const; >+ JS_EXPORT_PRIVATE DebuggerScope* scope(); > JS_EXPORT_PRIVATE String functionName() const; > JS_EXPORT_PRIVATE Type type() const; > JS_EXPORT_PRIVATE JSValue thisValue() const; >@@ -74,10 +78,16 @@ public: > JS_EXPORT_PRIVATE static SourceID sourceIDForCallFrame(CallFrame*); > static JSValue thisValueForCallFrame(CallFrame*); > >+ VM& vm() const; >+ JSGlobalObject* lexicalGlobalObject() const; >+ > private: > CallFrame* m_callFrame; > RefPtr<DebuggerCallFrame> m_caller; > TextPosition m_position; >+ Strong<DebuggerScope> m_scope; >+ >+ friend class DebuggerScope; > }; > > } // namespace JSC >Index: Source/JavaScriptCore/debugger/DebuggerScope.cpp >=================================================================== >--- Source/JavaScriptCore/debugger/DebuggerScope.cpp (revision 170504) >+++ Source/JavaScriptCore/debugger/DebuggerScope.cpp (working copy) >@@ -26,8 +26,10 @@ > #include "config.h" > #include "DebuggerScope.h" > >+#include "DebuggerCallFrame.h" > #include "JSActivation.h" > #include "JSCInlines.h" >+#include "JSWithScope.h" > > namespace JSC { > >@@ -35,17 +37,31 @@ STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE( > > const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) }; > >-DebuggerScope::DebuggerScope(VM& vm) >- : JSNonFinalObject(vm, vm.debuggerScopeStructure.get()) >+DebuggerScope::DebuggerScope(VM& vm, DebuggerCallFrame* callFrame) >+ : JSNonFinalObject(vm, callFrame->lexicalGlobalObject()->debuggerScopeStructure()) >+ , m_debuggerCallFrame(callFrame) > { >+ ASSERT(callFrame->isValid()); > } > >-void DebuggerScope::finishCreation(VM& vm, JSObject* activation) >+void DebuggerScope::finishCreation(VM& vm, JSScope* scope) > { > Base::finishCreation(vm); >- ASSERT(activation); >- ASSERT(activation->isActivationObject()); >- m_activation.set(vm, this, jsCast<JSActivation*>(activation)); >+ >+ if (!scope) { >+ CallFrame* callFrame = m_debuggerCallFrame->m_callFrame; >+ CodeBlock* codeBlock = callFrame->codeBlock(); >+ if (codeBlock && codeBlock->needsActivation() && !callFrame->hasActivation()) { >+ ASSERT(!callFrame->scope()->isWithScope()); >+ JSActivation* activation = JSActivation::create(vm, callFrame, codeBlock); >+ callFrame->setActivation(activation); >+ callFrame->setScope(activation); >+ } >+ scope = callFrame->scope(); >+ } >+ >+ ASSERT(scope); >+ m_scope.set(vm, this, scope); > } > > void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor) >@@ -56,43 +72,108 @@ void DebuggerScope::visitChildren(JSCell > ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); > > JSObject::visitChildren(thisObject, visitor); >- visitor.append(&thisObject->m_activation); >+ visitor.append(&thisObject->m_scope); >+ visitor.append(&thisObject->m_next); > } > > String DebuggerScope::className(const JSObject* object) > { >- const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object); >- return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get()); >+ const DebuggerScope* scope = jsCast<const DebuggerScope*>(object); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return String(); >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ return thisObject->methodTable()->className(thisObject); > } > > bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) > { >- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); >- return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot); >+ DebuggerScope* scope = jsCast<DebuggerScope*>(object); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return false; >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); > } > > void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) > { >- DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); >- thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot); >+ DebuggerScope* scope = jsCast<DebuggerScope*>(cell); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return; >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); > } > > bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) > { >- DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); >- return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName); >+ DebuggerScope* scope = jsCast<DebuggerScope*>(cell); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return false; >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName); > } > > void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) > { >- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); >- thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode); >+ DebuggerScope* scope = jsCast<DebuggerScope*>(object); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return; >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode); > } > > bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) > { >- DebuggerScope* thisObject = jsCast<DebuggerScope*>(object); >- return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow); >+ DebuggerScope* scope = jsCast<DebuggerScope*>(object); >+ ASSERT(scope->isValid()); >+ if (!scope->isValid()) >+ return false; >+ JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); >+ return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); >+} >+ >+DebuggerScope* DebuggerScope::next() >+{ >+ ASSERT(isValid()); >+ if (!m_next && m_scope->next()) { >+ VM& vm = *m_scope->vm(); >+ DebuggerScope* nextScope = create(vm, m_debuggerCallFrame, m_scope->next()); >+ m_next.set(vm, this, nextScope); >+ } >+ return m_next.get(); >+} >+ >+void DebuggerScope::invalidateChain() >+{ >+ DebuggerScope* scope = this; >+ while (scope) { >+ ASSERT(scope->isValid()); >+ DebuggerScope* nextScope = scope->m_next.get(); >+ scope->m_next.clear(); >+ scope->m_scope.clear(); >+ scope = nextScope; >+ } >+} >+ >+bool DebuggerScope::isWithScope() const >+{ >+ return m_scope->isWithScope(); >+} >+ >+bool DebuggerScope::isGlobalScope() const >+{ >+ return m_scope->isGlobalObject(); >+} >+ >+bool DebuggerScope::isFunctionScope() const >+{ >+ // In the current debugger implementation, every function will create an >+ // activation object. Hence, an activation object implies a function scope. >+ return m_scope->isActivationObject(); > } > > } // namespace JSC >Index: Source/JavaScriptCore/debugger/DebuggerScope.h >=================================================================== >--- Source/JavaScriptCore/debugger/DebuggerScope.h (revision 170504) >+++ Source/JavaScriptCore/debugger/DebuggerScope.h (working copy) >@@ -26,19 +26,22 @@ > #ifndef DebuggerScope_h > #define DebuggerScope_h > >+#include "DebuggerCallFrame.h" > #include "JSObject.h" > > namespace JSC { > >+class JSScope; >+ > class DebuggerScope : public JSNonFinalObject { > public: > typedef JSNonFinalObject Base; > >- static DebuggerScope* create(VM& vm, JSObject* object) >+ static DebuggerScope* create(VM& vm, DebuggerCallFrame* callFrame, JSScope* scope = 0) > { >- DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm); >- activation->finishCreation(vm, object); >- return activation; >+ DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, callFrame); >+ debuggerScope->finishCreation(vm, scope); >+ return debuggerScope; > } > > static void visitChildren(JSCell*, SlotVisitor&); >@@ -56,16 +59,60 @@ public: > return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); > } > >-protected: >+ class Iterator { >+ public: >+ Iterator(DebuggerScope* node) >+ : m_node(node) >+ { >+ } >+ >+ DebuggerScope* get() { return m_node; } >+ Iterator& operator++() { m_node = m_node->next(); return *this; } >+ // postfix ++ intentionally omitted >+ >+ bool operator==(const Iterator& other) const { return m_node == other.m_node; } >+ bool operator!=(const Iterator& other) const { return m_node != other.m_node; } >+ >+ private: >+ DebuggerScope* m_node; >+ }; >+ >+ Iterator begin(); >+ Iterator end(); >+ DebuggerScope* next(); >+ >+ void invalidateChain(); >+ bool isValid() const { return !!m_scope; } >+ >+ bool isWithScope() const; >+ bool isGlobalScope() const; >+ bool isFunctionScope() const; >+ >+private: >+ JS_EXPORT_PRIVATE DebuggerScope(VM&, DebuggerCallFrame*); >+ JS_EXPORT_PRIVATE void finishCreation(VM&, JSScope*); >+ >+ JSScope* jsScope() const { return m_scope.get(); } >+ > static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags; > >- JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation); >+ DebuggerCallFrame* m_debuggerCallFrame; >+ WriteBarrier<JSScope> m_scope; >+ WriteBarrier<DebuggerScope> m_next; > >-private: >- JS_EXPORT_PRIVATE DebuggerScope(VM&); >- WriteBarrier<JSActivation> m_activation; >+ friend class DebuggerCallFrame; > }; > >+inline DebuggerScope::Iterator DebuggerScope::begin() >+{ >+ return Iterator(this); >+} >+ >+inline DebuggerScope::Iterator DebuggerScope::end() >+{ >+ return Iterator(0); >+} >+ > } // namespace JSC > > #endif // DebuggerScope_h >Index: Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp >=================================================================== >--- Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (revision 170504) >+++ Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp (working copy) >@@ -28,6 +28,7 @@ > > #if ENABLE(INSPECTOR) > >+#include "DebuggerScope.h" > #include "Error.h" > #include "JSCJSValue.h" > #include "JSCellInlines.h" >@@ -95,29 +96,30 @@ JSValue JSJavaScriptCallFrame::scopeType > return jsUndefined(); > int index = exec->argument(0).asInt32(); > >- JSScope* scopeChain = impl().scopeChain(); >- ScopeChainIterator end = scopeChain->end(); >- >- // FIXME: We should be identifying and returning CATCH_SCOPE appropriately. >+ DebuggerScope* scopeChain = impl().scopeChain(); >+ DebuggerScope::Iterator end = scopeChain->end(); > > bool foundLocalScope = false; >- for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) { >- JSObject* scope = iter.get(); >- if (scope->isActivationObject()) { >- if (!foundLocalScope) { >- // First activation object is local scope, each successive activation object is closure. >- if (!index) >- return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE); >- foundLocalScope = true; >- } else if (!index) >- return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); >+ for (DebuggerScope::Iterator iter = scopeChain->begin(); iter != end; ++iter) { >+ DebuggerScope* scope = iter.get(); >+ >+ if (!foundLocalScope && scope->isFunctionScope()) { >+ // First function scope is the local scope, each successive one is a closure. >+ if (!index) >+ return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE); >+ foundLocalScope = true; > } > > if (!index) { >- // Last in the chain is global scope. >- if (++iter == end) >+ if (scope->isWithScope()) >+ return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); >+ if (scope->isGlobalScope()) { >+ ASSERT(++iter == end); > return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE); >- return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE); >+ } >+ // FIXME: We should be identifying and returning CATCH_SCOPE appropriately. >+ ASSERT(scope->isFunctionScope()); >+ return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE); > } > > --index; >@@ -157,9 +159,9 @@ JSValue JSJavaScriptCallFrame::scopeChai > if (!impl().scopeChain()) > return jsNull(); > >- JSScope* scopeChain = impl().scopeChain(); >- ScopeChainIterator iter = scopeChain->begin(); >- ScopeChainIterator end = scopeChain->end(); >+ DebuggerScope* scopeChain = impl().scopeChain(); >+ DebuggerScope::Iterator iter = scopeChain->begin(); >+ DebuggerScope::Iterator end = scopeChain->end(); > > // We must always have something in the scope chain. > ASSERT(iter != end); >Index: Source/JavaScriptCore/inspector/JavaScriptCallFrame.h >=================================================================== >--- Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (revision 170504) >+++ Source/JavaScriptCore/inspector/JavaScriptCallFrame.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved. >+ * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -53,7 +53,7 @@ public: > > String functionName() const { return m_debuggerCallFrame->functionName(); } > JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); } >- JSC::JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); } >+ JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); } > JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); } > > JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); } >Index: Source/JavaScriptCore/inspector/ScriptDebugServer.cpp >=================================================================== >--- Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (revision 170504) >+++ Source/JavaScriptCore/inspector/ScriptDebugServer.cpp (working copy) >@@ -34,6 +34,7 @@ > #if ENABLE(INSPECTOR) > > #include "DebuggerCallFrame.h" >+#include "DebuggerScope.h" > #include "JSJavaScriptCallFrame.h" > #include "JSLock.h" > #include "JavaScriptCallFrame.h" >Index: Source/JavaScriptCore/runtime/JSGlobalObject.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.cpp (revision 170504) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.cpp (working copy) >@@ -45,6 +45,7 @@ > #include "DateConstructor.h" > #include "DatePrototype.h" > #include "Debugger.h" >+#include "DebuggerScope.h" > #include "Error.h" > #include "ErrorConstructor.h" > #include "ErrorPrototype.h" >@@ -320,6 +321,7 @@ void JSGlobalObject::reset(JSValue proto > m_nameScopeStructure.set(vm, this, JSNameScope::createStructure(vm, this, jsNull())); > m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull())); > m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull())); >+ m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this, jsNull())); > m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull())); > > m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity())); >@@ -661,6 +663,7 @@ void JSGlobalObject::visitChildren(JSCel > visitor.append(&thisObject->m_promisePrototype); > #endif > >+ visitor.append(&thisObject->m_debuggerScopeStructure); > visitor.append(&thisObject->m_withScopeStructure); > visitor.append(&thisObject->m_strictEvalActivationStructure); > visitor.append(&thisObject->m_activationStructure); >Index: Source/JavaScriptCore/runtime/JSGlobalObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSGlobalObject.h (revision 170504) >+++ Source/JavaScriptCore/runtime/JSGlobalObject.h (working copy) >@@ -183,6 +183,7 @@ protected: > WriteBarrier<JSPromisePrototype> m_promisePrototype; > #endif > >+ WriteBarrier<Structure> m_debuggerScopeStructure; > WriteBarrier<Structure> m_withScopeStructure; > WriteBarrier<Structure> m_strictEvalActivationStructure; > WriteBarrier<Structure> m_activationStructure; >@@ -388,6 +389,7 @@ public: > JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); } > #endif > >+ Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); } > Structure* withScopeStructure() const { return m_withScopeStructure.get(); } > Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); } > Structure* activationStructure() const { return m_activationStructure.get(); } >Index: Source/JavaScriptCore/runtime/JSObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSObject.h (revision 170504) >+++ Source/JavaScriptCore/runtime/JSObject.h (working copy) >@@ -599,6 +599,7 @@ public: > bool isNameScopeObject() const; > bool isActivationObject() const; > bool isErrorInstance() const; >+ bool isWithScope() const; > > JS_EXPORT_PRIVATE void seal(VM&); > JS_EXPORT_PRIVATE void freeze(VM&); >@@ -1147,6 +1148,11 @@ inline bool JSObject::isErrorInstance() > return type() == ErrorInstanceType; > } > >+inline bool JSObject::isWithScope() const >+{ >+ return type() == WithScopeType; >+} >+ > inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly) > { > ASSERT(structure); >Index: Source/JavaScriptCore/runtime/JSScope.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSScope.h (revision 170504) >+++ Source/JavaScriptCore/runtime/JSScope.h (working copy) >@@ -150,7 +150,7 @@ public: > friend class LLIntOffsetsExtractor; > static size_t offsetOfNext(); > >- JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*); >+ static JSObject* objectAtScope(JSScope*); > > static JSValue resolve(ExecState*, JSScope*, const Identifier&); > static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType); >Index: Source/JavaScriptCore/runtime/VM.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VM.cpp (revision 170504) >+++ Source/JavaScriptCore/runtime/VM.cpp (working copy) >@@ -39,7 +39,6 @@ > #include "CommonSlowPaths.h" > #include "DFGLongLivedState.h" > #include "DFGWorklist.h" >-#include "DebuggerScope.h" > #include "ErrorInstance.h" > #include "FTLThunks.h" > #include "FunctionConstructor.h" >@@ -255,7 +254,6 @@ VM::VM(VMType vmType, HeapType heapType) > propertyNames = new CommonIdentifiers(this); > structureStructure.set(*this, Structure::createStructure(*this)); > structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull())); >- debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull())); > terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); > stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); > notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); >Index: Source/JavaScriptCore/runtime/VM.h >=================================================================== >--- Source/JavaScriptCore/runtime/VM.h (revision 170504) >+++ Source/JavaScriptCore/runtime/VM.h (working copy) >@@ -262,7 +262,6 @@ namespace JSC { > > Strong<Structure> structureStructure; > Strong<Structure> structureRareDataStructure; >- Strong<Structure> debuggerScopeStructure; > Strong<Structure> terminatedExecutionErrorStructure; > Strong<Structure> stringStructure; > Strong<Structure> notAnObjectStructure; >Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 170562) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,18 @@ >+2014-06-27 Mark Lam <mark.lam@apple.com> >+ >+ [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope. >+ <https://webkit.org/b/134420> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ No new tests. >+ >+ * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed. >+ - This is not in use. Hence, we can remove it. >+ * bindings/js/ScriptController.cpp: >+ (WebCore::ScriptController::attachDebugger): >+ - We should acquire the JSLock before modifying a JS global object. >+ > 2014-06-24 Mark Lam <mark.lam@apple.com> > > [ftlopt] Renamed DebuggerActivation to DebuggerScope. >Index: Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h >=================================================================== >--- Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h (revision 170504) >+++ Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h (working copy) >@@ -1,4 +0,0 @@ >-#ifndef WebCore_FWD_DebuggerCallFrame_h >-#define WebCore_FWD_DebuggerCallFrame_h >-#include <JavaScriptCore/DebuggerCallFrame.h> >-#endif >Index: Source/WebCore/bindings/js/ScriptController.cpp >=================================================================== >--- Source/WebCore/bindings/js/ScriptController.cpp (revision 170504) >+++ Source/WebCore/bindings/js/ScriptController.cpp (working copy) >@@ -295,6 +295,7 @@ void ScriptController::attachDebugger(JS > return; > > JSDOMWindow* globalObject = shell->window(); >+ JSLockHolder lock(globalObject->vm()); > if (debugger) > debugger->attach(globalObject); > else if (JSC::Debugger* currentDebugger = globalObject->debugger())
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 134420
:
234038
|
234198
|
234219
|
237195
|
237196
|
237328