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 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 __ mov(r2, r0); | 776 __ mov(r2, r0); |
777 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 777 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
778 } | 778 } |
779 ASSERT(prop->key()->AsLiteral() != NULL && | 779 ASSERT(prop->key()->AsLiteral() != NULL && |
780 prop->key()->AsLiteral()->handle()->IsSmi()); | 780 prop->key()->AsLiteral()->handle()->IsSmi()); |
781 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); | 781 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); |
782 | 782 |
783 Handle<Code> ic = is_strict_mode() | 783 Handle<Code> ic = is_strict_mode() |
784 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 784 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
785 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 785 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
786 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 786 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
787 // Value in r0 is ignored (declarations are statements). | 787 // Value in r0 is ignored (declarations are statements). |
788 } | 788 } |
789 } | 789 } |
790 } | 790 } |
791 | 791 |
792 | 792 |
793 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 793 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
794 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 794 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
795 } | 795 } |
796 | 796 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 __ cmp(r1, r0); | 850 __ cmp(r1, r0); |
851 __ b(ne, &next_test); | 851 __ b(ne, &next_test); |
852 __ Drop(1); // Switch value is no longer needed. | 852 __ Drop(1); // Switch value is no longer needed. |
853 __ b(clause->body_target()); | 853 __ b(clause->body_target()); |
854 __ bind(&slow_case); | 854 __ bind(&slow_case); |
855 } | 855 } |
856 | 856 |
857 // Record position before stub call for type feedback. | 857 // Record position before stub call for type feedback. |
858 SetSourcePosition(clause->position()); | 858 SetSourcePosition(clause->position()); |
859 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 859 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
860 EmitCallIC(ic, &patch_site, clause->label()->id()); | 860 EmitCallIC(ic, &patch_site); |
861 __ cmp(r0, Operand(0)); | 861 __ cmp(r0, Operand(0)); |
862 __ b(ne, &next_test); | 862 __ b(ne, &next_test); |
863 __ Drop(1); // Switch value is no longer needed. | 863 __ Drop(1); // Switch value is no longer needed. |
864 __ b(clause->body_target()); | 864 __ b(clause->body_target()); |
865 } | 865 } |
866 | 866 |
867 // Discard the test value and jump to the default if present, otherwise to | 867 // Discard the test value and jump to the default if present, otherwise to |
868 // the end of the statement. | 868 // the end of the statement. |
869 __ bind(&next_test); | 869 __ bind(&next_test); |
870 __ Drop(1); // Switch value is no longer needed. | 870 __ 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); | 1102 context()->Plug(r0); |
1103 } | 1103 } |
1104 | 1104 |
1105 | 1105 |
1106 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1106 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
1107 Comment cmnt(masm_, "[ VariableProxy"); | 1107 Comment cmnt(masm_, "[ VariableProxy"); |
1108 EmitVariableLoad(expr->var()); | 1108 EmitVariableLoad(expr->var()); |
1109 } | 1109 } |
1110 | 1110 |
1111 | 1111 |
1112 void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( | |
1113 Slot* slot, | |
1114 TypeofState typeof_state, | |
1115 Label* slow) { | |
1116 Register current = cp; | |
1117 Register next = r1; | |
1118 Register temp = r2; | |
1119 | |
1120 Scope* s = scope(); | |
1121 while (s != NULL) { | |
1122 if (s->num_heap_slots() > 0) { | |
1123 if (s->calls_eval()) { | |
1124 // Check that extension is NULL. | |
1125 __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | |
1126 __ tst(temp, temp); | |
1127 __ b(ne, slow); | |
1128 } | |
1129 // Load next context in chain. | |
1130 __ ldr(next, ContextOperand(current, Context::CLOSURE_INDEX)); | |
1131 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | |
1132 // Walk the rest of the chain without clobbering cp. | |
1133 current = next; | |
1134 } | |
1135 // If no outer scope calls eval, we do not need to check more | |
1136 // context extensions. | |
1137 if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; | |
1138 s = s->outer_scope(); | |
1139 } | |
1140 | |
1141 if (s->is_eval_scope()) { | |
1142 Label loop, fast; | |
1143 if (!current.is(next)) { | |
1144 __ Move(next, current); | |
1145 } | |
1146 __ bind(&loop); | |
1147 // Terminate at global context. | |
1148 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); | |
1149 __ LoadRoot(ip, Heap::kGlobalContextMapRootIndex); | |
1150 __ cmp(temp, ip); | |
1151 __ b(eq, &fast); | |
1152 // Check that extension is NULL. | |
1153 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); | |
1154 __ tst(temp, temp); | |
1155 __ b(ne, slow); | |
1156 // Load next context in chain. | |
1157 __ ldr(next, ContextOperand(next, Context::CLOSURE_INDEX)); | |
1158 __ ldr(next, FieldMemOperand(next, JSFunction::kContextOffset)); | |
1159 __ b(&loop); | |
1160 __ bind(&fast); | |
1161 } | |
1162 | |
1163 __ ldr(r0, GlobalObjectOperand()); | |
1164 __ mov(r2, Operand(slot->var()->name())); | |
1165 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | |
1166 ? RelocInfo::CODE_TARGET | |
1167 : RelocInfo::CODE_TARGET_CONTEXT; | |
1168 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | |
1169 EmitCallIC(ic, mode, AstNode::kNoNumber); | |
1170 } | |
1171 | |
1172 | |
1173 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( | 1112 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions( |
1174 Slot* slot, | 1113 Slot* slot, |
1175 Label* slow) { | 1114 Label* slow) { |
1176 ASSERT(slot->type() == Slot::CONTEXT); | 1115 ASSERT(slot->type() == Slot::CONTEXT); |
1177 Register context = cp; | 1116 Register context = cp; |
1178 Register next = r3; | 1117 Register next = r3; |
1179 Register temp = r4; | 1118 Register temp = r4; |
1180 | 1119 |
1181 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { | 1120 for (Scope* s = scope(); s != slot->var()->scope(); s = s->outer_scope()) { |
1182 if (s->num_heap_slots() > 0) { | 1121 if (s->num_heap_slots() > 0) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 key_literal->handle()->IsSmi()) { | 1180 key_literal->handle()->IsSmi()) { |
1242 // Load arguments object if there are no eval-introduced | 1181 // Load arguments object if there are no eval-introduced |
1243 // variables. Then load the argument from the arguments | 1182 // variables. Then load the argument from the arguments |
1244 // object using keyed load. | 1183 // object using keyed load. |
1245 __ ldr(r1, | 1184 __ ldr(r1, |
1246 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1185 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), |
1247 slow)); | 1186 slow)); |
1248 __ mov(r0, Operand(key_literal->handle())); | 1187 __ mov(r0, Operand(key_literal->handle())); |
1249 Handle<Code> ic = | 1188 Handle<Code> ic = |
1250 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1189 isolate()->builtins()->KeyedLoadIC_Initialize(); |
1251 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1190 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1252 __ jmp(done); | 1191 __ jmp(done); |
1253 } | 1192 } |
1254 } | 1193 } |
1255 } | 1194 } |
1256 } | 1195 } |
1257 } | 1196 } |
1258 | 1197 |
1259 | 1198 |
| 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) { | 1260 void FullCodeGenerator::EmitVariableLoad(Variable* var) { |
1261 // Four cases: non-this global variables, lookup slots, all other | 1261 // Four cases: non-this global variables, lookup slots, all other |
1262 // types of slots, and parameters that rewrite to explicit property | 1262 // types of slots, and parameters that rewrite to explicit property |
1263 // accesses on the arguments object. | 1263 // accesses on the arguments object. |
1264 Slot* slot = var->AsSlot(); | 1264 Slot* slot = var->AsSlot(); |
1265 Property* property = var->AsProperty(); | 1265 Property* property = var->AsProperty(); |
1266 | 1266 |
1267 if (var->is_global() && !var->is_this()) { | 1267 if (var->is_global() && !var->is_this()) { |
1268 Comment cmnt(masm_, "Global variable"); | 1268 Comment cmnt(masm_, "Global variable"); |
1269 // Use inline caching. Variable name is passed in r2 and the global | 1269 // Use inline caching. Variable name is passed in r2 and the global |
1270 // object (receiver) in r0. | 1270 // object (receiver) in r0. |
1271 __ ldr(r0, GlobalObjectOperand()); | 1271 __ ldr(r0, GlobalObjectOperand()); |
1272 __ mov(r2, Operand(var->name())); | 1272 __ mov(r2, Operand(var->name())); |
1273 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1273 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1274 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1274 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1275 context()->Plug(r0); | 1275 context()->Plug(r0); |
1276 | 1276 |
1277 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1277 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
1278 Label done, slow; | 1278 Label done, slow; |
1279 | 1279 |
1280 // Generate code for loading from variables potentially shadowed | 1280 // Generate code for loading from variables potentially shadowed |
1281 // by eval-introduced variables. | 1281 // by eval-introduced variables. |
1282 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); | 1282 EmitDynamicLoadFromSlotFastCase(slot, NOT_INSIDE_TYPEOF, &slow, &done); |
1283 | 1283 |
1284 __ bind(&slow); | 1284 __ bind(&slow); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 // Assert that the key is a smi. | 1323 // Assert that the key is a smi. |
1324 Literal* key_literal = property->key()->AsLiteral(); | 1324 Literal* key_literal = property->key()->AsLiteral(); |
1325 ASSERT_NOT_NULL(key_literal); | 1325 ASSERT_NOT_NULL(key_literal); |
1326 ASSERT(key_literal->handle()->IsSmi()); | 1326 ASSERT(key_literal->handle()->IsSmi()); |
1327 | 1327 |
1328 // Load the key. | 1328 // Load the key. |
1329 __ mov(r0, Operand(key_literal->handle())); | 1329 __ mov(r0, Operand(key_literal->handle())); |
1330 | 1330 |
1331 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1331 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1332 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1332 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1333 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1333 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1334 context()->Plug(r0); | 1334 context()->Plug(r0); |
1335 } | 1335 } |
1336 } | 1336 } |
1337 | 1337 |
1338 | 1338 |
1339 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1339 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1340 Comment cmnt(masm_, "[ RegExpLiteral"); | 1340 Comment cmnt(masm_, "[ RegExpLiteral"); |
1341 Label materialized; | 1341 Label materialized; |
1342 // Registers will be used as follows: | 1342 // Registers will be used as follows: |
1343 // r5 = materialized value (RegExp literal) | 1343 // r5 = materialized value (RegExp literal) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 UNREACHABLE(); | 1431 UNREACHABLE(); |
1432 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1432 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1433 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1433 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
1434 // Fall through. | 1434 // Fall through. |
1435 case ObjectLiteral::Property::COMPUTED: | 1435 case ObjectLiteral::Property::COMPUTED: |
1436 if (key->handle()->IsSymbol()) { | 1436 if (key->handle()->IsSymbol()) { |
1437 if (property->emit_store()) { | 1437 if (property->emit_store()) { |
1438 VisitForAccumulatorValue(value); | 1438 VisitForAccumulatorValue(value); |
1439 __ mov(r2, Operand(key->handle())); | 1439 __ mov(r2, Operand(key->handle())); |
1440 __ ldr(r1, MemOperand(sp)); | 1440 __ ldr(r1, MemOperand(sp)); |
1441 Handle<Code> ic = is_strict_mode() | 1441 Handle<Code> ic = isolate()->builtins()->StoreIC_Initialize(); |
1442 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1442 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1443 : isolate()->builtins()->StoreIC_Initialize(); | |
1444 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, key->id()); | |
1445 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1443 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1446 } else { | 1444 } else { |
1447 VisitForEffect(value); | 1445 VisitForEffect(value); |
1448 } | 1446 } |
1449 break; | 1447 break; |
1450 } | 1448 } |
1451 // Fall through. | 1449 // Fall through. |
1452 case ObjectLiteral::Property::PROTOTYPE: | 1450 case ObjectLiteral::Property::PROTOTYPE: |
1453 // Duplicate receiver on stack. | 1451 // Duplicate receiver on stack. |
1454 __ ldr(r0, MemOperand(sp)); | 1452 __ ldr(r0, MemOperand(sp)); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 Token::Value op = expr->binary_op(); | 1644 Token::Value op = expr->binary_op(); |
1647 __ push(r0); // Left operand goes on the stack. | 1645 __ push(r0); // Left operand goes on the stack. |
1648 VisitForAccumulatorValue(expr->value()); | 1646 VisitForAccumulatorValue(expr->value()); |
1649 | 1647 |
1650 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1648 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() |
1651 ? OVERWRITE_RIGHT | 1649 ? OVERWRITE_RIGHT |
1652 : NO_OVERWRITE; | 1650 : NO_OVERWRITE; |
1653 SetSourcePosition(expr->position() + 1); | 1651 SetSourcePosition(expr->position() + 1); |
1654 AccumulatorValueContext context(this); | 1652 AccumulatorValueContext context(this); |
1655 if (ShouldInlineSmiCase(op)) { | 1653 if (ShouldInlineSmiCase(op)) { |
1656 EmitInlineSmiBinaryOp(expr->binary_operation(), | 1654 EmitInlineSmiBinaryOp(expr, |
1657 op, | 1655 op, |
1658 mode, | 1656 mode, |
1659 expr->target(), | 1657 expr->target(), |
1660 expr->value()); | 1658 expr->value()); |
1661 } else { | 1659 } else { |
1662 EmitBinaryOp(expr->binary_operation(), op, mode); | 1660 EmitBinaryOp(op, mode); |
1663 } | 1661 } |
1664 | 1662 |
1665 // Deoptimization point in case the binary operation may have side effects. | 1663 // Deoptimization point in case the binary operation may have side effects. |
1666 PrepareForBailout(expr->binary_operation(), TOS_REG); | 1664 PrepareForBailout(expr->binary_operation(), TOS_REG); |
1667 } else { | 1665 } else { |
1668 VisitForAccumulatorValue(expr->value()); | 1666 VisitForAccumulatorValue(expr->value()); |
1669 } | 1667 } |
1670 | 1668 |
1671 // Record source position before possible IC call. | 1669 // Record source position before possible IC call. |
1672 SetSourcePosition(expr->position()); | 1670 SetSourcePosition(expr->position()); |
(...skipping 15 matching lines...) Expand all Loading... |
1688 } | 1686 } |
1689 } | 1687 } |
1690 | 1688 |
1691 | 1689 |
1692 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1690 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1693 SetSourcePosition(prop->position()); | 1691 SetSourcePosition(prop->position()); |
1694 Literal* key = prop->key()->AsLiteral(); | 1692 Literal* key = prop->key()->AsLiteral(); |
1695 __ mov(r2, Operand(key->handle())); | 1693 __ mov(r2, Operand(key->handle())); |
1696 // Call load IC. It has arguments receiver and property name r0 and r2. | 1694 // Call load IC. It has arguments receiver and property name r0 and r2. |
1697 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1695 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1698 if (prop->is_synthetic()) { | 1696 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1699 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | |
1700 } else { | |
1701 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, prop->id()); | |
1702 } | |
1703 } | 1697 } |
1704 | 1698 |
1705 | 1699 |
1706 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1700 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1707 SetSourcePosition(prop->position()); | 1701 SetSourcePosition(prop->position()); |
1708 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1702 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1709 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1703 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1710 if (prop->is_synthetic()) { | 1704 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1711 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | |
1712 } else { | |
1713 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, prop->id()); | |
1714 } | |
1715 } | 1705 } |
1716 | 1706 |
1717 | 1707 |
1718 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1708 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, |
1719 Token::Value op, | 1709 Token::Value op, |
1720 OverwriteMode mode, | 1710 OverwriteMode mode, |
1721 Expression* left_expr, | 1711 Expression* left_expr, |
1722 Expression* right_expr) { | 1712 Expression* right_expr) { |
1723 Label done, smi_case, stub_call; | 1713 Label done, smi_case, stub_call; |
1724 | 1714 |
1725 Register scratch1 = r2; | 1715 Register scratch1 = r2; |
1726 Register scratch2 = r3; | 1716 Register scratch2 = r3; |
1727 | 1717 |
1728 // Get the arguments. | 1718 // Get the arguments. |
1729 Register left = r1; | 1719 Register left = r1; |
1730 Register right = r0; | 1720 Register right = r0; |
1731 __ pop(left); | 1721 __ pop(left); |
1732 | 1722 |
1733 // Perform combined smi check on both operands. | 1723 // Perform combined smi check on both operands. |
1734 __ orr(scratch1, left, Operand(right)); | 1724 __ orr(scratch1, left, Operand(right)); |
1735 STATIC_ASSERT(kSmiTag == 0); | 1725 STATIC_ASSERT(kSmiTag == 0); |
1736 JumpPatchSite patch_site(masm_); | 1726 JumpPatchSite patch_site(masm_); |
1737 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1727 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1738 | 1728 |
1739 __ bind(&stub_call); | 1729 __ bind(&stub_call); |
1740 TypeRecordingBinaryOpStub stub(op, mode); | 1730 TypeRecordingBinaryOpStub stub(op, mode); |
1741 EmitCallIC(stub.GetCode(), &patch_site, expr->id()); | 1731 EmitCallIC(stub.GetCode(), &patch_site); |
1742 __ jmp(&done); | 1732 __ jmp(&done); |
1743 | 1733 |
1744 __ bind(&smi_case); | 1734 __ bind(&smi_case); |
1745 // Smi case. This code works the same way as the smi-smi case in the type | 1735 // Smi case. This code works the same way as the smi-smi case in the type |
1746 // recording binary operation stub, see | 1736 // recording binary operation stub, see |
1747 // TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments. | 1737 // TypeRecordingBinaryOpStub::GenerateSmiSmiOperation for comments. |
1748 switch (op) { | 1738 switch (op) { |
1749 case Token::SAR: | 1739 case Token::SAR: |
1750 __ b(&stub_call); | 1740 __ b(&stub_call); |
1751 __ GetLeastBitsFromSmi(scratch1, right, 5); | 1741 __ GetLeastBitsFromSmi(scratch1, right, 5); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1807 break; | 1797 break; |
1808 default: | 1798 default: |
1809 UNREACHABLE(); | 1799 UNREACHABLE(); |
1810 } | 1800 } |
1811 | 1801 |
1812 __ bind(&done); | 1802 __ bind(&done); |
1813 context()->Plug(r0); | 1803 context()->Plug(r0); |
1814 } | 1804 } |
1815 | 1805 |
1816 | 1806 |
1817 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1807 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1818 Token::Value op, | |
1819 OverwriteMode mode) { | 1808 OverwriteMode mode) { |
1820 __ pop(r1); | 1809 __ pop(r1); |
1821 TypeRecordingBinaryOpStub stub(op, mode); | 1810 TypeRecordingBinaryOpStub stub(op, mode); |
1822 EmitCallIC(stub.GetCode(), NULL, expr->id()); | 1811 EmitCallIC(stub.GetCode(), NULL); |
1823 context()->Plug(r0); | 1812 context()->Plug(r0); |
1824 } | 1813 } |
1825 | 1814 |
1826 | 1815 |
1827 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { | 1816 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { |
1828 // Invalid left-hand sides are rewritten to have a 'throw | 1817 // Invalid left-hand sides are rewritten to have a 'throw |
1829 // ReferenceError' on the left-hand side. | 1818 // ReferenceError' on the left-hand side. |
1830 if (!expr->IsValidLeftHandSide()) { | 1819 if (!expr->IsValidLeftHandSide()) { |
1831 VisitForEffect(expr); | 1820 VisitForEffect(expr); |
1832 return; | 1821 return; |
(...skipping 19 matching lines...) Expand all Loading... |
1852 } | 1841 } |
1853 case NAMED_PROPERTY: { | 1842 case NAMED_PROPERTY: { |
1854 __ push(r0); // Preserve value. | 1843 __ push(r0); // Preserve value. |
1855 VisitForAccumulatorValue(prop->obj()); | 1844 VisitForAccumulatorValue(prop->obj()); |
1856 __ mov(r1, r0); | 1845 __ mov(r1, r0); |
1857 __ pop(r0); // Restore value. | 1846 __ pop(r0); // Restore value. |
1858 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1847 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1859 Handle<Code> ic = is_strict_mode() | 1848 Handle<Code> ic = is_strict_mode() |
1860 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1849 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1861 : isolate()->builtins()->StoreIC_Initialize(); | 1850 : isolate()->builtins()->StoreIC_Initialize(); |
1862 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1851 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1863 break; | 1852 break; |
1864 } | 1853 } |
1865 case KEYED_PROPERTY: { | 1854 case KEYED_PROPERTY: { |
1866 __ push(r0); // Preserve value. | 1855 __ push(r0); // Preserve value. |
1867 if (prop->is_synthetic()) { | 1856 if (prop->is_synthetic()) { |
1868 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 1857 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
1869 ASSERT(prop->key()->AsLiteral() != NULL); | 1858 ASSERT(prop->key()->AsLiteral() != NULL); |
1870 { AccumulatorValueContext for_object(this); | 1859 { AccumulatorValueContext for_object(this); |
1871 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); | 1860 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
1872 } | 1861 } |
1873 __ mov(r2, r0); | 1862 __ mov(r2, r0); |
1874 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); | 1863 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); |
1875 } else { | 1864 } else { |
1876 VisitForStackValue(prop->obj()); | 1865 VisitForStackValue(prop->obj()); |
1877 VisitForAccumulatorValue(prop->key()); | 1866 VisitForAccumulatorValue(prop->key()); |
1878 __ mov(r1, r0); | 1867 __ mov(r1, r0); |
1879 __ pop(r2); | 1868 __ pop(r2); |
1880 } | 1869 } |
1881 __ pop(r0); // Restore value. | 1870 __ pop(r0); // Restore value. |
1882 Handle<Code> ic = is_strict_mode() | 1871 Handle<Code> ic = is_strict_mode() |
1883 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 1872 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
1884 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 1873 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
1885 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 1874 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1886 break; | 1875 break; |
1887 } | 1876 } |
1888 } | 1877 } |
1889 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1878 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1890 context()->Plug(r0); | 1879 context()->Plug(r0); |
1891 } | 1880 } |
1892 | 1881 |
1893 | 1882 |
1894 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1883 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1895 Token::Value op) { | 1884 Token::Value op) { |
1896 // Left-hand sides that rewrite to explicit property accesses do not reach | 1885 // Left-hand sides that rewrite to explicit property accesses do not reach |
1897 // here. | 1886 // here. |
1898 ASSERT(var != NULL); | 1887 ASSERT(var != NULL); |
1899 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1888 ASSERT(var->is_global() || var->AsSlot() != NULL); |
1900 | 1889 |
1901 if (var->is_global()) { | 1890 if (var->is_global()) { |
1902 ASSERT(!var->is_this()); | 1891 ASSERT(!var->is_this()); |
1903 // Assignment to a global variable. Use inline caching for the | 1892 // Assignment to a global variable. Use inline caching for the |
1904 // assignment. Right-hand-side value is passed in r0, variable name in | 1893 // assignment. Right-hand-side value is passed in r0, variable name in |
1905 // r2, and the global object in r1. | 1894 // r2, and the global object in r1. |
1906 __ mov(r2, Operand(var->name())); | 1895 __ mov(r2, Operand(var->name())); |
1907 __ ldr(r1, GlobalObjectOperand()); | 1896 __ ldr(r1, GlobalObjectOperand()); |
1908 Handle<Code> ic = is_strict_mode() | 1897 Handle<Code> ic = is_strict_mode() |
1909 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1898 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1910 : isolate()->builtins()->StoreIC_Initialize(); | 1899 : isolate()->builtins()->StoreIC_Initialize(); |
1911 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber); | 1900 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1912 | 1901 |
1913 } else if (op == Token::INIT_CONST) { | 1902 } else if (op == Token::INIT_CONST) { |
1914 // Like var declarations, const declarations are hoisted to function | 1903 // Like var declarations, const declarations are hoisted to function |
1915 // scope. However, unlike var initializers, const initializers are able | 1904 // scope. However, unlike var initializers, const initializers are able |
1916 // to drill a hole to that function context, even from inside a 'with' | 1905 // to drill a hole to that function context, even from inside a 'with' |
1917 // context. We thus bypass the normal static scope lookup. | 1906 // context. We thus bypass the normal static scope lookup. |
1918 Slot* slot = var->AsSlot(); | 1907 Slot* slot = var->AsSlot(); |
1919 Label skip; | 1908 Label skip; |
1920 switch (slot->type()) { | 1909 switch (slot->type()) { |
1921 case Slot::PARAMETER: | 1910 case Slot::PARAMETER: |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2010 // receiver into fast case. | 1999 // receiver into fast case. |
2011 if (expr->ends_initialization_block()) { | 2000 if (expr->ends_initialization_block()) { |
2012 __ ldr(r1, MemOperand(sp)); | 2001 __ ldr(r1, MemOperand(sp)); |
2013 } else { | 2002 } else { |
2014 __ pop(r1); | 2003 __ pop(r1); |
2015 } | 2004 } |
2016 | 2005 |
2017 Handle<Code> ic = is_strict_mode() | 2006 Handle<Code> ic = is_strict_mode() |
2018 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2007 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2019 : isolate()->builtins()->StoreIC_Initialize(); | 2008 : isolate()->builtins()->StoreIC_Initialize(); |
2020 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); | 2009 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2021 | 2010 |
2022 // If the assignment ends an initialization block, revert to fast case. | 2011 // If the assignment ends an initialization block, revert to fast case. |
2023 if (expr->ends_initialization_block()) { | 2012 if (expr->ends_initialization_block()) { |
2024 __ push(r0); // Result of assignment, saved even if not needed. | 2013 __ push(r0); // Result of assignment, saved even if not needed. |
2025 // Receiver is under the result value. | 2014 // Receiver is under the result value. |
2026 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2015 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2027 __ push(ip); | 2016 __ push(ip); |
2028 __ CallRuntime(Runtime::kToFastProperties, 1); | 2017 __ CallRuntime(Runtime::kToFastProperties, 1); |
2029 __ pop(r0); | 2018 __ pop(r0); |
2030 __ Drop(1); | 2019 __ Drop(1); |
(...skipping 25 matching lines...) Expand all Loading... |
2056 // receiver into fast case. | 2045 // receiver into fast case. |
2057 if (expr->ends_initialization_block()) { | 2046 if (expr->ends_initialization_block()) { |
2058 __ ldr(r2, MemOperand(sp)); | 2047 __ ldr(r2, MemOperand(sp)); |
2059 } else { | 2048 } else { |
2060 __ pop(r2); | 2049 __ pop(r2); |
2061 } | 2050 } |
2062 | 2051 |
2063 Handle<Code> ic = is_strict_mode() | 2052 Handle<Code> ic = is_strict_mode() |
2064 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 2053 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
2065 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 2054 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
2066 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); | 2055 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2067 | 2056 |
2068 // If the assignment ends an initialization block, revert to fast case. | 2057 // If the assignment ends an initialization block, revert to fast case. |
2069 if (expr->ends_initialization_block()) { | 2058 if (expr->ends_initialization_block()) { |
2070 __ push(r0); // Result of assignment, saved even if not needed. | 2059 __ push(r0); // Result of assignment, saved even if not needed. |
2071 // Receiver is under the result value. | 2060 // Receiver is under the result value. |
2072 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2061 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2073 __ push(ip); | 2062 __ push(ip); |
2074 __ CallRuntime(Runtime::kToFastProperties, 1); | 2063 __ CallRuntime(Runtime::kToFastProperties, 1); |
2075 __ pop(r0); | 2064 __ pop(r0); |
2076 __ Drop(1); | 2065 __ Drop(1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 VisitForStackValue(args->at(i)); | 2097 VisitForStackValue(args->at(i)); |
2109 } | 2098 } |
2110 __ mov(r2, Operand(name)); | 2099 __ mov(r2, Operand(name)); |
2111 } | 2100 } |
2112 // Record source position for debugger. | 2101 // Record source position for debugger. |
2113 SetSourcePosition(expr->position()); | 2102 SetSourcePosition(expr->position()); |
2114 // Call the IC initialization code. | 2103 // Call the IC initialization code. |
2115 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2104 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2116 Handle<Code> ic = | 2105 Handle<Code> ic = |
2117 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); | 2106 isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); |
2118 unsigned ast_id = | 2107 EmitCallIC(ic, mode); |
2119 (mode == RelocInfo::CODE_TARGET_WITH_ID) ? expr->id() : kNoASTId; | |
2120 EmitCallIC(ic, mode, ast_id); | |
2121 RecordJSReturnSite(expr); | 2108 RecordJSReturnSite(expr); |
2122 // Restore context register. | 2109 // Restore context register. |
2123 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2110 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2124 context()->Plug(r0); | 2111 context()->Plug(r0); |
2125 } | 2112 } |
2126 | 2113 |
2127 | 2114 |
2128 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2115 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2129 Expression* key, | 2116 Expression* key, |
2130 RelocInfo::Mode mode) { | 2117 RelocInfo::Mode mode) { |
(...skipping 14 matching lines...) Expand all Loading... |
2145 VisitForStackValue(args->at(i)); | 2132 VisitForStackValue(args->at(i)); |
2146 } | 2133 } |
2147 } | 2134 } |
2148 // Record source position for debugger. | 2135 // Record source position for debugger. |
2149 SetSourcePosition(expr->position()); | 2136 SetSourcePosition(expr->position()); |
2150 // Call the IC initialization code. | 2137 // Call the IC initialization code. |
2151 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 2138 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
2152 Handle<Code> ic = | 2139 Handle<Code> ic = |
2153 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); | 2140 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); |
2154 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2141 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2155 EmitCallIC(ic, mode, expr->id()); | 2142 EmitCallIC(ic, mode); |
2156 RecordJSReturnSite(expr); | 2143 RecordJSReturnSite(expr); |
2157 // Restore context register. | 2144 // Restore context register. |
2158 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2145 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2159 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2146 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
2160 } | 2147 } |
2161 | 2148 |
2162 | 2149 |
2163 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 2150 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
2164 // Code common for calls using the call stub. | 2151 // Code common for calls using the call stub. |
2165 ZoneList<Expression*>* args = expr->arguments(); | 2152 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2321 EmitCallWithStub(expr); | 2308 EmitCallWithStub(expr); |
2322 } else if (fun->AsProperty() != NULL) { | 2309 } else if (fun->AsProperty() != NULL) { |
2323 // Call to an object property. | 2310 // Call to an object property. |
2324 Property* prop = fun->AsProperty(); | 2311 Property* prop = fun->AsProperty(); |
2325 Literal* key = prop->key()->AsLiteral(); | 2312 Literal* key = prop->key()->AsLiteral(); |
2326 if (key != NULL && key->handle()->IsSymbol()) { | 2313 if (key != NULL && key->handle()->IsSymbol()) { |
2327 // Call to a named property, use call IC. | 2314 // Call to a named property, use call IC. |
2328 { PreservePositionScope scope(masm()->positions_recorder()); | 2315 { PreservePositionScope scope(masm()->positions_recorder()); |
2329 VisitForStackValue(prop->obj()); | 2316 VisitForStackValue(prop->obj()); |
2330 } | 2317 } |
2331 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET_WITH_ID); | 2318 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
2332 } else { | 2319 } else { |
2333 // Call to a keyed property. | 2320 // Call to a keyed property. |
2334 // For a synthetic property use keyed load IC followed by function call, | 2321 // For a synthetic property use keyed load IC followed by function call, |
2335 // for a regular property use keyed EmitCallIC. | 2322 // for a regular property use keyed CallIC. |
2336 if (prop->is_synthetic()) { | 2323 if (prop->is_synthetic()) { |
2337 // Do not visit the object and key subexpressions (they are shared | 2324 // Do not visit the object and key subexpressions (they are shared |
2338 // by all occurrences of the same rewritten parameter). | 2325 // by all occurrences of the same rewritten parameter). |
2339 ASSERT(prop->obj()->AsVariableProxy() != NULL); | 2326 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
2340 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); | 2327 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); |
2341 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); | 2328 Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot(); |
2342 MemOperand operand = EmitSlotSearch(slot, r1); | 2329 MemOperand operand = EmitSlotSearch(slot, r1); |
2343 __ ldr(r1, operand); | 2330 __ ldr(r1, operand); |
2344 | 2331 |
2345 ASSERT(prop->key()->AsLiteral() != NULL); | 2332 ASSERT(prop->key()->AsLiteral() != NULL); |
2346 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); | 2333 ASSERT(prop->key()->AsLiteral()->handle()->IsSmi()); |
2347 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); | 2334 __ mov(r0, Operand(prop->key()->AsLiteral()->handle())); |
2348 | 2335 |
2349 // Record source code position for IC call. | 2336 // Record source code position for IC call. |
2350 SetSourcePosition(prop->position()); | 2337 SetSourcePosition(prop->position()); |
2351 | 2338 |
2352 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2339 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2353 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 2340 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
2354 __ ldr(r1, GlobalObjectOperand()); | 2341 __ ldr(r1, GlobalObjectOperand()); |
2355 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2342 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2356 __ Push(r0, r1); // Function, receiver. | 2343 __ Push(r0, r1); // Function, receiver. |
2357 EmitCallWithStub(expr); | 2344 EmitCallWithStub(expr); |
2358 } else { | 2345 } else { |
2359 { PreservePositionScope scope(masm()->positions_recorder()); | 2346 { PreservePositionScope scope(masm()->positions_recorder()); |
2360 VisitForStackValue(prop->obj()); | 2347 VisitForStackValue(prop->obj()); |
2361 } | 2348 } |
2362 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET_WITH_ID); | 2349 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
2363 } | 2350 } |
2364 } | 2351 } |
2365 } else { | 2352 } else { |
2366 { PreservePositionScope scope(masm()->positions_recorder()); | 2353 { PreservePositionScope scope(masm()->positions_recorder()); |
2367 VisitForStackValue(fun); | 2354 VisitForStackValue(fun); |
2368 } | 2355 } |
2369 // Load global receiver object. | 2356 // Load global receiver object. |
2370 __ ldr(r1, GlobalObjectOperand()); | 2357 __ ldr(r1, GlobalObjectOperand()); |
2371 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 2358 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
2372 __ push(r1); | 2359 __ push(r1); |
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3663 int arg_count = args->length(); | 3650 int arg_count = args->length(); |
3664 for (int i = 0; i < arg_count; i++) { | 3651 for (int i = 0; i < arg_count; i++) { |
3665 VisitForStackValue(args->at(i)); | 3652 VisitForStackValue(args->at(i)); |
3666 } | 3653 } |
3667 | 3654 |
3668 if (expr->is_jsruntime()) { | 3655 if (expr->is_jsruntime()) { |
3669 // Call the JS runtime function. | 3656 // Call the JS runtime function. |
3670 __ mov(r2, Operand(expr->name())); | 3657 __ mov(r2, Operand(expr->name())); |
3671 Handle<Code> ic = | 3658 Handle<Code> ic = |
3672 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); | 3659 isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); |
3673 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); | 3660 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3674 // Restore context register. | 3661 // Restore context register. |
3675 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3662 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3676 } else { | 3663 } else { |
3677 // Call the C runtime function. | 3664 // Call the C runtime function. |
3678 __ CallRuntime(expr->function(), arg_count); | 3665 __ CallRuntime(expr->function(), arg_count); |
3679 } | 3666 } |
3680 context()->Plug(r0); | 3667 context()->Plug(r0); |
3681 } | 3668 } |
3682 | 3669 |
3683 | 3670 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3942 __ bind(&stub_call); | 3929 __ bind(&stub_call); |
3943 // Call stub. Undo operation first. | 3930 // Call stub. Undo operation first. |
3944 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 3931 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
3945 } | 3932 } |
3946 __ mov(r1, Operand(Smi::FromInt(count_value))); | 3933 __ mov(r1, Operand(Smi::FromInt(count_value))); |
3947 | 3934 |
3948 // Record position before stub call. | 3935 // Record position before stub call. |
3949 SetSourcePosition(expr->position()); | 3936 SetSourcePosition(expr->position()); |
3950 | 3937 |
3951 TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 3938 TypeRecordingBinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
3952 EmitCallIC(stub.GetCode(), &patch_site, expr->CountId()); | 3939 EmitCallIC(stub.GetCode(), &patch_site); |
3953 __ bind(&done); | 3940 __ bind(&done); |
3954 | 3941 |
3955 // Store the value returned in r0. | 3942 // Store the value returned in r0. |
3956 switch (assign_type) { | 3943 switch (assign_type) { |
3957 case VARIABLE: | 3944 case VARIABLE: |
3958 if (expr->is_postfix()) { | 3945 if (expr->is_postfix()) { |
3959 { EffectContext context(this); | 3946 { EffectContext context(this); |
3960 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3947 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
3961 Token::ASSIGN); | 3948 Token::ASSIGN); |
3962 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3949 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
(...skipping 10 matching lines...) Expand all Loading... |
3973 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3960 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3974 context()->Plug(r0); | 3961 context()->Plug(r0); |
3975 } | 3962 } |
3976 break; | 3963 break; |
3977 case NAMED_PROPERTY: { | 3964 case NAMED_PROPERTY: { |
3978 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 3965 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
3979 __ pop(r1); | 3966 __ pop(r1); |
3980 Handle<Code> ic = is_strict_mode() | 3967 Handle<Code> ic = is_strict_mode() |
3981 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3968 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3982 : isolate()->builtins()->StoreIC_Initialize(); | 3969 : isolate()->builtins()->StoreIC_Initialize(); |
3983 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); | 3970 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
3984 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3971 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
3985 if (expr->is_postfix()) { | 3972 if (expr->is_postfix()) { |
3986 if (!context()->IsEffect()) { | 3973 if (!context()->IsEffect()) { |
3987 context()->PlugTOS(); | 3974 context()->PlugTOS(); |
3988 } | 3975 } |
3989 } else { | 3976 } else { |
3990 context()->Plug(r0); | 3977 context()->Plug(r0); |
3991 } | 3978 } |
3992 break; | 3979 break; |
3993 } | 3980 } |
3994 case KEYED_PROPERTY: { | 3981 case KEYED_PROPERTY: { |
3995 __ pop(r1); // Key. | 3982 __ pop(r1); // Key. |
3996 __ pop(r2); // Receiver. | 3983 __ pop(r2); // Receiver. |
3997 Handle<Code> ic = is_strict_mode() | 3984 Handle<Code> ic = is_strict_mode() |
3998 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3985 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3999 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3986 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4000 EmitCallIC(ic, RelocInfo::CODE_TARGET_WITH_ID, expr->id()); | 3987 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
4001 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 3988 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4002 if (expr->is_postfix()) { | 3989 if (expr->is_postfix()) { |
4003 if (!context()->IsEffect()) { | 3990 if (!context()->IsEffect()) { |
4004 context()->PlugTOS(); | 3991 context()->PlugTOS(); |
4005 } | 3992 } |
4006 } else { | 3993 } else { |
4007 context()->Plug(r0); | 3994 context()->Plug(r0); |
4008 } | 3995 } |
4009 break; | 3996 break; |
4010 } | 3997 } |
4011 } | 3998 } |
4012 } | 3999 } |
4013 | 4000 |
4014 | 4001 |
4015 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4002 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4016 ASSERT(!context()->IsEffect()); | 4003 ASSERT(!context()->IsEffect()); |
4017 ASSERT(!context()->IsTest()); | 4004 ASSERT(!context()->IsTest()); |
4018 VariableProxy* proxy = expr->AsVariableProxy(); | 4005 VariableProxy* proxy = expr->AsVariableProxy(); |
4019 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { | 4006 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { |
4020 Comment cmnt(masm_, "Global variable"); | 4007 Comment cmnt(masm_, "Global variable"); |
4021 __ ldr(r0, GlobalObjectOperand()); | 4008 __ ldr(r0, GlobalObjectOperand()); |
4022 __ mov(r2, Operand(proxy->name())); | 4009 __ mov(r2, Operand(proxy->name())); |
4023 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 4010 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
4024 // Use a regular load, not a contextual load, to avoid a reference | 4011 // Use a regular load, not a contextual load, to avoid a reference |
4025 // error. | 4012 // error. |
4026 EmitCallIC(ic, RelocInfo::CODE_TARGET, AstNode::kNoNumber); | 4013 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
4027 PrepareForBailout(expr, TOS_REG); | 4014 PrepareForBailout(expr, TOS_REG); |
4028 context()->Plug(r0); | 4015 context()->Plug(r0); |
4029 } else if (proxy != NULL && | 4016 } else if (proxy != NULL && |
4030 proxy->var()->AsSlot() != NULL && | 4017 proxy->var()->AsSlot() != NULL && |
4031 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 4018 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { |
4032 Label done, slow; | 4019 Label done, slow; |
4033 | 4020 |
4034 // Generate code for loading from variables potentially shadowed | 4021 // Generate code for loading from variables potentially shadowed |
4035 // by eval-introduced variables. | 4022 // by eval-introduced variables. |
4036 Slot* slot = proxy->var()->AsSlot(); | 4023 Slot* slot = proxy->var()->AsSlot(); |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4219 __ orr(r2, r0, Operand(r1)); | 4206 __ orr(r2, r0, Operand(r1)); |
4220 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4207 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
4221 __ cmp(r1, r0); | 4208 __ cmp(r1, r0); |
4222 Split(cond, if_true, if_false, NULL); | 4209 Split(cond, if_true, if_false, NULL); |
4223 __ bind(&slow_case); | 4210 __ bind(&slow_case); |
4224 } | 4211 } |
4225 | 4212 |
4226 // Record position and call the compare IC. | 4213 // Record position and call the compare IC. |
4227 SetSourcePosition(expr->position()); | 4214 SetSourcePosition(expr->position()); |
4228 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4215 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4229 EmitCallIC(ic, &patch_site, expr->id()); | 4216 EmitCallIC(ic, &patch_site); |
4230 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4217 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); |
4231 __ cmp(r0, Operand(0)); | 4218 __ cmp(r0, Operand(0)); |
4232 Split(cond, if_true, if_false, fall_through); | 4219 Split(cond, if_true, if_false, fall_through); |
4233 } | 4220 } |
4234 } | 4221 } |
4235 | 4222 |
4236 // Convert the result of the comparison into one expected for this | 4223 // Convert the result of the comparison into one expected for this |
4237 // expression's context. | 4224 // expression's context. |
4238 context()->Plug(if_true, if_false); | 4225 context()->Plug(if_true, if_false); |
4239 } | 4226 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4281 Register FullCodeGenerator::result_register() { | 4268 Register FullCodeGenerator::result_register() { |
4282 return r0; | 4269 return r0; |
4283 } | 4270 } |
4284 | 4271 |
4285 | 4272 |
4286 Register FullCodeGenerator::context_register() { | 4273 Register FullCodeGenerator::context_register() { |
4287 return cp; | 4274 return cp; |
4288 } | 4275 } |
4289 | 4276 |
4290 | 4277 |
4291 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4278 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) { |
4292 RelocInfo::Mode mode, | |
4293 unsigned ast_id) { | |
4294 ASSERT(mode == RelocInfo::CODE_TARGET || | 4279 ASSERT(mode == RelocInfo::CODE_TARGET || |
4295 mode == RelocInfo::CODE_TARGET_CONTEXT || | 4280 mode == RelocInfo::CODE_TARGET_CONTEXT); |
4296 mode == RelocInfo::CODE_TARGET_WITH_ID); | |
4297 Counters* counters = isolate()->counters(); | 4281 Counters* counters = isolate()->counters(); |
4298 switch (ic->kind()) { | 4282 switch (ic->kind()) { |
4299 case Code::LOAD_IC: | 4283 case Code::LOAD_IC: |
4300 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | 4284 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); |
4301 break; | 4285 break; |
4302 case Code::KEYED_LOAD_IC: | 4286 case Code::KEYED_LOAD_IC: |
4303 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | 4287 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); |
4304 break; | 4288 break; |
4305 case Code::STORE_IC: | 4289 case Code::STORE_IC: |
4306 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | 4290 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); |
4307 break; | 4291 break; |
4308 case Code::KEYED_STORE_IC: | 4292 case Code::KEYED_STORE_IC: |
4309 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | 4293 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); |
4310 default: | 4294 default: |
4311 break; | 4295 break; |
4312 } | 4296 } |
4313 if (mode == RelocInfo::CODE_TARGET_WITH_ID) { | 4297 __ Call(ic, mode); |
4314 ASSERT(ast_id != kNoASTId); | |
4315 __ CallWithAstId(ic, mode, ast_id); | |
4316 } else { | |
4317 ASSERT(ast_id == kNoASTId); | |
4318 __ Call(ic, mode); | |
4319 } | |
4320 } | 4298 } |
4321 | 4299 |
4322 | 4300 |
4323 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, | 4301 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |
4324 JumpPatchSite* patch_site, | |
4325 unsigned ast_id) { | |
4326 Counters* counters = isolate()->counters(); | 4302 Counters* counters = isolate()->counters(); |
4327 switch (ic->kind()) { | 4303 switch (ic->kind()) { |
4328 case Code::LOAD_IC: | 4304 case Code::LOAD_IC: |
4329 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); | 4305 __ IncrementCounter(counters->named_load_full(), 1, r1, r2); |
4330 break; | 4306 break; |
4331 case Code::KEYED_LOAD_IC: | 4307 case Code::KEYED_LOAD_IC: |
4332 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); | 4308 __ IncrementCounter(counters->keyed_load_full(), 1, r1, r2); |
4333 break; | 4309 break; |
4334 case Code::STORE_IC: | 4310 case Code::STORE_IC: |
4335 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); | 4311 __ IncrementCounter(counters->named_store_full(), 1, r1, r2); |
4336 break; | 4312 break; |
4337 case Code::KEYED_STORE_IC: | 4313 case Code::KEYED_STORE_IC: |
4338 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); | 4314 __ IncrementCounter(counters->keyed_store_full(), 1, r1, r2); |
4339 default: | 4315 default: |
4340 break; | 4316 break; |
4341 } | 4317 } |
4342 | 4318 __ Call(ic, RelocInfo::CODE_TARGET); |
4343 if (ast_id != kNoASTId) { | |
4344 __ CallWithAstId(ic, RelocInfo::CODE_TARGET_WITH_ID, ast_id); | |
4345 } else { | |
4346 __ Call(ic, RelocInfo::CODE_TARGET); | |
4347 } | |
4348 if (patch_site != NULL && patch_site->is_bound()) { | 4319 if (patch_site != NULL && patch_site->is_bound()) { |
4349 patch_site->EmitPatchInfo(); | 4320 patch_site->EmitPatchInfo(); |
4350 } else { | 4321 } else { |
4351 __ nop(); // Signals no inlined code. | 4322 __ nop(); // Signals no inlined code. |
4352 } | 4323 } |
4353 } | 4324 } |
4354 | 4325 |
4355 | 4326 |
4356 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4327 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
4357 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4328 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4390 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 4361 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
4391 __ add(pc, r1, Operand(masm_->CodeObject())); | 4362 __ add(pc, r1, Operand(masm_->CodeObject())); |
4392 } | 4363 } |
4393 | 4364 |
4394 | 4365 |
4395 #undef __ | 4366 #undef __ |
4396 | 4367 |
4397 } } // namespace v8::internal | 4368 } } // namespace v8::internal |
4398 | 4369 |
4399 #endif // V8_TARGET_ARCH_ARM | 4370 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |