1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file. 4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if V8_TARGET_ARCH_IA32 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/codegen.h" 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal { 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define __ ACCESS_MASM(masm) 15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid EmitDebugBreakSlot(MacroAssembler* masm) { 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label check_codesize; 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&check_codesize); 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Nop(Assembler::kDebugBreakSlotLength); 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(Assembler::kDebugBreakSlotLength, 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->SizeOfCodeGeneratedSince(&check_codesize)); 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DebugCodegen::GenerateSlot(MacroAssembler* masm, RelocInfo::Mode mode) { 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Generate enough nop's to make space for a call instruction. 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->RecordDebugBreakSlot(mode); 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitDebugBreakSlot(masm); 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DebugCodegen::ClearDebugBreakSlot(Isolate* isolate, Address pc) { 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher patcher(isolate, pc, Assembler::kDebugBreakSlotLength); 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitDebugBreakSlot(patcher.masm()); 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc, 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Code> code) { 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(Code::BUILTIN, code->kind()); 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const int kSize = Assembler::kDebugBreakSlotLength; 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher patcher(isolate, pc, kSize); 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Add a label for checking the size of the code used for returning. 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label check_codesize; 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch patcher.masm()->bind(&check_codesize); 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch patcher.masm()->call(code->entry(), RelocInfo::NONE32); 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the size of the code generated is as expected. 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK_EQ(kSize, patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize)); 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DebugCodegen::GenerateDebugBreakStub(MacroAssembler* masm, 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DebugBreakCallHelperMode mode) { 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordComment("Debug break"); 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Enter an internal frame. 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load padding words on stack. 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingValue))); 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Immediate(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode == SAVE_RESULT_REGISTER) __ push(eax); 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(eax, Immediate(0)); // No arguments. 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Immediate(ExternalReference( 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::FunctionForId(Runtime::kDebugBreak), masm->isolate()))); 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CEntryStub ceb(masm->isolate(), 1); 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CallStub(&ceb); 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_debug_code) { 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < kNumJSCallerSaved; ++i) { 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register reg = {JSCallerSavedCode(i)}; 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Move(reg, Immediate(kDebugZapValue)); 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (mode == SAVE_RESULT_REGISTER) __ pop(eax); 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(ebx); 88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We divide stored value by 2 (untagging) and multiply it by word's size. 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(kSmiTagSize == 1 && kSmiShiftSize == 0); 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(esp, ebx, times_half_pointer_size, 0)); 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get rid of the internal frame. 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // This call did not replace a call , so there will be an unwanted 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // return address left on the stack. Here we get rid of that. 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(esp, Immediate(kPointerSize)); 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Now that the break point has been handled, resume normal execution by 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // jumping to the target address intended by the caller and that was 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // overwritten by the address of DebugBreakXXX. 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference after_break_target = 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference::debug_after_break_target_address(masm->isolate()); 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(Operand::StaticVariable(after_break_target)); 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We do not know our frame height, but set esp based on ebp. 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(esp, Operand(ebp, -1 * kPointerSize)); 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(edi); // Function. 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ pop(ebp); 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ParameterCount dummy(0); 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ FloodFunctionIfStepping(edi, no_reg, dummy, dummy); 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load context from the function. 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Clear new.target register as a safety measure. 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(edx, masm->isolate()->factory()->undefined_value()); 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Get function code. 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kCodeOffset)); 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ebx, FieldOperand(ebx, Code::kHeaderSize)); 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Re-run JSFunction, edi is function, esi is context. 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(ebx); 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst bool LiveEdit::kFrameDropperSupported = true; 135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef __ 137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif // V8_TARGET_ARCH_IA32 142