| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #if V8_TARGET_ARCH_IA32 |
| |
| #include "src/api-arguments-inl.h" |
| #include "src/assembler-inl.h" |
| #include "src/base/bits.h" |
| #include "src/bootstrapper.h" |
| #include "src/code-stubs.h" |
| #include "src/frame-constants.h" |
| #include "src/frames.h" |
| #include "src/ic/ic.h" |
| #include "src/ic/stub-cache.h" |
| #include "src/isolate.h" |
| #include "src/macro-assembler.h" |
| #include "src/objects/api-callbacks.h" |
| #include "src/regexp/jsregexp.h" |
| #include "src/regexp/regexp-macro-assembler.h" |
| #include "src/runtime/runtime.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| #define __ ACCESS_MASM(masm) |
| |
| // Called with the native C calling convention. The corresponding function |
| // signature is: |
| // |
| // using JSEntryFunction = GeneratedCode<Object*( |
| // Object * new_target, Object * target, Object * receiver, int argc, |
| // Object*** args, Address root_register_value)>; |
| void JSEntryStub::Generate(MacroAssembler* masm) { |
| Label invoke, handler_entry, exit; |
| Label not_outermost_js, not_outermost_js_2; |
| |
| { // NOLINT. Scope block confuses linter. |
| NoRootArrayScope uninitialized_root_register(masm); |
| |
| // Set up frame. |
| __ push(ebp); |
| __ mov(ebp, esp); |
| |
| // Push marker in two places. |
| StackFrame::Type marker = type(); |
| __ push(Immediate(StackFrame::TypeToMarker(marker))); // marker |
| ExternalReference context_address = |
| ExternalReference::Create(IsolateAddressId::kContextAddress, isolate()); |
| __ push(Operand(context_address.address(), |
| RelocInfo::EXTERNAL_REFERENCE)); // context |
| // Save callee-saved registers (C calling conventions). |
| __ push(edi); |
| __ push(esi); |
| __ push(ebx); |
| |
| // Initialize the root register based on the given Isolate* argument. |
| // C calling convention. The sixth argument is passed on the stack. |
| __ mov(kRootRegister, |
| Operand(ebp, EntryFrameConstants::kRootRegisterValueOffset)); |
| } |
| |
| // Save copies of the top frame descriptor on the stack. |
| ExternalReference c_entry_fp = |
| ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate()); |
| __ push(__ ExternalReferenceAsOperand(c_entry_fp, edi)); |
| |
| // If this is the outermost JS call, set js_entry_sp value. |
| ExternalReference js_entry_sp = |
| ExternalReference::Create(IsolateAddressId::kJSEntrySPAddress, isolate()); |
| __ cmp(__ ExternalReferenceAsOperand(js_entry_sp, edi), Immediate(0)); |
| __ j(not_equal, ¬_outermost_js, Label::kNear); |
| __ mov(__ ExternalReferenceAsOperand(js_entry_sp, edi), ebp); |
| __ push(Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME)); |
| __ jmp(&invoke, Label::kNear); |
| __ bind(¬_outermost_js); |
| __ push(Immediate(StackFrame::INNER_JSENTRY_FRAME)); |
| |
| // Jump to a faked try block that does the invoke, with a faked catch |
| // block that sets the pending exception. |
| __ jmp(&invoke); |
| __ bind(&handler_entry); |
| handler_offset_ = handler_entry.pos(); |
| // Caught exception: Store result (exception) in the pending exception |
| // field in the JSEnv and return a failure sentinel. |
| ExternalReference pending_exception = ExternalReference::Create( |
| IsolateAddressId::kPendingExceptionAddress, isolate()); |
| __ mov(__ ExternalReferenceAsOperand(pending_exception, edi), eax); |
| __ mov(eax, Immediate(isolate()->factory()->exception())); |
| __ jmp(&exit); |
| |
| // Invoke: Link this frame into the handler chain. |
| __ bind(&invoke); |
| __ PushStackHandler(edi); |
| |
| // Invoke the function by calling through JS entry trampoline builtin and |
| // pop the faked function when we return. Notice that we cannot store a |
| // reference to the trampoline code directly in this stub, because the |
| // builtin stubs may not have been generated yet. |
| __ Call(EntryTrampoline(), RelocInfo::CODE_TARGET); |
| |
| // Unlink this frame from the handler chain. |
| __ PopStackHandler(edi); |
| |
| __ bind(&exit); |
| |
| // Check if the current stack frame is marked as the outermost JS frame. |
| __ pop(edi); |
| __ cmp(edi, Immediate(StackFrame::OUTERMOST_JSENTRY_FRAME)); |
| __ j(not_equal, ¬_outermost_js_2); |
| __ mov(__ ExternalReferenceAsOperand(js_entry_sp, edi), Immediate(0)); |
| __ bind(¬_outermost_js_2); |
| |
| // Restore the top frame descriptor from the stack. |
| __ pop(__ ExternalReferenceAsOperand(c_entry_fp, edi)); |
| |
| // Restore callee-saved registers (C calling conventions). |
| __ pop(ebx); |
| __ pop(esi); |
| __ pop(edi); |
| __ add(esp, Immediate(2 * kPointerSize)); // remove markers |
| |
| // Restore frame pointer and return. |
| __ pop(ebp); |
| __ ret(0); |
| } |
| |
| #undef __ |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_TARGET_ARCH_IA32 |