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

Side by Side Diff: arguments/src/ia32/full-codegen-ia32.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
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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 } 628 }
629 } 629 }
630 630
631 631
632 void FullCodeGenerator::EmitDeclaration(Variable* variable, 632 void FullCodeGenerator::EmitDeclaration(Variable* variable,
633 Variable::Mode mode, 633 Variable::Mode mode,
634 FunctionLiteral* function) { 634 FunctionLiteral* function) {
635 Comment cmnt(masm_, "[ Declaration"); 635 Comment cmnt(masm_, "[ Declaration");
636 ASSERT(variable != NULL); // Must have been resolved. 636 ASSERT(variable != NULL); // Must have been resolved.
637 Slot* slot = variable->AsSlot(); 637 Slot* slot = variable->AsSlot();
638 Property* prop = variable->AsProperty();
639 638
640 if (slot != NULL) { 639 if (slot != NULL) {
641 switch (slot->type()) { 640 switch (slot->type()) {
642 case Slot::PARAMETER: 641 case Slot::PARAMETER:
643 case Slot::LOCAL: 642 case Slot::LOCAL:
644 if (mode == Variable::CONST) { 643 if (mode == Variable::CONST) {
645 __ mov(Operand(ebp, SlotOffset(slot)), 644 __ mov(Operand(ebp, SlotOffset(slot)),
646 Immediate(Factory::the_hole_value())); 645 Immediate(Factory::the_hole_value()));
647 } else if (function != NULL) { 646 } else if (function != NULL) {
648 VisitForAccumulatorValue(function); 647 VisitForAccumulatorValue(function);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 __ push(Immediate(Factory::the_hole_value())); 690 __ push(Immediate(Factory::the_hole_value()));
692 } else if (function != NULL) { 691 } else if (function != NULL) {
693 VisitForStackValue(function); 692 VisitForStackValue(function);
694 } else { 693 } else {
695 __ push(Immediate(Smi::FromInt(0))); // No initial value! 694 __ push(Immediate(Smi::FromInt(0))); // No initial value!
696 } 695 }
697 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 696 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
698 break; 697 break;
699 } 698 }
700 } 699 }
701
702 } else if (prop != NULL) {
703 if (function != NULL || mode == Variable::CONST) {
704 // We are declaring a function or constant that rewrites to a
705 // property. Use (keyed) IC to set the initial value. We cannot
706 // visit the rewrite because it's shared and we risk recording
707 // duplicate AST IDs for bailouts from optimized code.
708 ASSERT(prop->obj()->AsVariableProxy() != NULL);
709 { AccumulatorValueContext for_object(this);
710 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
711 }
712
713 if (function != NULL) {
714 __ push(eax);
715 VisitForAccumulatorValue(function);
716 __ pop(edx);
717 } else {
718 __ mov(edx, eax);
719 __ mov(eax, Factory::the_hole_value());
720 }
721 ASSERT(prop->key()->AsLiteral() != NULL &&
722 prop->key()->AsLiteral()->handle()->IsSmi());
723 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
724
725 Handle<Code> ic(Builtins::builtin(
726 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
727 : Builtins::KeyedStoreIC_Initialize));
728 EmitCallIC(ic, RelocInfo::CODE_TARGET);
729 }
730 } 700 }
731 } 701 }
732 702
733 703
734 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 704 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
735 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 705 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
736 } 706 }
737 707
738 708
739 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 709 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 // Generate fast-case code for variables that might be shadowed by 1109 // Generate fast-case code for variables that might be shadowed by
1140 // eval-introduced variables. Eval is used a lot without 1110 // eval-introduced variables. Eval is used a lot without
1141 // introducing variables. In those cases, we do not want to 1111 // introducing variables. In those cases, we do not want to
1142 // perform a runtime call for all variables in the scope 1112 // perform a runtime call for all variables in the scope
1143 // containing the eval. 1113 // containing the eval.
1144 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { 1114 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) {
1145 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); 1115 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow);
1146 __ jmp(done); 1116 __ jmp(done);
1147 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { 1117 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) {
1148 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); 1118 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot();
1149 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite();
1150 if (potential_slot != NULL) { 1119 if (potential_slot != NULL) {
1151 // Generate fast case for locals that rewrite to slots. 1120 // Generate fast case for locals that rewrite to slots.
1152 __ mov(eax, 1121 __ mov(eax,
1153 ContextSlotOperandCheckExtensions(potential_slot, slow)); 1122 ContextSlotOperandCheckExtensions(potential_slot, slow));
1154 if (potential_slot->var()->mode() == Variable::CONST) { 1123 if (potential_slot->var()->mode() == Variable::CONST) {
1155 __ cmp(eax, Factory::the_hole_value()); 1124 __ cmp(eax, Factory::the_hole_value());
1156 __ j(not_equal, done); 1125 __ j(not_equal, done);
1157 __ mov(eax, Factory::undefined_value()); 1126 __ mov(eax, Factory::undefined_value());
1158 } 1127 }
1159 __ jmp(done); 1128 __ jmp(done);
1160 } else if (rewrite != NULL) {
1161 // Generate fast case for calls of an argument function.
1162 Property* property = rewrite->AsProperty();
1163 if (property != NULL) {
1164 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1165 Literal* key_literal = property->key()->AsLiteral();
1166 if (obj_proxy != NULL &&
1167 key_literal != NULL &&
1168 obj_proxy->IsArguments() &&
1169 key_literal->handle()->IsSmi()) {
1170 // Load arguments object if there are no eval-introduced
1171 // variables. Then load the argument from the arguments
1172 // object using keyed load.
1173 __ mov(edx,
1174 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
1175 slow));
1176 __ mov(eax, Immediate(key_literal->handle()));
1177 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1178 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1179 __ jmp(done);
1180 }
1181 }
1182 } 1129 }
1183 } 1130 }
1184 } 1131 }
1185 1132
1186 1133
1187 void FullCodeGenerator::EmitVariableLoad(Variable* var) { 1134 void FullCodeGenerator::EmitVariableLoad(Variable* var) {
1188 // Four cases: non-this global variables, lookup slots, all other 1135 // Three cases: non-this global variables, lookup slots, and all other
1189 // types of slots, and parameters that rewrite to explicit property 1136 // types of slots.
1190 // accesses on the arguments object.
1191 Slot* slot = var->AsSlot(); 1137 Slot* slot = var->AsSlot();
1192 Property* property = var->AsProperty(); 1138 ASSERT((var->is_global() && !var->is_this()) == (slot != NULL));
1193 1139
1194 if (var->is_global() && !var->is_this()) { 1140 if (slot == NULL) {
1195 Comment cmnt(masm_, "Global variable"); 1141 Comment cmnt(masm_, "Global variable");
1196 // Use inline caching. Variable name is passed in ecx and the global 1142 // Use inline caching. Variable name is passed in ecx and the global
1197 // object on the stack. 1143 // object on the stack.
1198 __ mov(eax, GlobalObjectOperand()); 1144 __ mov(eax, GlobalObjectOperand());
1199 __ mov(ecx, var->name()); 1145 __ mov(ecx, var->name());
1200 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1146 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1201 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 1147 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1202 context()->Plug(eax); 1148 context()->Plug(eax);
1203 1149
1204 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 1150 } else if (slot->type() == Slot::LOOKUP) {
1205 Label done, slow; 1151 Label done, slow;
1206 1152
1207 // Generate code for loading from variables potentially shadowed 1153 // Generate code for loading from variables potentially shadowed
1208 // by eval-introduced variables. 1154 // by eval-introduced variables.
1209 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); 1155 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done);
1210 1156
1211 __ bind(&slow); 1157 __ bind(&slow);
1212 Comment cmnt(masm_, "Lookup slot"); 1158 Comment cmnt(masm_, "Lookup slot");
1213 __ push(esi); // Context. 1159 __ push(esi); // Context.
1214 __ push(Immediate(var->name())); 1160 __ push(Immediate(var->name()));
1215 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1161 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1216 __ bind(&done); 1162 __ bind(&done);
1217 1163
1218 context()->Plug(eax); 1164 context()->Plug(eax);
1219 1165
1220 } else if (slot != NULL) { 1166 } else {
1221 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT) 1167 Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
1222 ? "Context slot" 1168 ? "Context slot"
1223 : "Stack slot"); 1169 : "Stack slot");
1224 if (var->mode() == Variable::CONST) { 1170 if (var->mode() == Variable::CONST) {
1225 // Constants may be the hole value if they have not been initialized. 1171 // Constants may be the hole value if they have not been initialized.
1226 // Unhole them. 1172 // Unhole them.
1227 NearLabel done; 1173 NearLabel done;
1228 MemOperand slot_operand = EmitSlotSearch(slot, eax); 1174 MemOperand slot_operand = EmitSlotSearch(slot, eax);
1229 __ mov(eax, slot_operand); 1175 __ mov(eax, slot_operand);
1230 __ cmp(eax, Factory::the_hole_value()); 1176 __ cmp(eax, Factory::the_hole_value());
1231 __ j(not_equal, &done); 1177 __ j(not_equal, &done);
1232 __ mov(eax, Factory::undefined_value()); 1178 __ mov(eax, Factory::undefined_value());
1233 __ bind(&done); 1179 __ bind(&done);
1234 context()->Plug(eax); 1180 context()->Plug(eax);
1235 } else { 1181 } else {
1236 context()->Plug(slot); 1182 context()->Plug(slot);
1237 } 1183 }
1238
1239 } else {
1240 Comment cmnt(masm_, "Rewritten parameter");
1241 ASSERT_NOT_NULL(property);
1242 // Rewritten parameter accesses are of the form "slot[literal]".
1243
1244 // Assert that the object is in a slot.
1245 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
1246 ASSERT_NOT_NULL(object_var);
1247 Slot* object_slot = object_var->AsSlot();
1248 ASSERT_NOT_NULL(object_slot);
1249
1250 // Load the object.
1251 MemOperand object_loc = EmitSlotSearch(object_slot, eax);
1252 __ mov(edx, object_loc);
1253
1254 // Assert that the key is a smi.
1255 Literal* key_literal = property->key()->AsLiteral();
1256 ASSERT_NOT_NULL(key_literal);
1257 ASSERT(key_literal->handle()->IsSmi());
1258
1259 // Load the key.
1260 __ mov(eax, Immediate(key_literal->handle()));
1261
1262 // Do a keyed property load.
1263 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1264 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1265
1266 // Drop key and object left on the stack by IC.
1267 context()->Plug(eax);
1268 } 1184 }
1269 } 1185 }
1270 1186
1271 1187
1272 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1188 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1273 Comment cmnt(masm_, "[ RegExpLiteral"); 1189 Comment cmnt(masm_, "[ RegExpLiteral");
1274 NearLabel materialized; 1190 NearLabel materialized;
1275 // Registers will be used as follows: 1191 // Registers will be used as follows:
1276 // edi = JS function. 1192 // edi = JS function.
1277 // ecx = literals array. 1193 // ecx = literals array.
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 void FullCodeGenerator::VisitAssignment(Assignment* expr) { 1393 void FullCodeGenerator::VisitAssignment(Assignment* expr) {
1478 Comment cmnt(masm_, "[ Assignment"); 1394 Comment cmnt(masm_, "[ Assignment");
1479 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 1395 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
1480 // on the left-hand side. 1396 // on the left-hand side.
1481 if (!expr->target()->IsValidLeftHandSide()) { 1397 if (!expr->target()->IsValidLeftHandSide()) {
1482 VisitForEffect(expr->target()); 1398 VisitForEffect(expr->target());
1483 return; 1399 return;
1484 } 1400 }
1485 1401
1486 // Left-hand side can only be a property, a global or a (parameter or local) 1402 // Left-hand side can only be a property, a global or a (parameter or local)
1487 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1403 // slot.
1488 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1404 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1489 LhsKind assign_type = VARIABLE; 1405 LhsKind assign_type = VARIABLE;
1490 Property* property = expr->target()->AsProperty(); 1406 Property* property = expr->target()->AsProperty();
1491 if (property != NULL) { 1407 if (property != NULL) {
1492 assign_type = (property->key()->IsPropertyName()) 1408 assign_type = (property->key()->IsPropertyName())
1493 ? NAMED_PROPERTY 1409 ? NAMED_PROPERTY
1494 : KEYED_PROPERTY; 1410 : KEYED_PROPERTY;
1495 } 1411 }
1496 1412
1497 // Evaluate LHS expression. 1413 // Evaluate LHS expression.
1498 switch (assign_type) { 1414 switch (assign_type) {
1499 case VARIABLE: 1415 case VARIABLE:
1500 // Nothing to do here. 1416 // Nothing to do here.
1501 break; 1417 break;
1502 case NAMED_PROPERTY: 1418 case NAMED_PROPERTY:
1503 if (expr->is_compound()) { 1419 if (expr->is_compound()) {
1504 // We need the receiver both on the stack and in the accumulator. 1420 // We need the receiver both on the stack and in the accumulator.
1505 VisitForAccumulatorValue(property->obj()); 1421 VisitForAccumulatorValue(property->obj());
1506 __ push(result_register()); 1422 __ push(result_register());
1507 } else { 1423 } else {
1508 VisitForStackValue(property->obj()); 1424 VisitForStackValue(property->obj());
1509 } 1425 }
1510 break; 1426 break;
1511 case KEYED_PROPERTY: { 1427 case KEYED_PROPERTY: {
1512 if (expr->is_compound()) { 1428 if (expr->is_compound()) {
1513 if (property->is_arguments_access()) { 1429 VisitForStackValue(property->obj());
1514 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1430 VisitForAccumulatorValue(property->key());
1515 MemOperand slot_operand =
1516 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1517 __ push(slot_operand);
1518 __ mov(eax, Immediate(property->key()->AsLiteral()->handle()));
1519 } else {
1520 VisitForStackValue(property->obj());
1521 VisitForAccumulatorValue(property->key());
1522 }
1523 __ mov(edx, Operand(esp, 0)); 1431 __ mov(edx, Operand(esp, 0));
1524 __ push(eax); 1432 __ push(eax);
1525 } else { 1433 } else {
1526 if (property->is_arguments_access()) { 1434 VisitForStackValue(property->obj());
1527 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); 1435 VisitForStackValue(property->key());
1528 MemOperand slot_operand =
1529 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
1530 __ push(slot_operand);
1531 __ push(Immediate(property->key()->AsLiteral()->handle()));
1532 } else {
1533 VisitForStackValue(property->obj());
1534 VisitForStackValue(property->key());
1535 }
1536 } 1436 }
1537 break; 1437 break;
1538 } 1438 }
1539 } 1439 }
1540 1440
1541 // For compound assignments we need another deoptimization point after the 1441 // For compound assignments we need another deoptimization point after the
1542 // variable/property load. 1442 // variable/property load.
1543 if (expr->is_compound()) { 1443 if (expr->is_compound()) {
1544 { AccumulatorValueContext context(this); 1444 { AccumulatorValueContext context(this);
1545 switch (assign_type) { 1445 switch (assign_type) {
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 1626
1727 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { 1627 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1728 // Invalid left-hand sides are rewritten to have a 'throw 1628 // Invalid left-hand sides are rewritten to have a 'throw
1729 // ReferenceError' on the left-hand side. 1629 // ReferenceError' on the left-hand side.
1730 if (!expr->IsValidLeftHandSide()) { 1630 if (!expr->IsValidLeftHandSide()) {
1731 VisitForEffect(expr); 1631 VisitForEffect(expr);
1732 return; 1632 return;
1733 } 1633 }
1734 1634
1735 // Left-hand side can only be a property, a global or a (parameter or local) 1635 // Left-hand side can only be a property, a global or a (parameter or local)
1736 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1636 // slot.
1737 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1637 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
1738 LhsKind assign_type = VARIABLE; 1638 LhsKind assign_type = VARIABLE;
1739 Property* prop = expr->AsProperty(); 1639 Property* prop = expr->AsProperty();
1740 if (prop != NULL) { 1640 if (prop != NULL) {
1741 assign_type = (prop->key()->IsPropertyName()) 1641 assign_type = (prop->key()->IsPropertyName())
1742 ? NAMED_PROPERTY 1642 ? NAMED_PROPERTY
1743 : KEYED_PROPERTY; 1643 : KEYED_PROPERTY;
1744 } 1644 }
1745 1645
1746 switch (assign_type) { 1646 switch (assign_type) {
(...skipping 10 matching lines...) Expand all
1757 __ pop(eax); // Restore value. 1657 __ pop(eax); // Restore value.
1758 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1658 __ mov(ecx, prop->key()->AsLiteral()->handle());
1759 Handle<Code> ic(Builtins::builtin( 1659 Handle<Code> ic(Builtins::builtin(
1760 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict 1660 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
1761 : Builtins::StoreIC_Initialize)); 1661 : Builtins::StoreIC_Initialize));
1762 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1662 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1763 break; 1663 break;
1764 } 1664 }
1765 case KEYED_PROPERTY: { 1665 case KEYED_PROPERTY: {
1766 __ push(eax); // Preserve value. 1666 __ push(eax); // Preserve value.
1767 if (prop->is_synthetic()) { 1667 VisitForStackValue(prop->obj());
1768 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1668 VisitForAccumulatorValue(prop->key());
1769 ASSERT(prop->key()->AsLiteral() != NULL); 1669 __ mov(ecx, eax);
1770 { AccumulatorValueContext for_object(this); 1670 __ pop(edx);
1771 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1772 }
1773 __ mov(edx, eax);
1774 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1775 } else {
1776 VisitForStackValue(prop->obj());
1777 VisitForAccumulatorValue(prop->key());
1778 __ mov(ecx, eax);
1779 __ pop(edx);
1780 }
1781 __ pop(eax); // Restore value. 1671 __ pop(eax); // Restore value.
1782 Handle<Code> ic(Builtins::builtin( 1672 Handle<Code> ic(Builtins::builtin(
1783 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict 1673 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
1784 : Builtins::KeyedStoreIC_Initialize)); 1674 : Builtins::KeyedStoreIC_Initialize));
1785 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1675 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1786 break; 1676 break;
1787 } 1677 }
1788 } 1678 }
1789 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1679 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1790 context()->Plug(eax); 1680 context()->Plug(eax);
1791 } 1681 }
1792 1682
1793 1683
1794 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1684 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1795 Token::Value op) { 1685 Token::Value op) {
1796 // Left-hand sides that rewrite to explicit property accesses do not reach
1797 // here.
1798 ASSERT(var != NULL); 1686 ASSERT(var != NULL);
1799 ASSERT(var->is_global() || var->AsSlot() != NULL); 1687 ASSERT(var->is_global() || var->AsSlot() != NULL);
1800 1688
1801 if (var->is_global()) { 1689 if (var->is_global()) {
1802 ASSERT(!var->is_this()); 1690 ASSERT(!var->is_this());
1803 // Assignment to a global variable. Use inline caching for the 1691 // Assignment to a global variable. Use inline caching for the
1804 // assignment. Right-hand-side value is passed in eax, variable name in 1692 // assignment. Right-hand-side value is passed in eax, variable name in
1805 // ecx, and the global object on the stack. 1693 // ecx, and the global object on the stack.
1806 __ mov(ecx, var->name()); 1694 __ mov(ecx, var->name());
1807 __ mov(edx, GlobalObjectOperand()); 1695 __ mov(edx, GlobalObjectOperand());
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
2199 Property* prop = fun->AsProperty(); 2087 Property* prop = fun->AsProperty();
2200 Literal* key = prop->key()->AsLiteral(); 2088 Literal* key = prop->key()->AsLiteral();
2201 if (key != NULL && key->handle()->IsSymbol()) { 2089 if (key != NULL && key->handle()->IsSymbol()) {
2202 // Call to a named property, use call IC. 2090 // Call to a named property, use call IC.
2203 { PreservePositionScope scope(masm()->positions_recorder()); 2091 { PreservePositionScope scope(masm()->positions_recorder());
2204 VisitForStackValue(prop->obj()); 2092 VisitForStackValue(prop->obj());
2205 } 2093 }
2206 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2094 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2207 } else { 2095 } else {
2208 // Call to a keyed property. 2096 // Call to a keyed property.
2209 // For a synthetic property use keyed load IC followed by function call, 2097 { PreservePositionScope scope(masm()->positions_recorder());
2210 // for a regular property use keyed EmitCallIC. 2098 VisitForStackValue(prop->obj());
2211 if (prop->is_synthetic()) {
2212 // Do not visit the object and key subexpressions (they are shared
2213 // by all occurrences of the same rewritten parameter).
2214 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2215 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
2216 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
2217 MemOperand operand = EmitSlotSearch(slot, edx);
2218 __ mov(edx, operand);
2219
2220 ASSERT(prop->key()->AsLiteral() != NULL);
2221 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
2222 __ mov(eax, prop->key()->AsLiteral()->handle());
2223
2224 // Record source code position for IC call.
2225 SetSourcePosition(prop->position());
2226
2227 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
2228 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2229 // Push result (function).
2230 __ push(eax);
2231 // Push Global receiver.
2232 __ mov(ecx, GlobalObjectOperand());
2233 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
2234 EmitCallWithStub(expr);
2235 } else {
2236 { PreservePositionScope scope(masm()->positions_recorder());
2237 VisitForStackValue(prop->obj());
2238 }
2239 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2240 } 2099 }
2100 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
2241 } 2101 }
2242 } else { 2102 } else {
2243 // Call to some other expression. If the expression is an anonymous 2103 // Call to some other expression. If the expression is an anonymous
2244 // function literal not called in a loop, mark it as one that should 2104 // function literal not called in a loop, mark it as one that should
2245 // also use the full code generator. 2105 // also use the full code generator.
2246 FunctionLiteral* lit = fun->AsFunctionLiteral(); 2106 FunctionLiteral* lit = fun->AsFunctionLiteral();
2247 if (lit != NULL && 2107 if (lit != NULL &&
2248 lit->name()->Equals(Heap::empty_string()) && 2108 lit->name()->Equals(Heap::empty_string()) &&
2249 loop_depth() == 0) { 2109 loop_depth() == 0) {
2250 lit->set_try_full_codegen(true); 2110 lit->set_try_full_codegen(true);
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after
3534 3394
3535 3395
3536 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3396 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3537 switch (expr->op()) { 3397 switch (expr->op()) {
3538 case Token::DELETE: { 3398 case Token::DELETE: {
3539 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3399 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3540 Property* prop = expr->expression()->AsProperty(); 3400 Property* prop = expr->expression()->AsProperty();
3541 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3401 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3542 3402
3543 if (prop != NULL) { 3403 if (prop != NULL) {
3544 if (prop->is_synthetic()) { 3404 VisitForStackValue(prop->obj());
3545 // Result of deleting parameters is false, even when they rewrite 3405 VisitForStackValue(prop->key());
3546 // to accesses on the arguments object. 3406 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3547 context()->Plug(false); 3407 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3548 } else { 3408 context()->Plug(eax);
3549 VisitForStackValue(prop->obj());
3550 VisitForStackValue(prop->key());
3551 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3552 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3553 context()->Plug(eax);
3554 }
3555 } else if (var != NULL) { 3409 } else if (var != NULL) {
3556 // Delete of an unqualified identifier is disallowed in strict mode 3410 // Delete of an unqualified identifier is disallowed in strict mode
3557 // but "delete this" is. 3411 // but "delete this" is.
3558 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); 3412 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3559 if (var->is_global()) { 3413 if (var->is_global()) {
3560 __ push(GlobalObjectOperand()); 3414 __ push(GlobalObjectOperand());
3561 __ push(Immediate(var->name())); 3415 __ push(Immediate(var->name()));
3562 __ push(Immediate(Smi::FromInt(kNonStrictMode))); 3416 __ push(Immediate(Smi::FromInt(kNonStrictMode)));
3563 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3417 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3564 context()->Plug(eax); 3418 context()->Plug(eax);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
3690 SetSourcePosition(expr->position()); 3544 SetSourcePosition(expr->position());
3691 3545
3692 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' 3546 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
3693 // as the left-hand side. 3547 // as the left-hand side.
3694 if (!expr->expression()->IsValidLeftHandSide()) { 3548 if (!expr->expression()->IsValidLeftHandSide()) {
3695 VisitForEffect(expr->expression()); 3549 VisitForEffect(expr->expression());
3696 return; 3550 return;
3697 } 3551 }
3698 3552
3699 // Expression can only be a property, a global or a (parameter or local) 3553 // Expression can only be a property, a global or a (parameter or local)
3700 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 3554 // slot.
3701 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 3555 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
3702 LhsKind assign_type = VARIABLE; 3556 LhsKind assign_type = VARIABLE;
3703 Property* prop = expr->expression()->AsProperty(); 3557 Property* prop = expr->expression()->AsProperty();
3704 // In case of a property we use the uninitialized expression context 3558 // In case of a property we use the uninitialized expression context
3705 // of the key to detect a named property. 3559 // of the key to detect a named property.
3706 if (prop != NULL) { 3560 if (prop != NULL) {
3707 assign_type = 3561 assign_type =
3708 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 3562 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY;
3709 } 3563 }
3710 3564
3711 // Evaluate expression and get value. 3565 // Evaluate expression and get value.
3712 if (assign_type == VARIABLE) { 3566 if (assign_type == VARIABLE) {
3713 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 3567 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
3714 AccumulatorValueContext context(this); 3568 AccumulatorValueContext context(this);
3715 EmitVariableLoad(expr->expression()->AsVariableProxy()->var()); 3569 EmitVariableLoad(expr->expression()->AsVariableProxy()->var());
3716 } else { 3570 } else {
3717 // Reserve space for result of postfix operation. 3571 // Reserve space for result of postfix operation.
3718 if (expr->is_postfix() && !context()->IsEffect()) { 3572 if (expr->is_postfix() && !context()->IsEffect()) {
3719 __ push(Immediate(Smi::FromInt(0))); 3573 __ push(Immediate(Smi::FromInt(0)));
3720 } 3574 }
3721 if (assign_type == NAMED_PROPERTY) { 3575 if (assign_type == NAMED_PROPERTY) {
3722 // Put the object both on the stack and in the accumulator. 3576 // Put the object both on the stack and in the accumulator.
3723 VisitForAccumulatorValue(prop->obj()); 3577 VisitForAccumulatorValue(prop->obj());
3724 __ push(eax); 3578 __ push(eax);
3725 EmitNamedPropertyLoad(prop); 3579 EmitNamedPropertyLoad(prop);
3726 } else { 3580 } else {
3727 if (prop->is_arguments_access()) { 3581 VisitForStackValue(prop->obj());
3728 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy(); 3582 VisitForAccumulatorValue(prop->key());
3729 MemOperand slot_operand =
3730 EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
3731 __ push(slot_operand);
3732 __ mov(eax, Immediate(prop->key()->AsLiteral()->handle()));
3733 } else {
3734 VisitForStackValue(prop->obj());
3735 VisitForAccumulatorValue(prop->key());
3736 }
3737 __ mov(edx, Operand(esp, 0)); 3583 __ mov(edx, Operand(esp, 0));
3738 __ push(eax); 3584 __ push(eax);
3739 EmitKeyedPropertyLoad(prop); 3585 EmitKeyedPropertyLoad(prop);
3740 } 3586 }
3741 } 3587 }
3742 3588
3743 // We need a second deoptimization point after loading the value 3589 // We need a second deoptimization point after loading the value
3744 // in case evaluating the property load my have a side effect. 3590 // in case evaluating the property load my have a side effect.
3745 if (assign_type == VARIABLE) { 3591 if (assign_type == VARIABLE) {
3746 PrepareForBailout(expr->expression(), TOS_REG); 3592 PrepareForBailout(expr->expression(), TOS_REG);
(...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after
4257 // And return. 4103 // And return.
4258 __ ret(0); 4104 __ ret(0);
4259 } 4105 }
4260 4106
4261 4107
4262 #undef __ 4108 #undef __
4263 4109
4264 } } // namespace v8::internal 4110 } } // namespace v8::internal
4265 4111
4266 #endif // V8_TARGET_ARCH_IA32 4112 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698