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 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_MIPS | 9 #if V8_TARGET_ARCH_MIPS |
10 | 10 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions); | 53 CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions); |
54 patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int32_t>( | 54 patcher.masm()->li(v8::internal::t9, Operand(reinterpret_cast<int32_t>( |
55 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()))); | 55 debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()))); |
56 patcher.masm()->Call(v8::internal::t9); | 56 patcher.masm()->Call(v8::internal::t9); |
57 } | 57 } |
58 | 58 |
59 | 59 |
60 #define __ ACCESS_MASM(masm) | 60 #define __ ACCESS_MASM(masm) |
61 | 61 |
62 | 62 |
63 | |
64 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 63 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
65 RegList object_regs, | 64 RegList object_regs) { |
66 RegList non_object_regs) { | |
67 { | 65 { |
68 FrameScope scope(masm, StackFrame::INTERNAL); | 66 FrameScope scope(masm, StackFrame::INTERNAL); |
69 | 67 |
70 // Load padding words on stack. | 68 // Load padding words on stack. |
71 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); | 69 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); |
72 __ Subu(sp, sp, | 70 __ Subu(sp, sp, |
73 Operand(kPointerSize * LiveEdit::kFramePaddingInitialSize)); | 71 Operand(kPointerSize * LiveEdit::kFramePaddingInitialSize)); |
74 for (int i = LiveEdit::kFramePaddingInitialSize - 1; i >= 0; i--) { | 72 for (int i = LiveEdit::kFramePaddingInitialSize - 1; i >= 0; i--) { |
75 __ sw(at, MemOperand(sp, kPointerSize * i)); | 73 __ sw(at, MemOperand(sp, kPointerSize * i)); |
76 } | 74 } |
77 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); | 75 __ li(at, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); |
78 __ push(at); | 76 __ push(at); |
79 | 77 |
80 // Store the registers containing live values on the expression stack to | 78 // Store the registers containing live values on the expression stack to |
81 // make sure that these are correctly updated during GC. Non object values | 79 // make sure that these are correctly updated during GC. Non object values |
82 // are stored as a smi causing it to be untouched by GC. | 80 // are stored as a smi causing it to be untouched by GC. |
83 DCHECK((object_regs & ~kJSCallerSaved) == 0); | 81 DCHECK((object_regs & ~kJSCallerSaved) == 0); |
84 DCHECK((non_object_regs & ~kJSCallerSaved) == 0); | 82 if (object_regs != 0) { |
85 DCHECK((object_regs & non_object_regs) == 0); | 83 __ MultiPush(object_regs); |
86 if ((object_regs | non_object_regs) != 0) { | |
87 for (int i = 0; i < kNumJSCallerSaved; i++) { | |
88 int r = JSCallerSavedCode(i); | |
89 Register reg = { r }; | |
90 if ((non_object_regs & (1 << r)) != 0) { | |
91 if (FLAG_debug_code) { | |
92 __ And(at, reg, 0xc0000000); | |
93 __ Assert(eq, kUnableToEncodeValueAsSmi, at, Operand(zero_reg)); | |
94 } | |
95 __ sll(reg, reg, kSmiTagSize); | |
96 } | |
97 } | |
98 __ MultiPush(object_regs | non_object_regs); | |
99 } | 84 } |
100 | 85 |
101 #ifdef DEBUG | 86 #ifdef DEBUG |
102 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 87 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
103 #endif | 88 #endif |
104 __ PrepareCEntryArgs(0); // No arguments. | 89 __ PrepareCEntryArgs(0); // No arguments. |
105 __ PrepareCEntryFunction(ExternalReference::debug_break(masm->isolate())); | 90 __ PrepareCEntryFunction(ExternalReference::debug_break(masm->isolate())); |
106 | 91 |
107 CEntryStub ceb(masm->isolate(), 1); | 92 CEntryStub ceb(masm->isolate(), 1); |
108 __ CallStub(&ceb); | 93 __ CallStub(&ceb); |
109 | 94 |
110 // Restore the register values from the expression stack. | 95 // Restore the register values from the expression stack. |
111 if ((object_regs | non_object_regs) != 0) { | 96 if (object_regs != 0) { |
112 __ MultiPop(object_regs | non_object_regs); | 97 __ MultiPop(object_regs); |
113 for (int i = 0; i < kNumJSCallerSaved; i++) { | 98 } |
114 int r = JSCallerSavedCode(i); | 99 for (int i = 0; i < kNumJSCallerSaved; i++) { |
115 Register reg = { r }; | 100 int r = JSCallerSavedCode(i); |
116 if ((non_object_regs & (1 << r)) != 0) { | 101 Register reg = {r}; |
117 __ srl(reg, reg, kSmiTagSize); | 102 if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) { |
118 } | 103 __ li(reg, kDebugZapValue); |
119 if (FLAG_debug_code && | |
120 (((object_regs |non_object_regs) & (1 << r)) == 0)) { | |
121 __ li(reg, kDebugZapValue); | |
122 } | |
123 } | 104 } |
124 } | 105 } |
125 | 106 |
126 // Don't bother removing padding bytes pushed on the stack | 107 // Don't bother removing padding bytes pushed on the stack |
127 // as the frame is going to be restored right away. | 108 // as the frame is going to be restored right away. |
128 | 109 |
129 // Leave the internal frame. | 110 // Leave the internal frame. |
130 } | 111 } |
131 | 112 |
132 // Now that the break point has been handled, resume normal execution by | 113 // Now that the break point has been handled, resume normal execution by |
133 // jumping to the target address intended by the caller and that was | 114 // jumping to the target address intended by the caller and that was |
134 // overwritten by the address of DebugBreakXXX. | 115 // overwritten by the address of DebugBreakXXX. |
135 ExternalReference after_break_target = | 116 ExternalReference after_break_target = |
136 ExternalReference::debug_after_break_target_address(masm->isolate()); | 117 ExternalReference::debug_after_break_target_address(masm->isolate()); |
137 __ li(t9, Operand(after_break_target)); | 118 __ li(t9, Operand(after_break_target)); |
138 __ lw(t9, MemOperand(t9)); | 119 __ lw(t9, MemOperand(t9)); |
139 __ Jump(t9); | 120 __ Jump(t9); |
140 } | 121 } |
141 | 122 |
142 | 123 |
143 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { | |
144 // Register state for CallICStub | |
145 // ----------- S t a t e ------------- | |
146 // -- a1 : function | |
147 // -- a3 : slot in feedback array (smi) | |
148 // ----------------------------------- | |
149 Generate_DebugBreakCallHelper(masm, a1.bit() | a3.bit(), 0); | |
150 } | |
151 | |
152 | |
153 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { | 124 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
154 // In places other than IC call sites it is expected that v0 is TOS which | 125 // In places other than IC call sites it is expected that v0 is TOS which |
155 // is an object - this is not generally the case so this should be used with | 126 // is an object - this is not generally the case so this should be used with |
156 // care. | 127 // care. |
157 Generate_DebugBreakCallHelper(masm, v0.bit(), 0); | 128 Generate_DebugBreakCallHelper(masm, v0.bit()); |
158 } | 129 } |
159 | 130 |
160 | 131 |
161 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { | |
162 // Register state for CallFunctionStub (from code-stubs-mips.cc). | |
163 // ----------- S t a t e ------------- | |
164 // -- a1 : function | |
165 // ----------------------------------- | |
166 Generate_DebugBreakCallHelper(masm, a1.bit(), 0); | |
167 } | |
168 | |
169 | |
170 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { | |
171 // Calling convention for CallConstructStub (from code-stubs-mips.cc). | |
172 // ----------- S t a t e ------------- | |
173 // -- a0 : number of arguments (not smi) | |
174 // -- a1 : constructor function | |
175 // ----------------------------------- | |
176 Generate_DebugBreakCallHelper(masm, a1.bit() , a0.bit()); | |
177 } | |
178 | |
179 | |
180 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( | |
181 MacroAssembler* masm) { | |
182 // Calling convention for CallConstructStub (from code-stubs-mips.cc). | |
183 // ----------- S t a t e ------------- | |
184 // -- a0 : number of arguments (not smi) | |
185 // -- a1 : constructor function | |
186 // -- a2 : feedback array | |
187 // -- a3 : feedback slot (smi) | |
188 // ----------------------------------- | |
189 Generate_DebugBreakCallHelper(masm, a1.bit() | a2.bit() | a3.bit(), a0.bit()); | |
190 } | |
191 | |
192 | |
193 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { | 132 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
194 // Generate enough nop's to make space for a call instruction. Avoid emitting | 133 // Generate enough nop's to make space for a call instruction. Avoid emitting |
195 // the trampoline pool in the debug break slot code. | 134 // the trampoline pool in the debug break slot code. |
196 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); | 135 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); |
197 Label check_codesize; | 136 Label check_codesize; |
198 __ bind(&check_codesize); | 137 __ bind(&check_codesize); |
199 __ RecordDebugBreakSlot(); | |
200 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { | 138 for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
201 __ nop(MacroAssembler::DEBUG_BREAK_NOP); | 139 __ nop(MacroAssembler::DEBUG_BREAK_NOP); |
202 } | 140 } |
203 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, | 141 DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, |
204 masm->InstructionsGeneratedSince(&check_codesize)); | 142 masm->InstructionsGeneratedSince(&check_codesize)); |
205 } | 143 } |
206 | 144 |
207 | 145 |
208 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { | 146 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
209 // In the places where a debug break slot is inserted no registers can contain | 147 // In the places where a debug break slot is inserted no registers can contain |
210 // object pointers. | 148 // object pointers. |
211 Generate_DebugBreakCallHelper(masm, 0, 0); | 149 Generate_DebugBreakCallHelper(masm, 0); |
212 } | 150 } |
213 | 151 |
214 | 152 |
215 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 153 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
216 __ Ret(); | 154 __ Ret(); |
217 } | 155 } |
218 | 156 |
219 | 157 |
220 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 158 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
221 ExternalReference restarter_frame_function_slot = | 159 ExternalReference restarter_frame_function_slot = |
(...skipping 21 matching lines...) Expand all Loading... |
243 | 181 |
244 | 182 |
245 const bool LiveEdit::kFrameDropperSupported = true; | 183 const bool LiveEdit::kFrameDropperSupported = true; |
246 | 184 |
247 #undef __ | 185 #undef __ |
248 | 186 |
249 } // namespace internal | 187 } // namespace internal |
250 } // namespace v8 | 188 } // namespace v8 |
251 | 189 |
252 #endif // V8_TARGET_ARCH_MIPS | 190 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |