📄 builtins-ia32.cc.svn-base
字号:
// Use inline caching to speed up access to arguments. Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); // Remove IC arguments from the stack and push the nth argument. __ add(Operand(esp), Immediate(2 * kPointerSize)); __ push(eax); // Update the index on the stack and in register eax. __ mov(eax, Operand(ebp, kIndexOffset)); __ add(Operand(eax), Immediate(1 << kSmiTagSize)); __ mov(Operand(ebp, kIndexOffset), eax); __ bind(&entry); __ cmp(eax, Operand(ebp, kLimitOffset)); __ j(not_equal, &loop); // Invoke the function. ParameterCount actual(eax); __ shr(eax, kSmiTagSize); __ mov(edi, Operand(ebp, 4 * kPointerSize)); __ InvokeFunction(edi, actual, CALL_FUNCTION); __ LeaveInternalFrame(); __ ret(3 * kPointerSize); // remove this, receiver, and arguments}static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { __ push(ebp); __ mov(ebp, Operand(esp)); // Store the arguments adaptor context sentinel. __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); // Push the function on the stack. __ push(edi); // Preserve the number of arguments on the stack. Must preserve both // eax and ebx because these registers are used when copying the // arguments and the receiver. ASSERT(kSmiTagSize == 1); __ lea(ecx, Operand(eax, eax, times_1, kSmiTag)); __ push(Operand(ecx));}static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) { // Retrieve the number of arguments from the stack. __ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset)); // Leave the frame. __ leave(); // Remove caller arguments from the stack. ASSERT(kSmiTagSize == 1 && kSmiTag == 0); __ pop(ecx); __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver __ push(ecx);}void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : actual number of arguments // -- ebx : expected number of arguments // -- edx : code entry to call // ----------------------------------- Label invoke, dont_adapt_arguments; __ IncrementCounter(&Counters::arguments_adaptors, 1); Label enough, too_few; __ cmp(eax, Operand(ebx)); __ j(less, &too_few); __ cmp(ebx, SharedFunctionInfo::kDontAdaptArgumentsSentinel); __ j(equal, &dont_adapt_arguments); { // Enough parameters: Actual >= expected. __ bind(&enough); EnterArgumentsAdaptorFrame(masm); // Copy receiver and all expected arguments. const int offset = StandardFrameConstants::kCallerSPOffset; __ lea(eax, Operand(ebp, eax, times_4, offset)); __ mov(ecx, -1); // account for receiver Label copy; __ bind(©); __ inc(ecx); __ push(Operand(eax, 0)); __ sub(Operand(eax), Immediate(kPointerSize)); __ cmp(ecx, Operand(ebx)); __ j(less, ©); __ jmp(&invoke); } { // Too few parameters: Actual < expected. __ bind(&too_few); EnterArgumentsAdaptorFrame(masm); // Copy receiver and all actual arguments. const int offset = StandardFrameConstants::kCallerSPOffset; __ lea(edi, Operand(ebp, eax, times_4, offset)); __ mov(ecx, -1); // account for receiver Label copy; __ bind(©); __ inc(ecx); __ push(Operand(edi, 0)); __ sub(Operand(edi), Immediate(kPointerSize)); __ cmp(ecx, Operand(eax)); __ j(less, ©); // Fill remaining expected arguments with undefined values. Label fill; __ bind(&fill); __ inc(ecx); __ push(Immediate(Factory::undefined_value())); __ cmp(ecx, Operand(ebx)); __ j(less, &fill); // Restore function pointer. __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); } // Call the entry point. Label return_site; __ bind(&invoke); __ call(Operand(edx)); __ bind(&return_site); ExitArgumentsAdaptorFrame(masm); __ ret(0); // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline // builtin code object to the return address after the call. ASSERT(return_site.is_bound()); arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; // ------------------------------------------- // Dont adapt arguments. // ------------------------------------------- __ bind(&dont_adapt_arguments); __ jmp(Operand(edx));}static void Generate_DebugBreakCallHelper(MacroAssembler* masm, RegList pointer_regs, bool convert_call_to_jmp) { // Save the content of all general purpose registers in memory. This copy in // memory is later pushed onto the JS expression stack for the fake JS frame // generated and also to the C frame generated on top of that. In the JS // frame ONLY the registers containing pointers will be pushed on the // expression stack. This causes the GC to update these pointers so that // they will have the correct value when returning from the debugger. __ SaveRegistersToMemory(kJSCallerSaved); // Enter an internal frame. __ EnterInternalFrame(); // Store the registers containing object pointers on the expression stack to // make sure that these are correctly updated during GC. __ PushRegistersFromMemory(pointer_regs);#ifdef DEBUG __ RecordComment("// Calling from debug break to runtime - come in - over");#endif __ Set(eax, Immediate(0)); // no arguments __ mov(Operand(ebx), Immediate(ExternalReference::debug_break())); CEntryDebugBreakStub ceb; __ CallStub(&ceb); // Restore the register values containing object pointers from the expression // stack in the reverse order as they where pushed. __ PopRegistersToMemory(pointer_regs); // Get rid of the internal frame. __ LeaveInternalFrame(); // If this call did not replace a call but patched other code then there will // be an unwanted return address left on the stack. Here we get rid of that. if (convert_call_to_jmp) { __ pop(eax); } // Finally restore all registers. __ RestoreRegistersFromMemory(kJSCallerSaved); // Now that the break point has been handled, resume normal execution by // jumping to the target address intended by the caller and that was // overwritten by the address of DebugBreakXXX. ExternalReference after_break_target = ExternalReference(Debug_Address::AfterBreakTarget()); __ jmp(Operand::StaticVariable(after_break_target));}void Builtins::Generate_LoadIC_DebugBreak(MacroAssembler* masm) { // Register state for IC load call (from ic-ia32.cc). // ----------- S t a t e ------------- // -- ecx : name // ----------------------------------- Generate_DebugBreakCallHelper(masm, ecx.bit(), false);}void Builtins::Generate_StoreIC_DebugBreak(MacroAssembler* masm) { // REgister state for IC store call (from ic-ia32.cc). // ----------- S t a t e ------------- // -- eax : value // -- ecx : name // ----------------------------------- Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit(), false);}void Builtins::Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) { // Register state for keyed IC load call (from ic-ia32.cc). // ----------- S t a t e ------------- // No registers used on entry. // ----------------------------------- Generate_DebugBreakCallHelper(masm, 0, false);}void Builtins::Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) { // Register state for keyed IC load call (from ic-ia32.cc). // ----------- S t a t e ------------- // -- eax : value // ----------------------------------- // Register eax contains an object that needs to be pushed on the // expression stack of the fake JS frame. Generate_DebugBreakCallHelper(masm, eax.bit(), false);}void Builtins::Generate_CallIC_DebugBreak(MacroAssembler* masm) { // Register state for keyed IC call call (from ic-ia32.cc) // ----------- S t a t e ------------- // -- eax: number of arguments // ----------------------------------- // The number of arguments in eax is not smi encoded. Generate_DebugBreakCallHelper(masm, 0, false);}void Builtins::Generate_ConstructCall_DebugBreak(MacroAssembler* masm) { // Register state just before return from JS function (from codegen-ia32.cc). // eax is the actual number of arguments not encoded as a smi see comment // above IC call. // ----------- S t a t e ------------- // -- eax: number of arguments // ----------------------------------- // The number of arguments in eax is not smi encoded. Generate_DebugBreakCallHelper(masm, 0, false);}void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) { // Register state just before return from JS function (from codegen-ia32.cc). // ----------- S t a t e ------------- // -- eax: return value // ----------------------------------- Generate_DebugBreakCallHelper(masm, eax.bit(), true);}void Builtins::Generate_Return_DebugBreakEntry(MacroAssembler* masm) { // OK to clobber ebx as we are returning from a JS function in the code // generated by Ia32CodeGenerator::ExitJSFrame. ExternalReference debug_break_return = ExternalReference(Debug_Address::DebugBreakReturn()); __ mov(ebx, Operand::StaticVariable(debug_break_return)); __ add(Operand(ebx), Immediate(Code::kHeaderSize - kHeapObjectTag)); __ jmp(Operand(ebx));}void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { // Register state for stub CallFunction (from CallFunctionStub in ic-ia32.cc). // ----------- S t a t e ------------- // No registers used on entry. // ----------------------------------- Generate_DebugBreakCallHelper(masm, 0, false);}#undef __} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -