Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / liveedit.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_LIVEEDIT_H_
6 #define V8_LIVEEDIT_H_
7
8
9
10 // Live Edit feature implementation.
11 // User should be able to change script on already running VM. This feature
12 // matches hot swap features in other frameworks.
13 //
14 // The basic use-case is when user spots some mistake in function body
15 // from debugger and wishes to change the algorithm without restart.
16 //
17 // A single change always has a form of a simple replacement (in pseudo-code):
18 //   script.source[positions, positions+length] = new_string;
19 // Implementation first determines, which function's body includes this
20 // change area. Then both old and new versions of script are fully compiled
21 // in order to analyze, whether the function changed its outer scope
22 // expectations (or number of parameters). If it didn't, function's code is
23 // patched with a newly compiled code. If it did change, enclosing function
24 // gets patched. All inner functions are left untouched, whatever happened
25 // to them in a new script version. However, new version of code will
26 // instantiate newly compiled functions.
27
28
29 #include "src/allocation.h"
30 #include "src/compiler.h"
31
32 namespace v8 {
33 namespace internal {
34
35 // This class collects some specific information on structure of functions
36 // in a particular script. It gets called from compiler all the time, but
37 // actually records any data only when liveedit operation is in process;
38 // in any other time this class is very cheap.
39 //
40 // The primary interest of the Tracker is to record function scope structures
41 // in order to analyze whether function code maybe safely patched (with new
42 // code successfully reading existing data from function scopes). The Tracker
43 // also collects compiled function codes.
44 class LiveEditFunctionTracker {
45  public:
46   explicit LiveEditFunctionTracker(Isolate* isolate, FunctionLiteral* fun);
47   ~LiveEditFunctionTracker();
48   void RecordFunctionInfo(Handle<SharedFunctionInfo> info,
49                           FunctionLiteral* lit, Zone* zone);
50   void RecordRootFunctionInfo(Handle<Code> code);
51
52   static bool IsActive(Isolate* isolate);
53
54  private:
55   Isolate* isolate_;
56 };
57
58
59 class LiveEdit : AllStatic {
60  public:
61   // Describes how exactly a frame has been dropped from stack.
62   enum FrameDropMode {
63     // No frame has been dropped.
64     FRAMES_UNTOUCHED,
65     // The top JS frame had been calling IC stub. IC stub mustn't be called now.
66     FRAME_DROPPED_IN_IC_CALL,
67     // The top JS frame had been calling debug break slot stub. Patch the
68     // address this stub jumps to in the end.
69     FRAME_DROPPED_IN_DEBUG_SLOT_CALL,
70     // The top JS frame had been calling some C++ function. The return address
71     // gets patched automatically.
72     FRAME_DROPPED_IN_DIRECT_CALL,
73     FRAME_DROPPED_IN_RETURN_CALL,
74     CURRENTLY_SET_MODE
75   };
76
77   static void InitializeThreadLocal(Debug* debug);
78
79   static bool SetAfterBreakTarget(Debug* debug);
80
81   MUST_USE_RESULT static MaybeHandle<JSArray> GatherCompileInfo(
82       Handle<Script> script,
83       Handle<String> source);
84
85   static void WrapSharedFunctionInfos(Handle<JSArray> array);
86
87   static void ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
88                                   Handle<JSArray> shared_info_array);
89
90   static void FunctionSourceUpdated(Handle<JSArray> shared_info_array);
91
92   // Updates script field in FunctionSharedInfo.
93   static void SetFunctionScript(Handle<JSValue> function_wrapper,
94                                 Handle<Object> script_handle);
95
96   static void PatchFunctionPositions(Handle<JSArray> shared_info_array,
97                                      Handle<JSArray> position_change_array);
98
99   // For a script updates its source field. If old_script_name is provided
100   // (i.e. is a String), also creates a copy of the script with its original
101   // source and sends notification to debugger.
102   static Handle<Object> ChangeScriptSource(Handle<Script> original_script,
103                                            Handle<String> new_source,
104                                            Handle<Object> old_script_name);
105
106   // In a code of a parent function replaces original function as embedded
107   // object with a substitution one.
108   static void ReplaceRefToNestedFunction(Handle<JSValue> parent_function_shared,
109                                          Handle<JSValue> orig_function_shared,
110                                          Handle<JSValue> subst_function_shared);
111
112   // Find open generator activations, and set corresponding "result" elements to
113   // FUNCTION_BLOCKED_ACTIVE_GENERATOR.
114   static bool FindActiveGenerators(Handle<FixedArray> shared_info_array,
115                                    Handle<FixedArray> result, int len);
116
117   // Checks listed functions on stack and return array with corresponding
118   // FunctionPatchabilityStatus statuses; extra array element may
119   // contain general error message. Modifies the current stack and
120   // has restart the lowest found frames and drops all other frames above
121   // if possible and if do_drop is true.
122   static Handle<JSArray> CheckAndDropActivations(
123       Handle<JSArray> shared_info_array, bool do_drop);
124
125   // Restarts the call frame and completely drops all frames above it.
126   // Return error message or NULL.
127   static const char* RestartFrame(JavaScriptFrame* frame);
128
129   // A copy of this is in liveedit-debugger.js.
130   enum FunctionPatchabilityStatus {
131     FUNCTION_AVAILABLE_FOR_PATCH = 1,
132     FUNCTION_BLOCKED_ON_ACTIVE_STACK = 2,
133     FUNCTION_BLOCKED_ON_OTHER_STACK = 3,
134     FUNCTION_BLOCKED_UNDER_NATIVE_CODE = 4,
135     FUNCTION_REPLACED_ON_ACTIVE_STACK = 5,
136     FUNCTION_BLOCKED_UNDER_GENERATOR = 6,
137     FUNCTION_BLOCKED_ACTIVE_GENERATOR = 7
138   };
139
140   // Compares 2 strings line-by-line, then token-wise and returns diff in form
141   // of array of triplets (pos1, pos1_end, pos2_end) describing list
142   // of diff chunks.
143   static Handle<JSArray> CompareStrings(Handle<String> s1,
144                                         Handle<String> s2);
145
146   // Architecture-specific constant.
147   static const bool kFrameDropperSupported;
148
149   /**
150    * Defines layout of a stack frame that supports padding. This is a regular
151    * internal frame that has a flexible stack structure. LiveEdit can shift
152    * its lower part up the stack, taking up the 'padding' space when additional
153    * stack memory is required.
154    * Such frame is expected immediately above the topmost JavaScript frame.
155    *
156    * Stack Layout:
157    *   --- Top
158    *   LiveEdit routine frames
159    *   ---
160    *   C frames of debug handler
161    *   ---
162    *   ...
163    *   ---
164    *      An internal frame that has n padding words:
165    *      - any number of words as needed by code -- upper part of frame
166    *      - padding size: a Smi storing n -- current size of padding
167    *      - padding: n words filled with kPaddingValue in form of Smi
168    *      - 3 context/type words of a regular InternalFrame
169    *      - fp
170    *   ---
171    *      Topmost JavaScript frame
172    *   ---
173    *   ...
174    *   --- Bottom
175    */
176   // A size of frame base including fp. Padding words starts right above
177   // the base.
178   static const int kFrameDropperFrameSize = 4;
179   // A number of words that should be reserved on stack for the LiveEdit use.
180   // Stored on stack in form of Smi.
181   static const int kFramePaddingInitialSize = 1;
182   // A value that padding words are filled with (in form of Smi). Going
183   // bottom-top, the first word not having this value is a counter word.
184   static const int kFramePaddingValue = kFramePaddingInitialSize + 1;
185 };
186
187
188 // A general-purpose comparator between 2 arrays.
189 class Comparator {
190  public:
191   // Holds 2 arrays of some elements allowing to compare any pair of
192   // element from the first array and element from the second array.
193   class Input {
194    public:
195     virtual int GetLength1() = 0;
196     virtual int GetLength2() = 0;
197     virtual bool Equals(int index1, int index2) = 0;
198
199    protected:
200     virtual ~Input() {}
201   };
202
203   // Receives compare result as a series of chunks.
204   class Output {
205    public:
206     // Puts another chunk in result list. Note that technically speaking
207     // only 3 arguments actually needed with 4th being derivable.
208     virtual void AddChunk(int pos1, int pos2, int len1, int len2) = 0;
209
210    protected:
211     virtual ~Output() {}
212   };
213
214   // Finds the difference between 2 arrays of elements.
215   static void CalculateDifference(Input* input,
216                                   Output* result_writer);
217 };
218
219
220
221 // Simple helper class that creates more or less typed structures over
222 // JSArray object. This is an adhoc method of passing structures from C++
223 // to JavaScript.
224 template<typename S>
225 class JSArrayBasedStruct {
226  public:
227   static S Create(Isolate* isolate) {
228     Factory* factory = isolate->factory();
229     Handle<JSArray> array = factory->NewJSArray(S::kSize_);
230     return S(array);
231   }
232
233   static S cast(Object* object) {
234     JSArray* array = JSArray::cast(object);
235     Handle<JSArray> array_handle(array);
236     return S(array_handle);
237   }
238
239   explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
240   }
241
242   Handle<JSArray> GetJSArray() {
243     return array_;
244   }
245
246   Isolate* isolate() const {
247     return array_->GetIsolate();
248   }
249
250  protected:
251   void SetField(int field_position, Handle<Object> value) {
252     JSObject::SetElement(array_, field_position, value, NONE, SLOPPY).Assert();
253   }
254
255   void SetSmiValueField(int field_position, int value) {
256     SetField(field_position, Handle<Smi>(Smi::FromInt(value), isolate()));
257   }
258
259   Handle<Object> GetField(int field_position) {
260     return Object::GetElement(
261         isolate(), array_, field_position).ToHandleChecked();
262   }
263
264   int GetSmiValueField(int field_position) {
265     Handle<Object> res = GetField(field_position);
266     return Handle<Smi>::cast(res)->value();
267   }
268
269  private:
270   Handle<JSArray> array_;
271 };
272
273
274 // Represents some function compilation details. This structure will be used
275 // from JavaScript. It contains Code object, which is kept wrapped
276 // into a BlindReference for sanitizing reasons.
277 class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
278  public:
279   explicit FunctionInfoWrapper(Handle<JSArray> array)
280       : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
281   }
282
283   void SetInitialProperties(Handle<String> name, int start_position,
284                             int end_position, int param_num, int literal_count,
285                             int slot_count, int ic_slot_count,
286                             int parent_index);
287
288   void SetFunctionCode(Handle<Code> function_code,
289                        Handle<HeapObject> code_scope_info);
290
291   void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
292     this->SetField(kFunctionScopeInfoOffset_, scope_info_array);
293   }
294
295   void SetSharedFunctionInfo(Handle<SharedFunctionInfo> info);
296
297   int GetLiteralCount() {
298     return this->GetSmiValueField(kLiteralNumOffset_);
299   }
300
301   int GetParentIndex() {
302     return this->GetSmiValueField(kParentIndexOffset_);
303   }
304
305   Handle<Code> GetFunctionCode();
306
307   Handle<TypeFeedbackVector> GetFeedbackVector();
308
309   Handle<Object> GetCodeScopeInfo();
310
311   int GetStartPosition() {
312     return this->GetSmiValueField(kStartPositionOffset_);
313   }
314
315   int GetEndPosition() { return this->GetSmiValueField(kEndPositionOffset_); }
316
317   int GetSlotCount() {
318     return this->GetSmiValueField(kSlotNumOffset_);
319   }
320
321   int GetICSlotCount() { return this->GetSmiValueField(kICSlotNumOffset_); }
322
323  private:
324   static const int kFunctionNameOffset_ = 0;
325   static const int kStartPositionOffset_ = 1;
326   static const int kEndPositionOffset_ = 2;
327   static const int kParamNumOffset_ = 3;
328   static const int kCodeOffset_ = 4;
329   static const int kCodeScopeInfoOffset_ = 5;
330   static const int kFunctionScopeInfoOffset_ = 6;
331   static const int kParentIndexOffset_ = 7;
332   static const int kSharedFunctionInfoOffset_ = 8;
333   static const int kLiteralNumOffset_ = 9;
334   static const int kSlotNumOffset_ = 10;
335   static const int kICSlotNumOffset_ = 11;
336   static const int kSize_ = 12;
337
338   friend class JSArrayBasedStruct<FunctionInfoWrapper>;
339 };
340
341
342 // Wraps SharedFunctionInfo along with some of its fields for passing it
343 // back to JavaScript. SharedFunctionInfo object itself is additionally
344 // wrapped into BlindReference for sanitizing reasons.
345 class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
346  public:
347   static bool IsInstance(Handle<JSArray> array) {
348     if (array->length() != Smi::FromInt(kSize_)) return false;
349     Handle<Object> element(
350         Object::GetElement(array->GetIsolate(),
351                            array,
352                            kSharedInfoOffset_).ToHandleChecked());
353     if (!element->IsJSValue()) return false;
354     return Handle<JSValue>::cast(element)->value()->IsSharedFunctionInfo();
355   }
356
357   explicit SharedInfoWrapper(Handle<JSArray> array)
358       : JSArrayBasedStruct<SharedInfoWrapper>(array) {
359   }
360
361   void SetProperties(Handle<String> name,
362                      int start_position,
363                      int end_position,
364                      Handle<SharedFunctionInfo> info);
365
366   Handle<SharedFunctionInfo> GetInfo();
367
368  private:
369   static const int kFunctionNameOffset_ = 0;
370   static const int kStartPositionOffset_ = 1;
371   static const int kEndPositionOffset_ = 2;
372   static const int kSharedInfoOffset_ = 3;
373   static const int kSize_ = 4;
374
375   friend class JSArrayBasedStruct<SharedInfoWrapper>;
376 };
377
378 } }  // namespace v8::internal
379
380 #endif /* V*_LIVEEDIT_H_ */