| 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 700 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 711 | 711 | 
| 712 | 712 | 
| 713 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 713 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, | 
| 714                                         VariableMode mode, | 714                                         VariableMode mode, | 
| 715                                         FunctionLiteral* function, | 715                                         FunctionLiteral* function, | 
| 716                                         int* global_count) { | 716                                         int* global_count) { | 
| 717   // If it was not possible to allocate the variable at compile time, we | 717   // If it was not possible to allocate the variable at compile time, we | 
| 718   // need to "declare" it at runtime to make sure it actually exists in the | 718   // need to "declare" it at runtime to make sure it actually exists in the | 
| 719   // local context. | 719   // local context. | 
| 720   Variable* variable = proxy->var(); | 720   Variable* variable = proxy->var(); | 
|  | 721   bool binding_needs_init = | 
|  | 722       mode == CONST || mode == CONST_HARMONY || mode == LET; | 
| 721   switch (variable->location()) { | 723   switch (variable->location()) { | 
| 722     case Variable::UNALLOCATED: | 724     case Variable::UNALLOCATED: | 
| 723       ++(*global_count); | 725       ++(*global_count); | 
| 724       break; | 726       break; | 
| 725 | 727 | 
| 726     case Variable::PARAMETER: | 728     case Variable::PARAMETER: | 
| 727     case Variable::LOCAL: | 729     case Variable::LOCAL: | 
| 728       if (function != NULL) { | 730       if (function != NULL) { | 
| 729         Comment cmnt(masm_, "[ Declaration"); | 731         Comment cmnt(masm_, "[ Declaration"); | 
| 730         VisitForAccumulatorValue(function); | 732         VisitForAccumulatorValue(function); | 
| 731         __ str(result_register(), StackOperand(variable)); | 733         __ str(result_register(), StackOperand(variable)); | 
| 732       } else if (mode == CONST || mode == LET) { | 734       } else if (binding_needs_init) { | 
| 733         Comment cmnt(masm_, "[ Declaration"); | 735         Comment cmnt(masm_, "[ Declaration"); | 
| 734         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 736         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 
| 735         __ str(ip, StackOperand(variable)); | 737         __ str(ip, StackOperand(variable)); | 
| 736       } | 738       } | 
| 737       break; | 739       break; | 
| 738 | 740 | 
| 739     case Variable::CONTEXT: | 741     case Variable::CONTEXT: | 
| 740       // The variable in the decl always resides in the current function | 742       // The variable in the decl always resides in the current function | 
| 741       // context. | 743       // context. | 
| 742       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 744       ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 756         // We know that we have written a function, which is not a smi. | 758         // We know that we have written a function, which is not a smi. | 
| 757         __ RecordWriteContextSlot(cp, | 759         __ RecordWriteContextSlot(cp, | 
| 758                                   offset, | 760                                   offset, | 
| 759                                   result_register(), | 761                                   result_register(), | 
| 760                                   r2, | 762                                   r2, | 
| 761                                   kLRHasBeenSaved, | 763                                   kLRHasBeenSaved, | 
| 762                                   kDontSaveFPRegs, | 764                                   kDontSaveFPRegs, | 
| 763                                   EMIT_REMEMBERED_SET, | 765                                   EMIT_REMEMBERED_SET, | 
| 764                                   OMIT_SMI_CHECK); | 766                                   OMIT_SMI_CHECK); | 
| 765         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 767         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
| 766       } else if (mode == CONST || mode == LET) { | 768       } else if (binding_needs_init) { | 
| 767         Comment cmnt(masm_, "[ Declaration"); | 769         Comment cmnt(masm_, "[ Declaration"); | 
| 768         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 770         __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 
| 769         __ str(ip, ContextOperand(cp, variable->index())); | 771         __ str(ip, ContextOperand(cp, variable->index())); | 
| 770         // No write barrier since the_hole_value is in old space. | 772         // No write barrier since the_hole_value is in old space. | 
| 771         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 773         PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 
| 772       } | 774       } | 
| 773       break; | 775       break; | 
| 774 | 776 | 
| 775     case Variable::LOOKUP: { | 777     case Variable::LOOKUP: { | 
| 776       Comment cmnt(masm_, "[ Declaration"); | 778       Comment cmnt(masm_, "[ Declaration"); | 
| 777       __ mov(r2, Operand(variable->name())); | 779       __ mov(r2, Operand(variable->name())); | 
| 778       // Declaration nodes are always introduced in one of three modes. | 780       // Declaration nodes are always introduced in one of four modes. | 
| 779       ASSERT(mode == VAR || mode == CONST || mode == LET); | 781       ASSERT(mode == VAR || | 
| 780       PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE; | 782              mode == CONST || | 
|  | 783              mode == CONST_HARMONY || | 
|  | 784              mode == LET); | 
|  | 785       PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) | 
|  | 786           ? READ_ONLY : NONE; | 
| 781       __ mov(r1, Operand(Smi::FromInt(attr))); | 787       __ mov(r1, Operand(Smi::FromInt(attr))); | 
| 782       // Push initial value, if any. | 788       // Push initial value, if any. | 
| 783       // Note: For variables we must not push an initial value (such as | 789       // Note: For variables we must not push an initial value (such as | 
| 784       // 'undefined') because we may have a (legal) redeclaration and we | 790       // 'undefined') because we may have a (legal) redeclaration and we | 
| 785       // must not destroy the current value. | 791       // must not destroy the current value. | 
| 786       if (function != NULL) { | 792       if (function != NULL) { | 
| 787         __ Push(cp, r2, r1); | 793         __ Push(cp, r2, r1); | 
| 788         // Push initial value for function declaration. | 794         // Push initial value for function declaration. | 
| 789         VisitForStackValue(function); | 795         VisitForStackValue(function); | 
| 790       } else if (mode == CONST || mode == LET) { | 796       } else if (binding_needs_init) { | 
| 791         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 797         __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 
| 792         __ Push(cp, r2, r1, r0); | 798         __ Push(cp, r2, r1, r0); | 
| 793       } else { | 799       } else { | 
| 794         __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value. | 800         __ mov(r0, Operand(Smi::FromInt(0)));  // Indicates no initial value. | 
| 795         __ Push(cp, r2, r1, r0); | 801         __ Push(cp, r2, r1, r0); | 
| 796       } | 802       } | 
| 797       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 803       __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 
| 798       break; | 804       break; | 
| 799     } | 805     } | 
| 800   } | 806   } | 
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1217   // introducing variables.  In those cases, we do not want to | 1223   // introducing variables.  In those cases, we do not want to | 
| 1218   // perform a runtime call for all variables in the scope | 1224   // perform a runtime call for all variables in the scope | 
| 1219   // containing the eval. | 1225   // containing the eval. | 
| 1220   if (var->mode() == DYNAMIC_GLOBAL) { | 1226   if (var->mode() == DYNAMIC_GLOBAL) { | 
| 1221     EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 1227     EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 
| 1222     __ jmp(done); | 1228     __ jmp(done); | 
| 1223   } else if (var->mode() == DYNAMIC_LOCAL) { | 1229   } else if (var->mode() == DYNAMIC_LOCAL) { | 
| 1224     Variable* local = var->local_if_not_shadowed(); | 1230     Variable* local = var->local_if_not_shadowed(); | 
| 1225     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); | 1231     __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); | 
| 1226     if (local->mode() == CONST || | 1232     if (local->mode() == CONST || | 
|  | 1233         local->mode() == CONST_HARMONY || | 
| 1227         local->mode() == LET) { | 1234         local->mode() == LET) { | 
| 1228       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1235       __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 
| 1229       if (local->mode() == CONST) { | 1236       if (local->mode() == CONST) { | 
| 1230         __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1237         __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 
| 1231       } else {  // LET | 1238       } else {  // LET || CONST_HARMONY | 
| 1232         __ b(ne, done); | 1239         __ b(ne, done); | 
| 1233         __ mov(r0, Operand(var->name())); | 1240         __ mov(r0, Operand(var->name())); | 
| 1234         __ push(r0); | 1241         __ push(r0); | 
| 1235         __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1242         __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 1236       } | 1243       } | 
| 1237     } | 1244     } | 
| 1238     __ jmp(done); | 1245     __ jmp(done); | 
| 1239   } | 1246   } | 
| 1240 } | 1247 } | 
| 1241 | 1248 | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 1259       context()->Plug(r0); | 1266       context()->Plug(r0); | 
| 1260       break; | 1267       break; | 
| 1261     } | 1268     } | 
| 1262 | 1269 | 
| 1263     case Variable::PARAMETER: | 1270     case Variable::PARAMETER: | 
| 1264     case Variable::LOCAL: | 1271     case Variable::LOCAL: | 
| 1265     case Variable::CONTEXT: { | 1272     case Variable::CONTEXT: { | 
| 1266       Comment cmnt(masm_, var->IsContextSlot() | 1273       Comment cmnt(masm_, var->IsContextSlot() | 
| 1267                               ? "Context variable" | 1274                               ? "Context variable" | 
| 1268                               : "Stack variable"); | 1275                               : "Stack variable"); | 
| 1269       if (var->mode() != LET && var->mode() != CONST) { | 1276       if (!var->binding_needs_init()) { | 
| 1270         context()->Plug(var); | 1277         context()->Plug(var); | 
| 1271       } else { | 1278       } else { | 
| 1272         // Let and const need a read barrier. | 1279         // Let and const need a read barrier. | 
| 1273         GetVar(r0, var); | 1280         GetVar(r0, var); | 
| 1274         __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1281         __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 
| 1275         if (var->mode() == LET) { | 1282         if (var->mode() == LET || var->mode() == CONST_HARMONY) { | 
|  | 1283           // Throw a reference error when using an uninitialized let/const | 
|  | 1284           // binding in harmony mode. | 
| 1276           Label done; | 1285           Label done; | 
| 1277           __ b(ne, &done); | 1286           __ b(ne, &done); | 
| 1278           __ mov(r0, Operand(var->name())); | 1287           __ mov(r0, Operand(var->name())); | 
| 1279           __ push(r0); | 1288           __ push(r0); | 
| 1280           __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1289           __ CallRuntime(Runtime::kThrowReferenceError, 1); | 
| 1281           __ bind(&done); | 1290           __ bind(&done); | 
| 1282         } else { | 1291         } else { | 
|  | 1292           // Uninitalized const bindings outside of harmony mode are unholed. | 
|  | 1293           ASSERT(var->mode() == CONST); | 
| 1283           __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 1294           __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); | 
| 1284         } | 1295         } | 
| 1285         context()->Plug(r0); | 1296         context()->Plug(r0); | 
| 1286       } | 1297       } | 
| 1287       break; | 1298       break; | 
| 1288     } | 1299     } | 
| 1289 | 1300 | 
| 1290     case Variable::LOOKUP: { | 1301     case Variable::LOOKUP: { | 
| 1291       Label done, slow; | 1302       Label done, slow; | 
| 1292       // Generate code for loading from variables potentially shadowed | 1303       // Generate code for loading from variables potentially shadowed | 
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1896       __ str(result_register(), location); | 1907       __ str(result_register(), location); | 
| 1897       if (var->IsContextSlot()) { | 1908       if (var->IsContextSlot()) { | 
| 1898         // RecordWrite may destroy all its register arguments. | 1909         // RecordWrite may destroy all its register arguments. | 
| 1899         __ mov(r3, result_register()); | 1910         __ mov(r3, result_register()); | 
| 1900         int offset = Context::SlotOffset(var->index()); | 1911         int offset = Context::SlotOffset(var->index()); | 
| 1901         __ RecordWriteContextSlot( | 1912         __ RecordWriteContextSlot( | 
| 1902             r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); | 1913             r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); | 
| 1903       } | 1914       } | 
| 1904     } | 1915     } | 
| 1905 | 1916 | 
| 1906   } else if (var->mode() != CONST) { | 1917   } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 
| 1907     // Assignment to var or initializing assignment to let. | 1918     // Assignment to var or initializing assignment to let/const | 
|  | 1919     // in harmony mode. | 
| 1908     if (var->IsStackAllocated() || var->IsContextSlot()) { | 1920     if (var->IsStackAllocated() || var->IsContextSlot()) { | 
| 1909       MemOperand location = VarOperand(var, r1); | 1921       MemOperand location = VarOperand(var, r1); | 
| 1910       if (FLAG_debug_code && op == Token::INIT_LET) { | 1922       if (FLAG_debug_code && op == Token::INIT_LET) { | 
| 1911         // Check for an uninitialized let binding. | 1923         // Check for an uninitialized let binding. | 
| 1912         __ ldr(r2, location); | 1924         __ ldr(r2, location); | 
| 1913         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 1925         __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 
| 1914         __ Check(eq, "Let binding re-initialization."); | 1926         __ Check(eq, "Let binding re-initialization."); | 
| 1915       } | 1927       } | 
| 1916       // Perform the assignment. | 1928       // Perform the assignment. | 
| 1917       __ str(r0, location); | 1929       __ str(r0, location); | 
| (...skipping 2342 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4260   *context_length = 0; | 4272   *context_length = 0; | 
| 4261   return previous_; | 4273   return previous_; | 
| 4262 } | 4274 } | 
| 4263 | 4275 | 
| 4264 | 4276 | 
| 4265 #undef __ | 4277 #undef __ | 
| 4266 | 4278 | 
| 4267 } }  // namespace v8::internal | 4279 } }  // namespace v8::internal | 
| 4268 | 4280 | 
| 4269 #endif  // V8_TARGET_ARCH_ARM | 4281 #endif  // V8_TARGET_ARCH_ARM | 
| OLD | NEW | 
|---|