OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 28 matching lines...) Expand all Loading... |
39 #include "stub-cache.h" | 39 #include "stub-cache.h" |
40 | 40 |
41 #include "arm/code-stubs-arm.h" | 41 #include "arm/code-stubs-arm.h" |
42 | 42 |
43 namespace v8 { | 43 namespace v8 { |
44 namespace internal { | 44 namespace internal { |
45 | 45 |
46 #define __ ACCESS_MASM(masm_) | 46 #define __ ACCESS_MASM(masm_) |
47 | 47 |
48 | 48 |
| 49 static unsigned GetPropertyId(Property* property) { |
| 50 if (property->is_synthetic()) return AstNode::kNoNumber; |
| 51 return property->id(); |
| 52 } |
| 53 |
| 54 |
49 // A patch site is a location in the code which it is possible to patch. This | 55 // A patch site is a location in the code which it is possible to patch. This |
50 // class has a number of methods to emit the code which is patchable and the | 56 // class has a number of methods to emit the code which is patchable and the |
51 // method EmitPatchInfo to record a marker back to the patchable code. This | 57 // method EmitPatchInfo to record a marker back to the patchable code. This |
52 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit | 58 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit |
53 // immediate value is used) is the delta from the pc to the first instruction of | 59 // immediate value is used) is the delta from the pc to the first instruction of |
54 // the patchable code. | 60 // the patchable code. |
55 class JumpPatchSite BASE_EMBEDDED { | 61 class JumpPatchSite BASE_EMBEDDED { |
56 public: | 62 public: |
57 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { | 63 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { |
58 #ifdef DEBUG | 64 #ifdef DEBUG |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 __ cmp(r1, r0); | 856 __ cmp(r1, r0); |
851 __ b(ne, &next_test); | 857 __ b(ne, &next_test); |
852 __ Drop(1); // Switch value is no longer needed. | 858 __ Drop(1); // Switch value is no longer needed. |
853 __ b(clause->body_target()); | 859 __ b(clause->body_target()); |
854 __ bind(&slow_case); | 860 __ bind(&slow_case); |
855 } | 861 } |
856 | 862 |
857 // Record position before stub call for type feedback. | 863 // Record position before stub call for type feedback. |
858 SetSourcePosition(clause->position()); | 864 SetSourcePosition(clause->position()); |
859 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 865 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
860 EmitCallIC(ic, &patch_site); | 866 EmitCallIC(ic, &patch_site, clause->label()->id()); |
861 __ cmp(r0, Operand(0)); | 867 __ cmp(r0, Operand(0)); |
862 __ b(ne, &next_test); | 868 __ b(ne, &next_test); |
863 __ Drop(1); // Switch value is no longer needed. | 869 __ Drop(1); // Switch value is no longer needed. |
864 __ b(clause->body_target()); | 870 __ b(clause->body_target()); |
865 } | 871 } |
866 | 872 |
867 // Discard the test value and jump to the default if present, otherwise to | 873 // Discard the test value and jump to the default if present, otherwise to |
868 // the end of the statement. | 874 // the end of the statement. |
869 __ bind(&next_test); | 875 __ bind(&next_test); |
870 __ Drop(1); // Switch value is no longer needed. | 876 __ Drop(1); // Switch value is no longer needed. |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 context()->Plug(r0); | 1108 context()->Plug(r0); |
1103 } | 1109 } |
1104 | 1110 |
1105 | 1111 |
1106 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1112 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
1107 Comment cmnt(masm_, "[ VariableProxy"); | 1113 Comment cmnt(masm_, "[ VariableProxy"); |
1108 EmitVariableLoad(expr->var()); | 1114 EmitVariableLoad(expr->var()); |
1109 } | 1115 } |
1110 | 1116 |
1111 | 1117 |
| 1118 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( |
| 1119 Slot* slot, |
| 1120 TypeofState typeof_state, |
| 1121 Label* slow) { |
| 1122 Register current = cp; |
| 1123 Register next = r1; |
| 1124 Register temp = r2; |
| 1125 |
| 1126 Scope* s = scope(); |
| 1127 while (s != NULL) { |
| 1128 if (s->num_heap_slots() > 0) { |
| 1129 if (s->calls_eval()) { |
| 1130 // Check that extension is NULL. |
| 1131 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); |
| 1132 __ tst(temp, temp); |
| 1133 __ b(ne, slow); |
| 1134 } |
| 1135 // Load next context in chain. |
| 1136 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); |
| 1137 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); |
| 1138 // Walk the rest of the chain without clobbering cp. |
| 1139 current = next; |
| 1140 } |
| 1141 // If no outer scope calls eval, we do not need to check more |
| 1142 // context extensions. |
| 1143 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; |
| 1144 s = s->outer_scope(); |
| 1145 } |
| 1146 |
| 1147 if (s->is_eval_scope()) { |
| 1148 Label loop, fast; |
| 1149 if (!current.is(next)) { |
| 1150 __ Move(next, current); |
| 1151 } |
| 1152 __ bind(&loop); |
| 1153 // Terminate at global context. |
| 1154 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); |
| 1155 __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex); |
| 1156 __ cmp(temp, ip); |
| 1157 __ b(eq, &fast); |
| 1158 // Check that extension is NULL. |
| 1159 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); |
| 1160 __ tst(temp, temp); |
| 1161 __ b(ne, slow); |
| 1162 // Load next context in chain. |
| 1163 __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX)); |
| 1164 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); |
| 1165 __ b(&loop); |
| 1166 __ bind(&fast); |
| 1167 } |
| 1168 |
| 1169 __ ldr(r0, GlobalObjectOperand()); |
| 1170 __ mov(r2, Operand(slot->var()->name())); |
| 1171 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
| 1172 ? RelocInfo::CODE_TARGET |
| 1173 : RelocInfo::CODE_TARGET_CONTEXT; |
| 1174 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 1175 EmitCallIC(ic, mode); |
| 1176 } |
| 1177 |
| 1178 |
1112 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1179 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
1113 Slot* slot, | 1180 Slot* slot, |
1114 Label* slow) { | 1181 Label* slow) { |
1115 ASSERT(slot->type() == Slot::CONTEXT); | 1182 ASSERT(slot->type() == Slot::CONTEXT); |
1116 Register context = cp; | 1183 Register context = cp; |
1117 Register next = r3; | 1184 Register next = r3; |
1118 Register temp = r4; | 1185 Register temp = r4; |
1119 | 1186 |
1120 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { | 1187 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { |
1121 if (s->num_heap_slots() > 0) { | 1188 if (s->num_heap_slots() > 0) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1180 key_literal->handle()->IsSmi()) { | 1247 key_literal->handle()->IsSmi()) { |
1181 // Load arguments object if there are no eval-introduced | 1248 // Load arguments object if there are no eval-introduced |
1182 // variables. Then load the argument from the arguments | 1249 // variables. Then load the argument from the arguments |
1183 // object using keyed load. | 1250 // object using keyed load. |
1184 __ ldr(r1, | 1251 __ ldr(r1, |
1185 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1252 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
1186 slow)); | 1253 slow)); |
1187 __ mov(r0, Operand(key_literal->handle())); | 1254 __ mov(r0, Operand(key_literal->handle())); |
1188 Handle<Code> ic = | 1255 Handle<Code> ic = |
1189 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1256 isolate()->builtins()->KeyedLoadIC_Initialize(); |
1190 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1257 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, |
| 1258 GetPropertyId(property)); |
1191 __ jmp(done); | 1259 __ jmp(done); |
1192 } | 1260 } |
1193 } | 1261 } |
1194 } | 1262 } |
1195 } | 1263 } |
1196 } | 1264 } |
1197 | 1265 |
1198 | 1266 |
1199 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( | |
1200 Slot* slot, | |
1201 TypeofState typeof_state, | |
1202 Label* slow) { | |
1203 Register current = cp; | |
1204 Register next = r1; | |
1205 Register temp = r2; | |
1206 | |
1207 Scope* s = scope(); | |
1208 while (s != NULL) { | |
1209 if (s->num_heap_slots() > 0) { | |
1210 if (s->calls_eval()) { | |
1211 // Check that extension is NULL. | |
1212 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | |
1213 __ tst(temp, temp); | |
1214 __ b(ne, slow); | |
1215 } | |
1216 // Load next context in chain. | |
1217 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); | |
1218 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | |
1219 // Walk the rest of the chain without clobbering cp. | |
1220 current = next; | |
1221 } | |
1222 // If no outer scope calls eval, we do not need to check more | |
1223 // context extensions. | |
1224 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; | |
1225 s = s->outer_scope(); | |
1226 } | |
1227 | |
1228 if (s->is_eval_scope()) { | |
1229 Label loop, fast; | |
1230 if (!current.is(next)) { | |
1231 __ Move(next, current); | |
1232 } | |
1233 __ bind(&loop); | |
1234 // Terminate at global context. | |
1235 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); | |
1236 __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex); | |
1237 __ cmp(temp, ip); | |
1238 __ b(eq, &fast); | |
1239 // Check that extension is NULL. | |
1240 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); | |
1241 __ tst(temp, temp); | |
1242 __ b(ne, slow); | |
1243 // Load next context in chain. | |
1244 __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX)); | |
1245 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | |
1246 __ b(&loop); | |
1247 __ bind(&fast); | |
1248 } | |
1249 | |
1250 __ ldr(r0, GlobalObjectOperand()); | |
1251 __ mov(r2, Operand(slot->var()->name())); | |
1252 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | |
1253 ? RelocInfo::CODE_TARGET | |
1254 : RelocInfo::CODE_TARGET_CONTEXT; | |
1255 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
1256 EmitCallIC(ic, mode); | |
1257 } | |
1258 | |
1259 | |
1260 void FullCodeGenerator::EmitVariableLoad(Variable* var) { | 1267 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1261 // Four cases: non-this global variables, lookup slots, all other | 1268 // Four cases: non-this global variables, lookup slots, all other |
1262 // types of slots, and parameters that rewrite to explicit property | 1269 // types of slots, and parameters that rewrite to explicit property |
1263 // accesses on the arguments object. | 1270 // accesses on the arguments object. |
1264 Slot* slot = var->AsSlot(); | 1271 Slot* slot = var->AsSlot(); |
1265 Property* property = var->AsProperty(); | 1272 Property* property = var->AsProperty(); |
1266 | 1273 |
1267 if (var->is_global() && !var->is_this()) { | 1274 if (var->is_global() && !var->is_this()) { |
1268 Comment cmnt(masm_, "Global variable"); | 1275 Comment cmnt(masm_, "Global variable"); |
1269 // Use inline caching. Variable name is passed in r2 and the global | 1276 // Use inline caching. Variable name is passed in r2 and the global |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 // Assert that the key is a smi. | 1330 // Assert that the key is a smi. |
1324 Literal* key_literal = property->key()->AsLiteral(); | 1331 Literal* key_literal = property->key()->AsLiteral(); |
1325 ASSERT_NOT_NULL(key_literal); | 1332 ASSERT_NOT_NULL(key_literal); |
1326 ASSERT(key_literal->handle()->IsSmi()); | 1333 ASSERT(key_literal->handle()->IsSmi()); |
1327 | 1334 |
1328 // Load the key. | 1335 // Load the key. |
1329 __ mov(r0, Operand(key_literal->handle())); | 1336 __ mov(r0, Operand(key_literal->handle())); |
1330 | 1337 |
1331 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1338 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1332 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1339 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1333 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1340 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, GetPropertyId(property)); |
1334 context()->Plug(r0); | 1341 context()->Plug(r0); |
1335 } | 1342 } |
1336 } | 1343 } |
1337 | 1344 |
1338 | 1345 |
1339 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1346 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1340 Comment cmnt(masm_, "[ RegExpLiteral"); | 1347 Comment cmnt(masm_, "[ RegExpLiteral"); |
1341 Label materialized; | 1348 Label materialized; |
1342 // Registers will be used as follows: | 1349 // Registers will be used as follows: |
1343 // r5 = materialized value (RegExp literal) | 1350 // r5 = materialized value (RegExp literal) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 UNREACHABLE(); | 1438 UNREACHABLE(); |
1432 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1439 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1433 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1440 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
1434 // Fall through. | 1441 // Fall through. |
1435 case ObjectLiteral::Property::COMPUTED: | 1442 case ObjectLiteral::Property::COMPUTED: |
1436 if (key->handle()->IsSymbol()) { | 1443 if (key->handle()->IsSymbol()) { |
1437 if (property->emit_store()) { | 1444 if (property->emit_store()) { |
1438 VisitForAccumulatorValue(value); | 1445 VisitForAccumulatorValue(value); |
1439 __ mov(r2, Operand(key->handle())); | 1446 __ mov(r2, Operand(key->handle())); |
1440 __ ldr(r1, MemOperand(sp)); | 1447 __ ldr(r1, MemOperand(sp)); |
1441 Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize(); | 1448 Handle<Code> ic = is_strict_mode() |
1442 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1449 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 1450 : isolate()->builtins()->StoreIC_Initialize(); |
| 1451 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, key->id()); |
1443 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1452 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1444 } else { | 1453 } else { |
1445 VisitForEffect(value); | 1454 VisitForEffect(value); |
1446 } | 1455 } |
1447 break; | 1456 break; |
1448 } | 1457 } |
1449 // Fall through. | 1458 // Fall through. |
1450 case ObjectLiteral::Property::PROTOTYPE: | 1459 case ObjectLiteral::Property::PROTOTYPE: |
1451 // Duplicate receiver on stack. | 1460 // Duplicate receiver on stack. |
1452 __ ldr(r0, MemOperand(sp)); | 1461 __ ldr(r0, MemOperand(sp)); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1644 Token::Value op = expr->binary_op(); | 1653 Token::Value op = expr->binary_op(); |
1645 __ push(r0); // Left operand goes on the stack. | 1654 __ push(r0); // Left operand goes on the stack. |
1646 VisitForAccumulatorValue(expr->value()); | 1655 VisitForAccumulatorValue(expr->value()); |
1647 | 1656 |
1648 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1657 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
1649 ? OVERWRITE_RIGHT | 1658 ? OVERWRITE_RIGHT |
1650 : NO_OVERWRITE; | 1659 : NO_OVERWRITE; |
1651 SetSourcePosition(expr->position() + 1); | 1660 SetSourcePosition(expr->position() + 1); |
1652 AccumulatorValueContext context(this); | 1661 AccumulatorValueContext context(this); |
1653 if (ShouldInlineSmiCase(op)) { | 1662 if (ShouldInlineSmiCase(op)) { |
1654 EmitInlineSmiBinaryOp(expr, | 1663 EmitInlineSmiBinaryOp(expr->binary_operation(), |
1655 op, | 1664 op, |
1656 mode, | 1665 mode, |
1657 expr->target(), | 1666 expr->target(), |
1658 expr->value()); | 1667 expr->value()); |
1659 } else { | 1668 } else { |
1660 EmitBinaryOp(op, mode); | 1669 EmitBinaryOp(expr->binary_operation(), op, mode); |
1661 } | 1670 } |
1662 | 1671 |
1663 // Deoptimization point in case the binary operation may have side effects. | 1672 // Deoptimization point in case the binary operation may have side effects. |
1664 PrepareForBailout(expr->binary_operation(), TOS_REG); | 1673 PrepareForBailout(expr->binary_operation(), TOS_REG); |
1665 } else { | 1674 } else { |
1666 VisitForAccumulatorValue(expr->value()); | 1675 VisitForAccumulatorValue(expr->value()); |
1667 } | 1676 } |
1668 | 1677 |
1669 // Record source position before possible IC call. | 1678 // Record source position before possible IC call. |
1670 SetSourcePosition(expr->position()); | 1679 SetSourcePosition(expr->position()); |
(...skipping 15 matching lines...) Expand all Loading... |
1686 } | 1695 } |
1687 } | 1696 } |
1688 | 1697 |
1689 | 1698 |
1690 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1699 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1691 SetSourcePosition(prop->position()); | 1700 SetSourcePosition(prop->position()); |
1692 Literal* key = prop->key()->AsLiteral(); | 1701 Literal* key = prop->key()->AsLiteral(); |
1693 __ mov(r2, Operand(key->handle())); | 1702 __ mov(r2, Operand(key->handle())); |
1694 // Call load IC. It has arguments receiver and property name r0 and r2. | 1703 // Call load IC. It has arguments receiver and property name r0 and r2. |
1695 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1704 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1696 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1705 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, GetPropertyId(prop)); |
1697 } | 1706 } |
1698 | 1707 |
1699 | 1708 |
1700 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1709 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1701 SetSourcePosition(prop->position()); | 1710 SetSourcePosition(prop->position()); |
1702 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1711 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1703 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1712 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1704 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1713 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, GetPropertyId(prop)); |
1705 } | 1714 } |
1706 | 1715 |
1707 | 1716 |
1708 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1717 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1709 Token::Value op, | 1718 Token::Value op, |
1710 OverwriteMode mode, | 1719 OverwriteMode mode, |
1711 Expression* left_expr, | 1720 Expression* left_expr, |
1712 Expression* right_expr) { | 1721 Expression* right_expr) { |
1713 Label done, smi_case, stub_call; | 1722 Label done, smi_case, stub_call; |
1714 | 1723 |
1715 Register scratch1 = r2; | 1724 Register scratch1 = r2; |
1716 Register scratch2 = r3; | 1725 Register scratch2 = r3; |
1717 | 1726 |
1718 // Get the arguments. | 1727 // Get the arguments. |
1719 Register left = r1; | 1728 Register left = r1; |
1720 Register right = r0; | 1729 Register right = r0; |
1721 __ pop(left); | 1730 __ pop(left); |
1722 | 1731 |
1723 // Perform combined smi check on both operands. | 1732 // Perform combined smi check on both operands. |
1724 __ orr(scratch1, left, Operand(right)); | 1733 __ orr(scratch1, left, Operand(right)); |
1725 STATIC_ASSERT(kSmiTag == 0); | 1734 STATIC_ASSERT(kSmiTag == 0); |
1726 JumpPatchSite patch_site(masm_); | 1735 JumpPatchSite patch_site(masm_); |
1727 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1736 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1728 | 1737 |
1729 __ bind(&stub_call); | 1738 __ bind(&stub_call); |
1730 TypeRecordingBinaryOpStub stub(op, mode); | 1739 TypeRecordingBinaryOpStub stub(op, mode); |
1731 EmitCallIC(stub.GetCode(), &patch_site); | 1740 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); |
1732 __ jmp(&done); | 1741 __ jmp(&done); |
1733 | 1742 |
1734 __ bind(&smi_case); | 1743 __ bind(&smi_case); |
1735 // Smi case. This code works the same way as the smi-smi case in the type | 1744 // Smi case. This code works the same way as the smi-smi case in the type |
1736 // recording binary operation stub, see | 1745 // recording binary operation stub, see |
1737 // TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments. | 1746 // TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments. |
1738 switch (op) { | 1747 switch (op) { |
1739 case Token::SAR: | 1748 case Token::SAR: |
1740 __ b(&stub_call); | 1749 __ b(&stub_call); |
1741 __ GetLeastBitsFromSmi(scratch1, right, 5); | 1750 __ GetLeastBitsFromSmi(scratch1, right, 5); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 break; | 1806 break; |
1798 default: | 1807 default: |
1799 UNREACHABLE(); | 1808 UNREACHABLE(); |
1800 } | 1809 } |
1801 | 1810 |
1802 __ bind(&done); | 1811 __ bind(&done); |
1803 context()->Plug(r0); | 1812 context()->Plug(r0); |
1804 } | 1813 } |
1805 | 1814 |
1806 | 1815 |
1807 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1816 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
| 1817 Token::Value op, |
1808 OverwriteMode mode) { | 1818 OverwriteMode mode) { |
1809 __ pop(r1); | 1819 __ pop(r1); |
1810 TypeRecordingBinaryOpStub stub(op, mode); | 1820 TypeRecordingBinaryOpStub stub(op, mode); |
1811 EmitCallIC(stub.GetCode(), NULL); | 1821 EmitCallIC(stub.GetCode(), NULL, expr->id()); |
1812 context()->Plug(r0); | 1822 context()->Plug(r0); |
1813 } | 1823 } |
1814 | 1824 |
1815 | 1825 |
1816 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1826 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1817 // Invalid left-hand sides are rewritten to have a 'throw | 1827 // Invalid left-hand sides are rewritten to have a 'throw |
1818 // ReferenceError' on the left-hand side. | 1828 // ReferenceError' on the left-hand side. |
1819 if (!expr->IsValidLeftHandSide()) { | 1829 if (!expr->IsValidLeftHandSide()) { |
1820 VisitForEffect(expr); | 1830 VisitForEffect(expr); |
1821 return; | 1831 return; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1999 // receiver into fast case. | 2009 // receiver into fast case. |
2000 if (expr->ends_initialization_block()) { | 2010 if (expr->ends_initialization_block()) { |
2001 __ ldr(r1, MemOperand(sp)); | 2011 __ ldr(r1, MemOperand(sp)); |
2002 } else { | 2012 } else { |
2003 __ pop(r1); | 2013 __ pop(r1); |
2004 } | 2014 } |
2005 | 2015 |
2006 Handle<Code> ic = is_strict_mode() | 2016 Handle<Code> ic = is_strict_mode() |
2007 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2017 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2008 : isolate()->builtins()->StoreIC_Initialize(); | 2018 : isolate()->builtins()->StoreIC_Initialize(); |
2009 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2019 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); |
2010 | 2020 |
2011 // If the assignment ends an initialization block, revert to fast case. | 2021 // If the assignment ends an initialization block, revert to fast case. |
2012 if (expr->ends_initialization_block()) { | 2022 if (expr->ends_initialization_block()) { |
2013 __ push(r0); // Result of assignment, saved even if not needed. | 2023 __ push(r0); // Result of assignment, saved even if not needed. |
2014 // Receiver is under the result value. | 2024 // Receiver is under the result value. |
2015 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2025 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2016 __ push(ip); | 2026 __ push(ip); |
2017 __ CallRuntime(Runtime::kToFastProperties, 1); | 2027 __ CallRuntime(Runtime::kToFastProperties, 1); |
2018 __ pop(r0); | 2028 __ pop(r0); |
2019 __ Drop(1); | 2029 __ Drop(1); |
(...skipping 25 matching lines...) Expand all Loading... |
2045 // receiver into fast case. | 2055 // receiver into fast case. |
2046 if (expr->ends_initialization_block()) { | 2056 if (expr->ends_initialization_block()) { |
2047 __ ldr(r2, MemOperand(sp)); | 2057 __ ldr(r2, MemOperand(sp)); |
2048 } else { | 2058 } else { |
2049 __ pop(r2); | 2059 __ pop(r2); |
2050 } | 2060 } |
2051 | 2061 |
2052 Handle<Code> ic = is_strict_mode() | 2062 Handle<Code> ic = is_strict_mode() |
2053 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 2063 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
2054 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 2064 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
2055 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2065 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); |
2056 | 2066 |
2057 // If the assignment ends an initialization block, revert to fast case. | 2067 // If the assignment ends an initialization block, revert to fast case. |
2058 if (expr->ends_initialization_block()) { | 2068 if (expr->ends_initialization_block()) { |
2059 __ push(r0); // Result of assignment, saved even if not needed. | 2069 __ push(r0); // Result of assignment, saved even if not needed. |
2060 // Receiver is under the result value. | 2070 // Receiver is under the result value. |
2061 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2071 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2062 __ push(ip); | 2072 __ push(ip); |
2063 __ CallRuntime(Runtime::kToFastProperties, 1); | 2073 __ CallRuntime(Runtime::kToFastProperties, 1); |
2064 __ pop(r0); | 2074 __ pop(r0); |
2065 __ Drop(1); | 2075 __ Drop(1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2097 VisitForStackValue(args->at(i)); | 2107 VisitForStackValue(args->at(i)); |
2098 } | 2108 } |
2099 __ mov(r2, Operand(name)); | 2109 __ mov(r2, Operand(name)); |
2100 } | 2110 } |
2101 // Record source position for debugger. | 2111 // Record source position for debugger. |
2102 SetSourcePosition(expr->position()); | 2112 SetSourcePosition(expr->position()); |
2103 // Call the IC initialization code. | 2113 // Call the IC initialization code. |
2104 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2114 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2105 Handle<Code> ic = | 2115 Handle<Code> ic = |
2106 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 2116 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
2107 EmitCallIC(ic, mode); | 2117 EmitCallIC(ic, mode, expr->id()); |
2108 RecordJSReturnSite(expr); | 2118 RecordJSReturnSite(expr); |
2109 // Restore context register. | 2119 // Restore context register. |
2110 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2120 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2111 context()->Plug(r0); | 2121 context()->Plug(r0); |
2112 } | 2122 } |
2113 | 2123 |
2114 | 2124 |
2115 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2125 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2116 Expression* key, | 2126 Expression* key, |
2117 RelocInfo::Mode mode) { | 2127 RelocInfo::Mode mode) { |
(...skipping 14 matching lines...) Expand all Loading... |
2132 VisitForStackValue(args->at(i)); | 2142 VisitForStackValue(args->at(i)); |
2133 } | 2143 } |
2134 } | 2144 } |
2135 // Record source position for debugger. | 2145 // Record source position for debugger. |
2136 SetSourcePosition(expr->position()); | 2146 SetSourcePosition(expr->position()); |
2137 // Call the IC initialization code. | 2147 // Call the IC initialization code. |
2138 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2148 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2139 Handle<Code> ic = | 2149 Handle<Code> ic = |
2140 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); | 2150 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
2141 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2151 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2142 EmitCallIC(ic, mode); | 2152 EmitCallIC(ic, mode, expr->id()); |
2143 RecordJSReturnSite(expr); | 2153 RecordJSReturnSite(expr); |
2144 // Restore context register. | 2154 // Restore context register. |
2145 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2155 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2146 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2156 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
2147 } | 2157 } |
2148 | 2158 |
2149 | 2159 |
2150 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2160 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
2151 // Code common for calls using the call stub. | 2161 // Code common for calls using the call stub. |
2152 ZoneList<Expression*>* args = expr->arguments(); | 2162 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2308 EmitCallWithStub(expr); | 2318 EmitCallWithStub(expr); |
2309 } else if (fun->AsProperty() != NULL) { | 2319 } else if (fun->AsProperty() != NULL) { |
2310 // Call to an object property. | 2320 // Call to an object property. |
2311 Property* prop = fun->AsProperty(); | 2321 Property* prop = fun->AsProperty(); |
2312 Literal* key = prop->key()->AsLiteral(); | 2322 Literal* key = prop->key()->AsLiteral(); |
2313 if (key != NULL && key->handle()->IsSymbol()) { | 2323 if (key != NULL && key->handle()->IsSymbol()) { |
2314 // Call to a named property, use call IC. | 2324 // Call to a named property, use call IC. |
2315 { PreservePositionScope scope(masm()->positions_recorder()); | 2325 { PreservePositionScope scope(masm()->positions_recorder()); |
2316 VisitForStackValue(prop->obj()); | 2326 VisitForStackValue(prop->obj()); |
2317 } | 2327 } |
2318 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 2328 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET_WITH_ID); |
2319 } else { | 2329 } else { |
2320 // Call to a keyed property. | 2330 // Call to a keyed property. |
2321 // For a synthetic property use keyed load IC followed by function call, | 2331 // For a synthetic property use keyed load IC followed by function call, |
2322 // for a regular property use keyed CallIC. | 2332 // for a regular property use keyed EmitCallIC. |
2323 if (prop->is_synthetic()) { | 2333 if (prop->is_synthetic()) { |
2324 // Do not visit the object and key subexpressions (they are shared | 2334 // Do not visit the object and key subexpressions (they are shared |
2325 // by all occurrences of the same rewritten parameter). | 2335 // by all occurrences of the same rewritten parameter). |
2326 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 2336 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
2327 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); | 2337 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); |
2328 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); | 2338 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); |
2329 MemOperand operand = EmitSlotSearch(slot, r1); | 2339 MemOperand operand = EmitSlotSearch(slot, r1); |
2330 __ ldr(r1, operand); | 2340 __ ldr(r1, operand); |
2331 | 2341 |
2332 ASSERT(prop->key()->AsLiteral() != NULL); | 2342 ASSERT(prop->key()->AsLiteral() != NULL); |
2333 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2343 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
2334 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); | 2344 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); |
2335 | 2345 |
2336 // Record source code position for IC call. | 2346 // Record source code position for IC call. |
2337 SetSourcePosition(prop->position()); | 2347 SetSourcePosition(prop->position()); |
2338 | 2348 |
2339 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2349 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2340 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 2350 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, GetPropertyId(prop)); |
2341 __ ldr(r1, GlobalObjectOperand()); | 2351 __ ldr(r1, GlobalObjectOperand()); |
2342 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2352 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2343 __ Push(r0, r1); // Function, receiver. | 2353 __ Push(r0, r1); // Function, receiver. |
2344 EmitCallWithStub(expr); | 2354 EmitCallWithStub(expr); |
2345 } else { | 2355 } else { |
2346 { PreservePositionScope scope(masm()->positions_recorder()); | 2356 { PreservePositionScope scope(masm()->positions_recorder()); |
2347 VisitForStackValue(prop->obj()); | 2357 VisitForStackValue(prop->obj()); |
2348 } | 2358 } |
2349 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 2359 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET_WITH_ID); |
2350 } | 2360 } |
2351 } | 2361 } |
2352 } else { | 2362 } else { |
2353 { PreservePositionScope scope(masm()->positions_recorder()); | 2363 { PreservePositionScope scope(masm()->positions_recorder()); |
2354 VisitForStackValue(fun); | 2364 VisitForStackValue(fun); |
2355 } | 2365 } |
2356 // Load global receiver object. | 2366 // Load global receiver object. |
2357 __ ldr(r1, GlobalObjectOperand()); | 2367 __ ldr(r1, GlobalObjectOperand()); |
2358 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2368 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2359 __ push(r1); | 2369 __ push(r1); |
(...skipping 1291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3651 int arg_count = args->length(); | 3661 int arg_count = args->length(); |
3652 for (int i = 0; i < arg_count; i++) { | 3662 for (int i = 0; i < arg_count; i++) { |
3653 VisitForStackValue(args->at(i)); | 3663 VisitForStackValue(args->at(i)); |
3654 } | 3664 } |
3655 | 3665 |
3656 if (expr->is_jsruntime()) { | 3666 if (expr->is_jsruntime()) { |
3657 // Call the JS runtime function. | 3667 // Call the JS runtime function. |
3658 __ mov(r2, Operand(expr->name())); | 3668 __ mov(r2, Operand(expr->name())); |
3659 Handle<Code> ic = | 3669 Handle<Code> ic = |
3660 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); | 3670 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); |
3661 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3671 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); |
3662 // Restore context register. | 3672 // Restore context register. |
3663 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3673 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3664 } else { | 3674 } else { |
3665 // Call the C runtime function. | 3675 // Call the C runtime function. |
3666 __ CallRuntime(expr->function(), arg_count); | 3676 __ CallRuntime(expr->function(), arg_count); |
3667 } | 3677 } |
3668 context()->Plug(r0); | 3678 context()->Plug(r0); |
3669 } | 3679 } |
3670 | 3680 |
3671 | 3681 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3930 __ bind(&stub_call); | 3940 __ bind(&stub_call); |
3931 // Call stub. Undo operation first. | 3941 // Call stub. Undo operation first. |
3932 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 3942 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
3933 } | 3943 } |
3934 __ mov(r1, Operand(Smi::FromInt(count_value))); | 3944 __ mov(r1, Operand(Smi::FromInt(count_value))); |
3935 | 3945 |
3936 // Record position before stub call. | 3946 // Record position before stub call. |
3937 SetSourcePosition(expr->position()); | 3947 SetSourcePosition(expr->position()); |
3938 | 3948 |
3939 TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 3949 TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
3940 EmitCallIC(stub.GetCode(), &patch_site); | 3950 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); |
3941 __ bind(&done); | 3951 __ bind(&done); |
3942 | 3952 |
3943 // Store the value returned in r0. | 3953 // Store the value returned in r0. |
3944 switch (assign_type) { | 3954 switch (assign_type) { |
3945 case VARIABLE: | 3955 case VARIABLE: |
3946 if (expr->is_postfix()) { | 3956 if (expr->is_postfix()) { |
3947 { EffectContext context(this); | 3957 { EffectContext context(this); |
3948 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3958 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3949 Token::ASSIGN); | 3959 Token::ASSIGN); |
3950 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3960 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 10 matching lines...) Expand all Loading... |
3961 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3971 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3962 context()->Plug(r0); | 3972 context()->Plug(r0); |
3963 } | 3973 } |
3964 break; | 3974 break; |
3965 case NAMED_PROPERTY: { | 3975 case NAMED_PROPERTY: { |
3966 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 3976 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
3967 __ pop(r1); | 3977 __ pop(r1); |
3968 Handle<Code> ic = is_strict_mode() | 3978 Handle<Code> ic = is_strict_mode() |
3969 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3979 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3970 : isolate()->builtins()->StoreIC_Initialize(); | 3980 : isolate()->builtins()->StoreIC_Initialize(); |
3971 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3981 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); |
3972 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3982 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3973 if (expr->is_postfix()) { | 3983 if (expr->is_postfix()) { |
3974 if (!context()->IsEffect()) { | 3984 if (!context()->IsEffect()) { |
3975 context()->PlugTOS(); | 3985 context()->PlugTOS(); |
3976 } | 3986 } |
3977 } else { | 3987 } else { |
3978 context()->Plug(r0); | 3988 context()->Plug(r0); |
3979 } | 3989 } |
3980 break; | 3990 break; |
3981 } | 3991 } |
3982 case KEYED_PROPERTY: { | 3992 case KEYED_PROPERTY: { |
3983 __ pop(r1); // Key. | 3993 __ pop(r1); // Key. |
3984 __ pop(r2); // Receiver. | 3994 __ pop(r2); // Receiver. |
3985 Handle<Code> ic = is_strict_mode() | 3995 Handle<Code> ic = is_strict_mode() |
3986 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3996 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3987 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3997 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3988 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 3998 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); |
3989 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3999 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3990 if (expr->is_postfix()) { | 4000 if (expr->is_postfix()) { |
3991 if (!context()->IsEffect()) { | 4001 if (!context()->IsEffect()) { |
3992 context()->PlugTOS(); | 4002 context()->PlugTOS(); |
3993 } | 4003 } |
3994 } else { | 4004 } else { |
3995 context()->Plug(r0); | 4005 context()->Plug(r0); |
3996 } | 4006 } |
3997 break; | 4007 break; |
3998 } | 4008 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4207 __ orr(r2, r0, Operand(r1)); | 4217 __ orr(r2, r0, Operand(r1)); |
4208 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4218 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
4209 __ cmp(r1, r0); | 4219 __ cmp(r1, r0); |
4210 Split(cond, if_true, if_false, NULL); | 4220 Split(cond, if_true, if_false, NULL); |
4211 __ bind(&slow_case); | 4221 __ bind(&slow_case); |
4212 } | 4222 } |
4213 | 4223 |
4214 // Record position and call the compare IC. | 4224 // Record position and call the compare IC. |
4215 SetSourcePosition(expr->position()); | 4225 SetSourcePosition(expr->position()); |
4216 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4226 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4217 EmitCallIC(ic, &patch_site); | 4227 EmitCallIC(ic, &patch_site, expr->id()); |
4218 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4228 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4219 __ cmp(r0, Operand(0)); | 4229 __ cmp(r0, Operand(0)); |
4220 Split(cond, if_true, if_false, fall_through); | 4230 Split(cond, if_true, if_false, fall_through); |
4221 } | 4231 } |
4222 } | 4232 } |
4223 | 4233 |
4224 // Convert the result of the comparison into one expected for this | 4234 // Convert the result of the comparison into one expected for this |
4225 // expression's context. | 4235 // expression's context. |
4226 context()->Plug(if_true, if_false); | 4236 context()->Plug(if_true, if_false); |
4227 } | 4237 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4269 Register FullCodeGenerator::result_register() { | 4279 Register FullCodeGenerator::result_register() { |
4270 return r0; | 4280 return r0; |
4271 } | 4281 } |
4272 | 4282 |
4273 | 4283 |
4274 Register FullCodeGenerator::context_register() { | 4284 Register FullCodeGenerator::context_register() { |
4275 return cp; | 4285 return cp; |
4276 } | 4286 } |
4277 | 4287 |
4278 | 4288 |
4279 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { | 4289 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, |
| 4290 RelocInfo::Mode mode, |
| 4291 unsigned ast_id) { |
4280 ASSERT(mode == RelocInfo::CODE_TARGET || | 4292 ASSERT(mode == RelocInfo::CODE_TARGET || |
4281 mode == RelocInfo::CODE_TARGET_CONTEXT); | 4293 mode == RelocInfo::CODE_TARGET_CONTEXT || |
| 4294 mode == RelocInfo::CODE_TARGET_WITH_ID); |
4282 Counters* counters = isolate()->counters(); | 4295 Counters* counters = isolate()->counters(); |
4283 switch (ic->kind()) { | 4296 switch (ic->kind()) { |
4284 case Code::LOAD_IC: | 4297 case Code::LOAD_IC: |
4285 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | 4298 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); |
4286 break; | 4299 break; |
4287 case Code::KEYED_LOAD_IC: | 4300 case Code::KEYED_LOAD_IC: |
4288 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | 4301 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); |
4289 break; | 4302 break; |
4290 case Code::STORE_IC: | 4303 case Code::STORE_IC: |
4291 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | 4304 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); |
4292 break; | 4305 break; |
4293 case Code::KEYED_STORE_IC: | 4306 case Code::KEYED_STORE_IC: |
4294 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | 4307 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); |
4295 default: | 4308 default: |
4296 break; | 4309 break; |
4297 } | 4310 } |
4298 | 4311 if (mode == RelocInfo::CODE_TARGET_WITH_ID) { |
4299 __ Call(ic, mode); | 4312 ASSERT(ast_id != kNoASTId); |
| 4313 __ CallWithAstId(ic, mode, ast_id); |
| 4314 } else { |
| 4315 ASSERT(ast_id == kNoASTId); |
| 4316 __ Call(ic, mode); |
| 4317 } |
4300 } | 4318 } |
4301 | 4319 |
4302 | 4320 |
4303 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { | 4321 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, |
| 4322 JumpPatchSite* patch_site, |
| 4323 unsigned ast_id) { |
4304 Counters* counters = isolate()->counters(); | 4324 Counters* counters = isolate()->counters(); |
4305 switch (ic->kind()) { | 4325 switch (ic->kind()) { |
4306 case Code::LOAD_IC: | 4326 case Code::LOAD_IC: |
4307 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | 4327 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); |
4308 break; | 4328 break; |
4309 case Code::KEYED_LOAD_IC: | 4329 case Code::KEYED_LOAD_IC: |
4310 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | 4330 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); |
4311 break; | 4331 break; |
4312 case Code::STORE_IC: | 4332 case Code::STORE_IC: |
4313 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | 4333 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); |
4314 break; | 4334 break; |
4315 case Code::KEYED_STORE_IC: | 4335 case Code::KEYED_STORE_IC: |
4316 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | 4336 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); |
4317 default: | 4337 default: |
4318 break; | 4338 break; |
4319 } | 4339 } |
4320 | 4340 |
4321 __ Call(ic, RelocInfo::CODE_TARGET); | 4341 if (ast_id != kNoASTId) { |
| 4342 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); |
| 4343 } else { |
| 4344 __ Call(ic, RelocInfo::CODE_TARGET); |
| 4345 } |
4322 if (patch_site != NULL && patch_site->is_bound()) { | 4346 if (patch_site != NULL && patch_site->is_bound()) { |
4323 patch_site->EmitPatchInfo(); | 4347 patch_site->EmitPatchInfo(); |
4324 } else { | 4348 } else { |
4325 __ nop(); // Signals no inlined code. | 4349 __ nop(); // Signals no inlined code. |
4326 } | 4350 } |
4327 } | 4351 } |
4328 | 4352 |
4329 | 4353 |
4330 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4354 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4331 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4355 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4364 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4388 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
4365 __ add(pc, r1, Operand(masm_->CodeObject())); | 4389 __ add(pc, r1, Operand(masm_->CodeObject())); |
4366 } | 4390 } |
4367 | 4391 |
4368 | 4392 |
4369 #undef __ | 4393 #undef __ |
4370 | 4394 |
4371 } } // namespace v8::internal | 4395 } } // namespace v8::internal |
4372 | 4396 |
4373 #endif // V8_TARGET_ARCH_ARM | 4397 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |