| OLD | NEW |
| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 void BreakLocationIterator::ClearDebugBreakAtSlot() { | 87 void BreakLocationIterator::ClearDebugBreakAtSlot() { |
| 88 ASSERT(IsDebugBreakSlot()); | 88 ASSERT(IsDebugBreakSlot()); |
| 89 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); | 89 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 #define __ ACCESS_MASM(masm) | 93 #define __ ACCESS_MASM(masm) |
| 94 | 94 |
| 95 | 95 |
| 96 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 96 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
| 97 RegList pointer_regs, | 97 RegList object_regs, |
| 98 RegList non_object_regs, |
| 98 bool convert_call_to_jmp) { | 99 bool convert_call_to_jmp) { |
| 99 // Save the content of all general purpose registers in memory. This copy in | |
| 100 // memory is later pushed onto the JS expression stack for the fake JS frame | |
| 101 // generated and also to the C frame generated on top of that. In the JS | |
| 102 // frame ONLY the registers containing pointers will be pushed on the | |
| 103 // expression stack. This causes the GC to update these pointers so that | |
| 104 // they will have the correct value when returning from the debugger. | |
| 105 __ SaveRegistersToMemory(kJSCallerSaved); | |
| 106 | |
| 107 // Enter an internal frame. | 100 // Enter an internal frame. |
| 108 __ EnterInternalFrame(); | 101 __ EnterInternalFrame(); |
| 109 | 102 |
| 110 // Store the registers containing object pointers on the expression stack to | 103 // Store the registers containing live values on the expression stack to |
| 111 // make sure that these are correctly updated during GC. | 104 // make sure that these are correctly updated during GC. Non object values |
| 112 __ PushRegistersFromMemory(pointer_regs); | 105 // are stored as a smi causing it to be untouched by GC. |
| 106 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
| 107 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
| 108 ASSERT((object_regs & non_object_regs) == 0); |
| 109 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 110 int r = JSCallerSavedCode(i); |
| 111 Register reg = { r }; |
| 112 if ((object_regs & (1 << r)) != 0) { |
| 113 __ push(reg); |
| 114 } |
| 115 if ((non_object_regs & (1 << r)) != 0) { |
| 116 if (FLAG_debug_code) { |
| 117 __ test(reg, Immediate(0xc0000000)); |
| 118 __ Assert(zero, "Unable to encode value as smi"); |
| 119 } |
| 120 __ SmiTag(reg); |
| 121 __ push(reg); |
| 122 } |
| 123 } |
| 113 | 124 |
| 114 #ifdef DEBUG | 125 #ifdef DEBUG |
| 115 __ RecordComment("// Calling from debug break to runtime - come in - over"); | 126 __ RecordComment("// Calling from debug break to runtime - come in - over"); |
| 116 #endif | 127 #endif |
| 117 __ Set(eax, Immediate(0)); // no arguments | 128 __ Set(eax, Immediate(0)); // no arguments |
| 118 __ mov(ebx, Immediate(ExternalReference::debug_break())); | 129 __ mov(ebx, Immediate(ExternalReference::debug_break())); |
| 119 | 130 |
| 120 CEntryStub ceb(1, ExitFrame::MODE_DEBUG); | 131 CEntryStub ceb(1); |
| 121 __ CallStub(&ceb); | 132 __ CallStub(&ceb); |
| 122 | 133 |
| 123 // Restore the register values containing object pointers from the expression | 134 // Restore the register values containing object pointers from the expression |
| 124 // stack in the reverse order as they where pushed. | 135 // stack. |
| 125 __ PopRegistersToMemory(pointer_regs); | 136 for (int i = kNumJSCallerSaved; --i >= 0;) { |
| 137 int r = JSCallerSavedCode(i); |
| 138 Register reg = { r }; |
| 139 if (FLAG_debug_code) { |
| 140 __ Set(reg, Immediate(kDebugZapValue)); |
| 141 } |
| 142 if ((object_regs & (1 << r)) != 0) { |
| 143 __ pop(reg); |
| 144 } |
| 145 if ((non_object_regs & (1 << r)) != 0) { |
| 146 __ pop(reg); |
| 147 __ SmiUntag(reg); |
| 148 } |
| 149 } |
| 126 | 150 |
| 127 // Get rid of the internal frame. | 151 // Get rid of the internal frame. |
| 128 __ LeaveInternalFrame(); | 152 __ LeaveInternalFrame(); |
| 129 | 153 |
| 130 // If this call did not replace a call but patched other code then there will | 154 // If this call did not replace a call but patched other code then there will |
| 131 // be an unwanted return address left on the stack. Here we get rid of that. | 155 // be an unwanted return address left on the stack. Here we get rid of that. |
| 132 if (convert_call_to_jmp) { | 156 if (convert_call_to_jmp) { |
| 133 __ pop(eax); | 157 __ add(Operand(esp), Immediate(kPointerSize)); |
| 134 } | 158 } |
| 135 | 159 |
| 136 // Finally restore all registers. | |
| 137 __ RestoreRegistersFromMemory(kJSCallerSaved); | |
| 138 | |
| 139 // Now that the break point has been handled, resume normal execution by | 160 // Now that the break point has been handled, resume normal execution by |
| 140 // jumping to the target address intended by the caller and that was | 161 // jumping to the target address intended by the caller and that was |
| 141 // overwritten by the address of DebugBreakXXX. | 162 // overwritten by the address of DebugBreakXXX. |
| 142 ExternalReference after_break_target = | 163 ExternalReference after_break_target = |
| 143 ExternalReference(Debug_Address::AfterBreakTarget()); | 164 ExternalReference(Debug_Address::AfterBreakTarget()); |
| 144 __ jmp(Operand::StaticVariable(after_break_target)); | 165 __ jmp(Operand::StaticVariable(after_break_target)); |
| 145 } | 166 } |
| 146 | 167 |
| 147 | 168 |
| 148 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 169 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
| 149 // Register state for IC load call (from ic-ia32.cc). | 170 // Register state for IC load call (from ic-ia32.cc). |
| 150 // ----------- S t a t e ------------- | 171 // ----------- S t a t e ------------- |
| 151 // -- eax : receiver | 172 // -- eax : receiver |
| 152 // -- ecx : name | 173 // -- ecx : name |
| 153 // ----------------------------------- | 174 // ----------------------------------- |
| 154 Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false); | 175 Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), 0, false); |
| 155 } | 176 } |
| 156 | 177 |
| 157 | 178 |
| 158 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 179 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
| 159 // Register state for IC store call (from ic-ia32.cc). | 180 // Register state for IC store call (from ic-ia32.cc). |
| 160 // ----------- S t a t e ------------- | 181 // ----------- S t a t e ------------- |
| 161 // -- eax : value | 182 // -- eax : value |
| 162 // -- ecx : name | 183 // -- ecx : name |
| 163 // -- edx : receiver | 184 // -- edx : receiver |
| 164 // ----------------------------------- | 185 // ----------------------------------- |
| 165 Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false); | 186 Generate_DebugBreakCallHelper( |
| 187 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); |
| 166 } | 188 } |
| 167 | 189 |
| 168 | 190 |
| 169 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 191 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
| 170 // Register state for keyed IC load call (from ic-ia32.cc). | 192 // Register state for keyed IC load call (from ic-ia32.cc). |
| 171 // ----------- S t a t e ------------- | 193 // ----------- S t a t e ------------- |
| 172 // -- edx : receiver | 194 // -- edx : receiver |
| 173 // -- eax : key | 195 // -- eax : key |
| 174 // ----------------------------------- | 196 // ----------------------------------- |
| 175 Generate_DebugBreakCallHelper(masm, eax.bit() | edx.bit(), false); | 197 Generate_DebugBreakCallHelper(masm, eax.bit() | edx.bit(), 0, false); |
| 176 } | 198 } |
| 177 | 199 |
| 178 | 200 |
| 179 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 201 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
| 180 // Register state for keyed IC load call (from ic-ia32.cc). | 202 // Register state for keyed IC load call (from ic-ia32.cc). |
| 181 // ----------- S t a t e ------------- | 203 // ----------- S t a t e ------------- |
| 182 // -- eax : value | 204 // -- eax : value |
| 183 // -- ecx : key | 205 // -- ecx : key |
| 184 // -- edx : receiver | 206 // -- edx : receiver |
| 185 // ----------------------------------- | 207 // ----------------------------------- |
| 186 Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false); | 208 Generate_DebugBreakCallHelper( |
| 209 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); |
| 187 } | 210 } |
| 188 | 211 |
| 189 | 212 |
| 190 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { | 213 void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) { |
| 191 // Register state for keyed IC call call (from ic-ia32.cc) | 214 // Register state for keyed IC call call (from ic-ia32.cc) |
| 192 // ----------- S t a t e ------------- | 215 // ----------- S t a t e ------------- |
| 193 // -- ecx: name | 216 // -- ecx: name |
| 194 // ----------------------------------- | 217 // ----------------------------------- |
| 195 Generate_DebugBreakCallHelper(masm, ecx.bit(), false); | 218 Generate_DebugBreakCallHelper(masm, ecx.bit(), 0, false); |
| 196 } | 219 } |
| 197 | 220 |
| 198 | 221 |
| 199 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { | 222 void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) { |
| 200 // Register state just before return from JS function (from codegen-ia32.cc). | 223 // Register state just before return from JS function (from codegen-ia32.cc). |
| 201 // eax is the actual number of arguments not encoded as a smi see comment | 224 // eax is the actual number of arguments not encoded as a smi see comment |
| 202 // above IC call. | 225 // above IC call. |
| 203 // ----------- S t a t e ------------- | 226 // ----------- S t a t e ------------- |
| 204 // -- eax: number of arguments | 227 // -- eax: number of arguments (not smi) |
| 228 // -- edi: constructor function |
| 205 // ----------------------------------- | 229 // ----------------------------------- |
| 206 // The number of arguments in eax is not smi encoded. | 230 // The number of arguments in eax is not smi encoded. |
| 207 Generate_DebugBreakCallHelper(masm, 0, false); | 231 Generate_DebugBreakCallHelper(masm, edi.bit(), eax.bit(), false); |
| 208 } | 232 } |
| 209 | 233 |
| 210 | 234 |
| 211 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 235 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { |
| 212 // Register state just before return from JS function (from codegen-ia32.cc). | 236 // Register state just before return from JS function (from codegen-ia32.cc). |
| 213 // ----------- S t a t e ------------- | 237 // ----------- S t a t e ------------- |
| 214 // -- eax: return value | 238 // -- eax: return value |
| 215 // ----------------------------------- | 239 // ----------------------------------- |
| 216 Generate_DebugBreakCallHelper(masm, eax.bit(), true); | 240 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, true); |
| 217 } | 241 } |
| 218 | 242 |
| 219 | 243 |
| 220 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { | 244 void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) { |
| 221 // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc). | 245 // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc). |
| 222 // ----------- S t a t e ------------- | 246 // ----------- S t a t e ------------- |
| 223 // No registers used on entry. | 247 // No registers used on entry. |
| 224 // ----------------------------------- | 248 // ----------------------------------- |
| 225 Generate_DebugBreakCallHelper(masm, 0, false); | 249 Generate_DebugBreakCallHelper(masm, 0, 0, false); |
| 226 } | 250 } |
| 227 | 251 |
| 228 | 252 |
| 229 void Debug::GenerateSlot(MacroAssembler* masm) { | 253 void Debug::GenerateSlot(MacroAssembler* masm) { |
| 230 // Generate enough nop's to make space for a call instruction. | 254 // Generate enough nop's to make space for a call instruction. |
| 231 Label check_codesize; | 255 Label check_codesize; |
| 232 __ bind(&check_codesize); | 256 __ bind(&check_codesize); |
| 233 __ RecordDebugBreakSlot(); | 257 __ RecordDebugBreakSlot(); |
| 234 for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) { | 258 for (int i = 0; i < Assembler::kDebugBreakSlotLength; i++) { |
| 235 __ nop(); | 259 __ nop(); |
| 236 } | 260 } |
| 237 ASSERT_EQ(Assembler::kDebugBreakSlotLength, | 261 ASSERT_EQ(Assembler::kDebugBreakSlotLength, |
| 238 masm->SizeOfCodeGeneratedSince(&check_codesize)); | 262 masm->SizeOfCodeGeneratedSince(&check_codesize)); |
| 239 } | 263 } |
| 240 | 264 |
| 241 | 265 |
| 242 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { | 266 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { |
| 243 // In the places where a debug break slot is inserted no registers can contain | 267 // In the places where a debug break slot is inserted no registers can contain |
| 244 // object pointers. | 268 // object pointers. |
| 245 Generate_DebugBreakCallHelper(masm, 0, true); | 269 Generate_DebugBreakCallHelper(masm, 0, 0, true); |
| 246 } | 270 } |
| 247 | 271 |
| 248 | 272 |
| 249 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 273 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
| 250 masm->ret(0); | 274 masm->ret(0); |
| 251 } | 275 } |
| 252 | 276 |
| 253 | 277 |
| 254 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 278 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
| 255 ExternalReference restarter_frame_function_slot = | 279 ExternalReference restarter_frame_function_slot = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 276 | 300 |
| 277 const bool Debug::kFrameDropperSupported = true; | 301 const bool Debug::kFrameDropperSupported = true; |
| 278 | 302 |
| 279 #undef __ | 303 #undef __ |
| 280 | 304 |
| 281 #endif // ENABLE_DEBUGGER_SUPPORT | 305 #endif // ENABLE_DEBUGGER_SUPPORT |
| 282 | 306 |
| 283 } } // namespace v8::internal | 307 } } // namespace v8::internal |
| 284 | 308 |
| 285 #endif // V8_TARGET_ARCH_IA32 | 309 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |