OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
11 #include "src/x87/frames-x87.h" | 11 #include "src/x87/frames-x87.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
18 | 18 |
19 | 19 |
20 void Builtins::Generate_Adaptor(MacroAssembler* masm, | 20 void Builtins::Generate_Adaptor(MacroAssembler* masm, |
21 CFunctionId id, | 21 CFunctionId id, |
22 BuiltinExtraArguments extra_args) { | 22 BuiltinExtraArguments extra_args) { |
23 // ----------- S t a t e ------------- | 23 // ----------- S t a t e ------------- |
24 // -- eax : number of arguments excluding receiver | 24 // -- eax : number of arguments excluding receiver |
25 // -- edi : called function (only guaranteed when | 25 // -- edi : called function (only guaranteed when |
26 // extra_args requires it) | 26 // extra_args requires it) |
27 // -- esi : context | |
28 // -- esp[0] : return address | 27 // -- esp[0] : return address |
29 // -- esp[4] : last argument | 28 // -- esp[4] : last argument |
30 // -- ... | 29 // -- ... |
31 // -- esp[4 * argc] : first argument (argc == eax) | 30 // -- esp[4 * argc] : first argument (argc == eax) |
32 // -- esp[4 * (argc +1)] : receiver | 31 // -- esp[4 * (argc +1)] : receiver |
33 // ----------------------------------- | 32 // ----------------------------------- |
| 33 __ AssertFunction(edi); |
| 34 |
| 35 // Make sure we operate in the context of the called function (for example |
| 36 // ConstructStubs implemented in C++ will be run in the context of the caller |
| 37 // instead of the callee, due to the way that [[Construct]] is defined for |
| 38 // ordinary functions). |
| 39 // TODO(bmeurer): Can we make this more robust? |
| 40 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
34 | 41 |
35 // Insert extra arguments. | 42 // Insert extra arguments. |
36 int num_extra_args = 0; | 43 int num_extra_args = 0; |
37 if (extra_args == NEEDS_CALLED_FUNCTION) { | 44 if (extra_args == NEEDS_CALLED_FUNCTION) { |
38 num_extra_args = 1; | 45 num_extra_args = 1; |
39 Register scratch = ebx; | 46 Register scratch = ebx; |
40 __ pop(scratch); // Save return address. | 47 __ pop(scratch); // Save return address. |
41 __ push(edi); | 48 __ push(edi); |
42 __ push(scratch); // Restore return address. | 49 __ push(scratch); // Restore return address. |
43 } else { | 50 } else { |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 488 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
482 bool is_construct) { | 489 bool is_construct) { |
483 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 490 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
484 | 491 |
485 // Clear the context before we push it when entering the internal frame. | 492 // Clear the context before we push it when entering the internal frame. |
486 __ Move(esi, Immediate(0)); | 493 __ Move(esi, Immediate(0)); |
487 | 494 |
488 { | 495 { |
489 FrameScope scope(masm, StackFrame::INTERNAL); | 496 FrameScope scope(masm, StackFrame::INTERNAL); |
490 | 497 |
| 498 // Setup the context (we need to use the caller context from the isolate). |
| 499 ExternalReference context_address(Isolate::kContextAddress, |
| 500 masm->isolate()); |
| 501 __ mov(esi, Operand::StaticVariable(context_address)); |
| 502 |
491 // Load the previous frame pointer (ebx) to access C arguments | 503 // Load the previous frame pointer (ebx) to access C arguments |
492 __ mov(ebx, Operand(ebp, 0)); | 504 __ mov(ebx, Operand(ebp, 0)); |
493 | 505 |
494 // Get the function from the frame and setup the context. | |
495 __ mov(ecx, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); | |
496 __ mov(esi, FieldOperand(ecx, JSFunction::kContextOffset)); | |
497 | |
498 // Push the function and the receiver onto the stack. | 506 // Push the function and the receiver onto the stack. |
499 __ push(ecx); | 507 __ push(Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); |
500 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); | 508 __ push(Operand(ebx, EntryFrameConstants::kReceiverArgOffset)); |
501 | 509 |
502 // Load the number of arguments and setup pointer to the arguments. | 510 // Load the number of arguments and setup pointer to the arguments. |
503 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); | 511 __ mov(eax, Operand(ebx, EntryFrameConstants::kArgcOffset)); |
504 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); | 512 __ mov(ebx, Operand(ebx, EntryFrameConstants::kArgvOffset)); |
505 | 513 |
506 // Check if we have enough stack space to push all arguments. | 514 // Check if we have enough stack space to push all arguments. |
507 // The function is the first thing that was pushed above after entering | 515 // The function is the first thing that was pushed above after entering |
508 // the internal frame. | 516 // the internal frame. |
509 const int kFunctionOffset = | 517 const int kFunctionOffset = |
510 InternalFrameConstants::kCodeOffset - kPointerSize; | 518 InternalFrameConstants::kCodeOffset - kPointerSize; |
511 // Expects argument count in eax. Clobbers ecx, edx, edi. | 519 // Expects argument count in eax. Clobbers ecx, edx, edi. |
512 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsUntaggedInt); | 520 Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsUntaggedInt); |
513 | 521 |
514 // Copy arguments to the stack in a loop. | 522 // Copy arguments to the stack in a loop. |
515 Label loop, entry; | 523 Label loop, entry; |
516 __ Move(ecx, Immediate(0)); | 524 __ Move(ecx, Immediate(0)); |
517 __ jmp(&entry); | 525 __ jmp(&entry, Label::kNear); |
518 __ bind(&loop); | 526 __ bind(&loop); |
519 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv | 527 __ mov(edx, Operand(ebx, ecx, times_4, 0)); // push parameter from argv |
520 __ push(Operand(edx, 0)); // dereference handle | 528 __ push(Operand(edx, 0)); // dereference handle |
521 __ inc(ecx); | 529 __ inc(ecx); |
522 __ bind(&entry); | 530 __ bind(&entry); |
523 __ cmp(ecx, eax); | 531 __ cmp(ecx, eax); |
524 __ j(not_equal, &loop); | 532 __ j(not_equal, &loop); |
525 | 533 |
526 // Get the function from the stack and call it. | 534 // Load the previous frame pointer (ebx) to access C arguments |
527 // kPointerSize for the receiver. | 535 __ mov(ebx, Operand(ebp, 0)); |
528 __ mov(edi, Operand(esp, eax, times_4, kPointerSize)); | 536 |
| 537 // Get the new.target and function from the frame. |
| 538 __ mov(edx, Operand(ebx, EntryFrameConstants::kNewTargetArgOffset)); |
| 539 __ mov(edi, Operand(ebx, EntryFrameConstants::kFunctionArgOffset)); |
529 | 540 |
530 // Invoke the code. | 541 // Invoke the code. |
531 if (is_construct) { | 542 Handle<Code> builtin = is_construct |
532 // No type feedback cell is available | 543 ? masm->isolate()->builtins()->Construct() |
533 __ mov(ebx, masm->isolate()->factory()->undefined_value()); | 544 : masm->isolate()->builtins()->Call(); |
534 CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 545 __ Call(builtin, RelocInfo::CODE_TARGET); |
535 __ CallStub(&stub); | |
536 } else { | |
537 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
538 } | |
539 | 546 |
540 // Exit the internal frame. Notice that this also removes the empty. | 547 // Exit the internal frame. Notice that this also removes the empty. |
541 // context and the function left on the stack by the code | 548 // context and the function left on the stack by the code |
542 // invocation. | 549 // invocation. |
543 } | 550 } |
544 __ ret(kPointerSize); // Remove receiver. | 551 __ ret(kPointerSize); // Remove receiver. |
545 } | 552 } |
546 | 553 |
547 | 554 |
548 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 555 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 __ Pop(eax); | 1553 __ Pop(eax); |
1547 __ SmiUntag(eax); | 1554 __ SmiUntag(eax); |
1548 } | 1555 } |
1549 // The delegate is always a regular function. | 1556 // The delegate is always a regular function. |
1550 __ AssertFunction(edi); | 1557 __ AssertFunction(edi); |
1551 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1558 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
1552 } | 1559 } |
1553 | 1560 |
1554 | 1561 |
1555 // static | 1562 // static |
| 1563 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
| 1564 // ----------- S t a t e ------------- |
| 1565 // -- eax : the number of arguments (not including the receiver) |
| 1566 // -- edx : the original constructor (checked to be a JSFunction) |
| 1567 // -- edi : the constructor to call (checked to be a JSFunction) |
| 1568 // ----------------------------------- |
| 1569 __ AssertFunction(edx); |
| 1570 __ AssertFunction(edi); |
| 1571 |
| 1572 // Calling convention for function specific ConstructStubs require |
| 1573 // ebx to contain either an AllocationSite or undefined. |
| 1574 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); |
| 1575 |
| 1576 // Tail call to the function-specific construct stub (still in the caller |
| 1577 // context at this point). |
| 1578 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 1579 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
| 1580 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 1581 __ jmp(ecx); |
| 1582 } |
| 1583 |
| 1584 |
| 1585 // static |
| 1586 void Builtins::Generate_Construct(MacroAssembler* masm) { |
| 1587 // ----------- S t a t e ------------- |
| 1588 // -- eax : the number of arguments (not including the receiver) |
| 1589 // -- edx : the original constructor (either the same as the constructor or |
| 1590 // the JSFunction on which new was invoked initially) |
| 1591 // -- edi : the constructor to call (can be any Object) |
| 1592 // ----------------------------------- |
| 1593 |
| 1594 Label slow; |
| 1595 __ JumpIfSmi(edi, &slow, Label::kNear); |
| 1596 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 1597 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
| 1598 RelocInfo::CODE_TARGET); |
| 1599 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
| 1600 __ j(not_equal, &slow, Label::kNear); |
| 1601 |
| 1602 // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies. |
| 1603 __ mov(edi, FieldOperand(edi, JSFunctionProxy::kConstructTrapOffset)); |
| 1604 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1605 |
| 1606 __ bind(&slow); |
| 1607 { |
| 1608 // Determine the delegate for the target (if any). |
| 1609 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1610 __ SmiTag(eax); |
| 1611 __ Push(eax); |
| 1612 __ Push(edi); |
| 1613 __ CallRuntime(Runtime::kGetConstructorDelegate, 1); |
| 1614 __ mov(edi, eax); |
| 1615 __ Pop(eax); |
| 1616 __ SmiUntag(eax); |
| 1617 } |
| 1618 // The delegate is always a regular function. |
| 1619 __ AssertFunction(edi); |
| 1620 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1621 } |
| 1622 |
| 1623 |
| 1624 // static |
1556 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { | 1625 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { |
1557 // ----------- S t a t e ------------- | 1626 // ----------- S t a t e ------------- |
1558 // -- eax : the number of arguments (not including the receiver) | 1627 // -- eax : the number of arguments (not including the receiver) |
1559 // -- ebx : the address of the first argument to be pushed. Subsequent | 1628 // -- ebx : the address of the first argument to be pushed. Subsequent |
1560 // arguments should be consecutive above this, in the same order as | 1629 // arguments should be consecutive above this, in the same order as |
1561 // they are to be pushed onto the stack. | 1630 // they are to be pushed onto the stack. |
1562 // -- edi : the target to call (can be any Object). | 1631 // -- edi : the target to call (can be any Object). |
1563 | 1632 |
1564 // Pop return address to allow tail-call after pushing arguments. | 1633 // Pop return address to allow tail-call after pushing arguments. |
1565 __ Pop(edx); | 1634 __ Pop(edx); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 | 1837 |
1769 __ bind(&ok); | 1838 __ bind(&ok); |
1770 __ ret(0); | 1839 __ ret(0); |
1771 } | 1840 } |
1772 | 1841 |
1773 #undef __ | 1842 #undef __ |
1774 } // namespace internal | 1843 } // namespace internal |
1775 } // namespace v8 | 1844 } // namespace v8 |
1776 | 1845 |
1777 #endif // V8_TARGET_ARCH_X87 | 1846 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |