Index: src/liveedit.cc |
diff --git a/src/liveedit.cc b/src/liveedit.cc |
index 2a3aafc1f1daa355d817f3d0031315844a4d748f..cc5c28dd667f1a952510d9a20ed969c013c16190 100644 |
--- a/src/liveedit.cc |
+++ b/src/liveedit.cc |
@@ -703,12 +703,14 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> { |
: JSArrayBasedStruct<FunctionInfoWrapper>(array) { |
} |
void SetInitialProperties(Handle<String> name, int start_position, |
- int end_position, int param_num, int parent_index) { |
+ int end_position, int param_num, |
+ int literal_count, int parent_index) { |
HandleScope scope; |
this->SetField(kFunctionNameOffset_, name); |
this->SetSmiValueField(kStartPositionOffset_, start_position); |
this->SetSmiValueField(kEndPositionOffset_, end_position); |
this->SetSmiValueField(kParamNumOffset_, param_num); |
+ this->SetSmiValueField(kLiteralNumOffset_, literal_count); |
this->SetSmiValueField(kParentIndexOffset_, parent_index); |
} |
void SetFunctionCode(Handle<Code> function_code, |
@@ -726,6 +728,9 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> { |
Handle<JSValue> info_holder = WrapInJSValue(info); |
this->SetField(kSharedFunctionInfoOffset_, info_holder); |
} |
+ int GetLiteralCount() { |
+ return this->GetSmiValueField(kLiteralNumOffset_); |
+ } |
int GetParentIndex() { |
return this->GetSmiValueField(kParentIndexOffset_); |
} |
@@ -759,7 +764,8 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> { |
static const int kOuterScopeInfoOffset_ = 6; |
static const int kParentIndexOffset_ = 7; |
static const int kSharedFunctionInfoOffset_ = 8; |
- static const int kSize_ = 9; |
+ static const int kLiteralNumOffset_ = 9; |
+ static const int kSize_ = 10; |
friend class JSArrayBasedStruct<FunctionInfoWrapper>; |
}; |
@@ -819,6 +825,7 @@ class FunctionInfoListener { |
FunctionInfoWrapper info = FunctionInfoWrapper::Create(); |
info.SetInitialProperties(fun->name(), fun->start_position(), |
fun->end_position(), fun->parameter_count(), |
+ fun->materialized_literal_count(), |
current_parent_index_); |
current_parent_index_ = len_; |
SetElementNonStrict(result_, len_, info.GetJSArray()); |
@@ -1014,6 +1021,44 @@ static void ReplaceCodeObject(Handle<Code> original, |
} |
+// Finds all instances of JSFunction that refers to the provided shared_info. |
+// Return their number and optionally writes them into output array. |
+static int FindJSFunctions(Handle<SharedFunctionInfo> shared_info, |
+ Handle<FixedArray> output) { |
+ int pos = 0; |
+ |
+ AssertNoAllocation no_allocations_please; |
+ |
+ SharedFunctionInfo* shared_info_raw = *shared_info; |
+ HeapIterator iterator; |
+ for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
+ if (obj->IsJSFunction()) { |
+ JSFunction* function = JSFunction::cast(obj); |
+ if (function->shared() == shared_info_raw) { |
+ if (!output.is_null()) { |
+ output->set(pos, function); |
+ } |
+ pos++; |
+ } |
+ } |
+ } |
+ return pos; |
+} |
+ |
+ |
+// Finds all instances of JSFunction that refers to the provided shared_info |
+// and returns array with them. |
+static Handle<FixedArray> CollectJSFunctions( |
+ Handle<SharedFunctionInfo> shared_info, Isolate* isolate) { |
+ int size = FindJSFunctions(shared_info, Handle<FixedArray>::null()); |
+ Handle<FixedArray> result = isolate->factory()->NewFixedArray(size); |
+ if (size > 0) { |
+ FindJSFunctions(shared_info, result); |
Yang
2012/10/23 16:10:31
Running twice over the heap seems really inefficie
Peter Rybin
2012/11/11 03:28:47
In fact I only copy how Runtime_DebugReferencedBy
|
+ } |
+ return result; |
+} |
+ |
+ |
// Check whether the code is natural function code (not a lazy-compile stub |
// code). |
static bool IsJSFunctionCode(Code* code) { |
@@ -1080,9 +1125,10 @@ MaybeObject* LiveEdit::ReplaceFunctionCode( |
Handle<JSArray> new_compile_info_array, |
Handle<JSArray> shared_info_array) { |
HandleScope scope; |
+ Isolate* isolate = Isolate::Current(); |
if (!SharedInfoWrapper::IsInstance(shared_info_array)) { |
- return Isolate::Current()->ThrowIllegalOperation(); |
+ return isolate->ThrowIllegalOperation(); |
} |
FunctionInfoWrapper compile_info_wrapper(new_compile_info_array); |
@@ -1113,6 +1159,48 @@ MaybeObject* LiveEdit::ReplaceFunctionCode( |
shared_info->set_start_position(start_position); |
shared_info->set_end_position(end_position); |
+ // Patch function literals. |
+ // TODO(prybin): is the following legit? |
+ // Name 'literals' is a misnomer. Rather it's a cache for complex object |
+ // boilerplates and for a native context. We must clean cached values or |
+ // adjust array size. |
Yang
2012/10/23 16:10:31
Wouldn't adjusting array size imply cleaning cache
Peter Rybin
2012/11/11 03:28:47
Done.
|
+ { |
+ int new_literal_count = compile_info_wrapper.GetLiteralCount(); |
+ if (new_literal_count > 0) { |
+ new_literal_count += JSFunction::kLiteralsPrefixSize; |
+ } |
+ shared_info->set_num_literals(new_literal_count); |
+ |
+ Handle<FixedArray> function_instances = |
+ CollectJSFunctions(shared_info, isolate); |
+ for (int i = 0; i < function_instances->length(); i++) { |
Yang
2012/10/23 16:10:31
Instead of looping over function instances that yo
Peter Rybin
2012/11/11 03:28:47
I have to update literal array, and possibly creat
|
+ Handle<JSFunction> fun(JSFunction::cast(function_instances->get(i))); |
+ Handle<FixedArray> old_literals(fun->literals()); |
+ if (old_literals->length() == new_literal_count) { |
+ for (int j = JSFunction::kLiteralsPrefixSize; |
+ j < new_literal_count; j++) { |
+ old_literals->set(j, isolate->heap()->undefined_value()); |
Yang
2012/10/23 16:10:31
I guess you could use FixedArray->set_undefined he
Peter Rybin
2012/11/11 03:28:47
Done.
|
+ } |
+ } else { |
+ Handle<FixedArray> new_literals = |
+ isolate->factory()->NewFixedArray(new_literal_count); |
+ if (new_literal_count > 0) { |
+ Handle<Context> native_context; |
+ if (old_literals->length() > |
+ JSFunction::kLiteralNativeContextIndex) { |
+ native_context = Handle<Context>( |
+ JSFunction::NativeContextFromLiterals(fun->literals())); |
+ } else { |
+ native_context = Handle<Context>(fun->context()->native_context()); |
+ } |
+ new_literals->set(JSFunction::kLiteralNativeContextIndex, |
+ *native_context); |
+ } |
+ fun->set_literals(*new_literals); |
+ } |
Yang
2012/10/23 16:10:31
I assume that we are not dealing with optimized co
Peter Rybin
2012/11/11 03:28:47
May be it more safe to always create an accurate l
|
+ } |
+ } |
+ |
shared_info->set_construct_stub( |
Isolate::Current()->builtins()->builtin( |
Builtins::kJSConstructStubGeneric)); |