| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +109 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2014-07-01  Mark Lam  <mark.lam@apple.com>
2
3
        [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
4
        <https://webkit.org/b/134420>
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
9
        peers) which the WebInspector will use to introspect CallFrame variables.
10
        Instead, we should be returning a DebuggerScope as an abstraction layer that
11
        provides the introspection functionality that the WebInspector needs.  This
12
        is the first step towards not forcing every frame to have a JSActivation
13
        object just because the debugger is enabled.
14
15
        1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
16
           instead of the VM.  This allows JSObject::globalObject() to be able to
17
           return the global object for the DebuggerScope.
18
19
        2. On the DebuggerScope's life-cycle management:
20
21
           The DebuggerCallFrame is designed to be "valid" only during a debugging session
22
           (while the debugger is broken) through the use of a DebuggerCallFrameScope in
23
           Debugger::pauseIfNeeded().  Once the debugger resumes from the break, the
24
           DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
25
           We can't guarantee (from this code alone) that the Inspector code isn't still
26
           holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
27
           the frame will be invalidated, and any attempt to query it will return null values.
28
           This is pre-existing behavior.
29
30
           Now, we're adding the DebuggerScope into the picture.  While a single debugger
31
           pause session is in progress, the Inspector may request the scope from the
32
           DebuggerCallFrame.  While the DebuggerCallFrame is still valid, we want
33
           DebuggerCallFrame::scope() to always return the same DebuggerScope object.
34
           This is why we hold on to the DebuggerScope with a strong ref.
35
36
           If we use a weak ref instead, the following cooky behavior can manifest:
37
           1. The Inspector calls Debugger::scope() to get the top scope.
38
           2. The Inspector iterates down the scope chain and is now only holding a
39
              reference to a parent scope.  It is no longer referencing the top scope.
40
           3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
41
              gets cleared.
42
           4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
43
              a different DebuggerScope instance.
44
           5. The Inspector iterates down the scope chain but never sees the parent scope
45
              instance that retained a ref to in step 2 above.  This is because when iterating
46
              this new DebuggerScope instance (which has no knowledge of the previous parent
47
              DebuggerScope instance), a new DebuggerScope instance will get created for the
48
              same parent scope. 
49
50
           Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability.
51
           However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame.
52
           When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
53
           instantiated) will also get invalidated.  This is why we need the
54
           DebuggerScope::invalidateChain() method.  The Inspector should not be using the
55
           DebuggerScope instance after its owner DebuggerCallFrame is invalidated.  If it does,
56
           those methods will do nothing or returned a failed status.
57
58
        * debugger/Debugger.h:
59
        * debugger/DebuggerCallFrame.cpp:
60
        (JSC::DebuggerCallFrame::scope):
61
        (JSC::DebuggerCallFrame::evaluate):
62
        (JSC::DebuggerCallFrame::invalidate):
63
        (JSC::DebuggerCallFrame::vm):
64
        (JSC::DebuggerCallFrame::lexicalGlobalObject):
65
        * debugger/DebuggerCallFrame.h:
66
        * debugger/DebuggerScope.cpp:
67
        (JSC::DebuggerScope::DebuggerScope):
68
        (JSC::DebuggerScope::finishCreation):
69
        (JSC::DebuggerScope::visitChildren):
70
        (JSC::DebuggerScope::className):
71
        (JSC::DebuggerScope::getOwnPropertySlot):
72
        (JSC::DebuggerScope::put):
73
        (JSC::DebuggerScope::deleteProperty):
74
        (JSC::DebuggerScope::getOwnPropertyNames):
75
        (JSC::DebuggerScope::defineOwnProperty):
76
        (JSC::DebuggerScope::next):
77
        (JSC::DebuggerScope::invalidateChain):
78
        (JSC::DebuggerScope::isWithScope):
79
        (JSC::DebuggerScope::isGlobalScope):
80
        (JSC::DebuggerScope::isFunctionScope):
81
        * debugger/DebuggerScope.h:
82
        (JSC::DebuggerScope::create):
83
        (JSC::DebuggerScope::Iterator::Iterator):
84
        (JSC::DebuggerScope::Iterator::get):
85
        (JSC::DebuggerScope::Iterator::operator++):
