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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); | 298 bool is_unmapped = is_strict(language_mode()) || !has_simple_parameters(); |
299 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( | 299 ArgumentsAccessStub::Type type = ArgumentsAccessStub::ComputeType( |
300 is_unmapped, literal()->has_duplicate_parameters()); | 300 is_unmapped, literal()->has_duplicate_parameters()); |
301 ArgumentsAccessStub stub(isolate(), type); | 301 ArgumentsAccessStub stub(isolate(), type); |
302 __ CallStub(&stub); | 302 __ CallStub(&stub); |
303 | 303 |
304 SetVar(arguments, eax, ebx, edx); | 304 SetVar(arguments, eax, ebx, edx); |
305 } | 305 } |
306 | 306 |
307 if (FLAG_trace) { | 307 if (FLAG_trace) { |
308 __ CallRuntime(Runtime::kTraceEnter, 0); | 308 __ CallRuntime(Runtime::kTraceEnter); |
309 } | 309 } |
310 | 310 |
311 // Visit the declarations and body unless there is an illegal | 311 // Visit the declarations and body unless there is an illegal |
312 // redeclaration. | 312 // redeclaration. |
313 if (scope()->HasIllegalRedeclaration()) { | 313 if (scope()->HasIllegalRedeclaration()) { |
314 Comment cmnt(masm_, "[ Declarations"); | 314 Comment cmnt(masm_, "[ Declarations"); |
315 VisitForEffect(scope()->GetIllegalRedeclaration()); | 315 VisitForEffect(scope()->GetIllegalRedeclaration()); |
316 | 316 |
317 } else { | 317 } else { |
318 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 318 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 | 403 |
404 void FullCodeGenerator::EmitReturnSequence() { | 404 void FullCodeGenerator::EmitReturnSequence() { |
405 Comment cmnt(masm_, "[ Return sequence"); | 405 Comment cmnt(masm_, "[ Return sequence"); |
406 if (return_label_.is_bound()) { | 406 if (return_label_.is_bound()) { |
407 __ jmp(&return_label_); | 407 __ jmp(&return_label_); |
408 } else { | 408 } else { |
409 // Common return label | 409 // Common return label |
410 __ bind(&return_label_); | 410 __ bind(&return_label_); |
411 if (FLAG_trace) { | 411 if (FLAG_trace) { |
412 __ push(eax); | 412 __ push(eax); |
413 __ CallRuntime(Runtime::kTraceExit, 1); | 413 __ CallRuntime(Runtime::kTraceExit); |
414 } | 414 } |
415 // Pretend that the exit is a backwards jump to the entry. | 415 // Pretend that the exit is a backwards jump to the entry. |
416 int weight = 1; | 416 int weight = 1; |
417 if (info_->ShouldSelfOptimize()) { | 417 if (info_->ShouldSelfOptimize()) { |
418 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | 418 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
419 } else { | 419 } else { |
420 int distance = masm_->pc_offset(); | 420 int distance = masm_->pc_offset(); |
421 weight = Min(kMaxBackEdgeWeight, | 421 weight = Min(kMaxBackEdgeWeight, |
422 Max(1, distance / kCodeSizeMultiplier)); | 422 Max(1, distance / kCodeSizeMultiplier)); |
423 } | 423 } |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 // Note: For variables we must not push an initial value (such as | 788 // Note: For variables we must not push an initial value (such as |
789 // 'undefined') because we may have a (legal) redeclaration and we | 789 // 'undefined') because we may have a (legal) redeclaration and we |
790 // must not destroy the current value. | 790 // must not destroy the current value. |
791 if (hole_init) { | 791 if (hole_init) { |
792 __ push(Immediate(isolate()->factory()->the_hole_value())); | 792 __ push(Immediate(isolate()->factory()->the_hole_value())); |
793 } else { | 793 } else { |
794 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. | 794 __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value. |
795 } | 795 } |
796 __ push( | 796 __ push( |
797 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); | 797 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); |
798 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 798 __ CallRuntime(Runtime::kDeclareLookupSlot); |
799 break; | 799 break; |
800 } | 800 } |
801 } | 801 } |
802 } | 802 } |
803 | 803 |
804 | 804 |
805 void FullCodeGenerator::VisitFunctionDeclaration( | 805 void FullCodeGenerator::VisitFunctionDeclaration( |
806 FunctionDeclaration* declaration) { | 806 FunctionDeclaration* declaration) { |
807 VariableProxy* proxy = declaration->proxy(); | 807 VariableProxy* proxy = declaration->proxy(); |
808 Variable* variable = proxy->var(); | 808 Variable* variable = proxy->var(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); | 842 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); |
843 break; | 843 break; |
844 } | 844 } |
845 | 845 |
846 case VariableLocation::LOOKUP: { | 846 case VariableLocation::LOOKUP: { |
847 Comment cmnt(masm_, "[ FunctionDeclaration"); | 847 Comment cmnt(masm_, "[ FunctionDeclaration"); |
848 __ push(Immediate(variable->name())); | 848 __ push(Immediate(variable->name())); |
849 VisitForStackValue(declaration->fun()); | 849 VisitForStackValue(declaration->fun()); |
850 __ push( | 850 __ push( |
851 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); | 851 Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); |
852 __ CallRuntime(Runtime::kDeclareLookupSlot, 3); | 852 __ CallRuntime(Runtime::kDeclareLookupSlot); |
853 break; | 853 break; |
854 } | 854 } |
855 } | 855 } |
856 } | 856 } |
857 | 857 |
858 | 858 |
859 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 859 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
860 // Call the runtime to declare the globals. | 860 // Call the runtime to declare the globals. |
861 __ Push(pairs); | 861 __ Push(pairs); |
862 __ Push(Smi::FromInt(DeclareGlobalsFlags())); | 862 __ Push(Smi::FromInt(DeclareGlobalsFlags())); |
863 __ CallRuntime(Runtime::kDeclareGlobals, 2); | 863 __ CallRuntime(Runtime::kDeclareGlobals); |
864 // Return value is ignored. | 864 // Return value is ignored. |
865 } | 865 } |
866 | 866 |
867 | 867 |
868 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { | 868 void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { |
869 // Call the runtime to declare the modules. | 869 // Call the runtime to declare the modules. |
870 __ Push(descriptions); | 870 __ Push(descriptions); |
871 __ CallRuntime(Runtime::kDeclareModules, 1); | 871 __ CallRuntime(Runtime::kDeclareModules); |
872 // Return value is ignored. | 872 // Return value is ignored. |
873 } | 873 } |
874 | 874 |
875 | 875 |
876 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 876 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
877 Comment cmnt(masm_, "[ SwitchStatement"); | 877 Comment cmnt(masm_, "[ SwitchStatement"); |
878 Breakable nested_statement(this, stmt); | 878 Breakable nested_statement(this, stmt); |
879 SetStatementPosition(stmt); | 879 SetStatementPosition(stmt); |
880 | 880 |
881 // Keep the switch value on the stack until a case matches. | 881 // Keep the switch value on the stack until a case matches. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 // guarantee cache validity, call the runtime system to check cache | 1009 // guarantee cache validity, call the runtime system to check cache |
1010 // validity or get the property names in a fixed array. | 1010 // validity or get the property names in a fixed array. |
1011 __ CheckEnumCache(&call_runtime); | 1011 __ CheckEnumCache(&call_runtime); |
1012 | 1012 |
1013 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 1013 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
1014 __ jmp(&use_cache, Label::kNear); | 1014 __ jmp(&use_cache, Label::kNear); |
1015 | 1015 |
1016 // Get the set of properties to enumerate. | 1016 // Get the set of properties to enumerate. |
1017 __ bind(&call_runtime); | 1017 __ bind(&call_runtime); |
1018 __ push(eax); | 1018 __ push(eax); |
1019 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 1019 __ CallRuntime(Runtime::kGetPropertyNamesFast); |
1020 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); | 1020 PrepareForBailoutForId(stmt->EnumId(), TOS_REG); |
1021 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 1021 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
1022 isolate()->factory()->meta_map()); | 1022 isolate()->factory()->meta_map()); |
1023 __ j(not_equal, &fixed_array); | 1023 __ j(not_equal, &fixed_array); |
1024 | 1024 |
1025 | 1025 |
1026 // We got a map in register eax. Get the enumeration cache from it. | 1026 // We got a map in register eax. Get the enumeration cache from it. |
1027 Label no_descriptors; | 1027 Label no_descriptors; |
1028 __ bind(&use_cache); | 1028 __ bind(&use_cache); |
1029 | 1029 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1081 Label update_each; | 1081 Label update_each; |
1082 __ mov(ecx, Operand(esp, 4 * kPointerSize)); | 1082 __ mov(ecx, Operand(esp, 4 * kPointerSize)); |
1083 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); | 1083 __ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset)); |
1084 __ j(equal, &update_each, Label::kNear); | 1084 __ j(equal, &update_each, Label::kNear); |
1085 | 1085 |
1086 // Convert the entry to a string or null if it isn't a property | 1086 // Convert the entry to a string or null if it isn't a property |
1087 // anymore. If the property has been removed while iterating, we | 1087 // anymore. If the property has been removed while iterating, we |
1088 // just skip it. | 1088 // just skip it. |
1089 __ push(ecx); // Enumerable. | 1089 __ push(ecx); // Enumerable. |
1090 __ push(ebx); // Current entry. | 1090 __ push(ebx); // Current entry. |
1091 __ CallRuntime(Runtime::kForInFilter, 2); | 1091 __ CallRuntime(Runtime::kForInFilter); |
1092 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); | 1092 PrepareForBailoutForId(stmt->FilterId(), TOS_REG); |
1093 __ cmp(eax, isolate()->factory()->undefined_value()); | 1093 __ cmp(eax, isolate()->factory()->undefined_value()); |
1094 __ j(equal, loop_statement.continue_label()); | 1094 __ j(equal, loop_statement.continue_label()); |
1095 __ mov(ebx, eax); | 1095 __ mov(ebx, eax); |
1096 | 1096 |
1097 // Update the 'each' property or variable from the possibly filtered | 1097 // Update the 'each' property or variable from the possibly filtered |
1098 // entry in register ebx. | 1098 // entry in register ebx. |
1099 __ bind(&update_each); | 1099 __ bind(&update_each); |
1100 __ mov(result_register(), ebx); | 1100 __ mov(result_register(), ebx); |
1101 // Perform the assignment as if via '='. | 1101 // Perform the assignment as if via '='. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 if (!FLAG_always_opt && | 1139 if (!FLAG_always_opt && |
1140 !FLAG_prepare_always_opt && | 1140 !FLAG_prepare_always_opt && |
1141 !pretenure && | 1141 !pretenure && |
1142 scope()->is_function_scope() && | 1142 scope()->is_function_scope() && |
1143 info->num_literals() == 0) { | 1143 info->num_literals() == 0) { |
1144 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); | 1144 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
1145 __ mov(ebx, Immediate(info)); | 1145 __ mov(ebx, Immediate(info)); |
1146 __ CallStub(&stub); | 1146 __ CallStub(&stub); |
1147 } else { | 1147 } else { |
1148 __ push(Immediate(info)); | 1148 __ push(Immediate(info)); |
1149 __ CallRuntime( | 1149 __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured |
1150 pretenure ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure, 1); | 1150 : Runtime::kNewClosure); |
1151 } | 1151 } |
1152 context()->Plug(eax); | 1152 context()->Plug(eax); |
1153 } | 1153 } |
1154 | 1154 |
1155 | 1155 |
1156 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, | 1156 void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, |
1157 FeedbackVectorSlot slot) { | 1157 FeedbackVectorSlot slot) { |
1158 DCHECK(NeedsHomeObject(initializer)); | 1158 DCHECK(NeedsHomeObject(initializer)); |
1159 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); | 1159 __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); |
1160 __ mov(StoreDescriptor::NameRegister(), | 1160 __ mov(StoreDescriptor::NameRegister(), |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1276 Variable* local = var->local_if_not_shadowed(); | 1276 Variable* local = var->local_if_not_shadowed(); |
1277 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | 1277 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); |
1278 if (local->mode() == LET || local->mode() == CONST || | 1278 if (local->mode() == LET || local->mode() == CONST || |
1279 local->mode() == CONST_LEGACY) { | 1279 local->mode() == CONST_LEGACY) { |
1280 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1280 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1281 __ j(not_equal, done); | 1281 __ j(not_equal, done); |
1282 if (local->mode() == CONST_LEGACY) { | 1282 if (local->mode() == CONST_LEGACY) { |
1283 __ mov(eax, isolate()->factory()->undefined_value()); | 1283 __ mov(eax, isolate()->factory()->undefined_value()); |
1284 } else { // LET || CONST | 1284 } else { // LET || CONST |
1285 __ push(Immediate(var->name())); | 1285 __ push(Immediate(var->name())); |
1286 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1286 __ CallRuntime(Runtime::kThrowReferenceError); |
1287 } | 1287 } |
1288 } | 1288 } |
1289 __ jmp(done); | 1289 __ jmp(done); |
1290 } | 1290 } |
1291 } | 1291 } |
1292 | 1292 |
1293 | 1293 |
1294 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1294 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1295 TypeofMode typeof_mode) { | 1295 TypeofMode typeof_mode) { |
1296 Variable* var = proxy->var(); | 1296 Variable* var = proxy->var(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 if (NeedsHoleCheckForLoad(proxy)) { | 1334 if (NeedsHoleCheckForLoad(proxy)) { |
1335 // Let and const need a read barrier. | 1335 // Let and const need a read barrier. |
1336 Label done; | 1336 Label done; |
1337 GetVar(eax, var); | 1337 GetVar(eax, var); |
1338 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1338 __ cmp(eax, isolate()->factory()->the_hole_value()); |
1339 __ j(not_equal, &done, Label::kNear); | 1339 __ j(not_equal, &done, Label::kNear); |
1340 if (var->mode() == LET || var->mode() == CONST) { | 1340 if (var->mode() == LET || var->mode() == CONST) { |
1341 // Throw a reference error when using an uninitialized let/const | 1341 // Throw a reference error when using an uninitialized let/const |
1342 // binding in harmony mode. | 1342 // binding in harmony mode. |
1343 __ push(Immediate(var->name())); | 1343 __ push(Immediate(var->name())); |
1344 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1344 __ CallRuntime(Runtime::kThrowReferenceError); |
1345 } else { | 1345 } else { |
1346 // Uninitialized legacy const bindings are unholed. | 1346 // Uninitialized legacy const bindings are unholed. |
1347 DCHECK(var->mode() == CONST_LEGACY); | 1347 DCHECK(var->mode() == CONST_LEGACY); |
1348 __ mov(eax, isolate()->factory()->undefined_value()); | 1348 __ mov(eax, isolate()->factory()->undefined_value()); |
1349 } | 1349 } |
1350 __ bind(&done); | 1350 __ bind(&done); |
1351 context()->Plug(eax); | 1351 context()->Plug(eax); |
1352 break; | 1352 break; |
1353 } | 1353 } |
1354 context()->Plug(var); | 1354 context()->Plug(var); |
1355 break; | 1355 break; |
1356 } | 1356 } |
1357 | 1357 |
1358 case VariableLocation::LOOKUP: { | 1358 case VariableLocation::LOOKUP: { |
1359 Comment cmnt(masm_, "[ Lookup variable"); | 1359 Comment cmnt(masm_, "[ Lookup variable"); |
1360 Label done, slow; | 1360 Label done, slow; |
1361 // Generate code for loading from variables potentially shadowed | 1361 // Generate code for loading from variables potentially shadowed |
1362 // by eval-introduced variables. | 1362 // by eval-introduced variables. |
1363 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); | 1363 EmitDynamicLookupFastCase(proxy, typeof_mode, &slow, &done); |
1364 __ bind(&slow); | 1364 __ bind(&slow); |
1365 __ push(esi); // Context. | 1365 __ push(esi); // Context. |
1366 __ push(Immediate(var->name())); | 1366 __ push(Immediate(var->name())); |
1367 Runtime::FunctionId function_id = | 1367 Runtime::FunctionId function_id = |
1368 typeof_mode == NOT_INSIDE_TYPEOF | 1368 typeof_mode == NOT_INSIDE_TYPEOF |
1369 ? Runtime::kLoadLookupSlot | 1369 ? Runtime::kLoadLookupSlot |
1370 : Runtime::kLoadLookupSlotNoReferenceError; | 1370 : Runtime::kLoadLookupSlotNoReferenceError; |
1371 __ CallRuntime(function_id, 2); | 1371 __ CallRuntime(function_id); |
1372 __ bind(&done); | 1372 __ bind(&done); |
1373 context()->Plug(eax); | 1373 context()->Plug(eax); |
1374 break; | 1374 break; |
1375 } | 1375 } |
1376 } | 1376 } |
1377 } | 1377 } |
1378 | 1378 |
1379 | 1379 |
1380 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1380 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
1381 Comment cmnt(masm_, "[ RegExpLiteral"); | 1381 Comment cmnt(masm_, "[ RegExpLiteral"); |
(...skipping 28 matching lines...) Expand all Loading... |
1410 | 1410 |
1411 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1411 Handle<FixedArray> constant_properties = expr->constant_properties(); |
1412 int flags = expr->ComputeFlags(); | 1412 int flags = expr->ComputeFlags(); |
1413 // If any of the keys would store to the elements array, then we shouldn't | 1413 // If any of the keys would store to the elements array, then we shouldn't |
1414 // allow it. | 1414 // allow it. |
1415 if (MustCreateObjectLiteralWithRuntime(expr)) { | 1415 if (MustCreateObjectLiteralWithRuntime(expr)) { |
1416 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1416 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1417 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1417 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1418 __ push(Immediate(constant_properties)); | 1418 __ push(Immediate(constant_properties)); |
1419 __ push(Immediate(Smi::FromInt(flags))); | 1419 __ push(Immediate(Smi::FromInt(flags))); |
1420 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1420 __ CallRuntime(Runtime::kCreateObjectLiteral); |
1421 } else { | 1421 } else { |
1422 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1422 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1423 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1423 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
1424 __ mov(ecx, Immediate(constant_properties)); | 1424 __ mov(ecx, Immediate(constant_properties)); |
1425 __ mov(edx, Immediate(Smi::FromInt(flags))); | 1425 __ mov(edx, Immediate(Smi::FromInt(flags))); |
1426 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); | 1426 FastCloneShallowObjectStub stub(isolate(), expr->properties_count()); |
1427 __ CallStub(&stub); | 1427 __ CallStub(&stub); |
1428 } | 1428 } |
1429 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1429 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1430 | 1430 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1472 break; | 1472 break; |
1473 } | 1473 } |
1474 __ push(Operand(esp, 0)); // Duplicate receiver. | 1474 __ push(Operand(esp, 0)); // Duplicate receiver. |
1475 VisitForStackValue(key); | 1475 VisitForStackValue(key); |
1476 VisitForStackValue(value); | 1476 VisitForStackValue(value); |
1477 if (property->emit_store()) { | 1477 if (property->emit_store()) { |
1478 if (NeedsHomeObject(value)) { | 1478 if (NeedsHomeObject(value)) { |
1479 EmitSetHomeObject(value, 2, property->GetSlot()); | 1479 EmitSetHomeObject(value, 2, property->GetSlot()); |
1480 } | 1480 } |
1481 __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode | 1481 __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode |
1482 __ CallRuntime(Runtime::kSetProperty, 4); | 1482 __ CallRuntime(Runtime::kSetProperty); |
1483 } else { | 1483 } else { |
1484 __ Drop(3); | 1484 __ Drop(3); |
1485 } | 1485 } |
1486 break; | 1486 break; |
1487 case ObjectLiteral::Property::PROTOTYPE: | 1487 case ObjectLiteral::Property::PROTOTYPE: |
1488 __ push(Operand(esp, 0)); // Duplicate receiver. | 1488 __ push(Operand(esp, 0)); // Duplicate receiver. |
1489 VisitForStackValue(value); | 1489 VisitForStackValue(value); |
1490 DCHECK(property->emit_store()); | 1490 DCHECK(property->emit_store()); |
1491 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1491 __ CallRuntime(Runtime::kInternalSetPrototype); |
1492 break; | 1492 break; |
1493 case ObjectLiteral::Property::GETTER: | 1493 case ObjectLiteral::Property::GETTER: |
1494 if (property->emit_store()) { | 1494 if (property->emit_store()) { |
1495 accessor_table.lookup(key)->second->getter = property; | 1495 accessor_table.lookup(key)->second->getter = property; |
1496 } | 1496 } |
1497 break; | 1497 break; |
1498 case ObjectLiteral::Property::SETTER: | 1498 case ObjectLiteral::Property::SETTER: |
1499 if (property->emit_store()) { | 1499 if (property->emit_store()) { |
1500 accessor_table.lookup(key)->second->setter = property; | 1500 accessor_table.lookup(key)->second->setter = property; |
1501 } | 1501 } |
1502 break; | 1502 break; |
1503 } | 1503 } |
1504 } | 1504 } |
1505 | 1505 |
1506 // Emit code to define accessors, using only a single call to the runtime for | 1506 // Emit code to define accessors, using only a single call to the runtime for |
1507 // each pair of corresponding getters and setters. | 1507 // each pair of corresponding getters and setters. |
1508 for (AccessorTable::Iterator it = accessor_table.begin(); | 1508 for (AccessorTable::Iterator it = accessor_table.begin(); |
1509 it != accessor_table.end(); | 1509 it != accessor_table.end(); |
1510 ++it) { | 1510 ++it) { |
1511 __ push(Operand(esp, 0)); // Duplicate receiver. | 1511 __ push(Operand(esp, 0)); // Duplicate receiver. |
1512 VisitForStackValue(it->first); | 1512 VisitForStackValue(it->first); |
1513 | 1513 |
1514 EmitAccessor(it->second->getter); | 1514 EmitAccessor(it->second->getter); |
1515 EmitAccessor(it->second->setter); | 1515 EmitAccessor(it->second->setter); |
1516 | 1516 |
1517 __ push(Immediate(Smi::FromInt(NONE))); | 1517 __ push(Immediate(Smi::FromInt(NONE))); |
1518 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1518 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
1519 } | 1519 } |
1520 | 1520 |
1521 // Object literals have two parts. The "static" part on the left contains no | 1521 // Object literals have two parts. The "static" part on the left contains no |
1522 // computed property names, and so we can compute its map ahead of time; see | 1522 // computed property names, and so we can compute its map ahead of time; see |
1523 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part | 1523 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
1524 // starts with the first computed property name, and continues with all | 1524 // starts with the first computed property name, and continues with all |
1525 // properties to its right. All the code from above initializes the static | 1525 // properties to its right. All the code from above initializes the static |
1526 // component of the object literal, and arranges for the map of the result to | 1526 // component of the object literal, and arranges for the map of the result to |
1527 // reflect the static order in which the keys appear. For the dynamic | 1527 // reflect the static order in which the keys appear. For the dynamic |
1528 // properties, we compile them into a series of "SetOwnProperty" runtime | 1528 // properties, we compile them into a series of "SetOwnProperty" runtime |
1529 // calls. This will preserve insertion order. | 1529 // calls. This will preserve insertion order. |
1530 for (; property_index < expr->properties()->length(); property_index++) { | 1530 for (; property_index < expr->properties()->length(); property_index++) { |
1531 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 1531 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
1532 | 1532 |
1533 Expression* value = property->value(); | 1533 Expression* value = property->value(); |
1534 if (!result_saved) { | 1534 if (!result_saved) { |
1535 __ push(eax); // Save result on the stack | 1535 __ push(eax); // Save result on the stack |
1536 result_saved = true; | 1536 result_saved = true; |
1537 } | 1537 } |
1538 | 1538 |
1539 __ push(Operand(esp, 0)); // Duplicate receiver. | 1539 __ push(Operand(esp, 0)); // Duplicate receiver. |
1540 | 1540 |
1541 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1541 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
1542 DCHECK(!property->is_computed_name()); | 1542 DCHECK(!property->is_computed_name()); |
1543 VisitForStackValue(value); | 1543 VisitForStackValue(value); |
1544 DCHECK(property->emit_store()); | 1544 DCHECK(property->emit_store()); |
1545 __ CallRuntime(Runtime::kInternalSetPrototype, 2); | 1545 __ CallRuntime(Runtime::kInternalSetPrototype); |
1546 } else { | 1546 } else { |
1547 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); | 1547 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
1548 VisitForStackValue(value); | 1548 VisitForStackValue(value); |
1549 if (NeedsHomeObject(value)) { | 1549 if (NeedsHomeObject(value)) { |
1550 EmitSetHomeObject(value, 2, property->GetSlot()); | 1550 EmitSetHomeObject(value, 2, property->GetSlot()); |
1551 } | 1551 } |
1552 | 1552 |
1553 switch (property->kind()) { | 1553 switch (property->kind()) { |
1554 case ObjectLiteral::Property::CONSTANT: | 1554 case ObjectLiteral::Property::CONSTANT: |
1555 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1555 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1556 case ObjectLiteral::Property::COMPUTED: | 1556 case ObjectLiteral::Property::COMPUTED: |
1557 if (property->emit_store()) { | 1557 if (property->emit_store()) { |
1558 __ push(Immediate(Smi::FromInt(NONE))); | 1558 __ push(Immediate(Smi::FromInt(NONE))); |
1559 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); | 1559 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked); |
1560 } else { | 1560 } else { |
1561 __ Drop(3); | 1561 __ Drop(3); |
1562 } | 1562 } |
1563 break; | 1563 break; |
1564 | 1564 |
1565 case ObjectLiteral::Property::PROTOTYPE: | 1565 case ObjectLiteral::Property::PROTOTYPE: |
1566 UNREACHABLE(); | 1566 UNREACHABLE(); |
1567 break; | 1567 break; |
1568 | 1568 |
1569 case ObjectLiteral::Property::GETTER: | 1569 case ObjectLiteral::Property::GETTER: |
1570 __ push(Immediate(Smi::FromInt(NONE))); | 1570 __ push(Immediate(Smi::FromInt(NONE))); |
1571 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 1571 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
1572 break; | 1572 break; |
1573 | 1573 |
1574 case ObjectLiteral::Property::SETTER: | 1574 case ObjectLiteral::Property::SETTER: |
1575 __ push(Immediate(Smi::FromInt(NONE))); | 1575 __ push(Immediate(Smi::FromInt(NONE))); |
1576 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 1576 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
1577 break; | 1577 break; |
1578 } | 1578 } |
1579 } | 1579 } |
1580 } | 1580 } |
1581 | 1581 |
1582 if (expr->has_function()) { | 1582 if (expr->has_function()) { |
1583 DCHECK(result_saved); | 1583 DCHECK(result_saved); |
1584 __ push(Operand(esp, 0)); | 1584 __ push(Operand(esp, 0)); |
1585 __ CallRuntime(Runtime::kToFastProperties, 1); | 1585 __ CallRuntime(Runtime::kToFastProperties); |
1586 } | 1586 } |
1587 | 1587 |
1588 if (result_saved) { | 1588 if (result_saved) { |
1589 context()->PlugTOS(); | 1589 context()->PlugTOS(); |
1590 } else { | 1590 } else { |
1591 context()->Plug(eax); | 1591 context()->Plug(eax); |
1592 } | 1592 } |
1593 } | 1593 } |
1594 | 1594 |
1595 | 1595 |
1596 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1596 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
1597 Comment cmnt(masm_, "[ ArrayLiteral"); | 1597 Comment cmnt(masm_, "[ ArrayLiteral"); |
1598 | 1598 |
1599 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1599 Handle<FixedArray> constant_elements = expr->constant_elements(); |
1600 bool has_constant_fast_elements = | 1600 bool has_constant_fast_elements = |
1601 IsFastObjectElementsKind(expr->constant_elements_kind()); | 1601 IsFastObjectElementsKind(expr->constant_elements_kind()); |
1602 | 1602 |
1603 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; | 1603 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; |
1604 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { | 1604 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { |
1605 // If the only customer of allocation sites is transitioning, then | 1605 // If the only customer of allocation sites is transitioning, then |
1606 // we can turn it off if we don't have anywhere else to transition to. | 1606 // we can turn it off if we don't have anywhere else to transition to. |
1607 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; | 1607 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; |
1608 } | 1608 } |
1609 | 1609 |
1610 if (MustCreateArrayLiteralWithRuntime(expr)) { | 1610 if (MustCreateArrayLiteralWithRuntime(expr)) { |
1611 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1611 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1612 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 1612 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
1613 __ push(Immediate(constant_elements)); | 1613 __ push(Immediate(constant_elements)); |
1614 __ push(Immediate(Smi::FromInt(expr->ComputeFlags()))); | 1614 __ push(Immediate(Smi::FromInt(expr->ComputeFlags()))); |
1615 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); | 1615 __ CallRuntime(Runtime::kCreateArrayLiteral); |
1616 } else { | 1616 } else { |
1617 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1617 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1618 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); | 1618 __ mov(ebx, Immediate(Smi::FromInt(expr->literal_index()))); |
1619 __ mov(ecx, Immediate(constant_elements)); | 1619 __ mov(ecx, Immediate(constant_elements)); |
1620 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); | 1620 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); |
1621 __ CallStub(&stub); | 1621 __ CallStub(&stub); |
1622 } | 1622 } |
1623 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); | 1623 PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG); |
1624 | 1624 |
1625 bool result_saved = false; // Is the result saved to the stack? | 1625 bool result_saved = false; // Is the result saved to the stack? |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 for (; array_index < length; array_index++) { | 1665 for (; array_index < length; array_index++) { |
1666 Expression* subexpr = subexprs->at(array_index); | 1666 Expression* subexpr = subexprs->at(array_index); |
1667 | 1667 |
1668 __ Push(eax); | 1668 __ Push(eax); |
1669 if (subexpr->IsSpread()) { | 1669 if (subexpr->IsSpread()) { |
1670 VisitForStackValue(subexpr->AsSpread()->expression()); | 1670 VisitForStackValue(subexpr->AsSpread()->expression()); |
1671 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, | 1671 __ InvokeBuiltin(Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, |
1672 CALL_FUNCTION); | 1672 CALL_FUNCTION); |
1673 } else { | 1673 } else { |
1674 VisitForStackValue(subexpr); | 1674 VisitForStackValue(subexpr); |
1675 __ CallRuntime(Runtime::kAppendElement, 2); | 1675 __ CallRuntime(Runtime::kAppendElement); |
1676 } | 1676 } |
1677 | 1677 |
1678 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); | 1678 PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
1679 } | 1679 } |
1680 | 1680 |
1681 if (result_saved) { | 1681 if (result_saved) { |
1682 context()->PlugTOS(); | 1682 context()->PlugTOS(); |
1683 } else { | 1683 } else { |
1684 context()->Plug(eax); | 1684 context()->Plug(eax); |
1685 } | 1685 } |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2063 Label push_operand_holes, call_resume; | 2063 Label push_operand_holes, call_resume; |
2064 __ bind(&push_operand_holes); | 2064 __ bind(&push_operand_holes); |
2065 __ sub(edx, Immediate(1)); | 2065 __ sub(edx, Immediate(1)); |
2066 __ j(carry, &call_resume); | 2066 __ j(carry, &call_resume); |
2067 __ push(ecx); | 2067 __ push(ecx); |
2068 __ jmp(&push_operand_holes); | 2068 __ jmp(&push_operand_holes); |
2069 __ bind(&call_resume); | 2069 __ bind(&call_resume); |
2070 __ push(ebx); | 2070 __ push(ebx); |
2071 __ push(result_register()); | 2071 __ push(result_register()); |
2072 __ Push(Smi::FromInt(resume_mode)); | 2072 __ Push(Smi::FromInt(resume_mode)); |
2073 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2073 __ CallRuntime(Runtime::kResumeJSGeneratorObject); |
2074 // Not reached: the runtime call returns elsewhere. | 2074 // Not reached: the runtime call returns elsewhere. |
2075 __ Abort(kGeneratorFailedToResume); | 2075 __ Abort(kGeneratorFailedToResume); |
2076 | 2076 |
2077 __ bind(&done); | 2077 __ bind(&done); |
2078 context()->Plug(result_register()); | 2078 context()->Plug(result_register()); |
2079 } | 2079 } |
2080 | 2080 |
2081 | 2081 |
2082 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2082 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2083 Label allocate, done_allocate; | 2083 Label allocate, done_allocate; |
2084 | 2084 |
2085 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); | 2085 __ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &allocate, TAG_OBJECT); |
2086 __ jmp(&done_allocate, Label::kNear); | 2086 __ jmp(&done_allocate, Label::kNear); |
2087 | 2087 |
2088 __ bind(&allocate); | 2088 __ bind(&allocate); |
2089 __ Push(Smi::FromInt(JSIteratorResult::kSize)); | 2089 __ Push(Smi::FromInt(JSIteratorResult::kSize)); |
2090 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 2090 __ CallRuntime(Runtime::kAllocateInNewSpace); |
2091 | 2091 |
2092 __ bind(&done_allocate); | 2092 __ bind(&done_allocate); |
2093 __ mov(ebx, NativeContextOperand()); | 2093 __ mov(ebx, NativeContextOperand()); |
2094 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); | 2094 __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX)); |
2095 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2095 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
2096 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2096 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
2097 isolate()->factory()->empty_fixed_array()); | 2097 isolate()->factory()->empty_fixed_array()); |
2098 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2098 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
2099 isolate()->factory()->empty_fixed_array()); | 2099 isolate()->factory()->empty_fixed_array()); |
2100 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 2100 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
(...skipping 18 matching lines...) Expand all Loading... |
2119 | 2119 |
2120 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { | 2120 void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
2121 // Stack: receiver, home_object. | 2121 // Stack: receiver, home_object. |
2122 SetExpressionPosition(prop); | 2122 SetExpressionPosition(prop); |
2123 Literal* key = prop->key()->AsLiteral(); | 2123 Literal* key = prop->key()->AsLiteral(); |
2124 DCHECK(!key->value()->IsSmi()); | 2124 DCHECK(!key->value()->IsSmi()); |
2125 DCHECK(prop->IsSuperAccess()); | 2125 DCHECK(prop->IsSuperAccess()); |
2126 | 2126 |
2127 __ push(Immediate(key->value())); | 2127 __ push(Immediate(key->value())); |
2128 __ push(Immediate(Smi::FromInt(language_mode()))); | 2128 __ push(Immediate(Smi::FromInt(language_mode()))); |
2129 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2129 __ CallRuntime(Runtime::kLoadFromSuper); |
2130 } | 2130 } |
2131 | 2131 |
2132 | 2132 |
2133 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 2133 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
2134 SetExpressionPosition(prop); | 2134 SetExpressionPosition(prop); |
2135 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); | 2135 Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code(); |
2136 __ mov(LoadDescriptor::SlotRegister(), | 2136 __ mov(LoadDescriptor::SlotRegister(), |
2137 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); | 2137 Immediate(SmiFromSlot(prop->PropertyFeedbackSlot()))); |
2138 CallIC(ic); | 2138 CallIC(ic); |
2139 } | 2139 } |
2140 | 2140 |
2141 | 2141 |
2142 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2142 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
2143 // Stack: receiver, home_object, key. | 2143 // Stack: receiver, home_object, key. |
2144 SetExpressionPosition(prop); | 2144 SetExpressionPosition(prop); |
2145 __ push(Immediate(Smi::FromInt(language_mode()))); | 2145 __ push(Immediate(Smi::FromInt(language_mode()))); |
2146 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2146 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2147 } | 2147 } |
2148 | 2148 |
2149 | 2149 |
2150 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2150 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
2151 Token::Value op, | 2151 Token::Value op, |
2152 Expression* left, | 2152 Expression* left, |
2153 Expression* right) { | 2153 Expression* right) { |
2154 // Do combined smi check of the operands. Left operand is on the | 2154 // Do combined smi check of the operands. Left operand is on the |
2155 // stack. Right operand is in eax. | 2155 // stack. Right operand is in eax. |
2156 Label smi_case, done, stub_call; | 2156 Label smi_case, done, stub_call; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2262 } else { | 2262 } else { |
2263 __ push(Operand(esp, 0)); // prototype | 2263 __ push(Operand(esp, 0)); // prototype |
2264 } | 2264 } |
2265 EmitPropertyKey(property, lit->GetIdForProperty(i)); | 2265 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
2266 | 2266 |
2267 // The static prototype property is read only. We handle the non computed | 2267 // The static prototype property is read only. We handle the non computed |
2268 // property name case in the parser. Since this is the only case where we | 2268 // property name case in the parser. Since this is the only case where we |
2269 // need to check for an own read only property we special case this so we do | 2269 // need to check for an own read only property we special case this so we do |
2270 // not need to do this for every property. | 2270 // not need to do this for every property. |
2271 if (property->is_static() && property->is_computed_name()) { | 2271 if (property->is_static() && property->is_computed_name()) { |
2272 __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1); | 2272 __ CallRuntime(Runtime::kThrowIfStaticPrototype); |
2273 __ push(eax); | 2273 __ push(eax); |
2274 } | 2274 } |
2275 | 2275 |
2276 VisitForStackValue(value); | 2276 VisitForStackValue(value); |
2277 if (NeedsHomeObject(value)) { | 2277 if (NeedsHomeObject(value)) { |
2278 EmitSetHomeObject(value, 2, property->GetSlot()); | 2278 EmitSetHomeObject(value, 2, property->GetSlot()); |
2279 } | 2279 } |
2280 | 2280 |
2281 switch (property->kind()) { | 2281 switch (property->kind()) { |
2282 case ObjectLiteral::Property::CONSTANT: | 2282 case ObjectLiteral::Property::CONSTANT: |
2283 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2283 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2284 case ObjectLiteral::Property::PROTOTYPE: | 2284 case ObjectLiteral::Property::PROTOTYPE: |
2285 UNREACHABLE(); | 2285 UNREACHABLE(); |
2286 case ObjectLiteral::Property::COMPUTED: | 2286 case ObjectLiteral::Property::COMPUTED: |
2287 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2287 __ CallRuntime(Runtime::kDefineClassMethod); |
2288 break; | 2288 break; |
2289 | 2289 |
2290 case ObjectLiteral::Property::GETTER: | 2290 case ObjectLiteral::Property::GETTER: |
2291 __ push(Immediate(Smi::FromInt(DONT_ENUM))); | 2291 __ push(Immediate(Smi::FromInt(DONT_ENUM))); |
2292 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); | 2292 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
2293 break; | 2293 break; |
2294 | 2294 |
2295 case ObjectLiteral::Property::SETTER: | 2295 case ObjectLiteral::Property::SETTER: |
2296 __ push(Immediate(Smi::FromInt(DONT_ENUM))); | 2296 __ push(Immediate(Smi::FromInt(DONT_ENUM))); |
2297 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); | 2297 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
2298 break; | 2298 break; |
2299 } | 2299 } |
2300 } | 2300 } |
2301 | 2301 |
2302 // Set both the prototype and constructor to have fast properties, and also | 2302 // Set both the prototype and constructor to have fast properties, and also |
2303 // freeze them in strong mode. | 2303 // freeze them in strong mode. |
2304 __ CallRuntime(Runtime::kFinalizeClassDefinition, 2); | 2304 __ CallRuntime(Runtime::kFinalizeClassDefinition); |
2305 } | 2305 } |
2306 | 2306 |
2307 | 2307 |
2308 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { | 2308 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
2309 __ pop(edx); | 2309 __ pop(edx); |
2310 Handle<Code> code = | 2310 Handle<Code> code = |
2311 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); | 2311 CodeFactory::BinaryOpIC(isolate(), op, strength(language_mode())).code(); |
2312 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2312 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2313 CallIC(code, expr->BinaryOperationFeedbackId()); | 2313 CallIC(code, expr->BinaryOperationFeedbackId()); |
2314 patch_site.EmitPatchInfo(); | 2314 patch_site.EmitPatchInfo(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2422 } else if (var->mode() == LET && op != Token::INIT) { | 2422 } else if (var->mode() == LET && op != Token::INIT) { |
2423 // Non-initializing assignment to let variable needs a write barrier. | 2423 // Non-initializing assignment to let variable needs a write barrier. |
2424 DCHECK(!var->IsLookupSlot()); | 2424 DCHECK(!var->IsLookupSlot()); |
2425 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2425 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2426 Label assign; | 2426 Label assign; |
2427 MemOperand location = VarOperand(var, ecx); | 2427 MemOperand location = VarOperand(var, ecx); |
2428 __ mov(edx, location); | 2428 __ mov(edx, location); |
2429 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2429 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2430 __ j(not_equal, &assign, Label::kNear); | 2430 __ j(not_equal, &assign, Label::kNear); |
2431 __ push(Immediate(var->name())); | 2431 __ push(Immediate(var->name())); |
2432 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2432 __ CallRuntime(Runtime::kThrowReferenceError); |
2433 __ bind(&assign); | 2433 __ bind(&assign); |
2434 EmitStoreToStackLocalOrContextSlot(var, location); | 2434 EmitStoreToStackLocalOrContextSlot(var, location); |
2435 | 2435 |
2436 } else if (var->mode() == CONST && op != Token::INIT) { | 2436 } else if (var->mode() == CONST && op != Token::INIT) { |
2437 // Assignment to const variable needs a write barrier. | 2437 // Assignment to const variable needs a write barrier. |
2438 DCHECK(!var->IsLookupSlot()); | 2438 DCHECK(!var->IsLookupSlot()); |
2439 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2439 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2440 Label const_error; | 2440 Label const_error; |
2441 MemOperand location = VarOperand(var, ecx); | 2441 MemOperand location = VarOperand(var, ecx); |
2442 __ mov(edx, location); | 2442 __ mov(edx, location); |
2443 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2443 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2444 __ j(not_equal, &const_error, Label::kNear); | 2444 __ j(not_equal, &const_error, Label::kNear); |
2445 __ push(Immediate(var->name())); | 2445 __ push(Immediate(var->name())); |
2446 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2446 __ CallRuntime(Runtime::kThrowReferenceError); |
2447 __ bind(&const_error); | 2447 __ bind(&const_error); |
2448 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2448 __ CallRuntime(Runtime::kThrowConstAssignError); |
2449 | 2449 |
2450 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2450 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
2451 // Initializing assignment to const {this} needs a write barrier. | 2451 // Initializing assignment to const {this} needs a write barrier. |
2452 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2452 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2453 Label uninitialized_this; | 2453 Label uninitialized_this; |
2454 MemOperand location = VarOperand(var, ecx); | 2454 MemOperand location = VarOperand(var, ecx); |
2455 __ mov(edx, location); | 2455 __ mov(edx, location); |
2456 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2456 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2457 __ j(equal, &uninitialized_this); | 2457 __ j(equal, &uninitialized_this); |
2458 __ push(Immediate(var->name())); | 2458 __ push(Immediate(var->name())); |
2459 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2459 __ CallRuntime(Runtime::kThrowReferenceError); |
2460 __ bind(&uninitialized_this); | 2460 __ bind(&uninitialized_this); |
2461 EmitStoreToStackLocalOrContextSlot(var, location); | 2461 EmitStoreToStackLocalOrContextSlot(var, location); |
2462 | 2462 |
2463 } else if (!var->is_const_mode() || | 2463 } else if (!var->is_const_mode() || |
2464 (var->mode() == CONST && op == Token::INIT)) { | 2464 (var->mode() == CONST && op == Token::INIT)) { |
2465 if (var->IsLookupSlot()) { | 2465 if (var->IsLookupSlot()) { |
2466 // Assignment to var. | 2466 // Assignment to var. |
2467 __ push(eax); // Value. | 2467 __ push(eax); // Value. |
2468 __ push(esi); // Context. | 2468 __ push(esi); // Context. |
2469 __ push(Immediate(var->name())); | 2469 __ push(Immediate(var->name())); |
2470 __ push(Immediate(Smi::FromInt(language_mode()))); | 2470 __ push(Immediate(Smi::FromInt(language_mode()))); |
2471 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2471 __ CallRuntime(Runtime::kStoreLookupSlot); |
2472 } else { | 2472 } else { |
2473 // Assignment to var or initializing assignment to let/const in harmony | 2473 // Assignment to var or initializing assignment to let/const in harmony |
2474 // mode. | 2474 // mode. |
2475 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2475 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2476 MemOperand location = VarOperand(var, ecx); | 2476 MemOperand location = VarOperand(var, ecx); |
2477 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { | 2477 if (generate_debug_code_ && var->mode() == LET && op == Token::INIT) { |
2478 // Check for an uninitialized let binding. | 2478 // Check for an uninitialized let binding. |
2479 __ mov(edx, location); | 2479 __ mov(edx, location); |
2480 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2480 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2481 __ Check(equal, kLetBindingReInitialization); | 2481 __ Check(equal, kLetBindingReInitialization); |
2482 } | 2482 } |
2483 EmitStoreToStackLocalOrContextSlot(var, location); | 2483 EmitStoreToStackLocalOrContextSlot(var, location); |
2484 } | 2484 } |
2485 | 2485 |
2486 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | 2486 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { |
2487 // Const initializers need a write barrier. | 2487 // Const initializers need a write barrier. |
2488 DCHECK(!var->IsParameter()); // No const parameters. | 2488 DCHECK(!var->IsParameter()); // No const parameters. |
2489 if (var->IsLookupSlot()) { | 2489 if (var->IsLookupSlot()) { |
2490 __ push(eax); | 2490 __ push(eax); |
2491 __ push(esi); | 2491 __ push(esi); |
2492 __ push(Immediate(var->name())); | 2492 __ push(Immediate(var->name())); |
2493 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); | 2493 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); |
2494 } else { | 2494 } else { |
2495 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | 2495 DCHECK(var->IsStackLocal() || var->IsContextSlot()); |
2496 Label skip; | 2496 Label skip; |
2497 MemOperand location = VarOperand(var, ecx); | 2497 MemOperand location = VarOperand(var, ecx); |
2498 __ mov(edx, location); | 2498 __ mov(edx, location); |
2499 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2499 __ cmp(edx, isolate()->factory()->the_hole_value()); |
2500 __ j(not_equal, &skip, Label::kNear); | 2500 __ j(not_equal, &skip, Label::kNear); |
2501 EmitStoreToStackLocalOrContextSlot(var, location); | 2501 EmitStoreToStackLocalOrContextSlot(var, location); |
2502 __ bind(&skip); | 2502 __ bind(&skip); |
2503 } | 2503 } |
2504 | 2504 |
2505 } else { | 2505 } else { |
2506 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2506 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2507 if (is_strict(language_mode())) { | 2507 if (is_strict(language_mode())) { |
2508 __ CallRuntime(Runtime::kThrowConstAssignError, 0); | 2508 __ CallRuntime(Runtime::kThrowConstAssignError); |
2509 } | 2509 } |
2510 // Silently ignore store in sloppy mode. | 2510 // Silently ignore store in sloppy mode. |
2511 } | 2511 } |
2512 } | 2512 } |
2513 | 2513 |
2514 | 2514 |
2515 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2515 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2516 // Assignment to a property, using a named store IC. | 2516 // Assignment to a property, using a named store IC. |
2517 // eax : value | 2517 // eax : value |
2518 // esp[0] : receiver | 2518 // esp[0] : receiver |
(...skipping 14 matching lines...) Expand all Loading... |
2533 // Assignment to named property of super. | 2533 // Assignment to named property of super. |
2534 // eax : value | 2534 // eax : value |
2535 // stack : receiver ('this'), home_object | 2535 // stack : receiver ('this'), home_object |
2536 DCHECK(prop != NULL); | 2536 DCHECK(prop != NULL); |
2537 Literal* key = prop->key()->AsLiteral(); | 2537 Literal* key = prop->key()->AsLiteral(); |
2538 DCHECK(key != NULL); | 2538 DCHECK(key != NULL); |
2539 | 2539 |
2540 __ push(Immediate(key->value())); | 2540 __ push(Immediate(key->value())); |
2541 __ push(eax); | 2541 __ push(eax); |
2542 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict | 2542 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
2543 : Runtime::kStoreToSuper_Sloppy), | 2543 : Runtime::kStoreToSuper_Sloppy)); |
2544 4); | |
2545 } | 2544 } |
2546 | 2545 |
2547 | 2546 |
2548 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2547 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
2549 // Assignment to named property of super. | 2548 // Assignment to named property of super. |
2550 // eax : value | 2549 // eax : value |
2551 // stack : receiver ('this'), home_object, key | 2550 // stack : receiver ('this'), home_object, key |
2552 | 2551 |
2553 __ push(eax); | 2552 __ push(eax); |
2554 __ CallRuntime( | 2553 __ CallRuntime((is_strict(language_mode()) |
2555 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 2554 ? Runtime::kStoreKeyedToSuper_Strict |
2556 : Runtime::kStoreKeyedToSuper_Sloppy), | 2555 : Runtime::kStoreKeyedToSuper_Sloppy)); |
2557 4); | |
2558 } | 2556 } |
2559 | 2557 |
2560 | 2558 |
2561 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2559 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2562 // Assignment to a property, using a keyed store IC. | 2560 // Assignment to a property, using a keyed store IC. |
2563 // eax : value | 2561 // eax : value |
2564 // esp[0] : key | 2562 // esp[0] : key |
2565 // esp[kPointerSize] : receiver | 2563 // esp[kPointerSize] : receiver |
2566 | 2564 |
2567 __ pop(StoreDescriptor::NameRegister()); // Key. | 2565 __ pop(StoreDescriptor::NameRegister()); // Key. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2670 __ push(Operand(esp, kPointerSize * 2)); | 2668 __ push(Operand(esp, kPointerSize * 2)); |
2671 __ push(Immediate(key->value())); | 2669 __ push(Immediate(key->value())); |
2672 __ push(Immediate(Smi::FromInt(language_mode()))); | 2670 __ push(Immediate(Smi::FromInt(language_mode()))); |
2673 // Stack here: | 2671 // Stack here: |
2674 // - home_object | 2672 // - home_object |
2675 // - this (receiver) | 2673 // - this (receiver) |
2676 // - this (receiver) <-- LoadFromSuper will pop here and below. | 2674 // - this (receiver) <-- LoadFromSuper will pop here and below. |
2677 // - home_object | 2675 // - home_object |
2678 // - key | 2676 // - key |
2679 // - language_mode | 2677 // - language_mode |
2680 __ CallRuntime(Runtime::kLoadFromSuper, 4); | 2678 __ CallRuntime(Runtime::kLoadFromSuper); |
2681 | 2679 |
2682 // Replace home_object with target function. | 2680 // Replace home_object with target function. |
2683 __ mov(Operand(esp, kPointerSize), eax); | 2681 __ mov(Operand(esp, kPointerSize), eax); |
2684 | 2682 |
2685 // Stack here: | 2683 // Stack here: |
2686 // - target function | 2684 // - target function |
2687 // - this (receiver) | 2685 // - this (receiver) |
2688 EmitCall(expr); | 2686 EmitCall(expr); |
2689 } | 2687 } |
2690 | 2688 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2728 __ push(Operand(esp, kPointerSize * 2)); | 2726 __ push(Operand(esp, kPointerSize * 2)); |
2729 VisitForStackValue(prop->key()); | 2727 VisitForStackValue(prop->key()); |
2730 __ push(Immediate(Smi::FromInt(language_mode()))); | 2728 __ push(Immediate(Smi::FromInt(language_mode()))); |
2731 // Stack here: | 2729 // Stack here: |
2732 // - home_object | 2730 // - home_object |
2733 // - this (receiver) | 2731 // - this (receiver) |
2734 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. | 2732 // - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
2735 // - home_object | 2733 // - home_object |
2736 // - key | 2734 // - key |
2737 // - language_mode | 2735 // - language_mode |
2738 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 4); | 2736 __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
2739 | 2737 |
2740 // Replace home_object with target function. | 2738 // Replace home_object with target function. |
2741 __ mov(Operand(esp, kPointerSize), eax); | 2739 __ mov(Operand(esp, kPointerSize), eax); |
2742 | 2740 |
2743 // Stack here: | 2741 // Stack here: |
2744 // - target function | 2742 // - target function |
2745 // - this (receiver) | 2743 // - this (receiver) |
2746 EmitCall(expr); | 2744 EmitCall(expr); |
2747 } | 2745 } |
2748 | 2746 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2784 // Push the enclosing function. | 2782 // Push the enclosing function. |
2785 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 2783 __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
2786 | 2784 |
2787 // Push the language mode. | 2785 // Push the language mode. |
2788 __ push(Immediate(Smi::FromInt(language_mode()))); | 2786 __ push(Immediate(Smi::FromInt(language_mode()))); |
2789 | 2787 |
2790 // Push the start position of the scope the calls resides in. | 2788 // Push the start position of the scope the calls resides in. |
2791 __ push(Immediate(Smi::FromInt(scope()->start_position()))); | 2789 __ push(Immediate(Smi::FromInt(scope()->start_position()))); |
2792 | 2790 |
2793 // Do the runtime call. | 2791 // Do the runtime call. |
2794 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2792 __ CallRuntime(Runtime::kResolvePossiblyDirectEval); |
2795 } | 2793 } |
2796 | 2794 |
2797 | 2795 |
2798 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. | 2796 // See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls. |
2799 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { | 2797 void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
2800 VariableProxy* callee = expr->expression()->AsVariableProxy(); | 2798 VariableProxy* callee = expr->expression()->AsVariableProxy(); |
2801 if (callee->var()->IsLookupSlot()) { | 2799 if (callee->var()->IsLookupSlot()) { |
2802 Label slow, done; | 2800 Label slow, done; |
2803 SetExpressionPosition(callee); | 2801 SetExpressionPosition(callee); |
2804 // Generate code for loading from variables potentially shadowed by | 2802 // Generate code for loading from variables potentially shadowed by |
2805 // eval-introduced variables. | 2803 // eval-introduced variables. |
2806 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); | 2804 EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done); |
2807 | 2805 |
2808 __ bind(&slow); | 2806 __ bind(&slow); |
2809 // Call the runtime to find the function to call (returned in eax) and | 2807 // Call the runtime to find the function to call (returned in eax) and |
2810 // the object holding it (returned in edx). | 2808 // the object holding it (returned in edx). |
2811 __ push(context_register()); | 2809 __ push(context_register()); |
2812 __ push(Immediate(callee->name())); | 2810 __ push(Immediate(callee->name())); |
2813 __ CallRuntime(Runtime::kLoadLookupSlot, 2); | 2811 __ CallRuntime(Runtime::kLoadLookupSlot); |
2814 __ push(eax); // Function. | 2812 __ push(eax); // Function. |
2815 __ push(edx); // Receiver. | 2813 __ push(edx); // Receiver. |
2816 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); | 2814 PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
2817 | 2815 |
2818 // If fast case code has been generated, emit code to push the function | 2816 // If fast case code has been generated, emit code to push the function |
2819 // and receiver and have the slow path jump around this code. | 2817 // and receiver and have the slow path jump around this code. |
2820 if (done.is_linked()) { | 2818 if (done.is_linked()) { |
2821 Label call; | 2819 Label call; |
2822 __ jmp(&call, Label::kNear); | 2820 __ jmp(&call, Label::kNear); |
2823 __ bind(&done); | 2821 __ bind(&done); |
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3446 ZoneList<Expression*>* args = expr->arguments(); | 3444 ZoneList<Expression*>* args = expr->arguments(); |
3447 DCHECK_EQ(1, args->length()); | 3445 DCHECK_EQ(1, args->length()); |
3448 | 3446 |
3449 // Load the argument into eax and convert it. | 3447 // Load the argument into eax and convert it. |
3450 VisitForAccumulatorValue(args->at(0)); | 3448 VisitForAccumulatorValue(args->at(0)); |
3451 | 3449 |
3452 // Convert the object to an integer. | 3450 // Convert the object to an integer. |
3453 Label done_convert; | 3451 Label done_convert; |
3454 __ JumpIfSmi(eax, &done_convert, Label::kNear); | 3452 __ JumpIfSmi(eax, &done_convert, Label::kNear); |
3455 __ Push(eax); | 3453 __ Push(eax); |
3456 __ CallRuntime(Runtime::kToInteger, 1); | 3454 __ CallRuntime(Runtime::kToInteger); |
3457 __ bind(&done_convert); | 3455 __ bind(&done_convert); |
3458 context()->Plug(eax); | 3456 context()->Plug(eax); |
3459 } | 3457 } |
3460 | 3458 |
3461 | 3459 |
3462 void FullCodeGenerator::EmitToName(CallRuntime* expr) { | 3460 void FullCodeGenerator::EmitToName(CallRuntime* expr) { |
3463 ZoneList<Expression*>* args = expr->arguments(); | 3461 ZoneList<Expression*>* args = expr->arguments(); |
3464 DCHECK_EQ(1, args->length()); | 3462 DCHECK_EQ(1, args->length()); |
3465 | 3463 |
3466 // Load the argument into eax and convert it. | 3464 // Load the argument into eax and convert it. |
3467 VisitForAccumulatorValue(args->at(0)); | 3465 VisitForAccumulatorValue(args->at(0)); |
3468 | 3466 |
3469 // Convert the object to a name. | 3467 // Convert the object to a name. |
3470 Label convert, done_convert; | 3468 Label convert, done_convert; |
3471 __ JumpIfSmi(eax, &convert, Label::kNear); | 3469 __ JumpIfSmi(eax, &convert, Label::kNear); |
3472 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); | 3470 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE); |
3473 __ CmpObjectType(eax, LAST_NAME_TYPE, ecx); | 3471 __ CmpObjectType(eax, LAST_NAME_TYPE, ecx); |
3474 __ j(below_equal, &done_convert, Label::kNear); | 3472 __ j(below_equal, &done_convert, Label::kNear); |
3475 __ bind(&convert); | 3473 __ bind(&convert); |
3476 __ Push(eax); | 3474 __ Push(eax); |
3477 __ CallRuntime(Runtime::kToName, 1); | 3475 __ CallRuntime(Runtime::kToName); |
3478 __ bind(&done_convert); | 3476 __ bind(&done_convert); |
3479 context()->Plug(eax); | 3477 context()->Plug(eax); |
3480 } | 3478 } |
3481 | 3479 |
3482 | 3480 |
3483 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { | 3481 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { |
3484 ZoneList<Expression*>* args = expr->arguments(); | 3482 ZoneList<Expression*>* args = expr->arguments(); |
3485 DCHECK(args->length() == 1); | 3483 DCHECK(args->length() == 1); |
3486 | 3484 |
3487 VisitForAccumulatorValue(args->at(0)); | 3485 VisitForAccumulatorValue(args->at(0)); |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3957 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 3955 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
3958 isolate()->factory()->empty_fixed_array()); | 3956 isolate()->factory()->empty_fixed_array()); |
3959 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 3957 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
3960 isolate()->factory()->empty_fixed_array()); | 3958 isolate()->factory()->empty_fixed_array()); |
3961 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); | 3959 __ pop(FieldOperand(eax, JSIteratorResult::kDoneOffset)); |
3962 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); | 3960 __ pop(FieldOperand(eax, JSIteratorResult::kValueOffset)); |
3963 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 3961 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
3964 __ jmp(&done, Label::kNear); | 3962 __ jmp(&done, Label::kNear); |
3965 | 3963 |
3966 __ bind(&runtime); | 3964 __ bind(&runtime); |
3967 __ CallRuntime(Runtime::kCreateIterResultObject, 2); | 3965 __ CallRuntime(Runtime::kCreateIterResultObject); |
3968 | 3966 |
3969 __ bind(&done); | 3967 __ bind(&done); |
3970 context()->Plug(eax); | 3968 context()->Plug(eax); |
3971 } | 3969 } |
3972 | 3970 |
3973 | 3971 |
3974 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { | 3972 void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
3975 // Push undefined as receiver. | 3973 // Push undefined as receiver. |
3976 __ push(Immediate(isolate()->factory()->undefined_value())); | 3974 __ push(Immediate(isolate()->factory()->undefined_value())); |
3977 | 3975 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4047 case Token::DELETE: { | 4045 case Token::DELETE: { |
4048 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4046 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4049 Property* property = expr->expression()->AsProperty(); | 4047 Property* property = expr->expression()->AsProperty(); |
4050 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4048 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4051 | 4049 |
4052 if (property != NULL) { | 4050 if (property != NULL) { |
4053 VisitForStackValue(property->obj()); | 4051 VisitForStackValue(property->obj()); |
4054 VisitForStackValue(property->key()); | 4052 VisitForStackValue(property->key()); |
4055 __ CallRuntime(is_strict(language_mode()) | 4053 __ CallRuntime(is_strict(language_mode()) |
4056 ? Runtime::kDeleteProperty_Strict | 4054 ? Runtime::kDeleteProperty_Strict |
4057 : Runtime::kDeleteProperty_Sloppy, | 4055 : Runtime::kDeleteProperty_Sloppy); |
4058 2); | |
4059 context()->Plug(eax); | 4056 context()->Plug(eax); |
4060 } else if (proxy != NULL) { | 4057 } else if (proxy != NULL) { |
4061 Variable* var = proxy->var(); | 4058 Variable* var = proxy->var(); |
4062 // Delete of an unqualified identifier is disallowed in strict mode but | 4059 // Delete of an unqualified identifier is disallowed in strict mode but |
4063 // "delete this" is allowed. | 4060 // "delete this" is allowed. |
4064 bool is_this = var->HasThisName(isolate()); | 4061 bool is_this = var->HasThisName(isolate()); |
4065 DCHECK(is_sloppy(language_mode()) || is_this); | 4062 DCHECK(is_sloppy(language_mode()) || is_this); |
4066 if (var->IsUnallocatedOrGlobalSlot()) { | 4063 if (var->IsUnallocatedOrGlobalSlot()) { |
4067 __ mov(eax, NativeContextOperand()); | 4064 __ mov(eax, NativeContextOperand()); |
4068 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); | 4065 __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); |
4069 __ push(Immediate(var->name())); | 4066 __ push(Immediate(var->name())); |
4070 __ CallRuntime(Runtime::kDeleteProperty_Sloppy, 2); | 4067 __ CallRuntime(Runtime::kDeleteProperty_Sloppy); |
4071 context()->Plug(eax); | 4068 context()->Plug(eax); |
4072 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4069 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4073 // Result of deleting non-global variables is false. 'this' is | 4070 // Result of deleting non-global variables is false. 'this' is |
4074 // not really a variable, though we implement it as one. The | 4071 // not really a variable, though we implement it as one. The |
4075 // subexpression does not have side effects. | 4072 // subexpression does not have side effects. |
4076 context()->Plug(is_this); | 4073 context()->Plug(is_this); |
4077 } else { | 4074 } else { |
4078 // Non-global variable. Call the runtime to try to delete from the | 4075 // Non-global variable. Call the runtime to try to delete from the |
4079 // context where the variable was introduced. | 4076 // context where the variable was introduced. |
4080 __ push(context_register()); | 4077 __ push(context_register()); |
4081 __ push(Immediate(var->name())); | 4078 __ push(Immediate(var->name())); |
4082 __ CallRuntime(Runtime::kDeleteLookupSlot, 2); | 4079 __ CallRuntime(Runtime::kDeleteLookupSlot); |
4083 context()->Plug(eax); | 4080 context()->Plug(eax); |
4084 } | 4081 } |
4085 } else { | 4082 } else { |
4086 // Result of deleting non-property, non-variable reference is true. | 4083 // Result of deleting non-property, non-variable reference is true. |
4087 // The subexpression may have side effects. | 4084 // The subexpression may have side effects. |
4088 VisitForEffect(expr->expression()); | 4085 VisitForEffect(expr->expression()); |
4089 context()->Plug(true); | 4086 context()->Plug(true); |
4090 } | 4087 } |
4091 break; | 4088 break; |
4092 } | 4089 } |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4509 Label* if_false = NULL; | 4506 Label* if_false = NULL; |
4510 Label* fall_through = NULL; | 4507 Label* fall_through = NULL; |
4511 context()->PrepareTest(&materialize_true, &materialize_false, | 4508 context()->PrepareTest(&materialize_true, &materialize_false, |
4512 &if_true, &if_false, &fall_through); | 4509 &if_true, &if_false, &fall_through); |
4513 | 4510 |
4514 Token::Value op = expr->op(); | 4511 Token::Value op = expr->op(); |
4515 VisitForStackValue(expr->left()); | 4512 VisitForStackValue(expr->left()); |
4516 switch (op) { | 4513 switch (op) { |
4517 case Token::IN: | 4514 case Token::IN: |
4518 VisitForStackValue(expr->right()); | 4515 VisitForStackValue(expr->right()); |
4519 __ CallRuntime(Runtime::kHasProperty, 2); | 4516 __ CallRuntime(Runtime::kHasProperty); |
4520 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); | 4517 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
4521 __ cmp(eax, isolate()->factory()->true_value()); | 4518 __ cmp(eax, isolate()->factory()->true_value()); |
4522 Split(equal, if_true, if_false, fall_through); | 4519 Split(equal, if_true, if_false, fall_through); |
4523 break; | 4520 break; |
4524 | 4521 |
4525 case Token::INSTANCEOF: { | 4522 case Token::INSTANCEOF: { |
4526 VisitForAccumulatorValue(expr->right()); | 4523 VisitForAccumulatorValue(expr->right()); |
4527 __ Pop(edx); | 4524 __ Pop(edx); |
4528 InstanceOfStub stub(isolate()); | 4525 InstanceOfStub stub(isolate()); |
4529 __ CallStub(&stub); | 4526 __ CallStub(&stub); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4782 Assembler::target_address_at(call_target_address, | 4779 Assembler::target_address_at(call_target_address, |
4783 unoptimized_code)); | 4780 unoptimized_code)); |
4784 return OSR_AFTER_STACK_CHECK; | 4781 return OSR_AFTER_STACK_CHECK; |
4785 } | 4782 } |
4786 | 4783 |
4787 | 4784 |
4788 } // namespace internal | 4785 } // namespace internal |
4789 } // namespace v8 | 4786 } // namespace v8 |
4790 | 4787 |
4791 #endif // V8_TARGET_ARCH_IA32 | 4788 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |