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

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

Powered by Google App Engine
This is Rietveld 408576698