86
        (JSC::DebuggerScope::Iterator::operator==):
87
        (JSC::DebuggerScope::Iterator::operator!=):
88
        (JSC::DebuggerScope::isValid):
89
        (JSC::DebuggerScope::jsScope):
90
        (JSC::DebuggerScope::begin):
91
        (JSC::DebuggerScope::end):
92
        * inspector/JSJavaScriptCallFrame.cpp:
93
        (Inspector::JSJavaScriptCallFrame::scopeType):
94
        (Inspector::JSJavaScriptCallFrame::scopeChain):
95
        * inspector/JavaScriptCallFrame.h:
96
        (Inspector::JavaScriptCallFrame::scopeChain):
97
        * inspector/ScriptDebugServer.cpp:
98
        * runtime/JSGlobalObject.cpp:
99
        (JSC::JSGlobalObject::reset):
100
        (JSC::JSGlobalObject::visitChildren):
101
        * runtime/JSGlobalObject.h:
102
        (JSC::JSGlobalObject::debuggerScopeStructure):
103
        * runtime/JSObject.h:
104
        (JSC::JSObject::isWithScope):
105
        * runtime/JSScope.h:
106
        * runtime/VM.cpp:
107
        (JSC::VM::VM):
108
        * runtime/VM.h:
109
1
2014-07-01  Filip Pizlo  <fpizlo@apple.com>
110
2014-07-01  Filip Pizlo  <fpizlo@apple.com>
2
111
3
        [ftlopt] DFG bytecode parser should turn PutById with nothing but a Setter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
112
        [ftlopt] DFG bytecode parser should turn PutById with nothing but a Setter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
- Source/JavaScriptCore/debugger/Debugger.h +1 lines
Lines 34-39 Source/JavaScriptCore/debugger/Debugger.h_sec1
34
34
35
namespace JSC {
35
namespace JSC {
36
36
37
class CodeBlock;
37
class ExecState;
38
class ExecState;
38
class JSGlobalObject;
39
class JSGlobalObject;
39
class SourceProvider;
40
class SourceProvider;
- Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp -9 / +20 lines
Lines 30-41 Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp_sec1
30
#include "DebuggerCallFrame.h"
30
#include "DebuggerCallFrame.h"
31
31
32
#include "CodeBlock.h"
32
#include "CodeBlock.h"
33
#include "DebuggerScope.h"
33
#include "Interpreter.h"
34
#include "Interpreter.h"
34
#include "JSActivation.h"
35
#include "JSActivation.h"
35
#include "JSFunction.h"
36
#include "JSFunction.h"
36
#include "JSCInlines.h"
37
#include "JSCInlines.h"
37
#include "Parser.h"
38
#include "Parser.h"
38
#include "StackVisitor.h"
39
#include "StackVisitor.h"
40
#include "StrongInlines.h"
39
41
40
namespace JSC {
42
namespace JSC {
41
43
Lines 106-125 String DebuggerCallFrame::functionName() Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp_sec2
106
    return getCalculatedDisplayName(m_callFrame, function);
108
    return getCalculatedDisplayName(m_callFrame, function);
107
}
109
}
108
110
109
JSScope* DebuggerCallFrame::scope() const
111
DebuggerScope* DebuggerCallFrame::scope()
110
{
112
{
111
    ASSERT(isValid());
113
    ASSERT(isValid());
112
    if (!isValid())
114
    if (!isValid())
113
        return 0;
115
        return 0;
114
116
115
    CodeBlock* codeBlock = m_callFrame->codeBlock();
117
    if (!m_scope) {
116
    if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
118
        VM& vm = m_callFrame->vm();
117
        JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock);
119
        CodeBlock* codeBlock = m_callFrame->codeBlock();
118
        m_callFrame->setActivation(activation);
120
        if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
119
        m_callFrame->setScope(activation);
121
            ASSERT(!m_callFrame->scope()->isWithScope());
120
    }
122
            JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock);
123
            m_callFrame->setActivation(activation);
124
            m_callFrame->setScope(activation);
125
        }
121
126
122
    return m_callFrame->scope();
127
        m_scope.set(vm, DebuggerScope::create(vm, m_callFrame->scope()));
128
    }
129
    return m_scope.get();
123
}
130
}
124
131
125
DebuggerCallFrame::Type DebuggerCallFrame::type() const
132
DebuggerCallFrame::Type DebuggerCallFrame::type() const
Lines 162-168 JSValue DebuggerCallFrame::evaluate(cons Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp_sec3
162
    }
169
    }
163
170
164
    JSValue thisValue = thisValueForCallFrame(callFrame);
171
    JSValue thisValue = thisValueForCallFrame(callFrame);
165
    JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
172
    JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
166
    if (vm.exception()) {
173
    if (vm.exception()) {
167
        exception = vm.exception();
174
        exception = vm.exception();
168
        vm.clearException();
175
        vm.clearException();
Lines 174-179 JSValue DebuggerCallFrame::evaluate(cons Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp_sec4
174
void DebuggerCallFrame::invalidate()
181
void DebuggerCallFrame::invalidate()
175
{
182
{
176
    m_callFrame = nullptr;
183
    m_callFrame = nullptr;
184
    if (m_scope) {
185
        m_scope->invalidateChain();
186
        m_scope.clear();
187
    }
177
    RefPtr<DebuggerCallFrame> frame = m_caller.release();
188
    RefPtr<DebuggerCallFrame> frame = m_caller.release();
178
    while (frame) {
189
    while (frame) {
179
        frame->m_callFrame = nullptr;
190
        frame->m_callFrame = nullptr;
- Source/JavaScriptCore/debugger/DebuggerCallFrame.h -2 / +7 lines
Lines 29-42 Source/JavaScriptCore/debugger/DebuggerCallFrame.h_sec1
29
#ifndef DebuggerCallFrame_h
29
#ifndef DebuggerCallFrame_h
30
#define DebuggerCallFrame_h
30
#define DebuggerCallFrame_h
31
31
32
#include "CallFrame.h"
33
#include "DebuggerPrimitives.h"
32
#include "DebuggerPrimitives.h"
33
#include "Strong.h"
34
#include <wtf/PassRefPtr.h>
34
#include <wtf/PassRefPtr.h>
35
#include <wtf/RefCounted.h>
35
#include <wtf/RefCounted.h>
36
#include <wtf/text/TextPosition.h>
36
#include <wtf/text/TextPosition.h>
37
37
38
namespace JSC {
38
namespace JSC {
39
39
40
class DebuggerScope;
41
class ExecState;
42
typedef ExecState CallFrame;
43
40
class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
44
class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
41
public:
45
public:
42
    enum Type { ProgramType, FunctionType };
46
    enum Type { ProgramType, FunctionType };
Lines 58-64 public: Source/JavaScriptCore/debugger/DebuggerCallFrame.h_sec2
58
    JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; }
62
    JS_EXPORT_PRIVATE const TextPosition& position() const { return m_position; }
59
63
60
    JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const;
64
    JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const;
61
    JS_EXPORT_PRIVATE JSScope* scope() const;
65
    JS_EXPORT_PRIVATE DebuggerScope* scope();
62
    JS_EXPORT_PRIVATE String functionName() const;
66
    JS_EXPORT_PRIVATE String functionName() const;
63
    JS_EXPORT_PRIVATE Type type() const;
67
    JS_EXPORT_PRIVATE Type type() const;
64
    JS_EXPORT_PRIVATE JSValue thisValue() const;
68
    JS_EXPORT_PRIVATE JSValue thisValue() const;
Lines 78-83 private: Source/JavaScriptCore/debugger/DebuggerCallFrame.h_sec3
78
    CallFrame* m_callFrame;
82
    CallFrame* m_callFrame;
79
    RefPtr<DebuggerCallFrame> m_caller;
83
    RefPtr<DebuggerCallFrame> m_caller;
80
    TextPosition m_position;
84
    TextPosition m_position;
85
    Strong<DebuggerScope> m_scope;
81
};
86
};
82
87
83
} // namespace JSC
88
} // namespace JSC
- Source/JavaScriptCore/debugger/DebuggerScope.cpp -19 / +84 lines
Lines 28-33 Source/JavaScriptCore/debugger/DebuggerScope.cpp_sec1
28
28
29
#include "JSActivation.h"
29
#include "JSActivation.h"
30
#include "JSCInlines.h"
30
#include "JSCInlines.h"
31
#include "JSWithScope.h"
31
32
32
namespace JSC {
33
namespace JSC {
33
34
Lines 35-51 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE( Source/JavaScriptCore/debugger/DebuggerScope.cpp_sec2
35
36
36
const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) };
37
const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) };
37
38
38
DebuggerScope::DebuggerScope(VM& vm)
39
DebuggerScope::DebuggerScope(VM& vm, JSScope* scope)
39
    : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
40
    : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure())
40
{
41
{
42
    ASSERT(scope);
43
    m_scope.set(vm, this, scope);
41
}
44
}
42
45
43
void DebuggerScope::finishCreation(VM& vm, JSObject* activation)
46
void DebuggerScope::finishCreation(VM& vm)
44
{
47
{
45
    Base::finishCreation(vm);
48
    Base::finishCreation(vm);
46
    ASSERT(activation);
47
    ASSERT(activation->isActivationObject());
48
    m_activation.set(vm, this, jsCast<JSActivation*>(activation));
49
}
49
}
50
50
51
void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
51
void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
Lines 56-98 void DebuggerScope::visitChildren(JSCell Source/JavaScriptCore/debugger/DebuggerScope.cpp_sec3
56
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
56
    ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
57
57
58
    JSObject::visitChildren(thisObject, visitor);
58
    JSObject::visitChildren(thisObject, visitor);
59
    visitor.append(&thisObject->m_activation);
59
    visitor.append(&thisObject->m_scope);
60
    visitor.append(&thisObject->m_next);
60
}
61
}
61
62
62
String DebuggerScope::className(const JSObject* object)
63
String DebuggerScope::className(const JSObject* object)
63
{
64
{
64
    const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object);
65
    const DebuggerScope* scope = jsCast<const DebuggerScope*>(object);
65
    return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get());
66
    ASSERT(scope->isValid());
67
    if (!scope->isValid())
68
        return String();
69
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
70
    return thisObject->methodTable()->className(thisObject);
66
}
71
}
67
72
68
bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
73
bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
69
{
74
{
70
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
75
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
71
    return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot);
76
    ASSERT(scope->isValid());
77
    if (!scope->isValid())
78
        return false;
79
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
80
    return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
72
}
81
}
73
82
74
void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
83
void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
75
{
84
{
76
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
85
    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
77
    thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
86
    ASSERT(scope->isValid());
87
    if (!scope->isValid())
88
        return;
89
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
90
    thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot);
78
}
91
}
79
92
80
bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
93
bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
81
{
94
{
82
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
95
    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
83
    return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName);
96
    ASSERT(scope->isValid());
97
    if (!scope->isValid())
98
        return false;
99
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
100
    return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName);
