| 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 |