Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: src/arm/full-codegen-arm.cc

Issue 7992005: Block scoped const variables. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Removed redundant code. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/ast.h » ('j') | src/contexts.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 __ str(result_register(), location); 1951 __ str(result_register(), location);
1941 if (var->IsContextSlot()) { 1952 if (var->IsContextSlot()) {
1942 // RecordWrite may destroy all its register arguments. 1953 // RecordWrite may destroy all its register arguments.
1943 __ mov(r3, result_register()); 1954 __ mov(r3, result_register());
1944 int offset = Context::SlotOffset(var->index()); 1955 int offset = Context::SlotOffset(var->index());
1945 __ RecordWriteContextSlot( 1956 __ RecordWriteContextSlot(
1946 r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs); 1957 r1, offset, r3, r2, kLRHasBeenSaved, kDontSaveFPRegs);
1947 } 1958 }
1948 } 1959 }
1949 1960
1950 } else if (var->mode() != CONST) { 1961 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
1951 // Assignment to var or initializing assignment to let. 1962 // Assignment to var or initializing assignment to let/const
1963 // in harmony mode.
1952 if (var->IsStackAllocated() || var->IsContextSlot()) { 1964 if (var->IsStackAllocated() || var->IsContextSlot()) {
1953 MemOperand location = VarOperand(var, r1); 1965 MemOperand location = VarOperand(var, r1);
1954 if (FLAG_debug_code && op == Token::INIT_LET) { 1966 if (FLAG_debug_code && op == Token::INIT_LET) {
1955 // Check for an uninitialized let binding. 1967 // Check for an uninitialized let binding.
1956 __ ldr(r2, location); 1968 __ ldr(r2, location);
1957 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); 1969 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
1958 __ Check(eq, "Let binding re-initialization."); 1970 __ Check(eq, "Let binding re-initialization.");
1959 } 1971 }
1960 // Perform the assignment. 1972 // Perform the assignment.
1961 __ str(r0, location); 1973 __ str(r0, location);
(...skipping 2342 matching lines...) Expand 10 before | Expand all | Expand 10 after
4304 *context_length = 0; 4316 *context_length = 0;
4305 return previous_; 4317 return previous_;
4306 } 4318 }
4307 4319
4308 4320
4309 #undef __ 4321 #undef __
4310 4322
4311 } } // namespace v8::internal 4323 } } // namespace v8::internal
4312 4324
4313 #endif // V8_TARGET_ARCH_ARM 4325 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ast.h » ('j') | src/contexts.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698