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

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

Issue 8390033: MIPS: port Block scoped const variables. (Closed)
Patch Set: Created 9 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 Comment cmnt(masm_, "[ Declarations"); 271 Comment cmnt(masm_, "[ Declarations");
272 scope()->VisitIllegalRedeclaration(this); 272 scope()->VisitIllegalRedeclaration(this);
273 273
274 } else { 274 } else {
275 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS); 275 PrepareForBailoutForId(AstNode::kFunctionEntryId, NO_REGISTERS);
276 { Comment cmnt(masm_, "[ Declarations"); 276 { Comment cmnt(masm_, "[ Declarations");
277 // For named function expressions, declare the function name as a 277 // For named function expressions, declare the function name as a
278 // constant. 278 // constant.
279 if (scope()->is_function_scope() && scope()->function() != NULL) { 279 if (scope()->is_function_scope() && scope()->function() != NULL) {
280 int ignored = 0; 280 int ignored = 0;
281 EmitDeclaration(scope()->function(), CONST, NULL, &ignored); 281 VariableProxy* proxy = scope()->function();
282 ASSERT(proxy->var()->mode() == CONST ||
283 proxy->var()->mode() == CONST_HARMONY);
284 EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored);
282 } 285 }
283 VisitDeclarations(scope()->declarations()); 286 VisitDeclarations(scope()->declarations());
284 } 287 }
285 288
286 { Comment cmnt(masm_, "[ Stack check"); 289 { Comment cmnt(masm_, "[ Stack check");
287 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS); 290 PrepareForBailoutForId(AstNode::kDeclarationsId, NO_REGISTERS);
288 Label ok; 291 Label ok;
289 __ LoadRoot(t0, Heap::kStackLimitRootIndex); 292 __ LoadRoot(t0, Heap::kStackLimitRootIndex);
290 __ Branch(&ok, hs, sp, Operand(t0)); 293 __ Branch(&ok, hs, sp, Operand(t0));
291 StackCheckStub stub; 294 StackCheckStub stub;
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 724
722 725
723 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, 726 void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
724 VariableMode mode, 727 VariableMode mode,
725 FunctionLiteral* function, 728 FunctionLiteral* function,
726 int* global_count) { 729 int* global_count) {
727 // If it was not possible to allocate the variable at compile time, we 730 // If it was not possible to allocate the variable at compile time, we
728 // need to "declare" it at runtime to make sure it actually exists in the 731 // need to "declare" it at runtime to make sure it actually exists in the
729 // local context. 732 // local context.
730 Variable* variable = proxy->var(); 733 Variable* variable = proxy->var();
734 bool binding_needs_init =
735 mode == CONST || mode == CONST_HARMONY || mode == LET;
731 switch (variable->location()) { 736 switch (variable->location()) {
732 case Variable::UNALLOCATED: 737 case Variable::UNALLOCATED:
733 ++(*global_count); 738 ++(*global_count);
734 break; 739 break;
735 740
736 case Variable::PARAMETER: 741 case Variable::PARAMETER:
737 case Variable::LOCAL: 742 case Variable::LOCAL:
738 if (function != NULL) { 743 if (function != NULL) {
739 Comment cmnt(masm_, "[ Declaration"); 744 Comment cmnt(masm_, "[ Declaration");
740 VisitForAccumulatorValue(function); 745 VisitForAccumulatorValue(function);
741 __ sw(result_register(), StackOperand(variable)); 746 __ sw(result_register(), StackOperand(variable));
742 } else if (mode == CONST || mode == LET) { 747 } else if (binding_needs_init) {
743 Comment cmnt(masm_, "[ Declaration"); 748 Comment cmnt(masm_, "[ Declaration");
744 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 749 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
745 __ sw(t0, StackOperand(variable)); 750 __ sw(t0, StackOperand(variable));
746 } 751 }
747 break; 752 break;
748 753
749 case Variable::CONTEXT: 754 case Variable::CONTEXT:
750 // The variable in the decl always resides in the current function 755 // The variable in the decl always resides in the current function
751 // context. 756 // context.
752 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 757 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
(...skipping 15 matching lines...) Expand all
768 // We know that we have written a function, which is not a smi. 773 // We know that we have written a function, which is not a smi.
769 __ RecordWriteContextSlot(cp, 774 __ RecordWriteContextSlot(cp,
770 offset, 775 offset,
771 result_register(), 776 result_register(),
772 a2, 777 a2,
773 kRAHasBeenSaved, 778 kRAHasBeenSaved,
774 kDontSaveFPRegs, 779 kDontSaveFPRegs,
775 EMIT_REMEMBERED_SET, 780 EMIT_REMEMBERED_SET,
776 OMIT_SMI_CHECK); 781 OMIT_SMI_CHECK);
777 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 782 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
778 } else if (mode == CONST || mode == LET) { 783 } else if (binding_needs_init) {
779 Comment cmnt(masm_, "[ Declaration"); 784 Comment cmnt(masm_, "[ Declaration");
780 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 785 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
781 __ sw(at, ContextOperand(cp, variable->index())); 786 __ sw(at, ContextOperand(cp, variable->index()));
782 // No write barrier since the_hole_value is in old space. 787 // No write barrier since the_hole_value is in old space.
783 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 788 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
784 } 789 }
785 break; 790 break;
786 791
787 case Variable::LOOKUP: { 792 case Variable::LOOKUP: {
788 Comment cmnt(masm_, "[ Declaration"); 793 Comment cmnt(masm_, "[ Declaration");
789 __ li(a2, Operand(variable->name())); 794 __ li(a2, Operand(variable->name()));
790 // Declaration nodes are always introduced in one of three modes. 795 // Declaration nodes are always introduced in one of four modes.
791 ASSERT(mode == VAR || mode == CONST || mode == LET); 796 ASSERT(mode == VAR ||
792 PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE; 797 mode == CONST ||
798 mode == CONST_HARMONY ||
799 mode == LET);
800 PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY)
801 ? READ_ONLY : NONE;
793 __ li(a1, Operand(Smi::FromInt(attr))); 802 __ li(a1, Operand(Smi::FromInt(attr)));
794 // Push initial value, if any. 803 // Push initial value, if any.
795 // Note: For variables we must not push an initial value (such as 804 // Note: For variables we must not push an initial value (such as
796 // 'undefined') because we may have a (legal) redeclaration and we 805 // 'undefined') because we may have a (legal) redeclaration and we
797 // must not destroy the current value. 806 // must not destroy the current value.
798 if (function != NULL) { 807 if (function != NULL) {
799 __ Push(cp, a2, a1); 808 __ Push(cp, a2, a1);
800 // Push initial value for function declaration. 809 // Push initial value for function declaration.
801 VisitForStackValue(function); 810 VisitForStackValue(function);
802 } else if (mode == CONST || mode == LET) { 811 } else if (binding_needs_init) {
803 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex); 812 __ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
804 __ Push(cp, a2, a1, a0); 813 __ Push(cp, a2, a1, a0);
805 } else { 814 } else {
806 ASSERT(Smi::FromInt(0) == 0); 815 ASSERT(Smi::FromInt(0) == 0);
807 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value. 816 __ mov(a0, zero_reg); // Smi::FromInt(0) indicates no initial value.
808 __ Push(cp, a2, a1, a0); 817 __ Push(cp, a2, a1, a0);
809 } 818 }
810 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 819 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
811 break; 820 break;
812 } 821 }
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 // introducing variables. In those cases, we do not want to 1230 // introducing variables. In those cases, we do not want to
1222 // perform a runtime call for all variables in the scope 1231 // perform a runtime call for all variables in the scope
1223 // containing the eval. 1232 // containing the eval.
1224 if (var->mode() == DYNAMIC_GLOBAL) { 1233 if (var->mode() == DYNAMIC_GLOBAL) {
1225 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1234 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1226 __ Branch(done); 1235 __ Branch(done);
1227 } else if (var->mode() == DYNAMIC_LOCAL) { 1236 } else if (var->mode() == DYNAMIC_LOCAL) {
1228 Variable* local = var->local_if_not_shadowed(); 1237 Variable* local = var->local_if_not_shadowed();
1229 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); 1238 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow));
1230 if (local->mode() == CONST || 1239 if (local->mode() == CONST ||
1240 local->mode() == CONST_HARMONY ||
1231 local->mode() == LET) { 1241 local->mode() == LET) {
1232 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1242 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1233 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1243 __ subu(at, v0, at); // Sub as compare: at == 0 on eq.
1234 if (local->mode() == CONST) { 1244 if (local->mode() == CONST) {
1235 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1245 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1236 __ movz(v0, a0, at); // Conditional move: return Undefined if TheHole. 1246 __ movz(v0, a0, at); // Conditional move: return Undefined if TheHole.
1237 } else { // LET 1247 } else { // LET || CONST_HARMONY
1238 __ Branch(done, ne, at, Operand(zero_reg)); 1248 __ Branch(done, ne, at, Operand(zero_reg));
1239 __ li(a0, Operand(var->name())); 1249 __ li(a0, Operand(var->name()));
1240 __ push(a0); 1250 __ push(a0);
1241 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1251 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1242 } 1252 }
1243 } 1253 }
1244 __ Branch(done); 1254 __ Branch(done);
1245 } 1255 }
1246 } 1256 }
1247 1257
(...skipping 17 matching lines...) Expand all
1265 context()->Plug(v0); 1275 context()->Plug(v0);
1266 break; 1276 break;
1267 } 1277 }
1268 1278
1269 case Variable::PARAMETER: 1279 case Variable::PARAMETER:
1270 case Variable::LOCAL: 1280 case Variable::LOCAL:
1271 case Variable::CONTEXT: { 1281 case Variable::CONTEXT: {
1272 Comment cmnt(masm_, var->IsContextSlot() 1282 Comment cmnt(masm_, var->IsContextSlot()
1273 ? "Context variable" 1283 ? "Context variable"
1274 : "Stack variable"); 1284 : "Stack variable");
1275 if (var->mode() != LET && var->mode() != CONST) { 1285 if (!var->binding_needs_init()) {
1276 context()->Plug(var); 1286 context()->Plug(var);
1277 } else { 1287 } else {
1278 // Let and const need a read barrier. 1288 // Let and const need a read barrier.
1279 GetVar(v0, var); 1289 GetVar(v0, var);
1280 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1290 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1281 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1291 __ subu(at, v0, at); // Sub as compare: at == 0 on eq.
1282 if (var->mode() == LET) { 1292 if (var->mode() == LET || var->mode() == CONST_HARMONY) {
1293 // Throw a reference error when using an uninitialized let/const
1294 // binding in harmony mode.
1283 Label done; 1295 Label done;
1284 __ Branch(&done, ne, at, Operand(zero_reg)); 1296 __ Branch(&done, ne, at, Operand(zero_reg));
1285 __ li(a0, Operand(var->name())); 1297 __ li(a0, Operand(var->name()));
1286 __ push(a0); 1298 __ push(a0);
1287 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1299 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1288 __ bind(&done); 1300 __ bind(&done);
1289 } else { 1301 } else {
1302 // Uninitalized const bindings outside of harmony mode are unholed.
1303 ASSERT(var->mode() == CONST);
1290 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1304 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1291 __ movz(v0, a0, at); // Conditional move: Undefined if TheHole. 1305 __ movz(v0, a0, at); // Conditional move: Undefined if TheHole.
1292 } 1306 }
1293 context()->Plug(v0); 1307 context()->Plug(v0);
1294 } 1308 }
1295 break; 1309 break;
1296 } 1310 }
1297 1311
1298 case Variable::LOOKUP: { 1312 case Variable::LOOKUP: {
1299 Label done, slow; 1313 Label done, slow;
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 __ sw(result_register(), location); 1971 __ sw(result_register(), location);
1958 if (var->IsContextSlot()) { 1972 if (var->IsContextSlot()) {
1959 // RecordWrite may destroy all its register arguments. 1973 // RecordWrite may destroy all its register arguments.
1960 __ mov(a3, result_register()); 1974 __ mov(a3, result_register());
1961 int offset = Context::SlotOffset(var->index()); 1975 int offset = Context::SlotOffset(var->index());
1962 __ RecordWriteContextSlot( 1976 __ RecordWriteContextSlot(
1963 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); 1977 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
1964 } 1978 }
1965 } 1979 }
1966 1980
1967 } else if (var->mode() != CONST) { 1981 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
1968 // Assignment to var or initializing assignment to let. 1982 // Assignment to var or initializing assignment to let/const
1983 // in harmony mode.
1969 if (var->IsStackAllocated() || var->IsContextSlot()) { 1984 if (var->IsStackAllocated() || var->IsContextSlot()) {
1970 MemOperand location = VarOperand(var, a1); 1985 MemOperand location = VarOperand(var, a1);
1971 if (FLAG_debug_code && op == Token::INIT_LET) { 1986 if (FLAG_debug_code && op == Token::INIT_LET) {
1972 // Check for an uninitialized let binding. 1987 // Check for an uninitialized let binding.
1973 __ lw(a2, location); 1988 __ lw(a2, location);
1974 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 1989 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
1975 __ Check(eq, "Let binding re-initialization.", a2, Operand(t0)); 1990 __ Check(eq, "Let binding re-initialization.", a2, Operand(t0));
1976 } 1991 }
1977 // Perform the assignment. 1992 // Perform the assignment.
1978 __ sw(v0, location); 1993 __ sw(v0, location);
(...skipping 2357 matching lines...) Expand 10 before | Expand all | Expand 10 after
4336 *context_length = 0; 4351 *context_length = 0;
4337 return previous_; 4352 return previous_;
4338 } 4353 }
4339 4354
4340 4355
4341 #undef __ 4356 #undef __
4342 4357
4343 } } // namespace v8::internal 4358 } } // namespace v8::internal
4344 4359
4345 #endif // V8_TARGET_ARCH_MIPS 4360 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698