84
}
101
}
85
102
86
void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
103
void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
87
{
104
{
88
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
105
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
89
    thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode);
106
    ASSERT(scope->isValid());
107
    if (!scope->isValid())
108
        return;
109
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
110
    thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode);
90
}
111
}
91
112
92
bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
113
bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
93
{
114
{
94
    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
115
    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
95
    return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow);
116
    ASSERT(scope->isValid());
117
    if (!scope->isValid())
118
        return false;
119
    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
120
    return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
121
}
122
123
DebuggerScope* DebuggerScope::next()
124
{
125
    ASSERT(isValid());
126
    if (!m_next && m_scope->next()) {
127
        VM& vm = *m_scope->vm();
128
        DebuggerScope* nextScope = create(vm, m_scope->next());
129
        m_next.set(vm, this, nextScope);
130
    }
131
    return m_next.get();
132
}
133
134
void DebuggerScope::invalidateChain()
135
{
136
    DebuggerScope* scope = this;
137
    while (scope) {
138
        ASSERT(scope->isValid());
139
        DebuggerScope* nextScope = scope->m_next.get();
140
        scope->m_next.clear();
141
        scope->m_scope.clear();
142
        scope = nextScope;
143
    }
144
}
145
146
bool DebuggerScope::isWithScope() const
147
{
148
    return m_scope->isWithScope();
149
}
150
151
bool DebuggerScope::isGlobalScope() const
152
{
153
    return m_scope->isGlobalObject();
154
}
155
156
bool DebuggerScope::isFunctionScope() const
157
{
158
    // In the current debugger implementation, every function will create an
159
    // activation object. Hence, an activation object implies a function scope.
160
    return m_scope->isActivationObject();
96
}
161
}
97
162
98
} // namespace JSC
163
} // namespace JSC
- Source/JavaScriptCore/debugger/DebuggerScope.h -9 / +55 lines
Lines 30-44 Source/JavaScriptCore/debugger/DebuggerScope.h_sec1
30
30
31
namespace JSC {
31
namespace JSC {
32
32
33
class DebuggerCallFrame;
34
class JSScope;
35
33
class DebuggerScope : public JSNonFinalObject {
36
class DebuggerScope : public JSNonFinalObject {
34
public:
37
public:
35
    typedef JSNonFinalObject Base;
38
    typedef JSNonFinalObject Base;
36
39
37
    static DebuggerScope* create(VM& vm, JSObject* object)
40
    static DebuggerScope* create(VM& vm, JSScope* scope)
38
    {
41
    {
39
        DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm);
42
        DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope);
40
        activation->finishCreation(vm, object);
43
        debuggerScope->finishCreation(vm);
41
        return activation;
44
        return debuggerScope;
42
    }
45
    }
43
46
44
    static void visitChildren(JSCell*, SlotVisitor&);
47
    static void visitChildren(JSCell*, SlotVisitor&);
Lines 56-71 public: Source/JavaScriptCore/debugger/DebuggerScope.h_sec2
56
        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 
59
        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 
57
    }
60
    }
