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