Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(855)

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 3431010: Clean up the insertion of nops (signalling non-inlined loads and... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/x64/macro-assembler-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/full-codegen-ia32.cc ('k') | src/x64/macro-assembler-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698