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

📄 builtins-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
  // Restore the arguments count and exit the internal frame.  __ bind(&exit);  __ mov(ebx, Operand(esp, kPointerSize));  // get arguments count  __ LeaveInternalFrame();  // Remove caller arguments from the stack and return.  ASSERT(kSmiTagSize == 1 && kSmiTag == 0);  __ pop(ecx);  __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));  // 1 ~ receiver  __ push(ecx);  __ ret(0);  // Compute the offset from the beginning of the JSConstructCall  // builtin code object to the return address after the call.  ASSERT(return_site.is_bound());  construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;}static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,                                             bool is_construct) {  // Clear the context before we push it when entering the JS frame.  __ xor_(esi, Operand(esi));  // clear esi  // Enter an internal frame.  __ EnterInternalFrame();  // Load the previous frame pointer (ebx) to access C arguments  __ mov(ebx, Operand(ebp, 0));  // Get the function from the frame and setup the context.  __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset));  __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset));  // Push the function and the receiver onto the stack.  __ push(ecx);  __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset));  // Load the number of arguments and setup pointer to the arguments.  __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset));  __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset));  // Copy arguments to the stack in a loop.  Label loop, entry;  __ xor_(ecx, Operand(ecx));  // clear ecx  __ jmp(&entry);  __ bind(&loop);  __ mov(edx, Operand(ebx, ecx, times_4, 0));  // push parameter from argv  __ push(Operand(edx, 0));  // dereference handle  __ inc(Operand(ecx));  __ bind(&entry);  __ cmp(ecx, Operand(eax));  __ j(not_equal, &loop);  // Get the function from the stack and call it.  __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));  // +1 ~ receiver  // Invoke the code.  if (is_construct) {    __ call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),            RelocInfo::CODE_TARGET);  } else {    ParameterCount actual(eax);    __ InvokeFunction(edi, actual, CALL_FUNCTION);  }  // Exit the JS frame. Notice that this also removes the empty  // context and the function left on the stack by the code  // invocation.  __ LeaveInternalFrame();  __ ret(1 * kPointerSize);  // remove receiver}void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {  Generate_JSEntryTrampolineHelper(masm, false);}void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {  Generate_JSEntryTrampolineHelper(masm, true);}void Builtins::Generate_FunctionCall(MacroAssembler* masm) {  // 1. Make sure we have at least one argument.  { Label done;    __ test(eax, Operand(eax));    __ j(not_zero, &done, taken);    __ pop(ebx);    __ push(Immediate(Factory::undefined_value()));    __ push(ebx);    __ inc(eax);    __ bind(&done);  }  // 2. Get the function to call from the stack.  { Label done, non_function, function;    // +1 ~ return address.    __ mov(edi, Operand(esp, eax, times_4, +1 * kPointerSize));    __ test(edi, Immediate(kSmiTagMask));    __ j(zero, &non_function, not_taken);    __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));  // get the map    __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));    __ cmp(ecx, JS_FUNCTION_TYPE);    __ j(equal, &function, taken);    // Non-function called: Clear the function to force exception.    __ bind(&non_function);    __ xor_(edi, Operand(edi));    __ jmp(&done);    // Function called: Change context eagerly to get the right global object.    __ bind(&function);    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));    __ bind(&done);  }  // 3. Make sure first argument is an object; convert if necessary.  { Label call_to_object, use_global_receiver, patch_receiver, done;    __ mov(ebx, Operand(esp, eax, times_4, 0));    __ test(ebx, Immediate(kSmiTagMask));    __ j(zero, &call_to_object);    __ cmp(ebx, Factory::null_value());    __ j(equal, &use_global_receiver);    __ cmp(ebx, Factory::undefined_value());    __ j(equal, &use_global_receiver);    __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));    __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));    __ cmp(ecx, FIRST_JS_OBJECT_TYPE);    __ j(less, &call_to_object);    __ cmp(ecx, LAST_JS_OBJECT_TYPE);    __ j(less_equal, &done);    __ bind(&call_to_object);    __ EnterInternalFrame();  // preserves eax, ebx, edi    // Store the arguments count on the stack (smi tagged).    ASSERT(kSmiTag == 0);    __ shl(eax, kSmiTagSize);    __ push(eax);    __ push(edi);  // save edi across the call    __ push(ebx);    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);    __ mov(Operand(ebx), eax);    __ pop(edi);  // restore edi after the call    // Get the arguments count and untag it.    __ pop(eax);    __ shr(eax, kSmiTagSize);    __ LeaveInternalFrame();    __ jmp(&patch_receiver);    // Use the global object from the called function as the receiver.    __ bind(&use_global_receiver);    const int kGlobalIndex =        Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;    __ mov(ebx, FieldOperand(esi, kGlobalIndex));    __ bind(&patch_receiver);    __ mov(Operand(esp, eax, times_4, 0), ebx);    __ bind(&done);  }  // 4. Shift stuff one slot down the stack.  { Label loop;    __ lea(ecx, Operand(eax, +1));  // +1 ~ copy receiver too    __ bind(&loop);    __ mov(ebx, Operand(esp, ecx, times_4, 0));    __ mov(Operand(esp, ecx, times_4, kPointerSize), ebx);    __ dec(ecx);    __ j(not_zero, &loop);  }  // 5. Remove TOS (copy of last arguments), but keep return address.  __ pop(ebx);  __ pop(ecx);  __ push(ebx);  __ dec(eax);  // 6. Check that function really was a function and get the code to  //    call from the function and check that the number of expected  //    arguments matches what we're providing.  { Label invoke;    __ test(edi, Operand(edi));    __ j(not_zero, &invoke, taken);    __ xor_(ebx, Operand(ebx));    __ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);    __ jmp(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),           RelocInfo::CODE_TARGET);    __ bind(&invoke);    __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));    __ mov(ebx,           FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));    __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));    __ lea(edx, FieldOperand(edx, Code::kHeaderSize));    __ cmp(eax, Operand(ebx));    __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));  }  // 7. Jump (tail-call) to the code in register edx without checking arguments.  ParameterCount expected(0);  __ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);}void Builtins::Generate_FunctionApply(MacroAssembler* masm) {  __ EnterInternalFrame();  __ push(Operand(ebp, 4 * kPointerSize));  // push this  __ push(Operand(ebp, 2 * kPointerSize));  // push arguments  __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION);  // Eagerly check for stack-overflow before pushing all the arguments  // to the stack.  Label okay;  __ lea(ecx, Operand(esp, -3 * kPointerSize));  // receiver, limit, index  __ mov(edx, Operand(eax));  __ shl(edx, kPointerSizeLog2 - kSmiTagSize);  __ sub(ecx, Operand(edx));  ExternalReference stack_guard_limit_address =      ExternalReference::address_of_stack_guard_limit();  __ cmp(ecx, Operand::StaticVariable(stack_guard_limit_address));  __ j(greater, &okay, taken);  // Too bad: Out of stack space.  __ push(Operand(ebp, 4 * kPointerSize));  // push this  __ push(eax);  __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION);  __ bind(&okay);  // Push current index and limit.  const int kLimitOffset =      StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;  const int kIndexOffset = kLimitOffset - 1 * kPointerSize;  __ push(eax);  // limit  __ push(Immediate(0));  // index  // Change context eagerly to get the right global object if  // necessary.  __ mov(edi, Operand(ebp, 4 * kPointerSize));  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));  // Compute the receiver.  Label call_to_object, use_global_receiver, push_receiver;  __ mov(ebx, Operand(ebp, 3 * kPointerSize));  __ test(ebx, Immediate(kSmiTagMask));  __ j(zero, &call_to_object);  __ cmp(ebx, Factory::null_value());  __ j(equal, &use_global_receiver);  __ cmp(ebx, Factory::undefined_value());  __ j(equal, &use_global_receiver);  // If given receiver is already a JavaScript object then there's no  // reason for converting it.  __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);  __ j(less, &call_to_object);  __ cmp(ecx, LAST_JS_OBJECT_TYPE);  __ j(less_equal, &push_receiver);  // Convert the receiver to an object.  __ bind(&call_to_object);  __ push(ebx);  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);  __ mov(ebx, Operand(eax));  __ jmp(&push_receiver);  // Use the current global object as the receiver.  __ bind(&use_global_receiver);  const int kGlobalOffset =      Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;  __ mov(ebx, FieldOperand(esi, kGlobalOffset));  // Push the receiver.  __ bind(&push_receiver);  __ push(ebx);  // Copy all arguments from the array to the stack.  Label entry, loop;  __ mov(eax, Operand(ebp, kIndexOffset));  __ jmp(&entry);  __ bind(&loop);  __ mov(ecx, Operand(ebp, 2 * kPointerSize));  // load arguments  __ push(ecx);  __ push(eax);

⌨️ 快捷键说明

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