Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: src/full-codegen/ia32/full-codegen-ia32.cc

Issue 1553703002: [runtime] TailCallRuntime and CallRuntime should use default argument counts (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@2015-12-29_TailCallRuntime_default_result_size_1_1550923002
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698