58
61
59
protected:
62
    class Iterator {
63
    public:
64
        Iterator(DebuggerScope* node)
65
            : m_node(node)
66
        {
67
        }
68
69
        DebuggerScope* get() { return m_node; }
70
        Iterator& operator++() { m_node = m_node->next(); return *this; }
71
        // postfix ++ intentionally omitted
72
73
        bool operator==(const Iterator& other) const { return m_node == other.m_node; }
74
        bool operator!=(const Iterator& other) const { return m_node != other.m_node; }
75
76
    private:
77
        DebuggerScope* m_node;
78
    };
79
80
    Iterator begin();
81
    Iterator end();
82
    DebuggerScope* next();
83
84
    void invalidateChain();
85
    bool isValid() const { return !!m_scope; }
86
87
    bool isWithScope() const;
88
    bool isGlobalScope() const;
89
    bool isFunctionScope() const;
90
91
private:
92
    JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
93
    JS_EXPORT_PRIVATE void finishCreation(VM&);
94
95
    JSScope* jsScope() const { return m_scope.get(); }
96
60
    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
97
    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
61
98
62
    JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation);
99
    WriteBarrier<JSScope> m_scope;
100
    WriteBarrier<DebuggerScope> m_next;
63
101
64
private:
102
    friend class DebuggerCallFrame;
65
    JS_EXPORT_PRIVATE DebuggerScope(VM&);
66
    WriteBarrier<JSActivation> m_activation;
67
};
103
};
68
104
105
inline DebuggerScope::Iterator DebuggerScope::begin()
106
{
107
    return Iterator(this); 
108
}
109
110
inline DebuggerScope::Iterator DebuggerScope::end()
111
{ 
112
    return Iterator(0); 
113
}
114
69
} // namespace JSC
115
} // namespace JSC
70
116
71
#endif // DebuggerScope_h
117
#endif // DebuggerScope_h
- Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp -20 / +22 lines
Lines 28-33 Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp_sec1
28
28
29
#if ENABLE(INSPECTOR)
29
#if ENABLE(INSPECTOR)
30
30
31
#include "DebuggerScope.h"
31
#include "Error.h"
32
#include "Error.h"
32
#include "JSCJSValue.h"
33
#include "JSCJSValue.h"
33
#include "JSCellInlines.h"
34
#include "JSCellInlines.h"
Lines 95-123 JSValue JSJavaScriptCallFrame::scopeType Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp_sec2
95
        return jsUndefined();
96
        return jsUndefined();
96
    int index = exec->argument(0).asInt32();
97
    int index = exec->argument(0).asInt32();
97
98
98
    JSScope* scopeChain = impl().scopeChain();
99
    DebuggerScope* scopeChain = impl().scopeChain();
99
    ScopeChainIterator end = scopeChain->end();
