| 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 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 VisitForValue(function, kAccumulator); | 624 VisitForValue(function, kAccumulator); |
| 625 __ pop(ecx); | 625 __ pop(ecx); |
| 626 } else { | 626 } else { |
| 627 VisitForValue(prop->key(), kAccumulator); | 627 VisitForValue(prop->key(), kAccumulator); |
| 628 __ mov(ecx, result_register()); | 628 __ mov(ecx, result_register()); |
| 629 __ mov(result_register(), Factory::the_hole_value()); | 629 __ mov(result_register(), Factory::the_hole_value()); |
| 630 } | 630 } |
| 631 __ pop(edx); | 631 __ pop(edx); |
| 632 | 632 |
| 633 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 633 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 634 __ call(ic, RelocInfo::CODE_TARGET); | 634 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 635 // Absence of a test eax instruction following the call | |
| 636 // indicates that none of the load was inlined. | |
| 637 __ nop(); | |
| 638 } | 635 } |
| 639 } | 636 } |
| 640 } | 637 } |
| 641 | 638 |
| 642 | 639 |
| 643 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 640 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
| 644 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 641 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
| 645 } | 642 } |
| 646 | 643 |
| 647 | 644 |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 985 } | 982 } |
| 986 | 983 |
| 987 // All extension objects were empty and it is safe to use a global | 984 // All extension objects were empty and it is safe to use a global |
| 988 // load IC call. | 985 // load IC call. |
| 989 __ mov(eax, CodeGenerator::GlobalObject()); | 986 __ mov(eax, CodeGenerator::GlobalObject()); |
| 990 __ mov(ecx, slot->var()->name()); | 987 __ mov(ecx, slot->var()->name()); |
| 991 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 988 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 992 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 989 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 993 ? RelocInfo::CODE_TARGET | 990 ? RelocInfo::CODE_TARGET |
| 994 : RelocInfo::CODE_TARGET_CONTEXT; | 991 : RelocInfo::CODE_TARGET_CONTEXT; |
| 995 __ call(ic, mode); | 992 EmitCallIC(ic, mode); |
| 996 __ nop(); // Signal no inlined code. | |
| 997 } | 993 } |
| 998 | 994 |
| 999 | 995 |
| 1000 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 996 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
| 1001 Slot* slot, | 997 Slot* slot, |
| 1002 Label* slow) { | 998 Label* slow) { |
| 1003 ASSERT(slot->type() == Slot::CONTEXT); | 999 ASSERT(slot->type() == Slot::CONTEXT); |
| 1004 Register context = esi; | 1000 Register context = esi; |
| 1005 Register temp = ebx; | 1001 Register temp = ebx; |
| 1006 | 1002 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 obj_proxy->IsArguments() && | 1059 obj_proxy->IsArguments() && |
| 1064 key_literal->handle()->IsSmi()) { | 1060 key_literal->handle()->IsSmi()) { |
| 1065 // Load arguments object if there are no eval-introduced | 1061 // Load arguments object if there are no eval-introduced |
| 1066 // variables. Then load the argument from the arguments | 1062 // variables. Then load the argument from the arguments |
| 1067 // object using keyed load. | 1063 // object using keyed load. |
| 1068 __ mov(edx, | 1064 __ mov(edx, |
| 1069 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), | 1065 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), |
| 1070 slow)); | 1066 slow)); |
| 1071 __ mov(eax, Immediate(key_literal->handle())); | 1067 __ mov(eax, Immediate(key_literal->handle())); |
| 1072 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1068 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1073 __ call(ic, RelocInfo::CODE_TARGET); | 1069 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1074 __ jmp(done); | 1070 __ jmp(done); |
| 1075 } | 1071 } |
| 1076 } | 1072 } |
| 1077 } | 1073 } |
| 1078 } | 1074 } |
| 1079 } | 1075 } |
| 1080 | 1076 |
| 1081 | 1077 |
| 1082 void FullCodeGenerator::EmitVariableLoad(Variable* var, | 1078 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
| 1083 Expression::Context context) { | 1079 Expression::Context context) { |
| 1084 // Four cases: non-this global variables, lookup slots, all other | 1080 // Four cases: non-this global variables, lookup slots, all other |
| 1085 // types of slots, and parameters that rewrite to explicit property | 1081 // types of slots, and parameters that rewrite to explicit property |
| 1086 // accesses on the arguments object. | 1082 // accesses on the arguments object. |
| 1087 Slot* slot = var->slot(); | 1083 Slot* slot = var->slot(); |
| 1088 Property* property = var->AsProperty(); | 1084 Property* property = var->AsProperty(); |
| 1089 | 1085 |
| 1090 if (var->is_global() && !var->is_this()) { | 1086 if (var->is_global() && !var->is_this()) { |
| 1091 Comment cmnt(masm_, "Global variable"); | 1087 Comment cmnt(masm_, "Global variable"); |
| 1092 // Use inline caching. Variable name is passed in ecx and the global | 1088 // Use inline caching. Variable name is passed in ecx and the global |
| 1093 // object on the stack. | 1089 // object on the stack. |
| 1094 __ mov(eax, CodeGenerator::GlobalObject()); | 1090 __ mov(eax, CodeGenerator::GlobalObject()); |
| 1095 __ mov(ecx, var->name()); | 1091 __ mov(ecx, var->name()); |
| 1096 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1092 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1097 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1093 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
| 1098 // By emitting a nop we make sure that we do not have a test eax | |
| 1099 // instruction after the call it is treated specially by the LoadIC code | |
| 1100 // Remember that the assembler may choose to do peephole optimization | |
| 1101 // (eg, push/pop elimination). | |
| 1102 __ nop(); | |
| 1103 Apply(context, eax); | 1094 Apply(context, eax); |
| 1104 | 1095 |
| 1105 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1096 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 1106 Label done, slow; | 1097 Label done, slow; |
| 1107 | 1098 |
| 1108 // Generate code for loading from variables potentially shadowed | 1099 // Generate code for loading from variables potentially shadowed |
| 1109 // by eval-introduced variables. | 1100 // by eval-introduced variables. |
| 1110 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1101 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
| 1111 | 1102 |
| 1112 __ bind(&slow); | 1103 __ bind(&slow); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 // Assert that the key is a smi. | 1146 // Assert that the key is a smi. |
| 1156 Literal* key_literal = property->key()->AsLiteral(); | 1147 Literal* key_literal = property->key()->AsLiteral(); |
| 1157 ASSERT_NOT_NULL(key_literal); | 1148 ASSERT_NOT_NULL(key_literal); |
| 1158 ASSERT(key_literal->handle()->IsSmi()); | 1149 ASSERT(key_literal->handle()->IsSmi()); |
| 1159 | 1150 |
| 1160 // Load the key. | 1151 // Load the key. |
| 1161 __ mov(eax, Immediate(key_literal->handle())); | 1152 __ mov(eax, Immediate(key_literal->handle())); |
| 1162 | 1153 |
| 1163 // Do a keyed property load. | 1154 // Do a keyed property load. |
| 1164 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1155 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1165 __ call(ic, RelocInfo::CODE_TARGET); | 1156 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1166 // Notice: We must not have a "test eax, ..." instruction after the | 1157 |
| 1167 // call. It is treated specially by the LoadIC code. | |
| 1168 __ nop(); | |
| 1169 // Drop key and object left on the stack by IC. | 1158 // Drop key and object left on the stack by IC. |
| 1170 Apply(context, eax); | 1159 Apply(context, eax); |
| 1171 } | 1160 } |
| 1172 } | 1161 } |
| 1173 | 1162 |
| 1174 | 1163 |
| 1175 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1164 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1176 Comment cmnt(masm_, "[ RegExpLiteral"); | 1165 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 1177 NearLabel materialized; | 1166 NearLabel materialized; |
| 1178 // Registers will be used as follows: | 1167 // Registers will be used as follows: |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 switch (property->kind()) { | 1245 switch (property->kind()) { |
| 1257 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1246 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1258 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1247 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 1259 // Fall through. | 1248 // Fall through. |
| 1260 case ObjectLiteral::Property::COMPUTED: | 1249 case ObjectLiteral::Property::COMPUTED: |
| 1261 if (key->handle()->IsSymbol()) { | 1250 if (key->handle()->IsSymbol()) { |
| 1262 VisitForValue(value, kAccumulator); | 1251 VisitForValue(value, kAccumulator); |
| 1263 __ mov(ecx, Immediate(key->handle())); | 1252 __ mov(ecx, Immediate(key->handle())); |
| 1264 __ mov(edx, Operand(esp, 0)); | 1253 __ mov(edx, Operand(esp, 0)); |
| 1265 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1254 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1266 __ call(ic, RelocInfo::CODE_TARGET); | 1255 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1267 __ nop(); | |
| 1268 break; | 1256 break; |
| 1269 } | 1257 } |
| 1270 // Fall through. | 1258 // Fall through. |
| 1271 case ObjectLiteral::Property::PROTOTYPE: | 1259 case ObjectLiteral::Property::PROTOTYPE: |
| 1272 __ push(Operand(esp, 0)); // Duplicate receiver. | 1260 __ push(Operand(esp, 0)); // Duplicate receiver. |
| 1273 VisitForValue(key, kStack); | 1261 VisitForValue(key, kStack); |
| 1274 VisitForValue(value, kStack); | 1262 VisitForValue(value, kStack); |
| 1275 __ CallRuntime(Runtime::kSetProperty, 3); | 1263 __ CallRuntime(Runtime::kSetProperty, 3); |
| 1276 break; | 1264 break; |
| 1277 case ObjectLiteral::Property::SETTER: | 1265 case ObjectLiteral::Property::SETTER: |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 break; | 1458 break; |
| 1471 } | 1459 } |
| 1472 } | 1460 } |
| 1473 | 1461 |
| 1474 | 1462 |
| 1475 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1463 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1476 SetSourcePosition(prop->position()); | 1464 SetSourcePosition(prop->position()); |
| 1477 Literal* key = prop->key()->AsLiteral(); | 1465 Literal* key = prop->key()->AsLiteral(); |
| 1478 __ mov(ecx, Immediate(key->handle())); | 1466 __ mov(ecx, Immediate(key->handle())); |
| 1479 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1467 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1480 __ call(ic, RelocInfo::CODE_TARGET); | 1468 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1481 __ nop(); | |
| 1482 } | 1469 } |
| 1483 | 1470 |
| 1484 | 1471 |
| 1485 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1472 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| 1486 SetSourcePosition(prop->position()); | 1473 SetSourcePosition(prop->position()); |
| 1487 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1474 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 1488 __ call(ic, RelocInfo::CODE_TARGET); | 1475 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1489 __ nop(); | |
| 1490 } | 1476 } |
| 1491 | 1477 |
| 1492 | 1478 |
| 1493 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, | 1479 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, |
| 1494 Expression::Context context, | 1480 Expression::Context context, |
| 1495 OverwriteMode mode, | 1481 OverwriteMode mode, |
| 1496 bool left_is_constant_smi, | 1482 bool left_is_constant_smi, |
| 1497 Smi* value) { | 1483 Smi* value) { |
| 1498 NearLabel call_stub; | 1484 NearLabel call_stub; |
| 1499 Label done; | 1485 Label done; |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); | 1825 EmitVariableAssignment(var, Token::ASSIGN, Expression::kEffect); |
| 1840 break; | 1826 break; |
| 1841 } | 1827 } |
| 1842 case NAMED_PROPERTY: { | 1828 case NAMED_PROPERTY: { |
| 1843 __ push(eax); // Preserve value. | 1829 __ push(eax); // Preserve value. |
| 1844 VisitForValue(prop->obj(), kAccumulator); | 1830 VisitForValue(prop->obj(), kAccumulator); |
| 1845 __ mov(edx, eax); | 1831 __ mov(edx, eax); |
| 1846 __ pop(eax); // Restore value. | 1832 __ pop(eax); // Restore value. |
| 1847 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1833 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1848 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1834 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1849 __ call(ic, RelocInfo::CODE_TARGET); | 1835 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1850 __ nop(); // Signal no inlined code. | |
| 1851 break; | 1836 break; |
| 1852 } | 1837 } |
| 1853 case KEYED_PROPERTY: { | 1838 case KEYED_PROPERTY: { |
| 1854 __ push(eax); // Preserve value. | 1839 __ push(eax); // Preserve value. |
| 1855 VisitForValue(prop->obj(), kStack); | 1840 VisitForValue(prop->obj(), kStack); |
| 1856 VisitForValue(prop->key(), kAccumulator); | 1841 VisitForValue(prop->key(), kAccumulator); |
| 1857 __ mov(ecx, eax); | 1842 __ mov(ecx, eax); |
| 1858 __ pop(edx); | 1843 __ pop(edx); |
| 1859 __ pop(eax); // Restore value. | 1844 __ pop(eax); // Restore value. |
| 1860 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1845 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1861 __ call(ic, RelocInfo::CODE_TARGET); | 1846 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1862 __ nop(); // Signal no inlined code. | |
| 1863 break; | 1847 break; |
| 1864 } | 1848 } |
| 1865 } | 1849 } |
| 1866 } | 1850 } |
| 1867 | 1851 |
| 1868 | 1852 |
| 1869 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1853 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
| 1870 Token::Value op, | 1854 Token::Value op, |
| 1871 Expression::Context context) { | 1855 Expression::Context context) { |
| 1872 // Left-hand sides that rewrite to explicit property accesses do not reach | 1856 // Left-hand sides that rewrite to explicit property accesses do not reach |
| 1873 // here. | 1857 // here. |
| 1874 ASSERT(var != NULL); | 1858 ASSERT(var != NULL); |
| 1875 ASSERT(var->is_global() || var->slot() != NULL); | 1859 ASSERT(var->is_global() || var->slot() != NULL); |
| 1876 | 1860 |
| 1877 if (var->is_global()) { | 1861 if (var->is_global()) { |
| 1878 ASSERT(!var->is_this()); | 1862 ASSERT(!var->is_this()); |
| 1879 // Assignment to a global variable. Use inline caching for the | 1863 // Assignment to a global variable. Use inline caching for the |
| 1880 // assignment. Right-hand-side value is passed in eax, variable name in | 1864 // assignment. Right-hand-side value is passed in eax, variable name in |
| 1881 // ecx, and the global object on the stack. | 1865 // ecx, and the global object on the stack. |
| 1882 __ mov(ecx, var->name()); | 1866 __ mov(ecx, var->name()); |
| 1883 __ mov(edx, CodeGenerator::GlobalObject()); | 1867 __ mov(edx, CodeGenerator::GlobalObject()); |
| 1884 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1868 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1885 __ call(ic, RelocInfo::CODE_TARGET); | 1869 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1886 __ nop(); | |
| 1887 | 1870 |
| 1888 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { | 1871 } else if (var->mode() != Variable::CONST || op == Token::INIT_CONST) { |
| 1889 // Perform the assignment for non-const variables and for initialization | 1872 // Perform the assignment for non-const variables and for initialization |
| 1890 // of const variables. Const assignments are simply skipped. | 1873 // of const variables. Const assignments are simply skipped. |
| 1891 Label done; | 1874 Label done; |
| 1892 Slot* slot = var->slot(); | 1875 Slot* slot = var->slot(); |
| 1893 switch (slot->type()) { | 1876 switch (slot->type()) { |
| 1894 case Slot::PARAMETER: | 1877 case Slot::PARAMETER: |
| 1895 case Slot::LOCAL: | 1878 case Slot::LOCAL: |
| 1896 if (op == Token::INIT_CONST) { | 1879 if (op == Token::INIT_CONST) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1960 | 1943 |
| 1961 // Record source code position before IC call. | 1944 // Record source code position before IC call. |
| 1962 SetSourcePosition(expr->position()); | 1945 SetSourcePosition(expr->position()); |
| 1963 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1946 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 1964 if (expr->ends_initialization_block()) { | 1947 if (expr->ends_initialization_block()) { |
| 1965 __ mov(edx, Operand(esp, 0)); | 1948 __ mov(edx, Operand(esp, 0)); |
| 1966 } else { | 1949 } else { |
| 1967 __ pop(edx); | 1950 __ pop(edx); |
| 1968 } | 1951 } |
| 1969 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1952 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1970 __ call(ic, RelocInfo::CODE_TARGET); | 1953 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 1971 __ nop(); | |
| 1972 | 1954 |
| 1973 // If the assignment ends an initialization block, revert to fast case. | 1955 // If the assignment ends an initialization block, revert to fast case. |
| 1974 if (expr->ends_initialization_block()) { | 1956 if (expr->ends_initialization_block()) { |
| 1975 __ push(eax); // Result of assignment, saved even if not needed. | 1957 __ push(eax); // Result of assignment, saved even if not needed. |
| 1976 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1958 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
| 1977 __ CallRuntime(Runtime::kToFastProperties, 1); | 1959 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1978 __ pop(eax); | 1960 __ pop(eax); |
| 1979 DropAndApply(1, context_, eax); | 1961 DropAndApply(1, context_, eax); |
| 1980 } else { | 1962 } else { |
| 1981 Apply(context_, eax); | 1963 Apply(context_, eax); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1999 | 1981 |
| 2000 __ pop(ecx); | 1982 __ pop(ecx); |
| 2001 if (expr->ends_initialization_block()) { | 1983 if (expr->ends_initialization_block()) { |
| 2002 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 1984 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
| 2003 } else { | 1985 } else { |
| 2004 __ pop(edx); | 1986 __ pop(edx); |
| 2005 } | 1987 } |
| 2006 // Record source code position before IC call. | 1988 // Record source code position before IC call. |
| 2007 SetSourcePosition(expr->position()); | 1989 SetSourcePosition(expr->position()); |
| 2008 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1990 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 2009 __ call(ic, RelocInfo::CODE_TARGET); | 1991 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2010 // This nop signals to the IC that there is no inlined code at the call | |
| 2011 // site for it to patch. | |
| 2012 __ nop(); | |
| 2013 | 1992 |
| 2014 // If the assignment ends an initialization block, revert to fast case. | 1993 // If the assignment ends an initialization block, revert to fast case. |
| 2015 if (expr->ends_initialization_block()) { | 1994 if (expr->ends_initialization_block()) { |
| 2016 __ pop(edx); | 1995 __ pop(edx); |
| 2017 __ push(eax); // Result of assignment, saved even if not needed. | 1996 __ push(eax); // Result of assignment, saved even if not needed. |
| 2018 __ push(edx); | 1997 __ push(edx); |
| 2019 __ CallRuntime(Runtime::kToFastProperties, 1); | 1998 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 2020 __ pop(eax); | 1999 __ pop(eax); |
| 2021 } | 2000 } |
| 2022 | 2001 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2049 ZoneList<Expression*>* args = expr->arguments(); | 2028 ZoneList<Expression*>* args = expr->arguments(); |
| 2050 int arg_count = args->length(); | 2029 int arg_count = args->length(); |
| 2051 for (int i = 0; i < arg_count; i++) { | 2030 for (int i = 0; i < arg_count; i++) { |
| 2052 VisitForValue(args->at(i), kStack); | 2031 VisitForValue(args->at(i), kStack); |
| 2053 } | 2032 } |
| 2054 __ Set(ecx, Immediate(name)); | 2033 __ Set(ecx, Immediate(name)); |
| 2055 // Record source position of the IC call. | 2034 // Record source position of the IC call. |
| 2056 SetSourcePosition(expr->position()); | 2035 SetSourcePosition(expr->position()); |
| 2057 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2036 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2058 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 2037 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 2059 __ call(ic, mode); | 2038 EmitCallIC(ic, mode); |
| 2060 // Restore context register. | 2039 // Restore context register. |
| 2061 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2040 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2062 Apply(context_, eax); | 2041 Apply(context_, eax); |
| 2063 } | 2042 } |
| 2064 | 2043 |
| 2065 | 2044 |
| 2066 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2045 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
| 2067 Expression* key, | 2046 Expression* key, |
| 2068 RelocInfo::Mode mode) { | 2047 RelocInfo::Mode mode) { |
| 2069 // Code common for calls using the IC. | 2048 // Code common for calls using the IC. |
| 2070 ZoneList<Expression*>* args = expr->arguments(); | 2049 ZoneList<Expression*>* args = expr->arguments(); |
| 2071 int arg_count = args->length(); | 2050 int arg_count = args->length(); |
| 2072 for (int i = 0; i < arg_count; i++) { | 2051 for (int i = 0; i < arg_count; i++) { |
| 2073 VisitForValue(args->at(i), kStack); | 2052 VisitForValue(args->at(i), kStack); |
| 2074 } | 2053 } |
| 2075 VisitForValue(key, kAccumulator); | 2054 VisitForValue(key, kAccumulator); |
| 2076 __ mov(ecx, eax); | 2055 __ mov(ecx, eax); |
| 2077 // Record source position of the IC call. | 2056 // Record source position of the IC call. |
| 2078 SetSourcePosition(expr->position()); | 2057 SetSourcePosition(expr->position()); |
| 2079 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2058 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 2080 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize( | 2059 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize( |
| 2081 arg_count, in_loop); | 2060 arg_count, in_loop); |
| 2082 __ call(ic, mode); | 2061 EmitCallIC(ic, mode); |
| 2083 // Restore context register. | 2062 // Restore context register. |
| 2084 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2063 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2085 Apply(context_, eax); | 2064 Apply(context_, eax); |
| 2086 } | 2065 } |
| 2087 | 2066 |
| 2088 | 2067 |
| 2089 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2068 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 2090 // Code common for calls using the call stub. | 2069 // Code common for calls using the call stub. |
| 2091 ZoneList<Expression*>* args = expr->arguments(); | 2070 ZoneList<Expression*>* args = expr->arguments(); |
| 2092 int arg_count = args->length(); | 2071 int arg_count = args->length(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2196 // Call to an object property. | 2175 // Call to an object property. |
| 2197 Property* prop = fun->AsProperty(); | 2176 Property* prop = fun->AsProperty(); |
| 2198 Literal* key = prop->key()->AsLiteral(); | 2177 Literal* key = prop->key()->AsLiteral(); |
| 2199 if (key != NULL && key->handle()->IsSymbol()) { | 2178 if (key != NULL && key->handle()->IsSymbol()) { |
| 2200 // Call to a named property, use call IC. | 2179 // Call to a named property, use call IC. |
| 2201 VisitForValue(prop->obj(), kStack); | 2180 VisitForValue(prop->obj(), kStack); |
| 2202 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2181 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 2203 } else { | 2182 } else { |
| 2204 // Call to a keyed property. | 2183 // Call to a keyed property. |
| 2205 // For a synthetic property use keyed load IC followed by function call, | 2184 // For a synthetic property use keyed load IC followed by function call, |
| 2206 // for a regular property use keyed CallIC. | 2185 // for a regular property use keyed EmitCallIC. |
| 2207 VisitForValue(prop->obj(), kStack); | 2186 VisitForValue(prop->obj(), kStack); |
| 2208 if (prop->is_synthetic()) { | 2187 if (prop->is_synthetic()) { |
| 2209 VisitForValue(prop->key(), kAccumulator); | 2188 VisitForValue(prop->key(), kAccumulator); |
| 2210 // Record source code position for IC call. | 2189 // Record source code position for IC call. |
| 2211 SetSourcePosition(prop->position()); | 2190 SetSourcePosition(prop->position()); |
| 2212 __ pop(edx); // We do not need to keep the receiver. | 2191 __ pop(edx); // We do not need to keep the receiver. |
| 2213 | 2192 |
| 2214 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2193 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| 2215 __ call(ic, RelocInfo::CODE_TARGET); | 2194 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 2216 // By emitting a nop we make sure that we do not have a "test eax,..." | |
| 2217 // instruction after the call as it is treated specially | |
| 2218 // by the LoadIC code. | |
| 2219 __ nop(); | |
| 2220 // Push result (function). | 2195 // Push result (function). |
| 2221 __ push(eax); | 2196 __ push(eax); |
| 2222 // Push Global receiver. | 2197 // Push Global receiver. |
| 2223 __ mov(ecx, CodeGenerator::GlobalObject()); | 2198 __ mov(ecx, CodeGenerator::GlobalObject()); |
| 2224 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); | 2199 __ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 2225 EmitCallWithStub(expr); | 2200 EmitCallWithStub(expr); |
| 2226 } else { | 2201 } else { |
| 2227 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2202 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
| 2228 } | 2203 } |
| 2229 } | 2204 } |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3137 int arg_count = args->length(); | 3112 int arg_count = args->length(); |
| 3138 for (int i = 0; i < arg_count; i++) { | 3113 for (int i = 0; i < arg_count; i++) { |
| 3139 VisitForValue(args->at(i), kStack); | 3114 VisitForValue(args->at(i), kStack); |
| 3140 } | 3115 } |
| 3141 | 3116 |
| 3142 if (expr->is_jsruntime()) { | 3117 if (expr->is_jsruntime()) { |
| 3143 // Call the JS runtime function via a call IC. | 3118 // Call the JS runtime function via a call IC. |
| 3144 __ Set(ecx, Immediate(expr->name())); | 3119 __ Set(ecx, Immediate(expr->name())); |
| 3145 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 3120 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 3146 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 3121 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 3147 __ call(ic, RelocInfo::CODE_TARGET); | 3122 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3148 // Restore context register. | 3123 // Restore context register. |
| 3149 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3124 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3150 } else { | 3125 } else { |
| 3151 // Call the C runtime function. | 3126 // Call the C runtime function. |
| 3152 __ CallRuntime(expr->function(), arg_count); | 3127 __ CallRuntime(expr->function(), arg_count); |
| 3153 } | 3128 } |
| 3154 Apply(context_, eax); | 3129 Apply(context_, eax); |
| 3155 } | 3130 } |
| 3156 | 3131 |
| 3157 | 3132 |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3443 // Perform the assignment as if via '='. | 3418 // Perform the assignment as if via '='. |
| 3444 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3419 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 3445 Token::ASSIGN, | 3420 Token::ASSIGN, |
| 3446 context_); | 3421 context_); |
| 3447 } | 3422 } |
| 3448 break; | 3423 break; |
| 3449 case NAMED_PROPERTY: { | 3424 case NAMED_PROPERTY: { |
| 3450 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 3425 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
| 3451 __ pop(edx); | 3426 __ pop(edx); |
| 3452 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 3427 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 3453 __ call(ic, RelocInfo::CODE_TARGET); | 3428 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3454 // This nop signals to the IC that there is no inlined code at the call | |
| 3455 // site for it to patch. | |
| 3456 __ nop(); | |
| 3457 if (expr->is_postfix()) { | 3429 if (expr->is_postfix()) { |
| 3458 if (context_ != Expression::kEffect) { | 3430 if (context_ != Expression::kEffect) { |
| 3459 ApplyTOS(context_); | 3431 ApplyTOS(context_); |
| 3460 } | 3432 } |
| 3461 } else { | 3433 } else { |
| 3462 Apply(context_, eax); | 3434 Apply(context_, eax); |
| 3463 } | 3435 } |
| 3464 break; | 3436 break; |
| 3465 } | 3437 } |
| 3466 case KEYED_PROPERTY: { | 3438 case KEYED_PROPERTY: { |
| 3467 __ pop(ecx); | 3439 __ pop(ecx); |
| 3468 __ pop(edx); | 3440 __ pop(edx); |
| 3469 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 3441 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 3470 __ call(ic, RelocInfo::CODE_TARGET); | 3442 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3471 // This nop signals to the IC that there is no inlined code at the call | |
| 3472 // site for it to patch. | |
| 3473 __ nop(); | |
| 3474 if (expr->is_postfix()) { | 3443 if (expr->is_postfix()) { |
| 3475 // Result is on the stack | 3444 // Result is on the stack |
| 3476 if (context_ != Expression::kEffect) { | 3445 if (context_ != Expression::kEffect) { |
| 3477 ApplyTOS(context_); | 3446 ApplyTOS(context_); |
| 3478 } | 3447 } |
| 3479 } else { | 3448 } else { |
| 3480 Apply(context_, eax); | 3449 Apply(context_, eax); |
| 3481 } | 3450 } |
| 3482 break; | 3451 break; |
| 3483 } | 3452 } |
| 3484 } | 3453 } |
| 3485 } | 3454 } |
| 3486 | 3455 |
| 3487 | 3456 |
| 3488 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { | 3457 void FullCodeGenerator::VisitForTypeofValue(Expression* expr, Location where) { |
| 3489 VariableProxy* proxy = expr->AsVariableProxy(); | 3458 VariableProxy* proxy = expr->AsVariableProxy(); |
| 3490 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 3459 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
| 3491 Comment cmnt(masm_, "Global variable"); | 3460 Comment cmnt(masm_, "Global variable"); |
| 3492 __ mov(eax, CodeGenerator::GlobalObject()); | 3461 __ mov(eax, CodeGenerator::GlobalObject()); |
| 3493 __ mov(ecx, Immediate(proxy->name())); | 3462 __ mov(ecx, Immediate(proxy->name())); |
| 3494 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 3463 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 3495 // Use a regular load, not a contextual load, to avoid a reference | 3464 // Use a regular load, not a contextual load, to avoid a reference |
| 3496 // error. | 3465 // error. |
| 3497 __ call(ic, RelocInfo::CODE_TARGET); | 3466 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 3498 __ nop(); // Signal no inlined code. | |
| 3499 if (where == kStack) __ push(eax); | 3467 if (where == kStack) __ push(eax); |
| 3500 } else if (proxy != NULL && | 3468 } else if (proxy != NULL && |
| 3501 proxy->var()->slot() != NULL && | 3469 proxy->var()->slot() != NULL && |
| 3502 proxy->var()->slot()->type() == Slot::LOOKUP) { | 3470 proxy->var()->slot()->type() == Slot::LOOKUP) { |
| 3503 Label done, slow; | 3471 Label done, slow; |
| 3504 | 3472 |
| 3505 // Generate code for loading from variables potentially shadowed | 3473 // Generate code for loading from variables potentially shadowed |
| 3506 // by eval-introduced variables. | 3474 // by eval-introduced variables. |
| 3507 Slot* slot = proxy->var()->slot(); | 3475 Slot* slot = proxy->var()->slot(); |
| 3508 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3476 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3740 Apply(context_, if_true, if_false); | 3708 Apply(context_, if_true, if_false); |
| 3741 } | 3709 } |
| 3742 | 3710 |
| 3743 | 3711 |
| 3744 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3712 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 3745 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3713 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3746 Apply(context_, eax); | 3714 Apply(context_, eax); |
| 3747 } | 3715 } |
| 3748 | 3716 |
| 3749 | 3717 |
| 3750 Register FullCodeGenerator::result_register() { return eax; } | 3718 Register FullCodeGenerator::result_register() { |
| 3719 return eax; |
| 3720 } |
| 3751 | 3721 |
| 3752 | 3722 |
| 3753 Register FullCodeGenerator::context_register() { return esi; } | 3723 Register FullCodeGenerator::context_register() { |
| 3724 return esi; |
| 3725 } |
| 3726 |
| 3727 |
| 3728 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
| 3729 ASSERT(mode == RelocInfo::CODE_TARGET || |
| 3730 mode == RelocInfo::CODE_TARGET_CONTEXT); |
| 3731 __ call(ic, mode); |
| 3732 |
| 3733 // If we're calling a (keyed) load or store stub, we have to mark |
| 3734 // the call as containing no inlined code so we will not attempt to |
| 3735 // patch it. |
| 3736 switch (ic->kind()) { |
| 3737 case Code::LOAD_IC: |
| 3738 case Code::KEYED_LOAD_IC: |
| 3739 case Code::STORE_IC: |
| 3740 case Code::KEYED_STORE_IC: |
| 3741 __ nop(); // Signals no inlined code. |
| 3742 break; |
| 3743 default: |
| 3744 // Do nothing. |
| 3745 break; |
| 3746 } |
| 3747 } |
| 3754 | 3748 |
| 3755 | 3749 |
| 3756 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 3750 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
| 3757 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 3751 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
| 3758 __ mov(Operand(ebp, frame_offset), value); | 3752 __ mov(Operand(ebp, frame_offset), value); |
| 3759 } | 3753 } |
| 3760 | 3754 |
| 3761 | 3755 |
| 3762 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 3756 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
| 3763 __ mov(dst, ContextOperand(esi, context_index)); | 3757 __ mov(dst, ContextOperand(esi, context_index)); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 3793 // And return. | 3787 // And return. |
| 3794 __ ret(0); | 3788 __ ret(0); |
| 3795 } | 3789 } |
| 3796 | 3790 |
| 3797 | 3791 |
| 3798 #undef __ | 3792 #undef __ |
| 3799 | 3793 |
| 3800 } } // namespace v8::internal | 3794 } } // namespace v8::internal |
| 3801 | 3795 |
| 3802 #endif // V8_TARGET_ARCH_IA32 | 3796 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |