Bug 40300

Summary: Web Inspector: [JSC] implement script source editing
Product: WebKit Reporter: Yury Semikhatsky <yurys>
Component: JavaScriptCoreAssignee: Nobody <webkit-unassigned>
Status: NEW    
Severity: Normal CC: barraclough, bweinstein, charles.wei, dglazkov, fpizlo, ggaren, gustavo, joepeck, kangax, keishi, kpiascik, mark.lam, oliver, PeterHWang, pfeldman, philn, pmuellr, prybin, rik, vsevik, webkit-bug-importer, webkit.review.bot, xan.lopez, yong.li.webkit, yurys
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch
none
test case
none
Patch
none
Patch
none
Patch
none
Patch
none
Patch oliver: review-

Yury Semikhatsky
Reported 2010-06-08 07:41:42 PDT
Should be possible to edit script sources on the fly.
Attachments
Patch (14.35 KB, patch)
2012-06-20 01:48 PDT, Peter Wang
no flags
Patch (22.92 KB, patch)
2012-06-21 05:02 PDT, Peter Wang
no flags
Patch (22.84 KB, patch)
2012-06-21 06:12 PDT, Peter Wang
no flags
Patch (22.22 KB, patch)
2012-06-24 20:00 PDT, Peter Wang
no flags
Patch (22.21 KB, patch)
2012-06-24 22:31 PDT, Peter Wang
no flags
Patch (23.58 KB, patch)
2012-06-25 00:35 PDT, Peter Wang
no flags
Patch (23.47 KB, patch)
2012-06-25 01:58 PDT, Peter Wang
no flags
Patch (24.06 KB, patch)
2012-07-05 00:06 PDT, Peter Wang
no flags
Patch (23.89 KB, patch)
2012-07-05 00:54 PDT, Peter Wang
no flags
Patch (24.01 KB, patch)
2012-07-05 20:16 PDT, Peter Wang
no flags
Patch (24.25 KB, patch)
2012-07-11 19:59 PDT, Peter Wang
no flags
Patch (24.23 KB, patch)
2012-07-12 19:44 PDT, Peter Wang
no flags
test case (579 bytes, text/html)
2012-07-23 16:53 PDT, Geoffrey Garen
no flags
Patch (26.46 KB, patch)
2012-07-30 21:35 PDT, Peter Wang
no flags
Patch (26.75 KB, patch)
2012-07-30 23:12 PDT, Peter Wang
no flags
Patch (26.75 KB, patch)
2012-07-31 00:06 PDT, Peter Wang
no flags
Patch (26.75 KB, patch)
2012-07-31 01:09 PDT, Peter Wang
no flags
Patch (26.75 KB, patch)
2012-07-31 02:23 PDT, Peter Wang
oliver: review-
kangax
Comment 1 2011-11-05 14:42:18 PDT
This is now implemented, isn't it?
Timothy Hatcher
Comment 2 2012-05-30 13:24:15 PDT
Not for JSC.
Peter Wang
Comment 3 2012-06-20 01:48:48 PDT
WebKit Review Bot
Comment 4 2012-06-20 01:50:52 PDT
Attachment 148524 [details] did not pass style-queue: Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/JavaScriptCore/ChangeLog', u'Source..." exit_code: 1 Source/WebCore/ChangeLog:8: You should remove the 'No new tests' and either add and list tests, or explain why no new tests were possible. [changelog/nonewtests] [5] Total errors found: 1 in 13 files If any of these errors are false positives, please file a bug against check-webkit-style.
Gustavo Noronha (kov)
Comment 5 2012-06-20 01:58:03 PDT
Early Warning System Bot
Comment 6 2012-06-20 01:58:38 PDT
Early Warning System Bot
Comment 7 2012-06-20 01:59:15 PDT
Build Bot
Comment 8 2012-06-20 02:04:11 PDT
Build Bot
Comment 9 2012-06-20 02:13:11 PDT
Yury Semikhatsky
Comment 10 2012-06-20 02:21:51 PDT
Comment on attachment 148524 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=148524&action=review > Source/WebCore/bindings/js/PageScriptDebugServer.cpp:91 > + const ScriptValue& value = frame->script()->executeScript(newContent); This will just re-evaluate the script as if you were running it in the inspector console while setScriptSource command should allow you to modify a function that may have already been run and leave other stuff untouched if its source doesn't change. E.g. changing "var count = 1; function foo() { count++; }" to "var count = 1; function foo() { count--; }" shouldn't reset value of the count variable to 1.
Peter Wang
Comment 11 2012-06-20 02:25:46 PDT
(In reply to comment #10) > (From update of attachment 148524 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=148524&action=review > > > Source/WebCore/bindings/js/PageScriptDebugServer.cpp:91 > > + const ScriptValue& value = frame->script()->executeScript(newContent); > > This will just re-evaluate the script as if you were running it in the inspector console while setScriptSource command should allow you to modify a function that may have already been run and leave other stuff untouched if its source doesn't change. E.g. changing > > "var count = 1; > function foo() > { > count++; > }" > > to > > "var count = 1; > function foo() > { > count--; > }" > > shouldn't reset value of the count variable to 1. I see... Thx.
Peter Wang
Comment 12 2012-06-21 05:02:19 PDT
Build Bot
Comment 13 2012-06-21 05:21:35 PDT
Build Bot
Comment 14 2012-06-21 05:28:58 PDT
Peter Wang
Comment 15 2012-06-21 06:12:26 PDT
Build Bot
Comment 16 2012-06-21 06:33:07 PDT
Build Bot
Comment 17 2012-06-21 06:33:45 PDT
Early Warning System Bot
Comment 18 2012-06-21 06:53:55 PDT
Early Warning System Bot
Comment 19 2012-06-21 07:02:12 PDT
Gyuyoung Kim
Comment 20 2012-06-21 07:20:55 PDT
WebKit Review Bot
Comment 21 2012-06-21 07:21:24 PDT
Comment on attachment 148778 [details] Patch Attachment 148778 [details] did not pass chromium-ews (chromium-xvfb): Output: http://queues.webkit.org/results/13025119
Vsevolod Vlasov
Comment 22 2012-06-21 08:29:52 PDT
Comment on attachment 148778 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=148778&action=review > Source/WebCore/bindings/js/PageScriptDebugServer.cpp:85 > +{ You should change the script with given sourceID live, you are evaluating newContent here, basically creating a new script instead of changing the old one.
Peter Wang
Comment 23 2012-06-24 19:28:33 PDT
(In reply to comment #22) > (From update of attachment 148778 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=148778&action=review > > > Source/WebCore/bindings/js/PageScriptDebugServer.cpp:85 > > +{ > > You should change the script with given sourceID live, you are evaluating newContent here, basically creating a new script instead of changing the old one. I agree that your description is the ideal solution. But it seems impossible for JSC, since neither JSC nor Frame will cache the JS code they executed. JSC just read the string of JS code, "compile" it into Identifiers and executable code blocks, save these things in Global Data structure, and execute. My solution is taking an advantage of JSC: when JSC is "compiling" JS code, if there is an Identifier with an existent name in Global Data, JSC will replace the old with the new. So I did a little modification of "Interpreter::execute": if we just need to recompile, we send a flag to it to let it just replace the old Identifiers and executable code blocks but don't really execute them. By that way we implement the effect of "editing live js code".
Peter Wang
Comment 24 2012-06-24 20:00:21 PDT
Early Warning System Bot
Comment 25 2012-06-24 20:10:55 PDT
Early Warning System Bot
Comment 26 2012-06-24 20:13:11 PDT
Build Bot
Comment 27 2012-06-24 20:16:43 PDT
Build Bot
Comment 28 2012-06-24 20:22:45 PDT
Gyuyoung Kim
Comment 29 2012-06-24 20:41:17 PDT
Peter Wang
Comment 30 2012-06-24 22:31:02 PDT
Build Bot
Comment 31 2012-06-24 22:58:49 PDT
Peter Wang
Comment 32 2012-06-25 00:35:24 PDT
Build Bot
Comment 33 2012-06-25 01:07:21 PDT
Peter Wang
Comment 34 2012-06-25 01:58:37 PDT
Vsevolod Vlasov
Comment 35 2012-06-25 05:02:56 PDT
Someone who knows JSC better should take a look on this.
Geoffrey Garen
Comment 36 2012-06-25 12:05:20 PDT
Peter Wang
Comment 37 2012-07-02 04:25:20 PDT
The main modifications of this patch are: (1) Add a flag to JSC::Interpret::execute, if this flag is true that means we want to compile the code only. (2) In PageScriptDebugServer, record the map between frame and sourceID of JS to ensure the modified JS code will be recompiled in same world. (3) Implement WebCore::ScriptDebugServer::setScriptSource by calling JSC::Interpret::execute with a flag. This solution takes the advantage that when JSC compile the same script it will replace the old Identifier with the new one.
Yong Li
Comment 38 2012-07-04 07:35:56 PDT
Comment on attachment 149263 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=149263&action=review > Source/JavaScriptCore/ChangeLog:8 > +2012-06-21 Peter Wang <peter.wang@torchmobile.com.cn> > + > + [JSC] Web Inspector: implement script source editing > + https://bugs.webkit.org/show_bug.cgi?id=40300 > + > + Reviewed by NOBODY (OOPS!). > + > + * debugger/DebuggerCallFrame.cpp: Can you add more details in changelog? > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool justRecompile) I believe "fooOnly" is more popular pattern in webkit. > Source/JavaScriptCore/runtime/Completion.h:37 > + JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, bool, JSValue thisValue = JSValue(), JSValue* exception = 0); > } // namespace JSC Why isn't justRecompile the last argument here? > Source/WebCore/bindings/js/PageScriptDebugServer.h:58 > + typedef HashMap<String, Frame*> SourceIdToGlobalObjectMap; should be SourceIDToGlobalObjectMap? Are we sure using Frame* is always safe? I.E. no frame can be freed during the life time of this map? Also, is it possible that one script (or one script ID) can be shared by multiple frames? > Source/WebCore/bindings/js/ScriptController.cpp:130 > + > + RefPtr<Frame> protect(m_frame); why do we need this? I don't see how recompiling a script can free the Frame object. > Source/WebCore/bindings/js/ScriptController.h:89 > + JSC::ExecState* getScriptState(); WebKit doesn't use "getFoo" to name such a getter that passes result only through return value. it could be mainThreadNormalWorldState() -- probably too long? :) > Source/WebCore/bindings/js/ScriptDebugServer.cpp:201 > bool ScriptDebugServer::canSetScriptSource() > { > - return false; > + return true; > } why return true here? > Source/WebCore/bindings/js/ScriptDebugServer.cpp:206 > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > { > - // FIXME(40300): implement this. > - return false; > + return true; > } why return true here but nothing is done?
Yong Li
Comment 39 2012-07-04 07:40:13 PDT
Comment on attachment 149263 [details] Patch r- for lack of detailed descriptions in changelog. Also, can you provide a test case (even manual one) or mention how others can test it?
Peter Wang
Comment 40 2012-07-04 20:07:30 PDT
(In reply to comment #38) > (From update of attachment 149263 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=149263&action=review > > > Source/JavaScriptCore/ChangeLog:8 > > +2012-06-21 Peter Wang <peter.wang@torchmobile.com.cn> > > + > > + [JSC] Web Inspector: implement script source editing > > + https://bugs.webkit.org/show_bug.cgi?id=40300 > > + > > + Reviewed by NOBODY (OOPS!). > > + > > + * debugger/DebuggerCallFrame.cpp: > > Can you add more details in changelog? ok. > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool justRecompile) > > I believe "fooOnly" is more popular pattern in webkit. ok, thx. > > Source/JavaScriptCore/runtime/Completion.h:37 > > + JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, bool, JSValue thisValue = JSValue(), JSValue* exception = 0); > > } // namespace JSC > > Why isn't justRecompile the last argument here? Because the last two parameters have default value, if we pull justRecompile in last position we have to set a default value otherwise it causes a compiling error. > > Source/WebCore/bindings/js/PageScriptDebugServer.h:58 > > + typedef HashMap<String, Frame*> SourceIdToGlobalObjectMap; > > should be SourceIDToGlobalObjectMap? sure, thx. > Are we sure using Frame* is always safe? I.E. no frame can be freed during the life time of this map? Yes, if the frame is freed the inspector will refresh. So if you can see the source code in inspector, the related frame must exists. > Also, is it possible that one script (or one script ID) can be shared by multiple frames? Never. Actually the ID here is the address of SourceProvider of a JS code block. We take it as a index to record from which frame this piece of JS code is executed. > > Source/WebCore/bindings/js/ScriptController.cpp:130 > > + > > + RefPtr<Frame> protect(m_frame); > > why do we need this? I don't see how recompiling a script can free the Frame object. Yes, thx. It's the code from my old patch. It's useless now and should be removed. > > Source/WebCore/bindings/js/ScriptController.h:89 > > + JSC::ExecState* getScriptState(); > > WebKit doesn't use "getFoo" to name such a getter that passes result only through return value. it could be mainThreadNormalWorldState() -- probably too long? :) ok. > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:201 > > bool ScriptDebugServer::canSetScriptSource() > > { > > - return false; > > + return true; > > } > > why return true here? It's a legacy code, since JSC doesn't support this feature but V8 support. Inpsector uses this interface to probe it. If this bug is fixed, this function plus related JS code of front-end will be removed in a dependent bug report. > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:206 > > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > > { > > - // FIXME(40300): implement this. > > - return false; > > + return true; > > } > > why return true here but nothing is done? This function is never be invoked. Its override in PageScriptDebugServer will play the rule. For JSC we cannot implement the feature at "ScriptDebugServer" level as V8 does, since V8 seems have a extra shell layer to record the origin of JS source code.
Peter Wang
Comment 41 2012-07-05 00:06:17 PDT
Build Bot
Comment 42 2012-07-05 00:34:23 PDT
Peter Wang
Comment 43 2012-07-05 00:54:08 PDT
Yong Li
Comment 44 2012-07-05 07:22:29 PDT
(In reply to comment #40) > (In reply to comment #38) > > Why isn't justRecompile the last argument here? > Because the last two parameters have default value, if we pull justRecompile in last position we have to set a default value otherwise it causes a compiling error. Then we can give a default value? or move arg to the similar position for other functions? It is better to see consistent order. > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:201 > > > bool ScriptDebugServer::canSetScriptSource() > > > { > > > - return false; > > > + return true; > > > } > > > > why return true here? > It's a legacy code, since JSC doesn't support this feature but V8 support. Inpsector uses this interface to probe it. If this bug is fixed, this function plus related JS code of front-end will be removed in a dependent bug report. I see we are using PageScriptDebugServer. Can we make it virtual and leave the base class to return false? > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:206 > > > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > > > { > > > - // FIXME(40300): implement this. > > > - return false; > > > + return true; > > > } > > > > why return true here but nothing is done? > This function is never be invoked. Its override in PageScriptDebugServer will play the rule. For JSC we cannot implement the feature at "ScriptDebugServer" level as V8 does, since V8 seems have a extra shell layer to record the origin of JS source code. If it is never invoked, why do we change it? A pure virtual function or ASSERT_NOT_REACHED may be better. > > > > should be SourceIDToGlobalObjectMap? > sure, thx. m_sourceIdToGlobalObjectMap is still there :)
Peter Wang
Comment 45 2012-07-05 18:00:08 PDT
(In reply to comment #44) > (In reply to comment #40) > > (In reply to comment #38) > > > Why isn't justRecompile the last argument here? > > Because the last two parameters have default value, if we pull justRecompile in last position we have to set a default value otherwise it causes a compiling error. > > Then we can give a default value? or move arg to the similar position for other functions? It is better to see consistent order. Yes, but there is a trivial reason causes we cannot do that. Firstly, we have to keep the old interface untouched: evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0); Otherwise we will break the windows porting since it's a interface of DLL. Then if we put "compileOnly" in last position with a default value, looks like this: evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0, bool compileOnly = false); The compiler will confused it with the old interface and complain. > > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:201 > > > > bool ScriptDebugServer::canSetScriptSource() > > > > { > > > > - return false; > > > > + return true; > > > > } > > > > > > why return true here? > > It's a legacy code, since JSC doesn't support this feature but V8 support. Inpsector uses this interface to probe it. If this bug is fixed, this function plus related JS code of front-end will be removed in a dependent bug report. > > I see we are using PageScriptDebugServer. Can we make it virtual and leave the base class to return false? Don't worry this function too much. It will be removed soon after this bug fixed, like what we did in bug#88759 > > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:206 > > > > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > > > > { > > > > - // FIXME(40300): implement this. > > > > - return false; > > > > + return true; > > > > } > > > > > > why return true here but nothing is done? > > This function is never be invoked. Its override in PageScriptDebugServer will play the rule. For JSC we cannot implement the feature at "ScriptDebugServer" level as V8 does, since V8 seems have a extra shell layer to record the origin of JS source code. > > If it is never invoked, why do we change it? A pure virtual function or ASSERT_NOT_REACHED may be better. Agree with ASSERT_NOT_REACHED, it tells design intension more clearly. Thx. > > > > > > should be SourceIDToGlobalObjectMap? > > sure, thx. > > m_sourceIdToGlobalObjectMap is still there :) I'm so sorry. It'll be corrected.
Peter Wang
Comment 46 2012-07-05 20:16:20 PDT
Yong Li
Comment 47 2012-07-06 07:12:42 PDT
(In reply to comment #45) > (In reply to comment #44) > > (In reply to comment #40) > > > (In reply to comment #38) > > > > Why isn't justRecompile the last argument here? > > > Because the last two parameters have default value, if we pull justRecompile in last position we have to set a default value otherwise it causes a compiling error. > > > > Then we can give a default value? or move arg to the similar position for other functions? It is better to see consistent order. > > Yes, but there is a trivial reason causes we cannot do that. Firstly, we have to keep the old interface untouched: > evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0); > Otherwise we will break the windows porting since it's a interface of DLL. > Then if we put "compileOnly" in last position with a default value, looks like this: > evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0, bool compileOnly = false); > The compiler will confused it with the old interface and complain. Can't we change the DLL interface or ask Apple gentlemen for help? > > > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:201 > > > > > bool ScriptDebugServer::canSetScriptSource() > > > > > { > > > > > - return false; > > > > > + return true; > > > > > } > > > > > > > > why return true here? > > > It's a legacy code, since JSC doesn't support this feature but V8 support. Inpsector uses this interface to probe it. If this bug is fixed, this function plus related JS code of front-end will be removed in a dependent bug report. > > > > I see we are using PageScriptDebugServer. Can we make it virtual and leave the base class to return false? > Don't worry this function too much. It will be removed soon after this bug fixed, like what we did in bug#88759 We shouldn't push unfinished thing into the repo. Logically ScriptDebugServer doesn't support setScriptSource() by itself.
Konrad Piascik
Comment 48 2012-07-06 07:43:30 PDT
Comment on attachment 151015 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=151015&action=review > Source/WebCore/ChangeLog:12 > + The related test cases already exist. Do the tests need to be enalbed on JSC builds? ie unskipped?
Yong Li
Comment 49 2012-07-06 07:48:24 PDT
Comment on attachment 151015 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=151015&action=review > Source/WebCore/bindings/js/ScriptDebugServer.cpp:207 > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > { > - // FIXME(40300): implement this. > + ASSERT_NOT_REACHED(); > return false; > } As pointed by Konrad, ASSERT_NOT_REACHED() looks weird here because pure virtual function makes more sense. sorry for my old suggestion.
Yong Li
Comment 50 2012-07-06 07:50:22 PDT
Can JSC experts put some comments? Is it the right approach?
Peter Wang
Comment 51 2012-07-06 16:20:06 PDT
(In reply to comment #48) > (From update of attachment 151015 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=151015&action=review > > > Source/WebCore/ChangeLog:12 > > + The related test cases already exist. > > Do the tests need to be enalbed on JSC builds? ie unskipped? Frankly speaking, I don't plan to unskip related test case here, since at least Qt porting still has some problems to support some inspector test, like bug#89056. I'm planning to enable it in an independent bug report to make it more clear.
Peter Wang
Comment 52 2012-07-06 16:24:54 PDT
(In reply to comment #49) > (From update of attachment 151015 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=151015&action=review > > > Source/WebCore/bindings/js/ScriptDebugServer.cpp:207 > > bool ScriptDebugServer::setScriptSource(const String&, const String&, bool, String*, ScriptValue*, ScriptObject*) > > { > > - // FIXME(40300): implement this. > > + ASSERT_NOT_REACHED(); > > return false; > > } > > As pointed by Konrad, ASSERT_NOT_REACHED() looks weird here because pure virtual function makes more sense. sorry for my old suggestion. I agree with Konrad that pure virtual function is better, but some porting derived their own new class form "ScriptDebugServer", pure virtual function will break their own code :(.
Peter Wang
Comment 53 2012-07-11 19:59:57 PDT
Peter Wang
Comment 54 2012-07-11 21:08:23 PDT
(In reply to comment #53) > Created an attachment (id=151849) [details] > Patch Since the interface "setScriptSource" for JSC is implemented in "PageScriptDebugServer", so set it as pure virtual function to avoid misuse and make the meaning of code more clear.
Yong Li
Comment 55 2012-07-12 07:25:05 PDT
So, we don't worry about this any more? "some porting derived their own new class form "ScriptDebugServer" Also ScriptDebugServer::canSetScriptSource() should be virtual. It is weird that the base class forces all derived classes to support it. If so, why do we even call this method? Back to the approach you are doing, have you tested the case that the script has been referenced by other scripts? I am afraid some JIT assemblies can still be using the old executable, or even worse, linking to freed memory.
Filip Pizlo
Comment 56 2012-07-12 14:49:05 PDT
Comment on attachment 151849 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > Source/JavaScriptCore/runtime/Completion.cpp:-56 > - JSLockHolder lock(exec); Did you put in some locking elsewhere to justify the removal of this lock acquisition?
Peter Wang
Comment 57 2012-07-12 19:03:16 PDT
(In reply to comment #55) > So, we don't worry about this any more? "some porting derived their own new class form "ScriptDebugServer" > > Also ScriptDebugServer::canSetScriptSource() should be virtual. It is weird that the base class forces all derived classes to support it. If so, why do we even call this method? Like bug#88759, this bug removed an interface ScriptDebugServer::supportsNativeBreakpoints(), this interface existed just because JSC didn't support a feature that V8 supports. As JSC started to support it, this interface became useless and was removed. We'll do the same thing to canSetScriptSource(). These interfaces are just transitions, so eventually they will be removed. > Back to the approach you are doing, have you tested the case that the script has been referenced by other scripts? I am afraid some JIT assemblies can still be using the old executable, or even worse, linking to freed memory. Yes, I did. My approach is almost executing the same piece of JS again, just skip the step of creating a new call frame and reading the executable to evaluate. All the operations that can change the executable are still included, so I think it's safe.
Peter Wang
Comment 58 2012-07-12 19:34:09 PDT
(In reply to comment #56) > (From update of attachment 151849 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. It's the reason. > > > Source/JavaScriptCore/runtime/Completion.cpp:-56 > > - JSLockHolder lock(exec); > > Did you put in some locking elsewhere to justify the removal of this lock acquisition? Oops, sorry. It's supposed to be here. It's a mistake, seems imported from attachment 149263 [details]. I'll correct it.
Peter Wang
Comment 59 2012-07-12 19:44:43 PDT
Filip Pizlo
Comment 60 2012-07-12 19:51:26 PDT
Comment on attachment 152134 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=152134&action=review > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) Split this into two methods, one that compiles, and the other that compiles and executes.
Filip Pizlo
Comment 61 2012-07-12 19:51:51 PDT
(In reply to comment #58) > (In reply to comment #56) > > (From update of attachment 151849 [details] [details]) > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > > I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. > It's the reason. Are you joking? > > > > > > Source/JavaScriptCore/runtime/Completion.cpp:-56 > > > - JSLockHolder lock(exec); > > > > Did you put in some locking elsewhere to justify the removal of this lock acquisition? > > Oops, sorry. It's supposed to be here. It's a mistake, seems imported from attachment 149263 [details]. I'll correct it.
Peter Wang
Comment 62 2012-07-12 20:09:49 PDT
(In reply to comment #61) > (In reply to comment #58) > > (In reply to comment #56) > > > (From update of attachment 151849 [details] [details] [details]) > > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > > > > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > > > > I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. > > It's the reason. > > Are you joking? > ?? No. I'm serious. Parsing, Building AST, Generiting bytecode, creating call frame to evaluate the executable. Except the last step, Interpreter::execute does all steps of compiling.
Filip Pizlo
Comment 63 2012-07-12 20:11:31 PDT
(In reply to comment #62) > (In reply to comment #61) > > (In reply to comment #58) > > > (In reply to comment #56) > > > > (From update of attachment 151849 [details] [details] [details] [details]) > > > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > > > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > > > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > > > > > > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > > > > > > I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. > > > It's the reason. > > > > Are you joking? > > > ?? > No. I'm serious. Parsing, Building AST, Generiting bytecode, creating call frame to evaluate the executable. Except the last step, Interpreter::execute does all steps of compiling. Invoking a method called "execute" in order to compile something is bizarre.
Peter Wang
Comment 64 2012-07-12 20:34:47 PDT
(In reply to comment #63) > (In reply to comment #62) > > (In reply to comment #61) > > > (In reply to comment #58) > > > > (In reply to comment #56) > > > > > (From update of attachment 151849 [details] [details] [details] [details] [details]) > > > > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > > > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > > > > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > > > > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > > > > > > > > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > > > > > > > > I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. > > > > It's the reason. > > > > > > Are you joking? > > > > > ?? > > No. I'm serious. Parsing, Building AST, Generiting bytecode, creating call frame to evaluate the executable. Except the last step, Interpreter::execute does all steps of compiling. > > Invoking a method called "execute" in order to compile something is bizarre. Yes, so I'd like to discuss. Based on the current situation, by my opinion, I think there are three ways to solve it: (1) Have independent compile() and execute() with a big block of same code. (2) Have execute() with a parameter. (3) Move compiling related code to an independent function compile(), and let execute() to invoke it. I said the reason why I don't choose (1). I prefer (2) because it brings minimal modification. Do you mean you prefer (3)? I just concern there is too big modification.
Filip Pizlo
Comment 65 2012-07-12 20:43:19 PDT
(In reply to comment #64) > (In reply to comment #63) > > (In reply to comment #62) > > > (In reply to comment #61) > > > > (In reply to comment #58) > > > > > (In reply to comment #56) > > > > > > (From update of attachment 151849 [details] [details] [details] [details] [details] [details]) > > > > > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > > > > > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > > > > > > -JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj) > > > > > > > +JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, bool compileOnly) > > > > > > > > > > > > It would be better if we created a compile() helper, preferably outside of the Interpreter class if it's easy. That way instead of saying execute(blah, true) you'd say compile(). > > > > > > > > > > I considered this way once. But Interpreter::execute implements all steps of compiling, so that if I want to write an independent compile(), I just need to copy Interpreter::execute and delete several lines, it looks ugly. > > > > > It's the reason. > > > > > > > > Are you joking? > > > > > > > ?? > > > No. I'm serious. Parsing, Building AST, Generiting bytecode, creating call frame to evaluate the executable. Except the last step, Interpreter::execute does all steps of compiling. > > > > Invoking a method called "execute" in order to compile something is bizarre. > > Yes, so I'd like to discuss. Based on the current situation, by my opinion, I think there are three ways to solve it: > (1) Have independent compile() and execute() with a big block of same code. Bad. > (2) Have execute() with a parameter. Bad. > (3) Move compiling related code to an independent function compile(), and let execute() to invoke it. That's what I'm asking for. > I said the reason why I don't choose (1). I prefer (2) because it brings minimal modification. Do you mean you prefer (3)? I just concern there is too big modification. (3) is the only sensible path.
Peter Wang
Comment 66 2012-07-12 20:57:20 PDT
(In reply to comment #65) > (In reply to comment #64) > > (In reply to comment #63) > > > (In reply to comment #62) > > > > (In reply to comment #61) > > > > > (In reply to comment #58) > > > > > > (In reply to comment #56) > > > > > > > (From update of attachment 151849 [details] [details] [details] [details] [details] [details] [details]) > > > > > > > View in context: https://bugs.webkit.org/attachment.cgi?id=151849&action=review > > > > > > > > > > > > > > > Source/JavaScriptCore/interpreter/Interpreter.cpp:1094 > > (3) Move compiling related code to an independent function compile(), and let execute() to invoke it. > > That's what I'm asking for. > > > I said the reason why I don't choose (1). I prefer (2) because it brings minimal modification. Do you mean you prefer (3)? I just concern there is too big modification. > > (3) is the only sensible path. Ok, I understand what you mean now. I'll try to make a new patch.
Geoffrey Garen
Comment 67 2012-07-16 12:27:03 PDT
Comment on attachment 152134 [details] Patch It looks like this patch will recompile a top-level program and then replace all global functions declared by that program using the function keyword. Is that really how this feature is supposed to work? What happens to non-global functions and functions declared using the var keyword?
Peter Wang
Comment 68 2012-07-23 05:21:11 PDT
(In reply to comment #67) > (From update of attachment 152134 [details]) > It looks like this patch will recompile a top-level program and then replace all global functions declared by that program using the function keyword. Is that really how this feature is supposed to work? What happens to non-global functions and functions declared using the var keyword? Sorry for reply your comments so late. I did a test again, my patch can pass the test cases you mentioned. Since the Identifier of old function is replaced, the function body will also be recompiled.
Geoffrey Garen
Comment 69 2012-07-23 16:53:20 PDT
Created attachment 153900 [details] test case I believe this test case will fail, given your approach to code editing.
Peter Wang
Comment 70 2012-07-23 18:59:46 PDT
(In reply to comment #69) > Created an attachment (id=153900) [details] > test case > > I believe this test case will fail, given your approach to code editing. I did a test, my patch can pass this test. :)
Peter Wang
Comment 71 2012-07-30 21:35:59 PDT
Build Bot
Comment 72 2012-07-30 21:58:02 PDT
Build Bot
Comment 73 2012-07-30 22:10:32 PDT
Peter Wang
Comment 74 2012-07-30 23:12:15 PDT
Build Bot
Comment 75 2012-07-30 23:35:52 PDT
Peter Wang
Comment 76 2012-07-31 00:06:52 PDT
Build Bot
Comment 77 2012-07-31 00:24:25 PDT
Peter Wang
Comment 78 2012-07-31 01:09:02 PDT
Build Bot
Comment 79 2012-07-31 01:27:48 PDT
Peter Wang
Comment 80 2012-07-31 02:23:28 PDT
Geoffrey Garen
Comment 81 2012-08-16 09:49:11 PDT
> > I believe this test case will fail, given your approach to code editing. > > I did a test, my patch can pass this test. :) I don't think you ran the test right. I don't see any code in this patch that would make it work.
Peter Wang
Comment 82 2012-08-27 05:11:32 PDT
(In reply to comment #81) > > > I believe this test case will fail, given your approach to code editing. > > > > I did a test, my patch can pass this test. :) > > I don't think you ran the test right. I don't see any code in this patch that would make it work. Sorry, I did a test again with newest code, my patch doesn't pass this test, and V8 can pass it. :( However, the reason is not that the embedded functions aren't be recompiled. In JSC, the expression var aa = function button1Click() {...}; is compiled as there is a function declaration with name "aa" (refer to JSC::AssignResolveNode::emitBytecode). And we need "execute" these bytecodes to make "aa" to become related with the new function body. The book "JavaScript: The Definitive Guide" says, for that type of expression, like var aa = function button1Click() {...}; "aa" should work like a pointer to the function. I'm not expert of javascript syntax, maybe it's a defect of JSC implementation?
Geoffrey Garen
Comment 83 2012-08-27 17:50:05 PDT
> I'm not expert of javascript syntax, maybe it's a defect of JSC implementation? No, you've just misdiagnosed the issue.
Peter Wang
Comment 84 2012-08-27 18:27:50 PDT
(In reply to comment #83) > > I'm not expert of javascript syntax, maybe it's a defect of JSC implementation? > > No, you've just misdiagnosed the issue. Sorry, I'm a little confused. You mean: (1) The way to implementation of "setScriptSource" is wrong, I shouldn't implement it by recompiling? (2) Or, I don't understand this feature well? I think it gives user a chance to modify some function or expression and see what will happen if these function or expression triggered. Do you think it's right?
Peter Wang
Comment 85 2012-10-09 03:05:15 PDT
(In reply to comment #83) > > I'm not expert of javascript syntax, maybe it's a defect of JSC implementation? > > No, you've just misdiagnosed the issue. Agree, I understand it now, thank you very much.
Pavel Feldman
Comment 86 2012-12-14 00:20:16 PST
It requires a JSC reviewer, changing the component to remove it off the inspector dashboard.
Timothy Hatcher
Comment 87 2013-01-23 12:03:36 PST
Can someone on the JSC team take a look at the latest patch?
Oliver Hunt
Comment 88 2013-01-23 12:05:17 PST
Comment on attachment 155472 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=155472&action=review I've redone how compilation works since this patch was put up so a lot of the refactoring can probably go away :-/ > Source/JavaScriptCore/interpreter/Interpreter.cpp:1131 > - if (i == 0) { > + if (!i) { Don't change this, while it's a style violation we don't really like changes just to appease the style bot.
kangax
Comment 89 2013-12-10 01:57:51 PST
Any news on this?
Peter Wang
Comment 90 2013-12-11 19:07:43 PST
(In reply to comment #89) > Any news on this? The patches of mine cannot cover all the cases, so just ignore them. I'm not sure if JSC supports live-editing js code right now. If not, maybe, I should spend sometime to investigate and try again.
Timothy Hatcher
Comment 91 2013-12-11 19:44:14 PST
JSC does not support live-editing right now. It is a complex problem (especially when closures are involved.)
Note You need to log in before you can comment on or make changes to this bug.