100
    DebuggerScope::Iterator end = scopeChain->end();
100
101
    // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
102
101
103
    bool foundLocalScope = false;
102
    bool foundLocalScope = false;
104
    for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) {
103
    for (DebuggerScope::Iterator iter = scopeChain->begin(); iter != end; ++iter) {
105
        JSObject* scope = iter.get();
104
        DebuggerScope* scope = iter.get();
106
        if (scope->isActivationObject()) {
105
107
            if (!foundLocalScope) {
106
        if (!foundLocalScope && scope->isFunctionScope()) {
108
                // First activation object is local scope, each successive activation object is closure.
107
            // First function scope is the local scope, each successive one is a closure.
109
                if (!index)
108
            if (!index)
110
                    return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
109
                return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
111
                foundLocalScope = true;
110
            foundLocalScope = true;
112
            } else if (!index)
113
                return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
114
        }
111
        }
115
112
116
        if (!index) {
113
        if (!index) {
117
            // Last in the chain is global scope.
114
            if (scope->isWithScope())
118
            if (++iter == end)
115
                return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
116
            if (scope->isGlobalScope()) {
117
                ASSERT(++iter == end);
119
                return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
118
                return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
120
            return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
119
            }
120
            // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
121
            ASSERT(scope->isFunctionScope());
122
            return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
121
        }
123
        }
122
124
123
        --index;
125
        --index;
Lines 157-165 JSValue JSJavaScriptCallFrame::scopeChai Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp_sec3
157
    if (!impl().scopeChain())
159
    if (!impl().scopeChain())
158
        return jsNull();
160
        return jsNull();
159
161
160
    JSScope* scopeChain = impl().scopeChain();
162
    DebuggerScope* scopeChain = impl().scopeChain();
161
    ScopeChainIterator iter = scopeChain->begin();
163
    DebuggerScope::Iterator iter = scopeChain->begin();
162
    ScopeChainIterator end = scopeChain->end();
164
    DebuggerScope::Iterator end = scopeChain->end();
163
165
164
    // We must always have something in the scope chain.
166
    // We must always have something in the scope chain.
165
    ASSERT(iter != end);
167
    ASSERT(iter != end);
- Source/JavaScriptCore/inspector/JavaScriptCallFrame.h -2 / +2 lines
Lines 1-5 Source/JavaScriptCore/inspector/JavaScriptCallFrame.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
2
 * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 53-59 public: Source/JavaScriptCore/inspector/JavaScriptCallFrame.h_sec2
53
53
54
    String functionName() const { return m_debuggerCallFrame->functionName(); }
54
    String functionName() const { return m_debuggerCallFrame->functionName(); }
55
    JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); }
55
    JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); }
56
    JSC::JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
56
    JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
57
    JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); }
57
    JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); }
58
58
59
    JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); }
59
    JSC::JSValue thisValue() const { return m_debuggerCallFrame->thisValue(); }
- Source/JavaScriptCore/inspector/ScriptDebugServer.cpp +1 lines
Lines 34-39 Source/JavaScriptCore/inspector/ScriptDebugServer.cpp_sec1
34
#if ENABLE(INSPECTOR)
34
#if ENABLE(INSPECTOR)
35
35
36
#include "DebuggerCallFrame.h"
36
#include "DebuggerCallFrame.h"
37
#include "DebuggerScope.h"
37
#include "JSJavaScriptCallFrame.h"
38
#include "JSJavaScriptCallFrame.h"
38
#include "JSLock.h"
39
#include "JSLock.h"
39
#include "JavaScriptCallFrame.h"
40
#include "JavaScriptCallFrame.h"
- Source/JavaScriptCore/runtime/JSGlobalObject.cpp +3 lines
Lines 45-50 Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec1
45
#include "DateConstructor.h"
45
#include "DateConstructor.h"
46
#include "DatePrototype.h"
46
#include "DatePrototype.h"
47
#include "Debugger.h"
47
#include "Debugger.h"
48
#include "DebuggerScope.h"
48
#include "Error.h"
49
#include "Error.h"
49
#include "ErrorConstructor.h"
50
#include "ErrorConstructor.h"
50
#include "ErrorPrototype.h"
51
#include "ErrorPrototype.h"
Lines 320-325 void JSGlobalObject::reset(JSValue proto Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec2
320
    m_nameScopeStructure.set(vm, this, JSNameScope::createStructure(vm, this, jsNull()));
321
    m_nameScopeStructure.set(vm, this, JSNameScope::createStructure(vm, this, jsNull()));
321
    m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull()));
322
    m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull()));
322
    m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
323
    m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
324
    m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this, jsNull()));
323
    m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
325
    m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
324
326
325
    m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
327
    m_nullPrototypeObjectStructure.set(vm, this, JSFinalObject::createStructure(vm, this, jsNull(), JSFinalObject::defaultInlineCapacity()));
Lines 661-666 void JSGlobalObject::visitChildren(JSCel Source/JavaScriptCore/runtime/JSGlobalObject.cpp_sec3
661
    visitor.append(&thisObject->m_promisePrototype);
663
    visitor.append(&thisObject->m_promisePrototype);
662
#endif
664
#endif
663
665
666
    visitor.append(&thisObject->m_debuggerScopeStructure);
664
    visitor.append(&thisObject->m_withScopeStructure);
667
    visitor.append(&thisObject->m_withScopeStructure);
665
    visitor.append(&thisObject->m_strictEvalActivationStructure);
668
    visitor.append(&thisObject->m_strictEvalActivationStructure);
666
    visitor.append(&thisObject->m_activationStructure);
669
    visitor.append(&thisObject->m_activationStructure);
- Source/JavaScriptCore/runtime/JSGlobalObject.h +2 lines
Lines 183-188 protected: Source/JavaScriptCore/runtime/JSGlobalObject.h_sec1
183
    WriteBarrier<JSPromisePrototype> m_promisePrototype;
183
    WriteBarrier<JSPromisePrototype> m_promisePrototype;
184
#endif
184
#endif
185
185
186
    WriteBarrier<Structure> m_debuggerScopeStructure;
186
    WriteBarrier<Structure> m_withScopeStructure;
187
    WriteBarrier<Structure> m_withScopeStructure;
187
    WriteBarrier<Structure> m_strictEvalActivationStructure;
188
    WriteBarrier<Structure> m_strictEvalActivationStructure;
188
    WriteBarrier<Structure> m_activationStructure;
189
    WriteBarrier<Structure> m_activationStructure;
Lines 388-393 public: Source/JavaScriptCore/runtime/JSGlobalObject.h_sec2
388
    JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); }
389
    JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); }
389
#endif
390
#endif
390
391
392
    Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); }
391
    Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
393
    Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
392
    Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
394
    Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
393
    Structure* activationStructure() const { return m_activationStructure.get(); }
395
    Structure* activationStructure() const { return m_activationStructure.get(); }
- Source/JavaScriptCore/runtime/JSObject.h +6 lines
Lines 599-604 public: Source/JavaScriptCore/runtime/JSObject.h_sec1
599
    bool isNameScopeObject() const;
599
    bool isNameScopeObject() const;
600
    bool isActivationObject() const;
600
    bool isActivationObject() const;
601
    bool isErrorInstance() const;
601
    bool isErrorInstance() const;
602
    bool isWithScope() const;
602
603
603
    JS_EXPORT_PRIVATE void seal(VM&);
604
    JS_EXPORT_PRIVATE void seal(VM&);
604
    JS_EXPORT_PRIVATE void freeze(VM&);
605
    JS_EXPORT_PRIVATE void freeze(VM&);
Lines 1147-1152 inline bool JSObject::isErrorInstance() Source/JavaScriptCore/runtime/JSObject.h_sec2
1147
    return type() == ErrorInstanceType;
1148
    return type() == ErrorInstanceType;
