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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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" |
(...skipping 1506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 | 1517 |
1518 // Remove caller arguments from the stack. | 1518 // Remove caller arguments from the stack. |
1519 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 1519 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
1520 __ pop(ecx); | 1520 __ pop(ecx); |
1521 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver | 1521 __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver |
1522 __ push(ecx); | 1522 __ push(ecx); |
1523 } | 1523 } |
1524 | 1524 |
1525 | 1525 |
1526 // static | 1526 // static |
1527 void Builtins::Generate_CallFunction(MacroAssembler* masm) { | 1527 void Builtins::Generate_CallFunction(MacroAssembler* masm, |
| 1528 ConvertReceiverMode mode) { |
1528 // ----------- S t a t e ------------- | 1529 // ----------- S t a t e ------------- |
1529 // -- eax : the number of arguments (not including the receiver) | 1530 // -- eax : the number of arguments (not including the receiver) |
1530 // -- edi : the function to call (checked to be a JSFunction) | 1531 // -- edi : the function to call (checked to be a JSFunction) |
1531 // ----------------------------------- | 1532 // ----------------------------------- |
| 1533 __ AssertFunction(edi); |
| 1534 |
1532 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) | 1535 // See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList) |
1533 | 1536 // Check that the function is not a "classConstructor". |
1534 Label convert, convert_global_proxy, convert_to_object, done_convert; | 1537 Label class_constructor; |
1535 __ AssertFunction(edi); | |
1536 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 1538 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1537 | 1539 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), |
1538 { | 1540 SharedFunctionInfo::kClassConstructorBitsWithinByte); |
1539 Label non_class_constructor; | 1541 __ j(not_zero, &class_constructor); |
1540 // Check whether the current function is a classConstructor. | |
1541 __ test_b(FieldOperand(edx, SharedFunctionInfo::kFunctionKindByteOffset), | |
1542 SharedFunctionInfo::kClassConstructorBitsWithinByte); | |
1543 __ j(zero, &non_class_constructor, Label::kNear); | |
1544 // Step: 2, If we call a classConstructor Function throw a TypeError. | |
1545 { | |
1546 FrameScope frame(masm, StackFrame::INTERNAL); | |
1547 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); | |
1548 } | |
1549 __ bind(&non_class_constructor); | |
1550 } | |
1551 | 1542 |
1552 // Enter the context of the function; ToObject has to run in the function | 1543 // Enter the context of the function; ToObject has to run in the function |
1553 // context, and we also need to take the global proxy from the function | 1544 // context, and we also need to take the global proxy from the function |
1554 // context in case of conversion. | 1545 // context in case of conversion. |
1555 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == | 1546 STATIC_ASSERT(SharedFunctionInfo::kNativeByteOffset == |
1556 SharedFunctionInfo::kStrictModeByteOffset); | 1547 SharedFunctionInfo::kStrictModeByteOffset); |
1557 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1548 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
1558 // We need to convert the receiver for non-native sloppy mode functions. | 1549 // We need to convert the receiver for non-native sloppy mode functions. |
| 1550 Label done_convert; |
1559 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), | 1551 __ test_b(FieldOperand(edx, SharedFunctionInfo::kNativeByteOffset), |
1560 (1 << SharedFunctionInfo::kNativeBitWithinByte) | | 1552 (1 << SharedFunctionInfo::kNativeBitWithinByte) | |
1561 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 1553 (1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
1562 __ j(not_zero, &done_convert); | 1554 __ j(not_zero, &done_convert); |
1563 { | 1555 { |
1564 __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize)); | |
1565 | |
1566 // ----------- S t a t e ------------- | 1556 // ----------- S t a t e ------------- |
1567 // -- eax : the number of arguments (not including the receiver) | 1557 // -- eax : the number of arguments (not including the receiver) |
1568 // -- ecx : the receiver | |
1569 // -- edx : the shared function info. | 1558 // -- edx : the shared function info. |
1570 // -- edi : the function to call (checked to be a JSFunction) | 1559 // -- edi : the function to call (checked to be a JSFunction) |
1571 // -- esi : the function context. | 1560 // -- esi : the function context. |
1572 // ----------------------------------- | 1561 // ----------------------------------- |
1573 | 1562 |
1574 Label convert_receiver; | 1563 if (mode == ConvertReceiverMode::kNullOrUndefined) { |
1575 __ JumpIfSmi(ecx, &convert_to_object, Label::kNear); | |
1576 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
1577 __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx); | |
1578 __ j(above_equal, &done_convert); | |
1579 __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, &convert_global_proxy, | |
1580 Label::kNear); | |
1581 __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object, | |
1582 Label::kNear); | |
1583 __ bind(&convert_global_proxy); | |
1584 { | |
1585 // Patch receiver to global proxy. | 1564 // Patch receiver to global proxy. |
1586 __ LoadGlobalProxy(ecx); | 1565 __ LoadGlobalProxy(ecx); |
| 1566 } else { |
| 1567 Label convert_to_object, convert_receiver; |
| 1568 __ mov(ecx, Operand(esp, eax, times_pointer_size, kPointerSize)); |
| 1569 __ JumpIfSmi(ecx, &convert_to_object, Label::kNear); |
| 1570 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); |
| 1571 __ CmpObjectType(ecx, FIRST_JS_RECEIVER_TYPE, ebx); |
| 1572 __ j(above_equal, &done_convert); |
| 1573 if (mode != ConvertReceiverMode::kNotNullOrUndefined) { |
| 1574 Label convert_global_proxy; |
| 1575 __ JumpIfRoot(ecx, Heap::kUndefinedValueRootIndex, |
| 1576 &convert_global_proxy, Label::kNear); |
| 1577 __ JumpIfNotRoot(ecx, Heap::kNullValueRootIndex, &convert_to_object, |
| 1578 Label::kNear); |
| 1579 __ bind(&convert_global_proxy); |
| 1580 { |
| 1581 // Patch receiver to global proxy. |
| 1582 __ LoadGlobalProxy(ecx); |
| 1583 } |
| 1584 __ jmp(&convert_receiver); |
| 1585 } |
| 1586 __ bind(&convert_to_object); |
| 1587 { |
| 1588 // Convert receiver using ToObject. |
| 1589 // TODO(bmeurer): Inline the allocation here to avoid building the frame |
| 1590 // in the fast case? (fall back to AllocateInNewSpace?) |
| 1591 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1592 __ SmiTag(eax); |
| 1593 __ Push(eax); |
| 1594 __ Push(edi); |
| 1595 __ mov(eax, ecx); |
| 1596 ToObjectStub stub(masm->isolate()); |
| 1597 __ CallStub(&stub); |
| 1598 __ mov(ecx, eax); |
| 1599 __ Pop(edi); |
| 1600 __ Pop(eax); |
| 1601 __ SmiUntag(eax); |
| 1602 } |
| 1603 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 1604 __ bind(&convert_receiver); |
1587 } | 1605 } |
1588 __ jmp(&convert_receiver); | |
1589 __ bind(&convert_to_object); | |
1590 { | |
1591 // Convert receiver using ToObject. | |
1592 // TODO(bmeurer): Inline the allocation here to avoid building the frame | |
1593 // in the fast case? (fall back to AllocateInNewSpace?) | |
1594 FrameScope scope(masm, StackFrame::INTERNAL); | |
1595 __ SmiTag(eax); | |
1596 __ Push(eax); | |
1597 __ Push(edi); | |
1598 __ mov(eax, ecx); | |
1599 ToObjectStub stub(masm->isolate()); | |
1600 __ CallStub(&stub); | |
1601 __ mov(ecx, eax); | |
1602 __ Pop(edi); | |
1603 __ Pop(eax); | |
1604 __ SmiUntag(eax); | |
1605 } | |
1606 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
1607 __ bind(&convert_receiver); | |
1608 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx); | 1606 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), ecx); |
1609 } | 1607 } |
1610 __ bind(&done_convert); | 1608 __ bind(&done_convert); |
1611 | 1609 |
1612 // ----------- S t a t e ------------- | 1610 // ----------- S t a t e ------------- |
1613 // -- eax : the number of arguments (not including the receiver) | 1611 // -- eax : the number of arguments (not including the receiver) |
1614 // -- edx : the shared function info. | 1612 // -- edx : the shared function info. |
1615 // -- edi : the function to call (checked to be a JSFunction) | 1613 // -- edi : the function to call (checked to be a JSFunction) |
1616 // -- esi : the function context. | 1614 // -- esi : the function context. |
1617 // ----------------------------------- | 1615 // ----------------------------------- |
1618 | 1616 |
1619 __ mov(ebx, | 1617 __ mov(ebx, |
1620 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 1618 FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
1621 __ SmiUntag(ebx); | 1619 __ SmiUntag(ebx); |
1622 ParameterCount actual(eax); | 1620 ParameterCount actual(eax); |
1623 ParameterCount expected(ebx); | 1621 ParameterCount expected(ebx); |
1624 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), expected, | 1622 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), expected, |
1625 actual, JUMP_FUNCTION, NullCallWrapper()); | 1623 actual, JUMP_FUNCTION, NullCallWrapper()); |
| 1624 |
| 1625 // The function is a "classConstructor", need to raise an exception. |
| 1626 __ bind(&class_constructor); |
| 1627 { |
| 1628 FrameScope frame(masm, StackFrame::INTERNAL); |
| 1629 __ CallRuntime(Runtime::kThrowConstructorNonCallableError, 0); |
| 1630 } |
1626 } | 1631 } |
1627 | 1632 |
1628 | 1633 |
1629 // static | 1634 // static |
1630 void Builtins::Generate_Call(MacroAssembler* masm) { | 1635 void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { |
1631 // ----------- S t a t e ------------- | 1636 // ----------- S t a t e ------------- |
1632 // -- eax : the number of arguments (not including the receiver) | 1637 // -- eax : the number of arguments (not including the receiver) |
1633 // -- edi : the target to call (can be any Object). | 1638 // -- edi : the target to call (can be any Object). |
1634 // ----------------------------------- | 1639 // ----------------------------------- |
1635 | 1640 |
1636 Label non_callable, non_function, non_smi; | 1641 Label non_callable, non_function, non_smi; |
1637 __ JumpIfSmi(edi, &non_callable); | 1642 __ JumpIfSmi(edi, &non_callable); |
1638 __ bind(&non_smi); | 1643 __ bind(&non_smi); |
1639 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 1644 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
1640 __ j(equal, masm->isolate()->builtins()->CallFunction(), | 1645 __ j(equal, masm->isolate()->builtins()->CallFunction(mode), |
1641 RelocInfo::CODE_TARGET); | 1646 RelocInfo::CODE_TARGET); |
1642 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); | 1647 __ CmpInstanceType(ecx, JS_FUNCTION_PROXY_TYPE); |
1643 __ j(not_equal, &non_function); | 1648 __ j(not_equal, &non_function); |
1644 | 1649 |
1645 // 1. Call to function proxy. | 1650 // 1. Call to function proxy. |
1646 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. | 1651 // TODO(neis): This doesn't match the ES6 spec for [[Call]] on proxies. |
1647 __ mov(edi, FieldOperand(edi, JSFunctionProxy::kCallTrapOffset)); | 1652 __ mov(edi, FieldOperand(edi, JSFunctionProxy::kCallTrapOffset)); |
1648 __ AssertNotSmi(edi); | 1653 __ AssertNotSmi(edi); |
1649 __ jmp(&non_smi); | 1654 __ jmp(&non_smi); |
1650 | 1655 |
1651 // 2. Call to something else, which might have a [[Call]] internal method (if | 1656 // 2. Call to something else, which might have a [[Call]] internal method (if |
1652 // not we raise an exception). | 1657 // not we raise an exception). |
1653 __ bind(&non_function); | 1658 __ bind(&non_function); |
1654 // Check if target has a [[Call]] internal method. | 1659 // Check if target has a [[Call]] internal method. |
1655 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); | 1660 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), 1 << Map::kIsCallable); |
1656 __ j(zero, &non_callable, Label::kNear); | 1661 __ j(zero, &non_callable, Label::kNear); |
1657 // Overwrite the original receiver with the (original) target. | 1662 // Overwrite the original receiver with the (original) target. |
1658 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | 1663 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |
1659 // Let the "call_as_function_delegate" take care of the rest. | 1664 // Let the "call_as_function_delegate" take care of the rest. |
1660 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi); | 1665 __ LoadGlobalFunction(Context::CALL_AS_FUNCTION_DELEGATE_INDEX, edi); |
1661 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1666 __ Jump(masm->isolate()->builtins()->CallFunction( |
| 1667 ConvertReceiverMode::kNotNullOrUndefined), |
| 1668 RelocInfo::CODE_TARGET); |
1662 | 1669 |
1663 // 3. Call to something that is not callable. | 1670 // 3. Call to something that is not callable. |
1664 __ bind(&non_callable); | 1671 __ bind(&non_callable); |
1665 { | 1672 { |
1666 FrameScope scope(masm, StackFrame::INTERNAL); | 1673 FrameScope scope(masm, StackFrame::INTERNAL); |
1667 __ Push(edi); | 1674 __ Push(edi); |
1668 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); | 1675 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); |
1669 } | 1676 } |
1670 } | 1677 } |
1671 | 1678 |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1934 | 1941 |
1935 __ bind(&ok); | 1942 __ bind(&ok); |
1936 __ ret(0); | 1943 __ ret(0); |
1937 } | 1944 } |
1938 | 1945 |
1939 #undef __ | 1946 #undef __ |
1940 } // namespace internal | 1947 } // namespace internal |
1941 } // namespace v8 | 1948 } // namespace v8 |
1942 | 1949 |
1943 #endif // V8_TARGET_ARCH_IA32 | 1950 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |