OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 #include "src/v8.h" | 6 #include "src/v8.h" |
7 | 7 |
8 #include "src/liveedit.h" | 8 #include "src/liveedit.h" |
9 | 9 |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 return (len2_ - pos2) << kDirectionSizeBits; | 154 return (len2_ - pos2) << kDirectionSizeBits; |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 inline int& get_cell(int i1, int i2) { | 158 inline int& get_cell(int i1, int i2) { |
159 return buffer_[i1 + i2 * len1_]; | 159 return buffer_[i1 + i2 * len1_]; |
160 } | 160 } |
161 | 161 |
162 // Each cell keeps a value plus direction. Value is multiplied by 4. | 162 // Each cell keeps a value plus direction. Value is multiplied by 4. |
163 void set_value4_and_dir(int i1, int i2, int value4, Direction dir) { | 163 void set_value4_and_dir(int i1, int i2, int value4, Direction dir) { |
164 ASSERT((value4 & kDirectionMask) == 0); | 164 DCHECK((value4 & kDirectionMask) == 0); |
165 get_cell(i1, i2) = value4 | dir; | 165 get_cell(i1, i2) = value4 | dir; |
166 } | 166 } |
167 | 167 |
168 int get_value4(int i1, int i2) { | 168 int get_value4(int i1, int i2) { |
169 return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask); | 169 return get_cell(i1, i2) & (kMaxUInt32 ^ kDirectionMask); |
170 } | 170 } |
171 Direction get_direction(int i1, int i2) { | 171 Direction get_direction(int i1, int i2) { |
172 return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask); | 172 return static_cast<Direction>(get_cell(i1, i2) & kDirectionMask); |
173 } | 173 } |
174 | 174 |
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 static void ReplaceCodeObject(Handle<Code> original, | 969 static void ReplaceCodeObject(Handle<Code> original, |
970 Handle<Code> substitution) { | 970 Handle<Code> substitution) { |
971 // Perform a full GC in order to ensure that we are not in the middle of an | 971 // Perform a full GC in order to ensure that we are not in the middle of an |
972 // incremental marking phase when we are replacing the code object. | 972 // incremental marking phase when we are replacing the code object. |
973 // Since we are not in an incremental marking phase we can write pointers | 973 // Since we are not in an incremental marking phase we can write pointers |
974 // to code objects (that are never in new space) without worrying about | 974 // to code objects (that are never in new space) without worrying about |
975 // write barriers. | 975 // write barriers. |
976 Heap* heap = original->GetHeap(); | 976 Heap* heap = original->GetHeap(); |
977 HeapIterator iterator(heap); | 977 HeapIterator iterator(heap); |
978 | 978 |
979 ASSERT(!heap->InNewSpace(*substitution)); | 979 DCHECK(!heap->InNewSpace(*substitution)); |
980 | 980 |
981 ReplacingVisitor visitor(*original, *substitution); | 981 ReplacingVisitor visitor(*original, *substitution); |
982 | 982 |
983 // Iterate over all roots. Stack frames may have pointer into original code, | 983 // Iterate over all roots. Stack frames may have pointer into original code, |
984 // so temporary replace the pointers with offset numbers | 984 // so temporary replace the pointers with offset numbers |
985 // in prologue/epilogue. | 985 // in prologue/epilogue. |
986 heap->IterateRoots(&visitor, VISIT_ALL); | 986 heap->IterateRoots(&visitor, VISIT_ALL); |
987 | 987 |
988 // Now iterate over all pointers of all objects, including code_target | 988 // Now iterate over all pointers of all objects, including code_target |
989 // implicit pointers. | 989 // implicit pointers. |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1153 SharedFunctionInfo* shared_info_; | 1153 SharedFunctionInfo* shared_info_; |
1154 bool found_; | 1154 bool found_; |
1155 | 1155 |
1156 explicit DependentFunctionMarker(SharedFunctionInfo* shared_info) | 1156 explicit DependentFunctionMarker(SharedFunctionInfo* shared_info) |
1157 : shared_info_(shared_info), found_(false) { } | 1157 : shared_info_(shared_info), found_(false) { } |
1158 | 1158 |
1159 virtual void EnterContext(Context* context) { } // Don't care. | 1159 virtual void EnterContext(Context* context) { } // Don't care. |
1160 virtual void LeaveContext(Context* context) { } // Don't care. | 1160 virtual void LeaveContext(Context* context) { } // Don't care. |
1161 virtual void VisitFunction(JSFunction* function) { | 1161 virtual void VisitFunction(JSFunction* function) { |
1162 // It should be guaranteed by the iterator that everything is optimized. | 1162 // It should be guaranteed by the iterator that everything is optimized. |
1163 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | 1163 DCHECK(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
1164 if (shared_info_ == function->shared() || | 1164 if (shared_info_ == function->shared() || |
1165 IsInlined(function, shared_info_)) { | 1165 IsInlined(function, shared_info_)) { |
1166 // Mark the code for deoptimization. | 1166 // Mark the code for deoptimization. |
1167 function->code()->set_marked_for_deoptimization(true); | 1167 function->code()->set_marked_for_deoptimization(true); |
1168 found_ = true; | 1168 found_ = true; |
1169 } | 1169 } |
1170 } | 1170 } |
1171 }; | 1171 }; |
1172 | 1172 |
1173 | 1173 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 CHECK(element->IsSmi()); | 1272 CHECK(element->IsSmi()); |
1273 int chunk_start = Handle<Smi>::cast(element)->value(); | 1273 int chunk_start = Handle<Smi>::cast(element)->value(); |
1274 if (original_position < chunk_start) { | 1274 if (original_position < chunk_start) { |
1275 break; | 1275 break; |
1276 } | 1276 } |
1277 element = Object::GetElement( | 1277 element = Object::GetElement( |
1278 isolate, position_change_array, i + 1).ToHandleChecked(); | 1278 isolate, position_change_array, i + 1).ToHandleChecked(); |
1279 CHECK(element->IsSmi()); | 1279 CHECK(element->IsSmi()); |
1280 int chunk_end = Handle<Smi>::cast(element)->value(); | 1280 int chunk_end = Handle<Smi>::cast(element)->value(); |
1281 // Position mustn't be inside a chunk. | 1281 // Position mustn't be inside a chunk. |
1282 ASSERT(original_position >= chunk_end); | 1282 DCHECK(original_position >= chunk_end); |
1283 element = Object::GetElement( | 1283 element = Object::GetElement( |
1284 isolate, position_change_array, i + 2).ToHandleChecked(); | 1284 isolate, position_change_array, i + 2).ToHandleChecked(); |
1285 CHECK(element->IsSmi()); | 1285 CHECK(element->IsSmi()); |
1286 int chunk_changed_end = Handle<Smi>::cast(element)->value(); | 1286 int chunk_changed_end = Handle<Smi>::cast(element)->value(); |
1287 position_diff = chunk_changed_end - chunk_end; | 1287 position_diff = chunk_changed_end - chunk_end; |
1288 } | 1288 } |
1289 | 1289 |
1290 return original_position + position_diff; | 1290 return original_position + position_diff; |
1291 } | 1291 } |
1292 | 1292 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1572 // the value that is called 'restarter_frame_function_pointer'. The value | 1572 // the value that is called 'restarter_frame_function_pointer'. The value |
1573 // at this address (possibly updated by GC) may be used later when preparing | 1573 // at this address (possibly updated by GC) may be used later when preparing |
1574 // 'step in' operation. | 1574 // 'step in' operation. |
1575 // Frame structure (conforms InternalFrame structure): | 1575 // Frame structure (conforms InternalFrame structure): |
1576 // -- code | 1576 // -- code |
1577 // -- SMI maker | 1577 // -- SMI maker |
1578 // -- function (slot is called "context") | 1578 // -- function (slot is called "context") |
1579 // -- frame base | 1579 // -- frame base |
1580 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, | 1580 static Object** SetUpFrameDropperFrame(StackFrame* bottom_js_frame, |
1581 Handle<Code> code) { | 1581 Handle<Code> code) { |
1582 ASSERT(bottom_js_frame->is_java_script()); | 1582 DCHECK(bottom_js_frame->is_java_script()); |
1583 | 1583 |
1584 Address fp = bottom_js_frame->fp(); | 1584 Address fp = bottom_js_frame->fp(); |
1585 | 1585 |
1586 // Move function pointer into "context" slot. | 1586 // Move function pointer into "context" slot. |
1587 Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = | 1587 Memory::Object_at(fp + StandardFrameConstants::kContextOffset) = |
1588 Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); | 1588 Memory::Object_at(fp + JavaScriptFrameConstants::kFunctionOffset); |
1589 | 1589 |
1590 Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; | 1590 Memory::Object_at(fp + InternalFrameConstants::kCodeOffset) = *code; |
1591 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = | 1591 Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset) = |
1592 Smi::FromInt(StackFrame::INTERNAL); | 1592 Smi::FromInt(StackFrame::INTERNAL); |
(...skipping 13 matching lines...) Expand all Loading... |
1606 LiveEdit::FrameDropMode* mode, | 1606 LiveEdit::FrameDropMode* mode, |
1607 Object*** restarter_frame_function_pointer) { | 1607 Object*** restarter_frame_function_pointer) { |
1608 if (!LiveEdit::kFrameDropperSupported) { | 1608 if (!LiveEdit::kFrameDropperSupported) { |
1609 return "Stack manipulations are not supported in this architecture."; | 1609 return "Stack manipulations are not supported in this architecture."; |
1610 } | 1610 } |
1611 | 1611 |
1612 StackFrame* pre_top_frame = frames[top_frame_index - 1]; | 1612 StackFrame* pre_top_frame = frames[top_frame_index - 1]; |
1613 StackFrame* top_frame = frames[top_frame_index]; | 1613 StackFrame* top_frame = frames[top_frame_index]; |
1614 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; | 1614 StackFrame* bottom_js_frame = frames[bottom_js_frame_index]; |
1615 | 1615 |
1616 ASSERT(bottom_js_frame->is_java_script()); | 1616 DCHECK(bottom_js_frame->is_java_script()); |
1617 | 1617 |
1618 // Check the nature of the top frame. | 1618 // Check the nature of the top frame. |
1619 Isolate* isolate = bottom_js_frame->isolate(); | 1619 Isolate* isolate = bottom_js_frame->isolate(); |
1620 Code* pre_top_frame_code = pre_top_frame->LookupCode(); | 1620 Code* pre_top_frame_code = pre_top_frame->LookupCode(); |
1621 bool frame_has_padding = true; | 1621 bool frame_has_padding = true; |
1622 if (pre_top_frame_code->is_inline_cache_stub() && | 1622 if (pre_top_frame_code->is_inline_cache_stub() && |
1623 pre_top_frame_code->is_debug_stub()) { | 1623 pre_top_frame_code->is_debug_stub()) { |
1624 // OK, we can drop inline cache calls. | 1624 // OK, we can drop inline cache calls. |
1625 *mode = LiveEdit::FRAME_DROPPED_IN_IC_CALL; | 1625 *mode = LiveEdit::FRAME_DROPPED_IN_IC_CALL; |
1626 } else if (pre_top_frame_code == | 1626 } else if (pre_top_frame_code == |
(...skipping 15 matching lines...) Expand all Loading... |
1642 // Entry from our unit tests on 'debugger' statement. | 1642 // Entry from our unit tests on 'debugger' statement. |
1643 // It's fine, we support this case. | 1643 // It's fine, we support this case. |
1644 *mode = LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL; | 1644 *mode = LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL; |
1645 // We don't have a padding from 'debugger' statement call. | 1645 // We don't have a padding from 'debugger' statement call. |
1646 // Here the stub is CEntry, it's not debug-only and can't be padded. | 1646 // Here the stub is CEntry, it's not debug-only and can't be padded. |
1647 // If anyone would complain, a proxy padded stub could be added. | 1647 // If anyone would complain, a proxy padded stub could be added. |
1648 frame_has_padding = false; | 1648 frame_has_padding = false; |
1649 } else if (pre_top_frame->type() == StackFrame::ARGUMENTS_ADAPTOR) { | 1649 } else if (pre_top_frame->type() == StackFrame::ARGUMENTS_ADAPTOR) { |
1650 // This must be adaptor that remain from the frame dropping that | 1650 // This must be adaptor that remain from the frame dropping that |
1651 // is still on stack. A frame dropper frame must be above it. | 1651 // is still on stack. A frame dropper frame must be above it. |
1652 ASSERT(frames[top_frame_index - 2]->LookupCode() == | 1652 DCHECK(frames[top_frame_index - 2]->LookupCode() == |
1653 isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)); | 1653 isolate->builtins()->builtin(Builtins::kFrameDropper_LiveEdit)); |
1654 pre_top_frame = frames[top_frame_index - 3]; | 1654 pre_top_frame = frames[top_frame_index - 3]; |
1655 top_frame = frames[top_frame_index - 2]; | 1655 top_frame = frames[top_frame_index - 2]; |
1656 *mode = LiveEdit::CURRENTLY_SET_MODE; | 1656 *mode = LiveEdit::CURRENTLY_SET_MODE; |
1657 frame_has_padding = false; | 1657 frame_has_padding = false; |
1658 } else { | 1658 } else { |
1659 return "Unknown structure of stack above changing function"; | 1659 return "Unknown structure of stack above changing function"; |
1660 } | 1660 } |
1661 | 1661 |
1662 Address unused_stack_top = top_frame->sp(); | 1662 Address unused_stack_top = top_frame->sp(); |
1663 int new_frame_size = LiveEdit::kFrameDropperFrameSize * kPointerSize; | 1663 int new_frame_size = LiveEdit::kFrameDropperFrameSize * kPointerSize; |
1664 Address unused_stack_bottom = bottom_js_frame->fp() | 1664 Address unused_stack_bottom = bottom_js_frame->fp() |
1665 - new_frame_size + kPointerSize; // Bigger address end is exclusive. | 1665 - new_frame_size + kPointerSize; // Bigger address end is exclusive. |
1666 | 1666 |
1667 Address* top_frame_pc_address = top_frame->pc_address(); | 1667 Address* top_frame_pc_address = top_frame->pc_address(); |
1668 | 1668 |
1669 // top_frame may be damaged below this point. Do not used it. | 1669 // top_frame may be damaged below this point. Do not used it. |
1670 ASSERT(!(top_frame = NULL)); | 1670 DCHECK(!(top_frame = NULL)); |
1671 | 1671 |
1672 if (unused_stack_top > unused_stack_bottom) { | 1672 if (unused_stack_top > unused_stack_bottom) { |
1673 if (frame_has_padding) { | 1673 if (frame_has_padding) { |
1674 int shortage_bytes = | 1674 int shortage_bytes = |
1675 static_cast<int>(unused_stack_top - unused_stack_bottom); | 1675 static_cast<int>(unused_stack_top - unused_stack_bottom); |
1676 | 1676 |
1677 Address padding_start = pre_top_frame->fp() - | 1677 Address padding_start = pre_top_frame->fp() - |
1678 LiveEdit::kFrameDropperFrameSize * kPointerSize; | 1678 LiveEdit::kFrameDropperFrameSize * kPointerSize; |
1679 | 1679 |
1680 Address padding_pointer = padding_start; | 1680 Address padding_pointer = padding_start; |
(...skipping 24 matching lines...) Expand all Loading... |
1705 top_frame_pc_address -= shortage_bytes / kPointerSize; | 1705 top_frame_pc_address -= shortage_bytes / kPointerSize; |
1706 } else { | 1706 } else { |
1707 return "Not enough space for frame dropper frame"; | 1707 return "Not enough space for frame dropper frame"; |
1708 } | 1708 } |
1709 } | 1709 } |
1710 | 1710 |
1711 // Committing now. After this point we should return only NULL value. | 1711 // Committing now. After this point we should return only NULL value. |
1712 | 1712 |
1713 FixTryCatchHandler(pre_top_frame, bottom_js_frame); | 1713 FixTryCatchHandler(pre_top_frame, bottom_js_frame); |
1714 // Make sure FixTryCatchHandler is idempotent. | 1714 // Make sure FixTryCatchHandler is idempotent. |
1715 ASSERT(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); | 1715 DCHECK(!FixTryCatchHandler(pre_top_frame, bottom_js_frame)); |
1716 | 1716 |
1717 Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit(); | 1717 Handle<Code> code = isolate->builtins()->FrameDropper_LiveEdit(); |
1718 *top_frame_pc_address = code->entry(); | 1718 *top_frame_pc_address = code->entry(); |
1719 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); | 1719 pre_top_frame->SetCallerFp(bottom_js_frame->fp()); |
1720 | 1720 |
1721 *restarter_frame_function_pointer = | 1721 *restarter_frame_function_pointer = |
1722 SetUpFrameDropperFrame(bottom_js_frame, code); | 1722 SetUpFrameDropperFrame(bottom_js_frame, code); |
1723 | 1723 |
1724 ASSERT((**restarter_frame_function_pointer)->IsJSFunction()); | 1724 DCHECK((**restarter_frame_function_pointer)->IsJSFunction()); |
1725 | 1725 |
1726 for (Address a = unused_stack_top; | 1726 for (Address a = unused_stack_top; |
1727 a < unused_stack_bottom; | 1727 a < unused_stack_bottom; |
1728 a += kPointerSize) { | 1728 a += kPointerSize) { |
1729 Memory::Object_at(a) = Smi::FromInt(0); | 1729 Memory::Object_at(a) = Smi::FromInt(0); |
1730 } | 1730 } |
1731 | 1731 |
1732 return NULL; | 1732 return NULL; |
1733 } | 1733 } |
1734 | 1734 |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 return NULL; | 1888 return NULL; |
1889 } | 1889 } |
1890 | 1890 |
1891 | 1891 |
1892 bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array, | 1892 bool LiveEdit::FindActiveGenerators(Handle<FixedArray> shared_info_array, |
1893 Handle<FixedArray> result, | 1893 Handle<FixedArray> result, |
1894 int len) { | 1894 int len) { |
1895 Isolate* isolate = shared_info_array->GetIsolate(); | 1895 Isolate* isolate = shared_info_array->GetIsolate(); |
1896 bool found_suspended_activations = false; | 1896 bool found_suspended_activations = false; |
1897 | 1897 |
1898 ASSERT_LE(len, result->length()); | 1898 DCHECK_LE(len, result->length()); |
1899 | 1899 |
1900 FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR; | 1900 FunctionPatchabilityStatus active = FUNCTION_BLOCKED_ACTIVE_GENERATOR; |
1901 | 1901 |
1902 Heap* heap = isolate->heap(); | 1902 Heap* heap = isolate->heap(); |
1903 HeapIterator iterator(heap); | 1903 HeapIterator iterator(heap); |
1904 HeapObject* obj = NULL; | 1904 HeapObject* obj = NULL; |
1905 while ((obj = iterator.next()) != NULL) { | 1905 while ((obj = iterator.next()) != NULL) { |
1906 if (!obj->IsJSGeneratorObject()) continue; | 1906 if (!obj->IsJSGeneratorObject()) continue; |
1907 | 1907 |
1908 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); | 1908 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1950 Handle<JSArray> result_; | 1950 Handle<JSArray> result_; |
1951 bool has_blocked_functions_; | 1951 bool has_blocked_functions_; |
1952 }; | 1952 }; |
1953 | 1953 |
1954 | 1954 |
1955 Handle<JSArray> LiveEdit::CheckAndDropActivations( | 1955 Handle<JSArray> LiveEdit::CheckAndDropActivations( |
1956 Handle<JSArray> shared_info_array, bool do_drop) { | 1956 Handle<JSArray> shared_info_array, bool do_drop) { |
1957 Isolate* isolate = shared_info_array->GetIsolate(); | 1957 Isolate* isolate = shared_info_array->GetIsolate(); |
1958 int len = GetArrayLength(shared_info_array); | 1958 int len = GetArrayLength(shared_info_array); |
1959 | 1959 |
1960 ASSERT(shared_info_array->HasFastElements()); | 1960 DCHECK(shared_info_array->HasFastElements()); |
1961 Handle<FixedArray> shared_info_array_elements( | 1961 Handle<FixedArray> shared_info_array_elements( |
1962 FixedArray::cast(shared_info_array->elements())); | 1962 FixedArray::cast(shared_info_array->elements())); |
1963 | 1963 |
1964 Handle<JSArray> result = isolate->factory()->NewJSArray(len); | 1964 Handle<JSArray> result = isolate->factory()->NewJSArray(len); |
1965 Handle<FixedArray> result_elements = | 1965 Handle<FixedArray> result_elements = |
1966 JSObject::EnsureWritableFastElements(result); | 1966 JSObject::EnsureWritableFastElements(result); |
1967 | 1967 |
1968 // Fill the default values. | 1968 // Fill the default values. |
1969 for (int i = 0; i < len; i++) { | 1969 for (int i = 0; i < len; i++) { |
1970 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH; | 1970 FunctionPatchabilityStatus status = FUNCTION_AVAILABLE_FOR_PATCH; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { | 2078 void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) { |
2079 isolate_->active_function_info_listener()->FunctionCode(code); | 2079 isolate_->active_function_info_listener()->FunctionCode(code); |
2080 } | 2080 } |
2081 | 2081 |
2082 | 2082 |
2083 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { | 2083 bool LiveEditFunctionTracker::IsActive(Isolate* isolate) { |
2084 return isolate->active_function_info_listener() != NULL; | 2084 return isolate->active_function_info_listener() != NULL; |
2085 } | 2085 } |
2086 | 2086 |
2087 } } // namespace v8::internal | 2087 } } // namespace v8::internal |
OLD | NEW |