| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "codegen.h" | 9 #include "codegen.h" |
| 10 #include "debug.h" | 10 #include "debug.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength); | 60 Assembler::kDebugBreakSlotLength - Assembler::kCallInstructionLength); |
| 61 } | 61 } |
| 62 | 62 |
| 63 | 63 |
| 64 void BreakLocationIterator::ClearDebugBreakAtSlot() { | 64 void BreakLocationIterator::ClearDebugBreakAtSlot() { |
| 65 ASSERT(IsDebugBreakSlot()); | 65 ASSERT(IsDebugBreakSlot()); |
| 66 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); | 66 rinfo()->PatchCode(original_rinfo()->pc(), Assembler::kDebugBreakSlotLength); |
| 67 } | 67 } |
| 68 | 68 |
| 69 | 69 |
| 70 // All debug break stubs support padding for LiveEdit. | |
| 71 const bool Debug::FramePaddingLayout::kIsSupported = true; | |
| 72 | |
| 73 | |
| 74 #define __ ACCESS_MASM(masm) | 70 #define __ ACCESS_MASM(masm) |
| 75 | 71 |
| 76 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, | 72 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
| 77 RegList object_regs, | 73 RegList object_regs, |
| 78 RegList non_object_regs, | 74 RegList non_object_regs, |
| 79 bool convert_call_to_jmp) { | 75 bool convert_call_to_jmp) { |
| 80 // Enter an internal frame. | 76 // Enter an internal frame. |
| 81 { | 77 { |
| 82 FrameScope scope(masm, StackFrame::INTERNAL); | 78 FrameScope scope(masm, StackFrame::INTERNAL); |
| 83 | 79 |
| 84 // Load padding words on stack. | 80 // Load padding words on stack. |
| 85 for (int i = 0; i < Debug::FramePaddingLayout::kInitialSize; i++) { | 81 for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
| 86 __ push(Immediate(Smi::FromInt( | 82 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingValue))); |
| 87 Debug::FramePaddingLayout::kPaddingValue))); | |
| 88 } | 83 } |
| 89 __ push(Immediate(Smi::FromInt(Debug::FramePaddingLayout::kInitialSize))); | 84 __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); |
| 90 | 85 |
| 91 // Store the registers containing live values on the expression stack to | 86 // Store the registers containing live values on the expression stack to |
| 92 // make sure that these are correctly updated during GC. Non object values | 87 // make sure that these are correctly updated during GC. Non object values |
| 93 // are stored as a smi causing it to be untouched by GC. | 88 // are stored as a smi causing it to be untouched by GC. |
| 94 ASSERT((object_regs & ~kJSCallerSaved) == 0); | 89 ASSERT((object_regs & ~kJSCallerSaved) == 0); |
| 95 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); | 90 ASSERT((non_object_regs & ~kJSCallerSaved) == 0); |
| 96 ASSERT((object_regs & non_object_regs) == 0); | 91 ASSERT((object_regs & non_object_regs) == 0); |
| 97 for (int i = 0; i < kNumJSCallerSaved; i++) { | 92 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 98 int r = JSCallerSavedCode(i); | 93 int r = JSCallerSavedCode(i); |
| 99 Register reg = { r }; | 94 Register reg = { r }; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 | 160 |
| 166 // Now that the break point has been handled, resume normal execution by | 161 // Now that the break point has been handled, resume normal execution by |
| 167 // jumping to the target address intended by the caller and that was | 162 // jumping to the target address intended by the caller and that was |
| 168 // overwritten by the address of DebugBreakXXX. | 163 // overwritten by the address of DebugBreakXXX. |
| 169 ExternalReference after_break_target = | 164 ExternalReference after_break_target = |
| 170 ExternalReference::debug_after_break_target_address(masm->isolate()); | 165 ExternalReference::debug_after_break_target_address(masm->isolate()); |
| 171 __ jmp(Operand::StaticVariable(after_break_target)); | 166 __ jmp(Operand::StaticVariable(after_break_target)); |
| 172 } | 167 } |
| 173 | 168 |
| 174 | 169 |
| 175 void Debug::GenerateCallICStubDebugBreak(MacroAssembler* masm) { | 170 void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |
| 176 // Register state for CallICStub | 171 // Register state for CallICStub |
| 177 // ----------- S t a t e ------------- | 172 // ----------- S t a t e ------------- |
| 178 // -- edx : type feedback slot (smi) | 173 // -- edx : type feedback slot (smi) |
| 179 // -- edi : function | 174 // -- edi : function |
| 180 // ----------------------------------- | 175 // ----------------------------------- |
| 181 Generate_DebugBreakCallHelper(masm, edx.bit() | edi.bit(), | 176 Generate_DebugBreakCallHelper(masm, edx.bit() | edi.bit(), |
| 182 0, false); | 177 0, false); |
| 183 } | 178 } |
| 184 | 179 |
| 185 | 180 |
| 186 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) { | 181 void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) { |
| 187 // Register state for IC load call (from ic-ia32.cc). | 182 // Register state for IC load call (from ic-ia32.cc). |
| 188 // ----------- S t a t e ------------- | 183 // ----------- S t a t e ------------- |
| 189 // -- ecx : name | 184 // -- ecx : name |
| 190 // -- edx : receiver | 185 // -- edx : receiver |
| 191 // ----------------------------------- | 186 // ----------------------------------- |
| 192 Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false); | 187 Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false); |
| 193 } | 188 } |
| 194 | 189 |
| 195 | 190 |
| 196 void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) { | 191 void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) { |
| 197 // Register state for IC store call (from ic-ia32.cc). | 192 // Register state for IC store call (from ic-ia32.cc). |
| 198 // ----------- S t a t e ------------- | 193 // ----------- S t a t e ------------- |
| 199 // -- eax : value | 194 // -- eax : value |
| 200 // -- ecx : name | 195 // -- ecx : name |
| 201 // -- edx : receiver | 196 // -- edx : receiver |
| 202 // ----------------------------------- | 197 // ----------------------------------- |
| 203 Generate_DebugBreakCallHelper( | 198 Generate_DebugBreakCallHelper( |
| 204 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); | 199 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); |
| 205 } | 200 } |
| 206 | 201 |
| 207 | 202 |
| 208 void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { | 203 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) { |
| 209 // Register state for keyed IC load call (from ic-ia32.cc). | 204 // Register state for keyed IC load call (from ic-ia32.cc). |
| 210 // ----------- S t a t e ------------- | 205 // ----------- S t a t e ------------- |
| 211 // -- ecx : key | 206 // -- ecx : key |
| 212 // -- edx : receiver | 207 // -- edx : receiver |
| 213 // ----------------------------------- | 208 // ----------------------------------- |
| 214 Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false); | 209 Generate_DebugBreakCallHelper(masm, ecx.bit() | edx.bit(), 0, false); |
| 215 } | 210 } |
| 216 | 211 |
| 217 | 212 |
| 218 void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { | 213 void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) { |
| 219 // Register state for keyed IC load call (from ic-ia32.cc). | 214 // Register state for keyed IC load call (from ic-ia32.cc). |
| 220 // ----------- S t a t e ------------- | 215 // ----------- S t a t e ------------- |
| 221 // -- eax : value | 216 // -- eax : value |
| 222 // -- ecx : key | 217 // -- ecx : key |
| 223 // -- edx : receiver | 218 // -- edx : receiver |
| 224 // ----------------------------------- | 219 // ----------------------------------- |
| 225 Generate_DebugBreakCallHelper( | 220 Generate_DebugBreakCallHelper( |
| 226 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); | 221 masm, eax.bit() | ecx.bit() | edx.bit(), 0, false); |
| 227 } | 222 } |
| 228 | 223 |
| 229 | 224 |
| 230 void Debug::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { | 225 void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) { |
| 231 // Register state for CompareNil IC | 226 // Register state for CompareNil IC |
| 232 // ----------- S t a t e ------------- | 227 // ----------- S t a t e ------------- |
| 233 // -- eax : value | 228 // -- eax : value |
| 234 // ----------------------------------- | 229 // ----------------------------------- |
| 235 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, false); | 230 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, false); |
| 236 } | 231 } |
| 237 | 232 |
| 238 | 233 |
| 239 void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) { | 234 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
| 240 // Register state just before return from JS function (from codegen-ia32.cc). | 235 // Register state just before return from JS function (from codegen-ia32.cc). |
| 241 // ----------- S t a t e ------------- | 236 // ----------- S t a t e ------------- |
| 242 // -- eax: return value | 237 // -- eax: return value |
| 243 // ----------------------------------- | 238 // ----------------------------------- |
| 244 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, true); | 239 Generate_DebugBreakCallHelper(masm, eax.bit(), 0, true); |
| 245 } | 240 } |
| 246 | 241 |
| 247 | 242 |
| 248 void Debug::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { | 243 void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |
| 249 // Register state for CallFunctionStub (from code-stubs-ia32.cc). | 244 // Register state for CallFunctionStub (from code-stubs-ia32.cc). |
| 250 // ----------- S t a t e ------------- | 245 // ----------- S t a t e ------------- |
| 251 // -- edi: function | 246 // -- edi: function |
| 252 // ----------------------------------- | 247 // ----------------------------------- |
| 253 Generate_DebugBreakCallHelper(masm, edi.bit(), 0, false); | 248 Generate_DebugBreakCallHelper(masm, edi.bit(), 0, false); |
| 254 } | 249 } |
| 255 | 250 |
| 256 | 251 |
| 257 void Debug::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { | 252 void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |
| 258 // Register state for CallConstructStub (from code-stubs-ia32.cc). | 253 // Register state for CallConstructStub (from code-stubs-ia32.cc). |
| 259 // eax is the actual number of arguments not encoded as a smi see comment | 254 // eax is the actual number of arguments not encoded as a smi see comment |
| 260 // above IC call. | 255 // above IC call. |
| 261 // ----------- S t a t e ------------- | 256 // ----------- S t a t e ------------- |
| 262 // -- eax: number of arguments (not smi) | 257 // -- eax: number of arguments (not smi) |
| 263 // -- edi: constructor function | 258 // -- edi: constructor function |
| 264 // ----------------------------------- | 259 // ----------------------------------- |
| 265 // The number of arguments in eax is not smi encoded. | 260 // The number of arguments in eax is not smi encoded. |
| 266 Generate_DebugBreakCallHelper(masm, edi.bit(), eax.bit(), false); | 261 Generate_DebugBreakCallHelper(masm, edi.bit(), eax.bit(), false); |
| 267 } | 262 } |
| 268 | 263 |
| 269 | 264 |
| 270 void Debug::GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm) { | 265 void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |
| 266 MacroAssembler* masm) { |
| 271 // Register state for CallConstructStub (from code-stubs-ia32.cc). | 267 // Register state for CallConstructStub (from code-stubs-ia32.cc). |
| 272 // eax is the actual number of arguments not encoded as a smi see comment | 268 // eax is the actual number of arguments not encoded as a smi see comment |
| 273 // above IC call. | 269 // above IC call. |
| 274 // ----------- S t a t e ------------- | 270 // ----------- S t a t e ------------- |
| 275 // -- eax: number of arguments (not smi) | 271 // -- eax: number of arguments (not smi) |
| 276 // -- ebx: feedback array | 272 // -- ebx: feedback array |
| 277 // -- edx: feedback slot (smi) | 273 // -- edx: feedback slot (smi) |
| 278 // -- edi: constructor function | 274 // -- edi: constructor function |
| 279 // ----------------------------------- | 275 // ----------------------------------- |
| 280 // The number of arguments in eax is not smi encoded. | 276 // The number of arguments in eax is not smi encoded. |
| 281 Generate_DebugBreakCallHelper(masm, ebx.bit() | edx.bit() | edi.bit(), | 277 Generate_DebugBreakCallHelper(masm, ebx.bit() | edx.bit() | edi.bit(), |
| 282 eax.bit(), false); | 278 eax.bit(), false); |
| 283 } | 279 } |
| 284 | 280 |
| 285 | 281 |
| 286 void Debug::GenerateSlot(MacroAssembler* masm) { | 282 void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
| 287 // Generate enough nop's to make space for a call instruction. | 283 // Generate enough nop's to make space for a call instruction. |
| 288 Label check_codesize; | 284 Label check_codesize; |
| 289 __ bind(&check_codesize); | 285 __ bind(&check_codesize); |
| 290 __ RecordDebugBreakSlot(); | 286 __ RecordDebugBreakSlot(); |
| 291 __ Nop(Assembler::kDebugBreakSlotLength); | 287 __ Nop(Assembler::kDebugBreakSlotLength); |
| 292 ASSERT_EQ(Assembler::kDebugBreakSlotLength, | 288 ASSERT_EQ(Assembler::kDebugBreakSlotLength, |
| 293 masm->SizeOfCodeGeneratedSince(&check_codesize)); | 289 masm->SizeOfCodeGeneratedSince(&check_codesize)); |
| 294 } | 290 } |
| 295 | 291 |
| 296 | 292 |
| 297 void Debug::GenerateSlotDebugBreak(MacroAssembler* masm) { | 293 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
| 298 // In the places where a debug break slot is inserted no registers can contain | 294 // In the places where a debug break slot is inserted no registers can contain |
| 299 // object pointers. | 295 // object pointers. |
| 300 Generate_DebugBreakCallHelper(masm, 0, 0, true); | 296 Generate_DebugBreakCallHelper(masm, 0, 0, true); |
| 301 } | 297 } |
| 302 | 298 |
| 303 | 299 |
| 304 void Debug::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { | 300 void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
| 305 masm->ret(0); | 301 masm->ret(0); |
| 306 } | 302 } |
| 307 | 303 |
| 308 | 304 |
| 309 void Debug::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { | 305 void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
| 310 ExternalReference restarter_frame_function_slot = | 306 ExternalReference restarter_frame_function_slot = |
| 311 ExternalReference::debug_restarter_frame_function_pointer_address( | 307 ExternalReference::debug_restarter_frame_function_pointer_address( |
| 312 masm->isolate()); | 308 masm->isolate()); |
| 313 __ mov(Operand::StaticVariable(restarter_frame_function_slot), Immediate(0)); | 309 __ mov(Operand::StaticVariable(restarter_frame_function_slot), Immediate(0)); |
| 314 | 310 |
| 315 // We do not know our frame height, but set esp based on ebp. | 311 // We do not know our frame height, but set esp based on ebp. |
| 316 __ lea(esp, Operand(ebp, -1 * kPointerSize)); | 312 __ lea(esp, Operand(ebp, -1 * kPointerSize)); |
| 317 | 313 |
| 318 __ pop(edi); // Function. | 314 __ pop(edi); // Function. |
| 319 __ pop(ebp); | 315 __ pop(ebp); |
| 320 | 316 |
| 321 // Load context from the function. | 317 // Load context from the function. |
| 322 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 318 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 323 | 319 |
| 324 // Get function code. | 320 // Get function code. |
| 325 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 321 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 326 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); | 322 __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset)); |
| 327 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); | 323 __ lea(edx, FieldOperand(edx, Code::kHeaderSize)); |
| 328 | 324 |
| 329 // Re-run JSFunction, edi is function, esi is context. | 325 // Re-run JSFunction, edi is function, esi is context. |
| 330 __ jmp(edx); | 326 __ jmp(edx); |
| 331 } | 327 } |
| 332 | 328 |
| 333 const bool Debug::kFrameDropperSupported = true; | 329 |
| 330 const bool LiveEdit::kFrameDropperSupported = true; |
| 334 | 331 |
| 335 #undef __ | 332 #undef __ |
| 336 | 333 |
| 337 } } // namespace v8::internal | 334 } } // namespace v8::internal |
| 338 | 335 |
| 339 #endif // V8_TARGET_ARCH_IA32 | 336 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |