⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 builtins-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
  __ ldr(r0, MemOperand(fp, kFunctionOffset));  // get the function  __ push(r0);  __ ldr(r0, MemOperand(fp, kArgsOffset));  // get the args array  __ push(r0);  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);  // Eagerly check for stack-overflow before starting to push the arguments.  // r0: number of arguments  Label okay;  ExternalReference stack_guard_limit_address =      ExternalReference::address_of_stack_guard_limit();  __ mov(r2, Operand(stack_guard_limit_address));  __ ldr(r2, MemOperand(r2));  __ sub(r2, sp, r2);  __ sub(r2, r2, Operand(3 * kPointerSize));  // limit, index, receiver  __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));  __ b(hi, &okay);  // Out of stack space.  __ ldr(r1, MemOperand(fp, kFunctionOffset));  __ push(r1);  __ push(r0);  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);  // Push current limit and index.  __ bind(&okay);  __ push(r0);  // limit  __ mov(r1, Operand(0));  // initial index  __ push(r1);  // Change context eagerly to get the right global object if necessary.  __ ldr(r0, MemOperand(fp, kFunctionOffset));  __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));  // Compute the receiver.  Label call_to_object, use_global_receiver, push_receiver;  __ ldr(r0, MemOperand(fp, kRecvOffset));  __ tst(r0, Operand(kSmiTagMask));  __ b(eq, &call_to_object);  __ mov(r1, Operand(Factory::null_value()));  __ cmp(r0, r1);  __ b(eq, &use_global_receiver);  __ mov(r1, Operand(Factory::undefined_value()));  __ cmp(r0, r1);  __ b(eq, &use_global_receiver);  // Check if the receiver is already a JavaScript object.  // r0: receiver  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));  __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));  __ b(lt, &call_to_object);  __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));  __ b(le, &push_receiver);  // Convert the receiver to a regular object.  // r0: receiver  __ bind(&call_to_object);  __ push(r0);  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);  __ b(&push_receiver);  // Use the current global object as the receiver.  __ bind(&use_global_receiver);  __ ldr(r0, FieldMemOperand(cp, Context::kHeaderSize +                             Context::GLOBAL_INDEX * kPointerSize));  // Push the receiver.  // r0: receiver  __ bind(&push_receiver);  __ push(r0);  // Copy all arguments from the array to the stack.  Label entry, loop;  __ ldr(r0, MemOperand(fp, kIndexOffset));  __ b(&entry);  // Load the current argument from the arguments array and push it to the  // stack.  // r0: current argument index  __ bind(&loop);  __ ldr(r1, MemOperand(fp, kArgsOffset));  __ push(r1);  __ push(r0);  // Call the runtime to access the property in the arguments array.  __ CallRuntime(Runtime::kGetProperty, 2);  __ push(r0);  // Use inline caching to access the arguments.  __ ldr(r0, MemOperand(fp, kIndexOffset));  __ add(r0, r0, Operand(1 << kSmiTagSize));  __ str(r0, MemOperand(fp, kIndexOffset));  // Test if the copy loop has finished copying all the elements from the  // arguments object.  __ bind(&entry);  __ ldr(r1, MemOperand(fp, kLimitOffset));  __ cmp(r0, r1);  __ b(ne, &loop);  // Invoke the function.  ParameterCount actual(r0);  __ mov(r0, Operand(r0, ASR, kSmiTagSize));  __ ldr(r1, MemOperand(fp, kFunctionOffset));  __ InvokeFunction(r1, actual, CALL_FUNCTION);  // Tear down the internal frame and remove function, receiver and args.  __ LeaveInternalFrame();  __ add(sp, sp, Operand(3 * kPointerSize));  __ mov(pc, lr);}static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {  __ mov(r0, Operand(r0, LSL, kSmiTagSize));  __ mov(r4, Operand(ArgumentsAdaptorFrame::SENTINEL));  __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());  __ add(fp, sp, Operand(3 * kPointerSize));}static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) {  // ----------- S t a t e -------------  //  -- r0 : result being passed through  // -----------------------------------  // Get the number of arguments passed (as a smi), tear down the frame and  // then tear down the parameters.  __ ldr(r1, MemOperand(fp, -3 * kPointerSize));  __ mov(sp, fp);  __ ldm(ia_w, sp, fp.bit() | lr.bit());  __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));  __ add(sp, sp, Operand(kPointerSize));  // adjust for receiver}void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {  // ----------- S t a t e -------------  //  -- r0 : actual number of arguments  //  -- r1 : function (passed through to callee)  //  -- r2 : expected number of arguments  //  -- r3 : code entry to call  // -----------------------------------  Label invoke, dont_adapt_arguments;  Label enough, too_few;  __ cmp(r0, Operand(r2));  __ b(lt, &too_few);  __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));  __ b(eq, &dont_adapt_arguments);  {  // Enough parameters: actual >= excpected    __ bind(&enough);    EnterArgumentsAdaptorFrame(masm);    // Calculate copy start address into r0 and copy end address into r2.    // r0: actual number of arguments as a smi    // r1: function    // r2: expected number of arguments    // r3: code entry to call    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));    // adjust for return address and receiver    __ add(r0, r0, Operand(2 * kPointerSize));    __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));    // Copy the arguments (including the receiver) to the new stack frame.    // r0: copy start address    // r1: function    // r2: copy end address    // r3: code entry to call    Label copy;    __ bind(&copy);    __ ldr(ip, MemOperand(r0, 0));    __ push(ip);    __ cmp(r0, r2);  // Compare before moving to next argument.    __ sub(r0, r0, Operand(kPointerSize));    __ b(ne, &copy);    __ b(&invoke);  }  {  // Too few parameters: Actual < expected    __ bind(&too_few);    EnterArgumentsAdaptorFrame(masm);    // Calculate copy start address into r0 and copy end address is fp.    // r0: actual number of arguments as a smi    // r1: function    // r2: expected number of arguments    // r3: code entry to call    __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));    // Copy the arguments (including the receiver) to the new stack frame.    // r0: copy start address    // r1: function    // r2: expected number of arguments    // r3: code entry to call    Label copy;    __ bind(&copy);    // Adjust load for return address and receiver.    __ ldr(ip, MemOperand(r0, 2 * kPointerSize));    __ push(ip);    __ cmp(r0, fp);  // Compare before moving to next argument.    __ sub(r0, r0, Operand(kPointerSize));    __ b(ne, &copy);    // Fill the remaining expected arguments with undefined.    // r1: function    // r2: expected number of arguments    // r3: code entry to call    __ mov(ip, Operand(Factory::undefined_value()));    __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));    __ sub(r2, r2, Operand(4 * kPointerSize));  // Adjust for frame.    Label fill;    __ bind(&fill);    __ push(ip);    __ cmp(sp, r2);    __ b(ne, &fill);  }  // Call the entry point.  Label return_site;  __ bind(&invoke);  __ Call(r3);  __ bind(&return_site);  ExitArgumentsAdaptorFrame(masm);  __ mov(pc, lr);  // 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);  __ mov(pc, r3);}static void Generate_DebugBreakCallHelper(MacroAssembler* masm,                                          RegList pointer_regs) {  // 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);  // This is a direct call from a debug breakpoint. To build a fake JS frame  // with no parameters push a function and a receiver, keep the current  // return address in lr, and set r0 to zero.  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));  __ ldr(r3, MemOperand(ip));  __ mov(r0, Operand(0));  // Null receiver and zero arguments.  __ stm(db_w, sp, r0.bit() | r3.bit());  // push function and receiver  // r0: number of arguments.  // What follows is an inlined version of EnterJSFrame(0, 0).  // It needs to be kept in sync if any calling conventions are changed.  // Compute parameter pointer before making changes  // ip = sp + kPointerSize*(args_len+1);  // +1 for receiver, args_len == 0  __ add(ip, sp, Operand(kPointerSize));  __ mov(r3, Operand(0));  // args_len to be saved  __ mov(r2, Operand(cp));  // context to be saved  // push in reverse order: context (r2), args_len (r3), caller_pp, caller_fp,  // sp_on_exit (ip == pp), return address  __ stm(db_w, sp, r2.bit() | r3.bit() | pp.bit() | fp.bit() |         ip.bit() | lr.bit());  // Setup new frame pointer.  __ add(fp, sp, Operand(-StandardFrameConstants::kContextOffset));  __ mov(pp, Operand(ip));  // setup new parameter pointer  // r0 is already set to 0 as spare slot to store caller code object during GC  __ push(r0);  // code pointer  // Inlined EnterJSFrame ends here.  // Store the registers containing object pointers on the expression stack to  // make sure that these are correctly updated during GC.  // Use sp as base to push.  __ CopyRegistersFromMemoryToStack(sp, pointer_regs);#ifdef DEBUG  __ RecordComment("// Calling from debug break to runtime - come in - over");#endif  // r0 is already 0, no arguments  __ mov(r1, Operand(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.  // Use sp as base to pop.  __ CopyRegistersFromStackToMemory(sp, r3, pointer_regs);  // What follows is an inlined version of ExitJSFrame(0).  // It needs to be kept in sync if any calling conventions are changed.  // NOTE: loading the return address to lr and discarding the (fake) function  //       is an addition to this inlined copy.  __ mov(sp, Operand(fp));  // respect ABI stack constraint  __ ldm(ia, sp, pp.bit() | fp.bit() | sp.bit() | lr.bit());  __ pop();  // discard fake function  // Inlined ExitJSFrame ends here.  // 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.  __ mov(ip, Operand(ExternalReference(Debug_Address::AfterBreakTarget())));  __ ldr(ip, MemOperand(ip));  __ Jump(ip);}void Builtins::Generate_LoadIC_DebugBreak(MacroAssembler* masm) {  // Calling convention for IC load (from ic-arm.cc).  // ----------- S t a t e -------------  //  -- r0    : receiver  //  -- r2    : name  //  -- lr    : return address  //  -- [sp]  : receiver  // -----------------------------------  // Registers r0 and r2 contain objects that needs to be pushed on the  // expression stack of the fake JS frame.  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());}void Builtins::Generate_StoreIC_DebugBreak(MacroAssembler* masm) {  // Calling convention for IC store (from ic-arm.cc).  // ----------- S t a t e -------------  //  -- r0    : receiver  //  -- r2    : name  //  -- lr    : return address  //  -- [sp]  : receiver  // -----------------------------------  // Registers r0 and r2 contain objects that needs to be pushed on the  // expression stack of the fake JS frame.  Generate_DebugBreakCallHelper(masm, r0.bit() | r2.bit());}void Builtins::Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {  // Keyed load IC not implemented on ARM.}void Builtins::Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {  // Keyed store IC not implemented on ARM.}void Builtins::Generate_CallIC_DebugBreak(MacroAssembler* masm) {  // Calling convention for IC call (from ic-arm.cc)  // ----------- S t a t e -------------  //  -- r0: number of arguments  //  -- r1: receiver  //  -- lr: return address  // -----------------------------------  // Register r1 contains an object that needs to be pushed on the expression  // stack of the fake JS frame. r0 is the actual number of arguments not  // encoded as a smi, therefore it cannot be on the expression stack of the  // fake JS frame as it can easily be an invalid pointer (e.g. 1). r0 will be  // pushed on the stack of the C frame and restored from there.  Generate_DebugBreakCallHelper(masm, r1.bit());}void Builtins::Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {  // In places other than IC call sites it is expected that r0 is TOS which  // is an object - this is not generally the case so this should be used with  // care.  Generate_DebugBreakCallHelper(masm, r0.bit());}void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) {  // In places other than IC call sites it is expected that r0 is TOS which  // is an object - this is not generally the case so this should be used with  // care.  Generate_DebugBreakCallHelper(masm, r0.bit());}void Builtins::Generate_Return_DebugBreakEntry(MacroAssembler* masm) {  // Generate nothing as this handling of debug break return is not done this  // way on ARM  - yet.}void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {  // Generate nothing as CodeStub CallFunction is not used on ARM.}#undef __} }  // namespace v8::internal

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -