| 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 |