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