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

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

Issue 6665067: [Arguments] Remove synthetic properties and all code dealing with them. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental
Patch Set: Created 9 years, 9 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
« arguments/src/scopes.cc ('K') | « arguments/src/x64/codegen-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 } 640 }
641 } 641 }
642 642
643 643
644 void FullCodeGenerator::EmitDeclaration(Variable* variable, 644 void FullCodeGenerator::EmitDeclaration(Variable* variable,
645 Variable::Mode mode, 645 Variable::Mode mode,
646 FunctionLiteral* function) { 646 FunctionLiteral* function) {
647 Comment cmnt(masm_, "[ Declaration"); 647 Comment cmnt(masm_, "[ Declaration");
648 ASSERT(variable != NULL); // Must have been resolved. 648 ASSERT(variable != NULL); // Must have been resolved.
649 Slot* slot = variable->AsSlot(); 649 Slot* slot = variable->AsSlot();
650 Property* prop = variable->AsProperty();
651 650
652 if (slot != NULL) { 651 if (slot != NULL) {
653 switch (slot->type()) { 652 switch (slot->type()) {
654 case Slot::PARAMETER: 653 case Slot::PARAMETER:
655 case Slot::LOCAL: 654 case Slot::LOCAL:
656 if (mode == Variable::CONST) { 655 if (mode == Variable::CONST) {
657 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 656 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
658 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister); 657 __ movq(Operand(rbp, SlotOffset(slot)), kScratchRegister);
659 } else if (function != NULL) { 658 } else if (function != NULL) {
660 VisitForAccumulatorValue(function); 659 VisitForAccumulatorValue(function);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 __ PushRoot(Heap::kTheHoleValueRootIndex); 701 __ PushRoot(Heap::kTheHoleValueRootIndex);
703 } else if (function != NULL) { 702 } else if (function != NULL) {
704 VisitForStackValue(function); 703 VisitForStackValue(function);
705 } else { 704 } else {
706 __ Push(Smi::FromInt(0)); // no initial value! 705 __ Push(Smi::FromInt(0)); // no initial value!
707 } 706 }
708 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 707 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
709 break; 708 break;
710 } 709 }
711 } 710 }
712
713 } else if (prop != NULL) {
714 if (function != NULL || mode == Variable::CONST) {
715 // We are declaring a function or constant that rewrites to a
716 // property. Use (keyed) IC to set the initial value. We
717 // cannot visit the rewrite because it's shared and we risk
718 // recording duplicate AST IDs for bailouts from optimized code.
719 ASSERT(prop->obj()->AsVariableProxy() != NULL);
720 { AccumulatorValueContext for_object(this);
721 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
722 }
723 if (function != NULL) {
724 __ push(rax);
725 VisitForAccumulatorValue(function);
726 __ pop(rdx);
727 } else {
728 __ movq(rdx, rax);
729 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
730 }
731 ASSERT(prop->key()->AsLiteral() != NULL &&
732 prop->key()->AsLiteral()->handle()->IsSmi());
733 __ Move(rcx, prop->key()->AsLiteral()->handle());
734
735 Handle<Code> ic(Builtins::builtin(
736 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
737 : Builtins::KeyedStoreIC_Initialize));
738 EmitCallIC(ic, RelocInfo::CODE_TARGET);
739 }
740 } 711 }
741 } 712 }
742 713
743 714
744 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 715 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
745 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 716 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
746 } 717 }
747 718
748 719
749 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 720 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 // Generate fast-case code for variables that might be shadowed by 1130 // Generate fast-case code for variables that might be shadowed by
1160 // eval-introduced variables. Eval is used a lot without 1131 // eval-introduced variables. Eval is used a lot without
1161 // introducing variables. In those cases, we do not want to 1132 // introducing variables. In those cases, we do not want to
1162 // perform a runtime call for all variables in the scope 1133 // perform a runtime call for all variables in the scope
1163 // containing the eval. 1134 // containing the eval.
1164 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 1135 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
1165 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); 1136 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
1166 __ jmp(done); 1137 __ jmp(done);
1167 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 1138 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
1168 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); 1139 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
1169 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
1170 if (potential_slot != NULL) { 1140 if (potential_slot != NULL) {
1171 // Generate fast case for locals that rewrite to slots. 1141 // Generate fast case for locals that rewrite to slots.
1172 __ movq(rax, 1142 __ movq(rax,
1173 ContextSlotOperandCheckExtensions(potential_slot, slow)); 1143 ContextSlotOperandCheckExtensions(potential_slot, slow));
1174 if (potential_slot->var()->mode() == Variable::CONST) { 1144 if (potential_slot->var()->mode() == Variable::CONST) {
1175 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1145 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1176 __ j(not_equal, done); 1146 __ j(not_equal, done);
1177 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1147 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1178 } 1148 }
1179 __ jmp(done); 1149 __ jmp(done);
1180 } else if (rewrite != NULL) {
1181 // Generate fast case for calls of an argument function.
1182 Property* property = rewrite->AsProperty();
1183 if (property != NULL) {
1184 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1185 Literal* key_literal = property->key()->AsLiteral();
1186 if (obj_proxy != NULL &&
1187 key_literal != NULL &&
1188 obj_proxy->IsArguments() &&
1189 key_literal->handle()->IsSmi()) {
1190 // Load arguments object if there are no eval-introduced
1191 // variables. Then load the argument from the arguments
1192 // object using keyed load.
1193 __ movq(rdx,
1194 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
1195 slow));
1196 __ Move(rax, key_literal->handle());
1197 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1198 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1199 __ jmp(done);
1200 }
1201 }
1202 } 1150 }
1203 } 1151 }
1204 } 1152 }
1205 1153
1206 1154
1207 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1155 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1208 // Four cases: non-this global variables, lookup slots, all other 1156 // Three cases: non-this global variables, lookup slots, and all other
1209 // types of slots, and parameters that rewrite to explicit property 1157 // types of slots.
1210 // accesses on the arguments object.
1211 Slot* slot = var->AsSlot(); 1158 Slot* slot = var->AsSlot();
1212 Property* property = var->AsProperty(); 1159 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
1213 1160
1214 if (var->is_global() && !var->is_this()) { 1161 if (slot == NULL) {
1215 Comment cmnt(masm_, "Global variable"); 1162 Comment cmnt(masm_, "Global variable");
1216 // Use inline caching. Variable name is passed in rcx and the global 1163 // Use inline caching. Variable name is passed in rcx and the global
1217 // object on the stack. 1164 // object on the stack.
1218 __ Move(rcx, var->name()); 1165 __ Move(rcx, var->name());
1219 __ movq(rax, GlobalObjectOperand()); 1166 __ movq(rax, GlobalObjectOperand());
1220 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1167 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1221 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 1168 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1222 context()->Plug(rax); 1169 context()->Plug(rax);
1223 1170
1224 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1171 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
1225 Label done, slow; 1172 Label done, slow;
1226 1173
1227 // Generate code for loading from variables potentially shadowed 1174 // Generate code for loading from variables potentially shadowed
1228 // by eval-introduced variables. 1175 // by eval-introduced variables.
1229 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1176 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1230 1177
1231 __ bind(&slow); 1178 __ bind(&slow);
1232 Comment cmnt(masm_, "Lookup slot"); 1179 Comment cmnt(masm_, "Lookup slot");
1233 __ push(rsi); // Context. 1180 __ push(rsi); // Context.
1234 __ Push(var->name()); 1181 __ Push(var->name());
1235 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1182 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1236 __ bind(&done); 1183 __ bind(&done);
1237 1184
1238 context()->Plug(rax); 1185 context()->Plug(rax);
1239 1186
1240 } else if (slot != NULL) { 1187 } else {
1241 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1188 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1242 ? "Context slot" 1189 ? "Context slot"
1243 : "Stack slot"); 1190 : "Stack slot");
1244 if (var->mode() == Variable::CONST) { 1191 if (var->mode() == Variable::CONST) {
1245 // Constants may be the hole value if they have not been initialized. 1192 // Constants may be the hole value if they have not been initialized.
1246 // Unhole them. 1193 // Unhole them.
1247 NearLabel done; 1194 NearLabel done;
1248 MemOperand slot_operand = EmitSlotSearch(slot, rax); 1195 MemOperand slot_operand = EmitSlotSearch(slot, rax);
1249 __ movq(rax, slot_operand); 1196 __ movq(rax, slot_operand);
1250 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1197 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1251 __ j(not_equal, &done); 1198 __ j(not_equal, &done);
1252 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1199 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1253 __ bind(&done); 1200 __ bind(&done);
1254 context()->Plug(rax); 1201 context()->Plug(rax);
1255 } else { 1202 } else {
1256 context()->Plug(slot); 1203 context()->Plug(slot);
1257 } 1204 }
1258
1259 } else {
1260 Comment cmnt(masm_, "Rewritten parameter");
1261 ASSERT_NOT_NULL(property);
1262 // Rewritten parameter accesses are of the form "slot[literal]".
1263
1264 // Assert that the object is in a slot.
1265 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1266 ASSERT_NOT_NULL(object_var);
1267 Slot* object_slot = object_var->AsSlot();
1268 ASSERT_NOT_NULL(object_slot);
1269
1270 // Load the object.
1271 MemOperand object_loc = EmitSlotSearch(object_slot, rax);
1272 __ movq(rdx, object_loc);
1273
1274 // Assert that the key is a smi.
1275 Literal* key_literal = property->key()->AsLiteral();
1276 ASSERT_NOT_NULL(key_literal);
1277 ASSERT(key_literal->handle()->IsSmi());
1278
1279 // Load the key.
1280 __ Move(rax, key_literal->handle());
1281
1282 // Do a keyed property load.
1283 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1284 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1285 context()->Plug(rax);
1286 } 1205 }
1287 } 1206 }
1288 1207
1289 1208
1290 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1209 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1291 Comment cmnt(masm_, "[ RegExpLiteral"); 1210 Comment cmnt(masm_, "[ RegExpLiteral");
1292 Label materialized; 1211 Label materialized;
1293 // Registers will be used as follows: 1212 // Registers will be used as follows:
1294 // rdi = JS function. 1213 // rdi = JS function.
1295 // rcx = literals array. 1214 // rcx = literals array.
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1410 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1492 Comment cmnt(masm_, "[ Assignment"); 1411 Comment cmnt(masm_, "[ Assignment");
1493 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1412 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1494 // on the left-hand side. 1413 // on the left-hand side.
1495 if (!expr->target()->IsValidLeftHandSide()) { 1414 if (!expr->target()->IsValidLeftHandSide()) {
1496 VisitForEffect(expr->target()); 1415 VisitForEffect(expr->target());
1497 return; 1416 return;
1498 } 1417 }
1499 1418
1500 // Left-hand side can only be a property, a global or a (parameter or local) 1419 // Left-hand side can only be a property, a global or a (parameter or local)
1501 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1420 // slot.
1502 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1421 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1503 LhsKind assign_type = VARIABLE; 1422 LhsKind assign_type = VARIABLE;
1504 Property* property = expr->target()->AsProperty(); 1423 Property* property = expr->target()->AsProperty();
1505 if (property != NULL) { 1424 if (property != NULL) {
1506 assign_type = (property->key()->IsPropertyName()) 1425 assign_type = (property->key()->IsPropertyName())
1507 ? NAMED_PROPERTY 1426 ? NAMED_PROPERTY
1508 : KEYED_PROPERTY; 1427 : KEYED_PROPERTY;
1509 } 1428 }
1510 1429
1511 // Evaluate LHS expression. 1430 // Evaluate LHS expression.
1512 switch (assign_type) { 1431 switch (assign_type) {
1513 case VARIABLE: 1432 case VARIABLE:
1514 // Nothing to do here. 1433 // Nothing to do here.
1515 break; 1434 break;
1516 case NAMED_PROPERTY: 1435 case NAMED_PROPERTY:
1517 if (expr->is_compound()) { 1436 if (expr->is_compound()) {
1518 // We need the receiver both on the stack and in the accumulator. 1437 // We need the receiver both on the stack and in the accumulator.
1519 VisitForAccumulatorValue(property->obj()); 1438 VisitForAccumulatorValue(property->obj());
1520 __ push(result_register()); 1439 __ push(result_register());
1521 } else { 1440 } else {
1522 VisitForStackValue(property->obj()); 1441 VisitForStackValue(property->obj());
1523 } 1442 }
1524 break; 1443 break;
1525 case KEYED_PROPERTY: { 1444 case KEYED_PROPERTY: {
1526 if (expr->is_compound()) { 1445 if (expr->is_compound()) {
1527 if (property->is_arguments_access()) { 1446 VisitForStackValue(property->obj());
1528 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1447 VisitForAccumulatorValue(property->key());
1529 MemOperand slot_operand =
1530 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1531 __ push(slot_operand);
1532 __ Move(rax, property->key()->AsLiteral()->handle());
1533 } else {
1534 VisitForStackValue(property->obj());
1535 VisitForAccumulatorValue(property->key());
1536 }
1537 __ movq(rdx, Operand(rsp, 0)); 1448 __ movq(rdx, Operand(rsp, 0));
1538 __ push(rax); 1449 __ push(rax);
1539 } else { 1450 } else {
1540 if (property->is_arguments_access()) { 1451 VisitForStackValue(property->obj());
1541 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1452 VisitForStackValue(property->key());
1542 MemOperand slot_operand =
1543 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1544 __ push(slot_operand);
1545 __ Push(property->key()->AsLiteral()->handle());
1546 } else {
1547 VisitForStackValue(property->obj());
1548 VisitForStackValue(property->key());
1549 }
1550 } 1453 }
1551 break; 1454 break;
1552 } 1455 }
1553 } 1456 }
1554 1457
1555 // For compound assignments we need another deoptimization point after the 1458 // For compound assignments we need another deoptimization point after the
1556 // variable/property load. 1459 // variable/property load.
1557 if (expr->is_compound()) { 1460 if (expr->is_compound()) {
1558 { AccumulatorValueContext context(this); 1461 { AccumulatorValueContext context(this);
1559 switch (assign_type) { 1462 switch (assign_type) {
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1704 1607
1705 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1608 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1706 // Invalid left-hand sides are rewritten to have a 'throw 1609 // Invalid left-hand sides are rewritten to have a 'throw
1707 // ReferenceError' on the left-hand side. 1610 // ReferenceError' on the left-hand side.
1708 if (!expr->IsValidLeftHandSide()) { 1611 if (!expr->IsValidLeftHandSide()) {
1709 VisitForEffect(expr); 1612 VisitForEffect(expr);
1710 return; 1613 return;
1711 } 1614 }
1712 1615
1713 // Left-hand side can only be a property, a global or a (parameter or local) 1616 // Left-hand side can only be a property, a global or a (parameter or local)
1714 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1617 // slot.
1715 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1618 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1716 LhsKind assign_type = VARIABLE; 1619 LhsKind assign_type = VARIABLE;
1717 Property* prop = expr->AsProperty(); 1620 Property* prop = expr->AsProperty();
1718 if (prop != NULL) { 1621 if (prop != NULL) {
1719 assign_type = (prop->key()->IsPropertyName()) 1622 assign_type = (prop->key()->IsPropertyName())
1720 ? NAMED_PROPERTY 1623 ? NAMED_PROPERTY
1721 : KEYED_PROPERTY; 1624 : KEYED_PROPERTY;
1722 } 1625 }
1723 1626
1724 switch (assign_type) { 1627 switch (assign_type) {
(...skipping 10 matching lines...) Expand all
1735 __ pop(rax); // Restore value. 1638 __ pop(rax); // Restore value.
1736 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1639 __ Move(rcx, prop->key()->AsLiteral()->handle());
1737 Handle<Code> ic(Builtins::builtin( 1640 Handle<Code> ic(Builtins::builtin(
1738 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict 1641 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
1739 : Builtins::StoreIC_Initialize)); 1642 : Builtins::StoreIC_Initialize));
1740 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1643 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1741 break; 1644 break;
1742 } 1645 }
1743 case KEYED_PROPERTY: { 1646 case KEYED_PROPERTY: {
1744 __ push(rax); // Preserve value. 1647 __ push(rax); // Preserve value.
1745 if (prop->is_synthetic()) { 1648 VisitForStackValue(prop->obj());
1746 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1649 VisitForAccumulatorValue(prop->key());
1747 ASSERT(prop->key()->AsLiteral() != NULL); 1650 __ movq(rcx, rax);
1748 { AccumulatorValueContext for_object(this); 1651 __ pop(rdx);
1749 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1750 }
1751 __ movq(rdx, rax);
1752 __ Move(rcx, prop->key()->AsLiteral()->handle());
1753 } else {
1754 VisitForStackValue(prop->obj());
1755 VisitForAccumulatorValue(prop->key());
1756 __ movq(rcx, rax);
1757 __ pop(rdx);
1758 }
1759 __ pop(rax); // Restore value. 1652 __ pop(rax); // Restore value.
1760 Handle<Code> ic(Builtins::builtin( 1653 Handle<Code> ic(Builtins::builtin(
1761 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict 1654 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
1762 : Builtins::KeyedStoreIC_Initialize)); 1655 : Builtins::KeyedStoreIC_Initialize));
1763 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1656 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1764 break; 1657 break;
1765 } 1658 }
1766 } 1659 }
1767 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1660 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1768 context()->Plug(rax); 1661 context()->Plug(rax);
1769 } 1662 }
1770 1663
1771 1664
1772 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1665 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1773 Token::Value op) { 1666 Token::Value op) {
1774 // Left-hand sides that rewrite to explicit property accesses do not reach
1775 // here.
1776 ASSERT(var != NULL); 1667 ASSERT(var != NULL);
1777 ASSERT(var->is_global() || var->AsSlot() != NULL); 1668 ASSERT(var->is_global() || var->AsSlot() != NULL);
1778 1669
1779 if (var->is_global()) { 1670 if (var->is_global()) {
1780 ASSERT(!var->is_this()); 1671 ASSERT(!var->is_this());
1781 // Assignment to a global variable. Use inline caching for the 1672 // Assignment to a global variable. Use inline caching for the
1782 // assignment. Right-hand-side value is passed in rax, variable name in 1673 // assignment. Right-hand-side value is passed in rax, variable name in
1783 // rcx, and the global object on the stack. 1674 // rcx, and the global object on the stack.
1784 __ Move(rcx, var->name()); 1675 __ Move(rcx, var->name());
1785 __ movq(rdx, GlobalObjectOperand()); 1676 __ movq(rdx, GlobalObjectOperand());
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
2180 Property* prop = fun->AsProperty(); 2071 Property* prop = fun->AsProperty();
2181 Literal* key = prop->key()->AsLiteral(); 2072 Literal* key = prop->key()->AsLiteral();
2182 if (key != NULL && key->handle()->IsSymbol()) { 2073 if (key != NULL && key->handle()->IsSymbol()) {
2183 // Call to a named property, use call IC. 2074 // Call to a named property, use call IC.
2184 { PreservePositionScope scope(masm()->positions_recorder()); 2075 { PreservePositionScope scope(masm()->positions_recorder());
2185 VisitForStackValue(prop->obj()); 2076 VisitForStackValue(prop->obj());
2186 } 2077 }
2187 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2078 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2188 } else { 2079 } else {
2189 // Call to a keyed property. 2080 // Call to a keyed property.
2190 // For a synthetic property use keyed load IC followed by function call, 2081 { PreservePositionScope scope(masm()->positions_recorder());
2191 // for a regular property use keyed EmitCallIC. 2082 VisitForStackValue(prop->obj());
2192 if (prop->is_synthetic()) {
2193 // Do not visit the object and key subexpressions (they are shared
2194 // by all occurrences of the same rewritten parameter).
2195 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2196 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2197 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2198 MemOperand operand = EmitSlotSearch(slot, rdx);
2199 __ movq(rdx, operand);
2200
2201 ASSERT(prop->key()->AsLiteral() != NULL);
2202 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2203 __ Move(rax, prop->key()->AsLiteral()->handle());
2204
2205 // Record source code position for IC call.
2206 SetSourcePosition(prop->position());
2207
2208 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
2209 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2210 // Push result (function).
2211 __ push(rax);
2212 // Push Global receiver.
2213 __ movq(rcx, GlobalObjectOperand());
2214 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
2215 EmitCallWithStub(expr);
2216 } else {
2217 { PreservePositionScope scope(masm()->positions_recorder());
2218 VisitForStackValue(prop->obj());
2219 }
2220 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2221 } 2083 }
2084 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2222 } 2085 }
2223 } else { 2086 } else {
2224 // Call to some other expression. If the expression is an anonymous 2087 // Call to some other expression. If the expression is an anonymous
2225 // function literal not called in a loop, mark it as one that should 2088 // function literal not called in a loop, mark it as one that should
2226 // also use the full code generator. 2089 // also use the full code generator.
2227 FunctionLiteral* lit = fun->AsFunctionLiteral(); 2090 FunctionLiteral* lit = fun->AsFunctionLiteral();
2228 if (lit != NULL && 2091 if (lit != NULL &&
2229 lit->name()->Equals(Heap::empty_string()) && 2092 lit->name()->Equals(Heap::empty_string()) &&
2230 loop_depth() == 0) { 2093 loop_depth() == 0) {
2231 lit->set_try_full_codegen(true); 2094 lit->set_try_full_codegen(true);
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after
3239 3102
3240 3103
3241 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3104 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3242 switch (expr->op()) { 3105 switch (expr->op()) {
3243 case Token::DELETE: { 3106 case Token::DELETE: {
3244 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3107 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3245 Property* prop = expr->expression()->AsProperty(); 3108 Property* prop = expr->expression()->AsProperty();
3246 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3109 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3247 3110
3248 if (prop != NULL) { 3111 if (prop != NULL) {
3249 if (prop->is_synthetic()) { 3112 VisitForStackValue(prop->obj());
3250 // Result of deleting parameters is false, even when they rewrite 3113 VisitForStackValue(prop->key());
3251 // to accesses on the arguments object. 3114 __ Push(Smi::FromInt(strict_mode_flag()));
3252 context()->Plug(false); 3115 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3253 } else { 3116 context()->Plug(rax);
3254 VisitForStackValue(prop->obj());
3255 VisitForStackValue(prop->key());
3256 __ Push(Smi::FromInt(strict_mode_flag()));
3257 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3258 context()->Plug(rax);
3259 }
3260 } else if (var != NULL) { 3117 } else if (var != NULL) {
3261 // Delete of an unqualified identifier is disallowed in strict mode 3118 // Delete of an unqualified identifier is disallowed in strict mode
3262 // but "delete this" is. 3119 // but "delete this" is.
3263 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); 3120 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3264 if (var->is_global()) { 3121 if (var->is_global()) {
3265 __ push(GlobalObjectOperand()); 3122 __ push(GlobalObjectOperand());
3266 __ Push(var->name()); 3123 __ Push(var->name());
3267 __ Push(Smi::FromInt(kNonStrictMode)); 3124 __ Push(Smi::FromInt(kNonStrictMode));
3268 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3125 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3269 context()->Plug(rax); 3126 context()->Plug(rax);
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
3392 SetSourcePosition(expr->position()); 3249 SetSourcePosition(expr->position());
3393 3250
3394 // Invalid left-hand-sides are rewritten to have a 'throw 3251 // Invalid left-hand-sides are rewritten to have a 'throw
3395 // ReferenceError' as the left-hand side. 3252 // ReferenceError' as the left-hand side.
3396 if (!expr->expression()->IsValidLeftHandSide()) { 3253 if (!expr->expression()->IsValidLeftHandSide()) {
3397 VisitForEffect(expr->expression()); 3254 VisitForEffect(expr->expression());
3398 return; 3255 return;
3399 } 3256 }
3400 3257
3401 // Expression can only be a property, a global or a (parameter or local) 3258 // Expression can only be a property, a global or a (parameter or local)
3402 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3259 // slot.
3403 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3260 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3404 LhsKind assign_type = VARIABLE; 3261 LhsKind assign_type = VARIABLE;
3405 Property* prop = expr->expression()->AsProperty(); 3262 Property* prop = expr->expression()->AsProperty();
3406 // In case of a property we use the uninitialized expression context 3263 // In case of a property we use the uninitialized expression context
3407 // of the key to detect a named property. 3264 // of the key to detect a named property.
3408 if (prop != NULL) { 3265 if (prop != NULL) {
3409 assign_type = 3266 assign_type =
3410 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3267 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3411 } 3268 }
3412 3269
3413 // Evaluate expression and get value. 3270 // Evaluate expression and get value.
3414 if (assign_type == VARIABLE) { 3271 if (assign_type == VARIABLE) {
3415 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3272 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3416 AccumulatorValueContext context(this); 3273 AccumulatorValueContext context(this);
3417 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3274 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3418 } else { 3275 } else {
3419 // Reserve space for result of postfix operation. 3276 // Reserve space for result of postfix operation.
3420 if (expr->is_postfix() && !context()->IsEffect()) { 3277 if (expr->is_postfix() && !context()->IsEffect()) {
3421 __ Push(Smi::FromInt(0)); 3278 __ Push(Smi::FromInt(0));
3422 } 3279 }
3423 if (assign_type == NAMED_PROPERTY) { 3280 if (assign_type == NAMED_PROPERTY) {
3424 VisitForAccumulatorValue(prop->obj()); 3281 VisitForAccumulatorValue(prop->obj());
3425 __ push(rax); // Copy of receiver, needed for later store. 3282 __ push(rax); // Copy of receiver, needed for later store.
3426 EmitNamedPropertyLoad(prop); 3283 EmitNamedPropertyLoad(prop);
3427 } else { 3284 } else {
3428 if (prop->is_arguments_access()) { 3285 VisitForStackValue(prop->obj());
3429 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3286 VisitForAccumulatorValue(prop->key());
3430 MemOperand slot_operand =
3431 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
3432 __ push(slot_operand);
3433 __ Move(rax, prop->key()->AsLiteral()->handle());
3434 } else {
3435 VisitForStackValue(prop->obj());
3436 VisitForAccumulatorValue(prop->key());
3437 }
3438 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3287 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3439 __ push(rax); // Copy of key, needed for later store. 3288 __ push(rax); // Copy of key, needed for later store.
3440 EmitKeyedPropertyLoad(prop); 3289 EmitKeyedPropertyLoad(prop);
3441 } 3290 }
3442 } 3291 }
3443 3292
3444 // We need a second deoptimization point after loading the value 3293 // We need a second deoptimization point after loading the value
3445 // in case evaluating the property load my have a side effect. 3294 // in case evaluating the property load my have a side effect.
3446 if (assign_type == VARIABLE) { 3295 if (assign_type == VARIABLE) {
3447 PrepareForBailout(expr->expression(), TOS_REG); 3296 PrepareForBailout(expr->expression(), TOS_REG);
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
3963 __ ret(0); 3812 __ ret(0);
3964 } 3813 }
3965 3814
3966 3815
3967 #undef __ 3816 #undef __
3968 3817
3969 3818
3970 } } // namespace v8::internal 3819 } } // namespace v8::internal
3971 3820
3972 #endif // V8_TARGET_ARCH_X64 3821 #endif // V8_TARGET_ARCH_X64
OLDNEW
« arguments/src/scopes.cc ('K') | « arguments/src/x64/codegen-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698