OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 VisitForValue(function, kAccumulator); | 618 VisitForValue(function, kAccumulator); |
619 __ pop(rcx); | 619 __ pop(rcx); |
620 } else { | 620 } else { |
621 VisitForValue(prop->key(), kAccumulator); | 621 VisitForValue(prop->key(), kAccumulator); |
622 __ movq(rcx, result_register()); | 622 __ movq(rcx, result_register()); |
623 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); | 623 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); |
624 } | 624 } |
625 __ pop(rdx); | 625 __ pop(rdx); |
626 | 626 |
627 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 627 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
628 __ call(ic, RelocInfo::CODE_TARGET); | 628 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
629 // Absence of a test rax instruction following the call | |
630 // indicates that none of the load was inlined. | |
631 __ nop(); | |
632 } | 629 } |
633 } | 630 } |
634 } | 631 } |
635 | 632 |
636 | 633 |
637 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 634 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
638 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 635 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
639 } | 636 } |
640 | 637 |
641 | 638 |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 } | 931 } |
935 | 932 |
936 // All extension objects were empty and it is safe to use a global | 933 // All extension objects were empty and it is safe to use a global |
937 // load IC call. | 934 // load IC call. |
938 __ movq(rax, CodeGenerator::GlobalObject()); | 935 __ movq(rax, CodeGenerator::GlobalObject()); |
939 __ Move(rcx, slot->var()->name()); | 936 __ Move(rcx, slot->var()->name()); |
940 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 937 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
941 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 938 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
942 ? RelocInfo::CODE_TARGET | 939 ? RelocInfo::CODE_TARGET |
943 : RelocInfo::CODE_TARGET_CONTEXT; | 940 : RelocInfo::CODE_TARGET_CONTEXT; |
944 __ call(ic, mode); | 941 EmitCallIC(ic, mode); |
945 __ nop(); // Signal no inlined code. | |
946 } | 942 } |
947 | 943 |
948 | 944 |
949 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 945 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
950 Slot* slot, | 946 Slot* slot, |
951 Label* slow) { | 947 Label* slow) { |
952 ASSERT(slot->type() == Slot::CONTEXT); | 948 ASSERT(slot->type() == Slot::CONTEXT); |
953 Register context = rsi; | 949 Register context = rsi; |
954 Register temp = rbx; | 950 Register temp = rbx; |
955 | 951 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1012 obj_proxy->IsArguments() && | 1008 obj_proxy->IsArguments() && |
1013 key_literal->handle()->IsSmi()) { | 1009 key_literal->handle()->IsSmi()) { |
1014 // Load arguments object if there are no eval-introduced | 1010 // Load arguments object if there are no eval-introduced |
1015 // variables. Then load the argument from the arguments | 1011 // variables. Then load the argument from the arguments |
1016 // object using keyed load. | 1012 // object using keyed load. |
1017 __ movq(rdx, | 1013 __ movq(rdx, |
1018 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 1014 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), |
1019 slow)); | 1015 slow)); |
1020 __ Move(rax, key_literal->handle()); | 1016 __ Move(rax, key_literal->handle()); |
1021 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1017 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1022 __ call(ic, RelocInfo::CODE_TARGET); | 1018 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1023 __ jmp(done); | 1019 __ jmp(done); |
1024 } | 1020 } |
1025 } | 1021 } |
1026 } | 1022 } |
1027 } | 1023 } |
1028 } | 1024 } |
1029 | 1025 |
1030 | 1026 |
1031 void FullCodeGenerator::EmitVariableLoad(Variable* var, | 1027 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
1032 Expression::Context context) { | 1028 Expression::Context context) { |
1033 // Four cases: non-this global variables, lookup slots, all other | 1029 // Four cases: non-this global variables, lookup slots, all other |
1034 // types of slots, and parameters that rewrite to explicit property | 1030 // types of slots, and parameters that rewrite to explicit property |
1035 // accesses on the arguments object. | 1031 // accesses on the arguments object. |
1036 Slot* slot = var->slot(); | 1032 Slot* slot = var->slot(); |
1037 Property* property = var->AsProperty(); | 1033 Property* property = var->AsProperty(); |
1038 | 1034 |
1039 if (var->is_global() && !var->is_this()) { | 1035 if (var->is_global() && !var->is_this()) { |
1040 Comment cmnt(masm_, "Global variable"); | 1036 Comment cmnt(masm_, "Global variable"); |
1041 // Use inline caching. Variable name is passed in rcx and the global | 1037 // Use inline caching. Variable name is passed in rcx and the global |
1042 // object on the stack. | 1038 // object on the stack. |
1043 __ Move(rcx, var->name()); | 1039 __ Move(rcx, var->name()); |
1044 __ movq(rax, CodeGenerator::GlobalObject()); | 1040 __ movq(rax, CodeGenerator::GlobalObject()); |
1045 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1041 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1046 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1042 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1047 // A test rax instruction following the call is used by the IC to | |
1048 // indicate that the inobject property case was inlined. Ensure there | |
1049 // is no test rax instruction here. | |
1050 __ nop(); | |
1051 Apply(context, rax); | 1043 Apply(context, rax); |
1052 | 1044 |
1053 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1045 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1054 Label done, slow; | 1046 Label done, slow; |
1055 | 1047 |
1056 // Generate code for loading from variables potentially shadowed | 1048 // Generate code for loading from variables potentially shadowed |
1057 // by eval-introduced variables. | 1049 // by eval-introduced variables. |
1058 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1050 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1059 | 1051 |
1060 __ bind(&slow); | 1052 __ bind(&slow); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 // Assert that the key is a smi. | 1095 // Assert that the key is a smi. |
1104 Literal* key_literal = property->key()->AsLiteral(); | 1096 Literal* key_literal = property->key()->AsLiteral(); |
1105 ASSERT_NOT_NULL(key_literal); | 1097 ASSERT_NOT_NULL(key_literal); |
1106 ASSERT(key_literal->handle()->IsSmi()); | 1098 ASSERT(key_literal->handle()->IsSmi()); |
1107 | 1099 |
1108 // Load the key. | 1100 // Load the key. |
1109 __ Move(rax, key_literal->handle()); | 1101 __ Move(rax, key_literal->handle()); |
1110 | 1102 |
1111 // Do a keyed property load. | 1103 // Do a keyed property load. |
1112 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1104 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1113 __ call(ic, RelocInfo::CODE_TARGET); | 1105 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1114 // Notice: We must not have a "test rax, ..." instruction after the | |
1115 // call. It is treated specially by the LoadIC code. | |
1116 __ nop(); | |
1117 Apply(context, rax); | 1106 Apply(context, rax); |
1118 } | 1107 } |
1119 } | 1108 } |
1120 | 1109 |
1121 | 1110 |
1122 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1111 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1123 Comment cmnt(masm_, "[ RegExpLiteral"); | 1112 Comment cmnt(masm_, "[ RegExpLiteral"); |
1124 Label materialized; | 1113 Label materialized; |
1125 // Registers will be used as follows: | 1114 // Registers will be used as follows: |
1126 // rdi = JS function. | 1115 // rdi = JS function. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 UNREACHABLE(); | 1194 UNREACHABLE(); |
1206 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1195 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1207 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1196 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1208 // Fall through. | 1197 // Fall through. |
1209 case ObjectLiteral::Property::COMPUTED: | 1198 case ObjectLiteral::Property::COMPUTED: |
1210 if (key->handle()->IsSymbol()) { | 1199 if (key->handle()->IsSymbol()) { |
1211 VisitForValue(value, kAccumulator); | 1200 VisitForValue(value, kAccumulator); |
1212 __ Move(rcx, key->handle()); | 1201 __ Move(rcx, key->handle()); |
1213 __ movq(rdx, Operand(rsp, 0)); | 1202 __ movq(rdx, Operand(rsp, 0)); |
1214 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1203 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1215 __ call(ic, RelocInfo::CODE_TARGET); | 1204 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1216 __ nop(); | |
1217 break; | 1205 break; |
1218 } | 1206 } |
1219 // Fall through. | 1207 // Fall through. |
1220 case ObjectLiteral::Property::PROTOTYPE: | 1208 case ObjectLiteral::Property::PROTOTYPE: |
1221 __ push(Operand(rsp, 0)); // Duplicate receiver. | 1209 __ push(Operand(rsp, 0)); // Duplicate receiver. |
1222 VisitForValue(key, kStack); | 1210 VisitForValue(key, kStack); |
1223 VisitForValue(value, kStack); | 1211 VisitForValue(value, kStack); |
1224 __ CallRuntime(Runtime::kSetProperty, 3); | 1212 __ CallRuntime(Runtime::kSetProperty, 3); |
1225 break; | 1213 break; |
1226 case ObjectLiteral::Property::SETTER: | 1214 case ObjectLiteral::Property::SETTER: |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1418 break; | 1406 break; |
1419 } | 1407 } |
1420 } | 1408 } |
1421 | 1409 |
1422 | 1410 |
1423 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1411 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1424 SetSourcePosition(prop->position()); | 1412 SetSourcePosition(prop->position()); |
1425 Literal* key = prop->key()->AsLiteral(); | 1413 Literal* key = prop->key()->AsLiteral(); |
1426 __ Move(rcx, key->handle()); | 1414 __ Move(rcx, key->handle()); |
1427 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1415 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1428 __ Call(ic, RelocInfo::CODE_TARGET); | 1416 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1429 __ nop(); | |
1430 } | 1417 } |
1431 | 1418 |
1432 | 1419 |
1433 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1420 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1434 SetSourcePosition(prop->position()); | 1421 SetSourcePosition(prop->position()); |
1435 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1422 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1436 __ Call(ic, RelocInfo::CODE_TARGET); | 1423 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1437 __ nop(); | |
1438 } | 1424 } |
1439 | 1425 |
1440 | 1426 |
1441 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1427 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
1442 Token::Value op, | 1428 Token::Value op, |
1443 Expression::Context context, | 1429 Expression::Context context, |
1444 OverwriteMode mode, | 1430 OverwriteMode mode, |
1445 Expression* left, | 1431 Expression* left, |
1446 Expression* right, | 1432 Expression* right, |
1447 ConstantOperand constant) { | 1433 ConstantOperand constant) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); | 1532 EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); |
1547 break; | 1533 break; |
1548 } | 1534 } |
1549 case NAMED_PROPERTY: { | 1535 case NAMED_PROPERTY: { |
1550 __ push(rax); // Preserve value. | 1536 __ push(rax); // Preserve value. |
1551 VisitForValue(prop->obj(), kAccumulator); | 1537 VisitForValue(prop->obj(), kAccumulator); |
1552 __ movq(rdx, rax); | 1538 __ movq(rdx, rax); |
1553 __ pop(rax); // Restore value. | 1539 __ pop(rax); // Restore value. |
1554 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1540 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1555 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1541 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1556 __ call(ic, RelocInfo::CODE_TARGET); | 1542 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1557 __ nop(); // Signal no inlined code. | |
1558 break; | 1543 break; |
1559 } | 1544 } |
1560 case KEYED_PROPERTY: { | 1545 case KEYED_PROPERTY: { |
1561 __ push(rax); // Preserve value. | 1546 __ push(rax); // Preserve value. |
1562 VisitForValue(prop->obj(), kStack); | 1547 VisitForValue(prop->obj(), kStack); |
1563 VisitForValue(prop->key(), kAccumulator); | 1548 VisitForValue(prop->key(), kAccumulator); |
1564 __ movq(rcx, rax); | 1549 __ movq(rcx, rax); |
1565 __ pop(rdx); | 1550 __ pop(rdx); |
1566 __ pop(rax); | 1551 __ pop(rax); |
1567 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1552 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1568 __ call(ic, RelocInfo::CODE_TARGET); | 1553 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1569 __ nop(); // Signal no inlined code. | |
1570 break; | 1554 break; |
1571 } | 1555 } |
1572 } | 1556 } |
1573 } | 1557 } |
1574 | 1558 |
1575 | 1559 |
1576 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1560 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1577 Token::Value op, | 1561 Token::Value op, |
1578 Expression::Context context) { | 1562 Expression::Context context) { |
1579 // Left-hand sides that rewrite to explicit property accesses do not reach | 1563 // Left-hand sides that rewrite to explicit property accesses do not reach |
1580 // here. | 1564 // here. |
1581 ASSERT(var != NULL); | 1565 ASSERT(var != NULL); |
1582 ASSERT(var->is_global() || var->slot() != NULL); | 1566 ASSERT(var->is_global() || var->slot() != NULL); |
1583 | 1567 |
1584 if (var->is_global()) { | 1568 if (var->is_global()) { |
1585 ASSERT(!var->is_this()); | 1569 ASSERT(!var->is_this()); |
1586 // Assignment to a global variable. Use inline caching for the | 1570 // Assignment to a global variable. Use inline caching for the |
1587 // assignment. Right-hand-side value is passed in rax, variable name in | 1571 // assignment. Right-hand-side value is passed in rax, variable name in |
1588 // rcx, and the global object on the stack. | 1572 // rcx, and the global object on the stack. |
1589 __ Move(rcx, var->name()); | 1573 __ Move(rcx, var->name()); |
1590 __ movq(rdx, CodeGenerator::GlobalObject()); | 1574 __ movq(rdx, CodeGenerator::GlobalObject()); |
1591 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1575 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1592 __ Call(ic, RelocInfo::CODE_TARGET); | 1576 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1593 __ nop(); | |
1594 | 1577 |
1595 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { | 1578 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
1596 // Perform the assignment for non-const variables and for initialization | 1579 // Perform the assignment for non-const variables and for initialization |
1597 // of const variables. Const assignments are simply skipped. | 1580 // of const variables. Const assignments are simply skipped. |
1598 Label done; | 1581 Label done; |
1599 Slot* slot = var->slot(); | 1582 Slot* slot = var->slot(); |
1600 switch (slot->type()) { | 1583 switch (slot->type()) { |
1601 case Slot::PARAMETER: | 1584 case Slot::PARAMETER: |
1602 case Slot::LOCAL: | 1585 case Slot::LOCAL: |
1603 if (op == Token::INIT_CONST) { | 1586 if (op == Token::INIT_CONST) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1650 |
1668 // Record source code position before IC call. | 1651 // Record source code position before IC call. |
1669 SetSourcePosition(expr->position()); | 1652 SetSourcePosition(expr->position()); |
1670 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 1653 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
1671 if (expr->ends_initialization_block()) { | 1654 if (expr->ends_initialization_block()) { |
1672 __ movq(rdx, Operand(rsp, 0)); | 1655 __ movq(rdx, Operand(rsp, 0)); |
1673 } else { | 1656 } else { |
1674 __ pop(rdx); | 1657 __ pop(rdx); |
1675 } | 1658 } |
1676 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1659 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1677 __ Call(ic, RelocInfo::CODE_TARGET); | 1660 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1678 __ nop(); | |
1679 | 1661 |
1680 // If the assignment ends an initialization block, revert to fast case. | 1662 // If the assignment ends an initialization block, revert to fast case. |
1681 if (expr->ends_initialization_block()) { | 1663 if (expr->ends_initialization_block()) { |
1682 __ push(rax); // Result of assignment, saved even if not needed. | 1664 __ push(rax); // Result of assignment, saved even if not needed. |
1683 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. | 1665 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. |
1684 __ CallRuntime(Runtime::kToFastProperties, 1); | 1666 __ CallRuntime(Runtime::kToFastProperties, 1); |
1685 __ pop(rax); | 1667 __ pop(rax); |
1686 DropAndApply(1, context_, rax); | 1668 DropAndApply(1, context_, rax); |
1687 } else { | 1669 } else { |
1688 Apply(context_, rax); | 1670 Apply(context_, rax); |
(...skipping 17 matching lines...) Expand all Loading... |
1706 | 1688 |
1707 __ pop(rcx); | 1689 __ pop(rcx); |
1708 if (expr->ends_initialization_block()) { | 1690 if (expr->ends_initialization_block()) { |
1709 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. | 1691 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on the stack for later. |
1710 } else { | 1692 } else { |
1711 __ pop(rdx); | 1693 __ pop(rdx); |
1712 } | 1694 } |
1713 // Record source code position before IC call. | 1695 // Record source code position before IC call. |
1714 SetSourcePosition(expr->position()); | 1696 SetSourcePosition(expr->position()); |
1715 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1697 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1716 __ Call(ic, RelocInfo::CODE_TARGET); | 1698 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1717 // This nop signals to the IC that there is no inlined code at the call | |
1718 // site for it to patch. | |
1719 __ nop(); | |
1720 | 1699 |
1721 // If the assignment ends an initialization block, revert to fast case. | 1700 // If the assignment ends an initialization block, revert to fast case. |
1722 if (expr->ends_initialization_block()) { | 1701 if (expr->ends_initialization_block()) { |
1723 __ pop(rdx); | 1702 __ pop(rdx); |
1724 __ push(rax); // Result of assignment, saved even if not needed. | 1703 __ push(rax); // Result of assignment, saved even if not needed. |
1725 __ push(rdx); | 1704 __ push(rdx); |
1726 __ CallRuntime(Runtime::kToFastProperties, 1); | 1705 __ CallRuntime(Runtime::kToFastProperties, 1); |
1727 __ pop(rax); | 1706 __ pop(rax); |
1728 } | 1707 } |
1729 | 1708 |
(...skipping 28 matching lines...) Expand all Loading... |
1758 for (int i = 0; i < arg_count; i++) { | 1737 for (int i = 0; i < arg_count; i++) { |
1759 VisitForValue(args->at(i), kStack); | 1738 VisitForValue(args->at(i), kStack); |
1760 } | 1739 } |
1761 __ Move(rcx, name); | 1740 __ Move(rcx, name); |
1762 // Record source position for debugger. | 1741 // Record source position for debugger. |
1763 SetSourcePosition(expr->position()); | 1742 SetSourcePosition(expr->position()); |
1764 // Call the IC initialization code. | 1743 // Call the IC initialization code. |
1765 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1744 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1766 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1745 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1767 in_loop); | 1746 in_loop); |
1768 __ Call(ic, mode); | 1747 EmitCallIC(ic, mode); |
1769 // Restore context register. | 1748 // Restore context register. |
1770 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1749 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1771 Apply(context_, rax); | 1750 Apply(context_, rax); |
1772 } | 1751 } |
1773 | 1752 |
1774 | 1753 |
1775 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 1754 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
1776 Expression* key, | 1755 Expression* key, |
1777 RelocInfo::Mode mode) { | 1756 RelocInfo::Mode mode) { |
1778 // Code common for calls using the IC. | 1757 // Code common for calls using the IC. |
1779 ZoneList<Expression*>* args = expr->arguments(); | 1758 ZoneList<Expression*>* args = expr->arguments(); |
1780 int arg_count = args->length(); | 1759 int arg_count = args->length(); |
1781 for (int i = 0; i < arg_count; i++) { | 1760 for (int i = 0; i < arg_count; i++) { |
1782 VisitForValue(args->at(i), kStack); | 1761 VisitForValue(args->at(i), kStack); |
1783 } | 1762 } |
1784 VisitForValue(key, kAccumulator); | 1763 VisitForValue(key, kAccumulator); |
1785 __ movq(rcx, rax); | 1764 __ movq(rcx, rax); |
1786 // Record source position for debugger. | 1765 // Record source position for debugger. |
1787 SetSourcePosition(expr->position()); | 1766 SetSourcePosition(expr->position()); |
1788 // Call the IC initialization code. | 1767 // Call the IC initialization code. |
1789 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1768 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1790 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, | 1769 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, |
1791 in_loop); | 1770 in_loop); |
1792 __ Call(ic, mode); | 1771 EmitCallIC(ic, mode); |
1793 // Restore context register. | 1772 // Restore context register. |
1794 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1773 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1795 Apply(context_, rax); | 1774 Apply(context_, rax); |
1796 } | 1775 } |
1797 | 1776 |
1798 | 1777 |
1799 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 1778 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1800 // Code common for calls using the call stub. | 1779 // Code common for calls using the call stub. |
1801 ZoneList<Expression*>* args = expr->arguments(); | 1780 ZoneList<Expression*>* args = expr->arguments(); |
1802 int arg_count = args->length(); | 1781 int arg_count = args->length(); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1917 // Call to a keyed property. | 1896 // Call to a keyed property. |
1918 // For a synthetic property use keyed load IC followed by function call, | 1897 // For a synthetic property use keyed load IC followed by function call, |
1919 // for a regular property use KeyedCallIC. | 1898 // for a regular property use KeyedCallIC. |
1920 VisitForValue(prop->obj(), kStack); | 1899 VisitForValue(prop->obj(), kStack); |
1921 if (prop->is_synthetic()) { | 1900 if (prop->is_synthetic()) { |
1922 VisitForValue(prop->key(), kAccumulator); | 1901 VisitForValue(prop->key(), kAccumulator); |
1923 __ movq(rdx, Operand(rsp, 0)); | 1902 __ movq(rdx, Operand(rsp, 0)); |
1924 // Record source code position for IC call. | 1903 // Record source code position for IC call. |
1925 SetSourcePosition(prop->position()); | 1904 SetSourcePosition(prop->position()); |
1926 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1905 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1927 __ call(ic, RelocInfo::CODE_TARGET); | 1906 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1928 // By emitting a nop we make sure that we do not have a "test rax,..." | |
1929 // instruction after the call as it is treated specially | |
1930 // by the LoadIC code. | |
1931 __ nop(); | |
1932 // Pop receiver. | 1907 // Pop receiver. |
1933 __ pop(rbx); | 1908 __ pop(rbx); |
1934 // Push result (function). | 1909 // Push result (function). |
1935 __ push(rax); | 1910 __ push(rax); |
1936 // Push receiver object on stack. | 1911 // Push receiver object on stack. |
1937 __ movq(rcx, CodeGenerator::GlobalObject()); | 1912 __ movq(rcx, CodeGenerator::GlobalObject()); |
1938 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 1913 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
1939 EmitCallWithStub(expr); | 1914 EmitCallWithStub(expr); |
1940 } else { | 1915 } else { |
1941 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 1916 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2834 int arg_count = args->length(); | 2809 int arg_count = args->length(); |
2835 for (int i = 0; i < arg_count; i++) { | 2810 for (int i = 0; i < arg_count; i++) { |
2836 VisitForValue(args->at(i), kStack); | 2811 VisitForValue(args->at(i), kStack); |
2837 } | 2812 } |
2838 | 2813 |
2839 if (expr->is_jsruntime()) { | 2814 if (expr->is_jsruntime()) { |
2840 // Call the JS runtime function using a call IC. | 2815 // Call the JS runtime function using a call IC. |
2841 __ Move(rcx, expr->name()); | 2816 __ Move(rcx, expr->name()); |
2842 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2817 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2843 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 2818 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
2844 __ call(ic, RelocInfo::CODE_TARGET); | 2819 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2845 // Restore context register. | 2820 // Restore context register. |
2846 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2821 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
2847 } else { | 2822 } else { |
2848 __ CallRuntime(expr->function(), arg_count); | 2823 __ CallRuntime(expr->function(), arg_count); |
2849 } | 2824 } |
2850 Apply(context_, rax); | 2825 Apply(context_, rax); |
2851 } | 2826 } |
2852 | 2827 |
2853 | 2828 |
2854 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 2829 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3132 // Perform the assignment as if via '='. | 3107 // Perform the assignment as if via '='. |
3133 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3108 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3134 Token::ASSIGN, | 3109 Token::ASSIGN, |
3135 context_); | 3110 context_); |
3136 } | 3111 } |
3137 break; | 3112 break; |
3138 case NAMED_PROPERTY: { | 3113 case NAMED_PROPERTY: { |
3139 __ Move(rcx, prop->key()->AsLiteral()->handle()); | 3114 __ Move(rcx, prop->key()->AsLiteral()->handle()); |
3140 __ pop(rdx); | 3115 __ pop(rdx); |
3141 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3116 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
3142 __ call(ic, RelocInfo::CODE_TARGET); | 3117 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3143 // This nop signals to the IC that there is no inlined code at the call | |
3144 // site for it to patch. | |
3145 __ nop(); | |
3146 if (expr->is_postfix()) { | 3118 if (expr->is_postfix()) { |
3147 if (context_ != Expression::kEffect) { | 3119 if (context_ != Expression::kEffect) { |
3148 ApplyTOS(context_); | 3120 ApplyTOS(context_); |
3149 } | 3121 } |
3150 } else { | 3122 } else { |
3151 Apply(context_, rax); | 3123 Apply(context_, rax); |
3152 } | 3124 } |
3153 break; | 3125 break; |
3154 } | 3126 } |
3155 case KEYED_PROPERTY: { | 3127 case KEYED_PROPERTY: { |
3156 __ pop(rcx); | 3128 __ pop(rcx); |
3157 __ pop(rdx); | 3129 __ pop(rdx); |
3158 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3130 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
3159 __ call(ic, RelocInfo::CODE_TARGET); | 3131 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3160 // This nop signals to the IC that there is no inlined code at the call | |
3161 // site for it to patch. | |
3162 __ nop(); | |
3163 if (expr->is_postfix()) { | 3132 if (expr->is_postfix()) { |
3164 if (context_ != Expression::kEffect) { | 3133 if (context_ != Expression::kEffect) { |
3165 ApplyTOS(context_); | 3134 ApplyTOS(context_); |
3166 } | 3135 } |
3167 } else { | 3136 } else { |
3168 Apply(context_, rax); | 3137 Apply(context_, rax); |
3169 } | 3138 } |
3170 break; | 3139 break; |
3171 } | 3140 } |
3172 } | 3141 } |
3173 } | 3142 } |
3174 | 3143 |
3175 | 3144 |
3176 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { | 3145 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { |
3177 VariableProxy* proxy = expr->AsVariableProxy(); | 3146 VariableProxy* proxy = expr->AsVariableProxy(); |
3178 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3147 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
3179 Comment cmnt(masm_, "Global variable"); | 3148 Comment cmnt(masm_, "Global variable"); |
3180 __ Move(rcx, proxy->name()); | 3149 __ Move(rcx, proxy->name()); |
3181 __ movq(rax, CodeGenerator::GlobalObject()); | 3150 __ movq(rax, CodeGenerator::GlobalObject()); |
3182 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3151 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
3183 // Use a regular load, not a contextual load, to avoid a reference | 3152 // Use a regular load, not a contextual load, to avoid a reference |
3184 // error. | 3153 // error. |
3185 __ Call(ic, RelocInfo::CODE_TARGET); | 3154 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3186 __ nop(); // Signal no inlined code. | |
3187 if (where == kStack) __ push(rax); | 3155 if (where == kStack) __ push(rax); |
3188 } else if (proxy != NULL && | 3156 } else if (proxy != NULL && |
3189 proxy->var()->slot() != NULL && | 3157 proxy->var()->slot() != NULL && |
3190 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3158 proxy->var()->slot()->type() == Slot::LOOKUP) { |
3191 Label done, slow; | 3159 Label done, slow; |
3192 | 3160 |
3193 // Generate code for loading from variables potentially shadowed | 3161 // Generate code for loading from variables potentially shadowed |
3194 // by eval-introduced variables. | 3162 // by eval-introduced variables. |
3195 Slot* slot = proxy->var()->slot(); | 3163 Slot* slot = proxy->var()->slot(); |
3196 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3164 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3424 Apply(context_, if_true, if_false); | 3392 Apply(context_, if_true, if_false); |
3425 } | 3393 } |
3426 | 3394 |
3427 | 3395 |
3428 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3396 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
3429 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3397 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3430 Apply(context_, rax); | 3398 Apply(context_, rax); |
3431 } | 3399 } |
3432 | 3400 |
3433 | 3401 |
3434 Register FullCodeGenerator::result_register() { return rax; } | 3402 Register FullCodeGenerator::result_register() { |
| 3403 return rax; |
| 3404 } |
3435 | 3405 |
3436 | 3406 |
3437 Register FullCodeGenerator::context_register() { return rsi; } | 3407 Register FullCodeGenerator::context_register() { |
| 3408 return rsi; |
| 3409 } |
| 3410 |
| 3411 |
| 3412 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 3413 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 3414 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 3415 __ call(ic, mode); |
| 3416 |
| 3417 // If we're calling a (keyed) load or store stub, we have to mark |
| 3418 // the call as containing no inlined code so we will not attempt to |
| 3419 // patch it. |
| 3420 switch (ic->kind()) { |
| 3421 case Code::LOAD_IC: |
| 3422 case Code::KEYED_LOAD_IC: |
| 3423 case Code::STORE_IC: |
| 3424 case Code::KEYED_STORE_IC: |
| 3425 __ nop(); // Signals no inlined code. |
| 3426 break; |
| 3427 default: |
| 3428 // Do nothing. |
| 3429 break; |
| 3430 } |
| 3431 } |
3438 | 3432 |
3439 | 3433 |
3440 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 3434 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
3441 ASSERT(IsAligned(frame_offset, kPointerSize)); | 3435 ASSERT(IsAligned(frame_offset, kPointerSize)); |
3442 __ movq(Operand(rbp, frame_offset), value); | 3436 __ movq(Operand(rbp, frame_offset), value); |
3443 } | 3437 } |
3444 | 3438 |
3445 | 3439 |
3446 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 3440 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
3447 __ movq(dst, ContextOperand(rsi, context_index)); | 3441 __ movq(dst, ContextOperand(rsi, context_index)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3481 __ ret(0); | 3475 __ ret(0); |
3482 } | 3476 } |
3483 | 3477 |
3484 | 3478 |
3485 #undef __ | 3479 #undef __ |
3486 | 3480 |
3487 | 3481 |
3488 } } // namespace v8::internal | 3482 } } // namespace v8::internal |
3489 | 3483 |
3490 #endif // V8_TARGET_ARCH_X64 | 3484 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |