Add central bridge for liveedit support
authorpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Feb 2010 20:37:08 +0000 (20:37 +0000)
committerpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 17 Feb 2010 20:37:08 +0000 (20:37 +0000)
Review URL: http://codereview.chromium.org/607004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3891 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/SConscript
src/codegen.cc
src/compiler.cc
src/full-codegen.cc
src/liveedit.cc [new file with mode: 0644]
src/liveedit.h [new file with mode: 0644]
tools/gyp/v8.gyp
tools/visual_studio/v8_base.vcproj
tools/visual_studio/v8_base_arm.vcproj
tools/visual_studio/v8_base_x64.vcproj

index b5a894f..1a81cc7 100755 (executable)
@@ -72,6 +72,7 @@ SOURCES = {
     interpreter-irregexp.cc
     jsregexp.cc
     jump-target.cc
+    liveedit.cc
     log-utils.cc
     log.cc
     mark-compact.cc
index 1c3ecc4..01ee6d0 100644 (file)
@@ -31,6 +31,7 @@
 #include "codegen-inl.h"
 #include "compiler.h"
 #include "debug.h"
+#include "liveedit.h"
 #include "oprofile-agent.h"
 #include "prettyprinter.h"
 #include "register-allocator-inl.h"
@@ -234,6 +235,7 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
 // all the pieces into a Code object. This function is only to be called by
 // the compiler.cc code.
 Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
+  LiveEditFunctionTracker live_edit_tracker(info->function());
   Handle<Script> script = info->script();
   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
     int len = String::cast(script->source())->length();
@@ -245,6 +247,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
   MacroAssembler masm(NULL, kInitialBufferSize);
   CodeGenerator cgen(&masm);
   CodeGeneratorScope scope(&cgen);
+  live_edit_tracker.RecordFunctionScope(info->function()->scope());
   cgen.Generate(info, PRIMARY);
   if (cgen.HasStackOverflow()) {
     ASSERT(!Top::has_pending_exception());
@@ -253,7 +256,9 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
 
   InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
   Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
-  return MakeCodeEpilogue(cgen.masm(), flags, info);
+  Handle<Code> result = MakeCodeEpilogue(cgen.masm(), flags, info);
+  live_edit_tracker.RecordFunctionCode(result);
+  return result;
 }
 
 
index 6202431..557a91e 100755 (executable)
@@ -38,6 +38,7 @@
 #include "rewriter.h"
 #include "scopes.h"
 #include "usage-analyzer.h"
+#include "liveedit.h"
 
 namespace v8 {
 namespace internal {
@@ -429,7 +430,8 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
   // compiled. These builtins cannot be handled lazily by the parser,
   // since we have to know if a function uses the special natives
   // syntax, which is something the parser records.
-  bool allow_lazy = literal->AllowsLazyCompilation();
+  bool allow_lazy = literal->AllowsLazyCompilation() &&
+      !LiveEditFunctionTracker::IsActive();
 
   // Generate code
   Handle<Code> code;
index 40a1d66..d7e2504 100644 (file)
@@ -32,6 +32,7 @@
 #include "full-codegen.h"
 #include "stub-cache.h"
 #include "debug.h"
+#include "liveedit.h"
 
 namespace v8 {
 namespace internal {
@@ -448,6 +449,8 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
   CodeGenerator::MakeCodePrologue(info);
   const int kInitialBufferSize = 4 * KB;
   MacroAssembler masm(NULL, kInitialBufferSize);
+  LiveEditFunctionTracker live_edit_tracker(info->function());
+
   FullCodeGenerator cgen(&masm);
   cgen.Generate(info, PRIMARY);
   if (cgen.HasStackOverflow()) {
@@ -455,7 +458,9 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
     return Handle<Code>::null();
   }
   Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
-  return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
+  Handle<Code> result = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
+  live_edit_tracker.RecordFunctionCode(result);
+  return result;
 }
 
 
diff --git a/src/liveedit.cc b/src/liveedit.cc
new file mode 100644 (file)
index 0000000..01badc0
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+#include "v8.h"
+
+#include "liveedit.h"
+#include "compiler.h"
+#include "oprofile-agent.h"
+#include "scopes.h"
+#include "global-handles.h"
+#include "debug.h"
+
+namespace v8 {
+namespace internal {
+
+
+class FunctionInfoListener {
+ public:
+  void FunctionStarted(FunctionLiteral* fun) {
+    // Implementation follows.
+  }
+
+  void FunctionDone() {
+    // Implementation follows.
+  }
+
+  void FunctionScope(Scope* scope){
+    // Implementation follows.
+  }
+
+  void FunctionCode(Handle<Code> function_code) {
+    // Implementation follows.
+  }
+};
+
+static FunctionInfoListener* active_function_info_listener = NULL;
+
+LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
+  if (active_function_info_listener != NULL) {
+    active_function_info_listener->FunctionStarted(fun);
+  }
+}
+LiveEditFunctionTracker::~LiveEditFunctionTracker() {
+  if (active_function_info_listener != NULL) {
+    active_function_info_listener->FunctionDone();
+  }
+}
+void LiveEditFunctionTracker::RecordFunctionCode(Handle<Code> code) {
+  if (active_function_info_listener != NULL) {
+    active_function_info_listener->FunctionCode(code);
+  }
+}
+void LiveEditFunctionTracker::RecordFunctionScope(Scope* scope) {
+  if (active_function_info_listener != NULL) {
+    active_function_info_listener->FunctionScope(scope);
+  }
+}
+bool LiveEditFunctionTracker::IsActive() {
+  return active_function_info_listener != NULL;
+}
+
+} }  // namespace v8::internal
diff --git a/src/liveedit.h b/src/liveedit.h
new file mode 100644 (file)
index 0000000..96dea90
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_LIVEEDIT_H_
+#define V8_LIVEEDIT_H_
+
+
+
+// Live Edit feature implementation.
+// User should be able to change script on already running VM. This feature
+// matches hot swap features in other frameworks.
+//
+// The basic use-case is when user spots some mistake in function body
+// from debugger and wishes to change the algorithm without restart.
+//
+// A single change always has a form of a simple replacement (in pseudo-code):
+//   script.source[positions, positions+length] = new_string;
+// Implementation first determines, which function's body includes this
+// change area. Then both old and new versions of script are fully compiled
+// in order to analyze, whether the function changed its outer scope
+// expectations (or number of parameters). If it didn't, function's code is
+// patched with a newly compiled code. If it did change, enclosing function
+// gets patched. All inner functions are left untouched, whatever happened
+// to them in a new script version. However, new version of code will
+// instantiate newly compiled functions.
+
+
+#include "compiler.h"
+
+namespace v8 {
+namespace internal {
+
+// This class collects some specific information on structure of functions
+// in a particular script. It gets called from compiler all the time, but
+// actually records any data only when liveedit operation is in process;
+// in any other time this class is very cheap.
+//
+// The primary interest of the Tracker is to record function scope structures
+// in order to analyze whether function code maybe safely patched (with new
+// code successfully reading existing data from function scopes). The Tracker
+// also collects compiled function codes.
+class LiveEditFunctionTracker {
+ public:
+  LiveEditFunctionTracker(FunctionLiteral* fun);
+  ~LiveEditFunctionTracker();
+  void RecordFunctionCode(Handle<Code> code);
+  void RecordFunctionScope(Scope* scope);
+
+  static bool IsActive();
+};
+
+} }  // namespace v8::internal
+
+#endif /* V*_LIVEEDIT_H_ */
index 48070d4..9fea73c 100644 (file)
         '../../src/jsregexp.h',
         '../../src/list-inl.h',
         '../../src/list.h',
+        '../../src/liveedit.cc',
+        '../../src/liveedit.h',
         '../../src/log-inl.h',
         '../../src/log-utils.cc',
         '../../src/log-utils.h',
index 685ad64..fdb6cd0 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\src\liveedit.cc"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\liveedit.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\src\log.cc"
                                >
                        </File>
index 4fa8461..2602be4 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\src\liveedit.cc"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\liveedit.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\src\log.cc"
                                >
                        </File>
index b47d75f..d3f55c6 100644 (file)
                                >
                        </File>
                        <File
+                               RelativePath="..\..\src\liveedit.cc"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\..\src\liveedit.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\..\src\log.cc"
                                >
                        </File>