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