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 |