1148
}
1149
}
1149
1150
1151
inline bool JSObject::isWithScope() const
1152
{
1153
    return type() == WithScopeType;
1154
}
1155
1150
inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
1156
inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
1151
{
1157
{
1152
    ASSERT(structure);
1158
    ASSERT(structure);
- Source/JavaScriptCore/runtime/JSScope.h -1 / +1 lines
Lines 150-156 public: Source/JavaScriptCore/runtime/JSScope.h_sec1
150
    friend class LLIntOffsetsExtractor;
150
    friend class LLIntOffsetsExtractor;
151
    static size_t offsetOfNext();
151
    static size_t offsetOfNext();
152
152
153
    JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
153
    static JSObject* objectAtScope(JSScope*);
154
154
155
    static JSValue resolve(ExecState*, JSScope*, const Identifier&);
155
    static JSValue resolve(ExecState*, JSScope*, const Identifier&);
156
    static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType);
156
    static ResolveOp abstractResolve(ExecState*, JSScope*, const Identifier&, GetOrPut, ResolveType);
- Source/JavaScriptCore/runtime/VM.cpp -2 lines
Lines 39-45 Source/JavaScriptCore/runtime/VM.cpp_sec1
39
#include "CommonSlowPaths.h"
39
#include "CommonSlowPaths.h"
40
#include "DFGLongLivedState.h"
40
#include "DFGLongLivedState.h"
41
#include "DFGWorklist.h"
41
#include "DFGWorklist.h"
42
#include "DebuggerScope.h"
43
#include "ErrorInstance.h"
42
#include "ErrorInstance.h"
44
#include "FTLThunks.h"
43
#include "FTLThunks.h"
45
#include "FunctionConstructor.h"
44
#include "FunctionConstructor.h"
Lines 255-261 VM::VM(VMType vmType, HeapType heapType) Source/JavaScriptCore/runtime/VM.cpp_sec2
255
    propertyNames = new CommonIdentifiers(this);
254
    propertyNames = new CommonIdentifiers(this);
256
    structureStructure.set(*this, Structure::createStructure(*this));
255
    structureStructure.set(*this, Structure::createStructure(*this));
257
    structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
256
    structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
258
    debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull()));
259
    terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
257
    terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
260
    stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
258
    stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
261
    notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
259
    notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
- Source/JavaScriptCore/runtime/VM.h -1 lines
Lines 262-268 namespace JSC { Source/JavaScriptCore/runtime/VM.h_sec1
262
262
263
        Strong<Structure> structureStructure;
263
        Strong<Structure> structureStructure;
264
        Strong<Structure> structureRareDataStructure;
264
        Strong<Structure> structureRareDataStructure;
265
        Strong<Structure> debuggerScopeStructure;
266
        Strong<Structure> terminatedExecutionErrorStructure;
265
        Strong<Structure> terminatedExecutionErrorStructure;
267
        Strong<Structure> stringStructure;
266
        Strong<Structure> stringStructure;
268
        Strong<Structure> notAnObjectStructure;
267
        Strong<Structure> notAnObjectStructure;
- Source/WebCore/ChangeLog +15 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2014-07-01  Mark Lam  <mark.lam@apple.com>
2
3
        [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
4
        <https://webkit.org/b/134420>
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        No new tests.
9
10
        * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed.
11
        - This is not in use.  Hence, we can remove it.
12
        * bindings/js/ScriptController.cpp:
13
        (WebCore::ScriptController::attachDebugger):
14
        - We should acquire the JSLock before modifying a JS global object.
15
1
2014-06-25  Filip Pizlo  <fpizlo@apple.com>
16
2014-06-25  Filip Pizlo  <fpizlo@apple.com>
2
17
3
        [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
18
        [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
- Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h -4 lines
Lines 1-4 Source/WebCore/ForwardingHeaders/debugger/DebuggerCallFrame.h_sec1
1
#ifndef WebCore_FWD_DebuggerCallFrame_h
2
#define WebCore_FWD_DebuggerCallFrame_h
3
#include <JavaScriptCore/DebuggerCallFrame.h>
4
#endif
- Source/WebCore/bindings/js/ScriptController.cpp +1 lines
Lines 295-300 void ScriptController::attachDebugger(JS Source/WebCore/bindings/js/ScriptController.cpp_sec1
295
        return;
295
        return;
296
296
297
    JSDOMWindow* globalObject = shell->window();
297
    JSDOMWindow* globalObject = shell->window();
298
    JSLockHolder lock(globalObject->vm());
298
    if (debugger)
299
    if (debugger)
299
        debugger->attach(globalObject);
300
        debugger->attach(globalObject);
300
    else if (JSC::Debugger* currentDebugger = globalObject->debugger())
301
    else if (JSC::Debugger* currentDebugger = globalObject->debugger())

Return to Bug 134420