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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } else { | 193 } else { |
194 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 194 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
195 } | 195 } |
196 function_in_register = false; | 196 function_in_register = false; |
197 // Context is returned in both v0 and cp. It replaces the context | 197 // Context is returned in both v0 and cp. It replaces the context |
198 // passed to us. It's saved in the stack and kept live in cp. | 198 // passed to us. It's saved in the stack and kept live in cp. |
199 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 199 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
200 // Copy any necessary parameters into the context. | 200 // Copy any necessary parameters into the context. |
201 int num_parameters = info->scope()->num_parameters(); | 201 int num_parameters = info->scope()->num_parameters(); |
202 for (int i = 0; i < num_parameters; i++) { | 202 for (int i = 0; i < num_parameters; i++) { |
203 Slot* slot = scope()->parameter(i)->AsSlot(); | 203 Slot* slot = scope()->parameter(i)->rewrite(); |
204 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 204 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
205 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 205 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
206 (num_parameters - 1 - i) * kPointerSize; | 206 (num_parameters - 1 - i) * kPointerSize; |
207 // Load parameter from stack. | 207 // Load parameter from stack. |
208 __ lw(a0, MemOperand(fp, parameter_offset)); | 208 __ lw(a0, MemOperand(fp, parameter_offset)); |
209 // Store it in the context. | 209 // Store it in the context. |
210 __ li(a1, Operand(Context::SlotOffset(slot->index()))); | 210 __ li(a1, Operand(Context::SlotOffset(slot->index()))); |
211 __ addu(a2, cp, a1); | 211 __ addu(a2, cp, a1); |
212 __ sw(a0, MemOperand(a2, 0)); | 212 __ sw(a0, MemOperand(a2, 0)); |
213 // Update the write barrier. This clobbers all involved | 213 // Update the write barrier. This clobbers all involved |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 if (is_strict_mode()) { | 245 if (is_strict_mode()) { |
246 type = ArgumentsAccessStub::NEW_STRICT; | 246 type = ArgumentsAccessStub::NEW_STRICT; |
247 } else if (function()->has_duplicate_parameters()) { | 247 } else if (function()->has_duplicate_parameters()) { |
248 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 248 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; |
249 } else { | 249 } else { |
250 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 250 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; |
251 } | 251 } |
252 ArgumentsAccessStub stub(type); | 252 ArgumentsAccessStub stub(type); |
253 __ CallStub(&stub); | 253 __ CallStub(&stub); |
254 | 254 |
255 Move(arguments->AsSlot(), v0, a1, a2); | 255 Move(arguments->rewrite(), v0, a1, a2); |
256 } | 256 } |
257 | 257 |
258 if (FLAG_trace) { | 258 if (FLAG_trace) { |
259 __ CallRuntime(Runtime::kTraceEnter, 0); | 259 __ CallRuntime(Runtime::kTraceEnter, 0); |
260 } | 260 } |
261 | 261 |
262 // Visit the declarations and body unless there is an illegal | 262 // Visit the declarations and body unless there is an illegal |
263 // redeclaration. | 263 // redeclaration. |
264 if (scope()->HasIllegalRedeclaration()) { | 264 if (scope()->HasIllegalRedeclaration()) { |
265 Comment cmnt(masm_, "[ Declarations"); | 265 Comment cmnt(masm_, "[ Declarations"); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 case Slot::PARAMETER: | 626 case Slot::PARAMETER: |
627 case Slot::LOCAL: | 627 case Slot::LOCAL: |
628 return MemOperand(fp, SlotOffset(slot)); | 628 return MemOperand(fp, SlotOffset(slot)); |
629 case Slot::CONTEXT: { | 629 case Slot::CONTEXT: { |
630 int context_chain_length = | 630 int context_chain_length = |
631 scope()->ContextChainLength(slot->var()->scope()); | 631 scope()->ContextChainLength(slot->var()->scope()); |
632 __ LoadContext(scratch, context_chain_length); | 632 __ LoadContext(scratch, context_chain_length); |
633 return ContextOperand(scratch, slot->index()); | 633 return ContextOperand(scratch, slot->index()); |
634 } | 634 } |
635 case Slot::LOOKUP: | 635 case Slot::LOOKUP: |
| 636 case Slot::GLOBAL: |
636 UNREACHABLE(); | 637 UNREACHABLE(); |
637 } | 638 } |
638 UNREACHABLE(); | 639 UNREACHABLE(); |
639 return MemOperand(v0, 0); | 640 return MemOperand(v0, 0); |
640 } | 641 } |
641 | 642 |
642 | 643 |
643 void FullCodeGenerator::Move(Register destination, Slot* source) { | 644 void FullCodeGenerator::Move(Register destination, Slot* source) { |
644 // Use destination as scratch. | 645 // Use destination as scratch. |
645 MemOperand slot_operand = EmitSlotSearch(source, destination); | 646 MemOperand slot_operand = EmitSlotSearch(source, destination); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 src); | 690 src); |
690 } | 691 } |
691 } | 692 } |
692 | 693 |
693 | 694 |
694 void FullCodeGenerator::EmitDeclaration(Variable* variable, | 695 void FullCodeGenerator::EmitDeclaration(Variable* variable, |
695 Variable::Mode mode, | 696 Variable::Mode mode, |
696 FunctionLiteral* function) { | 697 FunctionLiteral* function) { |
697 Comment cmnt(masm_, "[ Declaration"); | 698 Comment cmnt(masm_, "[ Declaration"); |
698 ASSERT(variable != NULL); // Must have been resolved. | 699 ASSERT(variable != NULL); // Must have been resolved. |
699 Slot* slot = variable->AsSlot(); | 700 Slot* slot = variable->rewrite(); |
700 ASSERT(slot != NULL); | 701 ASSERT(slot != NULL); |
701 switch (slot->type()) { | 702 switch (slot->type()) { |
702 case Slot::PARAMETER: | 703 case Slot::PARAMETER: |
703 case Slot::LOCAL: | 704 case Slot::LOCAL: |
704 if (function != NULL) { | 705 if (function != NULL) { |
705 VisitForAccumulatorValue(function); | 706 VisitForAccumulatorValue(function); |
706 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); | 707 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); |
707 } else if (mode == Variable::CONST || mode == Variable::LET) { | 708 } else if (mode == Variable::CONST || mode == Variable::LET) { |
708 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 709 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
709 __ sw(t0, MemOperand(fp, SlotOffset(slot))); | 710 __ sw(t0, MemOperand(fp, SlotOffset(slot))); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 __ Push(cp, a2, a1, a0); | 763 __ Push(cp, a2, a1, a0); |
763 } else { | 764 } else { |
764 ASSERT(Smi::FromInt(0) == 0); | 765 ASSERT(Smi::FromInt(0) == 0); |
765 // No initial value! | 766 // No initial value! |
766 __ mov(a0, zero_reg); // Operand(Smi::FromInt(0))); | 767 __ mov(a0, zero_reg); // Operand(Smi::FromInt(0))); |
767 __ Push(cp, a2, a1, a0); | 768 __ Push(cp, a2, a1, a0); |
768 } | 769 } |
769 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 770 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
770 break; | 771 break; |
771 } | 772 } |
| 773 |
| 774 case Slot::GLOBAL: |
| 775 UNREACHABLE(); |
772 } | 776 } |
773 } | 777 } |
774 | 778 |
775 | 779 |
776 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { | 780 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
777 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); | 781 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); |
778 } | 782 } |
779 | 783 |
780 | 784 |
781 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 785 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 Label* done) { | 1186 Label* done) { |
1183 // Generate fast-case code for variables that might be shadowed by | 1187 // Generate fast-case code for variables that might be shadowed by |
1184 // eval-introduced variables. Eval is used a lot without | 1188 // eval-introduced variables. Eval is used a lot without |
1185 // introducing variables. In those cases, we do not want to | 1189 // introducing variables. In those cases, we do not want to |
1186 // perform a runtime call for all variables in the scope | 1190 // perform a runtime call for all variables in the scope |
1187 // containing the eval. | 1191 // containing the eval. |
1188 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { | 1192 if (slot->var()->mode() == Variable::DYNAMIC_GLOBAL) { |
1189 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); | 1193 EmitLoadGlobalSlotCheckExtensions(slot, typeof_state, slow); |
1190 __ Branch(done); | 1194 __ Branch(done); |
1191 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { | 1195 } else if (slot->var()->mode() == Variable::DYNAMIC_LOCAL) { |
1192 Slot* potential_slot = slot->var()->local_if_not_shadowed()->AsSlot(); | 1196 Slot* potential_slot = slot->var()->local_if_not_shadowed()->rewrite(); |
1193 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); | 1197 Expression* rewrite = slot->var()->local_if_not_shadowed()->rewrite(); |
1194 if (potential_slot != NULL) { | 1198 if (potential_slot != NULL) { |
1195 // Generate fast case for locals that rewrite to slots. | 1199 // Generate fast case for locals that rewrite to slots. |
1196 __ lw(v0, ContextSlotOperandCheckExtensions(potential_slot, slow)); | 1200 __ lw(v0, ContextSlotOperandCheckExtensions(potential_slot, slow)); |
1197 if (potential_slot->var()->mode() == Variable::CONST) { | 1201 if (potential_slot->var()->mode() == Variable::CONST) { |
1198 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1202 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1199 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1203 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
1200 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1204 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
1201 __ movz(v0, a0, at); // Conditional move. | 1205 __ movz(v0, a0, at); // Conditional move. |
1202 } | 1206 } |
1203 __ Branch(done); | 1207 __ Branch(done); |
1204 } else if (rewrite != NULL) { | 1208 } else if (rewrite != NULL) { |
1205 // Generate fast case for calls of an argument function. | 1209 // Generate fast case for calls of an argument function. |
1206 Property* property = rewrite->AsProperty(); | 1210 Property* property = rewrite->AsProperty(); |
1207 if (property != NULL) { | 1211 if (property != NULL) { |
1208 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); | 1212 VariableProxy* obj_proxy = property->obj()->AsVariableProxy(); |
1209 Literal* key_literal = property->key()->AsLiteral(); | 1213 Literal* key_literal = property->key()->AsLiteral(); |
1210 if (obj_proxy != NULL && | 1214 if (obj_proxy != NULL && |
1211 key_literal != NULL && | 1215 key_literal != NULL && |
1212 obj_proxy->IsArguments() && | 1216 obj_proxy->IsArguments() && |
1213 key_literal->handle()->IsSmi()) { | 1217 key_literal->handle()->IsSmi()) { |
1214 // Load arguments object if there are no eval-introduced | 1218 // Load arguments object if there are no eval-introduced |
1215 // variables. Then load the argument from the arguments | 1219 // variables. Then load the argument from the arguments |
1216 // object using keyed load. | 1220 // object using keyed load. |
1217 __ lw(a1, | 1221 __ lw(a1, |
1218 ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), | 1222 ContextSlotOperandCheckExtensions(obj_proxy->var()->rewrite(), |
1219 slow)); | 1223 slow)); |
1220 __ li(a0, Operand(key_literal->handle())); | 1224 __ li(a0, Operand(key_literal->handle())); |
1221 Handle<Code> ic = | 1225 Handle<Code> ic = |
1222 isolate()->builtins()->KeyedLoadIC_Initialize(); | 1226 isolate()->builtins()->KeyedLoadIC_Initialize(); |
1223 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); | 1227 __ Call(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); |
1224 __ Branch(done); | 1228 __ Branch(done); |
1225 } | 1229 } |
1226 } | 1230 } |
1227 } | 1231 } |
1228 } | 1232 } |
1229 } | 1233 } |
1230 | 1234 |
1231 | 1235 |
1232 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { | 1236 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { |
1233 // Record position before possible IC call. | 1237 // Record position before possible IC call. |
1234 SetSourcePosition(proxy->position()); | 1238 SetSourcePosition(proxy->position()); |
1235 Variable* var = proxy->var(); | 1239 Variable* var = proxy->var(); |
1236 | 1240 |
1237 // Three cases: non-this global variables, lookup slots, and all other | 1241 // Three cases: non-this global variables, lookup slots, and all other |
1238 // types of slots. | 1242 // types of slots. |
1239 Slot* slot = var->AsSlot(); | 1243 Slot* slot = var->rewrite(); |
1240 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); | 1244 ASSERT((var->is_global() && !var->is_this()) == (slot == NULL)); |
1241 | 1245 |
1242 if (slot == NULL) { | 1246 if (slot == NULL) { |
1243 Comment cmnt(masm_, "Global variable"); | 1247 Comment cmnt(masm_, "Global variable"); |
1244 // Use inline caching. Variable name is passed in a2 and the global | 1248 // Use inline caching. Variable name is passed in a2 and the global |
1245 // object (receiver) in a0. | 1249 // object (receiver) in a0. |
1246 __ lw(a0, GlobalObjectOperand()); | 1250 __ lw(a0, GlobalObjectOperand()); |
1247 __ li(a2, Operand(var->name())); | 1251 __ li(a2, Operand(var->name())); |
1248 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1249 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1253 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 } | 1830 } |
1827 } | 1831 } |
1828 PrepareForBailoutForId(bailout_ast_id, TOS_REG); | 1832 PrepareForBailoutForId(bailout_ast_id, TOS_REG); |
1829 context()->Plug(v0); | 1833 context()->Plug(v0); |
1830 } | 1834 } |
1831 | 1835 |
1832 | 1836 |
1833 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1837 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1834 Token::Value op) { | 1838 Token::Value op) { |
1835 ASSERT(var != NULL); | 1839 ASSERT(var != NULL); |
1836 ASSERT(var->is_global() || var->AsSlot() != NULL); | 1840 ASSERT(var->is_global() || var->rewrite() != NULL); |
1837 | 1841 |
1838 if (var->is_global()) { | 1842 if (var->is_global()) { |
1839 ASSERT(!var->is_this()); | 1843 ASSERT(!var->is_this()); |
1840 // Assignment to a global variable. Use inline caching for the | 1844 // Assignment to a global variable. Use inline caching for the |
1841 // assignment. Right-hand-side value is passed in a0, variable name in | 1845 // assignment. Right-hand-side value is passed in a0, variable name in |
1842 // a2, and the global object in a1. | 1846 // a2, and the global object in a1. |
1843 __ mov(a0, result_register()); | 1847 __ mov(a0, result_register()); |
1844 __ li(a2, Operand(var->name())); | 1848 __ li(a2, Operand(var->name())); |
1845 __ lw(a1, GlobalObjectOperand()); | 1849 __ lw(a1, GlobalObjectOperand()); |
1846 Handle<Code> ic = is_strict_mode() | 1850 Handle<Code> ic = is_strict_mode() |
1847 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 1851 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
1848 : isolate()->builtins()->StoreIC_Initialize(); | 1852 : isolate()->builtins()->StoreIC_Initialize(); |
1849 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1853 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1850 | 1854 |
1851 } else if (op == Token::INIT_CONST) { | 1855 } else if (op == Token::INIT_CONST) { |
1852 // Like var declarations, const declarations are hoisted to function | 1856 // Like var declarations, const declarations are hoisted to function |
1853 // scope. However, unlike var initializers, const initializers are able | 1857 // scope. However, unlike var initializers, const initializers are able |
1854 // to drill a hole to that function context, even from inside a 'with' | 1858 // to drill a hole to that function context, even from inside a 'with' |
1855 // context. We thus bypass the normal static scope lookup. | 1859 // context. We thus bypass the normal static scope lookup. |
1856 Slot* slot = var->AsSlot(); | 1860 Slot* slot = var->rewrite(); |
1857 Label skip; | 1861 Label skip; |
1858 switch (slot->type()) { | 1862 switch (slot->type()) { |
1859 case Slot::PARAMETER: | 1863 case Slot::PARAMETER: |
1860 // No const parameters. | 1864 // No const parameters. |
1861 UNREACHABLE(); | 1865 UNREACHABLE(); |
1862 break; | 1866 break; |
1863 case Slot::LOCAL: | 1867 case Slot::LOCAL: |
1864 // Detect const reinitialization by checking for the hole value. | 1868 // Detect const reinitialization by checking for the hole value. |
1865 __ lw(a1, MemOperand(fp, SlotOffset(slot))); | 1869 __ lw(a1, MemOperand(fp, SlotOffset(slot))); |
1866 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 1870 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
1867 __ Branch(&skip, ne, a1, Operand(t0)); | 1871 __ Branch(&skip, ne, a1, Operand(t0)); |
1868 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); | 1872 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); |
1869 break; | 1873 break; |
1870 case Slot::CONTEXT: | 1874 case Slot::CONTEXT: |
1871 case Slot::LOOKUP: | 1875 case Slot::LOOKUP: |
1872 __ push(result_register()); | 1876 __ push(result_register()); |
1873 __ li(a0, Operand(slot->var()->name())); | 1877 __ li(a0, Operand(slot->var()->name())); |
1874 __ Push(cp, a0); // Context and name. | 1878 __ Push(cp, a0); // Context and name. |
1875 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1879 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
1876 break; | 1880 break; |
| 1881 case Slot::GLOBAL: |
| 1882 UNREACHABLE(); |
1877 } | 1883 } |
1878 __ bind(&skip); | 1884 __ bind(&skip); |
1879 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) { | 1885 } else if (var->mode() == Variable::LET && op != Token::INIT_LET) { |
1880 // Perform the assignment for non-const variables. Const assignments | 1886 // Perform the assignment for non-const variables. Const assignments |
1881 // are simply skipped. | 1887 // are simply skipped. |
1882 Slot* slot = var->AsSlot(); | 1888 Slot* slot = var->AsSlot(); |
1883 switch (slot->type()) { | 1889 switch (slot->type()) { |
1884 case Slot::PARAMETER: | 1890 case Slot::PARAMETER: |
1885 case Slot::LOCAL: { | 1891 case Slot::LOCAL: { |
1886 Label assign; | 1892 Label assign; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1923 __ li(a1, Operand(slot->var()->name())); | 1929 __ li(a1, Operand(slot->var()->name())); |
1924 __ li(a0, Operand(Smi::FromInt(strict_mode_flag()))); | 1930 __ li(a0, Operand(Smi::FromInt(strict_mode_flag()))); |
1925 __ Push(cp, a1, a0); // Context, name, strict mode. | 1931 __ Push(cp, a1, a0); // Context, name, strict mode. |
1926 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1932 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1927 break; | 1933 break; |
1928 } | 1934 } |
1929 | 1935 |
1930 } else if (var->mode() != Variable::CONST) { | 1936 } else if (var->mode() != Variable::CONST) { |
1931 // Perform the assignment for non-const variables. Const assignments | 1937 // Perform the assignment for non-const variables. Const assignments |
1932 // are simply skipped. | 1938 // are simply skipped. |
1933 Slot* slot = var->AsSlot(); | 1939 Slot* slot = var->rewrite(); |
1934 switch (slot->type()) { | 1940 switch (slot->type()) { |
1935 case Slot::PARAMETER: | 1941 case Slot::PARAMETER: |
1936 case Slot::LOCAL: | 1942 case Slot::LOCAL: |
1937 // Perform the assignment. | 1943 // Perform the assignment. |
1938 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); | 1944 __ sw(result_register(), MemOperand(fp, SlotOffset(slot))); |
1939 break; | 1945 break; |
1940 | 1946 |
1941 case Slot::CONTEXT: { | 1947 case Slot::CONTEXT: { |
1942 MemOperand target = EmitSlotSearch(slot, a1); | 1948 MemOperand target = EmitSlotSearch(slot, a1); |
1943 // Perform the assignment and issue the write barrier. | 1949 // Perform the assignment and issue the write barrier. |
1944 __ sw(result_register(), target); | 1950 __ sw(result_register(), target); |
1945 // RecordWrite may destroy all its register arguments. | 1951 // RecordWrite may destroy all its register arguments. |
1946 __ mov(a3, result_register()); | 1952 __ mov(a3, result_register()); |
1947 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 1953 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
1948 __ RecordWrite(a1, Operand(offset), a2, a3); | 1954 __ RecordWrite(a1, Operand(offset), a2, a3); |
1949 break; | 1955 break; |
1950 } | 1956 } |
1951 | 1957 |
1952 case Slot::LOOKUP: | 1958 case Slot::LOOKUP: |
1953 // Call the runtime for the assignment. | 1959 // Call the runtime for the assignment. |
1954 __ push(v0); // Value. | 1960 __ push(v0); // Value. |
1955 __ li(a1, Operand(slot->var()->name())); | 1961 __ li(a1, Operand(slot->var()->name())); |
1956 __ li(a0, Operand(Smi::FromInt(strict_mode_flag()))); | 1962 __ li(a0, Operand(Smi::FromInt(strict_mode_flag()))); |
1957 __ Push(cp, a1, a0); // Context, name, strict mode. | 1963 __ Push(cp, a1, a0); // Context, name, strict mode. |
1958 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1964 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
1959 break; | 1965 break; |
| 1966 |
| 1967 case Slot::GLOBAL: |
| 1968 UNREACHABLE(); |
1960 } | 1969 } |
1961 } | 1970 } |
1962 } | 1971 } |
1963 | 1972 |
1964 | 1973 |
1965 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1974 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1966 // Assignment to a property, using a named store IC. | 1975 // Assignment to a property, using a named store IC. |
1967 Property* prop = expr->target()->AsProperty(); | 1976 Property* prop = expr->target()->AsProperty(); |
1968 ASSERT(prop != NULL); | 1977 ASSERT(prop != NULL); |
1969 ASSERT(prop->key()->AsLiteral() != NULL); | 1978 ASSERT(prop->key()->AsLiteral() != NULL); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2217 | 2226 |
2218 // Push the arguments. | 2227 // Push the arguments. |
2219 for (int i = 0; i < arg_count; i++) { | 2228 for (int i = 0; i < arg_count; i++) { |
2220 VisitForStackValue(args->at(i)); | 2229 VisitForStackValue(args->at(i)); |
2221 } | 2230 } |
2222 // If we know that eval can only be shadowed by eval-introduced | 2231 // If we know that eval can only be shadowed by eval-introduced |
2223 // variables we attempt to load the global eval function directly | 2232 // variables we attempt to load the global eval function directly |
2224 // in generated code. If we succeed, there is no need to perform a | 2233 // in generated code. If we succeed, there is no need to perform a |
2225 // context lookup in the runtime system. | 2234 // context lookup in the runtime system. |
2226 Label done; | 2235 Label done; |
2227 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { | 2236 if (var->rewrite() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) { |
2228 Label slow; | 2237 Label slow; |
2229 EmitLoadGlobalSlotCheckExtensions(var->AsSlot(), | 2238 EmitLoadGlobalSlotCheckExtensions(var->rewrite(), |
2230 NOT_INSIDE_TYPEOF, | 2239 NOT_INSIDE_TYPEOF, |
2231 &slow); | 2240 &slow); |
2232 // Push the function and resolve eval. | 2241 // Push the function and resolve eval. |
2233 __ push(v0); | 2242 __ push(v0); |
2234 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count); | 2243 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count); |
2235 __ jmp(&done); | 2244 __ jmp(&done); |
2236 __ bind(&slow); | 2245 __ bind(&slow); |
2237 } | 2246 } |
2238 | 2247 |
2239 // Push copy of the function (found below the arguments) and | 2248 // Push copy of the function (found below the arguments) and |
(...skipping 17 matching lines...) Expand all Loading... |
2257 __ CallStub(&stub); | 2266 __ CallStub(&stub); |
2258 RecordJSReturnSite(expr); | 2267 RecordJSReturnSite(expr); |
2259 // Restore context register. | 2268 // Restore context register. |
2260 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2269 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2261 context()->DropAndPlug(1, v0); | 2270 context()->DropAndPlug(1, v0); |
2262 } else if (var != NULL && !var->is_this() && var->is_global()) { | 2271 } else if (var != NULL && !var->is_this() && var->is_global()) { |
2263 // Push global object as receiver for the call IC. | 2272 // Push global object as receiver for the call IC. |
2264 __ lw(a0, GlobalObjectOperand()); | 2273 __ lw(a0, GlobalObjectOperand()); |
2265 __ push(a0); | 2274 __ push(a0); |
2266 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 2275 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
2267 } else if (var != NULL && var->AsSlot() != NULL && | 2276 } else if (var != NULL && var->rewrite() != NULL && |
2268 var->AsSlot()->type() == Slot::LOOKUP) { | 2277 var->rewrite()->type() == Slot::LOOKUP) { |
2269 // Call to a lookup slot (dynamically introduced variable). | 2278 // Call to a lookup slot (dynamically introduced variable). |
2270 Label slow, done; | 2279 Label slow, done; |
2271 | 2280 |
2272 { PreservePositionScope scope(masm()->positions_recorder()); | 2281 { PreservePositionScope scope(masm()->positions_recorder()); |
2273 // Generate code for loading from variables potentially shadowed | 2282 // Generate code for loading from variables potentially shadowed |
2274 // by eval-introduced variables. | 2283 // by eval-introduced variables. |
2275 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 2284 EmitDynamicLoadFromSlotFastCase(var->rewrite(), |
2276 NOT_INSIDE_TYPEOF, | 2285 NOT_INSIDE_TYPEOF, |
2277 &slow, | 2286 &slow, |
2278 &done); | 2287 &done); |
2279 } | 2288 } |
2280 | 2289 |
2281 __ bind(&slow); | 2290 __ bind(&slow); |
2282 // Call the runtime to find the function to call (returned in v0) | 2291 // Call the runtime to find the function to call (returned in v0) |
2283 // and the object holding it (returned in v1). | 2292 // and the object holding it (returned in v1). |
2284 __ push(context_register()); | 2293 __ push(context_register()); |
2285 __ li(a2, Operand(var->name())); | 2294 __ li(a2, Operand(var->name())); |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3670 // Delete of an unqualified identifier is disallowed in strict mode | 3679 // Delete of an unqualified identifier is disallowed in strict mode |
3671 // but "delete this" is. | 3680 // but "delete this" is. |
3672 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); | 3681 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); |
3673 if (var->is_global()) { | 3682 if (var->is_global()) { |
3674 __ lw(a2, GlobalObjectOperand()); | 3683 __ lw(a2, GlobalObjectOperand()); |
3675 __ li(a1, Operand(var->name())); | 3684 __ li(a1, Operand(var->name())); |
3676 __ li(a0, Operand(Smi::FromInt(kNonStrictMode))); | 3685 __ li(a0, Operand(Smi::FromInt(kNonStrictMode))); |
3677 __ Push(a2, a1, a0); | 3686 __ Push(a2, a1, a0); |
3678 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 3687 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
3679 context()->Plug(v0); | 3688 context()->Plug(v0); |
3680 } else if (var->AsSlot() != NULL && | 3689 } else if (var->rewrite() != NULL && |
3681 var->AsSlot()->type() != Slot::LOOKUP) { | 3690 var->rewrite()->type() != Slot::LOOKUP) { |
3682 // Result of deleting non-global, non-dynamic variables is false. | 3691 // Result of deleting non-global, non-dynamic variables is false. |
3683 // The subexpression does not have side effects. | 3692 // The subexpression does not have side effects. |
3684 context()->Plug(false); | 3693 context()->Plug(false); |
3685 } else { | 3694 } else { |
3686 // Non-global variable. Call the runtime to try to delete from the | 3695 // Non-global variable. Call the runtime to try to delete from the |
3687 // context where the variable was introduced. | 3696 // context where the variable was introduced. |
3688 __ push(context_register()); | 3697 __ push(context_register()); |
3689 __ li(a2, Operand(var->name())); | 3698 __ li(a2, Operand(var->name())); |
3690 __ push(a2); | 3699 __ push(a2); |
3691 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 3700 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3961 Comment cmnt(masm_, "Global variable"); | 3970 Comment cmnt(masm_, "Global variable"); |
3962 __ lw(a0, GlobalObjectOperand()); | 3971 __ lw(a0, GlobalObjectOperand()); |
3963 __ li(a2, Operand(proxy->name())); | 3972 __ li(a2, Operand(proxy->name())); |
3964 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3973 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
3965 // Use a regular load, not a contextual load, to avoid a reference | 3974 // Use a regular load, not a contextual load, to avoid a reference |
3966 // error. | 3975 // error. |
3967 __ Call(ic); | 3976 __ Call(ic); |
3968 PrepareForBailout(expr, TOS_REG); | 3977 PrepareForBailout(expr, TOS_REG); |
3969 context()->Plug(v0); | 3978 context()->Plug(v0); |
3970 } else if (proxy != NULL && | 3979 } else if (proxy != NULL && |
3971 proxy->var()->AsSlot() != NULL && | 3980 proxy->var()->rewrite() != NULL && |
3972 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { | 3981 proxy->var()->rewrite()->type() == Slot::LOOKUP) { |
3973 Label done, slow; | 3982 Label done, slow; |
3974 | 3983 |
3975 // Generate code for loading from variables potentially shadowed | 3984 // Generate code for loading from variables potentially shadowed |
3976 // by eval-introduced variables. | 3985 // by eval-introduced variables. |
3977 Slot* slot = proxy->var()->AsSlot(); | 3986 Slot* slot = proxy->var()->rewrite(); |
3978 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); | 3987 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); |
3979 | 3988 |
3980 __ bind(&slow); | 3989 __ bind(&slow); |
3981 __ li(a0, Operand(proxy->name())); | 3990 __ li(a0, Operand(proxy->name())); |
3982 __ Push(cp, a0); | 3991 __ Push(cp, a0); |
3983 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 3992 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
3984 PrepareForBailout(expr, TOS_REG); | 3993 PrepareForBailout(expr, TOS_REG); |
3985 __ bind(&done); | 3994 __ bind(&done); |
3986 | 3995 |
3987 context()->Plug(v0); | 3996 context()->Plug(v0); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4286 __ Addu(at, a1, Operand(masm_->CodeObject())); | 4295 __ Addu(at, a1, Operand(masm_->CodeObject())); |
4287 __ Jump(at); | 4296 __ Jump(at); |
4288 } | 4297 } |
4289 | 4298 |
4290 | 4299 |
4291 #undef __ | 4300 #undef __ |
4292 | 4301 |
4293 } } // namespace v8::internal | 4302 } } // namespace v8::internal |
4294 | 4303 |
4295 #endif // V8_TARGET_ARCH_MIPS | 4304 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |