Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: src/liveedit.cc

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 21 matching lines...) Expand all
32 #include "compiler.h" 32 #include "compiler.h"
33 #include "oprofile-agent.h" 33 #include "oprofile-agent.h"
34 #include "scopes.h" 34 #include "scopes.h"
35 #include "global-handles.h" 35 #include "global-handles.h"
36 #include "debug.h" 36 #include "debug.h"
37 37
38 namespace v8 { 38 namespace v8 {
39 namespace internal { 39 namespace internal {
40 40
41 41
42 #ifdef ENABLE_DEBUGGER_SUPPORT
43
44 static void CompileScriptForTracker(Handle<Script> script) {
45 const bool is_eval = false;
46 const bool is_global = true;
47 // TODO(635): support extensions.
48 Extension* extension = NULL;
49
50 PostponeInterruptsScope postpone;
51
52 // Only allow non-global compiles for eval.
53 ASSERT(is_eval || is_global);
54
55 // Build AST.
56 ScriptDataImpl* pre_data = NULL;
57 FunctionLiteral* lit = MakeAST(is_global, script, extension, pre_data);
58
59 // Check for parse errors.
60 if (lit == NULL) {
61 ASSERT(Top::has_pending_exception());
62 return;
63 }
64
65 // Compile the code.
66 CompilationInfo info(lit, script, is_eval);
67 Handle<Code> code = MakeCodeForLiveEdit(&info);
68
69 // Check for stack-overflow exceptions.
70 if (code.is_null()) {
71 Top::StackOverflow();
72 return;
73 }
74 }
75
76 // Unwraps JSValue object, returning its field "value"
77 static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
78 return Handle<Object>(jsValue->value());
79 }
80
81 // Wraps any object into a OpaqueReference, that will hide the object
82 // from JavaScript.
83 static Handle<JSValue> WrapInJSValue(Object* object) {
84 Handle<JSFunction> constructor = Top::opaque_reference_function();
85 Handle<JSValue> result =
86 Handle<JSValue>::cast(Factory::NewJSObject(constructor));
87 result->set_value(object);
88 return result;
89 }
90
91 // Simple helper class that creates more or less typed structures over
92 // JSArray object. This is an adhoc method of passing structures from C++
93 // to JavaScript.
94 template<typename S>
95 class JSArrayBasedStruct {
96 public:
97 static S Create() {
98 Handle<JSArray> array = Factory::NewJSArray(S::kSize_);
99 return S(array);
100 }
101 static S cast(Object* object) {
102 JSArray* array = JSArray::cast(object);
103 Handle<JSArray> array_handle(array);
104 return S(array_handle);
105 }
106 explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
107 }
108 Handle<JSArray> GetJSArray() {
109 return array_;
110 }
111 protected:
112 void SetField(int field_position, Handle<Object> value) {
113 SetElement(array_, field_position, value);
114 }
115 void SetSmiValueField(int field_position, int value) {
116 SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
117 }
118 Object* GetField(int field_position) {
119 return array_->GetElement(field_position);
120 }
121 int GetSmiValueField(int field_position) {
122 Object* res = GetField(field_position);
123 return Smi::cast(res)->value();
124 }
125 private:
126 Handle<JSArray> array_;
127 };
128
129
130 // Represents some function compilation details. This structure will be used
131 // from JavaScript. It contains Code object, which is kept wrapped
132 // into a BlindReference for sanitizing reasons.
133 class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
134 public:
135 explicit FunctionInfoWrapper(Handle<JSArray> array)
136 : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
137 }
138 void SetInitialProperties(Handle<String> name, int start_position,
139 int end_position, int param_num, int parent_index) {
140 HandleScope scope;
141 this->SetField(kFunctionNameOffset_, name);
142 this->SetSmiValueField(kStartPositionOffset_, start_position);
143 this->SetSmiValueField(kEndPositionOffset_, end_position);
144 this->SetSmiValueField(kParamNumOffset_, param_num);
145 this->SetSmiValueField(kParentIndexOffset_, parent_index);
146 }
147 void SetFunctionCode(Handle<Code> function_code) {
148 Handle<JSValue> wrapper = WrapInJSValue(*function_code);
149 this->SetField(kCodeOffset_, wrapper);
150 }
151 void SetScopeInfo(Handle<JSArray> scope_info_array) {
152 this->SetField(kScopeInfoOffset_, scope_info_array);
153 }
154 int GetParentIndex() {
155 return this->GetSmiValueField(kParentIndexOffset_);
156 }
157 Handle<Code> GetFunctionCode() {
158 Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
159 JSValue::cast(this->GetField(kCodeOffset_))));
160 return Handle<Code>::cast(raw_result);
161 }
162 int GetStartPosition() {
163 return this->GetSmiValueField(kStartPositionOffset_);
164 }
165 int GetEndPosition() {
166 return this->GetSmiValueField(kEndPositionOffset_);
167 }
168
169 private:
170 static const int kFunctionNameOffset_ = 0;
171 static const int kStartPositionOffset_ = 1;
172 static const int kEndPositionOffset_ = 2;
173 static const int kParamNumOffset_ = 3;
174 static const int kCodeOffset_ = 4;
175 static const int kScopeInfoOffset_ = 5;
176 static const int kParentIndexOffset_ = 6;
177 static const int kSize_ = 7;
178
179 friend class JSArrayBasedStruct<FunctionInfoWrapper>;
180 };
181
182 // Wraps SharedFunctionInfo along with some of its fields for passing it
183 // back to JavaScript. SharedFunctionInfo object itself is additionally
184 // wrapped into BlindReference for sanitizing reasons.
185 class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
186 public:
187 explicit SharedInfoWrapper(Handle<JSArray> array)
188 : JSArrayBasedStruct<SharedInfoWrapper>(array) {
189 }
190
191 void SetProperties(Handle<String> name, int start_position, int end_position,
192 Handle<SharedFunctionInfo> info) {
193 HandleScope scope;
194 this->SetField(kFunctionNameOffset_, name);
195 Handle<JSValue> info_holder = WrapInJSValue(*info);
196 this->SetField(kSharedInfoOffset_, info_holder);
197 this->SetSmiValueField(kStartPositionOffset_, start_position);
198 this->SetSmiValueField(kEndPositionOffset_, end_position);
199 }
200 Handle<SharedFunctionInfo> GetInfo() {
201 Object* element = this->GetField(kSharedInfoOffset_);
202 Handle<JSValue> value_wrapper(JSValue::cast(element));
203 Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
204 return Handle<SharedFunctionInfo>::cast(raw_result);
205 }
206
207 private:
208 static const int kFunctionNameOffset_ = 0;
209 static const int kStartPositionOffset_ = 1;
210 static const int kEndPositionOffset_ = 2;
211 static const int kSharedInfoOffset_ = 3;
212 static const int kSize_ = 4;
213
214 friend class JSArrayBasedStruct<SharedInfoWrapper>;
215 };
216
42 class FunctionInfoListener { 217 class FunctionInfoListener {
43 public: 218 public:
219 FunctionInfoListener() {
220 current_parent_index_ = -1;
221 len_ = 0;
222 result_ = Factory::NewJSArray(10);
223 }
224
44 void FunctionStarted(FunctionLiteral* fun) { 225 void FunctionStarted(FunctionLiteral* fun) {
45 // Implementation follows. 226 HandleScope scope;
227 FunctionInfoWrapper info = FunctionInfoWrapper::Create();
228 info.SetInitialProperties(fun->name(), fun->start_position(),
229 fun->end_position(), fun->num_parameters(),
230 current_parent_index_);
231 current_parent_index_ = len_;
232 SetElement(result_, len_, info.GetJSArray());
233 len_++;
46 } 234 }
47 235
48 void FunctionDone() { 236 void FunctionDone() {
49 // Implementation follows. 237 HandleScope scope;
238 FunctionInfoWrapper info =
239 FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
240 current_parent_index_ = info.GetParentIndex();
50 } 241 }
51 242
52 void FunctionScope(Scope* scope) { 243 void FunctionScope(Scope* scope) {
53 // Implementation follows. 244 HandleScope handle_scope;
245
246 Handle<JSArray> scope_info_list = Factory::NewJSArray(10);
247 int scope_info_length = 0;
248
249 // Saves some description of scope. It stores name and indexes of
250 // variables in the whole scope chain. Null-named slots delimit
251 // scopes of this chain.
252 Scope* outer_scope = scope->outer_scope();
253 if (outer_scope == NULL) {
254 return;
255 }
256 do {
257 ZoneList<Variable*> list(10);
258 outer_scope->CollectUsedVariables(&list);
259 int j = 0;
260 for (int i = 0; i < list.length(); i++) {
261 Variable* var1 = list[i];
262 Slot* slot = var1->slot();
263 if (slot != NULL && slot->type() == Slot::CONTEXT) {
264 if (j != i) {
265 list[j] = var1;
266 }
267 j++;
268 }
269 }
270
271 // Sort it.
272 for (int k = 1; k < j; k++) {
273 int l = k;
274 for (int m = k + 1; m < j; m++) {
275 if (list[l]->slot()->index() > list[m]->slot()->index()) {
276 l = m;
277 }
278 }
279 list[k] = list[l];
280 }
281 for (int i = 0; i < j; i++) {
282 SetElement(scope_info_list, scope_info_length, list[i]->name());
283 scope_info_length++;
284 SetElement(scope_info_list, scope_info_length,
285 Handle<Smi>(Smi::FromInt(list[i]->slot()->index())));
286 scope_info_length++;
287 }
288 SetElement(scope_info_list, scope_info_length,
289 Handle<Object>(Heap::null_value()));
290 scope_info_length++;
291
292 outer_scope = outer_scope->outer_scope();
293 } while (outer_scope != NULL);
294
295 FunctionInfoWrapper info =
296 FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
297 info.SetScopeInfo(scope_info_list);
54 } 298 }
55 299
56 void FunctionCode(Handle<Code> function_code) { 300 void FunctionCode(Handle<Code> function_code) {
57 // Implementation follows. 301 FunctionInfoWrapper info =
58 } 302 FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_));
303 info.SetFunctionCode(function_code);
304 }
305
306 Handle<JSArray> GetResult() {
307 return result_;
308 }
309
310 private:
311 Handle<JSArray> result_;
312 int len_;
313 int current_parent_index_;
59 }; 314 };
60 315
61 static FunctionInfoListener* active_function_info_listener = NULL; 316 static FunctionInfoListener* active_function_info_listener = NULL;
62 317
318 JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,
319 Handle<String> source) {
320 CompilationZoneScope zone_scope(DELETE_ON_EXIT);
321
322 FunctionInfoListener listener;
323 Handle<Object> original_source = Handle<Object>(script->source());
324 script->set_source(*source);
325 active_function_info_listener = &listener;
326 CompileScriptForTracker(script);
327 active_function_info_listener = NULL;
328 script->set_source(*original_source);
329
330 return *(listener.GetResult());
331 }
332
333
334 void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
335 HandleScope scope;
336 int len = Smi::cast(array->length())->value();
337 for (int i = 0; i < len; i++) {
338 Handle<SharedFunctionInfo> info(
339 SharedFunctionInfo::cast(array->GetElement(i)));
340 SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
341 Handle<String> name_handle(String::cast(info->name()));
342 info_wrapper.SetProperties(name_handle, info->start_position(),
343 info->end_position(), info);
344 array->SetElement(i, *(info_wrapper.GetJSArray()));
345 }
346 }
347
348
349 void LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array,
350 Handle<JSArray> shared_info_array) {
351 HandleScope scope;
352
353 FunctionInfoWrapper compile_info_wrapper(new_compile_info_array);
354 SharedInfoWrapper shared_info_wrapper(shared_info_array);
355
356 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
357
358 shared_info->set_code(*(compile_info_wrapper.GetFunctionCode()),
359 UPDATE_WRITE_BARRIER);
360 shared_info->set_start_position(compile_info_wrapper.GetStartPosition());
361 shared_info->set_end_position(compile_info_wrapper.GetEndPosition());
362 // update breakpoints, original code, constructor stub
363 }
364
365
366 void LiveEdit::RelinkFunctionToScript(Handle<JSArray> shared_info_array,
367 Handle<Script> script_handle) {
368 SharedInfoWrapper shared_info_wrapper(shared_info_array);
369 Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
370
371 shared_info->set_script(*script_handle);
372 }
373
374
375 // For a script text change (defined as position_change_array), translates
376 // position in unchanged text to position in changed text.
377 // Text change is a set of non-overlapping regions in text, that have changed
378 // their contents and length. It is specified as array of groups of 3 numbers:
379 // (change_begin, change_end, change_end_new_position).
380 // Each group describes a change in text; groups are sorted by change_begin.
381 // Only position in text beyond any changes may be successfully translated.
382 // If a positions is inside some region that changed, result is currently
383 // undefined.
384 static int TranslatePosition(int original_position,
385 Handle<JSArray> position_change_array) {
386 int position_diff = 0;
387 int array_len = Smi::cast(position_change_array->length())->value();
388 // TODO(635): binary search may be used here
389 for (int i = 0; i < array_len; i += 3) {
390 int chunk_start =
391 Smi::cast(position_change_array->GetElement(i))->value();
392 int chunk_end =
393 Smi::cast(position_change_array->GetElement(i + 1))->value();
394 int chunk_changed_end =
395 Smi::cast(position_change_array->GetElement(i + 2))->value();
396 position_diff = chunk_changed_end - chunk_end;
397 if (original_position < chunk_start) {
398 break;
399 }
400 // Position mustn't be inside a chunk.
401 ASSERT(original_position >= chunk_end);
402 }
403
404 return original_position + position_diff;
405 }
406
407
408 void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array,
409 Handle<JSArray> position_change_array) {
410 SharedInfoWrapper shared_info_wrapper(shared_info_array);
411 Handle<SharedFunctionInfo> info = shared_info_wrapper.GetInfo();
412
413 info->set_start_position(TranslatePosition(info->start_position(),
414 position_change_array));
415 info->set_end_position(TranslatePosition(info->end_position(),
416 position_change_array));
417
418 // Also patch rinfos (both in working code and original code), breakpoints.
419 }
420
421
63 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) { 422 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
64 if (active_function_info_listener != NULL) { 423 if (active_function_info_listener != NULL) {
65 active_function_info_listener->FunctionStarted(fun); 424 active_function_info_listener->FunctionStarted(fun);
66 } 425 }
67 } 426 }
427
428
68 LiveEditFunctionTracker::~LiveEditFunctionTracker() { 429 LiveEditFunctionTracker::~LiveEditFunctionTracker() {
69 if (active_function_info_listener != NULL) { 430 if (active_function_info_listener != NULL) {
70 active_function_info_listener->FunctionDone(); 431 active_function_info_listener->FunctionDone();
71 } 432 }
72 } 433 }
434
435
73 void LiveEditFunctionTracker::RecordFunctionCode(Handle<Code> code) { 436 void LiveEditFunctionTracker::RecordFunctionCode(Handle<Code> code) {
74 if (active_function_info_listener != NULL) { 437 if (active_function_info_listener != NULL) {
75 active_function_info_listener->FunctionCode(code); 438 active_function_info_listener->FunctionCode(code);
76 } 439 }
77 } 440 }
441
442
78 void LiveEditFunctionTracker::RecordFunctionScope(Scope* scope) { 443 void LiveEditFunctionTracker::RecordFunctionScope(Scope* scope) {
79 if (active_function_info_listener != NULL) { 444 if (active_function_info_listener != NULL) {
80 active_function_info_listener->FunctionScope(scope); 445 active_function_info_listener->FunctionScope(scope);
81 } 446 }
82 } 447 }
448
449
83 bool LiveEditFunctionTracker::IsActive() { 450 bool LiveEditFunctionTracker::IsActive() {
84 return active_function_info_listener != NULL; 451 return active_function_info_listener != NULL;
85 } 452 }
86 453
454
455 #else // ENABLE_DEBUGGER_SUPPORT
456
457 // This ifdef-else-endif section provides working or stub implementation of
458 // LiveEditFunctionTracker.
459 LiveEditFunctionTracker::LiveEditFunctionTracker(FunctionLiteral* fun) {
460 }
461
462
463 LiveEditFunctionTracker::~LiveEditFunctionTracker() {
464 }
465
466
467 void LiveEditFunctionTracker::RecordFunctionCode(Handle<Code> code) {
468 }
469
470
471 void LiveEditFunctionTracker::RecordFunctionScope(Scope* scope) {
472 }
473
474
475 bool LiveEditFunctionTracker::IsActive() {
476 return false;
477 }
478
479 #endif // ENABLE_DEBUGGER_SUPPORT
480
481
482
87 } } // namespace v8::internal 483 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/liveedit.h ('k') | src/liveedit-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698