OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 __ cmp(edx, eax); | 869 __ cmp(edx, eax); |
870 __ j(not_equal, &next_test); | 870 __ j(not_equal, &next_test); |
871 __ Drop(1); // Switch value is no longer needed. | 871 __ Drop(1); // Switch value is no longer needed. |
872 __ jmp(clause->body_target()); | 872 __ jmp(clause->body_target()); |
873 __ bind(&slow_case); | 873 __ bind(&slow_case); |
874 } | 874 } |
875 | 875 |
876 // Record position before stub call for type feedback. | 876 // Record position before stub call for type feedback. |
877 SetSourcePosition(clause->position()); | 877 SetSourcePosition(clause->position()); |
878 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 878 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
879 __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 879 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
880 patch_site.EmitPatchInfo(); | 880 patch_site.EmitPatchInfo(); |
881 __ test(eax, eax); | 881 __ test(eax, eax); |
882 __ j(not_equal, &next_test); | 882 __ j(not_equal, &next_test); |
883 __ Drop(1); // Switch value is no longer needed. | 883 __ Drop(1); // Switch value is no longer needed. |
884 __ jmp(clause->body_target()); | 884 __ jmp(clause->body_target()); |
885 } | 885 } |
886 | 886 |
887 // Discard the test value and jump to the default if present, otherwise to | 887 // Discard the test value and jump to the default if present, otherwise to |
888 // the end of the statement. | 888 // the end of the statement. |
889 __ bind(&next_test); | 889 __ bind(&next_test); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 } | 1182 } |
1183 | 1183 |
1184 // All extension objects were empty and it is safe to use a global | 1184 // All extension objects were empty and it is safe to use a global |
1185 // load IC call. | 1185 // load IC call. |
1186 __ mov(eax, GlobalObjectOperand()); | 1186 __ mov(eax, GlobalObjectOperand()); |
1187 __ mov(ecx, var->name()); | 1187 __ mov(ecx, var->name()); |
1188 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1188 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1189 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1189 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1190 ? RelocInfo::CODE_TARGET | 1190 ? RelocInfo::CODE_TARGET |
1191 : RelocInfo::CODE_TARGET_CONTEXT; | 1191 : RelocInfo::CODE_TARGET_CONTEXT; |
1192 __ call(ic, mode); | 1192 CallIC(ic, mode); |
1193 } | 1193 } |
1194 | 1194 |
1195 | 1195 |
1196 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1196 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1197 Label* slow) { | 1197 Label* slow) { |
1198 ASSERT(var->IsContextSlot()); | 1198 ASSERT(var->IsContextSlot()); |
1199 Register context = esi; | 1199 Register context = esi; |
1200 Register temp = ebx; | 1200 Register temp = ebx; |
1201 | 1201 |
1202 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1202 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 // Three cases: global variables, lookup variables, and all other types of | 1263 // Three cases: global variables, lookup variables, and all other types of |
1264 // variables. | 1264 // variables. |
1265 switch (var->location()) { | 1265 switch (var->location()) { |
1266 case Variable::UNALLOCATED: { | 1266 case Variable::UNALLOCATED: { |
1267 Comment cmnt(masm_, "Global variable"); | 1267 Comment cmnt(masm_, "Global variable"); |
1268 // Use inline caching. Variable name is passed in ecx and the global | 1268 // Use inline caching. Variable name is passed in ecx and the global |
1269 // object in eax. | 1269 // object in eax. |
1270 __ mov(eax, GlobalObjectOperand()); | 1270 __ mov(eax, GlobalObjectOperand()); |
1271 __ mov(ecx, var->name()); | 1271 __ mov(ecx, var->name()); |
1272 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1272 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1273 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1273 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1274 context()->Plug(eax); | 1274 context()->Plug(eax); |
1275 break; | 1275 break; |
1276 } | 1276 } |
1277 | 1277 |
1278 case Variable::PARAMETER: | 1278 case Variable::PARAMETER: |
1279 case Variable::LOCAL: | 1279 case Variable::LOCAL: |
1280 case Variable::CONTEXT: { | 1280 case Variable::CONTEXT: { |
1281 Comment cmnt(masm_, var->IsContextSlot() | 1281 Comment cmnt(masm_, var->IsContextSlot() |
1282 ? "Context variable" | 1282 ? "Context variable" |
1283 : "Stack variable"); | 1283 : "Stack variable"); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 // Fall through. | 1463 // Fall through. |
1464 case ObjectLiteral::Property::COMPUTED: | 1464 case ObjectLiteral::Property::COMPUTED: |
1465 if (key->handle()->IsSymbol()) { | 1465 if (key->handle()->IsSymbol()) { |
1466 if (property->emit_store()) { | 1466 if (property->emit_store()) { |
1467 VisitForAccumulatorValue(value); | 1467 VisitForAccumulatorValue(value); |
1468 __ mov(ecx, Immediate(key->handle())); | 1468 __ mov(ecx, Immediate(key->handle())); |
1469 __ mov(edx, Operand(esp, 0)); | 1469 __ mov(edx, Operand(esp, 0)); |
1470 Handle<Code> ic = is_classic_mode() | 1470 Handle<Code> ic = is_classic_mode() |
1471 ? isolate()->builtins()->StoreIC_Initialize() | 1471 ? isolate()->builtins()->StoreIC_Initialize() |
1472 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1472 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1473 __ call(ic, RelocInfo::CODE_TARGET, key->id()); | 1473 CallIC(ic, RelocInfo::CODE_TARGET, key->id()); |
1474 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1474 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1475 } else { | 1475 } else { |
1476 VisitForEffect(value); | 1476 VisitForEffect(value); |
1477 } | 1477 } |
1478 break; | 1478 break; |
1479 } | 1479 } |
1480 // Fall through. | 1480 // Fall through. |
1481 case ObjectLiteral::Property::PROTOTYPE: | 1481 case ObjectLiteral::Property::PROTOTYPE: |
1482 __ push(Operand(esp, 0)); // Duplicate receiver. | 1482 __ push(Operand(esp, 0)); // Duplicate receiver. |
1483 VisitForStackValue(key); | 1483 VisitForStackValue(key); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 } | 1727 } |
1728 } | 1728 } |
1729 | 1729 |
1730 | 1730 |
1731 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1731 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1732 SetSourcePosition(prop->position()); | 1732 SetSourcePosition(prop->position()); |
1733 Literal* key = prop->key()->AsLiteral(); | 1733 Literal* key = prop->key()->AsLiteral(); |
1734 ASSERT(!key->handle()->IsSmi()); | 1734 ASSERT(!key->handle()->IsSmi()); |
1735 __ mov(ecx, Immediate(key->handle())); | 1735 __ mov(ecx, Immediate(key->handle())); |
1736 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1736 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1737 __ call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1737 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1738 } | 1738 } |
1739 | 1739 |
1740 | 1740 |
1741 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1741 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1742 SetSourcePosition(prop->position()); | 1742 SetSourcePosition(prop->position()); |
1743 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1743 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1744 __ call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1744 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1745 } | 1745 } |
1746 | 1746 |
1747 | 1747 |
1748 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1748 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1749 Token::Value op, | 1749 Token::Value op, |
1750 OverwriteMode mode, | 1750 OverwriteMode mode, |
1751 Expression* left, | 1751 Expression* left, |
1752 Expression* right) { | 1752 Expression* right) { |
1753 // Do combined smi check of the operands. Left operand is on the | 1753 // Do combined smi check of the operands. Left operand is on the |
1754 // stack. Right operand is in eax. | 1754 // stack. Right operand is in eax. |
1755 Label smi_case, done, stub_call; | 1755 Label smi_case, done, stub_call; |
1756 __ pop(edx); | 1756 __ pop(edx); |
1757 __ mov(ecx, eax); | 1757 __ mov(ecx, eax); |
1758 __ or_(eax, edx); | 1758 __ or_(eax, edx); |
1759 JumpPatchSite patch_site(masm_); | 1759 JumpPatchSite patch_site(masm_); |
1760 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); | 1760 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); |
1761 | 1761 |
1762 __ bind(&stub_call); | 1762 __ bind(&stub_call); |
1763 __ mov(eax, ecx); | 1763 __ mov(eax, ecx); |
1764 BinaryOpStub stub(op, mode); | 1764 BinaryOpStub stub(op, mode); |
1765 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1765 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1766 patch_site.EmitPatchInfo(); | 1766 patch_site.EmitPatchInfo(); |
1767 __ jmp(&done, Label::kNear); | 1767 __ jmp(&done, Label::kNear); |
1768 | 1768 |
1769 // Smi case. | 1769 // Smi case. |
1770 __ bind(&smi_case); | 1770 __ bind(&smi_case); |
1771 __ mov(eax, edx); // Copy left operand in case of a stub call. | 1771 __ mov(eax, edx); // Copy left operand in case of a stub call. |
1772 | 1772 |
1773 switch (op) { | 1773 switch (op) { |
1774 case Token::SAR: | 1774 case Token::SAR: |
1775 __ SmiUntag(eax); | 1775 __ SmiUntag(eax); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 context()->Plug(eax); | 1840 context()->Plug(eax); |
1841 } | 1841 } |
1842 | 1842 |
1843 | 1843 |
1844 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1844 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
1845 Token::Value op, | 1845 Token::Value op, |
1846 OverwriteMode mode) { | 1846 OverwriteMode mode) { |
1847 __ pop(edx); | 1847 __ pop(edx); |
1848 BinaryOpStub stub(op, mode); | 1848 BinaryOpStub stub(op, mode); |
1849 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1849 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
1850 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1850 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1851 patch_site.EmitPatchInfo(); | 1851 patch_site.EmitPatchInfo(); |
1852 context()->Plug(eax); | 1852 context()->Plug(eax); |
1853 } | 1853 } |
1854 | 1854 |
1855 | 1855 |
1856 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1856 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1857 // Invalid left-hand sides are rewritten to have a 'throw | 1857 // Invalid left-hand sides are rewritten to have a 'throw |
1858 // ReferenceError' on the left-hand side. | 1858 // ReferenceError' on the left-hand side. |
1859 if (!expr->IsValidLeftHandSide()) { | 1859 if (!expr->IsValidLeftHandSide()) { |
1860 VisitForEffect(expr); | 1860 VisitForEffect(expr); |
(...skipping 20 matching lines...) Expand all Loading... |
1881 } | 1881 } |
1882 case NAMED_PROPERTY: { | 1882 case NAMED_PROPERTY: { |
1883 __ push(eax); // Preserve value. | 1883 __ push(eax); // Preserve value. |
1884 VisitForAccumulatorValue(prop->obj()); | 1884 VisitForAccumulatorValue(prop->obj()); |
1885 __ mov(edx, eax); | 1885 __ mov(edx, eax); |
1886 __ pop(eax); // Restore value. | 1886 __ pop(eax); // Restore value. |
1887 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1887 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1888 Handle<Code> ic = is_classic_mode() | 1888 Handle<Code> ic = is_classic_mode() |
1889 ? isolate()->builtins()->StoreIC_Initialize() | 1889 ? isolate()->builtins()->StoreIC_Initialize() |
1890 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1890 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1891 __ call(ic); | 1891 CallIC(ic); |
1892 break; | 1892 break; |
1893 } | 1893 } |
1894 case KEYED_PROPERTY: { | 1894 case KEYED_PROPERTY: { |
1895 __ push(eax); // Preserve value. | 1895 __ push(eax); // Preserve value. |
1896 VisitForStackValue(prop->obj()); | 1896 VisitForStackValue(prop->obj()); |
1897 VisitForAccumulatorValue(prop->key()); | 1897 VisitForAccumulatorValue(prop->key()); |
1898 __ mov(ecx, eax); | 1898 __ mov(ecx, eax); |
1899 __ pop(edx); | 1899 __ pop(edx); |
1900 __ pop(eax); // Restore value. | 1900 __ pop(eax); // Restore value. |
1901 Handle<Code> ic = is_classic_mode() | 1901 Handle<Code> ic = is_classic_mode() |
1902 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1902 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1903 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1903 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1904 __ call(ic); | 1904 CallIC(ic); |
1905 break; | 1905 break; |
1906 } | 1906 } |
1907 } | 1907 } |
1908 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1908 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1909 context()->Plug(eax); | 1909 context()->Plug(eax); |
1910 } | 1910 } |
1911 | 1911 |
1912 | 1912 |
1913 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1913 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1914 Token::Value op) { | 1914 Token::Value op) { |
1915 if (var->IsUnallocated()) { | 1915 if (var->IsUnallocated()) { |
1916 // Global var, const, or let. | 1916 // Global var, const, or let. |
1917 __ mov(ecx, var->name()); | 1917 __ mov(ecx, var->name()); |
1918 __ mov(edx, GlobalObjectOperand()); | 1918 __ mov(edx, GlobalObjectOperand()); |
1919 Handle<Code> ic = is_classic_mode() | 1919 Handle<Code> ic = is_classic_mode() |
1920 ? isolate()->builtins()->StoreIC_Initialize() | 1920 ? isolate()->builtins()->StoreIC_Initialize() |
1921 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1921 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1922 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1922 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1923 | 1923 |
1924 } else if (op == Token::INIT_CONST) { | 1924 } else if (op == Token::INIT_CONST) { |
1925 // Const initializers need a write barrier. | 1925 // Const initializers need a write barrier. |
1926 ASSERT(!var->IsParameter()); // No const parameters. | 1926 ASSERT(!var->IsParameter()); // No const parameters. |
1927 if (var->IsStackLocal()) { | 1927 if (var->IsStackLocal()) { |
1928 Label skip; | 1928 Label skip; |
1929 __ mov(edx, StackOperand(var)); | 1929 __ mov(edx, StackOperand(var)); |
1930 __ cmp(edx, isolate()->factory()->the_hole_value()); | 1930 __ cmp(edx, isolate()->factory()->the_hole_value()); |
1931 __ j(not_equal, &skip); | 1931 __ j(not_equal, &skip); |
1932 __ mov(StackOperand(var), eax); | 1932 __ mov(StackOperand(var), eax); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2021 SetSourcePosition(expr->position()); | 2021 SetSourcePosition(expr->position()); |
2022 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 2022 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
2023 if (expr->ends_initialization_block()) { | 2023 if (expr->ends_initialization_block()) { |
2024 __ mov(edx, Operand(esp, 0)); | 2024 __ mov(edx, Operand(esp, 0)); |
2025 } else { | 2025 } else { |
2026 __ pop(edx); | 2026 __ pop(edx); |
2027 } | 2027 } |
2028 Handle<Code> ic = is_classic_mode() | 2028 Handle<Code> ic = is_classic_mode() |
2029 ? isolate()->builtins()->StoreIC_Initialize() | 2029 ? isolate()->builtins()->StoreIC_Initialize() |
2030 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2030 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2031 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2031 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2032 | 2032 |
2033 // If the assignment ends an initialization block, revert to fast case. | 2033 // If the assignment ends an initialization block, revert to fast case. |
2034 if (expr->ends_initialization_block()) { | 2034 if (expr->ends_initialization_block()) { |
2035 __ push(eax); // Result of assignment, saved even if not needed. | 2035 __ push(eax); // Result of assignment, saved even if not needed. |
2036 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 2036 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
2037 __ CallRuntime(Runtime::kToFastProperties, 1); | 2037 __ CallRuntime(Runtime::kToFastProperties, 1); |
2038 __ pop(eax); | 2038 __ pop(eax); |
2039 __ Drop(1); | 2039 __ Drop(1); |
2040 } | 2040 } |
2041 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2041 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 19 matching lines...) Expand all Loading... |
2061 if (expr->ends_initialization_block()) { | 2061 if (expr->ends_initialization_block()) { |
2062 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. | 2062 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. |
2063 } else { | 2063 } else { |
2064 __ pop(edx); | 2064 __ pop(edx); |
2065 } | 2065 } |
2066 // Record source code position before IC call. | 2066 // Record source code position before IC call. |
2067 SetSourcePosition(expr->position()); | 2067 SetSourcePosition(expr->position()); |
2068 Handle<Code> ic = is_classic_mode() | 2068 Handle<Code> ic = is_classic_mode() |
2069 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2069 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2070 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2070 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2071 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2071 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2072 | 2072 |
2073 // If the assignment ends an initialization block, revert to fast case. | 2073 // If the assignment ends an initialization block, revert to fast case. |
2074 if (expr->ends_initialization_block()) { | 2074 if (expr->ends_initialization_block()) { |
2075 __ pop(edx); | 2075 __ pop(edx); |
2076 __ push(eax); // Result of assignment, saved even if not needed. | 2076 __ push(eax); // Result of assignment, saved even if not needed. |
2077 __ push(edx); | 2077 __ push(edx); |
2078 __ CallRuntime(Runtime::kToFastProperties, 1); | 2078 __ CallRuntime(Runtime::kToFastProperties, 1); |
2079 __ pop(eax); | 2079 __ pop(eax); |
2080 } | 2080 } |
2081 | 2081 |
(...skipping 13 matching lines...) Expand all Loading... |
2095 } else { | 2095 } else { |
2096 VisitForStackValue(expr->obj()); | 2096 VisitForStackValue(expr->obj()); |
2097 VisitForAccumulatorValue(expr->key()); | 2097 VisitForAccumulatorValue(expr->key()); |
2098 __ pop(edx); | 2098 __ pop(edx); |
2099 EmitKeyedPropertyLoad(expr); | 2099 EmitKeyedPropertyLoad(expr); |
2100 context()->Plug(eax); | 2100 context()->Plug(eax); |
2101 } | 2101 } |
2102 } | 2102 } |
2103 | 2103 |
2104 | 2104 |
| 2105 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2106 RelocInfo::Mode rmode, |
| 2107 unsigned ast_id) { |
| 2108 ic_total_count_++; |
| 2109 __ call(code, rmode, ast_id); |
| 2110 } |
| 2111 |
| 2112 |
| 2113 |
| 2114 |
2105 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2115 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
2106 Handle<Object> name, | 2116 Handle<Object> name, |
2107 RelocInfo::Mode mode) { | 2117 RelocInfo::Mode mode) { |
2108 // Code common for calls using the IC. | 2118 // Code common for calls using the IC. |
2109 ZoneList<Expression*>* args = expr->arguments(); | 2119 ZoneList<Expression*>* args = expr->arguments(); |
2110 int arg_count = args->length(); | 2120 int arg_count = args->length(); |
2111 { PreservePositionScope scope(masm()->positions_recorder()); | 2121 { PreservePositionScope scope(masm()->positions_recorder()); |
2112 for (int i = 0; i < arg_count; i++) { | 2122 for (int i = 0; i < arg_count; i++) { |
2113 VisitForStackValue(args->at(i)); | 2123 VisitForStackValue(args->at(i)); |
2114 } | 2124 } |
2115 __ Set(ecx, Immediate(name)); | 2125 __ Set(ecx, Immediate(name)); |
2116 } | 2126 } |
2117 // Record source position of the IC call. | 2127 // Record source position of the IC call. |
2118 SetSourcePosition(expr->position()); | 2128 SetSourcePosition(expr->position()); |
2119 Handle<Code> ic = | 2129 Handle<Code> ic = |
2120 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2130 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
2121 __ call(ic, mode, expr->id()); | 2131 CallIC(ic, mode, expr->id()); |
2122 RecordJSReturnSite(expr); | 2132 RecordJSReturnSite(expr); |
2123 // Restore context register. | 2133 // Restore context register. |
2124 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2134 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2125 context()->Plug(eax); | 2135 context()->Plug(eax); |
2126 } | 2136 } |
2127 | 2137 |
2128 | 2138 |
2129 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2139 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2130 Expression* key) { | 2140 Expression* key) { |
2131 // Load the key. | 2141 // Load the key. |
(...skipping 11 matching lines...) Expand all Loading... |
2143 { PreservePositionScope scope(masm()->positions_recorder()); | 2153 { PreservePositionScope scope(masm()->positions_recorder()); |
2144 for (int i = 0; i < arg_count; i++) { | 2154 for (int i = 0; i < arg_count; i++) { |
2145 VisitForStackValue(args->at(i)); | 2155 VisitForStackValue(args->at(i)); |
2146 } | 2156 } |
2147 } | 2157 } |
2148 // Record source position of the IC call. | 2158 // Record source position of the IC call. |
2149 SetSourcePosition(expr->position()); | 2159 SetSourcePosition(expr->position()); |
2150 Handle<Code> ic = | 2160 Handle<Code> ic = |
2151 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2161 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
2152 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. | 2162 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. |
2153 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2163 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2154 RecordJSReturnSite(expr); | 2164 RecordJSReturnSite(expr); |
2155 // Restore context register. | 2165 // Restore context register. |
2156 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2166 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
2157 context()->DropAndPlug(1, eax); // Drop the key still on the stack. | 2167 context()->DropAndPlug(1, eax); // Drop the key still on the stack. |
2158 } | 2168 } |
2159 | 2169 |
2160 | 2170 |
2161 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2171 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2162 // Code common for calls using the call stub. | 2172 // Code common for calls using the call stub. |
2163 ZoneList<Expression*>* args = expr->arguments(); | 2173 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 1566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3730 for (int i = 0; i < arg_count; i++) { | 3740 for (int i = 0; i < arg_count; i++) { |
3731 VisitForStackValue(args->at(i)); | 3741 VisitForStackValue(args->at(i)); |
3732 } | 3742 } |
3733 | 3743 |
3734 if (expr->is_jsruntime()) { | 3744 if (expr->is_jsruntime()) { |
3735 // Call the JS runtime function via a call IC. | 3745 // Call the JS runtime function via a call IC. |
3736 __ Set(ecx, Immediate(expr->name())); | 3746 __ Set(ecx, Immediate(expr->name())); |
3737 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3747 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3738 Handle<Code> ic = | 3748 Handle<Code> ic = |
3739 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 3749 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
3740 __ call(ic, mode, expr->id()); | 3750 CallIC(ic, mode, expr->id()); |
3741 // Restore context register. | 3751 // Restore context register. |
3742 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 3752 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
3743 } else { | 3753 } else { |
3744 // Call the C runtime function. | 3754 // Call the C runtime function. |
3745 __ CallRuntime(expr->function(), arg_count); | 3755 __ CallRuntime(expr->function(), arg_count); |
3746 } | 3756 } |
3747 context()->Plug(eax); | 3757 context()->Plug(eax); |
3748 } | 3758 } |
3749 | 3759 |
3750 | 3760 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3888 const char* comment) { | 3898 const char* comment) { |
3889 Comment cmt(masm_, comment); | 3899 Comment cmt(masm_, comment); |
3890 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 3900 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
3891 UnaryOverwriteMode overwrite = | 3901 UnaryOverwriteMode overwrite = |
3892 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3902 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
3893 UnaryOpStub stub(expr->op(), overwrite); | 3903 UnaryOpStub stub(expr->op(), overwrite); |
3894 // UnaryOpStub expects the argument to be in the | 3904 // UnaryOpStub expects the argument to be in the |
3895 // accumulator register eax. | 3905 // accumulator register eax. |
3896 VisitForAccumulatorValue(expr->expression()); | 3906 VisitForAccumulatorValue(expr->expression()); |
3897 SetSourcePosition(expr->position()); | 3907 SetSourcePosition(expr->position()); |
3898 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 3908 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
3899 context()->Plug(eax); | 3909 context()->Plug(eax); |
3900 } | 3910 } |
3901 | 3911 |
3902 | 3912 |
3903 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 3913 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
3904 Comment cmnt(masm_, "[ CountOperation"); | 3914 Comment cmnt(masm_, "[ CountOperation"); |
3905 SetSourcePosition(expr->position()); | 3915 SetSourcePosition(expr->position()); |
3906 | 3916 |
3907 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 3917 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
3908 // as the left-hand side. | 3918 // as the left-hand side. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4008 } | 4018 } |
4009 } | 4019 } |
4010 | 4020 |
4011 // Record position before stub call. | 4021 // Record position before stub call. |
4012 SetSourcePosition(expr->position()); | 4022 SetSourcePosition(expr->position()); |
4013 | 4023 |
4014 // Call stub for +1/-1. | 4024 // Call stub for +1/-1. |
4015 __ mov(edx, eax); | 4025 __ mov(edx, eax); |
4016 __ mov(eax, Immediate(Smi::FromInt(1))); | 4026 __ mov(eax, Immediate(Smi::FromInt(1))); |
4017 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); | 4027 BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); |
4018 __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); | 4028 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
4019 patch_site.EmitPatchInfo(); | 4029 patch_site.EmitPatchInfo(); |
4020 __ bind(&done); | 4030 __ bind(&done); |
4021 | 4031 |
4022 // Store the value returned in eax. | 4032 // Store the value returned in eax. |
4023 switch (assign_type) { | 4033 switch (assign_type) { |
4024 case VARIABLE: | 4034 case VARIABLE: |
4025 if (expr->is_postfix()) { | 4035 if (expr->is_postfix()) { |
4026 // Perform the assignment as if via '='. | 4036 // Perform the assignment as if via '='. |
4027 { EffectContext context(this); | 4037 { EffectContext context(this); |
4028 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4038 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
(...skipping 13 matching lines...) Expand all Loading... |
4042 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4052 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4043 context()->Plug(eax); | 4053 context()->Plug(eax); |
4044 } | 4054 } |
4045 break; | 4055 break; |
4046 case NAMED_PROPERTY: { | 4056 case NAMED_PROPERTY: { |
4047 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 4057 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
4048 __ pop(edx); | 4058 __ pop(edx); |
4049 Handle<Code> ic = is_classic_mode() | 4059 Handle<Code> ic = is_classic_mode() |
4050 ? isolate()->builtins()->StoreIC_Initialize() | 4060 ? isolate()->builtins()->StoreIC_Initialize() |
4051 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 4061 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
4052 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4062 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4053 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4063 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4054 if (expr->is_postfix()) { | 4064 if (expr->is_postfix()) { |
4055 if (!context()->IsEffect()) { | 4065 if (!context()->IsEffect()) { |
4056 context()->PlugTOS(); | 4066 context()->PlugTOS(); |
4057 } | 4067 } |
4058 } else { | 4068 } else { |
4059 context()->Plug(eax); | 4069 context()->Plug(eax); |
4060 } | 4070 } |
4061 break; | 4071 break; |
4062 } | 4072 } |
4063 case KEYED_PROPERTY: { | 4073 case KEYED_PROPERTY: { |
4064 __ pop(ecx); | 4074 __ pop(ecx); |
4065 __ pop(edx); | 4075 __ pop(edx); |
4066 Handle<Code> ic = is_classic_mode() | 4076 Handle<Code> ic = is_classic_mode() |
4067 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4077 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4068 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4078 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4069 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4079 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4070 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4080 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4071 if (expr->is_postfix()) { | 4081 if (expr->is_postfix()) { |
4072 // Result is on the stack | 4082 // Result is on the stack |
4073 if (!context()->IsEffect()) { | 4083 if (!context()->IsEffect()) { |
4074 context()->PlugTOS(); | 4084 context()->PlugTOS(); |
4075 } | 4085 } |
4076 } else { | 4086 } else { |
4077 context()->Plug(eax); | 4087 context()->Plug(eax); |
4078 } | 4088 } |
4079 break; | 4089 break; |
4080 } | 4090 } |
4081 } | 4091 } |
4082 } | 4092 } |
4083 | 4093 |
4084 | 4094 |
4085 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4095 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4086 VariableProxy* proxy = expr->AsVariableProxy(); | 4096 VariableProxy* proxy = expr->AsVariableProxy(); |
4087 ASSERT(!context()->IsEffect()); | 4097 ASSERT(!context()->IsEffect()); |
4088 ASSERT(!context()->IsTest()); | 4098 ASSERT(!context()->IsTest()); |
4089 | 4099 |
4090 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4100 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4091 Comment cmnt(masm_, "Global variable"); | 4101 Comment cmnt(masm_, "Global variable"); |
4092 __ mov(eax, GlobalObjectOperand()); | 4102 __ mov(eax, GlobalObjectOperand()); |
4093 __ mov(ecx, Immediate(proxy->name())); | 4103 __ mov(ecx, Immediate(proxy->name())); |
4094 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 4104 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
4095 // Use a regular load, not a contextual load, to avoid a reference | 4105 // Use a regular load, not a contextual load, to avoid a reference |
4096 // error. | 4106 // error. |
4097 __ call(ic); | 4107 CallIC(ic); |
4098 PrepareForBailout(expr, TOS_REG); | 4108 PrepareForBailout(expr, TOS_REG); |
4099 context()->Plug(eax); | 4109 context()->Plug(eax); |
4100 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4110 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
4101 Label done, slow; | 4111 Label done, slow; |
4102 | 4112 |
4103 // Generate code for loading from variables potentially shadowed | 4113 // Generate code for loading from variables potentially shadowed |
4104 // by eval-introduced variables. | 4114 // by eval-introduced variables. |
4105 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4115 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
4106 | 4116 |
4107 __ bind(&slow); | 4117 __ bind(&slow); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4267 __ or_(ecx, eax); | 4277 __ or_(ecx, eax); |
4268 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); | 4278 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); |
4269 __ cmp(edx, eax); | 4279 __ cmp(edx, eax); |
4270 Split(cc, if_true, if_false, NULL); | 4280 Split(cc, if_true, if_false, NULL); |
4271 __ bind(&slow_case); | 4281 __ bind(&slow_case); |
4272 } | 4282 } |
4273 | 4283 |
4274 // Record position and call the compare IC. | 4284 // Record position and call the compare IC. |
4275 SetSourcePosition(expr->position()); | 4285 SetSourcePosition(expr->position()); |
4276 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4286 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4277 __ call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4287 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4278 patch_site.EmitPatchInfo(); | 4288 patch_site.EmitPatchInfo(); |
4279 | 4289 |
4280 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4290 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4281 __ test(eax, eax); | 4291 __ test(eax, eax); |
4282 Split(cc, if_true, if_false, fall_through); | 4292 Split(cc, if_true, if_false, fall_through); |
4283 } | 4293 } |
4284 } | 4294 } |
4285 | 4295 |
4286 // Convert the result of the comparison into one expected for this | 4296 // Convert the result of the comparison into one expected for this |
4287 // expression's context. | 4297 // expression's context. |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4426 *context_length = 0; | 4436 *context_length = 0; |
4427 return previous_; | 4437 return previous_; |
4428 } | 4438 } |
4429 | 4439 |
4430 | 4440 |
4431 #undef __ | 4441 #undef __ |
4432 | 4442 |
4433 } } // namespace v8::internal | 4443 } } // namespace v8::internal |
4434 | 4444 |
4435 #endif // V8_TARGET_ARCH_IA32 | 4445 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |