OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 __ push(Immediate(isolate()->factory()->undefined_value())); | 130 __ push(Immediate(isolate()->factory()->undefined_value())); |
131 } else if (locals_count > 1) { | 131 } else if (locals_count > 1) { |
132 if (locals_count >= 128) { | 132 if (locals_count >= 128) { |
133 Label ok; | 133 Label ok; |
134 __ mov(ecx, esp); | 134 __ mov(ecx, esp); |
135 __ sub(ecx, Immediate(locals_count * kPointerSize)); | 135 __ sub(ecx, Immediate(locals_count * kPointerSize)); |
136 ExternalReference stack_limit = | 136 ExternalReference stack_limit = |
137 ExternalReference::address_of_real_stack_limit(isolate()); | 137 ExternalReference::address_of_real_stack_limit(isolate()); |
138 __ cmp(ecx, Operand::StaticVariable(stack_limit)); | 138 __ cmp(ecx, Operand::StaticVariable(stack_limit)); |
139 __ j(above_equal, &ok, Label::kNear); | 139 __ j(above_equal, &ok, Label::kNear); |
140 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 140 __ CallRuntime(Runtime::kThrowStackOverflow); |
141 __ bind(&ok); | 141 __ bind(&ok); |
142 } | 142 } |
143 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); | 143 __ mov(eax, Immediate(isolate()->factory()->undefined_value())); |
144 const int kMaxPushes = 32; | 144 const int kMaxPushes = 32; |
145 if (locals_count >= kMaxPushes) { | 145 if (locals_count >= kMaxPushes) { |
146 int loop_iterations = locals_count / kMaxPushes; | 146 int loop_iterations = locals_count / kMaxPushes; |
147 __ mov(ecx, loop_iterations); | 147 __ mov(ecx, loop_iterations); |
148 Label loop_header; | 148 Label loop_header; |
149 __ bind(&loop_header); | 149 __ bind(&loop_header); |
150 // Do pushes. | 150 // Do pushes. |
(...skipping 15 matching lines...) Expand all Loading... |
166 | 166 |
167 // Possibly allocate a local context. | 167 // Possibly allocate a local context. |
168 if (info->scope()->num_heap_slots() > 0) { | 168 if (info->scope()->num_heap_slots() > 0) { |
169 Comment cmnt(masm_, "[ Allocate context"); | 169 Comment cmnt(masm_, "[ Allocate context"); |
170 bool need_write_barrier = true; | 170 bool need_write_barrier = true; |
171 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 171 int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
172 // Argument to NewContext is the function, which is still in edi. | 172 // Argument to NewContext is the function, which is still in edi. |
173 if (info->scope()->is_script_scope()) { | 173 if (info->scope()->is_script_scope()) { |
174 __ push(edi); | 174 __ push(edi); |
175 __ Push(info->scope()->GetScopeInfo(info->isolate())); | 175 __ Push(info->scope()->GetScopeInfo(info->isolate())); |
176 __ CallRuntime(Runtime::kNewScriptContext, 2); | 176 __ CallRuntime(Runtime::kNewScriptContext); |
177 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); | 177 PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG); |
178 // The new target value is not used, clobbering is safe. | 178 // The new target value is not used, clobbering is safe. |
179 DCHECK_NULL(info->scope()->new_target_var()); | 179 DCHECK_NULL(info->scope()->new_target_var()); |
180 } else { | 180 } else { |
181 if (info->scope()->new_target_var() != nullptr) { | 181 if (info->scope()->new_target_var() != nullptr) { |
182 __ push(edx); // Preserve new target. | 182 __ push(edx); // Preserve new target. |
183 } | 183 } |
184 if (slots <= FastNewContextStub::kMaximumSlots) { | 184 if (slots <= FastNewContextStub::kMaximumSlots) { |
185 FastNewContextStub stub(isolate(), slots); | 185 FastNewContextStub stub(isolate(), slots); |
186 __ CallStub(&stub); | 186 __ CallStub(&stub); |
187 // Result of FastNewContextStub is always in new space. | 187 // Result of FastNewContextStub is always in new space. |
188 need_write_barrier = false; | 188 need_write_barrier = false; |
189 } else { | 189 } else { |
190 __ push(edi); | 190 __ push(edi); |
191 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 191 __ CallRuntime(Runtime::kNewFunctionContext); |
192 } | 192 } |
193 if (info->scope()->new_target_var() != nullptr) { | 193 if (info->scope()->new_target_var() != nullptr) { |
194 __ pop(edx); // Restore new target. | 194 __ pop(edx); // Restore new target. |
195 } | 195 } |
196 } | 196 } |
197 function_in_register = false; | 197 function_in_register = false; |
198 // Context is returned in eax. It replaces the context passed to us. | 198 // Context is returned in eax. It replaces the context passed to us. |
199 // It's saved in the stack and kept live in esi. | 199 // It's saved in the stack and kept live in esi. |
200 __ mov(esi, eax); | 200 __ mov(esi, eax); |
201 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); | 201 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 295 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
296 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 296 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
297 is_unmapped, literal()->has_duplicate_parameters()); | 297 is_unmapped, literal()->has_duplicate_parameters()); |
298 ArgumentsAccessStub stub(isolate(), type); | 298 ArgumentsAccessStub stub(isolate(), type); |
299 __ CallStub(&stub); | 299 __ CallStub(&stub); |
300 | 300 |
301 SetVar(arguments, eax, ebx, edx); | 301 SetVar(arguments, eax, ebx, edx); |
302 } | 302 } |
303 | 303 |
304 if (FLAG_trace) { | 304 if (FLAG_trace) { |
305 __ CallRuntime(Runtime::kTraceEnter, 0); | 305 __ CallRuntime(Runtime::kTraceEnter); |
306 } | 306 } |
307 | 307 |
308 // Visit the declarations and body unless there is an illegal | 308 // Visit the declarations and body unless there is an illegal |
309 // redeclaration. | 309 // redeclaration. |
310 if (scope()->HasIllegalRedeclaration()) { | 310 if (scope()->HasIllegalRedeclaration()) { |
311 Comment cmnt(masm_, "[ Declarations"); | 311 Comment cmnt(masm_, "[ Declarations"); |
312 VisitForEffect(scope()->GetIllegalRedeclaration()); | 312 VisitForEffect(scope()->GetIllegalRedeclaration()); |
313 | 313 |
314 } else { | 314 } else { |
315 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 315 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 | 400 |
401 void FullCodeGenerator::EmitReturnSequence() { | 401 void FullCodeGenerator::EmitReturnSequence() { |
402 Comment cmnt(masm_, "[ Return sequence"); | 402 Comment cmnt(masm_, "[ Return sequence"); |
403 if (return_label_.is_bound()) { | 403 if (return_label_.is_bound()) { |
404 __ jmp(&return_label_); | 404 __ jmp(&return_label_); |
405 } else { | 405 } else { |
406 // Common return label | 406 // Common return label |
407 __ bind(&return_label_); | 407 __ bind(&return_label_); |
408 if (FLAG_trace) { | 408 if (FLAG_trace) { |
409 __ push(eax); | 409 __ push(eax); |
410 __ CallRuntime(Runtime::kTraceExit, 1); | 410 __ CallRuntime(Runtime::kTraceExit); |
411 } | 411 } |
412 // Pretend that the exit is a backwards jump to the entry. | 412 // Pretend that the exit is a backwards jump to the entry. |
413 int weight = 1; | 413 int weight = 1; |
414 if (info_->ShouldSelfOptimize()) { | 414 if (info_->ShouldSelfOptimize()) { |
415 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 415 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
416 } else { | 416 } else { |
417 int distance = masm_->pc_offset(); | 417 int distance = masm_->pc_offset(); |
418 weight = Min(kMaxBackEdgeWeight, | 418 weight = Min(kMaxBackEdgeWeight, |
419 Max(1, distance / kCodeSizeMultiplier)); | 419 Max(1, distance / kCodeSizeMultiplier)); |
420 } | 420 } |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 // Note: For variables we must not push an initial value (such as | 785 // Note: For variables we must not push an initial value (such as |
786 // 'undefined') because we may have a (legal) redeclaration and we | 786 // 'undefined') because we may have a (legal) redeclaration and we |
787 // must not destroy the current value. | 787 // must not destroy the current value. |
788 if (hole_init) { | 788 if (hole_init) { |
789 __ push(Immediate(isolate()->factory()->the_hole_value())); | 789 __ push(Immediate(isolate()->factory()->the_hole_value())); |
790 } else { | 790 } else { |
791 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 791 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
792 } | 792 } |
793 __ push( | 793 __ push( |
794 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); | 794 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); |
795 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 795 __ CallRuntime(Runtime::kDeclareLookupSlot); |
796 break; | 796 break; |
797 } | 797 } |
798 } | 798 } |
799 } | 799 } |
800 | 800 |
801 void FullCodeGenerator::VisitFunctionDeclaration( | 801 void FullCodeGenerator::VisitFunctionDeclaration( |
802 FunctionDeclaration* declaration) { | 802 FunctionDeclaration* declaration) { |
803 VariableProxy* proxy = declaration->proxy(); | 803 VariableProxy* proxy = declaration->proxy(); |
804 Variable* variable = proxy->var(); | 804 Variable* variable = proxy->var(); |
805 switch (variable->location()) { | 805 switch (variable->location()) { |
(...skipping 28 matching lines...) Expand all Loading... |
834 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 834 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
835 break; | 835 break; |
836 } | 836 } |
837 | 837 |
838 case VariableLocation::LOOKUP: { | 838 case VariableLocation::LOOKUP: { |
839 Comment cmnt(masm_, "[ FunctionDeclaration"); | 839 Comment cmnt(masm_, "[ FunctionDeclaration"); |
840 __ push(Immediate(variable->name())); | 840 __ push(Immediate(variable->name())); |
841 VisitForStackValue(declaration->fun()); | 841 VisitForStackValue(declaration->fun()); |
842 __ push( | 842 __ push( |
843 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); | 843 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); |
844 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 844 __ CallRuntime(Runtime::kDeclareLookupSlot); |
845 break; | 845 break; |
846 } | 846 } |
847 } | 847 } |
848 } | 848 } |
849 | 849 |
850 | 850 |
851 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 851 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
852 // Call the runtime to declare the globals. | 852 // Call the runtime to declare the globals. |
853 __ Push(pairs); | 853 __ Push(pairs); |
854 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 854 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
855 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 855 __ CallRuntime(Runtime::kDeclareGlobals); |
856 // Return value is ignored. | 856 // Return value is ignored. |
857 } | 857 } |
858 | 858 |
859 | 859 |
860 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 860 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
861 // Call the runtime to declare the modules. | 861 // Call the runtime to declare the modules. |
862 __ Push(descriptions); | 862 __ Push(descriptions); |
863 __ CallRuntime(Runtime::kDeclareModules, 1); | 863 __ CallRuntime(Runtime::kDeclareModules); |
864 // Return value is ignored. | 864 // Return value is ignored. |
865 } | 865 } |
866 | 866 |
867 | 867 |
868 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 868 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
869 Comment cmnt(masm_, "[ SwitchStatement"); | 869 Comment cmnt(masm_, "[ SwitchStatement"); |
870 Breakable nested_statement(this, stmt); | 870 Breakable nested_statement(this, stmt); |
871 SetStatementPosition(stmt); | 871 SetStatementPosition(stmt); |
872 | 872 |
873 // Keep the switch value on the stack until a case matches. | 873 // Keep the switch value on the stack until a case matches. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 // guarantee cache validity, call the runtime system to check cache | 1001 // guarantee cache validity, call the runtime system to check cache |
1002 // validity or get the property names in a fixed array. | 1002 // validity or get the property names in a fixed array. |
1003 __ CheckEnumCache(&call_runtime); | 1003 __ CheckEnumCache(&call_runtime); |
1004 | 1004 |
1005 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 1005 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
1006 __ jmp(&use_cache, Label::kNear); | 1006 __ jmp(&use_cache, Label::kNear); |
1007 | 1007 |
1008 // Get the set of properties to enumerate. | 1008 // Get the set of properties to enumerate. |
1009 __ bind(&call_runtime); | 1009 __ bind(&call_runtime); |
1010 __ push(eax); | 1010 __ push(eax); |
1011 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1011 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
1012 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1012 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
1013 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 1013 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
1014 isolate()->factory()->meta_map()); | 1014 isolate()->factory()->meta_map()); |
1015 __ j(not_equal, &fixed_array); | 1015 __ j(not_equal, &fixed_array); |
1016 | 1016 |
1017 | 1017 |
1018 // We got a map in register eax. Get the enumeration cache from it. | 1018 // We got a map in register eax. Get the enumeration cache from it. |
1019 Label no_descriptors; | 1019 Label no_descriptors; |
1020 __ bind(&use_cache); | 1020 __ bind(&use_cache); |
1021 | 1021 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 Label update_each; | 1073 Label update_each; |
1074 __ mov(ecx, Operand(esp, 4 * kPointerSize)); | 1074 __ mov(ecx, Operand(esp, 4 * kPointerSize)); |
1075 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 1075 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); |
1076 __ j(equal, &update_each, Label::kNear); | 1076 __ j(equal, &update_each, Label::kNear); |
1077 | 1077 |
1078 // Convert the entry to a string or null if it isn't a property | 1078 // Convert the entry to a string or null if it isn't a property |
1079 // anymore. If the property has been removed while iterating, we | 1079 // anymore. If the property has been removed while iterating, we |
1080 // just skip it. | 1080 // just skip it. |
1081 __ push(ecx); // Enumerable. | 1081 __ push(ecx); // Enumerable. |
1082 __ push(ebx); // Current entry. | 1082 __ push(ebx); // Current entry. |
1083 __ CallRuntime(Runtime::kForInFilter, 2); | 1083 __ CallRuntime(Runtime::kForInFilter); |
1084 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1084 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
1085 __ cmp(eax, isolate()->factory()->undefined_value()); | 1085 __ cmp(eax, isolate()->factory()->undefined_value()); |
1086 __ j(equal, loop_statement.continue_label()); | 1086 __ j(equal, loop_statement.continue_label()); |
1087 __ mov(ebx, eax); | 1087 __ mov(ebx, eax); |
1088 | 1088 |
1089 // Update the 'each' property or variable from the possibly filtered | 1089 // Update the 'each' property or variable from the possibly filtered |
1090 // entry in register ebx. | 1090 // entry in register ebx. |
1091 __ bind(&update_each); | 1091 __ bind(&update_each); |
1092 __ mov(result_register(), ebx); | 1092 __ mov(result_register(), ebx); |
1093 // Perform the assignment as if via '='. | 1093 // Perform the assignment as if via '='. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1131 if (!FLAG_always_opt && | 1131 if (!FLAG_always_opt && |
1132 !FLAG_prepare_always_opt && | 1132 !FLAG_prepare_always_opt && |
1133 !pretenure && | 1133 !pretenure && |
1134 scope()->is_function_scope() && | 1134 scope()->is_function_scope() && |
1135 info->num_literals() == 0) { | 1135 info->num_literals() == 0) { |
1136 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1136 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
1137 __ mov(ebx, Immediate(info)); | 1137 __ mov(ebx, Immediate(info)); |
1138 __ CallStub(&stub); | 1138 __ CallStub(&stub); |
1139 } else { | 1139 } else { |
1140 __ push(Immediate(info)); | 1140 __ push(Immediate(info)); |
1141 __ CallRuntime( | 1141 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
1142 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1142 : Runtime::kNewClosure); |
1143 } | 1143 } |
1144 context()->Plug(eax); | 1144 context()->Plug(eax); |
1145 } | 1145 } |
1146 | 1146 |
1147 | 1147 |
1148 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1148 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
1149 FeedbackVectorSlot slot) { | 1149 FeedbackVectorSlot slot) { |
1150 DCHECK(NeedsHomeObject(initializer)); | 1150 DCHECK(NeedsHomeObject(initializer)); |
1151 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1151 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
1152 __ mov(StoreDescriptor::NameRegister(), | 1152 __ mov(StoreDescriptor::NameRegister(), |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 Variable* local = var->local_if_not_shadowed(); | 1268 Variable* local = var->local_if_not_shadowed(); |
1269 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | 1269 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); |
1270 if (local->mode() == LET || local->mode() == CONST || | 1270 if (local->mode() == LET || local->mode() == CONST || |
1271 local->mode() == CONST_LEGACY) { | 1271 local->mode() == CONST_LEGACY) { |
1272 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1272 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1273 __ j(not_equal, done); | 1273 __ j(not_equal, done); |
1274 if (local->mode() == CONST_LEGACY) { | 1274 if (local->mode() == CONST_LEGACY) { |
1275 __ mov(eax, isolate()->factory()->undefined_value()); | 1275 __ mov(eax, isolate()->factory()->undefined_value()); |
1276 } else { // LET || CONST | 1276 } else { // LET || CONST |
1277 __ push(Immediate(var->name())); | 1277 __ push(Immediate(var->name())); |
1278 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1278 __ CallRuntime(Runtime::kThrowReferenceError); |
1279 } | 1279 } |
1280 } | 1280 } |
1281 __ jmp(done); | 1281 __ jmp(done); |
1282 } | 1282 } |
1283 } | 1283 } |
1284 | 1284 |
1285 | 1285 |
1286 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1286 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1287 TypeofMode typeof_mode) { | 1287 TypeofMode typeof_mode) { |
1288 Variable* var = proxy->var(); | 1288 Variable* var = proxy->var(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 if (NeedsHoleCheckForLoad(proxy)) { | 1326 if (NeedsHoleCheckForLoad(proxy)) { |
1327 // Let and const need a read barrier. | 1327 // Let and const need a read barrier. |
1328 Label done; | 1328 Label done; |
1329 GetVar(eax, var); | 1329 GetVar(eax, var); |
1330 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1330 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1331 __ j(not_equal, &done, Label::kNear); | 1331 __ j(not_equal, &done, Label::kNear); |
1332 if (var->mode() == LET || var->mode() == CONST) { | 1332 if (var->mode() == LET || var->mode() == CONST) { |
1333 // Throw a reference error when using an uninitialized let/const | 1333 // Throw a reference error when using an uninitialized let/const |
1334 // binding in harmony mode. | 1334 // binding in harmony mode. |
1335 __ push(Immediate(var->name())); | 1335 __ push(Immediate(var->name())); |
1336 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1336 __ CallRuntime(Runtime::kThrowReferenceError); |
1337 } else { | 1337 } else { |
1338 // Uninitialized legacy const bindings are unholed. | 1338 // Uninitialized legacy const bindings are unholed. |
1339 DCHECK(var->mode() == CONST_LEGACY); | 1339 DCHECK(var->mode() == CONST_LEGACY); |
1340 __ mov(eax, isolate()->factory()->undefined_value()); | 1340 __ mov(eax, isolate()->factory()->undefined_value()); |
1341 } | 1341 } |
1342 __ bind(&done); | 1342 __ bind(&done); |
1343 context()->Plug(eax); | 1343 context()->Plug(eax); |
1344 break; | 1344 break; |
1345 } | 1345 } |
1346 context()->Plug(var); | 1346 context()->Plug(var); |
1347 break; | 1347 break; |
1348 } | 1348 } |
1349 | 1349 |
1350 case VariableLocation::LOOKUP: { | 1350 case VariableLocation::LOOKUP: { |
1351 Comment cmnt(masm_, "[ Lookup variable"); | 1351 Comment cmnt(masm_, "[ Lookup variable"); |
1352 Label done, slow; | 1352 Label done, slow; |
1353 // Generate code for loading from variables potentially shadowed | 1353 // Generate code for loading from variables potentially shadowed |
1354 // by eval-introduced variables. | 1354 // by eval-introduced variables. |
1355 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1355 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
1356 __ bind(&slow); | 1356 __ bind(&slow); |
1357 __ push(esi); // Context. | 1357 __ push(esi); // Context. |
1358 __ push(Immediate(var->name())); | 1358 __ push(Immediate(var->name())); |
1359 Runtime::FunctionId function_id = | 1359 Runtime::FunctionId function_id = |
1360 typeof_mode == NOT_INSIDE_TYPEOF | 1360 typeof_mode == NOT_INSIDE_TYPEOF |
1361 ? Runtime::kLoadLookupSlot | 1361 ? Runtime::kLoadLookupSlot |
1362 : Runtime::kLoadLookupSlotNoReferenceError; | 1362 : Runtime::kLoadLookupSlotNoReferenceError; |
1363 __ CallRuntime(function_id, 2); | 1363 __ CallRuntime(function_id); |
1364 __ bind(&done); | 1364 __ bind(&done); |
1365 context()->Plug(eax); | 1365 context()->Plug(eax); |
1366 break; | 1366 break; |
1367 } | 1367 } |
1368 } | 1368 } |
1369 } | 1369 } |
1370 | 1370 |
1371 | 1371 |
1372 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1372 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1373 Comment cmnt(masm_, "[ RegExpLiteral"); | 1373 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 28 matching lines...) Expand all Loading... |
1402 | 1402 |
1403 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1403 Handle<FixedArray> constant_properties = expr->constant_properties(); |
1404 int flags = expr->ComputeFlags(); | 1404 int flags = expr->ComputeFlags(); |
1405 // If any of the keys would store to the elements array, then we shouldn't | 1405 // If any of the keys would store to the elements array, then we shouldn't |
1406 // allow it. | 1406 // allow it. |
1407 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1407 if (MustCreateObjectLiteralWithRuntime(expr)) { |
1408 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1408 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1409 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1409 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1410 __ push(Immediate(constant_properties)); | 1410 __ push(Immediate(constant_properties)); |
1411 __ push(Immediate(Smi::FromInt(flags))); | 1411 __ push(Immediate(Smi::FromInt(flags))); |
1412 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1412 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1413 } else { | 1413 } else { |
1414 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1414 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1415 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1415 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
1416 __ mov(ecx, Immediate(constant_properties)); | 1416 __ mov(ecx, Immediate(constant_properties)); |
1417 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1417 __ mov(edx, Immediate(Smi::FromInt(flags))); |
1418 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1418 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1419 __ CallStub(&stub); | 1419 __ CallStub(&stub); |
1420 } | 1420 } |
1421 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1421 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1422 | 1422 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 break; | 1464 break; |
1465 } | 1465 } |
1466 __ push(Operand(esp, 0)); // Duplicate receiver. | 1466 __ push(Operand(esp, 0)); // Duplicate receiver. |
1467 VisitForStackValue(key); | 1467 VisitForStackValue(key); |
1468 VisitForStackValue(value); | 1468 VisitForStackValue(value); |
1469 if (property->emit_store()) { | 1469 if (property->emit_store()) { |
1470 if (NeedsHomeObject(value)) { | 1470 if (NeedsHomeObject(value)) { |
1471 EmitSetHomeObject(value, 2, property->GetSlot()); | 1471 EmitSetHomeObject(value, 2, property->GetSlot()); |
1472 } | 1472 } |
1473 __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode | 1473 __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode |
1474 __ CallRuntime(Runtime::kSetProperty, 4); | 1474 __ CallRuntime(Runtime::kSetProperty); |
1475 } else { | 1475 } else { |
1476 __ Drop(3); | 1476 __ Drop(3); |
1477 } | 1477 } |
1478 break; | 1478 break; |
1479 case ObjectLiteral::Property::PROTOTYPE: | 1479 case ObjectLiteral::Property::PROTOTYPE: |
1480 __ push(Operand(esp, 0)); // Duplicate receiver. | 1480 __ push(Operand(esp, 0)); // Duplicate receiver. |
1481 VisitForStackValue(value); | 1481 VisitForStackValue(value); |
1482 DCHECK(property->emit_store()); | 1482 DCHECK(property->emit_store()); |
1483 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1483 __ CallRuntime(Runtime::kInternalSetPrototype); |
1484 break; | 1484 break; |
1485 case ObjectLiteral::Property::GETTER: | 1485 case ObjectLiteral::Property::GETTER: |
1486 if (property->emit_store()) { | 1486 if (property->emit_store()) { |
1487 accessor_table.lookup(key)->second->getter = property; | 1487 accessor_table.lookup(key)->second->getter = property; |
1488 } | 1488 } |
1489 break; | 1489 break; |
1490 case ObjectLiteral::Property::SETTER: | 1490 case ObjectLiteral::Property::SETTER: |
1491 if (property->emit_store()) { | 1491 if (property->emit_store()) { |
1492 accessor_table.lookup(key)->second->setter = property; | 1492 accessor_table.lookup(key)->second->setter = property; |
1493 } | 1493 } |
1494 break; | 1494 break; |
1495 } | 1495 } |
1496 } | 1496 } |
1497 | 1497 |
1498 // Emit code to define accessors, using only a single call to the runtime for | 1498 // Emit code to define accessors, using only a single call to the runtime for |
1499 // each pair of corresponding getters and setters. | 1499 // each pair of corresponding getters and setters. |
1500 for (AccessorTable::Iterator it = accessor_table.begin(); | 1500 for (AccessorTable::Iterator it = accessor_table.begin(); |
1501 it != accessor_table.end(); | 1501 it != accessor_table.end(); |
1502 ++it) { | 1502 ++it) { |
1503 __ push(Operand(esp, 0)); // Duplicate receiver. | 1503 __ push(Operand(esp, 0)); // Duplicate receiver. |
1504 VisitForStackValue(it->first); | 1504 VisitForStackValue(it->first); |
1505 | 1505 |
1506 EmitAccessor(it->second->getter); | 1506 EmitAccessor(it->second->getter); |
1507 EmitAccessor(it->second->setter); | 1507 EmitAccessor(it->second->setter); |
1508 | 1508 |
1509 __ push(Immediate(Smi::FromInt(NONE))); | 1509 __ push(Immediate(Smi::FromInt(NONE))); |
1510 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1510 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
1511 } | 1511 } |
1512 | 1512 |
1513 // Object literals have two parts. The "static" part on the left contains no | 1513 // Object literals have two parts. The "static" part on the left contains no |
1514 // computed property names, and so we can compute its map ahead of time; see | 1514 // computed property names, and so we can compute its map ahead of time; see |
1515 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1515 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
1516 // starts with the first computed property name, and continues with all | 1516 // starts with the first computed property name, and continues with all |
1517 // properties to its right. All the code from above initializes the static | 1517 // properties to its right. All the code from above initializes the static |
1518 // component of the object literal, and arranges for the map of the result to | 1518 // component of the object literal, and arranges for the map of the result to |
1519 // reflect the static order in which the keys appear. For the dynamic | 1519 // reflect the static order in which the keys appear. For the dynamic |
1520 // properties, we compile them into a series of "SetOwnProperty" runtime | 1520 // properties, we compile them into a series of "SetOwnProperty" runtime |
1521 // calls. This will preserve insertion order. | 1521 // calls. This will preserve insertion order. |
1522 for (; property_index < expr->properties()->length(); property_index++) { | 1522 for (; property_index < expr->properties()->length(); property_index++) { |
1523 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1523 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
1524 | 1524 |
1525 Expression* value = property->value(); | 1525 Expression* value = property->value(); |
1526 if (!result_saved) { | 1526 if (!result_saved) { |
1527 __ push(eax); // Save result on the stack | 1527 __ push(eax); // Save result on the stack |
1528 result_saved = true; | 1528 result_saved = true; |
1529 } | 1529 } |
1530 | 1530 |
1531 __ push(Operand(esp, 0)); // Duplicate receiver. | 1531 __ push(Operand(esp, 0)); // Duplicate receiver. |
1532 | 1532 |
1533 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1533 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
1534 DCHECK(!property->is_computed_name()); | 1534 DCHECK(!property->is_computed_name()); |
1535 VisitForStackValue(value); | 1535 VisitForStackValue(value); |
1536 DCHECK(property->emit_store()); | 1536 DCHECK(property->emit_store()); |
1537 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1537 __ CallRuntime(Runtime::kInternalSetPrototype); |
1538 } else { | 1538 } else { |
1539 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1539 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
1540 VisitForStackValue(value); | 1540 VisitForStackValue(value); |
1541 if (NeedsHomeObject(value)) { | 1541 if (NeedsHomeObject(value)) { |
1542 EmitSetHomeObject(value, 2, property->GetSlot()); | 1542 EmitSetHomeObject(value, 2, property->GetSlot()); |
1543 } | 1543 } |
1544 | 1544 |
1545 switch (property->kind()) { | 1545 switch (property->kind()) { |
1546 case ObjectLiteral::Property::CONSTANT: | 1546 case ObjectLiteral::Property::CONSTANT: |
1547 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1547 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1548 case ObjectLiteral::Property::COMPUTED: | 1548 case ObjectLiteral::Property::COMPUTED: |
1549 if (property->emit_store()) { | 1549 if (property->emit_store()) { |
1550 __ push(Immediate(Smi::FromInt(NONE))); | 1550 __ push(Immediate(Smi::FromInt(NONE))); |
1551 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1551 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
1552 } else { | 1552 } else { |
1553 __ Drop(3); | 1553 __ Drop(3); |
1554 } | 1554 } |
1555 break; | 1555 break; |
1556 | 1556 |
1557 case ObjectLiteral::Property::PROTOTYPE: | 1557 case ObjectLiteral::Property::PROTOTYPE: |
1558 UNREACHABLE(); | 1558 UNREACHABLE(); |
1559 break; | 1559 break; |
1560 | 1560 |
1561 case ObjectLiteral::Property::GETTER: | 1561 case ObjectLiteral::Property::GETTER: |
1562 __ push(Immediate(Smi::FromInt(NONE))); | 1562 __ push(Immediate(Smi::FromInt(NONE))); |
1563 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1563 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
1564 break; | 1564 break; |
1565 | 1565 |
1566 case ObjectLiteral::Property::SETTER: | 1566 case ObjectLiteral::Property::SETTER: |
1567 __ push(Immediate(Smi::FromInt(NONE))); | 1567 __ push(Immediate(Smi::FromInt(NONE))); |
1568 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1568 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
1569 break; | 1569 break; |
1570 } | 1570 } |
1571 } | 1571 } |
1572 } | 1572 } |
1573 | 1573 |
1574 if (expr->has_function()) { | 1574 if (expr->has_function()) { |
1575 DCHECK(result_saved); | 1575 DCHECK(result_saved); |
1576 __ push(Operand(esp, 0)); | 1576 __ push(Operand(esp, 0)); |
1577 __ CallRuntime(Runtime::kToFastProperties, 1); | 1577 __ CallRuntime(Runtime::kToFastProperties); |
1578 } | 1578 } |
1579 | 1579 |
1580 if (result_saved) { | 1580 if (result_saved) { |
1581 context()->PlugTOS(); | 1581 context()->PlugTOS(); |
1582 } else { | 1582 } else { |
1583 context()->Plug(eax); | 1583 context()->Plug(eax); |
1584 } | 1584 } |
1585 } | 1585 } |
1586 | 1586 |
1587 | 1587 |
1588 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1588 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1589 Comment cmnt(masm_, "[ ArrayLiteral"); | 1589 Comment cmnt(masm_, "[ ArrayLiteral"); |
1590 | 1590 |
1591 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1591 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1592 bool has_constant_fast_elements = | 1592 bool has_constant_fast_elements = |
1593 IsFastObjectElementsKind(expr->constant_elements_kind()); | 1593 IsFastObjectElementsKind(expr->constant_elements_kind()); |
1594 | 1594 |
1595 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1595 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1596 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1596 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
1597 // If the only customer of allocation sites is transitioning, then | 1597 // If the only customer of allocation sites is transitioning, then |
1598 // we can turn it off if we don't have anywhere else to transition to. | 1598 // we can turn it off if we don't have anywhere else to transition to. |
1599 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1599 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
1600 } | 1600 } |
1601 | 1601 |
1602 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1602 if (MustCreateArrayLiteralWithRuntime(expr)) { |
1603 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1603 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1604 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1604 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1605 __ push(Immediate(constant_elements)); | 1605 __ push(Immediate(constant_elements)); |
1606 __ push(Immediate(Smi::FromInt(expr->ComputeFlags()))); | 1606 __ push(Immediate(Smi::FromInt(expr->ComputeFlags()))); |
1607 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1607 __ CallRuntime(Runtime::kCreateArrayLiteral); |
1608 } else { | 1608 } else { |
1609 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1609 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1610 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1610 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
1611 __ mov(ecx, Immediate(constant_elements)); | 1611 __ mov(ecx, Immediate(constant_elements)); |
1612 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1612 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
1613 __ CallStub(&stub); | 1613 __ CallStub(&stub); |
1614 } | 1614 } |
1615 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1615 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1616 | 1616 |
1617 bool result_saved = false; // Is the result saved to the stack? | 1617 bool result_saved = false; // Is the result saved to the stack? |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1657 for (; array_index < length; array_index++) { | 1657 for (; array_index < length; array_index++) { |
1658 Expression* subexpr = subexprs->at(array_index); | 1658 Expression* subexpr = subexprs->at(array_index); |
1659 | 1659 |
1660 __ Push(eax); | 1660 __ Push(eax); |
1661 if (subexpr->IsSpread()) { | 1661 if (subexpr->IsSpread()) { |
1662 VisitForStackValue(subexpr->AsSpread()->expression()); | 1662 VisitForStackValue(subexpr->AsSpread()->expression()); |
1663 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1663 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
1664 CALL_FUNCTION); | 1664 CALL_FUNCTION); |
1665 } else { | 1665 } else { |
1666 VisitForStackValue(subexpr); | 1666 VisitForStackValue(subexpr); |
1667 __ CallRuntime(Runtime::kAppendElement, 2); | 1667 __ CallRuntime(Runtime::kAppendElement); |
1668 } | 1668 } |
1669 | 1669 |
1670 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1670 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
1671 } | 1671 } |
1672 | 1672 |
1673 if (result_saved) { | 1673 if (result_saved) { |
1674 context()->PlugTOS(); | 1674 context()->PlugTOS(); |
1675 } else { | 1675 } else { |
1676 context()->Plug(eax); | 1676 context()->Plug(eax); |
1677 } | 1677 } |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 Label push_operand_holes, call_resume; | 2055 Label push_operand_holes, call_resume; |
2056 __ bind(&push_operand_holes); | 2056 __ bind(&push_operand_holes); |
2057 __ sub(edx, Immediate(1)); | 2057 __ sub(edx, Immediate(1)); |
2058 __ j(carry, &call_resume); | 2058 __ j(carry, &call_resume); |
2059 __ push(ecx); | 2059 __ push(ecx); |
2060 __ jmp(&push_operand_holes); | 2060 __ jmp(&push_operand_holes); |
2061 __ bind(&call_resume); | 2061 __ bind(&call_resume); |
2062 __ push(ebx); | 2062 __ push(ebx); |
2063 __ push(result_register()); | 2063 __ push(result_register()); |
2064 __ Push(Smi::FromInt(resume_mode)); | 2064 __ Push(Smi::FromInt(resume_mode)); |
2065 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2065 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
2066 // Not reached: the runtime call returns elsewhere. | 2066 // Not reached: the runtime call returns elsewhere. |
2067 __ Abort(kGeneratorFailedToResume); | 2067 __ Abort(kGeneratorFailedToResume); |
2068 | 2068 |
2069 __ bind(&done); | 2069 __ bind(&done); |
2070 context()->Plug(result_register()); | 2070 context()->Plug(result_register()); |
2071 } | 2071 } |
2072 | 2072 |
2073 | 2073 |
2074 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2074 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2075 Label allocate, done_allocate; | 2075 Label allocate, done_allocate; |
2076 | 2076 |
2077 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); | 2077 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); |
2078 __ jmp(&done_allocate, Label::kNear); | 2078 __ jmp(&done_allocate, Label::kNear); |
2079 | 2079 |
2080 __ bind(&allocate); | 2080 __ bind(&allocate); |
2081 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2081 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
2082 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2082 __ CallRuntime(Runtime::kAllocateInNewSpace); |
2083 | 2083 |
2084 __ bind(&done_allocate); | 2084 __ bind(&done_allocate); |
2085 __ mov(ebx, NativeContextOperand()); | 2085 __ mov(ebx, NativeContextOperand()); |
2086 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 2086 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
2087 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2087 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
2088 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2088 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
2089 isolate()->factory()->empty_fixed_array()); | 2089 isolate()->factory()->empty_fixed_array()); |
2090 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2090 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
2091 isolate()->factory()->empty_fixed_array()); | 2091 isolate()->factory()->empty_fixed_array()); |
2092 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 2092 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
(...skipping 18 matching lines...) Expand all Loading... |
2111 | 2111 |
2112 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2112 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
2113 // Stack: receiver, home_object. | 2113 // Stack: receiver, home_object. |
2114 SetExpressionPosition(prop); | 2114 SetExpressionPosition(prop); |
2115 Literal* key = prop->key()->AsLiteral(); | 2115 Literal* key = prop->key()->AsLiteral(); |
2116 DCHECK(!key->value()->IsSmi()); | 2116 DCHECK(!key->value()->IsSmi()); |
2117 DCHECK(prop->IsSuperAccess()); | 2117 DCHECK(prop->IsSuperAccess()); |
2118 | 2118 |
2119 __ push(Immediate(key->value())); | 2119 __ push(Immediate(key->value())); |
2120 __ push(Immediate(Smi::FromInt(language_mode()))); | 2120 __ push(Immediate(Smi::FromInt(language_mode()))); |
2121 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2121 __ CallRuntime(Runtime::kLoadFromSuper); |
2122 } | 2122 } |
2123 | 2123 |
2124 | 2124 |
2125 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2125 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
2126 SetExpressionPosition(prop); | 2126 SetExpressionPosition(prop); |
2127 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2127 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
2128 __ mov(LoadDescriptor::SlotRegister(), | 2128 __ mov(LoadDescriptor::SlotRegister(), |
2129 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2129 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
2130 CallIC(ic); | 2130 CallIC(ic); |
2131 } | 2131 } |
2132 | 2132 |
2133 | 2133 |
2134 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2134 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
2135 // Stack: receiver, home_object, key. | 2135 // Stack: receiver, home_object, key. |
2136 SetExpressionPosition(prop); | 2136 SetExpressionPosition(prop); |
2137 __ push(Immediate(Smi::FromInt(language_mode()))); | 2137 __ push(Immediate(Smi::FromInt(language_mode()))); |
2138 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2138 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2139 } | 2139 } |
2140 | 2140 |
2141 | 2141 |
2142 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2142 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
2143 Token::Value op, | 2143 Token::Value op, |
2144 Expression* left, | 2144 Expression* left, |
2145 Expression* right) { | 2145 Expression* right) { |
2146 // Do combined smi check of the operands. Left operand is on the | 2146 // Do combined smi check of the operands. Left operand is on the |
2147 // stack. Right operand is in eax. | 2147 // stack. Right operand is in eax. |
2148 Label smi_case, done, stub_call; | 2148 Label smi_case, done, stub_call; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2254 } else { | 2254 } else { |
2255 __ push(Operand(esp, 0)); // prototype | 2255 __ push(Operand(esp, 0)); // prototype |
2256 } | 2256 } |
2257 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2257 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
2258 | 2258 |
2259 // The static prototype property is read only. We handle the non computed | 2259 // The static prototype property is read only. We handle the non computed |
2260 // property name case in the parser. Since this is the only case where we | 2260 // property name case in the parser. Since this is the only case where we |
2261 // need to check for an own read only property we special case this so we do | 2261 // need to check for an own read only property we special case this so we do |
2262 // not need to do this for every property. | 2262 // not need to do this for every property. |
2263 if (property->is_static() && property->is_computed_name()) { | 2263 if (property->is_static() && property->is_computed_name()) { |
2264 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2264 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
2265 __ push(eax); | 2265 __ push(eax); |
2266 } | 2266 } |
2267 | 2267 |
2268 VisitForStackValue(value); | 2268 VisitForStackValue(value); |
2269 if (NeedsHomeObject(value)) { | 2269 if (NeedsHomeObject(value)) { |
2270 EmitSetHomeObject(value, 2, property->GetSlot()); | 2270 EmitSetHomeObject(value, 2, property->GetSlot()); |
2271 } | 2271 } |
2272 | 2272 |
2273 switch (property->kind()) { | 2273 switch (property->kind()) { |
2274 case ObjectLiteral::Property::CONSTANT: | 2274 case ObjectLiteral::Property::CONSTANT: |
2275 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2275 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2276 case ObjectLiteral::Property::PROTOTYPE: | 2276 case ObjectLiteral::Property::PROTOTYPE: |
2277 UNREACHABLE(); | 2277 UNREACHABLE(); |
2278 case ObjectLiteral::Property::COMPUTED: | 2278 case ObjectLiteral::Property::COMPUTED: |
2279 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2279 __ CallRuntime(Runtime::kDefineClassMethod); |
2280 break; | 2280 break; |
2281 | 2281 |
2282 case ObjectLiteral::Property::GETTER: | 2282 case ObjectLiteral::Property::GETTER: |
2283 __ push(Immediate(Smi::FromInt(DONT_ENUM))); | 2283 __ push(Immediate(Smi::FromInt(DONT_ENUM))); |
2284 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2284 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
2285 break; | 2285 break; |
2286 | 2286 |
2287 case ObjectLiteral::Property::SETTER: | 2287 case ObjectLiteral::Property::SETTER: |
2288 __ push(Immediate(Smi::FromInt(DONT_ENUM))); | 2288 __ push(Immediate(Smi::FromInt(DONT_ENUM))); |
2289 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2289 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
2290 break; | 2290 break; |
2291 } | 2291 } |
2292 } | 2292 } |
2293 | 2293 |
2294 // Set both the prototype and constructor to have fast properties, and also | 2294 // Set both the prototype and constructor to have fast properties, and also |
2295 // freeze them in strong mode. | 2295 // freeze them in strong mode. |
2296 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2296 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
2297 } | 2297 } |
2298 | 2298 |
2299 | 2299 |
2300 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2300 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
2301 __ pop(edx); | 2301 __ pop(edx); |
2302 Handle<Code> code = | 2302 Handle<Code> code = |
2303 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2303 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
2304 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2304 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2305 CallIC(code, expr->BinaryOperationFeedbackId()); | 2305 CallIC(code, expr->BinaryOperationFeedbackId()); |
2306 patch_site.EmitPatchInfo(); | 2306 patch_site.EmitPatchInfo(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2414 } else if (var->mode() == LET && op != Token::INIT) { | 2414 } else if (var->mode() == LET && op != Token::INIT) { |
2415 // Non-initializing assignment to let variable needs a write barrier. | 2415 // Non-initializing assignment to let variable needs a write barrier. |
2416 DCHECK(!var->IsLookupSlot()); | 2416 DCHECK(!var->IsLookupSlot()); |
2417 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2417 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2418 Label assign; | 2418 Label assign; |
2419 MemOperand location = VarOperand(var, ecx); | 2419 MemOperand location = VarOperand(var, ecx); |
2420 __ mov(edx, location); | 2420 __ mov(edx, location); |
2421 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2421 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2422 __ j(not_equal, &assign, Label::kNear); | 2422 __ j(not_equal, &assign, Label::kNear); |
2423 __ push(Immediate(var->name())); | 2423 __ push(Immediate(var->name())); |
2424 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2424 __ CallRuntime(Runtime::kThrowReferenceError); |
2425 __ bind(&assign); | 2425 __ bind(&assign); |
2426 EmitStoreToStackLocalOrContextSlot(var, location); | 2426 EmitStoreToStackLocalOrContextSlot(var, location); |
2427 | 2427 |
2428 } else if (var->mode() == CONST && op != Token::INIT) { | 2428 } else if (var->mode() == CONST && op != Token::INIT) { |
2429 // Assignment to const variable needs a write barrier. | 2429 // Assignment to const variable needs a write barrier. |
2430 DCHECK(!var->IsLookupSlot()); | 2430 DCHECK(!var->IsLookupSlot()); |
2431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2431 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2432 Label const_error; | 2432 Label const_error; |
2433 MemOperand location = VarOperand(var, ecx); | 2433 MemOperand location = VarOperand(var, ecx); |
2434 __ mov(edx, location); | 2434 __ mov(edx, location); |
2435 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2435 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2436 __ j(not_equal, &const_error, Label::kNear); | 2436 __ j(not_equal, &const_error, Label::kNear); |
2437 __ push(Immediate(var->name())); | 2437 __ push(Immediate(var->name())); |
2438 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2438 __ CallRuntime(Runtime::kThrowReferenceError); |
2439 __ bind(&const_error); | 2439 __ bind(&const_error); |
2440 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2440 __ CallRuntime(Runtime::kThrowConstAssignError); |
2441 | 2441 |
2442 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2442 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
2443 // Initializing assignment to const {this} needs a write barrier. | 2443 // Initializing assignment to const {this} needs a write barrier. |
2444 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2444 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2445 Label uninitialized_this; | 2445 Label uninitialized_this; |
2446 MemOperand location = VarOperand(var, ecx); | 2446 MemOperand location = VarOperand(var, ecx); |
2447 __ mov(edx, location); | 2447 __ mov(edx, location); |
2448 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2448 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2449 __ j(equal, &uninitialized_this); | 2449 __ j(equal, &uninitialized_this); |
2450 __ push(Immediate(var->name())); | 2450 __ push(Immediate(var->name())); |
2451 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2451 __ CallRuntime(Runtime::kThrowReferenceError); |
2452 __ bind(&uninitialized_this); | 2452 __ bind(&uninitialized_this); |
2453 EmitStoreToStackLocalOrContextSlot(var, location); | 2453 EmitStoreToStackLocalOrContextSlot(var, location); |
2454 | 2454 |
2455 } else if (!var->is_const_mode() || | 2455 } else if (!var->is_const_mode() || |
2456 (var->mode() == CONST && op == Token::INIT)) { | 2456 (var->mode() == CONST && op == Token::INIT)) { |
2457 if (var->IsLookupSlot()) { | 2457 if (var->IsLookupSlot()) { |
2458 // Assignment to var. | 2458 // Assignment to var. |
2459 __ push(eax); // Value. | 2459 __ push(eax); // Value. |
2460 __ push(esi); // Context. | 2460 __ push(esi); // Context. |
2461 __ push(Immediate(var->name())); | 2461 __ push(Immediate(var->name())); |
2462 __ push(Immediate(Smi::FromInt(language_mode()))); | 2462 __ push(Immediate(Smi::FromInt(language_mode()))); |
2463 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2463 __ CallRuntime(Runtime::kStoreLookupSlot); |
2464 } else { | 2464 } else { |
2465 // Assignment to var or initializing assignment to let/const in harmony | 2465 // Assignment to var or initializing assignment to let/const in harmony |
2466 // mode. | 2466 // mode. |
2467 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2467 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2468 MemOperand location = VarOperand(var, ecx); | 2468 MemOperand location = VarOperand(var, ecx); |
2469 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2469 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
2470 // Check for an uninitialized let binding. | 2470 // Check for an uninitialized let binding. |
2471 __ mov(edx, location); | 2471 __ mov(edx, location); |
2472 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2472 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2473 __ Check(equal, kLetBindingReInitialization); | 2473 __ Check(equal, kLetBindingReInitialization); |
2474 } | 2474 } |
2475 EmitStoreToStackLocalOrContextSlot(var, location); | 2475 EmitStoreToStackLocalOrContextSlot(var, location); |
2476 } | 2476 } |
2477 | 2477 |
2478 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2478 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
2479 // Const initializers need a write barrier. | 2479 // Const initializers need a write barrier. |
2480 DCHECK(!var->IsParameter()); // No const parameters. | 2480 DCHECK(!var->IsParameter()); // No const parameters. |
2481 if (var->IsLookupSlot()) { | 2481 if (var->IsLookupSlot()) { |
2482 __ push(eax); | 2482 __ push(eax); |
2483 __ push(esi); | 2483 __ push(esi); |
2484 __ push(Immediate(var->name())); | 2484 __ push(Immediate(var->name())); |
2485 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2485 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
2486 } else { | 2486 } else { |
2487 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | 2487 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2488 Label skip; | 2488 Label skip; |
2489 MemOperand location = VarOperand(var, ecx); | 2489 MemOperand location = VarOperand(var, ecx); |
2490 __ mov(edx, location); | 2490 __ mov(edx, location); |
2491 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2491 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2492 __ j(not_equal, &skip, Label::kNear); | 2492 __ j(not_equal, &skip, Label::kNear); |
2493 EmitStoreToStackLocalOrContextSlot(var, location); | 2493 EmitStoreToStackLocalOrContextSlot(var, location); |
2494 __ bind(&skip); | 2494 __ bind(&skip); |
2495 } | 2495 } |
2496 | 2496 |
2497 } else { | 2497 } else { |
2498 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2498 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2499 if (is_strict(language_mode())) { | 2499 if (is_strict(language_mode())) { |
2500 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2500 __ CallRuntime(Runtime::kThrowConstAssignError); |
2501 } | 2501 } |
2502 // Silently ignore store in sloppy mode. | 2502 // Silently ignore store in sloppy mode. |
2503 } | 2503 } |
2504 } | 2504 } |
2505 | 2505 |
2506 | 2506 |
2507 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2507 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2508 // Assignment to a property, using a named store IC. | 2508 // Assignment to a property, using a named store IC. |
2509 // eax : value | 2509 // eax : value |
2510 // esp[0] : receiver | 2510 // esp[0] : receiver |
(...skipping 14 matching lines...) Expand all Loading... |
2525 // Assignment to named property of super. | 2525 // Assignment to named property of super. |
2526 // eax : value | 2526 // eax : value |
2527 // stack : receiver ('this'), home_object | 2527 // stack : receiver ('this'), home_object |
2528 DCHECK(prop != NULL); | 2528 DCHECK(prop != NULL); |
2529 Literal* key = prop->key()->AsLiteral(); | 2529 Literal* key = prop->key()->AsLiteral(); |
2530 DCHECK(key != NULL); | 2530 DCHECK(key != NULL); |
2531 | 2531 |
2532 __ push(Immediate(key->value())); | 2532 __ push(Immediate(key->value())); |
2533 __ push(eax); | 2533 __ push(eax); |
2534 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2534 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
2535 : Runtime::kStoreToSuper_Sloppy), | 2535 : Runtime::kStoreToSuper_Sloppy)); |
2536 4); | |
2537 } | 2536 } |
2538 | 2537 |
2539 | 2538 |
2540 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2539 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
2541 // Assignment to named property of super. | 2540 // Assignment to named property of super. |
2542 // eax : value | 2541 // eax : value |
2543 // stack : receiver ('this'), home_object, key | 2542 // stack : receiver ('this'), home_object, key |
2544 | 2543 |
2545 __ push(eax); | 2544 __ push(eax); |
2546 __ CallRuntime( | 2545 __ CallRuntime((is_strict(language_mode()) |
2547 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2546 ? Runtime::kStoreKeyedToSuper_Strict |
2548 : Runtime::kStoreKeyedToSuper_Sloppy), | 2547 : Runtime::kStoreKeyedToSuper_Sloppy)); |
2549 4); | |
2550 } | 2548 } |
2551 | 2549 |
2552 | 2550 |
2553 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2551 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2554 // Assignment to a property, using a keyed store IC. | 2552 // Assignment to a property, using a keyed store IC. |
2555 // eax : value | 2553 // eax : value |
2556 // esp[0] : key | 2554 // esp[0] : key |
2557 // esp[kPointerSize] : receiver | 2555 // esp[kPointerSize] : receiver |
2558 | 2556 |
2559 __ pop(StoreDescriptor::NameRegister()); // Key. | 2557 __ pop(StoreDescriptor::NameRegister()); // Key. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2662 __ push(Operand(esp, kPointerSize * 2)); | 2660 __ push(Operand(esp, kPointerSize * 2)); |
2663 __ push(Immediate(key->value())); | 2661 __ push(Immediate(key->value())); |
2664 __ push(Immediate(Smi::FromInt(language_mode()))); | 2662 __ push(Immediate(Smi::FromInt(language_mode()))); |
2665 // Stack here: | 2663 // Stack here: |
2666 // - home_object | 2664 // - home_object |
2667 // - this (receiver) | 2665 // - this (receiver) |
2668 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2666 // - this (receiver) <-- LoadFromSuper will pop here and below. |
2669 // - home_object | 2667 // - home_object |
2670 // - key | 2668 // - key |
2671 // - language_mode | 2669 // - language_mode |
2672 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2670 __ CallRuntime(Runtime::kLoadFromSuper); |
2673 | 2671 |
2674 // Replace home_object with target function. | 2672 // Replace home_object with target function. |
2675 __ mov(Operand(esp, kPointerSize), eax); | 2673 __ mov(Operand(esp, kPointerSize), eax); |
2676 | 2674 |
2677 // Stack here: | 2675 // Stack here: |
2678 // - target function | 2676 // - target function |
2679 // - this (receiver) | 2677 // - this (receiver) |
2680 EmitCall(expr); | 2678 EmitCall(expr); |
2681 } | 2679 } |
2682 | 2680 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2720 __ push(Operand(esp, kPointerSize * 2)); | 2718 __ push(Operand(esp, kPointerSize * 2)); |
2721 VisitForStackValue(prop->key()); | 2719 VisitForStackValue(prop->key()); |
2722 __ push(Immediate(Smi::FromInt(language_mode()))); | 2720 __ push(Immediate(Smi::FromInt(language_mode()))); |
2723 // Stack here: | 2721 // Stack here: |
2724 // - home_object | 2722 // - home_object |
2725 // - this (receiver) | 2723 // - this (receiver) |
2726 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2724 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
2727 // - home_object | 2725 // - home_object |
2728 // - key | 2726 // - key |
2729 // - language_mode | 2727 // - language_mode |
2730 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2728 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2731 | 2729 |
2732 // Replace home_object with target function. | 2730 // Replace home_object with target function. |
2733 __ mov(Operand(esp, kPointerSize), eax); | 2731 __ mov(Operand(esp, kPointerSize), eax); |
2734 | 2732 |
2735 // Stack here: | 2733 // Stack here: |
2736 // - target function | 2734 // - target function |
2737 // - this (receiver) | 2735 // - this (receiver) |
2738 EmitCall(expr); | 2736 EmitCall(expr); |
2739 } | 2737 } |
2740 | 2738 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2776 // Push the enclosing function. | 2774 // Push the enclosing function. |
2777 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 2775 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
2778 | 2776 |
2779 // Push the language mode. | 2777 // Push the language mode. |
2780 __ push(Immediate(Smi::FromInt(language_mode()))); | 2778 __ push(Immediate(Smi::FromInt(language_mode()))); |
2781 | 2779 |
2782 // Push the start position of the scope the calls resides in. | 2780 // Push the start position of the scope the calls resides in. |
2783 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 2781 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
2784 | 2782 |
2785 // Do the runtime call. | 2783 // Do the runtime call. |
2786 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2784 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
2787 } | 2785 } |
2788 | 2786 |
2789 | 2787 |
2790 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2788 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
2791 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2789 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
2792 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2790 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
2793 if (callee->var()->IsLookupSlot()) { | 2791 if (callee->var()->IsLookupSlot()) { |
2794 Label slow, done; | 2792 Label slow, done; |
2795 SetExpressionPosition(callee); | 2793 SetExpressionPosition(callee); |
2796 // Generate code for loading from variables potentially shadowed by | 2794 // Generate code for loading from variables potentially shadowed by |
2797 // eval-introduced variables. | 2795 // eval-introduced variables. |
2798 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2796 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
2799 | 2797 |
2800 __ bind(&slow); | 2798 __ bind(&slow); |
2801 // Call the runtime to find the function to call (returned in eax) and | 2799 // Call the runtime to find the function to call (returned in eax) and |
2802 // the object holding it (returned in edx). | 2800 // the object holding it (returned in edx). |
2803 __ push(context_register()); | 2801 __ push(context_register()); |
2804 __ push(Immediate(callee->name())); | 2802 __ push(Immediate(callee->name())); |
2805 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2803 __ CallRuntime(Runtime::kLoadLookupSlot); |
2806 __ push(eax); // Function. | 2804 __ push(eax); // Function. |
2807 __ push(edx); // Receiver. | 2805 __ push(edx); // Receiver. |
2808 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2806 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
2809 | 2807 |
2810 // If fast case code has been generated, emit code to push the function | 2808 // If fast case code has been generated, emit code to push the function |
2811 // and receiver and have the slow path jump around this code. | 2809 // and receiver and have the slow path jump around this code. |
2812 if (done.is_linked()) { | 2810 if (done.is_linked()) { |
2813 Label call; | 2811 Label call; |
2814 __ jmp(&call, Label::kNear); | 2812 __ jmp(&call, Label::kNear); |
2815 __ bind(&done); | 2813 __ bind(&done); |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3438 ZoneList<Expression*>* args = expr->arguments(); | 3436 ZoneList<Expression*>* args = expr->arguments(); |
3439 DCHECK_EQ(1, args->length()); | 3437 DCHECK_EQ(1, args->length()); |
3440 | 3438 |
3441 // Load the argument into eax and convert it. | 3439 // Load the argument into eax and convert it. |
3442 VisitForAccumulatorValue(args->at(0)); | 3440 VisitForAccumulatorValue(args->at(0)); |
3443 | 3441 |
3444 // Convert the object to an integer. | 3442 // Convert the object to an integer. |
3445 Label done_convert; | 3443 Label done_convert; |
3446 __ JumpIfSmi(eax, &done_convert, Label::kNear); | 3444 __ JumpIfSmi(eax, &done_convert, Label::kNear); |
3447 __ Push(eax); | 3445 __ Push(eax); |
3448 __ CallRuntime(Runtime::kToInteger, 1); | 3446 __ CallRuntime(Runtime::kToInteger); |
3449 __ bind(&done_convert); | 3447 __ bind(&done_convert); |
3450 context()->Plug(eax); | 3448 context()->Plug(eax); |
3451 } | 3449 } |
3452 | 3450 |
3453 | 3451 |
3454 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3452 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
3455 ZoneList<Expression*>* args = expr->arguments(); | 3453 ZoneList<Expression*>* args = expr->arguments(); |
3456 DCHECK_EQ(1, args->length()); | 3454 DCHECK_EQ(1, args->length()); |
3457 | 3455 |
3458 // Load the argument into eax and convert it. | 3456 // Load the argument into eax and convert it. |
3459 VisitForAccumulatorValue(args->at(0)); | 3457 VisitForAccumulatorValue(args->at(0)); |
3460 | 3458 |
3461 // Convert the object to a name. | 3459 // Convert the object to a name. |
3462 Label convert, done_convert; | 3460 Label convert, done_convert; |
3463 __ JumpIfSmi(eax, &convert, Label::kNear); | 3461 __ JumpIfSmi(eax, &convert, Label::kNear); |
3464 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3462 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
3465 __ CmpObjectType(eax, LAST_NAME_TYPE, ecx); | 3463 __ CmpObjectType(eax, LAST_NAME_TYPE, ecx); |
3466 __ j(below_equal, &done_convert, Label::kNear); | 3464 __ j(below_equal, &done_convert, Label::kNear); |
3467 __ bind(&convert); | 3465 __ bind(&convert); |
3468 __ Push(eax); | 3466 __ Push(eax); |
3469 __ CallRuntime(Runtime::kToName, 1); | 3467 __ CallRuntime(Runtime::kToName); |
3470 __ bind(&done_convert); | 3468 __ bind(&done_convert); |
3471 context()->Plug(eax); | 3469 context()->Plug(eax); |
3472 } | 3470 } |
3473 | 3471 |
3474 | 3472 |
3475 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3473 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3476 ZoneList<Expression*>* args = expr->arguments(); | 3474 ZoneList<Expression*>* args = expr->arguments(); |
3477 DCHECK(args->length() == 1); | 3475 DCHECK(args->length() == 1); |
3478 | 3476 |
3479 VisitForAccumulatorValue(args->at(0)); | 3477 VisitForAccumulatorValue(args->at(0)); |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3949 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 3947 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
3950 isolate()->factory()->empty_fixed_array()); | 3948 isolate()->factory()->empty_fixed_array()); |
3951 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 3949 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
3952 isolate()->factory()->empty_fixed_array()); | 3950 isolate()->factory()->empty_fixed_array()); |
3953 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); | 3951 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); |
3954 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 3952 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
3955 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 3953 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
3956 __ jmp(&done, Label::kNear); | 3954 __ jmp(&done, Label::kNear); |
3957 | 3955 |
3958 __ bind(&runtime); | 3956 __ bind(&runtime); |
3959 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 3957 __ CallRuntime(Runtime::kCreateIterResultObject); |
3960 | 3958 |
3961 __ bind(&done); | 3959 __ bind(&done); |
3962 context()->Plug(eax); | 3960 context()->Plug(eax); |
3963 } | 3961 } |
3964 | 3962 |
3965 | 3963 |
3966 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 3964 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
3967 // Push undefined as receiver. | 3965 // Push undefined as receiver. |
3968 __ push(Immediate(isolate()->factory()->undefined_value())); | 3966 __ push(Immediate(isolate()->factory()->undefined_value())); |
3969 | 3967 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4039 case Token::DELETE: { | 4037 case Token::DELETE: { |
4040 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4038 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4041 Property* property = expr->expression()->AsProperty(); | 4039 Property* property = expr->expression()->AsProperty(); |
4042 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4040 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4043 | 4041 |
4044 if (property != NULL) { | 4042 if (property != NULL) { |
4045 VisitForStackValue(property->obj()); | 4043 VisitForStackValue(property->obj()); |
4046 VisitForStackValue(property->key()); | 4044 VisitForStackValue(property->key()); |
4047 __ CallRuntime(is_strict(language_mode()) | 4045 __ CallRuntime(is_strict(language_mode()) |
4048 ? Runtime::kDeleteProperty_Strict | 4046 ? Runtime::kDeleteProperty_Strict |
4049 : Runtime::kDeleteProperty_Sloppy, | 4047 : Runtime::kDeleteProperty_Sloppy); |
4050 2); | |
4051 context()->Plug(eax); | 4048 context()->Plug(eax); |
4052 } else if (proxy != NULL) { | 4049 } else if (proxy != NULL) { |
4053 Variable* var = proxy->var(); | 4050 Variable* var = proxy->var(); |
4054 // Delete of an unqualified identifier is disallowed in strict mode but | 4051 // Delete of an unqualified identifier is disallowed in strict mode but |
4055 // "delete this" is allowed. | 4052 // "delete this" is allowed. |
4056 bool is_this = var->HasThisName(isolate()); | 4053 bool is_this = var->HasThisName(isolate()); |
4057 DCHECK(is_sloppy(language_mode()) || is_this); | 4054 DCHECK(is_sloppy(language_mode()) || is_this); |
4058 if (var->IsUnallocatedOrGlobalSlot()) { | 4055 if (var->IsUnallocatedOrGlobalSlot()) { |
4059 __ mov(eax, NativeContextOperand()); | 4056 __ mov(eax, NativeContextOperand()); |
4060 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); | 4057 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
4061 __ push(Immediate(var->name())); | 4058 __ push(Immediate(var->name())); |
4062 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4059 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
4063 context()->Plug(eax); | 4060 context()->Plug(eax); |
4064 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4061 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4065 // Result of deleting non-global variables is false. 'this' is | 4062 // Result of deleting non-global variables is false. 'this' is |
4066 // not really a variable, though we implement it as one. The | 4063 // not really a variable, though we implement it as one. The |
4067 // subexpression does not have side effects. | 4064 // subexpression does not have side effects. |
4068 context()->Plug(is_this); | 4065 context()->Plug(is_this); |
4069 } else { | 4066 } else { |
4070 // Non-global variable. Call the runtime to try to delete from the | 4067 // Non-global variable. Call the runtime to try to delete from the |
4071 // context where the variable was introduced. | 4068 // context where the variable was introduced. |
4072 __ push(context_register()); | 4069 __ push(context_register()); |
4073 __ push(Immediate(var->name())); | 4070 __ push(Immediate(var->name())); |
4074 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4071 __ CallRuntime(Runtime::kDeleteLookupSlot); |
4075 context()->Plug(eax); | 4072 context()->Plug(eax); |
4076 } | 4073 } |
4077 } else { | 4074 } else { |
4078 // Result of deleting non-property, non-variable reference is true. | 4075 // Result of deleting non-property, non-variable reference is true. |
4079 // The subexpression may have side effects. | 4076 // The subexpression may have side effects. |
4080 VisitForEffect(expr->expression()); | 4077 VisitForEffect(expr->expression()); |
4081 context()->Plug(true); | 4078 context()->Plug(true); |
4082 } | 4079 } |
4083 break; | 4080 break; |
4084 } | 4081 } |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4501 Label* if_false = NULL; | 4498 Label* if_false = NULL; |
4502 Label* fall_through = NULL; | 4499 Label* fall_through = NULL; |
4503 context()->PrepareTest(&materialize_true, &materialize_false, | 4500 context()->PrepareTest(&materialize_true, &materialize_false, |
4504 &if_true, &if_false, &fall_through); | 4501 &if_true, &if_false, &fall_through); |
4505 | 4502 |
4506 Token::Value op = expr->op(); | 4503 Token::Value op = expr->op(); |
4507 VisitForStackValue(expr->left()); | 4504 VisitForStackValue(expr->left()); |
4508 switch (op) { | 4505 switch (op) { |
4509 case Token::IN: | 4506 case Token::IN: |
4510 VisitForStackValue(expr->right()); | 4507 VisitForStackValue(expr->right()); |
4511 __ CallRuntime(Runtime::kHasProperty, 2); | 4508 __ CallRuntime(Runtime::kHasProperty); |
4512 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4509 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
4513 __ cmp(eax, isolate()->factory()->true_value()); | 4510 __ cmp(eax, isolate()->factory()->true_value()); |
4514 Split(equal, if_true, if_false, fall_through); | 4511 Split(equal, if_true, if_false, fall_through); |
4515 break; | 4512 break; |
4516 | 4513 |
4517 case Token::INSTANCEOF: { | 4514 case Token::INSTANCEOF: { |
4518 VisitForAccumulatorValue(expr->right()); | 4515 VisitForAccumulatorValue(expr->right()); |
4519 __ Pop(edx); | 4516 __ Pop(edx); |
4520 InstanceOfStub stub(isolate()); | 4517 InstanceOfStub stub(isolate()); |
4521 __ CallStub(&stub); | 4518 __ CallStub(&stub); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4774 Assembler::target_address_at(call_target_address, | 4771 Assembler::target_address_at(call_target_address, |
4775 unoptimized_code)); | 4772 unoptimized_code)); |
4776 return OSR_AFTER_STACK_CHECK; | 4773 return OSR_AFTER_STACK_CHECK; |
4777 } | 4774 } |
4778 | 4775 |
4779 | 4776 |
4780 } // namespace internal | 4777 } // namespace internal |
4781 } // namespace v8 | 4778 } // namespace v8 |
4782 | 4779 |
4783 #endif // V8_TARGET_ARCH_X87 | 4780 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |