Home | History | Annotate | Download | only in src
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_LIVEEDIT_H_
     29 #define V8_LIVEEDIT_H_
     30 
     31 
     32 
     33 // Live Edit feature implementation.
     34 // User should be able to change script on already running VM. This feature
     35 // matches hot swap features in other frameworks.
     36 //
     37 // The basic use-case is when user spots some mistake in function body
     38 // from debugger and wishes to change the algorithm without restart.
     39 //
     40 // A single change always has a form of a simple replacement (in pseudo-code):
     41 //   script.source[positions, positions+length] = new_string;
     42 // Implementation first determines, which function's body includes this
     43 // change area. Then both old and new versions of script are fully compiled
     44 // in order to analyze, whether the function changed its outer scope
     45 // expectations (or number of parameters). If it didn't, function's code is
     46 // patched with a newly compiled code. If it did change, enclosing function
     47 // gets patched. All inner functions are left untouched, whatever happened
     48 // to them in a new script version. However, new version of code will
     49 // instantiate newly compiled functions.
     50 
     51 
     52 #include "allocation.h"
     53 #include "compiler.h"
     54 
     55 namespace v8 {
     56 namespace internal {
     57 
     58 // This class collects some specific information on structure of functions
     59 // in a particular script. It gets called from compiler all the time, but
     60 // actually records any data only when liveedit operation is in process;
     61 // in any other time this class is very cheap.
     62 //
     63 // The primary interest of the Tracker is to record function scope structures
     64 // in order to analyze whether function code maybe safely patched (with new
     65 // code successfully reading existing data from function scopes). The Tracker
     66 // also collects compiled function codes.
     67 class LiveEditFunctionTracker {
     68  public:
     69   explicit LiveEditFunctionTracker(Isolate* isolate, FunctionLiteral* fun);
     70   ~LiveEditFunctionTracker();
     71   void RecordFunctionInfo(Handle<SharedFunctionInfo> info,
     72                           FunctionLiteral* lit);
     73   void RecordRootFunctionInfo(Handle<Code> code);
     74 
     75   static bool IsActive(Isolate* isolate);
     76 
     77  private:
     78 #ifdef ENABLE_DEBUGGER_SUPPORT
     79   Isolate* isolate_;
     80 #endif
     81 };
     82 
     83 #ifdef ENABLE_DEBUGGER_SUPPORT
     84 
     85 class LiveEdit : AllStatic {
     86  public:
     87   static JSArray* GatherCompileInfo(Handle<Script> script,
     88                                     Handle<String> source);
     89 
     90   static void WrapSharedFunctionInfos(Handle<JSArray> array);
     91 
     92   MUST_USE_RESULT static MaybeObject* ReplaceFunctionCode(
     93       Handle<JSArray> new_compile_info_array,
     94       Handle<JSArray> shared_info_array);
     95 
     96   static MaybeObject* FunctionSourceUpdated(Handle<JSArray> shared_info_array);
     97 
     98   // Updates script field in FunctionSharedInfo.
     99   static void SetFunctionScript(Handle<JSValue> function_wrapper,
    100                                 Handle<Object> script_handle);
    101 
    102   MUST_USE_RESULT static MaybeObject* PatchFunctionPositions(
    103       Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array);
    104 
    105   // For a script updates its source field. If old_script_name is provided
    106   // (i.e. is a String), also creates a copy of the script with its original
    107   // source and sends notification to debugger.
    108   static Object* ChangeScriptSource(Handle<Script> original_script,
    109                                     Handle<String> new_source,
    110                                     Handle<Object> old_script_name);
    111 
    112   // In a code of a parent function replaces original function as embedded
    113   // object with a substitution one.
    114   static void ReplaceRefToNestedFunction(Handle<JSValue> parent_function_shared,
    115                                          Handle<JSValue> orig_function_shared,
    116                                          Handle<JSValue> subst_function_shared);
    117 
    118   // Checks listed functions on stack and return array with corresponding
    119   // FunctionPatchabilityStatus statuses; extra array element may
    120   // contain general error message. Modifies the current stack and
    121   // has restart the lowest found frames and drops all other frames above
    122   // if possible and if do_drop is true.
    123   static Handle<JSArray> CheckAndDropActivations(
    124       Handle<JSArray> shared_info_array, bool do_drop);
    125 
    126   // A copy of this is in liveedit-debugger.js.
    127   enum FunctionPatchabilityStatus {
    128     FUNCTION_AVAILABLE_FOR_PATCH = 1,
    129     FUNCTION_BLOCKED_ON_ACTIVE_STACK = 2,
    130     FUNCTION_BLOCKED_ON_OTHER_STACK = 3,
    131     FUNCTION_BLOCKED_UNDER_NATIVE_CODE = 4,
    132     FUNCTION_REPLACED_ON_ACTIVE_STACK = 5
    133   };
    134 
    135   // Compares 2 strings line-by-line, then token-wise and returns diff in form
    136   // of array of triplets (pos1, pos1_end, pos2_end) describing list
    137   // of diff chunks.
    138   static Handle<JSArray> CompareStrings(Handle<String> s1,
    139                                         Handle<String> s2);
    140 };
    141 
    142 
    143 // A general-purpose comparator between 2 arrays.
    144 class Comparator {
    145  public:
    146   // Holds 2 arrays of some elements allowing to compare any pair of
    147   // element from the first array and element from the second array.
    148   class Input {
    149    public:
    150     virtual int GetLength1() = 0;
    151     virtual int GetLength2() = 0;
    152     virtual bool Equals(int index1, int index2) = 0;
    153 
    154    protected:
    155     virtual ~Input() {}
    156   };
    157 
    158   // Receives compare result as a series of chunks.
    159   class Output {
    160    public:
    161     // Puts another chunk in result list. Note that technically speaking
    162     // only 3 arguments actually needed with 4th being derivable.
    163     virtual void AddChunk(int pos1, int pos2, int len1, int len2) = 0;
    164 
    165    protected:
    166     virtual ~Output() {}
    167   };
    168 
    169   // Finds the difference between 2 arrays of elements.
    170   static void CalculateDifference(Input* input,
    171                                   Output* result_writer);
    172 };
    173 
    174 #endif  // ENABLE_DEBUGGER_SUPPORT
    175 
    176 
    177 } }  // namespace v8::internal
    178 
    179 #endif /* V*_LIVEEDIT_H_ */
    180