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

📄 codegen-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
  masm->StubReturn(argc_);}void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {  // r0 holds exception  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));  __ ldr(sp, MemOperand(r3));  __ pop(r2);  // pop next in chain  __ str(r2, MemOperand(r3));  // restore parameter- and frame-pointer and pop state.  __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());  // Before returning we restore the context from the frame pointer if not NULL.  // The frame pointer is NULL in the exception handler of a JS entry frame.  __ cmp(fp, Operand(0));  // Set cp to NULL if fp is NULL.  __ mov(cp, Operand(0), LeaveCC, eq);  // Restore cp otherwise.  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));  __ pop(pc);}void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {  // Fetch top stack handler.  __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));  __ ldr(r3, MemOperand(r3));  // Unwind the handlers until the ENTRY handler is found.  Label loop, done;  __ bind(&loop);  // Load the type of the current stack handler.  const int kStateOffset = StackHandlerConstants::kAddressDisplacement +      StackHandlerConstants::kStateOffset;  __ ldr(r2, MemOperand(r3, kStateOffset));  __ cmp(r2, Operand(StackHandler::ENTRY));  __ b(eq, &done);  // Fetch the next handler in the list.  const int kNextOffset =  StackHandlerConstants::kAddressDisplacement +      StackHandlerConstants::kNextOffset;  __ ldr(r3, MemOperand(r3, kNextOffset));  __ jmp(&loop);  __ bind(&done);  // Set the top handler address to next handler past the current ENTRY handler.  __ ldr(r0, MemOperand(r3, kNextOffset));  __ mov(r2, Operand(ExternalReference(Top::k_handler_address)));  __ str(r0, MemOperand(r2));  // Set external caught exception to false.  __ mov(r0, Operand(false));  ExternalReference external_caught(Top::k_external_caught_exception_address);  __ mov(r2, Operand(external_caught));  __ str(r0, MemOperand(r2));  // Set pending exception and r0 to out of memory exception.  Failure* out_of_memory = Failure::OutOfMemoryException();  __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));  __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));  __ str(r0, MemOperand(r2));  // Restore the stack to the address of the ENTRY handler  __ mov(sp, Operand(r3));  // restore parameter- and frame-pointer and pop state.  __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());  // Before returning we restore the context from the frame pointer if not NULL.  // The frame pointer is NULL in the exception handler of a JS entry frame.  __ cmp(fp, Operand(0));  // Set cp to NULL if fp is NULL.  __ mov(cp, Operand(0), LeaveCC, eq);  // Restore cp otherwise.  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);  if (kDebug && FLAG_debug_code) __ mov(lr, Operand(pc));  __ pop(pc);}void CEntryStub::GenerateCore(MacroAssembler* masm,                              Label* throw_normal_exception,                              Label* throw_out_of_memory_exception,                              StackFrame::Type frame_type,                              bool do_gc) {  // r0: result parameter for PerformGC, if any  // r4: number of arguments including receiver  (C callee-saved)  // r5: pointer to builtin function  (C callee-saved)  // r6: pointer to the first argument (C callee-saved)  if (do_gc) {    // Passing r0.    __ Call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY);  }  // Call C built-in.  // r0 = argc, r1 = argv  __ mov(r0, Operand(r4));  __ mov(r1, Operand(r6));  // TODO(1242173): To let the GC traverse the return address of the exit  // frames, we need to know where the return address is. Right now,  // we push it on the stack to be able to find it again, but we never  // restore from it in case of changes, which makes it impossible to  // support moving the C entry code stub. This should be fixed, but currently  // this is OK because the CEntryStub gets generated so early in the V8 boot  // sequence that it is not moving ever.  __ add(lr, pc, Operand(4));  // compute return address: (pc + 8) + 4  __ push(lr);#if !defined(__arm__)  // Notify the simulator of the transition to C code.  __ swi(assembler::arm::call_rt_r5);#else /* !defined(__arm__) */  __ mov(pc, Operand(r5));#endif /* !defined(__arm__) */  // result is in r0 or r0:r1 - do not destroy these registers!  // check for failure result  Label failure_returned;  ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);  // Lower 2 bits of r2 are 0 iff r0 has failure tag.  __ add(r2, r0, Operand(1));  __ tst(r2, Operand(kFailureTagMask));  __ b(eq, &failure_returned);  // Exit C frame and return.  // r0:r1: result  // sp: stack pointer  // fp: frame pointer  // pp: caller's parameter pointer pp  (restored as C callee-saved)  __ LeaveExitFrame(frame_type);  // check if we should retry or throw exception  Label retry;  __ bind(&failure_returned);  ASSERT(Failure::RETRY_AFTER_GC == 0);  __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));  __ b(eq, &retry);  Label continue_exception;  // If the returned failure is EXCEPTION then promote Top::pending_exception().  __ cmp(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));  __ b(ne, &continue_exception);  // Retrieve the pending exception and clear the variable.  __ mov(ip, Operand(Factory::the_hole_value().location()));  __ ldr(r3, MemOperand(ip));  __ mov(ip, Operand(Top::pending_exception_address()));  __ ldr(r0, MemOperand(ip));  __ str(r3, MemOperand(ip));  __ bind(&continue_exception);  // Special handling of out of memory exception.  Failure* out_of_memory = Failure::OutOfMemoryException();  __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));  __ b(eq, throw_out_of_memory_exception);  // Handle normal exception.  __ jmp(throw_normal_exception);  __ bind(&retry);  // pass last failure (r0) as parameter (r0) when retrying}void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {  // Called from JavaScript; parameters are on stack as if calling JS function  // r0: number of arguments including receiver  // r1: pointer to builtin function  // fp: frame pointer  (restored after C call)  // sp: stack pointer  (restored as callee's pp after C call)  // cp: current context  (C callee-saved)  // pp: caller's parameter pointer pp  (C callee-saved)  // NOTE: Invocations of builtins may return failure objects  // instead of a proper result. The builtin entry handles  // this by performing a garbage collection and retrying the  // builtin once.  StackFrame::Type frame_type = is_debug_break      ? StackFrame::EXIT_DEBUG      : StackFrame::EXIT;  // Enter the exit frame that transitions from JavaScript to C++.  __ EnterExitFrame(frame_type);  // r4: number of arguments (C callee-saved)  // r5: pointer to builtin function (C callee-saved)  // r6: pointer to first argument (C callee-saved)  Label throw_out_of_memory_exception;  Label throw_normal_exception;#ifdef DEBUG  if (FLAG_gc_greedy) {    Failure* failure = Failure::RetryAfterGC(0, NEW_SPACE);    __ mov(r0, Operand(reinterpret_cast<intptr_t>(failure)));  }  GenerateCore(masm,               &throw_normal_exception,               &throw_out_of_memory_exception,               frame_type,               FLAG_gc_greedy);#else  GenerateCore(masm,               &throw_normal_exception,               &throw_out_of_memory_exception,               frame_type,               false);#endif  GenerateCore(masm,               &throw_normal_exception,               &throw_out_of_memory_exception,               frame_type,               true);  __ bind(&throw_out_of_memory_exception);  GenerateThrowOutOfMemory(masm);  // control flow for generated will not return.  __ bind(&throw_normal_exception);  GenerateThrowTOS(masm);}void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {  // r0: code entry  // r1: function  // r2: receiver  // r3: argc  // [sp+0]: argv  Label invoke, exit;  // Called from C, so do not pop argc and args on exit (preserve sp)  // No need to save register-passed args  // Save callee-saved registers (incl. cp, pp, and fp), sp, and lr  __ stm(db_w, sp, kCalleeSaved | lr.bit());  // Get address of argv, see stm above.  // r0: code entry  // r1: function  // r2: receiver  // r3: argc  __ add(r4, sp, Operand((kNumCalleeSaved + 1)*kPointerSize));  __ ldr(r4, MemOperand(r4));  // argv  // Push a frame with special values setup to mark it as an entry frame.  // r0: code entry  // r1: function  // r2: receiver  // r3: argc  // r4: argv  int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;  __ mov(r8, Operand(-1));  // Push a bad frame pointer to fail if it is used.  __ mov(r7, Operand(~ArgumentsAdaptorFrame::SENTINEL));  __ mov(r6, Operand(Smi::FromInt(marker)));  __ mov(r5, Operand(ExternalReference(Top::k_c_entry_fp_address)));  __ ldr(r5, MemOperand(r5));  __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | r8.bit());  // Setup frame pointer for the frame to be pushed.  __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));  // Call a faked try-block that does the invoke.  __ bl(&invoke);  // Caught exception: Store result (exception) in the pending  // exception field in the JSEnv and return a failure sentinel.  // Coming in here the fp will be invalid because the PushTryHandler below  // sets it to 0 to signal the existence of the JSEntry frame.  __ mov(ip, Operand(Top::pending_exception_address()));  __ str(r0, MemOperand(ip));  __ mov(r0, Operand(Handle<Failure>(Failure::Exception())));  __ b(&exit);  // Invoke: Link this frame into the handler chain.  __ bind(&invoke);  // Must preserve r0-r4, r5-r7 are available.  __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);  // If an exception not caught by another handler occurs, this handler returns  // control to the code after the bl(&invoke) above, which restores all  // kCalleeSaved registers (including cp, pp and fp) to their saved values  // before returning a failure to C.  // Clear any pending exceptions.  __ mov(ip, Operand(ExternalReference::the_hole_value_location()));  __ ldr(r5, MemOperand(ip));  __ mov(ip, Operand(Top::pending_exception_address()));  __ str(r5, MemOperand(ip));  // Invoke the function by calling through JS entry trampoline builtin.  // Notice that we cannot store a reference to the trampoline code directly in  // this stub, because runtime stubs are not traversed when doing GC.  // Expected registers by Builtins::JSEntryTrampoline  // r0: code entry  // r1: function  // r2: receiver  // r3: argc  // r4: argv  if (is_construct) {    ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline);    __ mov(ip, Operand(construct_entry));  } else {    ExternalReference entry(Builtins::JSEntryTrampoline);    __ mov(ip, Operand(entry));  }  __ ldr(ip, MemOperand(ip));  // deref address  // Branch and link to JSEntryTrampoline  __ mov(lr, Operand(pc));  __ add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));  // Unlink this frame from the handler chain. When reading the  // address of the next handler, there is no need to use the address  // displacement since the current stack pointer (sp) points directly  // to the stack handler.  __ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset));  __ mov(ip, Operand(ExternalReference(Top::k_handler_address)));  __ str(r3, MemOperand(ip));  // No need to restore registers  __ add(sp, sp, Operand(StackHandlerConstants::kSize));  __ bind(&exit);  // r0 holds result  // Restore the top frame descriptors from the stack.  __ pop(r3);  __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));  __ str(r3, MemOperand(ip));  // Reset the stack to the callee saved registers.  __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));  // Restore callee-saved registers and return.#ifdef DEBUG  if (FLAG_debug_code) __ mov(lr, Operand(pc));#endif  __ ldm(ia_w, sp, kCalleeSaved | pc.bit());}class ArgumentsAccessStub: public CodeStub { public:  explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { } private:  bool is_length_;  Major MajorKey() { return ArgumentsAccess; }  int MinorKey() { return is_length_ ? 1 : 0; }  void Generate(MacroAssembler* masm);  const char* GetName() { return "ArgumentsAccessStub"; }#ifdef DEBUG  void Print() {    PrintF("ArgumentsAccessStub (is_length %s)\n",           is_length_ ? "true" : "false");  }#endif};void ArgumentsAccessStub::Generate(MacroAssembler* masm) {  // ----------- S t a t e -------------  //  -- r0: formal number of parameters for the calling function  //  -- r1: key (if value access)  //  -- lr: return address  // -----------------------------------  // Check that the key is a smi for non-length accesses.  Label slow;  if (!is_length_) {    __ tst(r1, Operand(kSmiTagMask));    __ b(ne, &slow);  }  // Check if the calling frame is an arguments adaptor frame.  // r0: formal number of parameters  // r1: key (if access)  Label adaptor;  __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));  __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));  __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));  __ b(eq, &adaptor);  static const int kParamDisplace

⌨️ 快捷键说明

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